1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "pipe/p_compiler.h" 27bf215546Sopenharmony_ci#include "util/u_inlines.h" 28bf215546Sopenharmony_ci#include "pipe/p_defines.h" 29bf215546Sopenharmony_ci#include "util/u_helpers.h" 30bf215546Sopenharmony_ci#include "util/u_memory.h" 31bf215546Sopenharmony_ci#include "util/u_math.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "svga_context.h" 34bf215546Sopenharmony_ci#include "svga_draw.h" 35bf215546Sopenharmony_ci#include "svga_draw_private.h" 36bf215546Sopenharmony_ci#include "svga_debug.h" 37bf215546Sopenharmony_ci#include "svga_screen.h" 38bf215546Sopenharmony_ci#include "svga_resource.h" 39bf215546Sopenharmony_ci#include "svga_resource_buffer.h" 40bf215546Sopenharmony_ci#include "svga_resource_texture.h" 41bf215546Sopenharmony_ci#include "svga_sampler_view.h" 42bf215546Sopenharmony_ci#include "svga_shader.h" 43bf215546Sopenharmony_ci#include "svga_surface.h" 44bf215546Sopenharmony_ci#include "svga_winsys.h" 45bf215546Sopenharmony_ci#include "svga_cmd.h" 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistruct svga_hwtnl * 49bf215546Sopenharmony_cisvga_hwtnl_create(struct svga_context *svga) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci struct svga_hwtnl *hwtnl = CALLOC_STRUCT(svga_hwtnl); 52bf215546Sopenharmony_ci if (!hwtnl) 53bf215546Sopenharmony_ci goto fail; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci hwtnl->svga = svga; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci hwtnl->cmd.swc = svga->swc; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci return hwtnl; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_cifail: 62bf215546Sopenharmony_ci return NULL; 63bf215546Sopenharmony_ci} 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_civoid 67bf215546Sopenharmony_cisvga_hwtnl_destroy(struct svga_hwtnl *hwtnl) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci unsigned i, j; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci for (i = 0; i < PIPE_PRIM_MAX; i++) { 72bf215546Sopenharmony_ci for (j = 0; j < IDX_CACHE_MAX; j++) { 73bf215546Sopenharmony_ci pipe_resource_reference(&hwtnl->index_cache[i][j].buffer, NULL); 74bf215546Sopenharmony_ci } 75bf215546Sopenharmony_ci } 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.vbuf_count; i++) 78bf215546Sopenharmony_ci pipe_vertex_buffer_unreference(&hwtnl->cmd.vbufs[i]); 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.prim_count; i++) 81bf215546Sopenharmony_ci pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL); 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci FREE(hwtnl); 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_civoid 88bf215546Sopenharmony_cisvga_hwtnl_set_flatshade(struct svga_hwtnl *hwtnl, 89bf215546Sopenharmony_ci boolean flatshade, boolean flatshade_first) 90bf215546Sopenharmony_ci{ 91bf215546Sopenharmony_ci struct svga_screen *svgascreen = svga_screen(hwtnl->svga->pipe.screen); 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci /* User-specified PV */ 94bf215546Sopenharmony_ci hwtnl->api_pv = (flatshade && !flatshade_first) ? PV_LAST : PV_FIRST; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci /* Device supported PV */ 97bf215546Sopenharmony_ci if (svgascreen->haveProvokingVertex) { 98bf215546Sopenharmony_ci /* use the mode specified by the user */ 99bf215546Sopenharmony_ci hwtnl->hw_pv = hwtnl->api_pv; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci else { 102bf215546Sopenharmony_ci /* the device only support first provoking vertex */ 103bf215546Sopenharmony_ci hwtnl->hw_pv = PV_FIRST; 104bf215546Sopenharmony_ci } 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_civoid 109bf215546Sopenharmony_cisvga_hwtnl_set_fillmode(struct svga_hwtnl *hwtnl, unsigned mode) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci hwtnl->api_fillmode = mode; 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_civoid 116bf215546Sopenharmony_cisvga_hwtnl_vertex_decls(struct svga_hwtnl *hwtnl, 117bf215546Sopenharmony_ci unsigned count, 118bf215546Sopenharmony_ci const SVGA3dVertexDecl * decls, 119bf215546Sopenharmony_ci const unsigned *buffer_indexes, 120bf215546Sopenharmony_ci SVGA3dElementLayoutId layout_id) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci assert(hwtnl->cmd.prim_count == 0); 123bf215546Sopenharmony_ci hwtnl->cmd.vdecl_count = count; 124bf215546Sopenharmony_ci hwtnl->cmd.vdecl_layout_id = layout_id; 125bf215546Sopenharmony_ci memcpy(hwtnl->cmd.vdecl, decls, count * sizeof(*decls)); 126bf215546Sopenharmony_ci memcpy(hwtnl->cmd.vdecl_buffer_index, buffer_indexes, 127bf215546Sopenharmony_ci count * sizeof(unsigned)); 128bf215546Sopenharmony_ci} 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci/** 132bf215546Sopenharmony_ci * Specify vertex buffers for hardware drawing. 133bf215546Sopenharmony_ci */ 134bf215546Sopenharmony_civoid 135bf215546Sopenharmony_cisvga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl, 136bf215546Sopenharmony_ci unsigned count, struct pipe_vertex_buffer *buffers) 137bf215546Sopenharmony_ci{ 138bf215546Sopenharmony_ci struct pipe_vertex_buffer *dst = hwtnl->cmd.vbufs; 139bf215546Sopenharmony_ci const struct pipe_vertex_buffer *src = buffers; 140bf215546Sopenharmony_ci unsigned i; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 143bf215546Sopenharmony_ci pipe_vertex_buffer_reference(&dst[i], &src[i]); 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci /* release old buffer references */ 147bf215546Sopenharmony_ci for ( ; i < hwtnl->cmd.vbuf_count; i++) { 148bf215546Sopenharmony_ci pipe_vertex_buffer_unreference(&dst[i]); 149bf215546Sopenharmony_ci /* don't bother zeroing stride/offset fields */ 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci hwtnl->cmd.vbuf_count = count; 153bf215546Sopenharmony_ci} 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci/** 157bf215546Sopenharmony_ci * Determine whether the specified buffer is referred in the primitive queue, 158bf215546Sopenharmony_ci * for which no commands have been written yet. 159bf215546Sopenharmony_ci */ 160bf215546Sopenharmony_ciboolean 161bf215546Sopenharmony_cisvga_hwtnl_is_buffer_referred(struct svga_hwtnl *hwtnl, 162bf215546Sopenharmony_ci struct pipe_resource *buffer) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci unsigned i; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci if (svga_buffer_is_user_buffer(buffer)) { 167bf215546Sopenharmony_ci return FALSE; 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci if (!hwtnl->cmd.prim_count) { 171bf215546Sopenharmony_ci return FALSE; 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.vbuf_count; ++i) { 175bf215546Sopenharmony_ci if (hwtnl->cmd.vbufs[i].buffer.resource == buffer) { 176bf215546Sopenharmony_ci return TRUE; 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.prim_count; ++i) { 181bf215546Sopenharmony_ci if (hwtnl->cmd.prim_ib[i] == buffer) { 182bf215546Sopenharmony_ci return TRUE; 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci return FALSE; 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic enum pipe_error 191bf215546Sopenharmony_cidraw_vgpu9(struct svga_hwtnl *hwtnl) 192bf215546Sopenharmony_ci{ 193bf215546Sopenharmony_ci struct svga_winsys_context *swc = hwtnl->cmd.swc; 194bf215546Sopenharmony_ci struct svga_context *svga = hwtnl->svga; 195bf215546Sopenharmony_ci enum pipe_error ret; 196bf215546Sopenharmony_ci struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX]; 197bf215546Sopenharmony_ci struct svga_winsys_surface *ib_handle[QSZ]; 198bf215546Sopenharmony_ci struct svga_winsys_surface *handle; 199bf215546Sopenharmony_ci SVGA3dVertexDecl *vdecl; 200bf215546Sopenharmony_ci SVGA3dPrimitiveRange *prim; 201bf215546Sopenharmony_ci unsigned i; 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci /* Re-validate those sampler views with backing copy 204bf215546Sopenharmony_ci * of texture whose original copy has been updated. 205bf215546Sopenharmony_ci * This is done here at draw time because the texture binding might not 206bf215546Sopenharmony_ci * have modified, hence validation is not triggered at state update time, 207bf215546Sopenharmony_ci * and yet the texture might have been updated in another context, so 208bf215546Sopenharmony_ci * we need to re-validate the sampler view in order to update the backing 209bf215546Sopenharmony_ci * copy of the updated texture. 210bf215546Sopenharmony_ci */ 211bf215546Sopenharmony_ci if (svga->state.hw_draw.num_backed_views) { 212bf215546Sopenharmony_ci for (i = 0; i < svga->state.hw_draw.num_views; i++) { 213bf215546Sopenharmony_ci struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; 214bf215546Sopenharmony_ci struct svga_texture *tex = svga_texture(view->texture); 215bf215546Sopenharmony_ci struct svga_sampler_view *sv = view->v; 216bf215546Sopenharmony_ci if (sv && tex && sv->handle != tex->handle && sv->age < tex->age) 217bf215546Sopenharmony_ci svga_validate_sampler_view(svga, view->v); 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 222bf215546Sopenharmony_ci unsigned j = hwtnl->cmd.vdecl_buffer_index[i]; 223bf215546Sopenharmony_ci handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer.resource, 224bf215546Sopenharmony_ci PIPE_BIND_VERTEX_BUFFER); 225bf215546Sopenharmony_ci if (!handle) 226bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci vb_handle[i] = handle; 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.prim_count; i++) { 232bf215546Sopenharmony_ci if (hwtnl->cmd.prim_ib[i]) { 233bf215546Sopenharmony_ci handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i], 234bf215546Sopenharmony_ci PIPE_BIND_INDEX_BUFFER); 235bf215546Sopenharmony_ci if (!handle) 236bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci else 239bf215546Sopenharmony_ci handle = NULL; 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci ib_handle[i] = handle; 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if (svga->rebind.flags.rendertargets) { 245bf215546Sopenharmony_ci ret = svga_reemit_framebuffer_bindings(svga); 246bf215546Sopenharmony_ci if (ret != PIPE_OK) { 247bf215546Sopenharmony_ci return ret; 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci } 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci if (svga->rebind.flags.texture_samplers) { 252bf215546Sopenharmony_ci ret = svga_reemit_tss_bindings(svga); 253bf215546Sopenharmony_ci if (ret != PIPE_OK) { 254bf215546Sopenharmony_ci return ret; 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci if (svga->rebind.flags.vs) { 259bf215546Sopenharmony_ci ret = svga_reemit_vs_bindings(svga); 260bf215546Sopenharmony_ci if (ret != PIPE_OK) { 261bf215546Sopenharmony_ci return ret; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci } 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci if (svga->rebind.flags.fs) { 266bf215546Sopenharmony_ci ret = svga_reemit_fs_bindings(svga); 267bf215546Sopenharmony_ci if (ret != PIPE_OK) { 268bf215546Sopenharmony_ci return ret; 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n", 273bf215546Sopenharmony_ci svga->curr.framebuffer.cbufs[0] ? 274bf215546Sopenharmony_ci svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL, 275bf215546Sopenharmony_ci hwtnl->cmd.prim_count); 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci ret = SVGA3D_BeginDrawPrimitives(swc, 278bf215546Sopenharmony_ci &vdecl, 279bf215546Sopenharmony_ci hwtnl->cmd.vdecl_count, 280bf215546Sopenharmony_ci &prim, hwtnl->cmd.prim_count); 281bf215546Sopenharmony_ci if (ret != PIPE_OK) 282bf215546Sopenharmony_ci return ret; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci memcpy(vdecl, 285bf215546Sopenharmony_ci hwtnl->cmd.vdecl, 286bf215546Sopenharmony_ci hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]); 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 289bf215546Sopenharmony_ci /* check for 4-byte alignment */ 290bf215546Sopenharmony_ci assert(vdecl[i].array.offset % 4 == 0); 291bf215546Sopenharmony_ci assert(vdecl[i].array.stride % 4 == 0); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci /* Given rangeHint is considered to be relative to indexBias, and 294bf215546Sopenharmony_ci * indexBias varies per primitive, we cannot accurately supply an 295bf215546Sopenharmony_ci * rangeHint when emitting more than one primitive per draw command. 296bf215546Sopenharmony_ci */ 297bf215546Sopenharmony_ci if (hwtnl->cmd.prim_count == 1) { 298bf215546Sopenharmony_ci vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0]; 299bf215546Sopenharmony_ci vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1; 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci else { 302bf215546Sopenharmony_ci vdecl[i].rangeHint.first = 0; 303bf215546Sopenharmony_ci vdecl[i].rangeHint.last = 0; 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci swc->surface_relocation(swc, 307bf215546Sopenharmony_ci &vdecl[i].array.surfaceId, 308bf215546Sopenharmony_ci NULL, vb_handle[i], SVGA_RELOC_READ); 309bf215546Sopenharmony_ci } 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci memcpy(prim, 312bf215546Sopenharmony_ci hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]); 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.prim_count; i++) { 315bf215546Sopenharmony_ci swc->surface_relocation(swc, 316bf215546Sopenharmony_ci &prim[i].indexArray.surfaceId, 317bf215546Sopenharmony_ci NULL, ib_handle[i], SVGA_RELOC_READ); 318bf215546Sopenharmony_ci pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL); 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci SVGA_FIFOCommitAll(swc); 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci hwtnl->cmd.prim_count = 0; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci return PIPE_OK; 326bf215546Sopenharmony_ci} 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_cistatic SVGA3dSurfaceFormat 330bf215546Sopenharmony_cixlate_index_format(unsigned indexWidth) 331bf215546Sopenharmony_ci{ 332bf215546Sopenharmony_ci if (indexWidth == 2) { 333bf215546Sopenharmony_ci return SVGA3D_R16_UINT; 334bf215546Sopenharmony_ci } 335bf215546Sopenharmony_ci else if (indexWidth == 4) { 336bf215546Sopenharmony_ci return SVGA3D_R32_UINT; 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci else { 339bf215546Sopenharmony_ci assert(!"Bad indexWidth"); 340bf215546Sopenharmony_ci return SVGA3D_R32_UINT; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci} 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci/** 346bf215546Sopenharmony_ci * A helper function to validate sampler view resources to ensure any 347bf215546Sopenharmony_ci * pending updates to buffers will be emitted before they are referenced 348bf215546Sopenharmony_ci * at draw or dispatch time. It also rebinds the resources if needed. 349bf215546Sopenharmony_ci */ 350bf215546Sopenharmony_cienum pipe_error 351bf215546Sopenharmony_cisvga_validate_sampler_resources(struct svga_context *svga, 352bf215546Sopenharmony_ci enum svga_pipe_type pipe_type) 353bf215546Sopenharmony_ci{ 354bf215546Sopenharmony_ci enum pipe_shader_type shader, first_shader, last_shader; 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci if (pipe_type == SVGA_PIPE_GRAPHICS) { 359bf215546Sopenharmony_ci first_shader = PIPE_SHADER_VERTEX; 360bf215546Sopenharmony_ci last_shader = PIPE_SHADER_TESS_EVAL; 361bf215546Sopenharmony_ci } 362bf215546Sopenharmony_ci else { 363bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 364bf215546Sopenharmony_ci first_shader = PIPE_SHADER_COMPUTE; 365bf215546Sopenharmony_ci last_shader = PIPE_SHADER_COMPUTE; 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci for (shader = first_shader; shader <= last_shader; shader++) { 369bf215546Sopenharmony_ci unsigned count = svga->curr.num_sampler_views[shader]; 370bf215546Sopenharmony_ci unsigned i; 371bf215546Sopenharmony_ci struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS]; 372bf215546Sopenharmony_ci enum pipe_error ret; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci /* 375bf215546Sopenharmony_ci * Reference bound sampler resources to ensure pending updates are 376bf215546Sopenharmony_ci * noticed by the device. 377bf215546Sopenharmony_ci */ 378bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 379bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv = 380bf215546Sopenharmony_ci svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci if (sv) { 383bf215546Sopenharmony_ci if (sv->base.texture->target == PIPE_BUFFER) { 384bf215546Sopenharmony_ci surfaces[i] = svga_buffer_handle(svga, sv->base.texture, 385bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW); 386bf215546Sopenharmony_ci } 387bf215546Sopenharmony_ci else { 388bf215546Sopenharmony_ci surfaces[i] = svga_texture(sv->base.texture)->handle; 389bf215546Sopenharmony_ci } 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci else { 392bf215546Sopenharmony_ci surfaces[i] = NULL; 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci } 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci if (shader == PIPE_SHADER_FRAGMENT && 397bf215546Sopenharmony_ci svga->curr.rast->templ.poly_stipple_enable) { 398bf215546Sopenharmony_ci const unsigned unit = 399bf215546Sopenharmony_ci svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit; 400bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv = 401bf215546Sopenharmony_ci svga->polygon_stipple.sampler_view; 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci assert(sv); 404bf215546Sopenharmony_ci surfaces[unit] = svga_texture(sv->base.texture)->handle; 405bf215546Sopenharmony_ci count = MAX2(count, unit+1); 406bf215546Sopenharmony_ci } 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci /* rebind the shader resources if needed */ 409bf215546Sopenharmony_ci if (svga->rebind.flags.texture_samplers) { 410bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 411bf215546Sopenharmony_ci if (surfaces[i]) { 412bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, 413bf215546Sopenharmony_ci surfaces[i], 414bf215546Sopenharmony_ci NULL, 415bf215546Sopenharmony_ci SVGA_RELOC_READ); 416bf215546Sopenharmony_ci if (ret != PIPE_OK) 417bf215546Sopenharmony_ci return ret; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci } 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci svga->rebind.flags.texture_samplers = FALSE; 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci return PIPE_OK; 425bf215546Sopenharmony_ci} 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci/** 429bf215546Sopenharmony_ci * A helper function to validate constant buffers to ensure any 430bf215546Sopenharmony_ci * pending updates to the buffers will be emitted before they are referenced 431bf215546Sopenharmony_ci * at draw or dispatch time. It also rebinds the resources if needed. 432bf215546Sopenharmony_ci */ 433bf215546Sopenharmony_cienum pipe_error 434bf215546Sopenharmony_cisvga_validate_constant_buffers(struct svga_context *svga, 435bf215546Sopenharmony_ci enum svga_pipe_type pipe_type) 436bf215546Sopenharmony_ci{ 437bf215546Sopenharmony_ci enum pipe_shader_type shader, first_shader, last_shader; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci if (pipe_type == SVGA_PIPE_GRAPHICS) { 442bf215546Sopenharmony_ci first_shader = PIPE_SHADER_VERTEX; 443bf215546Sopenharmony_ci last_shader = PIPE_SHADER_TESS_EVAL; 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci else { 446bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 447bf215546Sopenharmony_ci first_shader = PIPE_SHADER_COMPUTE; 448bf215546Sopenharmony_ci last_shader = PIPE_SHADER_COMPUTE; 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci for (shader = first_shader; shader <= last_shader; shader++) { 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci enum pipe_error ret; 454bf215546Sopenharmony_ci struct svga_buffer *buffer; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci /* Rebind the default constant buffer if needed */ 457bf215546Sopenharmony_ci if (svga->rebind.flags.constbufs) { 458bf215546Sopenharmony_ci buffer = svga_buffer(svga->state.hw_draw.constbuf[shader][0]); 459bf215546Sopenharmony_ci if (buffer) { 460bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, 461bf215546Sopenharmony_ci buffer->handle, 462bf215546Sopenharmony_ci NULL, 463bf215546Sopenharmony_ci SVGA_RELOC_READ); 464bf215546Sopenharmony_ci if (ret != PIPE_OK) 465bf215546Sopenharmony_ci return ret; 466bf215546Sopenharmony_ci } 467bf215546Sopenharmony_ci } 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci struct svga_winsys_surface *handle; 470bf215546Sopenharmony_ci unsigned enabled_constbufs; 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci /* 473bf215546Sopenharmony_ci * Reference other bound constant buffers to ensure pending updates are 474bf215546Sopenharmony_ci * noticed by the device. 475bf215546Sopenharmony_ci */ 476bf215546Sopenharmony_ci enabled_constbufs = svga->state.hw_draw.enabled_constbufs[shader] & ~1u; 477bf215546Sopenharmony_ci while (enabled_constbufs) { 478bf215546Sopenharmony_ci unsigned i = u_bit_scan(&enabled_constbufs); 479bf215546Sopenharmony_ci buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci /* If the constant buffer has hw storage, get the buffer winsys handle. 482bf215546Sopenharmony_ci * Rebind the resource if needed. 483bf215546Sopenharmony_ci */ 484bf215546Sopenharmony_ci if (buffer && !buffer->use_swbuf) 485bf215546Sopenharmony_ci handle = svga_buffer_handle(svga, &buffer->b, 486bf215546Sopenharmony_ci PIPE_BIND_CONSTANT_BUFFER); 487bf215546Sopenharmony_ci else 488bf215546Sopenharmony_ci handle = svga->state.hw_draw.constbufoffsets[shader][i].handle; 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci if (svga->rebind.flags.constbufs && handle) { 491bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, 492bf215546Sopenharmony_ci handle, 493bf215546Sopenharmony_ci NULL, 494bf215546Sopenharmony_ci SVGA_RELOC_READ); 495bf215546Sopenharmony_ci if (ret != PIPE_OK) 496bf215546Sopenharmony_ci return ret; 497bf215546Sopenharmony_ci } 498bf215546Sopenharmony_ci } 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci /* Reference raw constant buffers as they are not included in the 501bf215546Sopenharmony_ci * hw constant buffers list. 502bf215546Sopenharmony_ci */ 503bf215546Sopenharmony_ci unsigned enabled_rawbufs = svga->state.hw_draw.enabled_rawbufs[shader] & ~1u; 504bf215546Sopenharmony_ci while (enabled_rawbufs) { 505bf215546Sopenharmony_ci unsigned i = u_bit_scan(&enabled_rawbufs); 506bf215546Sopenharmony_ci buffer = svga_buffer(svga->curr.constbufs[shader][i].buffer); 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci assert(buffer != NULL); 509bf215546Sopenharmony_ci handle = svga_buffer_handle(svga, &buffer->b, 510bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW); 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci if (svga->rebind.flags.constbufs && handle) { 513bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, 514bf215546Sopenharmony_ci handle, 515bf215546Sopenharmony_ci NULL, 516bf215546Sopenharmony_ci SVGA_RELOC_READ); 517bf215546Sopenharmony_ci if (ret != PIPE_OK) 518bf215546Sopenharmony_ci return ret; 519bf215546Sopenharmony_ci } 520bf215546Sopenharmony_ci } 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci svga->rebind.flags.constbufs = FALSE; 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci return PIPE_OK; 525bf215546Sopenharmony_ci} 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci/** 529bf215546Sopenharmony_ci * A helper function to validate image view resources to ensure any 530bf215546Sopenharmony_ci * pending updates to buffers will be emitted before they are referenced 531bf215546Sopenharmony_ci * at draw or dispatch time. It also rebinds the resources if needed. 532bf215546Sopenharmony_ci */ 533bf215546Sopenharmony_cienum pipe_error 534bf215546Sopenharmony_cisvga_validate_image_views(struct svga_context *svga, 535bf215546Sopenharmony_ci enum svga_pipe_type pipe_type) 536bf215546Sopenharmony_ci{ 537bf215546Sopenharmony_ci enum pipe_shader_type shader, first_shader, last_shader; 538bf215546Sopenharmony_ci bool rebind = svga->rebind.flags.images; 539bf215546Sopenharmony_ci enum pipe_error ret; 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci if (pipe_type == SVGA_PIPE_GRAPHICS) { 544bf215546Sopenharmony_ci first_shader = PIPE_SHADER_VERTEX; 545bf215546Sopenharmony_ci last_shader = PIPE_SHADER_TESS_EVAL; 546bf215546Sopenharmony_ci } 547bf215546Sopenharmony_ci else { 548bf215546Sopenharmony_ci first_shader = PIPE_SHADER_COMPUTE; 549bf215546Sopenharmony_ci last_shader = PIPE_SHADER_COMPUTE; 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci for (shader = first_shader; shader <= last_shader; shader++) { 553bf215546Sopenharmony_ci ret = svga_validate_image_view_resources(svga, 554bf215546Sopenharmony_ci svga->state.hw_draw.num_image_views[shader], 555bf215546Sopenharmony_ci &svga->state.hw_draw.image_views[shader][0], rebind); 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci if (ret != PIPE_OK) 558bf215546Sopenharmony_ci return ret; 559bf215546Sopenharmony_ci } 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci svga->rebind.flags.images = FALSE; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci return PIPE_OK; 564bf215546Sopenharmony_ci} 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci/** 568bf215546Sopenharmony_ci * A helper function to validate shader buffer and atomic buffer resources to 569bf215546Sopenharmony_ci * ensure any pending updates to buffers will be emitted before they are 570bf215546Sopenharmony_ci * referenced at draw or dispatch time. It also rebinds the resources if needed. 571bf215546Sopenharmony_ci */ 572bf215546Sopenharmony_cienum pipe_error 573bf215546Sopenharmony_cisvga_validate_shader_buffers(struct svga_context *svga, 574bf215546Sopenharmony_ci enum svga_pipe_type pipe_type) 575bf215546Sopenharmony_ci{ 576bf215546Sopenharmony_ci enum pipe_shader_type shader, first_shader, last_shader; 577bf215546Sopenharmony_ci bool rebind = svga->rebind.flags.shaderbufs; 578bf215546Sopenharmony_ci enum pipe_error ret; 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_ci assert(svga_have_gl43(svga)); 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ci if (pipe_type == SVGA_PIPE_GRAPHICS) { 583bf215546Sopenharmony_ci first_shader = PIPE_SHADER_VERTEX; 584bf215546Sopenharmony_ci last_shader = PIPE_SHADER_TESS_EVAL; 585bf215546Sopenharmony_ci } 586bf215546Sopenharmony_ci else { 587bf215546Sopenharmony_ci first_shader = PIPE_SHADER_COMPUTE; 588bf215546Sopenharmony_ci last_shader = PIPE_SHADER_COMPUTE; 589bf215546Sopenharmony_ci } 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci for (shader = first_shader; shader <= last_shader; shader++) { 592bf215546Sopenharmony_ci ret = svga_validate_shader_buffer_resources(svga, 593bf215546Sopenharmony_ci svga->state.hw_draw.num_shader_buffers[shader], 594bf215546Sopenharmony_ci &svga->state.hw_draw.shader_buffers[shader][0], rebind); 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_ci if (ret != PIPE_OK) 597bf215546Sopenharmony_ci return ret; 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci svga->rebind.flags.shaderbufs = FALSE; 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci ret = svga_validate_shader_buffer_resources(svga, 603bf215546Sopenharmony_ci svga->state.hw_draw.num_atomic_buffers, 604bf215546Sopenharmony_ci svga->state.hw_draw.atomic_buffers, 605bf215546Sopenharmony_ci svga->rebind.flags.atomicbufs); 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci if (ret != PIPE_OK) 608bf215546Sopenharmony_ci return ret; 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ci svga->rebind.flags.atomicbufs = FALSE; 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci return PIPE_OK; 613bf215546Sopenharmony_ci} 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci/** 617bf215546Sopenharmony_ci * Was the last command put into the command buffer a drawing command? 618bf215546Sopenharmony_ci * We use this to determine if we can skip emitting buffer re-bind 619bf215546Sopenharmony_ci * commands when we have a sequence of drawing commands that use the 620bf215546Sopenharmony_ci * same vertex/index buffers with no intervening commands. 621bf215546Sopenharmony_ci * 622bf215546Sopenharmony_ci * The first drawing command will bind the vertex/index buffers. If 623bf215546Sopenharmony_ci * the immediately following command is also a drawing command using the 624bf215546Sopenharmony_ci * same buffers, we shouldn't have to rebind them. 625bf215546Sopenharmony_ci */ 626bf215546Sopenharmony_cistatic bool 627bf215546Sopenharmony_cilast_command_was_draw(const struct svga_context *svga) 628bf215546Sopenharmony_ci{ 629bf215546Sopenharmony_ci switch (SVGA3D_GetLastCommand(svga->swc)) { 630bf215546Sopenharmony_ci case SVGA_3D_CMD_DX_DRAW: 631bf215546Sopenharmony_ci case SVGA_3D_CMD_DX_DRAW_INDEXED: 632bf215546Sopenharmony_ci case SVGA_3D_CMD_DX_DRAW_INSTANCED: 633bf215546Sopenharmony_ci case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED: 634bf215546Sopenharmony_ci case SVGA_3D_CMD_DX_DRAW_AUTO: 635bf215546Sopenharmony_ci case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT: 636bf215546Sopenharmony_ci case SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT: 637bf215546Sopenharmony_ci return true; 638bf215546Sopenharmony_ci default: 639bf215546Sopenharmony_ci return false; 640bf215546Sopenharmony_ci } 641bf215546Sopenharmony_ci} 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ci/** 645bf215546Sopenharmony_ci * A helper function to compare vertex buffers. 646bf215546Sopenharmony_ci * They are equal if the vertex buffer attributes and the vertex buffer 647bf215546Sopenharmony_ci * resources are identical. 648bf215546Sopenharmony_ci */ 649bf215546Sopenharmony_cistatic boolean 650bf215546Sopenharmony_civertex_buffers_equal(unsigned count, 651bf215546Sopenharmony_ci SVGA3dVertexBuffer_v2 *pVBufAttr1, 652bf215546Sopenharmony_ci struct pipe_resource **pVBuf1, 653bf215546Sopenharmony_ci SVGA3dVertexBuffer_v2 *pVBufAttr2, 654bf215546Sopenharmony_ci struct pipe_resource **pVBuf2) 655bf215546Sopenharmony_ci{ 656bf215546Sopenharmony_ci return (memcmp(pVBufAttr1, pVBufAttr2, 657bf215546Sopenharmony_ci count * sizeof(*pVBufAttr1)) == 0) && 658bf215546Sopenharmony_ci (memcmp(pVBuf1, pVBuf2, count * sizeof(*pVBuf1)) == 0); 659bf215546Sopenharmony_ci} 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci/* 663bf215546Sopenharmony_ci * Prepare the vertex buffers for a drawing command. 664bf215546Sopenharmony_ci */ 665bf215546Sopenharmony_cistatic enum pipe_error 666bf215546Sopenharmony_civalidate_vertex_buffers(struct svga_hwtnl *hwtnl, 667bf215546Sopenharmony_ci const struct pipe_stream_output_target *so_vertex_count) 668bf215546Sopenharmony_ci{ 669bf215546Sopenharmony_ci struct svga_context *svga = hwtnl->svga; 670bf215546Sopenharmony_ci struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX]; 671bf215546Sopenharmony_ci struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX]; 672bf215546Sopenharmony_ci struct svga_winsys_surface *so_vertex_count_handle = NULL; 673bf215546Sopenharmony_ci const unsigned vbuf_count = so_vertex_count ? 1 : hwtnl->cmd.vbuf_count; 674bf215546Sopenharmony_ci SVGA3dVertexBuffer_v2 vbuffer_attrs[PIPE_MAX_ATTRIBS]; 675bf215546Sopenharmony_ci int last_vbuf = -1; 676bf215546Sopenharmony_ci unsigned i; 677bf215546Sopenharmony_ci 678bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci /* setup vertex attribute input layout */ 681bf215546Sopenharmony_ci if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) { 682bf215546Sopenharmony_ci enum pipe_error ret = 683bf215546Sopenharmony_ci SVGA3D_vgpu10_SetInputLayout(svga->swc, 684bf215546Sopenharmony_ci hwtnl->cmd.vdecl_layout_id); 685bf215546Sopenharmony_ci if (ret != PIPE_OK) 686bf215546Sopenharmony_ci return ret; 687bf215546Sopenharmony_ci 688bf215546Sopenharmony_ci svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id; 689bf215546Sopenharmony_ci } 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci /* Get handle for each referenced vertex buffer, unless we're using a 692bf215546Sopenharmony_ci * stream-out buffer to specify the drawing information (DrawAuto). 693bf215546Sopenharmony_ci * Also set up the buffer attributes. 694bf215546Sopenharmony_ci */ 695bf215546Sopenharmony_ci if (so_vertex_count) { 696bf215546Sopenharmony_ci so_vertex_count_handle = svga_buffer_handle(svga, 697bf215546Sopenharmony_ci so_vertex_count->buffer, 698bf215546Sopenharmony_ci (PIPE_BIND_VERTEX_BUFFER | 699bf215546Sopenharmony_ci PIPE_BIND_STREAM_OUTPUT)); 700bf215546Sopenharmony_ci if (!so_vertex_count_handle) 701bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci /* Set IA slot0 input buffer to the SO buffer */ 704bf215546Sopenharmony_ci assert(vbuf_count == 1); 705bf215546Sopenharmony_ci vbuffer_attrs[0].stride = hwtnl->cmd.vbufs[0].stride; 706bf215546Sopenharmony_ci vbuffer_attrs[0].offset = hwtnl->cmd.vbufs[0].buffer_offset; 707bf215546Sopenharmony_ci vbuffer_attrs[0].sid = 0; 708bf215546Sopenharmony_ci assert(so_vertex_count->buffer != NULL); 709bf215546Sopenharmony_ci vbuffer_attrs[0].sizeInBytes = svga_buffer(so_vertex_count->buffer)->size; 710bf215546Sopenharmony_ci vbuffers[0] = so_vertex_count->buffer; 711bf215546Sopenharmony_ci vbuffer_handles[0] = so_vertex_count_handle; 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci i = 1; 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci else { 716bf215546Sopenharmony_ci for (i = 0; i < vbuf_count; i++) { 717bf215546Sopenharmony_ci struct svga_buffer *sbuf = 718bf215546Sopenharmony_ci svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource); 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride; 721bf215546Sopenharmony_ci vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset; 722bf215546Sopenharmony_ci vbuffer_attrs[i].sid = 0; 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci if (sbuf) { 725bf215546Sopenharmony_ci vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b, 726bf215546Sopenharmony_ci PIPE_BIND_VERTEX_BUFFER); 727bf215546Sopenharmony_ci assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER); 728bf215546Sopenharmony_ci if (vbuffer_handles[i] == NULL) 729bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 730bf215546Sopenharmony_ci vbuffers[i] = &sbuf->b; 731bf215546Sopenharmony_ci last_vbuf = i; 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_ci vbuffer_attrs[i].sizeInBytes = sbuf->size; 734bf215546Sopenharmony_ci } 735bf215546Sopenharmony_ci else { 736bf215546Sopenharmony_ci vbuffers[i] = NULL; 737bf215546Sopenharmony_ci vbuffer_handles[i] = NULL; 738bf215546Sopenharmony_ci vbuffer_attrs[i].sizeInBytes = 0; 739bf215546Sopenharmony_ci } 740bf215546Sopenharmony_ci } 741bf215546Sopenharmony_ci } 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci /* Unbind the unreferenced the vertex buffer handles */ 744bf215546Sopenharmony_ci for (; i < svga->state.hw_draw.num_vbuffers; i++) { 745bf215546Sopenharmony_ci vbuffers[i] = NULL; 746bf215546Sopenharmony_ci vbuffer_handles[i] = NULL; 747bf215546Sopenharmony_ci vbuffer_attrs[i].sid = 0; 748bf215546Sopenharmony_ci vbuffer_attrs[i].stride = 0; 749bf215546Sopenharmony_ci vbuffer_attrs[i].offset = 0; 750bf215546Sopenharmony_ci vbuffer_attrs[i].sizeInBytes = 0; 751bf215546Sopenharmony_ci } 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_ci /* Get handle for each referenced vertex buffer */ 754bf215546Sopenharmony_ci for (i = 0; i < vbuf_count; i++) { 755bf215546Sopenharmony_ci struct svga_buffer *sbuf = 756bf215546Sopenharmony_ci svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource); 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci if (sbuf) { 759bf215546Sopenharmony_ci vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b, 760bf215546Sopenharmony_ci PIPE_BIND_VERTEX_BUFFER); 761bf215546Sopenharmony_ci assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER); 762bf215546Sopenharmony_ci if (vbuffer_handles[i] == NULL) 763bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 764bf215546Sopenharmony_ci vbuffers[i] = &sbuf->b; 765bf215546Sopenharmony_ci last_vbuf = i; 766bf215546Sopenharmony_ci } 767bf215546Sopenharmony_ci else { 768bf215546Sopenharmony_ci vbuffers[i] = NULL; 769bf215546Sopenharmony_ci vbuffer_handles[i] = NULL; 770bf215546Sopenharmony_ci } 771bf215546Sopenharmony_ci } 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_ci for (; i < svga->state.hw_draw.num_vbuffers; i++) { 774bf215546Sopenharmony_ci vbuffers[i] = NULL; 775bf215546Sopenharmony_ci vbuffer_handles[i] = NULL; 776bf215546Sopenharmony_ci } 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_ci /* setup vertex attribute input layout */ 779bf215546Sopenharmony_ci if (svga->state.hw_draw.layout_id != hwtnl->cmd.vdecl_layout_id) { 780bf215546Sopenharmony_ci enum pipe_error ret = 781bf215546Sopenharmony_ci SVGA3D_vgpu10_SetInputLayout(svga->swc, 782bf215546Sopenharmony_ci hwtnl->cmd.vdecl_layout_id); 783bf215546Sopenharmony_ci if (ret != PIPE_OK) 784bf215546Sopenharmony_ci return ret; 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id; 787bf215546Sopenharmony_ci } 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ci /* Get handle for the stream out buffer */ 790bf215546Sopenharmony_ci if (so_vertex_count) { 791bf215546Sopenharmony_ci so_vertex_count_handle = svga_buffer_handle(svga, 792bf215546Sopenharmony_ci so_vertex_count->buffer, 793bf215546Sopenharmony_ci (PIPE_BIND_VERTEX_BUFFER | 794bf215546Sopenharmony_ci PIPE_BIND_STREAM_OUTPUT)); 795bf215546Sopenharmony_ci if (!so_vertex_count_handle) 796bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 797bf215546Sopenharmony_ci } 798bf215546Sopenharmony_ci else { 799bf215546Sopenharmony_ci so_vertex_count_handle = NULL; 800bf215546Sopenharmony_ci } 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci /* setup vertex buffers */ 803bf215546Sopenharmony_ci { 804bf215546Sopenharmony_ci /* If any of the vertex buffer state has changed, issue 805bf215546Sopenharmony_ci * the SetVertexBuffers command. Otherwise, we will just 806bf215546Sopenharmony_ci * need to rebind the resources. 807bf215546Sopenharmony_ci */ 808bf215546Sopenharmony_ci if (vbuf_count != svga->state.hw_draw.num_vbuffers || 809bf215546Sopenharmony_ci !vertex_buffers_equal(vbuf_count, 810bf215546Sopenharmony_ci vbuffer_attrs, 811bf215546Sopenharmony_ci vbuffers, 812bf215546Sopenharmony_ci svga->state.hw_draw.vbuffer_attrs, 813bf215546Sopenharmony_ci svga->state.hw_draw.vbuffers)) { 814bf215546Sopenharmony_ci 815bf215546Sopenharmony_ci unsigned num_vbuffers; 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci /* get the max of the current bound vertex buffers count and 818bf215546Sopenharmony_ci * the to-be-bound vertex buffers count, so as to unbind 819bf215546Sopenharmony_ci * the unused vertex buffers. 820bf215546Sopenharmony_ci */ 821bf215546Sopenharmony_ci num_vbuffers = MAX2(vbuf_count, svga->state.hw_draw.num_vbuffers); 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci if (num_vbuffers > 0) { 824bf215546Sopenharmony_ci SVGA3dVertexBuffer_v2 *pbufAttrs = vbuffer_attrs; 825bf215546Sopenharmony_ci struct svga_winsys_surface **pbufHandles = vbuffer_handles; 826bf215546Sopenharmony_ci unsigned numVBuf = 0; 827bf215546Sopenharmony_ci boolean emitVBufs = 828bf215546Sopenharmony_ci !svga_sws(svga)->have_index_vertex_buffer_offset_cmd || 829bf215546Sopenharmony_ci svga->rebind.flags.vertexbufs; 830bf215546Sopenharmony_ci 831bf215546Sopenharmony_ci /* Loop through the vertex buffer lists to only emit 832bf215546Sopenharmony_ci * those vertex buffers that are not already in the 833bf215546Sopenharmony_ci * corresponding entries in the device's vertex buffer list. 834bf215546Sopenharmony_ci */ 835bf215546Sopenharmony_ci for (i = 0; i < num_vbuffers; i++) { 836bf215546Sopenharmony_ci boolean emit = 837bf215546Sopenharmony_ci vertex_buffers_equal(1, 838bf215546Sopenharmony_ci &vbuffer_attrs[i], 839bf215546Sopenharmony_ci &vbuffers[i], 840bf215546Sopenharmony_ci &svga->state.hw_draw.vbuffer_attrs[i], 841bf215546Sopenharmony_ci &svga->state.hw_draw.vbuffers[i]); 842bf215546Sopenharmony_ci 843bf215546Sopenharmony_ci /* Check if we can use the SetVertexBuffersOffsetAndSize command */ 844bf215546Sopenharmony_ci emitVBufs = emitVBufs || 845bf215546Sopenharmony_ci (vbuffers[i] != svga->state.hw_draw.vbuffers[i]); 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ci if (!emit && i == num_vbuffers-1) { 848bf215546Sopenharmony_ci /* Include the last vertex buffer in the next emit 849bf215546Sopenharmony_ci * if it is different. 850bf215546Sopenharmony_ci */ 851bf215546Sopenharmony_ci emit = TRUE; 852bf215546Sopenharmony_ci numVBuf++; 853bf215546Sopenharmony_ci i++; 854bf215546Sopenharmony_ci } 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci if (emit) { 857bf215546Sopenharmony_ci /* numVBuf can only be 0 if the first vertex buffer 858bf215546Sopenharmony_ci * is the same as the one in the device's list. 859bf215546Sopenharmony_ci * In this case, there is nothing to send yet. 860bf215546Sopenharmony_ci */ 861bf215546Sopenharmony_ci if (numVBuf) { 862bf215546Sopenharmony_ci enum pipe_error ret; 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_ci /* If all vertex buffers handle are the same as the one 865bf215546Sopenharmony_ci * in the device, just use the 866bf215546Sopenharmony_ci * SetVertexBuffersOffsetAndSize comand. 867bf215546Sopenharmony_ci */ 868bf215546Sopenharmony_ci if (emitVBufs) { 869bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetVertexBuffers(svga->swc, 870bf215546Sopenharmony_ci numVBuf, 871bf215546Sopenharmony_ci i - numVBuf, 872bf215546Sopenharmony_ci pbufAttrs, pbufHandles); 873bf215546Sopenharmony_ci } else { 874bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetVertexBuffersOffsetAndSize(svga->swc, 875bf215546Sopenharmony_ci numVBuf, 876bf215546Sopenharmony_ci i - numVBuf, 877bf215546Sopenharmony_ci pbufAttrs); 878bf215546Sopenharmony_ci } 879bf215546Sopenharmony_ci if (ret != PIPE_OK) 880bf215546Sopenharmony_ci return ret; 881bf215546Sopenharmony_ci } 882bf215546Sopenharmony_ci pbufAttrs += (numVBuf + 1); 883bf215546Sopenharmony_ci pbufHandles += (numVBuf + 1); 884bf215546Sopenharmony_ci numVBuf = 0; 885bf215546Sopenharmony_ci } 886bf215546Sopenharmony_ci else 887bf215546Sopenharmony_ci numVBuf++; 888bf215546Sopenharmony_ci } 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci /* save the number of vertex buffers sent to the device, not 891bf215546Sopenharmony_ci * including trailing unbound vertex buffers. 892bf215546Sopenharmony_ci */ 893bf215546Sopenharmony_ci svga->state.hw_draw.num_vbuffers = last_vbuf + 1; 894bf215546Sopenharmony_ci memcpy(svga->state.hw_draw.vbuffer_attrs, vbuffer_attrs, 895bf215546Sopenharmony_ci num_vbuffers * sizeof(vbuffer_attrs[0])); 896bf215546Sopenharmony_ci for (i = 0; i < num_vbuffers; i++) { 897bf215546Sopenharmony_ci pipe_resource_reference(&svga->state.hw_draw.vbuffers[i], 898bf215546Sopenharmony_ci vbuffers[i]); 899bf215546Sopenharmony_ci } 900bf215546Sopenharmony_ci } 901bf215546Sopenharmony_ci } 902bf215546Sopenharmony_ci else { 903bf215546Sopenharmony_ci /* Even though we can avoid emitting the redundant SetVertexBuffers 904bf215546Sopenharmony_ci * command, we still need to reference the vertex buffers surfaces. 905bf215546Sopenharmony_ci */ 906bf215546Sopenharmony_ci for (i = 0; i < vbuf_count; i++) { 907bf215546Sopenharmony_ci if (vbuffer_handles[i] && !last_command_was_draw(svga)) { 908bf215546Sopenharmony_ci enum pipe_error ret = 909bf215546Sopenharmony_ci svga->swc->resource_rebind(svga->swc, vbuffer_handles[i], 910bf215546Sopenharmony_ci NULL, SVGA_RELOC_READ); 911bf215546Sopenharmony_ci if (ret != PIPE_OK) 912bf215546Sopenharmony_ci return ret; 913bf215546Sopenharmony_ci } 914bf215546Sopenharmony_ci } 915bf215546Sopenharmony_ci } 916bf215546Sopenharmony_ci } 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci svga->rebind.flags.vertexbufs = FALSE; 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci return PIPE_OK; 921bf215546Sopenharmony_ci} 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_ci 924bf215546Sopenharmony_ci/* 925bf215546Sopenharmony_ci * Prepare the index buffer for a drawing command. 926bf215546Sopenharmony_ci */ 927bf215546Sopenharmony_cistatic enum pipe_error 928bf215546Sopenharmony_civalidate_index_buffer(struct svga_hwtnl *hwtnl, 929bf215546Sopenharmony_ci const SVGA3dPrimitiveRange *range, 930bf215546Sopenharmony_ci struct pipe_resource *ib) 931bf215546Sopenharmony_ci{ 932bf215546Sopenharmony_ci struct svga_context *svga = hwtnl->svga; 933bf215546Sopenharmony_ci struct svga_winsys_surface *ib_handle = 934bf215546Sopenharmony_ci svga_buffer_handle(svga, ib, PIPE_BIND_INDEX_BUFFER); 935bf215546Sopenharmony_ci enum pipe_error ret; 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci if (!ib_handle) 938bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 939bf215546Sopenharmony_ci 940bf215546Sopenharmony_ci struct svga_buffer *sbuf = svga_buffer(ib); 941bf215546Sopenharmony_ci assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_INDEX_BUFFER); 942bf215546Sopenharmony_ci (void) sbuf; /* silence unused var warning */ 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci SVGA3dSurfaceFormat indexFormat = xlate_index_format(range->indexWidth); 945bf215546Sopenharmony_ci 946bf215546Sopenharmony_ci if (ib != svga->state.hw_draw.ib || 947bf215546Sopenharmony_ci indexFormat != svga->state.hw_draw.ib_format || 948bf215546Sopenharmony_ci range->indexArray.offset != svga->state.hw_draw.ib_offset) { 949bf215546Sopenharmony_ci 950bf215546Sopenharmony_ci assert(indexFormat != SVGA3D_FORMAT_INVALID); 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci if ((ib == svga->state.hw_draw.ib) && 953bf215546Sopenharmony_ci svga_sws(hwtnl->svga)->have_index_vertex_buffer_offset_cmd && 954bf215546Sopenharmony_ci !svga->rebind.flags.indexbuf) { 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetIndexBufferOffsetAndSize(svga->swc, 957bf215546Sopenharmony_ci indexFormat, 958bf215546Sopenharmony_ci range->indexArray.offset, 959bf215546Sopenharmony_ci sbuf->size); 960bf215546Sopenharmony_ci if (ret != PIPE_OK) 961bf215546Sopenharmony_ci return ret; 962bf215546Sopenharmony_ci } 963bf215546Sopenharmony_ci else { 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, ib_handle, 966bf215546Sopenharmony_ci indexFormat, 967bf215546Sopenharmony_ci range->indexArray.offset); 968bf215546Sopenharmony_ci if (ret != PIPE_OK) 969bf215546Sopenharmony_ci return ret; 970bf215546Sopenharmony_ci } 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_ci pipe_resource_reference(&svga->state.hw_draw.ib, ib); 973bf215546Sopenharmony_ci svga->state.hw_draw.ib_format = indexFormat; 974bf215546Sopenharmony_ci svga->state.hw_draw.ib_offset = range->indexArray.offset; 975bf215546Sopenharmony_ci } 976bf215546Sopenharmony_ci else { 977bf215546Sopenharmony_ci /* Even though we can avoid emitting the redundant SetIndexBuffer 978bf215546Sopenharmony_ci * command, we still need to reference the index buffer surface. 979bf215546Sopenharmony_ci */ 980bf215546Sopenharmony_ci if (!last_command_was_draw(svga)) { 981bf215546Sopenharmony_ci enum pipe_error ret = svga->swc->resource_rebind(svga->swc, 982bf215546Sopenharmony_ci ib_handle, 983bf215546Sopenharmony_ci NULL, 984bf215546Sopenharmony_ci SVGA_RELOC_READ); 985bf215546Sopenharmony_ci if (ret != PIPE_OK) 986bf215546Sopenharmony_ci return ret; 987bf215546Sopenharmony_ci } 988bf215546Sopenharmony_ci } 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci svga->rebind.flags.indexbuf = FALSE; 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci return PIPE_OK; 993bf215546Sopenharmony_ci} 994bf215546Sopenharmony_ci 995bf215546Sopenharmony_ci 996bf215546Sopenharmony_cistatic enum pipe_error 997bf215546Sopenharmony_cidraw_vgpu10(struct svga_hwtnl *hwtnl, 998bf215546Sopenharmony_ci const SVGA3dPrimitiveRange *range, 999bf215546Sopenharmony_ci unsigned vcount, 1000bf215546Sopenharmony_ci unsigned min_index, unsigned max_index, 1001bf215546Sopenharmony_ci struct pipe_resource *ib, 1002bf215546Sopenharmony_ci unsigned start_instance, unsigned instance_count, 1003bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 1004bf215546Sopenharmony_ci const struct pipe_stream_output_target *so_vertex_count) 1005bf215546Sopenharmony_ci{ 1006bf215546Sopenharmony_ci struct svga_context *svga = hwtnl->svga; 1007bf215546Sopenharmony_ci struct svga_winsys_surface *indirect_handle; 1008bf215546Sopenharmony_ci enum pipe_error ret; 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 1011bf215546Sopenharmony_ci assert(hwtnl->cmd.prim_count == 0); 1012bf215546Sopenharmony_ci 1013bf215546Sopenharmony_ci /* We need to reemit all the current resource bindings along with the Draw 1014bf215546Sopenharmony_ci * command to be sure that the referenced resources are available for the 1015bf215546Sopenharmony_ci * Draw command, just in case the surfaces associated with the resources 1016bf215546Sopenharmony_ci * are paged out. 1017bf215546Sopenharmony_ci */ 1018bf215546Sopenharmony_ci if (svga->rebind.val) { 1019bf215546Sopenharmony_ci ret = svga_rebind_framebuffer_bindings(svga); 1020bf215546Sopenharmony_ci if (ret != PIPE_OK) 1021bf215546Sopenharmony_ci return ret; 1022bf215546Sopenharmony_ci 1023bf215546Sopenharmony_ci ret = svga_rebind_shaders(svga); 1024bf215546Sopenharmony_ci if (ret != PIPE_OK) 1025bf215546Sopenharmony_ci return ret; 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci /* Rebind stream output targets */ 1028bf215546Sopenharmony_ci ret = svga_rebind_stream_output_targets(svga); 1029bf215546Sopenharmony_ci if (ret != PIPE_OK) 1030bf215546Sopenharmony_ci return ret; 1031bf215546Sopenharmony_ci 1032bf215546Sopenharmony_ci /* No need to explicitly rebind index buffer and vertex buffers here. 1033bf215546Sopenharmony_ci * Even if the same index buffer or vertex buffers are referenced for this 1034bf215546Sopenharmony_ci * draw and we skip emitting the redundant set command, we will still 1035bf215546Sopenharmony_ci * reference the associated resources. 1036bf215546Sopenharmony_ci */ 1037bf215546Sopenharmony_ci } 1038bf215546Sopenharmony_ci 1039bf215546Sopenharmony_ci ret = svga_validate_sampler_resources(svga, SVGA_PIPE_GRAPHICS); 1040bf215546Sopenharmony_ci if (ret != PIPE_OK) 1041bf215546Sopenharmony_ci return ret; 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci ret = svga_validate_constant_buffers(svga, SVGA_PIPE_GRAPHICS); 1044bf215546Sopenharmony_ci if (ret != PIPE_OK) 1045bf215546Sopenharmony_ci return ret; 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci if (svga_have_gl43(svga)) { 1048bf215546Sopenharmony_ci ret = svga_validate_image_views(svga, SVGA_PIPE_GRAPHICS); 1049bf215546Sopenharmony_ci if (ret != PIPE_OK) 1050bf215546Sopenharmony_ci return ret; 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci ret = svga_validate_shader_buffers(svga, SVGA_PIPE_GRAPHICS); 1053bf215546Sopenharmony_ci if (ret != PIPE_OK) 1054bf215546Sopenharmony_ci return ret; 1055bf215546Sopenharmony_ci 1056bf215546Sopenharmony_ci if (svga->rebind.flags.uav) { 1057bf215546Sopenharmony_ci ret= svga_rebind_uav(svga); 1058bf215546Sopenharmony_ci if (ret != PIPE_OK) 1059bf215546Sopenharmony_ci return ret; 1060bf215546Sopenharmony_ci } 1061bf215546Sopenharmony_ci } 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci ret = validate_vertex_buffers(hwtnl, so_vertex_count); 1064bf215546Sopenharmony_ci if (ret != PIPE_OK) 1065bf215546Sopenharmony_ci return ret; 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_ci if (ib) { 1068bf215546Sopenharmony_ci ret = validate_index_buffer(hwtnl, range, ib); 1069bf215546Sopenharmony_ci if (ret != PIPE_OK) 1070bf215546Sopenharmony_ci return ret; 1071bf215546Sopenharmony_ci } 1072bf215546Sopenharmony_ci 1073bf215546Sopenharmony_ci if (indirect) { 1074bf215546Sopenharmony_ci indirect_handle = svga_buffer_handle(svga, indirect->buffer, 1075bf215546Sopenharmony_ci PIPE_BIND_COMMAND_ARGS_BUFFER); 1076bf215546Sopenharmony_ci if (!indirect_handle) 1077bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 1078bf215546Sopenharmony_ci } 1079bf215546Sopenharmony_ci else { 1080bf215546Sopenharmony_ci indirect_handle = NULL; 1081bf215546Sopenharmony_ci } 1082bf215546Sopenharmony_ci 1083bf215546Sopenharmony_ci /* Set primitive type (line, tri, etc) */ 1084bf215546Sopenharmony_ci if (svga->state.hw_draw.topology != range->primType) { 1085bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType); 1086bf215546Sopenharmony_ci if (ret != PIPE_OK) 1087bf215546Sopenharmony_ci return ret; 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci svga->state.hw_draw.topology = range->primType; 1090bf215546Sopenharmony_ci } 1091bf215546Sopenharmony_ci 1092bf215546Sopenharmony_ci if (ib) { 1093bf215546Sopenharmony_ci /* indexed drawing */ 1094bf215546Sopenharmony_ci if (indirect) { 1095bf215546Sopenharmony_ci ret = SVGA3D_sm5_DrawIndexedInstancedIndirect(svga->swc, 1096bf215546Sopenharmony_ci indirect_handle, 1097bf215546Sopenharmony_ci indirect->offset); 1098bf215546Sopenharmony_ci } 1099bf215546Sopenharmony_ci else if (instance_count > 1) { 1100bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc, 1101bf215546Sopenharmony_ci vcount, 1102bf215546Sopenharmony_ci instance_count, 1103bf215546Sopenharmony_ci 0, /* startIndexLocation */ 1104bf215546Sopenharmony_ci range->indexBias, 1105bf215546Sopenharmony_ci start_instance); 1106bf215546Sopenharmony_ci } 1107bf215546Sopenharmony_ci else { 1108bf215546Sopenharmony_ci /* non-instanced drawing */ 1109bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_DrawIndexed(svga->swc, 1110bf215546Sopenharmony_ci vcount, 1111bf215546Sopenharmony_ci 0, /* startIndexLocation */ 1112bf215546Sopenharmony_ci range->indexBias); 1113bf215546Sopenharmony_ci } 1114bf215546Sopenharmony_ci if (ret != PIPE_OK) { 1115bf215546Sopenharmony_ci return ret; 1116bf215546Sopenharmony_ci } 1117bf215546Sopenharmony_ci } 1118bf215546Sopenharmony_ci else { 1119bf215546Sopenharmony_ci /* non-indexed drawing */ 1120bf215546Sopenharmony_ci if (svga->state.hw_draw.ib_format != SVGA3D_FORMAT_INVALID || 1121bf215546Sopenharmony_ci svga->state.hw_draw.ib != NULL) { 1122bf215546Sopenharmony_ci /* Unbind previously bound index buffer */ 1123bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetIndexBuffer(svga->swc, NULL, 1124bf215546Sopenharmony_ci SVGA3D_FORMAT_INVALID, 0); 1125bf215546Sopenharmony_ci if (ret != PIPE_OK) 1126bf215546Sopenharmony_ci return ret; 1127bf215546Sopenharmony_ci pipe_resource_reference(&svga->state.hw_draw.ib, NULL); 1128bf215546Sopenharmony_ci svga->state.hw_draw.ib_format = SVGA3D_FORMAT_INVALID; 1129bf215546Sopenharmony_ci } 1130bf215546Sopenharmony_ci 1131bf215546Sopenharmony_ci assert(svga->state.hw_draw.ib == NULL); 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci if (so_vertex_count) { 1134bf215546Sopenharmony_ci /* Stream-output drawing */ 1135bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_DrawAuto(svga->swc); 1136bf215546Sopenharmony_ci } 1137bf215546Sopenharmony_ci else if (indirect) { 1138bf215546Sopenharmony_ci ret = SVGA3D_sm5_DrawInstancedIndirect(svga->swc, 1139bf215546Sopenharmony_ci indirect_handle, 1140bf215546Sopenharmony_ci indirect->offset); 1141bf215546Sopenharmony_ci } 1142bf215546Sopenharmony_ci else if (instance_count > 1) { 1143bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_DrawInstanced(svga->swc, 1144bf215546Sopenharmony_ci vcount, 1145bf215546Sopenharmony_ci instance_count, 1146bf215546Sopenharmony_ci range->indexBias, 1147bf215546Sopenharmony_ci start_instance); 1148bf215546Sopenharmony_ci } 1149bf215546Sopenharmony_ci else { 1150bf215546Sopenharmony_ci /* non-instanced */ 1151bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_Draw(svga->swc, 1152bf215546Sopenharmony_ci vcount, 1153bf215546Sopenharmony_ci range->indexBias); 1154bf215546Sopenharmony_ci } 1155bf215546Sopenharmony_ci if (ret != PIPE_OK) { 1156bf215546Sopenharmony_ci return ret; 1157bf215546Sopenharmony_ci } 1158bf215546Sopenharmony_ci } 1159bf215546Sopenharmony_ci 1160bf215546Sopenharmony_ci hwtnl->cmd.prim_count = 0; 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_ci return PIPE_OK; 1163bf215546Sopenharmony_ci} 1164bf215546Sopenharmony_ci 1165bf215546Sopenharmony_ci 1166bf215546Sopenharmony_ci 1167bf215546Sopenharmony_ci/** 1168bf215546Sopenharmony_ci * Emit any pending drawing commands to the command buffer. 1169bf215546Sopenharmony_ci * When we receive VGPU9 drawing commands we accumulate them and don't 1170bf215546Sopenharmony_ci * immediately emit them into the command buffer. 1171bf215546Sopenharmony_ci * This function needs to be called before we change state that could 1172bf215546Sopenharmony_ci * effect those pending draws. 1173bf215546Sopenharmony_ci */ 1174bf215546Sopenharmony_cienum pipe_error 1175bf215546Sopenharmony_cisvga_hwtnl_flush(struct svga_hwtnl *hwtnl) 1176bf215546Sopenharmony_ci{ 1177bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLFLUSH); 1180bf215546Sopenharmony_ci 1181bf215546Sopenharmony_ci if (!svga_have_vgpu10(hwtnl->svga) && hwtnl->cmd.prim_count) { 1182bf215546Sopenharmony_ci /* we only queue up primitive for VGPU9 */ 1183bf215546Sopenharmony_ci ret = draw_vgpu9(hwtnl); 1184bf215546Sopenharmony_ci } 1185bf215546Sopenharmony_ci 1186bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws); 1187bf215546Sopenharmony_ci return ret; 1188bf215546Sopenharmony_ci} 1189bf215546Sopenharmony_ci 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_civoid 1192bf215546Sopenharmony_cisvga_hwtnl_set_index_bias(struct svga_hwtnl *hwtnl, int index_bias) 1193bf215546Sopenharmony_ci{ 1194bf215546Sopenharmony_ci hwtnl->index_bias = index_bias; 1195bf215546Sopenharmony_ci} 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_ci 1198bf215546Sopenharmony_ci 1199bf215546Sopenharmony_ci/*********************************************************************** 1200bf215546Sopenharmony_ci * Internal functions: 1201bf215546Sopenharmony_ci */ 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_ci/** 1204bf215546Sopenharmony_ci * For debugging only. 1205bf215546Sopenharmony_ci */ 1206bf215546Sopenharmony_cistatic void 1207bf215546Sopenharmony_cicheck_draw_params(struct svga_hwtnl *hwtnl, 1208bf215546Sopenharmony_ci const SVGA3dPrimitiveRange *range, 1209bf215546Sopenharmony_ci unsigned min_index, unsigned max_index, 1210bf215546Sopenharmony_ci struct pipe_resource *ib) 1211bf215546Sopenharmony_ci{ 1212bf215546Sopenharmony_ci unsigned i; 1213bf215546Sopenharmony_ci 1214bf215546Sopenharmony_ci assert(!svga_have_vgpu10(hwtnl->svga)); 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_ci for (i = 0; i < hwtnl->cmd.vdecl_count; i++) { 1217bf215546Sopenharmony_ci unsigned j = hwtnl->cmd.vdecl_buffer_index[i]; 1218bf215546Sopenharmony_ci const struct pipe_vertex_buffer *vb = &hwtnl->cmd.vbufs[j]; 1219bf215546Sopenharmony_ci unsigned size = vb->buffer.resource ? vb->buffer.resource->width0 : 0; 1220bf215546Sopenharmony_ci unsigned offset = hwtnl->cmd.vdecl[i].array.offset; 1221bf215546Sopenharmony_ci unsigned stride = hwtnl->cmd.vdecl[i].array.stride; 1222bf215546Sopenharmony_ci int index_bias = (int) range->indexBias + hwtnl->index_bias; 1223bf215546Sopenharmony_ci unsigned width; 1224bf215546Sopenharmony_ci 1225bf215546Sopenharmony_ci if (size == 0) 1226bf215546Sopenharmony_ci continue; 1227bf215546Sopenharmony_ci 1228bf215546Sopenharmony_ci assert(vb); 1229bf215546Sopenharmony_ci assert(size); 1230bf215546Sopenharmony_ci assert(offset < size); 1231bf215546Sopenharmony_ci assert(min_index <= max_index); 1232bf215546Sopenharmony_ci (void) width; 1233bf215546Sopenharmony_ci (void) stride; 1234bf215546Sopenharmony_ci (void) offset; 1235bf215546Sopenharmony_ci (void) size; 1236bf215546Sopenharmony_ci 1237bf215546Sopenharmony_ci switch (hwtnl->cmd.vdecl[i].identity.type) { 1238bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_FLOAT1: 1239bf215546Sopenharmony_ci width = 4; 1240bf215546Sopenharmony_ci break; 1241bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_FLOAT2: 1242bf215546Sopenharmony_ci width = 4 * 2; 1243bf215546Sopenharmony_ci break; 1244bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_FLOAT3: 1245bf215546Sopenharmony_ci width = 4 * 3; 1246bf215546Sopenharmony_ci break; 1247bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_FLOAT4: 1248bf215546Sopenharmony_ci width = 4 * 4; 1249bf215546Sopenharmony_ci break; 1250bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_D3DCOLOR: 1251bf215546Sopenharmony_ci width = 4; 1252bf215546Sopenharmony_ci break; 1253bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_UBYTE4: 1254bf215546Sopenharmony_ci width = 1 * 4; 1255bf215546Sopenharmony_ci break; 1256bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_SHORT2: 1257bf215546Sopenharmony_ci width = 2 * 2; 1258bf215546Sopenharmony_ci break; 1259bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_SHORT4: 1260bf215546Sopenharmony_ci width = 2 * 4; 1261bf215546Sopenharmony_ci break; 1262bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_UBYTE4N: 1263bf215546Sopenharmony_ci width = 1 * 4; 1264bf215546Sopenharmony_ci break; 1265bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_SHORT2N: 1266bf215546Sopenharmony_ci width = 2 * 2; 1267bf215546Sopenharmony_ci break; 1268bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_SHORT4N: 1269bf215546Sopenharmony_ci width = 2 * 4; 1270bf215546Sopenharmony_ci break; 1271bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_USHORT2N: 1272bf215546Sopenharmony_ci width = 2 * 2; 1273bf215546Sopenharmony_ci break; 1274bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_USHORT4N: 1275bf215546Sopenharmony_ci width = 2 * 4; 1276bf215546Sopenharmony_ci break; 1277bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_UDEC3: 1278bf215546Sopenharmony_ci width = 4; 1279bf215546Sopenharmony_ci break; 1280bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_DEC3N: 1281bf215546Sopenharmony_ci width = 4; 1282bf215546Sopenharmony_ci break; 1283bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_FLOAT16_2: 1284bf215546Sopenharmony_ci width = 2 * 2; 1285bf215546Sopenharmony_ci break; 1286bf215546Sopenharmony_ci case SVGA3D_DECLTYPE_FLOAT16_4: 1287bf215546Sopenharmony_ci width = 2 * 4; 1288bf215546Sopenharmony_ci break; 1289bf215546Sopenharmony_ci default: 1290bf215546Sopenharmony_ci assert(0); 1291bf215546Sopenharmony_ci width = 0; 1292bf215546Sopenharmony_ci break; 1293bf215546Sopenharmony_ci } 1294bf215546Sopenharmony_ci 1295bf215546Sopenharmony_ci if (index_bias >= 0) { 1296bf215546Sopenharmony_ci assert(offset + index_bias * stride + width <= size); 1297bf215546Sopenharmony_ci } 1298bf215546Sopenharmony_ci 1299bf215546Sopenharmony_ci /* 1300bf215546Sopenharmony_ci * min_index/max_index are merely conservative guesses, so we can't 1301bf215546Sopenharmony_ci * make buffer overflow detection based on their values. 1302bf215546Sopenharmony_ci */ 1303bf215546Sopenharmony_ci } 1304bf215546Sopenharmony_ci 1305bf215546Sopenharmony_ci assert(range->indexWidth == range->indexArray.stride); 1306bf215546Sopenharmony_ci 1307bf215546Sopenharmony_ci if (ib) { 1308bf215546Sopenharmony_ci ASSERTED unsigned size = ib->width0; 1309bf215546Sopenharmony_ci ASSERTED unsigned offset = range->indexArray.offset; 1310bf215546Sopenharmony_ci ASSERTED unsigned stride = range->indexArray.stride; 1311bf215546Sopenharmony_ci ASSERTED unsigned count; 1312bf215546Sopenharmony_ci 1313bf215546Sopenharmony_ci assert(size); 1314bf215546Sopenharmony_ci assert(offset < size); 1315bf215546Sopenharmony_ci assert(stride); 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci switch (range->primType) { 1318bf215546Sopenharmony_ci case SVGA3D_PRIMITIVE_POINTLIST: 1319bf215546Sopenharmony_ci count = range->primitiveCount; 1320bf215546Sopenharmony_ci break; 1321bf215546Sopenharmony_ci case SVGA3D_PRIMITIVE_LINELIST: 1322bf215546Sopenharmony_ci count = range->primitiveCount * 2; 1323bf215546Sopenharmony_ci break; 1324bf215546Sopenharmony_ci case SVGA3D_PRIMITIVE_LINESTRIP: 1325bf215546Sopenharmony_ci count = range->primitiveCount + 1; 1326bf215546Sopenharmony_ci break; 1327bf215546Sopenharmony_ci case SVGA3D_PRIMITIVE_TRIANGLELIST: 1328bf215546Sopenharmony_ci count = range->primitiveCount * 3; 1329bf215546Sopenharmony_ci break; 1330bf215546Sopenharmony_ci case SVGA3D_PRIMITIVE_TRIANGLESTRIP: 1331bf215546Sopenharmony_ci count = range->primitiveCount + 2; 1332bf215546Sopenharmony_ci break; 1333bf215546Sopenharmony_ci case SVGA3D_PRIMITIVE_TRIANGLEFAN: 1334bf215546Sopenharmony_ci count = range->primitiveCount + 2; 1335bf215546Sopenharmony_ci break; 1336bf215546Sopenharmony_ci default: 1337bf215546Sopenharmony_ci assert(0); 1338bf215546Sopenharmony_ci count = 0; 1339bf215546Sopenharmony_ci break; 1340bf215546Sopenharmony_ci } 1341bf215546Sopenharmony_ci 1342bf215546Sopenharmony_ci assert(offset + count * stride <= size); 1343bf215546Sopenharmony_ci } 1344bf215546Sopenharmony_ci} 1345bf215546Sopenharmony_ci 1346bf215546Sopenharmony_ci 1347bf215546Sopenharmony_ci/** 1348bf215546Sopenharmony_ci * All drawing filters down into this function, either directly 1349bf215546Sopenharmony_ci * on the hardware path or after doing software vertex processing. 1350bf215546Sopenharmony_ci * \param indirect if non-null, get the vertex count, first vertex, etc. 1351bf215546Sopenharmony_ci * from a buffer. 1352bf215546Sopenharmony_ci * \param so_vertex_count if non-null, get the vertex count from a 1353bf215546Sopenharmony_ci * stream-output target. 1354bf215546Sopenharmony_ci */ 1355bf215546Sopenharmony_cienum pipe_error 1356bf215546Sopenharmony_cisvga_hwtnl_prim(struct svga_hwtnl *hwtnl, 1357bf215546Sopenharmony_ci const SVGA3dPrimitiveRange *range, 1358bf215546Sopenharmony_ci unsigned vcount, 1359bf215546Sopenharmony_ci unsigned min_index, unsigned max_index, 1360bf215546Sopenharmony_ci struct pipe_resource *ib, 1361bf215546Sopenharmony_ci unsigned start_instance, unsigned instance_count, 1362bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 1363bf215546Sopenharmony_ci const struct pipe_stream_output_target *so_vertex_count) 1364bf215546Sopenharmony_ci{ 1365bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 1366bf215546Sopenharmony_ci 1367bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(hwtnl->svga), SVGA_STATS_TIME_HWTNLPRIM); 1368bf215546Sopenharmony_ci 1369bf215546Sopenharmony_ci if (svga_have_vgpu10(hwtnl->svga)) { 1370bf215546Sopenharmony_ci /* draw immediately */ 1371bf215546Sopenharmony_ci SVGA_RETRY(hwtnl->svga, draw_vgpu10(hwtnl, range, vcount, min_index, 1372bf215546Sopenharmony_ci max_index, ib, start_instance, 1373bf215546Sopenharmony_ci instance_count, indirect, 1374bf215546Sopenharmony_ci so_vertex_count)); 1375bf215546Sopenharmony_ci } 1376bf215546Sopenharmony_ci else { 1377bf215546Sopenharmony_ci /* batch up drawing commands */ 1378bf215546Sopenharmony_ci assert(indirect == NULL); 1379bf215546Sopenharmony_ci#ifdef DEBUG 1380bf215546Sopenharmony_ci check_draw_params(hwtnl, range, min_index, max_index, ib); 1381bf215546Sopenharmony_ci assert(start_instance == 0); 1382bf215546Sopenharmony_ci assert(instance_count <= 1); 1383bf215546Sopenharmony_ci#else 1384bf215546Sopenharmony_ci (void) check_draw_params; 1385bf215546Sopenharmony_ci#endif 1386bf215546Sopenharmony_ci 1387bf215546Sopenharmony_ci if (hwtnl->cmd.prim_count + 1 >= QSZ) { 1388bf215546Sopenharmony_ci ret = svga_hwtnl_flush(hwtnl); 1389bf215546Sopenharmony_ci if (ret != PIPE_OK) 1390bf215546Sopenharmony_ci goto done; 1391bf215546Sopenharmony_ci } 1392bf215546Sopenharmony_ci 1393bf215546Sopenharmony_ci /* min/max indices are relative to bias */ 1394bf215546Sopenharmony_ci hwtnl->cmd.min_index[hwtnl->cmd.prim_count] = min_index; 1395bf215546Sopenharmony_ci hwtnl->cmd.max_index[hwtnl->cmd.prim_count] = max_index; 1396bf215546Sopenharmony_ci 1397bf215546Sopenharmony_ci hwtnl->cmd.prim[hwtnl->cmd.prim_count] = *range; 1398bf215546Sopenharmony_ci hwtnl->cmd.prim[hwtnl->cmd.prim_count].indexBias += hwtnl->index_bias; 1399bf215546Sopenharmony_ci 1400bf215546Sopenharmony_ci pipe_resource_reference(&hwtnl->cmd.prim_ib[hwtnl->cmd.prim_count], ib); 1401bf215546Sopenharmony_ci hwtnl->cmd.prim_count++; 1402bf215546Sopenharmony_ci } 1403bf215546Sopenharmony_ci 1404bf215546Sopenharmony_cidone: 1405bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_screen(hwtnl->svga->pipe.screen)->sws); 1406bf215546Sopenharmony_ci return ret; 1407bf215546Sopenharmony_ci} 1408bf215546Sopenharmony_ci 1409bf215546Sopenharmony_ci 1410bf215546Sopenharmony_ci/** 1411bf215546Sopenharmony_ci * Return TRUE if there are pending primitives. 1412bf215546Sopenharmony_ci */ 1413bf215546Sopenharmony_ciboolean 1414bf215546Sopenharmony_cisvga_hwtnl_has_pending_prim(struct svga_hwtnl *hwtnl) 1415bf215546Sopenharmony_ci{ 1416bf215546Sopenharmony_ci return hwtnl->cmd.prim_count > 0; 1417bf215546Sopenharmony_ci} 1418