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