14a49301eSmrg/********************************************************** 24a49301eSmrg * Copyright 2008-2009 VMware, Inc. All rights reserved. 34a49301eSmrg * 44a49301eSmrg * Permission is hereby granted, free of charge, to any person 54a49301eSmrg * obtaining a copy of this software and associated documentation 64a49301eSmrg * files (the "Software"), to deal in the Software without 74a49301eSmrg * restriction, including without limitation the rights to use, copy, 84a49301eSmrg * modify, merge, publish, distribute, sublicense, and/or sell copies 94a49301eSmrg * of the Software, and to permit persons to whom the Software is 104a49301eSmrg * furnished to do so, subject to the following conditions: 114a49301eSmrg * 124a49301eSmrg * The above copyright notice and this permission notice shall be 134a49301eSmrg * included in all copies or substantial portions of the Software. 144a49301eSmrg * 154a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 164a49301eSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 174a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 184a49301eSmrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 194a49301eSmrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 204a49301eSmrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 214a49301eSmrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 224a49301eSmrg * SOFTWARE. 234a49301eSmrg * 244a49301eSmrg **********************************************************/ 254a49301eSmrg 264a49301eSmrg#include "pipe/p_compiler.h" 27cdc920a0Smrg#include "util/u_inlines.h" 284a49301eSmrg#include "pipe/p_defines.h" 2901e04c3fSmrg#include "util/u_helpers.h" 304a49301eSmrg#include "util/u_memory.h" 314a49301eSmrg#include "util/u_math.h" 324a49301eSmrg 334a49301eSmrg#include "svga_context.h" 344a49301eSmrg#include "svga_draw.h" 354a49301eSmrg#include "svga_draw_private.h" 364a49301eSmrg#include "svga_debug.h" 374a49301eSmrg#include "svga_screen.h" 3801e04c3fSmrg#include "svga_resource.h" 393464ebd5Sriastradh#include "svga_resource_buffer.h" 403464ebd5Sriastradh#include "svga_resource_texture.h" 4101e04c3fSmrg#include "svga_sampler_view.h" 4201e04c3fSmrg#include "svga_shader.h" 433464ebd5Sriastradh#include "svga_surface.h" 444a49301eSmrg#include "svga_winsys.h" 454a49301eSmrg#include "svga_cmd.h" 464a49301eSmrg 474a49301eSmrg 48af69d88dSmrgstruct svga_hwtnl * 49af69d88dSmrgsvga_hwtnl_create(struct svga_context *svga) 504a49301eSmrg{ 514a49301eSmrg struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl); 5201e04c3fSmrg if (!hwtnl) 534a49301eSmrg goto fail; 544a49301eSmrg 554a49301eSmrg hwtnl->svga = svga; 56af69d88dSmrg 57af69d88dSmrg hwtnl->cmd.swc = svga->swc; 584a49301eSmrg 594a49301eSmrg return hwtnl; 604a49301eSmrg 614a49301eSmrgfail: 624a49301eSmrg return NULL; 634a49301eSmrg} 644a49301eSmrg 65af69d88dSmrg 66af69d88dSmrgvoid 67af69d88dSmrgsvga_hwtnl_destroy(struct svga_hwtnl *hwtnl) 684a49301eSmrg{ 69af69d88dSmrg unsigned i, j; 704a49301eSmrg 714a49301eSmrg for (i = 0; i < PIPE_PRIM_MAX; i++) { 724a49301eSmrg for (j = 0; j < IDX_CACHE_MAX; j++) { 73af69d88dSmrg pipe_resource_reference(&hwtnl->index_cache[i][j].buffer, NULL); 744a49301eSmrg } 754a49301eSmrg } 764a49301eSmrg 7701e04c3fSmrg for (i = 0; i < hwtnl->cmd.vbuf_count; i++) 7801e04c3fSmrg pipe_vertex_buffer_unreference(&hwtnl->cmd.vbufs[i]); 794a49301eSmrg 804a49301eSmrg for (i = 0; i < hwtnl->cmd.prim_count; i++) 813464ebd5Sriastradh pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL); 824a49301eSmrg 834a49301eSmrg FREE(hwtnl); 844a49301eSmrg} 854a49301eSmrg 864a49301eSmrg 87af69d88dSmrgvoid 88af69d88dSmrgsvga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl, 89af69d88dSmrg boolean flatshade, boolean flatshade_first) 904a49301eSmrg{ 9101e04c3fSmrg struct svga_screen *svgascreen = svga_screen(hwtnl->svga->pipe.screen); 9201e04c3fSmrg 9301e04c3fSmrg /* User-specified PV */ 944a49301eSmrg hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST; 9501e04c3fSmrg 9601e04c3fSmrg /* Device supported PV */ 9701e04c3fSmrg if (svgascreen->haveProvokingVertex) { 9801e04c3fSmrg /* use the mode specified by the user */ 9901e04c3fSmrg hwtnl->hw_pv = hwtnl->api_pv; 10001e04c3fSmrg } 10101e04c3fSmrg else { 10201e04c3fSmrg /* the device only support first provoking vertex */ 10301e04c3fSmrg hwtnl->hw_pv = PV_FIRST; 10401e04c3fSmrg } 105af69d88dSmrg} 106af69d88dSmrg 1074a49301eSmrg 108af69d88dSmrgvoid 10901e04c3fSmrgsvga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode) 1104a49301eSmrg{ 1114a49301eSmrg hwtnl->api_fillmode = mode; 112af69d88dSmrg} 113af69d88dSmrg 1144a49301eSmrg 115af69d88dSmrgvoid 11601e04c3fSmrgsvga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl, 11701e04c3fSmrg unsigned count, 11801e04c3fSmrg const SVGA3dVertexDecl * decls, 11901e04c3fSmrg const unsigned *buffer_indexes, 12001e04c3fSmrg SVGA3dElementLayoutId layout_id) 1214a49301eSmrg{ 1224a49301eSmrg assert(hwtnl->cmd.prim_count == 0); 1234a49301eSmrg hwtnl->cmd.vdecl_count = count; 12401e04c3fSmrg hwtnl->cmd.vdecl_layout_id = layout_id; 12501e04c3fSmrg memcpy(hwtnl->cmd.vdecl, decls, count * sizeof(*decls)); 12601e04c3fSmrg memcpy(hwtnl->cmd.vdecl_buffer_index, buffer_indexes, 12701e04c3fSmrg count * sizeof(unsigned)); 1284a49301eSmrg} 1294a49301eSmrg 1304a49301eSmrg 13101e04c3fSmrg/** 13201e04c3fSmrg * Specify vertex buffers for hardware drawing. 13301e04c3fSmrg */ 134af69d88dSmrgvoid 13501e04c3fSmrgsvga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl, 13601e04c3fSmrg unsigned count, struct pipe_vertex_buffer *buffers) 1374a49301eSmrg{ 13801e04c3fSmrg struct pipe_vertex_buffer *dst = hwtnl->cmd.vbufs; 13901e04c3fSmrg const struct pipe_vertex_buffer *src = buffers; 14001e04c3fSmrg unsigned i; 1414a49301eSmrg 14201e04c3fSmrg for (i = 0; i < count; i++) { 14301e04c3fSmrg pipe_vertex_buffer_reference(&dst[i], &src[i]); 14401e04c3fSmrg } 1454a49301eSmrg 14601e04c3fSmrg /* release old buffer references */ 14701e04c3fSmrg for ( ; i < hwtnl->cmd.vbuf_count; i++) { 14801e04c3fSmrg pipe_vertex_buffer_unreference(&dst[i]); 14901e04c3fSmrg /* don't bother zeroing stride/offset fields */ 15001e04c3fSmrg } 1514a49301eSmrg 15201e04c3fSmrg hwtnl->cmd.vbuf_count = count; 1534a49301eSmrg} 1544a49301eSmrg 1554a49301eSmrg 156af69d88dSmrg/** 157af69d88dSmrg * Determine whether the specified buffer is referred in the primitive queue, 158af69d88dSmrg * for which no commands have been written yet. 159af69d88dSmrg */ 160af69d88dSmrgboolean 161af69d88dSmrgsvga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl, 162af69d88dSmrg struct pipe_resource *buffer) 163af69d88dSmrg{ 164af69d88dSmrg unsigned i; 165af69d88dSmrg 166af69d88dSmrg if (svga_buffer_is_user_buffer(buffer)) { 167af69d88dSmrg return FALSE; 168af69d88dSmrg } 169af69d88dSmrg 170af69d88dSmrg if (!hwtnl->cmd.prim_count) { 171af69d88dSmrg return FALSE; 172af69d88dSmrg } 173af69d88dSmrg 17401e04c3fSmrg for (i = 0; i < hwtnl->cmd.vbuf_count; ++i) { 17501e04c3fSmrg if (hwtnl->cmd.vbufs[i].buffer.resource == buffer) { 176af69d88dSmrg return TRUE; 177af69d88dSmrg } 178af69d88dSmrg } 179af69d88dSmrg 180af69d88dSmrg for (i = 0; i < hwtnl->cmd.prim_count; ++i) { 181af69d88dSmrg if (hwtnl->cmd.prim_ib[i] == buffer) { 182af69d88dSmrg return TRUE; 183af69d88dSmrg } 184af69d88dSmrg } 185af69d88dSmrg 186af69d88dSmrg return FALSE; 187af69d88dSmrg} 188af69d88dSmrg 1894a49301eSmrg 19001e04c3fSmrgstatic enum pipe_error 19101e04c3fSmrgdraw_vgpu9(struct svga_hwtnl *hwtnl) 1924a49301eSmrg{ 1934a49301eSmrg struct svga_winsys_context *swc = hwtnl->cmd.swc; 1944a49301eSmrg struct svga_context *svga = hwtnl->svga; 1954a49301eSmrg enum pipe_error ret; 19601e04c3fSmrg struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX]; 19701e04c3fSmrg struct svga_winsys_surface *ib_handle[QSZ]; 19801e04c3fSmrg struct svga_winsys_surface *handle; 19901e04c3fSmrg SVGA3dVertexDecl *vdecl; 20001e04c3fSmrg SVGA3dPrimitiveRange *prim; 20101e04c3fSmrg unsigned i; 2024a49301eSmrg 20301e04c3fSmrg /* Re-validate those sampler views with backing copy 20401e04c3fSmrg * of texture whose original copy has been updated. 20501e04c3fSmrg * This is done here at draw time because the texture binding might not 20601e04c3fSmrg * have modified, hence validation is not triggered at state update time, 20701e04c3fSmrg * and yet the texture might have been updated in another context, so 20801e04c3fSmrg * we need to re-validate the sampler view in order to update the backing 20901e04c3fSmrg * copy of the updated texture. 21001e04c3fSmrg */ 21101e04c3fSmrg if (svga->state.hw_draw.num_backed_views) { 21201e04c3fSmrg for (i = 0; i < svga->state.hw_draw.num_views; i++) { 21301e04c3fSmrg struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; 21401e04c3fSmrg struct svga_texture *tex = svga_texture(view->texture); 21501e04c3fSmrg struct svga_sampler_view *sv = view->v; 21601e04c3fSmrg if (sv && tex && sv->handle != tex->handle && sv->age < tex->age) 21701e04c3fSmrg svga_validate_sampler_view(svga, view->v); 21801e04c3fSmrg } 21901e04c3fSmrg } 22001e04c3fSmrg 22101e04c3fSmrg for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 22201e04c3fSmrg unsigned j = hwtnl->cmd.vdecl_buffer_index[i]; 22301e04c3fSmrg handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer.resource, 22401e04c3fSmrg PIPE_BIND_VERTEX_BUFFER); 22501e04c3fSmrg if (!handle) 22601e04c3fSmrg return PIPE_ERROR_OUT_OF_MEMORY; 2274a49301eSmrg 22801e04c3fSmrg vb_handle[i] = handle; 22901e04c3fSmrg } 23001e04c3fSmrg 23101e04c3fSmrg for (i = 0; i < hwtnl->cmd.prim_count; i++) { 23201e04c3fSmrg if (hwtnl->cmd.prim_ib[i]) { 23301e04c3fSmrg handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i], 23401e04c3fSmrg PIPE_BIND_INDEX_BUFFER); 23501e04c3fSmrg if (!handle) 2364a49301eSmrg return PIPE_ERROR_OUT_OF_MEMORY; 23701e04c3fSmrg } 23801e04c3fSmrg else 23901e04c3fSmrg handle = NULL; 2404a49301eSmrg 24101e04c3fSmrg ib_handle[i] = handle; 24201e04c3fSmrg } 24301e04c3fSmrg 24401e04c3fSmrg if (svga->rebind.flags.rendertargets) { 24501e04c3fSmrg ret = svga_reemit_framebuffer_bindings(svga); 24601e04c3fSmrg if (ret != PIPE_OK) { 24701e04c3fSmrg return ret; 24801e04c3fSmrg } 24901e04c3fSmrg } 25001e04c3fSmrg 25101e04c3fSmrg if (svga->rebind.flags.texture_samplers) { 25201e04c3fSmrg ret = svga_reemit_tss_bindings(svga); 25301e04c3fSmrg if (ret != PIPE_OK) { 25401e04c3fSmrg return ret; 25501e04c3fSmrg } 25601e04c3fSmrg } 25701e04c3fSmrg 25801e04c3fSmrg if (svga->rebind.flags.vs) { 25901e04c3fSmrg ret = svga_reemit_vs_bindings(svga); 26001e04c3fSmrg if (ret != PIPE_OK) { 26101e04c3fSmrg return ret; 26201e04c3fSmrg } 26301e04c3fSmrg } 26401e04c3fSmrg 26501e04c3fSmrg if (svga->rebind.flags.fs) { 26601e04c3fSmrg ret = svga_reemit_fs_bindings(svga); 26701e04c3fSmrg if (ret != PIPE_OK) { 26801e04c3fSmrg return ret; 2694a49301eSmrg } 27001e04c3fSmrg } 27101e04c3fSmrg 27201e04c3fSmrg SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n", 27301e04c3fSmrg svga->curr.framebuffer.cbufs[0] ? 27401e04c3fSmrg svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL, 27501e04c3fSmrg hwtnl->cmd.prim_count); 27601e04c3fSmrg 27701e04c3fSmrg ret = SVGA3D_BeginDrawPrimitives(swc, 27801e04c3fSmrg &vdecl, 27901e04c3fSmrg hwtnl->cmd.vdecl_count, 28001e04c3fSmrg &prim, hwtnl->cmd.prim_count); 28101e04c3fSmrg if (ret != PIPE_OK) 28201e04c3fSmrg return ret; 28301e04c3fSmrg 28401e04c3fSmrg memcpy(vdecl, 28501e04c3fSmrg hwtnl->cmd.vdecl, 28601e04c3fSmrg hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]); 28701e04c3fSmrg 28801e04c3fSmrg for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 28901e04c3fSmrg /* check for 4-byte alignment */ 29001e04c3fSmrg assert(vdecl[i].array.offset % 4 == 0); 29101e04c3fSmrg assert(vdecl[i].array.stride % 4 == 0); 29201e04c3fSmrg 29301e04c3fSmrg /* Given rangeHint is considered to be relative to indexBias, and 29401e04c3fSmrg * indexBias varies per primitive, we cannot accurately supply an 29501e04c3fSmrg * rangeHint when emitting more than one primitive per draw command. 29601e04c3fSmrg */ 29701e04c3fSmrg if (hwtnl->cmd.prim_count == 1) { 29801e04c3fSmrg vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0]; 29901e04c3fSmrg vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1; 30001e04c3fSmrg } 30101e04c3fSmrg else { 30201e04c3fSmrg vdecl[i].rangeHint.first = 0; 30301e04c3fSmrg vdecl[i].rangeHint.last = 0; 30401e04c3fSmrg } 30501e04c3fSmrg 30601e04c3fSmrg swc->surface_relocation(swc, 30701e04c3fSmrg &vdecl[i].array.surfaceId, 30801e04c3fSmrg NULL, vb_handle[i], SVGA_RELOC_READ); 30901e04c3fSmrg } 31001e04c3fSmrg 31101e04c3fSmrg memcpy(prim, 31201e04c3fSmrg hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]); 31301e04c3fSmrg 31401e04c3fSmrg for (i = 0; i < hwtnl->cmd.prim_count; i++) { 31501e04c3fSmrg swc->surface_relocation(swc, 31601e04c3fSmrg &prim[i].indexArray.surfaceId, 31701e04c3fSmrg NULL, ib_handle[i], SVGA_RELOC_READ); 31801e04c3fSmrg pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL); 31901e04c3fSmrg } 32001e04c3fSmrg 32101e04c3fSmrg SVGA_FIFOCommitAll(swc); 32201e04c3fSmrg 32301e04c3fSmrg hwtnl->cmd.prim_count = 0; 3244a49301eSmrg 32501e04c3fSmrg return PIPE_OK; 32601e04c3fSmrg} 32701e04c3fSmrg 32801e04c3fSmrg 32901e04c3fSmrgstatic SVGA3dSurfaceFormat 33001e04c3fSmrgxlate_index_format(unsigned indexWidth) 33101e04c3fSmrg{ 33201e04c3fSmrg if (indexWidth == 2) { 33301e04c3fSmrg return SVGA3D_R16_UINT; 33401e04c3fSmrg } 33501e04c3fSmrg else if (indexWidth == 4) { 33601e04c3fSmrg return SVGA3D_R32_UINT; 33701e04c3fSmrg } 33801e04c3fSmrg else { 33901e04c3fSmrg assert(!"Bad indexWidth"); 34001e04c3fSmrg return SVGA3D_R32_UINT; 34101e04c3fSmrg } 34201e04c3fSmrg} 34301e04c3fSmrg 34401e04c3fSmrg 34501e04c3fSmrgstatic enum pipe_error 34601e04c3fSmrgvalidate_sampler_resources(struct svga_context *svga) 34701e04c3fSmrg{ 34801e04c3fSmrg enum pipe_shader_type shader; 34901e04c3fSmrg 35001e04c3fSmrg assert(svga_have_vgpu10(svga)); 35101e04c3fSmrg 3527ec681f3Smrg for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_COMPUTE; shader++) { 35301e04c3fSmrg unsigned count = svga->curr.num_sampler_views[shader]; 35401e04c3fSmrg unsigned i; 35501e04c3fSmrg struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS]; 35601e04c3fSmrg enum pipe_error ret; 35701e04c3fSmrg 35801e04c3fSmrg /* 35901e04c3fSmrg * Reference bound sampler resources to ensure pending updates are 36001e04c3fSmrg * noticed by the device. 36101e04c3fSmrg */ 36201e04c3fSmrg for (i = 0; i < count; i++) { 36301e04c3fSmrg struct svga_pipe_sampler_view *sv = 36401e04c3fSmrg svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]); 36501e04c3fSmrg 36601e04c3fSmrg if (sv) { 36701e04c3fSmrg if (sv->base.texture->target == PIPE_BUFFER) { 36801e04c3fSmrg surfaces[i] = svga_buffer_handle(svga, sv->base.texture, 36901e04c3fSmrg PIPE_BIND_SAMPLER_VIEW); 37001e04c3fSmrg } 37101e04c3fSmrg else { 37201e04c3fSmrg surfaces[i] = svga_texture(sv->base.texture)->handle; 37301e04c3fSmrg } 3744a49301eSmrg } 375af69d88dSmrg else { 37601e04c3fSmrg surfaces[i] = NULL; 377af69d88dSmrg } 37801e04c3fSmrg } 37901e04c3fSmrg 38001e04c3fSmrg if (shader == PIPE_SHADER_FRAGMENT && 38101e04c3fSmrg svga->curr.rast->templ.poly_stipple_enable) { 3827ec681f3Smrg const unsigned unit = 3837ec681f3Smrg svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit; 38401e04c3fSmrg struct svga_pipe_sampler_view *sv = 38501e04c3fSmrg svga->polygon_stipple.sampler_view; 3864a49301eSmrg 38701e04c3fSmrg assert(sv); 38801e04c3fSmrg surfaces[unit] = svga_texture(sv->base.texture)->handle; 38901e04c3fSmrg count = MAX2(count, unit+1); 3904a49301eSmrg } 3914a49301eSmrg 39201e04c3fSmrg /* rebind the shader resources if needed */ 39301e04c3fSmrg if (svga->rebind.flags.texture_samplers) { 39401e04c3fSmrg for (i = 0; i < count; i++) { 39501e04c3fSmrg if (surfaces[i]) { 39601e04c3fSmrg ret = svga->swc->resource_rebind(svga->swc, 39701e04c3fSmrg surfaces[i], 39801e04c3fSmrg NULL, 39901e04c3fSmrg SVGA_RELOC_READ); 40001e04c3fSmrg if (ret != PIPE_OK) 40101e04c3fSmrg return ret; 40201e04c3fSmrg } 4033464ebd5Sriastradh } 4043464ebd5Sriastradh } 40501e04c3fSmrg } 40601e04c3fSmrg svga->rebind.flags.texture_samplers = FALSE; 4073464ebd5Sriastradh 40801e04c3fSmrg return PIPE_OK; 40901e04c3fSmrg} 41001e04c3fSmrg 41101e04c3fSmrg 41201e04c3fSmrgstatic enum pipe_error 41301e04c3fSmrgvalidate_constant_buffers(struct svga_context *svga) 41401e04c3fSmrg{ 41501e04c3fSmrg enum pipe_shader_type shader; 41601e04c3fSmrg 41701e04c3fSmrg assert(svga_have_vgpu10(svga)); 41801e04c3fSmrg 4197ec681f3Smrg for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_COMPUTE; shader++) { 42001e04c3fSmrg enum pipe_error ret; 42101e04c3fSmrg struct svga_buffer *buffer; 42201e04c3fSmrg 42301e04c3fSmrg /* Rebind the default constant buffer if needed */ 42401e04c3fSmrg if (svga->rebind.flags.constbufs) { 4257ec681f3Smrg buffer = svga_buffer(svga->state.hw_draw.constbuf[shader][0]); 42601e04c3fSmrg if (buffer) { 42701e04c3fSmrg ret = svga->swc->resource_rebind(svga->swc, 42801e04c3fSmrg buffer->handle, 42901e04c3fSmrg NULL, 43001e04c3fSmrg SVGA_RELOC_READ); 43101e04c3fSmrg if (ret != PIPE_OK) 43201e04c3fSmrg return ret; 4333464ebd5Sriastradh } 4343464ebd5Sriastradh } 4353464ebd5Sriastradh 4367ec681f3Smrg struct svga_winsys_surface *handle; 4377ec681f3Smrg unsigned enabled_constbufs; 4387ec681f3Smrg 43901e04c3fSmrg /* 44001e04c3fSmrg * Reference other bound constant buffers to ensure pending updates are 44101e04c3fSmrg * noticed by the device. 44201e04c3fSmrg */ 44301e04c3fSmrg enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] & ~1u; 44401e04c3fSmrg while (enabled_constbufs) { 44501e04c3fSmrg unsigned i = u_bit_scan(&enabled_constbufs); 44601e04c3fSmrg buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer); 4477ec681f3Smrg 4487ec681f3Smrg /* If the constant buffer has hw storage, get the buffer winsys handle. 4497ec681f3Smrg * Rebind the resource if needed. 4507ec681f3Smrg */ 4517ec681f3Smrg if (buffer && !buffer->use_swbuf) 4527ec681f3Smrg handle = svga_buffer_handle(svga, &buffer->b, 45301e04c3fSmrg PIPE_BIND_CONSTANT_BUFFER); 4547ec681f3Smrg else 4557ec681f3Smrg handle = svga->state.hw_draw.constbufoffsets[shader][i].handle; 45601e04c3fSmrg 4577ec681f3Smrg if (svga->rebind.flags.constbufs && handle) { 4587ec681f3Smrg ret = svga->swc->resource_rebind(svga->swc, 4597ec681f3Smrg handle, 4607ec681f3Smrg NULL, 4617ec681f3Smrg SVGA_RELOC_READ); 4627ec681f3Smrg if (ret != PIPE_OK) 4637ec681f3Smrg return ret; 464af69d88dSmrg } 465af69d88dSmrg } 46601e04c3fSmrg } 46701e04c3fSmrg svga->rebind.flags.constbufs = FALSE; 468af69d88dSmrg 46901e04c3fSmrg return PIPE_OK; 47001e04c3fSmrg} 47101e04c3fSmrg 47201e04c3fSmrg 47301e04c3fSmrg/** 47401e04c3fSmrg * Was the last command put into the command buffer a drawing command? 47501e04c3fSmrg * We use this to determine if we can skip emitting buffer re-bind 47601e04c3fSmrg * commands when we have a sequence of drawing commands that use the 47701e04c3fSmrg * same vertex/index buffers with no intervening commands. 47801e04c3fSmrg * 47901e04c3fSmrg * The first drawing command will bind the vertex/index buffers. If 48001e04c3fSmrg * the immediately following command is also a drawing command using the 48101e04c3fSmrg * same buffers, we shouldn't have to rebind them. 48201e04c3fSmrg */ 48301e04c3fSmrgstatic bool 48401e04c3fSmrglast_command_was_draw(const struct svga_context *svga) 48501e04c3fSmrg{ 48601e04c3fSmrg switch (SVGA3D_GetLastCommand(svga->swc)) { 48701e04c3fSmrg case SVGA_3D_CMD_DX_DRAW: 48801e04c3fSmrg case SVGA_3D_CMD_DX_DRAW_INDEXED: 48901e04c3fSmrg case SVGA_3D_CMD_DX_DRAW_INSTANCED: 49001e04c3fSmrg case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED: 49101e04c3fSmrg case SVGA_3D_CMD_DX_DRAW_AUTO: 4927ec681f3Smrg case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT: 4937ec681f3Smrg case SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT: 49401e04c3fSmrg return true; 49501e04c3fSmrg default: 49601e04c3fSmrg return false; 49701e04c3fSmrg } 49801e04c3fSmrg} 49901e04c3fSmrg 50001e04c3fSmrg 50101e04c3fSmrg/** 50201e04c3fSmrg * A helper function to compare vertex buffers. 50301e04c3fSmrg * They are equal if the vertex buffer attributes and the vertex buffer 50401e04c3fSmrg * resources are identical. 50501e04c3fSmrg */ 50601e04c3fSmrgstatic boolean 50701e04c3fSmrgvertex_buffers_equal(unsigned count, 50801e04c3fSmrg SVGA3dVertexBuffer *pVBufAttr1, 50901e04c3fSmrg struct pipe_resource **pVBuf1, 51001e04c3fSmrg SVGA3dVertexBuffer *pVBufAttr2, 51101e04c3fSmrg struct pipe_resource **pVBuf2) 51201e04c3fSmrg{ 51301e04c3fSmrg return (memcmp(pVBufAttr1, pVBufAttr2, 51401e04c3fSmrg count * sizeof(*pVBufAttr1)) == 0) && 51501e04c3fSmrg (memcmp(pVBuf1, pVBuf2, count * sizeof(*pVBuf1)) == 0); 51601e04c3fSmrg} 51701e04c3fSmrg 51801e04c3fSmrg 5199f464c52Smaya/* 5209f464c52Smaya * Prepare the vertex buffers for a drawing command. 5219f464c52Smaya */ 52201e04c3fSmrgstatic enum pipe_error 5237ec681f3Smrgvalidate_vertex_buffers(struct svga_hwtnl *hwtnl, 5247ec681f3Smrg const struct pipe_stream_output_target *so_vertex_count) 52501e04c3fSmrg{ 52601e04c3fSmrg struct svga_context *svga = hwtnl->svga; 52701e04c3fSmrg struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX]; 52801e04c3fSmrg struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX]; 5297ec681f3Smrg struct svga_winsys_surface *so_vertex_count_handle; 5307ec681f3Smrg const unsigned vbuf_count = so_vertex_count ? 1 : hwtnl->cmd.vbuf_count; 53101e04c3fSmrg int last_vbuf = -1; 53201e04c3fSmrg unsigned i; 53301e04c3fSmrg 53401e04c3fSmrg assert(svga_have_vgpu10(svga)); 53501e04c3fSmrg 5367ec681f3Smrg /* Get handle for each referenced vertex buffer, unless we're using a 5377ec681f3Smrg * stream-out buffer to specify the drawing information (DrawAuto). 5387ec681f3Smrg */ 5397ec681f3Smrg if (so_vertex_count) { 5407ec681f3Smrg i = 0; 5417ec681f3Smrg } 5427ec681f3Smrg else { 5437ec681f3Smrg for (i = 0; i < vbuf_count; i++) { 5447ec681f3Smrg struct svga_buffer *sbuf = 5457ec681f3Smrg svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource); 5467ec681f3Smrg 5477ec681f3Smrg if (sbuf) { 5487ec681f3Smrg vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b, 5497ec681f3Smrg PIPE_BIND_VERTEX_BUFFER); 5507ec681f3Smrg assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER); 5517ec681f3Smrg if (vbuffer_handles[i] == NULL) 5527ec681f3Smrg return PIPE_ERROR_OUT_OF_MEMORY; 5537ec681f3Smrg vbuffers[i] = &sbuf->b; 5547ec681f3Smrg last_vbuf = i; 5557ec681f3Smrg } 5567ec681f3Smrg else { 5577ec681f3Smrg vbuffers[i] = NULL; 5587ec681f3Smrg vbuffer_handles[i] = NULL; 5597ec681f3Smrg } 5607ec681f3Smrg } 5617ec681f3Smrg } 5627ec681f3Smrg 5637ec681f3Smrg for (; i < svga->state.hw_draw.num_vbuffers; i++) { 5647ec681f3Smrg vbuffers[i] = NULL; 5657ec681f3Smrg vbuffer_handles[i] = NULL; 5667ec681f3Smrg } 5677ec681f3Smrg 56801e04c3fSmrg /* Get handle for each referenced vertex buffer */ 56901e04c3fSmrg for (i = 0; i < vbuf_count; i++) { 5709f464c52Smaya struct svga_buffer *sbuf = 5719f464c52Smaya svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource); 57201e04c3fSmrg 57301e04c3fSmrg if (sbuf) { 5747ec681f3Smrg vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b, 57501e04c3fSmrg PIPE_BIND_VERTEX_BUFFER); 57601e04c3fSmrg assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER); 57701e04c3fSmrg if (vbuffer_handles[i] == NULL) 57801e04c3fSmrg return PIPE_ERROR_OUT_OF_MEMORY; 5797ec681f3Smrg vbuffers[i] = &sbuf->b; 58001e04c3fSmrg last_vbuf = i; 58101e04c3fSmrg } 58201e04c3fSmrg else { 58301e04c3fSmrg vbuffers[i] = NULL; 58401e04c3fSmrg vbuffer_handles[i] = NULL; 585af69d88dSmrg } 58601e04c3fSmrg } 587af69d88dSmrg 58801e04c3fSmrg for (; i < svga->state.hw_draw.num_vbuffers; i++) { 58901e04c3fSmrg vbuffers[i] = NULL; 59001e04c3fSmrg vbuffer_handles[i] = NULL; 59101e04c3fSmrg } 59201e04c3fSmrg 59301e04c3fSmrg /* setup vertex attribute input layout */ 59401e04c3fSmrg if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) { 5959f464c52Smaya enum pipe_error ret = 5969f464c52Smaya SVGA3D_vgpu10_SetInputLayout(svga->swc, 5979f464c52Smaya hwtnl->cmd.vdecl_layout_id); 598af69d88dSmrg if (ret != PIPE_OK) 5994a49301eSmrg return ret; 6004a49301eSmrg 60101e04c3fSmrg svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id; 60201e04c3fSmrg } 60301e04c3fSmrg 6047ec681f3Smrg /* Get handle for the stream out buffer */ 6057ec681f3Smrg if (so_vertex_count) { 6067ec681f3Smrg so_vertex_count_handle = svga_buffer_handle(svga, 6077ec681f3Smrg so_vertex_count->buffer, 6087ec681f3Smrg (PIPE_BIND_VERTEX_BUFFER | 6097ec681f3Smrg PIPE_BIND_STREAM_OUTPUT)); 6107ec681f3Smrg if (!so_vertex_count_handle) 6117ec681f3Smrg return PIPE_ERROR_OUT_OF_MEMORY; 6127ec681f3Smrg } 6137ec681f3Smrg else { 6147ec681f3Smrg so_vertex_count_handle = NULL; 6157ec681f3Smrg } 6167ec681f3Smrg 61701e04c3fSmrg /* setup vertex buffers */ 61801e04c3fSmrg { 61901e04c3fSmrg SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS]; 6204a49301eSmrg 6217ec681f3Smrg if (so_vertex_count) { 6227ec681f3Smrg /* Set IA slot0 input buffer to the SO buffer */ 6237ec681f3Smrg assert(vbuf_count == 1); 6247ec681f3Smrg vbuffer_attrs[0].stride = hwtnl->cmd.vbufs[0].stride; 6257ec681f3Smrg vbuffer_attrs[0].offset = hwtnl->cmd.vbufs[0].buffer_offset; 6267ec681f3Smrg vbuffer_attrs[0].sid = 0; 6277ec681f3Smrg vbuffers[0] = so_vertex_count->buffer; 6287ec681f3Smrg vbuffer_handles[0] = so_vertex_count_handle; 6297ec681f3Smrg } 6307ec681f3Smrg else { 6317ec681f3Smrg for (i = 0; i < vbuf_count; i++) { 6327ec681f3Smrg vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride; 6337ec681f3Smrg vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset; 6347ec681f3Smrg vbuffer_attrs[i].sid = 0; 6357ec681f3Smrg } 63601e04c3fSmrg } 63701e04c3fSmrg 6389f464c52Smaya /* If any of the vertex buffer state has changed, issue 6399f464c52Smaya * the SetVertexBuffers command. Otherwise, we will just 6409f464c52Smaya * need to rebind the resources. 64101e04c3fSmrg */ 6429f464c52Smaya if (vbuf_count != svga->state.hw_draw.num_vbuffers || 64301e04c3fSmrg !vertex_buffers_equal(vbuf_count, 64401e04c3fSmrg vbuffer_attrs, 64501e04c3fSmrg vbuffers, 64601e04c3fSmrg svga->state.hw_draw.vbuffer_attrs, 64701e04c3fSmrg svga->state.hw_draw.vbuffers)) { 64801e04c3fSmrg 64901e04c3fSmrg unsigned num_vbuffers; 65001e04c3fSmrg 65101e04c3fSmrg /* get the max of the current bound vertex buffers count and 65201e04c3fSmrg * the to-be-bound vertex buffers count, so as to unbind 65301e04c3fSmrg * the unused vertex buffers. 6544a49301eSmrg */ 65501e04c3fSmrg num_vbuffers = MAX2(vbuf_count, svga->state.hw_draw.num_vbuffers); 65601e04c3fSmrg 65701e04c3fSmrg /* Zero-out the old buffers we want to unbind (the number of loop 65801e04c3fSmrg * iterations here is typically very small, and often zero.) 65901e04c3fSmrg */ 66001e04c3fSmrg for (i = vbuf_count; i < num_vbuffers; i++) { 66101e04c3fSmrg vbuffer_attrs[i].sid = 0; 66201e04c3fSmrg vbuffer_attrs[i].stride = 0; 66301e04c3fSmrg vbuffer_attrs[i].offset = 0; 66401e04c3fSmrg vbuffer_handles[i] = NULL; 6654a49301eSmrg } 6664a49301eSmrg 66701e04c3fSmrg if (num_vbuffers > 0) { 66801e04c3fSmrg SVGA3dVertexBuffer *pbufAttrs = vbuffer_attrs; 66901e04c3fSmrg struct svga_winsys_surface **pbufHandles = vbuffer_handles; 67001e04c3fSmrg unsigned numVBuf = 0; 67101e04c3fSmrg 67201e04c3fSmrg /* Loop through the vertex buffer lists to only emit 67301e04c3fSmrg * those vertex buffers that are not already in the 67401e04c3fSmrg * corresponding entries in the device's vertex buffer list. 67501e04c3fSmrg */ 67601e04c3fSmrg for (i = 0; i < num_vbuffers; i++) { 6779f464c52Smaya boolean emit = 6789f464c52Smaya vertex_buffers_equal(1, 6799f464c52Smaya &vbuffer_attrs[i], 6809f464c52Smaya &vbuffers[i], 6819f464c52Smaya &svga->state.hw_draw.vbuffer_attrs[i], 6829f464c52Smaya &svga->state.hw_draw.vbuffers[i]); 6839f464c52Smaya 68401e04c3fSmrg if (!emit && i == num_vbuffers-1) { 68501e04c3fSmrg /* Include the last vertex buffer in the next emit 68601e04c3fSmrg * if it is different. 68701e04c3fSmrg */ 68801e04c3fSmrg emit = TRUE; 68901e04c3fSmrg numVBuf++; 69001e04c3fSmrg i++; 69101e04c3fSmrg } 69201e04c3fSmrg 69301e04c3fSmrg if (emit) { 69401e04c3fSmrg /* numVBuf can only be 0 if the first vertex buffer 69501e04c3fSmrg * is the same as the one in the device's list. 69601e04c3fSmrg * In this case, there is nothing to send yet. 69701e04c3fSmrg */ 69801e04c3fSmrg if (numVBuf) { 6999f464c52Smaya enum pipe_error ret = 7009f464c52Smaya SVGA3D_vgpu10_SetVertexBuffers(svga->swc, 7019f464c52Smaya numVBuf, 7029f464c52Smaya i - numVBuf, 7039f464c52Smaya pbufAttrs, pbufHandles); 70401e04c3fSmrg if (ret != PIPE_OK) 70501e04c3fSmrg return ret; 70601e04c3fSmrg } 70701e04c3fSmrg pbufAttrs += (numVBuf + 1); 70801e04c3fSmrg pbufHandles += (numVBuf + 1); 70901e04c3fSmrg numVBuf = 0; 71001e04c3fSmrg } 71101e04c3fSmrg else 71201e04c3fSmrg numVBuf++; 71301e04c3fSmrg } 71401e04c3fSmrg 71501e04c3fSmrg /* save the number of vertex buffers sent to the device, not 71601e04c3fSmrg * including trailing unbound vertex buffers. 71701e04c3fSmrg */ 71801e04c3fSmrg svga->state.hw_draw.num_vbuffers = last_vbuf + 1; 71901e04c3fSmrg memcpy(svga->state.hw_draw.vbuffer_attrs, vbuffer_attrs, 72001e04c3fSmrg num_vbuffers * sizeof(vbuffer_attrs[0])); 72101e04c3fSmrg for (i = 0; i < num_vbuffers; i++) { 72201e04c3fSmrg pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], 72301e04c3fSmrg vbuffers[i]); 72401e04c3fSmrg } 72501e04c3fSmrg } 72601e04c3fSmrg } 72701e04c3fSmrg else { 72801e04c3fSmrg /* Even though we can avoid emitting the redundant SetVertexBuffers 72901e04c3fSmrg * command, we still need to reference the vertex buffers surfaces. 73001e04c3fSmrg */ 73101e04c3fSmrg for (i = 0; i < vbuf_count; i++) { 73201e04c3fSmrg if (vbuffer_handles[i] && !last_command_was_draw(svga)) { 7339f464c52Smaya enum pipe_error ret = 7349f464c52Smaya svga->swc->resource_rebind(svga->swc, vbuffer_handles[i], 7359f464c52Smaya NULL, SVGA_RELOC_READ); 73601e04c3fSmrg if (ret != PIPE_OK) 73701e04c3fSmrg return ret; 73801e04c3fSmrg } 73901e04c3fSmrg } 7404a49301eSmrg } 74101e04c3fSmrg } 74201e04c3fSmrg 7439f464c52Smaya return PIPE_OK; 7449f464c52Smaya} 7459f464c52Smaya 7469f464c52Smaya 7479f464c52Smaya/* 7489f464c52Smaya * Prepare the index buffer for a drawing command. 7499f464c52Smaya */ 7509f464c52Smayastatic enum pipe_error 7519f464c52Smayavalidate_index_buffer(struct svga_hwtnl *hwtnl, 7529f464c52Smaya const SVGA3dPrimitiveRange *range, 7539f464c52Smaya struct pipe_resource *ib) 7549f464c52Smaya{ 7559f464c52Smaya struct svga_context *svga = hwtnl->svga; 7569f464c52Smaya struct svga_winsys_surface *ib_handle = 7579f464c52Smaya svga_buffer_handle(svga, ib, PIPE_BIND_INDEX_BUFFER); 7589f464c52Smaya 7599f464c52Smaya if (!ib_handle) 7609f464c52Smaya return PIPE_ERROR_OUT_OF_MEMORY; 7619f464c52Smaya 7629f464c52Smaya struct svga_buffer *sbuf = svga_buffer(ib); 7639f464c52Smaya assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_INDEX_BUFFER); 7649f464c52Smaya (void) sbuf; /* silence unused var warning */ 7659f464c52Smaya 7669f464c52Smaya SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth); 7679f464c52Smaya 7689f464c52Smaya if (ib != svga->state.hw_draw.ib || 7699f464c52Smaya indexFormat != svga->state.hw_draw.ib_format || 7709f464c52Smaya range->indexArray.offset != svga->state.hw_draw.ib_offset) { 7719f464c52Smaya 7729f464c52Smaya assert(indexFormat != SVGA3D_FORMAT_INVALID); 7739f464c52Smaya enum pipe_error ret = 7749f464c52Smaya SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle, 7759f464c52Smaya indexFormat, 7769f464c52Smaya range->indexArray.offset); 7779f464c52Smaya if (ret != PIPE_OK) 7789f464c52Smaya return ret; 7799f464c52Smaya 7809f464c52Smaya pipe_resource_reference(&svga->state.hw_draw.ib, ib); 7819f464c52Smaya svga->state.hw_draw.ib_format = indexFormat; 7829f464c52Smaya svga->state.hw_draw.ib_offset = range->indexArray.offset; 7839f464c52Smaya } 7849f464c52Smaya else { 7859f464c52Smaya /* Even though we can avoid emitting the redundant SetIndexBuffer 7869f464c52Smaya * command, we still need to reference the index buffer surface. 7879f464c52Smaya */ 7889f464c52Smaya if (!last_command_was_draw(svga)) { 7899f464c52Smaya enum pipe_error ret = svga->swc->resource_rebind(svga->swc, 7909f464c52Smaya ib_handle, 7919f464c52Smaya NULL, 7929f464c52Smaya SVGA_RELOC_READ); 7939f464c52Smaya if (ret != PIPE_OK) 7949f464c52Smaya return ret; 7959f464c52Smaya } 7969f464c52Smaya } 7979f464c52Smaya 7989f464c52Smaya return PIPE_OK; 7999f464c52Smaya} 8009f464c52Smaya 8019f464c52Smaya 8029f464c52Smayastatic enum pipe_error 8039f464c52Smayadraw_vgpu10(struct svga_hwtnl *hwtnl, 8049f464c52Smaya const SVGA3dPrimitiveRange *range, 8059f464c52Smaya unsigned vcount, 8067ec681f3Smrg unsigned min_index, unsigned max_index, 8079f464c52Smaya struct pipe_resource *ib, 8087ec681f3Smrg unsigned start_instance, unsigned instance_count, 8097ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 8107ec681f3Smrg const struct pipe_stream_output_target *so_vertex_count) 8119f464c52Smaya{ 8129f464c52Smaya struct svga_context *svga = hwtnl->svga; 8137ec681f3Smrg struct svga_winsys_surface *indirect_handle; 8149f464c52Smaya enum pipe_error ret; 8159f464c52Smaya 8169f464c52Smaya assert(svga_have_vgpu10(svga)); 8179f464c52Smaya assert(hwtnl->cmd.prim_count == 0); 8189f464c52Smaya 8199f464c52Smaya /* We need to reemit all the current resource bindings along with the Draw 8209f464c52Smaya * command to be sure that the referenced resources are available for the 8219f464c52Smaya * Draw command, just in case the surfaces associated with the resources 8229f464c52Smaya * are paged out. 8239f464c52Smaya */ 8249f464c52Smaya if (svga->rebind.val) { 8259f464c52Smaya ret = svga_rebind_framebuffer_bindings(svga); 8269f464c52Smaya if (ret != PIPE_OK) 8279f464c52Smaya return ret; 8289f464c52Smaya 8299f464c52Smaya ret = svga_rebind_shaders(svga); 8309f464c52Smaya if (ret != PIPE_OK) 8319f464c52Smaya return ret; 8329f464c52Smaya 8339f464c52Smaya /* Rebind stream output targets */ 8349f464c52Smaya ret = svga_rebind_stream_output_targets(svga); 8359f464c52Smaya if (ret != PIPE_OK) 8369f464c52Smaya return ret; 8379f464c52Smaya 8389f464c52Smaya /* No need to explicitly rebind index buffer and vertex buffers here. 8399f464c52Smaya * Even if the same index buffer or vertex buffers are referenced for this 8409f464c52Smaya * draw and we skip emitting the redundant set command, we will still 8419f464c52Smaya * reference the associated resources. 8429f464c52Smaya */ 8439f464c52Smaya } 8449f464c52Smaya 8459f464c52Smaya ret = validate_sampler_resources(svga); 8469f464c52Smaya if (ret != PIPE_OK) 8479f464c52Smaya return ret; 8489f464c52Smaya 8499f464c52Smaya ret = validate_constant_buffers(svga); 8509f464c52Smaya if (ret != PIPE_OK) 8519f464c52Smaya return ret; 8529f464c52Smaya 8537ec681f3Smrg ret = validate_vertex_buffers(hwtnl, so_vertex_count); 8549f464c52Smaya if (ret != PIPE_OK) 8559f464c52Smaya return ret; 8569f464c52Smaya 8579f464c52Smaya if (ib) { 8589f464c52Smaya ret = validate_index_buffer(hwtnl, range, ib); 8599f464c52Smaya if (ret != PIPE_OK) 8609f464c52Smaya return ret; 8619f464c52Smaya } 8629f464c52Smaya 8637ec681f3Smrg if (indirect) { 8647ec681f3Smrg indirect_handle = svga_buffer_handle(svga, indirect->buffer, 8657ec681f3Smrg PIPE_BIND_COMMAND_ARGS_BUFFER); 8667ec681f3Smrg if (!indirect_handle) 8677ec681f3Smrg return PIPE_ERROR_OUT_OF_MEMORY; 8687ec681f3Smrg } 8697ec681f3Smrg else { 8707ec681f3Smrg indirect_handle = NULL; 8717ec681f3Smrg } 8727ec681f3Smrg 87301e04c3fSmrg /* Set primitive type (line, tri, etc) */ 87401e04c3fSmrg if (svga->state.hw_draw.topology != range->primType) { 87501e04c3fSmrg ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType); 87601e04c3fSmrg if (ret != PIPE_OK) 87701e04c3fSmrg return ret; 87801e04c3fSmrg 87901e04c3fSmrg svga->state.hw_draw.topology = range->primType; 88001e04c3fSmrg } 8814a49301eSmrg 8829f464c52Smaya if (ib) { 88301e04c3fSmrg /* indexed drawing */ 8847ec681f3Smrg if (indirect) { 8857ec681f3Smrg ret = SVGA3D_sm5_DrawIndexedInstancedIndirect(svga->swc, 8867ec681f3Smrg indirect_handle, 8877ec681f3Smrg indirect->offset); 8887ec681f3Smrg } 8897ec681f3Smrg else if (instance_count > 1) { 89001e04c3fSmrg ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc, 89101e04c3fSmrg vcount, 89201e04c3fSmrg instance_count, 89301e04c3fSmrg 0, /* startIndexLocation */ 89401e04c3fSmrg range->indexBias, 89501e04c3fSmrg start_instance); 89601e04c3fSmrg } 89701e04c3fSmrg else { 89801e04c3fSmrg /* non-instanced drawing */ 89901e04c3fSmrg ret = SVGA3D_vgpu10_DrawIndexed(svga->swc, 90001e04c3fSmrg vcount, 90101e04c3fSmrg 0, /* startIndexLocation */ 90201e04c3fSmrg range->indexBias); 9037ec681f3Smrg } 9047ec681f3Smrg if (ret != PIPE_OK) { 9057ec681f3Smrg return ret; 90601e04c3fSmrg } 9074a49301eSmrg } 90801e04c3fSmrg else { 90901e04c3fSmrg /* non-indexed drawing */ 91001e04c3fSmrg if (svga->state.hw_draw.ib_format != SVGA3D_FORMAT_INVALID || 91101e04c3fSmrg svga->state.hw_draw.ib != NULL) { 91201e04c3fSmrg /* Unbind previously bound index buffer */ 91301e04c3fSmrg ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, NULL, 91401e04c3fSmrg SVGA3D_FORMAT_INVALID, 0); 91501e04c3fSmrg if (ret != PIPE_OK) 91601e04c3fSmrg return ret; 91701e04c3fSmrg pipe_resource_reference(&svga->state.hw_draw.ib, NULL); 91801e04c3fSmrg svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID; 91901e04c3fSmrg } 92001e04c3fSmrg 92101e04c3fSmrg assert(svga->state.hw_draw.ib == NULL); 92201e04c3fSmrg 9237ec681f3Smrg if (so_vertex_count) { 9247ec681f3Smrg /* Stream-output drawing */ 9257ec681f3Smrg ret = SVGA3D_vgpu10_DrawAuto(svga->swc); 9267ec681f3Smrg } 9277ec681f3Smrg else if (indirect) { 9287ec681f3Smrg ret = SVGA3D_sm5_DrawInstancedIndirect(svga->swc, 9297ec681f3Smrg indirect_handle, 9307ec681f3Smrg indirect->offset); 9317ec681f3Smrg } 9327ec681f3Smrg else if (instance_count > 1) { 93301e04c3fSmrg ret = SVGA3D_vgpu10_DrawInstanced(svga->swc, 93401e04c3fSmrg vcount, 93501e04c3fSmrg instance_count, 93601e04c3fSmrg range->indexBias, 93701e04c3fSmrg start_instance); 93801e04c3fSmrg } 93901e04c3fSmrg else { 94001e04c3fSmrg /* non-instanced */ 94101e04c3fSmrg ret = SVGA3D_vgpu10_Draw(svga->swc, 94201e04c3fSmrg vcount, 94301e04c3fSmrg range->indexBias); 9447ec681f3Smrg } 9457ec681f3Smrg if (ret != PIPE_OK) { 9467ec681f3Smrg return ret; 94701e04c3fSmrg } 94801e04c3fSmrg } 94901e04c3fSmrg 95001e04c3fSmrg hwtnl->cmd.prim_count = 0; 9514a49301eSmrg 9524a49301eSmrg return PIPE_OK; 9534a49301eSmrg} 9544a49301eSmrg 9554a49301eSmrg 95601e04c3fSmrg 95701e04c3fSmrg/** 95801e04c3fSmrg * Emit any pending drawing commands to the command buffer. 95901e04c3fSmrg * When we receive VGPU9 drawing commands we accumulate them and don't 96001e04c3fSmrg * immediately emit them into the command buffer. 96101e04c3fSmrg * This function needs to be called before we change state that could 96201e04c3fSmrg * effect those pending draws. 96301e04c3fSmrg */ 96401e04c3fSmrgenum pipe_error 96501e04c3fSmrgsvga_hwtnl_flush(struct svga_hwtnl *hwtnl) 96601e04c3fSmrg{ 96701e04c3fSmrg enum pipe_error ret = PIPE_OK; 96801e04c3fSmrg 96901e04c3fSmrg SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLFLUSH); 97001e04c3fSmrg 97101e04c3fSmrg if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) { 97201e04c3fSmrg /* we only queue up primitive for VGPU9 */ 97301e04c3fSmrg ret = draw_vgpu9(hwtnl); 97401e04c3fSmrg } 97501e04c3fSmrg 97601e04c3fSmrg SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws); 97701e04c3fSmrg return ret; 97801e04c3fSmrg} 97901e04c3fSmrg 98001e04c3fSmrg 981af69d88dSmrgvoid 982af69d88dSmrgsvga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias) 983af69d88dSmrg{ 984af69d88dSmrg hwtnl->index_bias = index_bias; 985af69d88dSmrg} 9864a49301eSmrg 9874a49301eSmrg 9884a49301eSmrg 9894a49301eSmrg/*********************************************************************** 9904a49301eSmrg * Internal functions: 9914a49301eSmrg */ 9924a49301eSmrg 993af69d88dSmrg/** 994af69d88dSmrg * For debugging only. 995af69d88dSmrg */ 996af69d88dSmrgstatic void 997af69d88dSmrgcheck_draw_params(struct svga_hwtnl *hwtnl, 998af69d88dSmrg const SVGA3dPrimitiveRange *range, 999af69d88dSmrg unsigned min_index, unsigned max_index, 1000af69d88dSmrg struct pipe_resource *ib) 10014a49301eSmrg{ 1002af69d88dSmrg unsigned i; 10034a49301eSmrg 100401e04c3fSmrg assert(!svga_have_vgpu10(hwtnl->svga)); 100501e04c3fSmrg 1006af69d88dSmrg for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 100701e04c3fSmrg unsigned j = hwtnl->cmd.vdecl_buffer_index[i]; 100801e04c3fSmrg const struct pipe_vertex_buffer *vb = &hwtnl->cmd.vbufs[j]; 100901e04c3fSmrg unsigned size = vb->buffer.resource ? vb->buffer.resource->width0 : 0; 1010af69d88dSmrg unsigned offset = hwtnl->cmd.vdecl[i].array.offset; 1011af69d88dSmrg unsigned stride = hwtnl->cmd.vdecl[i].array.stride; 1012af69d88dSmrg int index_bias = (int) range->indexBias + hwtnl->index_bias; 1013af69d88dSmrg unsigned width; 1014af69d88dSmrg 101501e04c3fSmrg if (size == 0) 101601e04c3fSmrg continue; 101701e04c3fSmrg 1018af69d88dSmrg assert(vb); 1019af69d88dSmrg assert(size); 1020af69d88dSmrg assert(offset < size); 1021af69d88dSmrg assert(min_index <= max_index); 102201e04c3fSmrg (void) width; 102301e04c3fSmrg (void) stride; 102401e04c3fSmrg (void) offset; 102501e04c3fSmrg (void) size; 1026af69d88dSmrg 1027af69d88dSmrg switch (hwtnl->cmd.vdecl[i].identity.type) { 1028af69d88dSmrg case SVGA3D_DECLTYPE_FLOAT1: 1029af69d88dSmrg width = 4; 1030af69d88dSmrg break; 1031af69d88dSmrg case SVGA3D_DECLTYPE_FLOAT2: 1032af69d88dSmrg width = 4 * 2; 1033af69d88dSmrg break; 1034af69d88dSmrg case SVGA3D_DECLTYPE_FLOAT3: 1035af69d88dSmrg width = 4 * 3; 1036af69d88dSmrg break; 1037af69d88dSmrg case SVGA3D_DECLTYPE_FLOAT4: 1038af69d88dSmrg width = 4 * 4; 1039af69d88dSmrg break; 1040af69d88dSmrg case SVGA3D_DECLTYPE_D3DCOLOR: 1041af69d88dSmrg width = 4; 1042af69d88dSmrg break; 1043af69d88dSmrg case SVGA3D_DECLTYPE_UBYTE4: 1044af69d88dSmrg width = 1 * 4; 1045af69d88dSmrg break; 1046af69d88dSmrg case SVGA3D_DECLTYPE_SHORT2: 1047af69d88dSmrg width = 2 * 2; 1048af69d88dSmrg break; 1049af69d88dSmrg case SVGA3D_DECLTYPE_SHORT4: 1050af69d88dSmrg width = 2 * 4; 1051af69d88dSmrg break; 1052af69d88dSmrg case SVGA3D_DECLTYPE_UBYTE4N: 1053af69d88dSmrg width = 1 * 4; 1054af69d88dSmrg break; 1055af69d88dSmrg case SVGA3D_DECLTYPE_SHORT2N: 1056af69d88dSmrg width = 2 * 2; 1057af69d88dSmrg break; 1058af69d88dSmrg case SVGA3D_DECLTYPE_SHORT4N: 1059af69d88dSmrg width = 2 * 4; 1060af69d88dSmrg break; 1061af69d88dSmrg case SVGA3D_DECLTYPE_USHORT2N: 1062af69d88dSmrg width = 2 * 2; 1063af69d88dSmrg break; 1064af69d88dSmrg case SVGA3D_DECLTYPE_USHORT4N: 1065af69d88dSmrg width = 2 * 4; 1066af69d88dSmrg break; 1067af69d88dSmrg case SVGA3D_DECLTYPE_UDEC3: 1068af69d88dSmrg width = 4; 1069af69d88dSmrg break; 1070af69d88dSmrg case SVGA3D_DECLTYPE_DEC3N: 1071af69d88dSmrg width = 4; 1072af69d88dSmrg break; 1073af69d88dSmrg case SVGA3D_DECLTYPE_FLOAT16_2: 1074af69d88dSmrg width = 2 * 2; 1075af69d88dSmrg break; 1076af69d88dSmrg case SVGA3D_DECLTYPE_FLOAT16_4: 1077af69d88dSmrg width = 2 * 4; 1078af69d88dSmrg break; 1079af69d88dSmrg default: 1080af69d88dSmrg assert(0); 1081af69d88dSmrg width = 0; 1082af69d88dSmrg break; 1083af69d88dSmrg } 10844a49301eSmrg 1085af69d88dSmrg if (index_bias >= 0) { 1086af69d88dSmrg assert(offset + index_bias * stride + width <= size); 10874a49301eSmrg } 10884a49301eSmrg 1089af69d88dSmrg /* 1090af69d88dSmrg * min_index/max_index are merely conservative guesses, so we can't 1091af69d88dSmrg * make buffer overflow detection based on their values. 1092af69d88dSmrg */ 1093af69d88dSmrg } 10944a49301eSmrg 1095af69d88dSmrg assert(range->indexWidth == range->indexArray.stride); 1096af69d88dSmrg 1097af69d88dSmrg if (ib) { 10987ec681f3Smrg ASSERTED unsigned size = ib->width0; 10997ec681f3Smrg ASSERTED unsigned offset = range->indexArray.offset; 11007ec681f3Smrg ASSERTED unsigned stride = range->indexArray.stride; 11017ec681f3Smrg ASSERTED unsigned count; 1102af69d88dSmrg 1103af69d88dSmrg assert(size); 1104af69d88dSmrg assert(offset < size); 1105af69d88dSmrg assert(stride); 1106af69d88dSmrg 1107af69d88dSmrg switch (range->primType) { 1108af69d88dSmrg case SVGA3D_PRIMITIVE_POINTLIST: 1109af69d88dSmrg count = range->primitiveCount; 1110af69d88dSmrg break; 1111af69d88dSmrg case SVGA3D_PRIMITIVE_LINELIST: 1112af69d88dSmrg count = range->primitiveCount * 2; 1113af69d88dSmrg break; 1114af69d88dSmrg case SVGA3D_PRIMITIVE_LINESTRIP: 1115af69d88dSmrg count = range->primitiveCount + 1; 1116af69d88dSmrg break; 1117af69d88dSmrg case SVGA3D_PRIMITIVE_TRIANGLELIST: 1118af69d88dSmrg count = range->primitiveCount * 3; 1119af69d88dSmrg break; 1120af69d88dSmrg case SVGA3D_PRIMITIVE_TRIANGLESTRIP: 1121af69d88dSmrg count = range->primitiveCount + 2; 1122af69d88dSmrg break; 1123af69d88dSmrg case SVGA3D_PRIMITIVE_TRIANGLEFAN: 1124af69d88dSmrg count = range->primitiveCount + 2; 1125af69d88dSmrg break; 1126af69d88dSmrg default: 1127af69d88dSmrg assert(0); 1128af69d88dSmrg count = 0; 1129af69d88dSmrg break; 11304a49301eSmrg } 1131af69d88dSmrg 1132af69d88dSmrg assert(offset + count * stride <= size); 11334a49301eSmrg } 1134af69d88dSmrg} 1135af69d88dSmrg 1136af69d88dSmrg 113701e04c3fSmrg/** 113801e04c3fSmrg * All drawing filters down into this function, either directly 113901e04c3fSmrg * on the hardware path or after doing software vertex processing. 11407ec681f3Smrg * \param indirect if non-null, get the vertex count, first vertex, etc. 11417ec681f3Smrg * from a buffer. 11427ec681f3Smrg * \param so_vertex_count if non-null, get the vertex count from a 11437ec681f3Smrg * stream-output target. 114401e04c3fSmrg */ 1145af69d88dSmrgenum pipe_error 1146af69d88dSmrgsvga_hwtnl_prim(struct svga_hwtnl *hwtnl, 11477ec681f3Smrg const SVGA3dPrimitiveRange *range, 114801e04c3fSmrg unsigned vcount, 11497ec681f3Smrg unsigned min_index, unsigned max_index, 11507ec681f3Smrg struct pipe_resource *ib, 11517ec681f3Smrg unsigned start_instance, unsigned instance_count, 11527ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 11537ec681f3Smrg const struct pipe_stream_output_target *so_vertex_count) 1154af69d88dSmrg{ 1155af69d88dSmrg enum pipe_error ret = PIPE_OK; 1156af69d88dSmrg 115701e04c3fSmrg SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLPRIM); 115801e04c3fSmrg 115901e04c3fSmrg if (svga_have_vgpu10(hwtnl->svga)) { 116001e04c3fSmrg /* draw immediately */ 11617ec681f3Smrg SVGA_RETRY(hwtnl->svga, draw_vgpu10(hwtnl, range, vcount, min_index, 11627ec681f3Smrg max_index, ib, start_instance, 11637ec681f3Smrg instance_count, indirect, 11647ec681f3Smrg so_vertex_count)); 116501e04c3fSmrg } 116601e04c3fSmrg else { 116701e04c3fSmrg /* batch up drawing commands */ 11687ec681f3Smrg assert(indirect == NULL); 1169af69d88dSmrg#ifdef DEBUG 117001e04c3fSmrg check_draw_params(hwtnl, range, min_index, max_index, ib); 117101e04c3fSmrg assert(start_instance == 0); 117201e04c3fSmrg assert(instance_count <= 1); 117301e04c3fSmrg#else 117401e04c3fSmrg (void) check_draw_params; 11754a49301eSmrg#endif 11764a49301eSmrg 117701e04c3fSmrg if (hwtnl->cmd.prim_count + 1 >= QSZ) { 117801e04c3fSmrg ret = svga_hwtnl_flush(hwtnl); 117901e04c3fSmrg if (ret != PIPE_OK) 118001e04c3fSmrg goto done; 118101e04c3fSmrg } 1182af69d88dSmrg 118301e04c3fSmrg /* min/max indices are relative to bias */ 118401e04c3fSmrg hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index; 118501e04c3fSmrg hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index; 11864a49301eSmrg 118701e04c3fSmrg hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range; 118801e04c3fSmrg hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias; 11894a49301eSmrg 119001e04c3fSmrg pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib); 119101e04c3fSmrg hwtnl->cmd.prim_count++; 119201e04c3fSmrg } 11934a49301eSmrg 119401e04c3fSmrgdone: 119501e04c3fSmrg SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws); 11964a49301eSmrg return ret; 11974a49301eSmrg} 11987ec681f3Smrg 11997ec681f3Smrg 12007ec681f3Smrg/** 12017ec681f3Smrg * Return TRUE if there are pending primitives. 12027ec681f3Smrg */ 12037ec681f3Smrgboolean 12047ec681f3Smrgsvga_hwtnl_has_pending_prim(struct svga_hwtnl *hwtnl) 12057ec681f3Smrg{ 12067ec681f3Smrg return hwtnl->cmd.prim_count > 0; 12077ec681f3Smrg} 1208