Home | History | Annotate | Line # | Download | only in d3d12
      1 /*
      2  * Copyright  Microsoft Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  */
     23 
     24 #include "d3d12_compiler.h"
     25 #include "d3d12_context.h"
     26 #include "d3d12_format.h"
     27 #include "d3d12_query.h"
     28 #include "d3d12_resource.h"
     29 #include "d3d12_root_signature.h"
     30 #include "d3d12_screen.h"
     31 #include "d3d12_surface.h"
     32 
     33 #include "util/u_debug.h"
     34 #include "util/u_draw.h"
     35 #include "util/u_helpers.h"
     36 #include "util/u_inlines.h"
     37 #include "util/u_prim.h"
     38 #include "util/u_prim_restart.h"
     39 #include "util/u_math.h"
     40 
     41 extern "C" {
     42 #include "indices/u_primconvert.h"
     43 }
     44 
     45 static const D3D12_RECT MAX_SCISSOR = { D3D12_VIEWPORT_BOUNDS_MIN,
     46                                         D3D12_VIEWPORT_BOUNDS_MIN,
     47                                         D3D12_VIEWPORT_BOUNDS_MAX,
     48                                         D3D12_VIEWPORT_BOUNDS_MAX };
     49 
     50 static D3D12_GPU_DESCRIPTOR_HANDLE
     51 fill_cbv_descriptors(struct d3d12_context *ctx,
     52                      struct d3d12_shader *shader,
     53                      int stage)
     54 {
     55    struct d3d12_batch *batch = d3d12_current_batch(ctx);
     56    struct d3d12_descriptor_handle table_start;
     57    d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
     58 
     59    for (unsigned i = 0; i < shader->num_cb_bindings; i++) {
     60       unsigned binding = shader->cb_bindings[i].binding;
     61       struct pipe_constant_buffer *buffer = &ctx->cbufs[stage][binding];
     62 
     63       D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {};
     64       if (buffer && buffer->buffer) {
     65          struct d3d12_resource *res = d3d12_resource(buffer->buffer);
     66          d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE);
     67          cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset;
     68          cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16,
     69             align(buffer->buffer_size, 256));
     70          d3d12_batch_reference_resource(batch, res);
     71       }
     72 
     73       struct d3d12_descriptor_handle handle;
     74       d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle);
     75       d3d12_screen(ctx->base.screen)->dev->CreateConstantBufferView(&cbv_desc, handle.cpu_handle);
     76    }
     77 
     78    return table_start.gpu_handle;
     79 }
     80 
     81 static D3D12_GPU_DESCRIPTOR_HANDLE
     82 fill_srv_descriptors(struct d3d12_context *ctx,
     83                      struct d3d12_shader *shader,
     84                      unsigned stage)
     85 {
     86    struct d3d12_batch *batch = d3d12_current_batch(ctx);
     87    struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
     88    D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
     89    struct d3d12_descriptor_handle table_start;
     90 
     91    d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);
     92 
     93    for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)
     94    {
     95       struct d3d12_sampler_view *view;
     96 
     97       if (i == shader->pstipple_binding) {
     98          view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view;
     99       } else {
    100          view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i];
    101       }
    102 
    103       unsigned desc_idx = i - shader->begin_srv_binding;
    104       if (view != NULL) {
    105          descs[desc_idx] = view->handle.cpu_handle;
    106          d3d12_batch_reference_sampler_view(batch, view);
    107 
    108          D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ?
    109                                        D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE :
    110                                        D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
    111          if (view->base.texture->target == PIPE_BUFFER) {
    112             d3d12_transition_resource_state(ctx, d3d12_resource(view->base.texture),
    113                                             state,
    114                                             D3D12_BIND_INVALIDATE_NONE);
    115          } else {
    116             d3d12_transition_subresources_state(ctx, d3d12_resource(view->base.texture),
    117                                                 view->base.u.tex.first_level, view->mip_levels,
    118                                                 view->base.u.tex.first_layer, view->array_size,
    119                                                 d3d12_get_format_start_plane(view->base.format),
    120                                                 d3d12_get_format_num_planes(view->base.format),
    121                                                 state,
    122                                                 D3D12_BIND_INVALIDATE_NONE);
    123          }
    124       } else {
    125          descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle;
    126       }
    127    }
    128 
    129    d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);
    130 
    131    return table_start.gpu_handle;
    132 }
    133 
    134 static D3D12_GPU_DESCRIPTOR_HANDLE
    135 fill_sampler_descriptors(struct d3d12_context *ctx,
    136                          const struct d3d12_shader_selector *shader_sel,
    137                          unsigned stage)
    138 {
    139    const struct d3d12_shader *shader = shader_sel->current;
    140    struct d3d12_batch *batch = d3d12_current_batch(ctx);
    141    D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
    142    struct d3d12_descriptor_handle table_start;
    143 
    144    d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start);
    145 
    146    for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)
    147    {
    148       struct d3d12_sampler_state *sampler;
    149 
    150       if (i == shader->pstipple_binding) {
    151          sampler = ctx->pstipple.sampler_cso;
    152       } else {
    153          sampler = ctx->samplers[stage][i];
    154       }
    155 
    156       unsigned desc_idx = i - shader->begin_srv_binding;
    157       if (sampler != NULL) {
    158          if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad)
    159             descs[desc_idx] = sampler->handle_without_shadow.cpu_handle;
    160          else
    161             descs[desc_idx] = sampler->handle.cpu_handle;
    162       } else
    163          descs[desc_idx] = ctx->null_sampler.cpu_handle;
    164    }
    165 
    166    d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);
    167    return table_start.gpu_handle;
    168 }
    169 
    170 static unsigned
    171 fill_state_vars(struct d3d12_context *ctx,
    172                 const struct pipe_draw_info *dinfo,
    173                 const struct pipe_draw_start_count_bias *draw,
    174                 struct d3d12_shader *shader,
    175                 uint32_t *values)
    176 {
    177    unsigned size = 0;
    178 
    179    for (unsigned j = 0; j < shader->num_state_vars; ++j) {
    180       uint32_t *ptr = values + size;
    181 
    182       switch (shader->state_vars[j].var) {
    183       case D3D12_STATE_VAR_Y_FLIP:
    184          ptr[0] = fui(ctx->flip_y);
    185          size += 4;
    186          break;
    187       case D3D12_STATE_VAR_PT_SPRITE:
    188          ptr[0] = fui(1.0 / ctx->viewports[0].Width);
    189          ptr[1] = fui(1.0 / ctx->viewports[0].Height);
    190          ptr[2] = fui(ctx->gfx_pipeline_state.rast->base.point_size);
    191          ptr[3] = fui(D3D12_MAX_POINT_SIZE);
    192          size += 4;
    193          break;
    194       case D3D12_STATE_VAR_FIRST_VERTEX:
    195          ptr[0] = dinfo->index_size ? draw->index_bias : draw->start;
    196          size += 4;
    197          break;
    198       case D3D12_STATE_VAR_DEPTH_TRANSFORM:
    199          ptr[0] = fui(2.0f * ctx->viewport_states[0].scale[2]);
    200          ptr[1] = fui(ctx->viewport_states[0].translate[2] - ctx->viewport_states[0].scale[2]);
    201          size += 4;
    202          break;
    203       default:
    204          unreachable("unknown state variable");
    205       }
    206    }
    207 
    208    return size;
    209 }
    210 
    211 static bool
    212 check_descriptors_left(struct d3d12_context *ctx)
    213 {
    214    struct d3d12_batch *batch = d3d12_current_batch(ctx);
    215    unsigned needed_descs = 0;
    216 
    217    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
    218       struct d3d12_shader_selector *shader = ctx->gfx_stages[i];
    219 
    220       if (!shader)
    221          continue;
    222 
    223       needed_descs += shader->current->num_cb_bindings;
    224       needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;
    225    }
    226 
    227    if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs)
    228       return false;
    229 
    230    needed_descs = 0;
    231    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
    232       struct d3d12_shader_selector *shader = ctx->gfx_stages[i];
    233 
    234       if (!shader)
    235          continue;
    236 
    237       needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;
    238    }
    239 
    240    if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs)
    241       return false;
    242 
    243    return true;
    244 }
    245 
    246 #define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 3)
    247 
    248 static unsigned
    249 update_graphics_root_parameters(struct d3d12_context *ctx,
    250                                 const struct pipe_draw_info *dinfo,
    251                                 const struct pipe_draw_start_count_bias *draw,
    252                                 D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],
    253                                 int root_desc_indices[MAX_DESCRIPTOR_TABLES])
    254 {
    255    unsigned num_params = 0;
    256    unsigned num_root_desciptors = 0;
    257 
    258    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
    259       if (!ctx->gfx_stages[i])
    260          continue;
    261 
    262       struct d3d12_shader_selector *shader_sel = ctx->gfx_stages[i];
    263       struct d3d12_shader *shader = shader_sel->current;
    264       uint64_t dirty = ctx->shader_dirty[i];
    265       assert(shader);
    266 
    267       if (shader->num_cb_bindings > 0) {
    268          if (dirty & D3D12_SHADER_DIRTY_CONSTBUF) {
    269             assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);
    270             root_desc_tables[num_root_desciptors] = fill_cbv_descriptors(ctx, shader, i);
    271             root_desc_indices[num_root_desciptors++] = num_params;
    272          }
    273          num_params++;
    274       }
    275       if (shader->end_srv_binding > 0) {
    276          if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) {
    277             assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);
    278             root_desc_tables[num_root_desciptors] = fill_srv_descriptors(ctx, shader, i);
    279             root_desc_indices[num_root_desciptors++] = num_params;
    280          }
    281          num_params++;
    282          if (dirty & D3D12_SHADER_DIRTY_SAMPLERS) {
    283             assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);
    284             root_desc_tables[num_root_desciptors] = fill_sampler_descriptors(ctx, shader_sel, i);
    285             root_desc_indices[num_root_desciptors++] = num_params;
    286          }
    287          num_params++;
    288       }
    289       /* TODO Don't always update state vars */
    290       if (shader->num_state_vars > 0) {
    291          uint32_t constants[D3D12_MAX_STATE_VARS * 4];
    292          unsigned size = fill_state_vars(ctx, dinfo, draw, shader, constants);
    293          ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0);
    294          num_params++;
    295       }
    296    }
    297    return num_root_desciptors;
    298 }
    299 
    300 static bool
    301 validate_stream_output_targets(struct d3d12_context *ctx)
    302 {
    303    unsigned factor = 0;
    304 
    305    if (ctx->gfx_pipeline_state.num_so_targets &&
    306        ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY])
    307       factor = ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]->key.gs.stream_output_factor;
    308 
    309    if (factor > 1)
    310       return d3d12_enable_fake_so_buffers(ctx, factor);
    311    else
    312       return d3d12_disable_fake_so_buffers(ctx);
    313 }
    314 
    315 static D3D_PRIMITIVE_TOPOLOGY
    316 topology(enum pipe_prim_type prim_type)
    317 {
    318    switch (prim_type) {
    319    case PIPE_PRIM_POINTS:
    320       return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
    321 
    322    case PIPE_PRIM_LINES:
    323       return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
    324 
    325    case PIPE_PRIM_LINE_STRIP:
    326       return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
    327 
    328    case PIPE_PRIM_TRIANGLES:
    329       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
    330 
    331    case PIPE_PRIM_TRIANGLE_STRIP:
    332       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
    333 
    334    case PIPE_PRIM_LINES_ADJACENCY:
    335       return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
    336 
    337    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
    338       return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;
    339 
    340    case PIPE_PRIM_TRIANGLES_ADJACENCY:
    341       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;
    342 
    343    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
    344       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;
    345 
    346 /*
    347    case PIPE_PRIM_PATCHES:
    348       return D3D_PRIMITIVE_TOPOLOGY_PATCHLIST;
    349 */
    350 
    351    case PIPE_PRIM_QUADS:
    352    case PIPE_PRIM_QUAD_STRIP:
    353       return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; /* HACK: this is just wrong! */
    354 
    355    default:
    356       debug_printf("pipe_prim_type: %s\n", u_prim_name(prim_type));
    357       unreachable("unexpected enum pipe_prim_type");
    358    }
    359 }
    360 
    361 static DXGI_FORMAT
    362 ib_format(unsigned index_size)
    363 {
    364    switch (index_size) {
    365    case 1: return DXGI_FORMAT_R8_UINT;
    366    case 2: return DXGI_FORMAT_R16_UINT;
    367    case 4: return DXGI_FORMAT_R32_UINT;
    368 
    369    default:
    370       unreachable("unexpected index-buffer size");
    371    }
    372 }
    373 
    374 static void
    375 twoface_emulation(struct d3d12_context *ctx,
    376                   struct d3d12_rasterizer_state *rast,
    377                   const struct pipe_draw_info *dinfo,
    378                   const struct pipe_draw_start_count_bias *draw)
    379 {
    380    /* draw backfaces */
    381    ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back);
    382    d3d12_draw_vbo(&ctx->base, dinfo, 0, NULL, draw, 1);
    383 
    384    /* restore real state */
    385    ctx->base.bind_rasterizer_state(&ctx->base, rast);
    386 }
    387 
    388 static void
    389 transition_surface_subresources_state(struct d3d12_context *ctx,
    390                                       struct pipe_surface *psurf,
    391                                       struct pipe_resource *pres,
    392                                       D3D12_RESOURCE_STATES state)
    393 {
    394    struct d3d12_resource *res = d3d12_resource(pres);
    395    unsigned start_layer, num_layers;
    396    if (!d3d12_subresource_id_uses_layer(res->base.target)) {
    397       start_layer = 0;
    398       num_layers = 1;
    399    } else {
    400       start_layer = psurf->u.tex.first_layer;
    401       num_layers = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;
    402    }
    403    d3d12_transition_subresources_state(ctx, res,
    404                                        psurf->u.tex.level, 1,
    405                                        start_layer, num_layers,
    406                                        d3d12_get_format_start_plane(psurf->format),
    407                                        d3d12_get_format_num_planes(psurf->format),
    408                                        state,
    409                                        D3D12_BIND_INVALIDATE_FULL);
    410 }
    411 
    412 static bool
    413 prim_supported(enum pipe_prim_type prim_type)
    414 {
    415    switch (prim_type) {
    416    case PIPE_PRIM_POINTS:
    417    case PIPE_PRIM_LINES:
    418    case PIPE_PRIM_LINE_STRIP:
    419    case PIPE_PRIM_TRIANGLES:
    420    case PIPE_PRIM_TRIANGLE_STRIP:
    421    case PIPE_PRIM_LINES_ADJACENCY:
    422    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
    423    case PIPE_PRIM_TRIANGLES_ADJACENCY:
    424    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
    425       return true;
    426 
    427    default:
    428       return false;
    429    }
    430 }
    431 
    432 static inline struct d3d12_shader_selector *
    433 d3d12_last_vertex_stage(struct d3d12_context *ctx)
    434 {
    435    struct d3d12_shader_selector *sel = ctx->gfx_stages[PIPE_SHADER_GEOMETRY];
    436    if (!sel || sel->is_gs_variant)
    437       sel = ctx->gfx_stages[PIPE_SHADER_VERTEX];
    438    return sel;
    439 }
    440 
    441 void
    442 d3d12_draw_vbo(struct pipe_context *pctx,
    443                const struct pipe_draw_info *dinfo,
    444                unsigned drawid_offset,
    445                const struct pipe_draw_indirect_info *indirect,
    446                const struct pipe_draw_start_count_bias *draws,
    447                unsigned num_draws)
    448 {
    449    if (num_draws > 1) {
    450       util_draw_multi(pctx, dinfo, drawid_offset, indirect, draws, num_draws);
    451       return;
    452    }
    453 
    454    if (!indirect && (!draws[0].count || !dinfo->instance_count))
    455       return;
    456 
    457    struct d3d12_context *ctx = d3d12_context(pctx);
    458    struct d3d12_screen *screen = d3d12_screen(pctx->screen);
    459    struct d3d12_batch *batch;
    460    struct pipe_resource *index_buffer = NULL;
    461    unsigned index_offset = 0;
    462    enum d3d12_surface_conversion_mode conversion_modes[PIPE_MAX_COLOR_BUFS] = {};
    463 
    464    if (!prim_supported((enum pipe_prim_type)dinfo->mode) ||
    465        dinfo->index_size == 1 ||
    466        (dinfo->primitive_restart && dinfo->restart_index != 0xffff &&
    467         dinfo->restart_index != 0xffffffff)) {
    468 
    469       if (!dinfo->primitive_restart &&
    470           !u_trim_pipe_prim((enum pipe_prim_type)dinfo->mode, (unsigned *)&draws[0].count))
    471          return;
    472 
    473       ctx->initial_api_prim = (enum pipe_prim_type)dinfo->mode;
    474       util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base);
    475       util_primconvert_draw_vbo(ctx->primconvert, dinfo, drawid_offset, indirect, draws, num_draws);
    476       return;
    477    }
    478 
    479    for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
    480       if (ctx->fb.cbufs[i]) {
    481          struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
    482          conversion_modes[i] = d3d12_surface_update_pre_draw(surface, d3d12_rtv_format(ctx, i));
    483          if (conversion_modes[i] != D3D12_SURFACE_CONVERSION_NONE)
    484             ctx->cmdlist_dirty |= D3D12_DIRTY_FRAMEBUFFER;
    485       }
    486    }
    487 
    488    struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast;
    489    if (rast->twoface_back) {
    490       enum pipe_prim_type saved_mode = ctx->initial_api_prim;
    491       twoface_emulation(ctx, rast, dinfo, &draws[0]);
    492       ctx->initial_api_prim = saved_mode;
    493    }
    494 
    495    if (ctx->pstipple.enabled)
    496       ctx->shader_dirty[PIPE_SHADER_FRAGMENT] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS |
    497                                                  D3D12_SHADER_DIRTY_SAMPLERS;
    498 
    499    /* this should *really* be fixed at a higher level than here! */
    500    enum pipe_prim_type reduced_prim = u_reduced_prim((enum pipe_prim_type)dinfo->mode);
    501    if (reduced_prim == PIPE_PRIM_TRIANGLES &&
    502        ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT_AND_BACK)
    503       return;
    504 
    505    if (ctx->gfx_pipeline_state.prim_type != dinfo->mode) {
    506       ctx->gfx_pipeline_state.prim_type = (enum pipe_prim_type)dinfo->mode;
    507       ctx->state_dirty |= D3D12_DIRTY_PRIM_MODE;
    508    }
    509 
    510    d3d12_select_shader_variants(ctx, dinfo);
    511    d3d12_validate_queries(ctx);
    512    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {
    513       struct d3d12_shader *shader = ctx->gfx_stages[i] ? ctx->gfx_stages[i]->current : NULL;
    514       if (ctx->gfx_pipeline_state.stages[i] != shader) {
    515          ctx->gfx_pipeline_state.stages[i] = shader;
    516          ctx->state_dirty |= D3D12_DIRTY_SHADER;
    517       }
    518    }
    519 
    520    /* Reset to an invalid value after it's been used */
    521    ctx->initial_api_prim = PIPE_PRIM_MAX;
    522 
    523    /* Copy the stream output info from the current vertex/geometry shader */
    524    if (ctx->state_dirty & D3D12_DIRTY_SHADER) {
    525       struct d3d12_shader_selector *sel = d3d12_last_vertex_stage(ctx);
    526       if (sel) {
    527          ctx->gfx_pipeline_state.so_info = sel->so_info;
    528       } else {
    529          memset(&ctx->gfx_pipeline_state.so_info, 0, sizeof(sel->so_info));
    530       }
    531    }
    532    if (!validate_stream_output_targets(ctx)) {
    533       debug_printf("validate_stream_output_targets() failed\n");
    534       return;
    535    }
    536 
    537    D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value =
    538       D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
    539    if (dinfo->index_size > 0) {
    540       assert(dinfo->index_size != 1);
    541 
    542       if (dinfo->has_user_indices) {
    543          if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer,
    544              &index_offset, 4)) {
    545             debug_printf("util_upload_index_buffer() failed\n");
    546             return;
    547          }
    548       } else {
    549          index_buffer = dinfo->index.resource;
    550       }
    551 
    552       if (dinfo->primitive_restart) {
    553          assert(dinfo->restart_index == 0xffff ||
    554                 dinfo->restart_index == 0xffffffff);
    555          ib_strip_cut_value = dinfo->restart_index == 0xffff ?
    556             D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF :
    557             D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
    558       }
    559    }
    560 
    561    if (ctx->gfx_pipeline_state.ib_strip_cut_value != ib_strip_cut_value) {
    562       ctx->gfx_pipeline_state.ib_strip_cut_value = ib_strip_cut_value;
    563       ctx->state_dirty |= D3D12_DIRTY_STRIP_CUT_VALUE;
    564    }
    565 
    566    if (!ctx->gfx_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_SHADER) {
    567       ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx);
    568       if (ctx->gfx_pipeline_state.root_signature != root_signature) {
    569          ctx->gfx_pipeline_state.root_signature = root_signature;
    570          ctx->state_dirty |= D3D12_DIRTY_ROOT_SIGNATURE;
    571          for (int i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)
    572             ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_ALL;
    573       }
    574    }
    575 
    576    if (!ctx->current_pso || ctx->state_dirty & D3D12_DIRTY_PSO) {
    577       ctx->current_pso = d3d12_get_gfx_pipeline_state(ctx);
    578       assert(ctx->current_pso);
    579    }
    580 
    581    ctx->cmdlist_dirty |= ctx->state_dirty;
    582 
    583    if (!check_descriptors_left(ctx))
    584       d3d12_flush_cmdlist(ctx);
    585    batch = d3d12_current_batch(ctx);
    586 
    587    if (ctx->cmdlist_dirty & D3D12_DIRTY_ROOT_SIGNATURE) {
    588       d3d12_batch_reference_object(batch, ctx->gfx_pipeline_state.root_signature);
    589       ctx->cmdlist->SetGraphicsRootSignature(ctx->gfx_pipeline_state.root_signature);
    590    }
    591 
    592    if (ctx->cmdlist_dirty & D3D12_DIRTY_PSO) {
    593       assert(ctx->current_pso);
    594       d3d12_batch_reference_object(batch, ctx->current_pso);
    595       ctx->cmdlist->SetPipelineState(ctx->current_pso);
    596    }
    597 
    598    D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES];
    599    int root_desc_indices[MAX_DESCRIPTOR_TABLES];
    600    unsigned num_root_desciptors = update_graphics_root_parameters(ctx, dinfo, &draws[0], root_desc_tables, root_desc_indices);
    601 
    602    bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx);
    603    if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) {
    604       ctx->cmdlist_dirty |= D3D12_DIRTY_VIEWPORT;
    605       ctx->need_zero_one_depth_range = need_zero_one_depth_range;
    606    }
    607 
    608    if (ctx->cmdlist_dirty & D3D12_DIRTY_VIEWPORT) {
    609       if (ctx->need_zero_one_depth_range) {
    610          D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS];
    611          for (unsigned i = 0; i < ctx->num_viewports; ++i) {
    612             viewports[i] = ctx->viewports[i];
    613             viewports[i].MinDepth = 0.0f;
    614             viewports[i].MaxDepth = 1.0f;
    615          }
    616          ctx->cmdlist->RSSetViewports(ctx->num_viewports, viewports);
    617       } else
    618          ctx->cmdlist->RSSetViewports(ctx->num_viewports, ctx->viewports);
    619    }
    620 
    621    if (ctx->cmdlist_dirty & D3D12_DIRTY_SCISSOR) {
    622       if (ctx->gfx_pipeline_state.rast->base.scissor && ctx->num_viewports > 0)
    623          ctx->cmdlist->RSSetScissorRects(ctx->num_viewports, ctx->scissors);
    624       else
    625          ctx->cmdlist->RSSetScissorRects(1, &MAX_SCISSOR);
    626    }
    627 
    628    if (ctx->cmdlist_dirty & D3D12_DIRTY_BLEND_COLOR) {
    629       unsigned blend_factor_flags = ctx->gfx_pipeline_state.blend->blend_factor_flags;
    630       if (blend_factor_flags & (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ANY)) {
    631          ctx->cmdlist->OMSetBlendFactor(ctx->blend_factor);
    632       } else if (blend_factor_flags & D3D12_BLEND_FACTOR_ALPHA) {
    633          float alpha_const[4] = { ctx->blend_factor[3], ctx->blend_factor[3],
    634                                  ctx->blend_factor[3], ctx->blend_factor[3] };
    635          ctx->cmdlist->OMSetBlendFactor(alpha_const);
    636       }
    637    }
    638 
    639    if (ctx->cmdlist_dirty & D3D12_DIRTY_STENCIL_REF)
    640       ctx->cmdlist->OMSetStencilRef(ctx->stencil_ref.ref_value[0]);
    641 
    642    if (ctx->cmdlist_dirty & D3D12_DIRTY_PRIM_MODE)
    643       ctx->cmdlist->IASetPrimitiveTopology(topology((enum pipe_prim_type)dinfo->mode));
    644 
    645    for (unsigned i = 0; i < ctx->num_vbs; ++i) {
    646       if (ctx->vbs[i].buffer.resource) {
    647          struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource);
    648          d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE);
    649          if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)
    650             d3d12_batch_reference_resource(batch, res);
    651       }
    652    }
    653    if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)
    654       ctx->cmdlist->IASetVertexBuffers(0, ctx->num_vbs, ctx->vbvs);
    655 
    656    if (index_buffer) {
    657       D3D12_INDEX_BUFFER_VIEW ibv;
    658       struct d3d12_resource *res = d3d12_resource(index_buffer);
    659       ibv.BufferLocation = d3d12_resource_gpu_virtual_address(res) + index_offset;
    660       ibv.SizeInBytes = res->base.width0 - index_offset;
    661       ibv.Format = ib_format(dinfo->index_size);
    662       d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_INDEX_BUFFER, D3D12_BIND_INVALIDATE_NONE);
    663       if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER ||
    664           memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) {
    665          ctx->ibv = ibv;
    666          d3d12_batch_reference_resource(batch, res);
    667          ctx->cmdlist->IASetIndexBuffer(&ibv);
    668       }
    669 
    670       if (dinfo->has_user_indices)
    671          pipe_resource_reference(&index_buffer, NULL);
    672    }
    673 
    674    if (ctx->cmdlist_dirty & D3D12_DIRTY_FRAMEBUFFER) {
    675       D3D12_CPU_DESCRIPTOR_HANDLE render_targets[PIPE_MAX_COLOR_BUFS] = {};
    676       D3D12_CPU_DESCRIPTOR_HANDLE *depth_desc = NULL, tmp_desc;
    677       for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
    678          if (ctx->fb.cbufs[i]) {
    679             struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
    680             render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]);
    681             d3d12_batch_reference_surface_texture(batch, surface);
    682          } else
    683             render_targets[i] = screen->null_rtv.cpu_handle;
    684       }
    685       if (ctx->fb.zsbuf) {
    686          struct d3d12_surface *surface = d3d12_surface(ctx->fb.zsbuf);
    687          tmp_desc = surface->desc_handle.cpu_handle;
    688          d3d12_batch_reference_surface_texture(batch, surface);
    689          depth_desc = &tmp_desc;
    690       }
    691       ctx->cmdlist->OMSetRenderTargets(ctx->fb.nr_cbufs, render_targets, FALSE, depth_desc);
    692    }
    693 
    694    struct pipe_stream_output_target **so_targets = ctx->fake_so_buffer_factor ? ctx->fake_so_targets
    695                                                                               : ctx->so_targets;
    696    D3D12_STREAM_OUTPUT_BUFFER_VIEW *so_buffer_views = ctx->fake_so_buffer_factor ? ctx->fake_so_buffer_views
    697                                                                                  : ctx->so_buffer_views;
    698    for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) {
    699       struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)so_targets[i];
    700 
    701       if (!target)
    702          continue;
    703 
    704       struct d3d12_resource *so_buffer = d3d12_resource(target->base.buffer);
    705       struct d3d12_resource *fill_buffer = d3d12_resource(target->fill_buffer);
    706 
    707       d3d12_resource_make_writeable(pctx, target->base.buffer);
    708 
    709       if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) {
    710          d3d12_batch_reference_resource(batch, so_buffer);
    711          d3d12_batch_reference_resource(batch, fill_buffer);
    712       }
    713 
    714       d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE);
    715       d3d12_transition_resource_state(ctx, fill_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE);
    716    }
    717    if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT)
    718       ctx->cmdlist->SOSetTargets(0, 4, so_buffer_views);
    719 
    720    for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
    721       struct pipe_surface *psurf = ctx->fb.cbufs[i];
    722       if (!psurf)
    723          continue;
    724 
    725       struct pipe_resource *pres = conversion_modes[i] == D3D12_SURFACE_CONVERSION_BGRA_UINT ?
    726                                       d3d12_surface(psurf)->rgba_texture : psurf->texture;
    727       transition_surface_subresources_state(ctx, psurf, pres,
    728          D3D12_RESOURCE_STATE_RENDER_TARGET);
    729    }
    730    if (ctx->fb.zsbuf) {
    731       struct pipe_surface *psurf = ctx->fb.zsbuf;
    732       transition_surface_subresources_state(ctx, psurf, psurf->texture,
    733          D3D12_RESOURCE_STATE_DEPTH_WRITE);
    734    }
    735 
    736    d3d12_apply_resource_states(ctx);
    737 
    738    for (unsigned i = 0; i < num_root_desciptors; ++i)
    739       ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]);
    740 
    741    if (dinfo->index_size > 0)
    742       ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count,
    743                                          draws[0].start, draws[0].index_bias,
    744                                          dinfo->start_instance);
    745    else
    746       ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count,
    747                                   draws[0].start, dinfo->start_instance);
    748 
    749    ctx->state_dirty = 0;
    750 
    751    if (index_buffer)
    752       ctx->cmdlist_dirty = 0;
    753    else
    754       ctx->cmdlist_dirty &= D3D12_DIRTY_INDEX_BUFFER;
    755 
    756    for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)
    757       ctx->shader_dirty[i] = 0;
    758 
    759    for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {
    760       if (ctx->fb.cbufs[i]) {
    761          struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);
    762          d3d12_surface_update_post_draw(surface, conversion_modes[i]);
    763       }
    764    }
    765 }
    766