17ec681f3Smrg/* 27ec681f3Smrg * Copyright © Microsoft Corporation 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "d3d12_compiler.h" 257ec681f3Smrg#include "d3d12_context.h" 267ec681f3Smrg#include "d3d12_format.h" 277ec681f3Smrg#include "d3d12_query.h" 287ec681f3Smrg#include "d3d12_resource.h" 297ec681f3Smrg#include "d3d12_root_signature.h" 307ec681f3Smrg#include "d3d12_screen.h" 317ec681f3Smrg#include "d3d12_surface.h" 327ec681f3Smrg 337ec681f3Smrg#include "util/u_debug.h" 347ec681f3Smrg#include "util/u_draw.h" 357ec681f3Smrg#include "util/u_helpers.h" 367ec681f3Smrg#include "util/u_inlines.h" 377ec681f3Smrg#include "util/u_prim.h" 387ec681f3Smrg#include "util/u_prim_restart.h" 397ec681f3Smrg#include "util/u_math.h" 407ec681f3Smrg 417ec681f3Smrgextern "C" { 427ec681f3Smrg#include "indices/u_primconvert.h" 437ec681f3Smrg} 447ec681f3Smrg 457ec681f3Smrgstatic const D3D12_RECT MAX_SCISSOR = { D3D12_VIEWPORT_BOUNDS_MIN, 467ec681f3Smrg D3D12_VIEWPORT_BOUNDS_MIN, 477ec681f3Smrg D3D12_VIEWPORT_BOUNDS_MAX, 487ec681f3Smrg D3D12_VIEWPORT_BOUNDS_MAX }; 497ec681f3Smrg 507ec681f3Smrgstatic D3D12_GPU_DESCRIPTOR_HANDLE 517ec681f3Smrgfill_cbv_descriptors(struct d3d12_context *ctx, 527ec681f3Smrg struct d3d12_shader *shader, 537ec681f3Smrg int stage) 547ec681f3Smrg{ 557ec681f3Smrg struct d3d12_batch *batch = d3d12_current_batch(ctx); 567ec681f3Smrg struct d3d12_descriptor_handle table_start; 577ec681f3Smrg d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 587ec681f3Smrg 597ec681f3Smrg for (unsigned i = 0; i < shader->num_cb_bindings; i++) { 607ec681f3Smrg unsigned binding = shader->cb_bindings[i].binding; 617ec681f3Smrg struct pipe_constant_buffer *buffer = &ctx->cbufs[stage][binding]; 627ec681f3Smrg 637ec681f3Smrg D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {}; 647ec681f3Smrg if (buffer && buffer->buffer) { 657ec681f3Smrg struct d3d12_resource *res = d3d12_resource(buffer->buffer); 667ec681f3Smrg d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE); 677ec681f3Smrg cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset; 687ec681f3Smrg cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16, 697ec681f3Smrg align(buffer->buffer_size, 256)); 707ec681f3Smrg d3d12_batch_reference_resource(batch, res); 717ec681f3Smrg } 727ec681f3Smrg 737ec681f3Smrg struct d3d12_descriptor_handle handle; 747ec681f3Smrg d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle); 757ec681f3Smrg d3d12_screen(ctx->base.screen)->dev->CreateConstantBufferView(&cbv_desc, handle.cpu_handle); 767ec681f3Smrg } 777ec681f3Smrg 787ec681f3Smrg return table_start.gpu_handle; 797ec681f3Smrg} 807ec681f3Smrg 817ec681f3Smrgstatic D3D12_GPU_DESCRIPTOR_HANDLE 827ec681f3Smrgfill_srv_descriptors(struct d3d12_context *ctx, 837ec681f3Smrg struct d3d12_shader *shader, 847ec681f3Smrg unsigned stage) 857ec681f3Smrg{ 867ec681f3Smrg struct d3d12_batch *batch = d3d12_current_batch(ctx); 877ec681f3Smrg struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 887ec681f3Smrg D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 897ec681f3Smrg struct d3d12_descriptor_handle table_start; 907ec681f3Smrg 917ec681f3Smrg d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); 927ec681f3Smrg 937ec681f3Smrg for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) 947ec681f3Smrg { 957ec681f3Smrg struct d3d12_sampler_view *view; 967ec681f3Smrg 977ec681f3Smrg if (i == shader->pstipple_binding) { 987ec681f3Smrg view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view; 997ec681f3Smrg } else { 1007ec681f3Smrg view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i]; 1017ec681f3Smrg } 1027ec681f3Smrg 1037ec681f3Smrg unsigned desc_idx = i - shader->begin_srv_binding; 1047ec681f3Smrg if (view != NULL) { 1057ec681f3Smrg descs[desc_idx] = view->handle.cpu_handle; 1067ec681f3Smrg d3d12_batch_reference_sampler_view(batch, view); 1077ec681f3Smrg 1087ec681f3Smrg D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ? 1097ec681f3Smrg D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE : 1107ec681f3Smrg D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; 1117ec681f3Smrg if (view->base.texture->target == PIPE_BUFFER) { 1127ec681f3Smrg d3d12_transition_resource_state(ctx, d3d12_resource(view->base.texture), 1137ec681f3Smrg state, 1147ec681f3Smrg D3D12_BIND_INVALIDATE_NONE); 1157ec681f3Smrg } else { 1167ec681f3Smrg d3d12_transition_subresources_state(ctx, d3d12_resource(view->base.texture), 1177ec681f3Smrg view->base.u.tex.first_level, view->mip_levels, 1187ec681f3Smrg view->base.u.tex.first_layer, view->array_size, 1197ec681f3Smrg d3d12_get_format_start_plane(view->base.format), 1207ec681f3Smrg d3d12_get_format_num_planes(view->base.format), 1217ec681f3Smrg state, 1227ec681f3Smrg D3D12_BIND_INVALIDATE_NONE); 1237ec681f3Smrg } 1247ec681f3Smrg } else { 1257ec681f3Smrg descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle; 1267ec681f3Smrg } 1277ec681f3Smrg } 1287ec681f3Smrg 1297ec681f3Smrg d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); 1307ec681f3Smrg 1317ec681f3Smrg return table_start.gpu_handle; 1327ec681f3Smrg} 1337ec681f3Smrg 1347ec681f3Smrgstatic D3D12_GPU_DESCRIPTOR_HANDLE 1357ec681f3Smrgfill_sampler_descriptors(struct d3d12_context *ctx, 1367ec681f3Smrg const struct d3d12_shader_selector *shader_sel, 1377ec681f3Smrg unsigned stage) 1387ec681f3Smrg{ 1397ec681f3Smrg const struct d3d12_shader *shader = shader_sel->current; 1407ec681f3Smrg struct d3d12_batch *batch = d3d12_current_batch(ctx); 1417ec681f3Smrg D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 1427ec681f3Smrg struct d3d12_descriptor_handle table_start; 1437ec681f3Smrg 1447ec681f3Smrg d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start); 1457ec681f3Smrg 1467ec681f3Smrg for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) 1477ec681f3Smrg { 1487ec681f3Smrg struct d3d12_sampler_state *sampler; 1497ec681f3Smrg 1507ec681f3Smrg if (i == shader->pstipple_binding) { 1517ec681f3Smrg sampler = ctx->pstipple.sampler_cso; 1527ec681f3Smrg } else { 1537ec681f3Smrg sampler = ctx->samplers[stage][i]; 1547ec681f3Smrg } 1557ec681f3Smrg 1567ec681f3Smrg unsigned desc_idx = i - shader->begin_srv_binding; 1577ec681f3Smrg if (sampler != NULL) { 1587ec681f3Smrg if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad) 1597ec681f3Smrg descs[desc_idx] = sampler->handle_without_shadow.cpu_handle; 1607ec681f3Smrg else 1617ec681f3Smrg descs[desc_idx] = sampler->handle.cpu_handle; 1627ec681f3Smrg } else 1637ec681f3Smrg descs[desc_idx] = ctx->null_sampler.cpu_handle; 1647ec681f3Smrg } 1657ec681f3Smrg 1667ec681f3Smrg d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); 1677ec681f3Smrg return table_start.gpu_handle; 1687ec681f3Smrg} 1697ec681f3Smrg 1707ec681f3Smrgstatic unsigned 1717ec681f3Smrgfill_state_vars(struct d3d12_context *ctx, 1727ec681f3Smrg const struct pipe_draw_info *dinfo, 1737ec681f3Smrg const struct pipe_draw_start_count_bias *draw, 1747ec681f3Smrg struct d3d12_shader *shader, 1757ec681f3Smrg uint32_t *values) 1767ec681f3Smrg{ 1777ec681f3Smrg unsigned size = 0; 1787ec681f3Smrg 1797ec681f3Smrg for (unsigned j = 0; j < shader->num_state_vars; ++j) { 1807ec681f3Smrg uint32_t *ptr = values + size; 1817ec681f3Smrg 1827ec681f3Smrg switch (shader->state_vars[j].var) { 1837ec681f3Smrg case D3D12_STATE_VAR_Y_FLIP: 1847ec681f3Smrg ptr[0] = fui(ctx->flip_y); 1857ec681f3Smrg size += 4; 1867ec681f3Smrg break; 1877ec681f3Smrg case D3D12_STATE_VAR_PT_SPRITE: 1887ec681f3Smrg ptr[0] = fui(1.0 / ctx->viewports[0].Width); 1897ec681f3Smrg ptr[1] = fui(1.0 / ctx->viewports[0].Height); 1907ec681f3Smrg ptr[2] = fui(ctx->gfx_pipeline_state.rast->base.point_size); 1917ec681f3Smrg ptr[3] = fui(D3D12_MAX_POINT_SIZE); 1927ec681f3Smrg size += 4; 1937ec681f3Smrg break; 1947ec681f3Smrg case D3D12_STATE_VAR_FIRST_VERTEX: 1957ec681f3Smrg ptr[0] = dinfo->index_size ? draw->index_bias : draw->start; 1967ec681f3Smrg size += 4; 1977ec681f3Smrg break; 1987ec681f3Smrg case D3D12_STATE_VAR_DEPTH_TRANSFORM: 1997ec681f3Smrg ptr[0] = fui(2.0f * ctx->viewport_states[0].scale[2]); 2007ec681f3Smrg ptr[1] = fui(ctx->viewport_states[0].translate[2] - ctx->viewport_states[0].scale[2]); 2017ec681f3Smrg size += 4; 2027ec681f3Smrg break; 2037ec681f3Smrg default: 2047ec681f3Smrg unreachable("unknown state variable"); 2057ec681f3Smrg } 2067ec681f3Smrg } 2077ec681f3Smrg 2087ec681f3Smrg return size; 2097ec681f3Smrg} 2107ec681f3Smrg 2117ec681f3Smrgstatic bool 2127ec681f3Smrgcheck_descriptors_left(struct d3d12_context *ctx) 2137ec681f3Smrg{ 2147ec681f3Smrg struct d3d12_batch *batch = d3d12_current_batch(ctx); 2157ec681f3Smrg unsigned needed_descs = 0; 2167ec681f3Smrg 2177ec681f3Smrg for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 2187ec681f3Smrg struct d3d12_shader_selector *shader = ctx->gfx_stages[i]; 2197ec681f3Smrg 2207ec681f3Smrg if (!shader) 2217ec681f3Smrg continue; 2227ec681f3Smrg 2237ec681f3Smrg needed_descs += shader->current->num_cb_bindings; 2247ec681f3Smrg needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; 2257ec681f3Smrg } 2267ec681f3Smrg 2277ec681f3Smrg if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs) 2287ec681f3Smrg return false; 2297ec681f3Smrg 2307ec681f3Smrg needed_descs = 0; 2317ec681f3Smrg for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 2327ec681f3Smrg struct d3d12_shader_selector *shader = ctx->gfx_stages[i]; 2337ec681f3Smrg 2347ec681f3Smrg if (!shader) 2357ec681f3Smrg continue; 2367ec681f3Smrg 2377ec681f3Smrg needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; 2387ec681f3Smrg } 2397ec681f3Smrg 2407ec681f3Smrg if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs) 2417ec681f3Smrg return false; 2427ec681f3Smrg 2437ec681f3Smrg return true; 2447ec681f3Smrg} 2457ec681f3Smrg 2467ec681f3Smrg#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 3) 2477ec681f3Smrg 2487ec681f3Smrgstatic unsigned 2497ec681f3Smrgupdate_graphics_root_parameters(struct d3d12_context *ctx, 2507ec681f3Smrg const struct pipe_draw_info *dinfo, 2517ec681f3Smrg const struct pipe_draw_start_count_bias *draw, 2527ec681f3Smrg D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES], 2537ec681f3Smrg int root_desc_indices[MAX_DESCRIPTOR_TABLES]) 2547ec681f3Smrg{ 2557ec681f3Smrg unsigned num_params = 0; 2567ec681f3Smrg unsigned num_root_desciptors = 0; 2577ec681f3Smrg 2587ec681f3Smrg for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 2597ec681f3Smrg if (!ctx->gfx_stages[i]) 2607ec681f3Smrg continue; 2617ec681f3Smrg 2627ec681f3Smrg struct d3d12_shader_selector *shader_sel = ctx->gfx_stages[i]; 2637ec681f3Smrg struct d3d12_shader *shader = shader_sel->current; 2647ec681f3Smrg uint64_t dirty = ctx->shader_dirty[i]; 2657ec681f3Smrg assert(shader); 2667ec681f3Smrg 2677ec681f3Smrg if (shader->num_cb_bindings > 0) { 2687ec681f3Smrg if (dirty & D3D12_SHADER_DIRTY_CONSTBUF) { 2697ec681f3Smrg assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES); 2707ec681f3Smrg root_desc_tables[num_root_desciptors] = fill_cbv_descriptors(ctx, shader, i); 2717ec681f3Smrg root_desc_indices[num_root_desciptors++] = num_params; 2727ec681f3Smrg } 2737ec681f3Smrg num_params++; 2747ec681f3Smrg } 2757ec681f3Smrg if (shader->end_srv_binding > 0) { 2767ec681f3Smrg if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) { 2777ec681f3Smrg assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES); 2787ec681f3Smrg root_desc_tables[num_root_desciptors] = fill_srv_descriptors(ctx, shader, i); 2797ec681f3Smrg root_desc_indices[num_root_desciptors++] = num_params; 2807ec681f3Smrg } 2817ec681f3Smrg num_params++; 2827ec681f3Smrg if (dirty & D3D12_SHADER_DIRTY_SAMPLERS) { 2837ec681f3Smrg assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES); 2847ec681f3Smrg root_desc_tables[num_root_desciptors] = fill_sampler_descriptors(ctx, shader_sel, i); 2857ec681f3Smrg root_desc_indices[num_root_desciptors++] = num_params; 2867ec681f3Smrg } 2877ec681f3Smrg num_params++; 2887ec681f3Smrg } 2897ec681f3Smrg /* TODO Don't always update state vars */ 2907ec681f3Smrg if (shader->num_state_vars > 0) { 2917ec681f3Smrg uint32_t constants[D3D12_MAX_STATE_VARS * 4]; 2927ec681f3Smrg unsigned size = fill_state_vars(ctx, dinfo, draw, shader, constants); 2937ec681f3Smrg ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0); 2947ec681f3Smrg num_params++; 2957ec681f3Smrg } 2967ec681f3Smrg } 2977ec681f3Smrg return num_root_desciptors; 2987ec681f3Smrg} 2997ec681f3Smrg 3007ec681f3Smrgstatic bool 3017ec681f3Smrgvalidate_stream_output_targets(struct d3d12_context *ctx) 3027ec681f3Smrg{ 3037ec681f3Smrg unsigned factor = 0; 3047ec681f3Smrg 3057ec681f3Smrg if (ctx->gfx_pipeline_state.num_so_targets && 3067ec681f3Smrg ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]) 3077ec681f3Smrg factor = ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]->key.gs.stream_output_factor; 3087ec681f3Smrg 3097ec681f3Smrg if (factor > 1) 3107ec681f3Smrg return d3d12_enable_fake_so_buffers(ctx, factor); 3117ec681f3Smrg else 3127ec681f3Smrg return d3d12_disable_fake_so_buffers(ctx); 3137ec681f3Smrg} 3147ec681f3Smrg 3157ec681f3Smrgstatic D3D_PRIMITIVE_TOPOLOGY 3167ec681f3Smrgtopology(enum pipe_prim_type prim_type) 3177ec681f3Smrg{ 3187ec681f3Smrg switch (prim_type) { 3197ec681f3Smrg case PIPE_PRIM_POINTS: 3207ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_POINTLIST; 3217ec681f3Smrg 3227ec681f3Smrg case PIPE_PRIM_LINES: 3237ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_LINELIST; 3247ec681f3Smrg 3257ec681f3Smrg case PIPE_PRIM_LINE_STRIP: 3267ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; 3277ec681f3Smrg 3287ec681f3Smrg case PIPE_PRIM_TRIANGLES: 3297ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; 3307ec681f3Smrg 3317ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP: 3327ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; 3337ec681f3Smrg 3347ec681f3Smrg case PIPE_PRIM_LINES_ADJACENCY: 3357ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ; 3367ec681f3Smrg 3377ec681f3Smrg case PIPE_PRIM_LINE_STRIP_ADJACENCY: 3387ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ; 3397ec681f3Smrg 3407ec681f3Smrg case PIPE_PRIM_TRIANGLES_ADJACENCY: 3417ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ; 3427ec681f3Smrg 3437ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 3447ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ; 3457ec681f3Smrg 3467ec681f3Smrg/* 3477ec681f3Smrg case PIPE_PRIM_PATCHES: 3487ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_PATCHLIST; 3497ec681f3Smrg*/ 3507ec681f3Smrg 3517ec681f3Smrg case PIPE_PRIM_QUADS: 3527ec681f3Smrg case PIPE_PRIM_QUAD_STRIP: 3537ec681f3Smrg return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; /* HACK: this is just wrong! */ 3547ec681f3Smrg 3557ec681f3Smrg default: 3567ec681f3Smrg debug_printf("pipe_prim_type: %s\n", u_prim_name(prim_type)); 3577ec681f3Smrg unreachable("unexpected enum pipe_prim_type"); 3587ec681f3Smrg } 3597ec681f3Smrg} 3607ec681f3Smrg 3617ec681f3Smrgstatic DXGI_FORMAT 3627ec681f3Smrgib_format(unsigned index_size) 3637ec681f3Smrg{ 3647ec681f3Smrg switch (index_size) { 3657ec681f3Smrg case 1: return DXGI_FORMAT_R8_UINT; 3667ec681f3Smrg case 2: return DXGI_FORMAT_R16_UINT; 3677ec681f3Smrg case 4: return DXGI_FORMAT_R32_UINT; 3687ec681f3Smrg 3697ec681f3Smrg default: 3707ec681f3Smrg unreachable("unexpected index-buffer size"); 3717ec681f3Smrg } 3727ec681f3Smrg} 3737ec681f3Smrg 3747ec681f3Smrgstatic void 3757ec681f3Smrgtwoface_emulation(struct d3d12_context *ctx, 3767ec681f3Smrg struct d3d12_rasterizer_state *rast, 3777ec681f3Smrg const struct pipe_draw_info *dinfo, 3787ec681f3Smrg const struct pipe_draw_start_count_bias *draw) 3797ec681f3Smrg{ 3807ec681f3Smrg /* draw backfaces */ 3817ec681f3Smrg ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back); 3827ec681f3Smrg d3d12_draw_vbo(&ctx->base, dinfo, 0, NULL, draw, 1); 3837ec681f3Smrg 3847ec681f3Smrg /* restore real state */ 3857ec681f3Smrg ctx->base.bind_rasterizer_state(&ctx->base, rast); 3867ec681f3Smrg} 3877ec681f3Smrg 3887ec681f3Smrgstatic void 3897ec681f3Smrgtransition_surface_subresources_state(struct d3d12_context *ctx, 3907ec681f3Smrg struct pipe_surface *psurf, 3917ec681f3Smrg struct pipe_resource *pres, 3927ec681f3Smrg D3D12_RESOURCE_STATES state) 3937ec681f3Smrg{ 3947ec681f3Smrg struct d3d12_resource *res = d3d12_resource(pres); 3957ec681f3Smrg unsigned start_layer, num_layers; 3967ec681f3Smrg if (!d3d12_subresource_id_uses_layer(res->base.target)) { 3977ec681f3Smrg start_layer = 0; 3987ec681f3Smrg num_layers = 1; 3997ec681f3Smrg } else { 4007ec681f3Smrg start_layer = psurf->u.tex.first_layer; 4017ec681f3Smrg num_layers = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1; 4027ec681f3Smrg } 4037ec681f3Smrg d3d12_transition_subresources_state(ctx, res, 4047ec681f3Smrg psurf->u.tex.level, 1, 4057ec681f3Smrg start_layer, num_layers, 4067ec681f3Smrg d3d12_get_format_start_plane(psurf->format), 4077ec681f3Smrg d3d12_get_format_num_planes(psurf->format), 4087ec681f3Smrg state, 4097ec681f3Smrg D3D12_BIND_INVALIDATE_FULL); 4107ec681f3Smrg} 4117ec681f3Smrg 4127ec681f3Smrgstatic bool 4137ec681f3Smrgprim_supported(enum pipe_prim_type prim_type) 4147ec681f3Smrg{ 4157ec681f3Smrg switch (prim_type) { 4167ec681f3Smrg case PIPE_PRIM_POINTS: 4177ec681f3Smrg case PIPE_PRIM_LINES: 4187ec681f3Smrg case PIPE_PRIM_LINE_STRIP: 4197ec681f3Smrg case PIPE_PRIM_TRIANGLES: 4207ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP: 4217ec681f3Smrg case PIPE_PRIM_LINES_ADJACENCY: 4227ec681f3Smrg case PIPE_PRIM_LINE_STRIP_ADJACENCY: 4237ec681f3Smrg case PIPE_PRIM_TRIANGLES_ADJACENCY: 4247ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 4257ec681f3Smrg return true; 4267ec681f3Smrg 4277ec681f3Smrg default: 4287ec681f3Smrg return false; 4297ec681f3Smrg } 4307ec681f3Smrg} 4317ec681f3Smrg 4327ec681f3Smrgstatic inline struct d3d12_shader_selector * 4337ec681f3Smrgd3d12_last_vertex_stage(struct d3d12_context *ctx) 4347ec681f3Smrg{ 4357ec681f3Smrg struct d3d12_shader_selector *sel = ctx->gfx_stages[PIPE_SHADER_GEOMETRY]; 4367ec681f3Smrg if (!sel || sel->is_gs_variant) 4377ec681f3Smrg sel = ctx->gfx_stages[PIPE_SHADER_VERTEX]; 4387ec681f3Smrg return sel; 4397ec681f3Smrg} 4407ec681f3Smrg 4417ec681f3Smrgvoid 4427ec681f3Smrgd3d12_draw_vbo(struct pipe_context *pctx, 4437ec681f3Smrg const struct pipe_draw_info *dinfo, 4447ec681f3Smrg unsigned drawid_offset, 4457ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 4467ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 4477ec681f3Smrg unsigned num_draws) 4487ec681f3Smrg{ 4497ec681f3Smrg if (num_draws > 1) { 4507ec681f3Smrg util_draw_multi(pctx, dinfo, drawid_offset, indirect, draws, num_draws); 4517ec681f3Smrg return; 4527ec681f3Smrg } 4537ec681f3Smrg 4547ec681f3Smrg if (!indirect && (!draws[0].count || !dinfo->instance_count)) 4557ec681f3Smrg return; 4567ec681f3Smrg 4577ec681f3Smrg struct d3d12_context *ctx = d3d12_context(pctx); 4587ec681f3Smrg struct d3d12_screen *screen = d3d12_screen(pctx->screen); 4597ec681f3Smrg struct d3d12_batch *batch; 4607ec681f3Smrg struct pipe_resource *index_buffer = NULL; 4617ec681f3Smrg unsigned index_offset = 0; 4627ec681f3Smrg enum d3d12_surface_conversion_mode conversion_modes[PIPE_MAX_COLOR_BUFS] = {}; 4637ec681f3Smrg 4647ec681f3Smrg if (!prim_supported((enum pipe_prim_type)dinfo->mode) || 4657ec681f3Smrg dinfo->index_size == 1 || 4667ec681f3Smrg (dinfo->primitive_restart && dinfo->restart_index != 0xffff && 4677ec681f3Smrg dinfo->restart_index != 0xffffffff)) { 4687ec681f3Smrg 4697ec681f3Smrg if (!dinfo->primitive_restart && 4707ec681f3Smrg !u_trim_pipe_prim((enum pipe_prim_type)dinfo->mode, (unsigned *)&draws[0].count)) 4717ec681f3Smrg return; 4727ec681f3Smrg 4737ec681f3Smrg ctx->initial_api_prim = (enum pipe_prim_type)dinfo->mode; 4747ec681f3Smrg util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base); 4757ec681f3Smrg util_primconvert_draw_vbo(ctx->primconvert, dinfo, drawid_offset, indirect, draws, num_draws); 4767ec681f3Smrg return; 4777ec681f3Smrg } 4787ec681f3Smrg 4797ec681f3Smrg for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 4807ec681f3Smrg if (ctx->fb.cbufs[i]) { 4817ec681f3Smrg struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 4827ec681f3Smrg conversion_modes[i] = d3d12_surface_update_pre_draw(surface, d3d12_rtv_format(ctx, i)); 4837ec681f3Smrg if (conversion_modes[i] != D3D12_SURFACE_CONVERSION_NONE) 4847ec681f3Smrg ctx->cmdlist_dirty |= D3D12_DIRTY_FRAMEBUFFER; 4857ec681f3Smrg } 4867ec681f3Smrg } 4877ec681f3Smrg 4887ec681f3Smrg struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast; 4897ec681f3Smrg if (rast->twoface_back) { 4907ec681f3Smrg enum pipe_prim_type saved_mode = ctx->initial_api_prim; 4917ec681f3Smrg twoface_emulation(ctx, rast, dinfo, &draws[0]); 4927ec681f3Smrg ctx->initial_api_prim = saved_mode; 4937ec681f3Smrg } 4947ec681f3Smrg 4957ec681f3Smrg if (ctx->pstipple.enabled) 4967ec681f3Smrg ctx->shader_dirty[PIPE_SHADER_FRAGMENT] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS | 4977ec681f3Smrg D3D12_SHADER_DIRTY_SAMPLERS; 4987ec681f3Smrg 4997ec681f3Smrg /* this should *really* be fixed at a higher level than here! */ 5007ec681f3Smrg enum pipe_prim_type reduced_prim = u_reduced_prim((enum pipe_prim_type)dinfo->mode); 5017ec681f3Smrg if (reduced_prim == PIPE_PRIM_TRIANGLES && 5027ec681f3Smrg ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT_AND_BACK) 5037ec681f3Smrg return; 5047ec681f3Smrg 5057ec681f3Smrg if (ctx->gfx_pipeline_state.prim_type != dinfo->mode) { 5067ec681f3Smrg ctx->gfx_pipeline_state.prim_type = (enum pipe_prim_type)dinfo->mode; 5077ec681f3Smrg ctx->state_dirty |= D3D12_DIRTY_PRIM_MODE; 5087ec681f3Smrg } 5097ec681f3Smrg 5107ec681f3Smrg d3d12_select_shader_variants(ctx, dinfo); 5117ec681f3Smrg d3d12_validate_queries(ctx); 5127ec681f3Smrg for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) { 5137ec681f3Smrg struct d3d12_shader *shader = ctx->gfx_stages[i] ? ctx->gfx_stages[i]->current : NULL; 5147ec681f3Smrg if (ctx->gfx_pipeline_state.stages[i] != shader) { 5157ec681f3Smrg ctx->gfx_pipeline_state.stages[i] = shader; 5167ec681f3Smrg ctx->state_dirty |= D3D12_DIRTY_SHADER; 5177ec681f3Smrg } 5187ec681f3Smrg } 5197ec681f3Smrg 5207ec681f3Smrg /* Reset to an invalid value after it's been used */ 5217ec681f3Smrg ctx->initial_api_prim = PIPE_PRIM_MAX; 5227ec681f3Smrg 5237ec681f3Smrg /* Copy the stream output info from the current vertex/geometry shader */ 5247ec681f3Smrg if (ctx->state_dirty & D3D12_DIRTY_SHADER) { 5257ec681f3Smrg struct d3d12_shader_selector *sel = d3d12_last_vertex_stage(ctx); 5267ec681f3Smrg if (sel) { 5277ec681f3Smrg ctx->gfx_pipeline_state.so_info = sel->so_info; 5287ec681f3Smrg } else { 5297ec681f3Smrg memset(&ctx->gfx_pipeline_state.so_info, 0, sizeof(sel->so_info)); 5307ec681f3Smrg } 5317ec681f3Smrg } 5327ec681f3Smrg if (!validate_stream_output_targets(ctx)) { 5337ec681f3Smrg debug_printf("validate_stream_output_targets() failed\n"); 5347ec681f3Smrg return; 5357ec681f3Smrg } 5367ec681f3Smrg 5377ec681f3Smrg D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value = 5387ec681f3Smrg D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; 5397ec681f3Smrg if (dinfo->index_size > 0) { 5407ec681f3Smrg assert(dinfo->index_size != 1); 5417ec681f3Smrg 5427ec681f3Smrg if (dinfo->has_user_indices) { 5437ec681f3Smrg if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer, 5447ec681f3Smrg &index_offset, 4)) { 5457ec681f3Smrg debug_printf("util_upload_index_buffer() failed\n"); 5467ec681f3Smrg return; 5477ec681f3Smrg } 5487ec681f3Smrg } else { 5497ec681f3Smrg index_buffer = dinfo->index.resource; 5507ec681f3Smrg } 5517ec681f3Smrg 5527ec681f3Smrg if (dinfo->primitive_restart) { 5537ec681f3Smrg assert(dinfo->restart_index == 0xffff || 5547ec681f3Smrg dinfo->restart_index == 0xffffffff); 5557ec681f3Smrg ib_strip_cut_value = dinfo->restart_index == 0xffff ? 5567ec681f3Smrg D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF : 5577ec681f3Smrg D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF; 5587ec681f3Smrg } 5597ec681f3Smrg } 5607ec681f3Smrg 5617ec681f3Smrg if (ctx->gfx_pipeline_state.ib_strip_cut_value != ib_strip_cut_value) { 5627ec681f3Smrg ctx->gfx_pipeline_state.ib_strip_cut_value = ib_strip_cut_value; 5637ec681f3Smrg ctx->state_dirty |= D3D12_DIRTY_STRIP_CUT_VALUE; 5647ec681f3Smrg } 5657ec681f3Smrg 5667ec681f3Smrg if (!ctx->gfx_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_SHADER) { 5677ec681f3Smrg ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx); 5687ec681f3Smrg if (ctx->gfx_pipeline_state.root_signature != root_signature) { 5697ec681f3Smrg ctx->gfx_pipeline_state.root_signature = root_signature; 5707ec681f3Smrg ctx->state_dirty |= D3D12_DIRTY_ROOT_SIGNATURE; 5717ec681f3Smrg for (int i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) 5727ec681f3Smrg ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_ALL; 5737ec681f3Smrg } 5747ec681f3Smrg } 5757ec681f3Smrg 5767ec681f3Smrg if (!ctx->current_pso || ctx->state_dirty & D3D12_DIRTY_PSO) { 5777ec681f3Smrg ctx->current_pso = d3d12_get_gfx_pipeline_state(ctx); 5787ec681f3Smrg assert(ctx->current_pso); 5797ec681f3Smrg } 5807ec681f3Smrg 5817ec681f3Smrg ctx->cmdlist_dirty |= ctx->state_dirty; 5827ec681f3Smrg 5837ec681f3Smrg if (!check_descriptors_left(ctx)) 5847ec681f3Smrg d3d12_flush_cmdlist(ctx); 5857ec681f3Smrg batch = d3d12_current_batch(ctx); 5867ec681f3Smrg 5877ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_ROOT_SIGNATURE) { 5887ec681f3Smrg d3d12_batch_reference_object(batch, ctx->gfx_pipeline_state.root_signature); 5897ec681f3Smrg ctx->cmdlist->SetGraphicsRootSignature(ctx->gfx_pipeline_state.root_signature); 5907ec681f3Smrg } 5917ec681f3Smrg 5927ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_PSO) { 5937ec681f3Smrg assert(ctx->current_pso); 5947ec681f3Smrg d3d12_batch_reference_object(batch, ctx->current_pso); 5957ec681f3Smrg ctx->cmdlist->SetPipelineState(ctx->current_pso); 5967ec681f3Smrg } 5977ec681f3Smrg 5987ec681f3Smrg D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES]; 5997ec681f3Smrg int root_desc_indices[MAX_DESCRIPTOR_TABLES]; 6007ec681f3Smrg unsigned num_root_desciptors = update_graphics_root_parameters(ctx, dinfo, &draws[0], root_desc_tables, root_desc_indices); 6017ec681f3Smrg 6027ec681f3Smrg bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx); 6037ec681f3Smrg if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) { 6047ec681f3Smrg ctx->cmdlist_dirty |= D3D12_DIRTY_VIEWPORT; 6057ec681f3Smrg ctx->need_zero_one_depth_range = need_zero_one_depth_range; 6067ec681f3Smrg } 6077ec681f3Smrg 6087ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_VIEWPORT) { 6097ec681f3Smrg if (ctx->need_zero_one_depth_range) { 6107ec681f3Smrg D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS]; 6117ec681f3Smrg for (unsigned i = 0; i < ctx->num_viewports; ++i) { 6127ec681f3Smrg viewports[i] = ctx->viewports[i]; 6137ec681f3Smrg viewports[i].MinDepth = 0.0f; 6147ec681f3Smrg viewports[i].MaxDepth = 1.0f; 6157ec681f3Smrg } 6167ec681f3Smrg ctx->cmdlist->RSSetViewports(ctx->num_viewports, viewports); 6177ec681f3Smrg } else 6187ec681f3Smrg ctx->cmdlist->RSSetViewports(ctx->num_viewports, ctx->viewports); 6197ec681f3Smrg } 6207ec681f3Smrg 6217ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_SCISSOR) { 6227ec681f3Smrg if (ctx->gfx_pipeline_state.rast->base.scissor && ctx->num_viewports > 0) 6237ec681f3Smrg ctx->cmdlist->RSSetScissorRects(ctx->num_viewports, ctx->scissors); 6247ec681f3Smrg else 6257ec681f3Smrg ctx->cmdlist->RSSetScissorRects(1, &MAX_SCISSOR); 6267ec681f3Smrg } 6277ec681f3Smrg 6287ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_BLEND_COLOR) { 6297ec681f3Smrg unsigned blend_factor_flags = ctx->gfx_pipeline_state.blend->blend_factor_flags; 6307ec681f3Smrg if (blend_factor_flags & (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ANY)) { 6317ec681f3Smrg ctx->cmdlist->OMSetBlendFactor(ctx->blend_factor); 6327ec681f3Smrg } else if (blend_factor_flags & D3D12_BLEND_FACTOR_ALPHA) { 6337ec681f3Smrg float alpha_const[4] = { ctx->blend_factor[3], ctx->blend_factor[3], 6347ec681f3Smrg ctx->blend_factor[3], ctx->blend_factor[3] }; 6357ec681f3Smrg ctx->cmdlist->OMSetBlendFactor(alpha_const); 6367ec681f3Smrg } 6377ec681f3Smrg } 6387ec681f3Smrg 6397ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_STENCIL_REF) 6407ec681f3Smrg ctx->cmdlist->OMSetStencilRef(ctx->stencil_ref.ref_value[0]); 6417ec681f3Smrg 6427ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_PRIM_MODE) 6437ec681f3Smrg ctx->cmdlist->IASetPrimitiveTopology(topology((enum pipe_prim_type)dinfo->mode)); 6447ec681f3Smrg 6457ec681f3Smrg for (unsigned i = 0; i < ctx->num_vbs; ++i) { 6467ec681f3Smrg if (ctx->vbs[i].buffer.resource) { 6477ec681f3Smrg struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource); 6487ec681f3Smrg d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE); 6497ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) 6507ec681f3Smrg d3d12_batch_reference_resource(batch, res); 6517ec681f3Smrg } 6527ec681f3Smrg } 6537ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS) 6547ec681f3Smrg ctx->cmdlist->IASetVertexBuffers(0, ctx->num_vbs, ctx->vbvs); 6557ec681f3Smrg 6567ec681f3Smrg if (index_buffer) { 6577ec681f3Smrg D3D12_INDEX_BUFFER_VIEW ibv; 6587ec681f3Smrg struct d3d12_resource *res = d3d12_resource(index_buffer); 6597ec681f3Smrg ibv.BufferLocation = d3d12_resource_gpu_virtual_address(res) + index_offset; 6607ec681f3Smrg ibv.SizeInBytes = res->base.width0 - index_offset; 6617ec681f3Smrg ibv.Format = ib_format(dinfo->index_size); 6627ec681f3Smrg d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_INDEX_BUFFER, D3D12_BIND_INVALIDATE_NONE); 6637ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER || 6647ec681f3Smrg memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) { 6657ec681f3Smrg ctx->ibv = ibv; 6667ec681f3Smrg d3d12_batch_reference_resource(batch, res); 6677ec681f3Smrg ctx->cmdlist->IASetIndexBuffer(&ibv); 6687ec681f3Smrg } 6697ec681f3Smrg 6707ec681f3Smrg if (dinfo->has_user_indices) 6717ec681f3Smrg pipe_resource_reference(&index_buffer, NULL); 6727ec681f3Smrg } 6737ec681f3Smrg 6747ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_FRAMEBUFFER) { 6757ec681f3Smrg D3D12_CPU_DESCRIPTOR_HANDLE render_targets[PIPE_MAX_COLOR_BUFS] = {}; 6767ec681f3Smrg D3D12_CPU_DESCRIPTOR_HANDLE *depth_desc = NULL, tmp_desc; 6777ec681f3Smrg for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 6787ec681f3Smrg if (ctx->fb.cbufs[i]) { 6797ec681f3Smrg struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 6807ec681f3Smrg render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]); 6817ec681f3Smrg d3d12_batch_reference_surface_texture(batch, surface); 6827ec681f3Smrg } else 6837ec681f3Smrg render_targets[i] = screen->null_rtv.cpu_handle; 6847ec681f3Smrg } 6857ec681f3Smrg if (ctx->fb.zsbuf) { 6867ec681f3Smrg struct d3d12_surface *surface = d3d12_surface(ctx->fb.zsbuf); 6877ec681f3Smrg tmp_desc = surface->desc_handle.cpu_handle; 6887ec681f3Smrg d3d12_batch_reference_surface_texture(batch, surface); 6897ec681f3Smrg depth_desc = &tmp_desc; 6907ec681f3Smrg } 6917ec681f3Smrg ctx->cmdlist->OMSetRenderTargets(ctx->fb.nr_cbufs, render_targets, FALSE, depth_desc); 6927ec681f3Smrg } 6937ec681f3Smrg 6947ec681f3Smrg struct pipe_stream_output_target **so_targets = ctx->fake_so_buffer_factor ? ctx->fake_so_targets 6957ec681f3Smrg : ctx->so_targets; 6967ec681f3Smrg D3D12_STREAM_OUTPUT_BUFFER_VIEW *so_buffer_views = ctx->fake_so_buffer_factor ? ctx->fake_so_buffer_views 6977ec681f3Smrg : ctx->so_buffer_views; 6987ec681f3Smrg for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) { 6997ec681f3Smrg struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)so_targets[i]; 7007ec681f3Smrg 7017ec681f3Smrg if (!target) 7027ec681f3Smrg continue; 7037ec681f3Smrg 7047ec681f3Smrg struct d3d12_resource *so_buffer = d3d12_resource(target->base.buffer); 7057ec681f3Smrg struct d3d12_resource *fill_buffer = d3d12_resource(target->fill_buffer); 7067ec681f3Smrg 7077ec681f3Smrg d3d12_resource_make_writeable(pctx, target->base.buffer); 7087ec681f3Smrg 7097ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) { 7107ec681f3Smrg d3d12_batch_reference_resource(batch, so_buffer); 7117ec681f3Smrg d3d12_batch_reference_resource(batch, fill_buffer); 7127ec681f3Smrg } 7137ec681f3Smrg 7147ec681f3Smrg d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE); 7157ec681f3Smrg d3d12_transition_resource_state(ctx, fill_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE); 7167ec681f3Smrg } 7177ec681f3Smrg if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) 7187ec681f3Smrg ctx->cmdlist->SOSetTargets(0, 4, so_buffer_views); 7197ec681f3Smrg 7207ec681f3Smrg for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 7217ec681f3Smrg struct pipe_surface *psurf = ctx->fb.cbufs[i]; 7227ec681f3Smrg if (!psurf) 7237ec681f3Smrg continue; 7247ec681f3Smrg 7257ec681f3Smrg struct pipe_resource *pres = conversion_modes[i] == D3D12_SURFACE_CONVERSION_BGRA_UINT ? 7267ec681f3Smrg d3d12_surface(psurf)->rgba_texture : psurf->texture; 7277ec681f3Smrg transition_surface_subresources_state(ctx, psurf, pres, 7287ec681f3Smrg D3D12_RESOURCE_STATE_RENDER_TARGET); 7297ec681f3Smrg } 7307ec681f3Smrg if (ctx->fb.zsbuf) { 7317ec681f3Smrg struct pipe_surface *psurf = ctx->fb.zsbuf; 7327ec681f3Smrg transition_surface_subresources_state(ctx, psurf, psurf->texture, 7337ec681f3Smrg D3D12_RESOURCE_STATE_DEPTH_WRITE); 7347ec681f3Smrg } 7357ec681f3Smrg 7367ec681f3Smrg d3d12_apply_resource_states(ctx); 7377ec681f3Smrg 7387ec681f3Smrg for (unsigned i = 0; i < num_root_desciptors; ++i) 7397ec681f3Smrg ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]); 7407ec681f3Smrg 7417ec681f3Smrg if (dinfo->index_size > 0) 7427ec681f3Smrg ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count, 7437ec681f3Smrg draws[0].start, draws[0].index_bias, 7447ec681f3Smrg dinfo->start_instance); 7457ec681f3Smrg else 7467ec681f3Smrg ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count, 7477ec681f3Smrg draws[0].start, dinfo->start_instance); 7487ec681f3Smrg 7497ec681f3Smrg ctx->state_dirty = 0; 7507ec681f3Smrg 7517ec681f3Smrg if (index_buffer) 7527ec681f3Smrg ctx->cmdlist_dirty = 0; 7537ec681f3Smrg else 7547ec681f3Smrg ctx->cmdlist_dirty &= D3D12_DIRTY_INDEX_BUFFER; 7557ec681f3Smrg 7567ec681f3Smrg for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) 7577ec681f3Smrg ctx->shader_dirty[i] = 0; 7587ec681f3Smrg 7597ec681f3Smrg for (int i = 0; i < ctx->fb.nr_cbufs; ++i) { 7607ec681f3Smrg if (ctx->fb.cbufs[i]) { 7617ec681f3Smrg struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]); 7627ec681f3Smrg d3d12_surface_update_post_draw(surface, conversion_modes[i]); 7637ec681f3Smrg } 7647ec681f3Smrg } 7657ec681f3Smrg} 766