Path: blob/21.2-virgl/src/gallium/drivers/d3d12/d3d12_draw.cpp
4570 views
/*1* Copyright © Microsoft Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "d3d12_compiler.h"24#include "d3d12_context.h"25#include "d3d12_format.h"26#include "d3d12_query.h"27#include "d3d12_resource.h"28#include "d3d12_root_signature.h"29#include "d3d12_screen.h"30#include "d3d12_surface.h"3132#include "util/u_debug.h"33#include "util/u_draw.h"34#include "util/u_helpers.h"35#include "util/u_inlines.h"36#include "util/u_prim.h"37#include "util/u_prim_restart.h"38#include "util/u_math.h"3940extern "C" {41#include "indices/u_primconvert.h"42}4344static const D3D12_RECT MAX_SCISSOR = { D3D12_VIEWPORT_BOUNDS_MIN,45D3D12_VIEWPORT_BOUNDS_MIN,46D3D12_VIEWPORT_BOUNDS_MAX,47D3D12_VIEWPORT_BOUNDS_MAX };4849static D3D12_GPU_DESCRIPTOR_HANDLE50fill_cbv_descriptors(struct d3d12_context *ctx,51struct d3d12_shader *shader,52int stage)53{54struct d3d12_batch *batch = d3d12_current_batch(ctx);55struct d3d12_descriptor_handle table_start;56d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);5758for (unsigned i = 0; i < shader->num_cb_bindings; i++) {59unsigned binding = shader->cb_bindings[i].binding;60struct pipe_constant_buffer *buffer = &ctx->cbufs[stage][binding];6162D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {};63if (buffer && buffer->buffer) {64struct d3d12_resource *res = d3d12_resource(buffer->buffer);65d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE);66cbv_desc.BufferLocation = d3d12_resource_gpu_virtual_address(res) + buffer->buffer_offset;67cbv_desc.SizeInBytes = MIN2(D3D12_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16,68align(buffer->buffer_size, 256));69d3d12_batch_reference_resource(batch, res);70}7172struct d3d12_descriptor_handle handle;73d3d12_descriptor_heap_alloc_handle(batch->view_heap, &handle);74d3d12_screen(ctx->base.screen)->dev->CreateConstantBufferView(&cbv_desc, handle.cpu_handle);75}7677return table_start.gpu_handle;78}7980static D3D12_GPU_DESCRIPTOR_HANDLE81fill_srv_descriptors(struct d3d12_context *ctx,82struct d3d12_shader *shader,83unsigned stage)84{85struct d3d12_batch *batch = d3d12_current_batch(ctx);86struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);87D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];88struct d3d12_descriptor_handle table_start;8990d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start);9192for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)93{94struct d3d12_sampler_view *view;9596if (i == shader->pstipple_binding) {97view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view;98} else {99view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i];100}101102unsigned desc_idx = i - shader->begin_srv_binding;103if (view != NULL) {104descs[desc_idx] = view->handle.cpu_handle;105d3d12_batch_reference_sampler_view(batch, view);106107D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ?108D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE :109D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;110if (view->base.texture->target == PIPE_BUFFER) {111d3d12_transition_resource_state(ctx, d3d12_resource(view->base.texture),112state,113D3D12_BIND_INVALIDATE_NONE);114} else {115d3d12_transition_subresources_state(ctx, d3d12_resource(view->base.texture),116view->base.u.tex.first_level, view->mip_levels,117view->base.u.tex.first_layer, view->array_size,118d3d12_get_format_start_plane(view->base.format),119d3d12_get_format_num_planes(view->base.format),120state,121D3D12_BIND_INVALIDATE_NONE);122}123} else {124descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle;125}126}127128d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);129130return table_start.gpu_handle;131}132133static D3D12_GPU_DESCRIPTOR_HANDLE134fill_sampler_descriptors(struct d3d12_context *ctx,135const struct d3d12_shader_selector *shader_sel,136unsigned stage)137{138const struct d3d12_shader *shader = shader_sel->current;139struct d3d12_batch *batch = d3d12_current_batch(ctx);140D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];141struct d3d12_descriptor_handle table_start;142143d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start);144145for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)146{147struct d3d12_sampler_state *sampler;148149if (i == shader->pstipple_binding) {150sampler = ctx->pstipple.sampler_cso;151} else {152sampler = ctx->samplers[stage][i];153}154155unsigned desc_idx = i - shader->begin_srv_binding;156if (sampler != NULL) {157if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad)158descs[desc_idx] = sampler->handle_without_shadow.cpu_handle;159else160descs[desc_idx] = sampler->handle.cpu_handle;161} else162descs[desc_idx] = ctx->null_sampler.cpu_handle;163}164165d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);166return table_start.gpu_handle;167}168169static unsigned170fill_state_vars(struct d3d12_context *ctx,171const struct pipe_draw_info *dinfo,172const struct pipe_draw_start_count_bias *draw,173struct d3d12_shader *shader,174uint32_t *values)175{176unsigned size = 0;177178for (unsigned j = 0; j < shader->num_state_vars; ++j) {179uint32_t *ptr = values + size;180181switch (shader->state_vars[j].var) {182case D3D12_STATE_VAR_Y_FLIP:183ptr[0] = fui(ctx->flip_y);184size += 4;185break;186case D3D12_STATE_VAR_PT_SPRITE:187ptr[0] = fui(1.0 / ctx->viewports[0].Width);188ptr[1] = fui(1.0 / ctx->viewports[0].Height);189ptr[2] = fui(ctx->gfx_pipeline_state.rast->base.point_size);190ptr[3] = fui(D3D12_MAX_POINT_SIZE);191size += 4;192break;193case D3D12_STATE_VAR_FIRST_VERTEX:194ptr[0] = dinfo->index_size ? draw->index_bias : draw->start;195size += 4;196break;197case D3D12_STATE_VAR_DEPTH_TRANSFORM:198ptr[0] = fui(2.0f * ctx->viewport_states[0].scale[2]);199ptr[1] = fui(ctx->viewport_states[0].translate[2] - ctx->viewport_states[0].scale[2]);200size += 4;201break;202default:203unreachable("unknown state variable");204}205}206207return size;208}209210static bool211check_descriptors_left(struct d3d12_context *ctx)212{213struct d3d12_batch *batch = d3d12_current_batch(ctx);214unsigned needed_descs = 0;215216for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {217struct d3d12_shader_selector *shader = ctx->gfx_stages[i];218219if (!shader)220continue;221222needed_descs += shader->current->num_cb_bindings;223needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;224}225226if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs)227return false;228229needed_descs = 0;230for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {231struct d3d12_shader_selector *shader = ctx->gfx_stages[i];232233if (!shader)234continue;235236needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding;237}238239if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs)240return false;241242return true;243}244245#define MAX_DESCRIPTOR_TABLES (D3D12_GFX_SHADER_STAGES * 3)246247static unsigned248update_graphics_root_parameters(struct d3d12_context *ctx,249const struct pipe_draw_info *dinfo,250const struct pipe_draw_start_count_bias *draw,251D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES],252int root_desc_indices[MAX_DESCRIPTOR_TABLES])253{254unsigned num_params = 0;255unsigned num_root_desciptors = 0;256257for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {258if (!ctx->gfx_stages[i])259continue;260261struct d3d12_shader_selector *shader_sel = ctx->gfx_stages[i];262struct d3d12_shader *shader = shader_sel->current;263uint64_t dirty = ctx->shader_dirty[i];264assert(shader);265266if (shader->num_cb_bindings > 0) {267if (dirty & D3D12_SHADER_DIRTY_CONSTBUF) {268assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);269root_desc_tables[num_root_desciptors] = fill_cbv_descriptors(ctx, shader, i);270root_desc_indices[num_root_desciptors++] = num_params;271}272num_params++;273}274if (shader->end_srv_binding > 0) {275if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) {276assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);277root_desc_tables[num_root_desciptors] = fill_srv_descriptors(ctx, shader, i);278root_desc_indices[num_root_desciptors++] = num_params;279}280num_params++;281if (dirty & D3D12_SHADER_DIRTY_SAMPLERS) {282assert(num_root_desciptors < MAX_DESCRIPTOR_TABLES);283root_desc_tables[num_root_desciptors] = fill_sampler_descriptors(ctx, shader_sel, i);284root_desc_indices[num_root_desciptors++] = num_params;285}286num_params++;287}288/* TODO Don't always update state vars */289if (shader->num_state_vars > 0) {290uint32_t constants[D3D12_MAX_STATE_VARS * 4];291unsigned size = fill_state_vars(ctx, dinfo, draw, shader, constants);292ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0);293num_params++;294}295}296return num_root_desciptors;297}298299static bool300validate_stream_output_targets(struct d3d12_context *ctx)301{302unsigned factor = 0;303304if (ctx->gfx_pipeline_state.num_so_targets &&305ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY])306factor = ctx->gfx_pipeline_state.stages[PIPE_SHADER_GEOMETRY]->key.gs.stream_output_factor;307308if (factor > 1)309return d3d12_enable_fake_so_buffers(ctx, factor);310else311return d3d12_disable_fake_so_buffers(ctx);312}313314static D3D_PRIMITIVE_TOPOLOGY315topology(enum pipe_prim_type prim_type)316{317switch (prim_type) {318case PIPE_PRIM_POINTS:319return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;320321case PIPE_PRIM_LINES:322return D3D_PRIMITIVE_TOPOLOGY_LINELIST;323324case PIPE_PRIM_LINE_STRIP:325return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;326327case PIPE_PRIM_TRIANGLES:328return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;329330case PIPE_PRIM_TRIANGLE_STRIP:331return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;332333case PIPE_PRIM_LINES_ADJACENCY:334return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;335336case PIPE_PRIM_LINE_STRIP_ADJACENCY:337return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ;338339case PIPE_PRIM_TRIANGLES_ADJACENCY:340return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ;341342case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:343return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ;344345/*346case PIPE_PRIM_PATCHES:347return D3D_PRIMITIVE_TOPOLOGY_PATCHLIST;348*/349350case PIPE_PRIM_QUADS:351case PIPE_PRIM_QUAD_STRIP:352return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; /* HACK: this is just wrong! */353354default:355debug_printf("pipe_prim_type: %s\n", u_prim_name(prim_type));356unreachable("unexpected enum pipe_prim_type");357}358}359360static DXGI_FORMAT361ib_format(unsigned index_size)362{363switch (index_size) {364case 1: return DXGI_FORMAT_R8_UINT;365case 2: return DXGI_FORMAT_R16_UINT;366case 4: return DXGI_FORMAT_R32_UINT;367368default:369unreachable("unexpected index-buffer size");370}371}372373static void374twoface_emulation(struct d3d12_context *ctx,375struct d3d12_rasterizer_state *rast,376const struct pipe_draw_info *dinfo,377const struct pipe_draw_start_count_bias *draw)378{379/* draw backfaces */380ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back);381d3d12_draw_vbo(&ctx->base, dinfo, 0, NULL, draw, 1);382383/* restore real state */384ctx->base.bind_rasterizer_state(&ctx->base, rast);385}386387static void388transition_surface_subresources_state(struct d3d12_context *ctx,389struct pipe_surface *psurf,390struct pipe_resource *pres,391D3D12_RESOURCE_STATES state)392{393struct d3d12_resource *res = d3d12_resource(pres);394unsigned start_layer, num_layers;395if (!d3d12_subresource_id_uses_layer(res->base.target)) {396start_layer = 0;397num_layers = 1;398} else {399start_layer = psurf->u.tex.first_layer;400num_layers = psurf->u.tex.last_layer - psurf->u.tex.first_layer + 1;401}402d3d12_transition_subresources_state(ctx, res,403psurf->u.tex.level, 1,404start_layer, num_layers,405d3d12_get_format_start_plane(psurf->format),406d3d12_get_format_num_planes(psurf->format),407state,408D3D12_BIND_INVALIDATE_FULL);409}410411static bool412prim_supported(enum pipe_prim_type prim_type)413{414switch (prim_type) {415case PIPE_PRIM_POINTS:416case PIPE_PRIM_LINES:417case PIPE_PRIM_LINE_STRIP:418case PIPE_PRIM_TRIANGLES:419case PIPE_PRIM_TRIANGLE_STRIP:420case PIPE_PRIM_LINES_ADJACENCY:421case PIPE_PRIM_LINE_STRIP_ADJACENCY:422case PIPE_PRIM_TRIANGLES_ADJACENCY:423case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:424return true;425426default:427return false;428}429}430431static inline struct d3d12_shader_selector *432d3d12_last_vertex_stage(struct d3d12_context *ctx)433{434struct d3d12_shader_selector *sel = ctx->gfx_stages[PIPE_SHADER_GEOMETRY];435if (!sel || sel->is_gs_variant)436sel = ctx->gfx_stages[PIPE_SHADER_VERTEX];437return sel;438}439440void441d3d12_draw_vbo(struct pipe_context *pctx,442const struct pipe_draw_info *dinfo,443unsigned drawid_offset,444const struct pipe_draw_indirect_info *indirect,445const struct pipe_draw_start_count_bias *draws,446unsigned num_draws)447{448if (num_draws > 1) {449util_draw_multi(pctx, dinfo, drawid_offset, indirect, draws, num_draws);450return;451}452453if (!indirect && (!draws[0].count || !dinfo->instance_count))454return;455456struct d3d12_context *ctx = d3d12_context(pctx);457struct d3d12_screen *screen = d3d12_screen(pctx->screen);458struct d3d12_batch *batch;459struct pipe_resource *index_buffer = NULL;460unsigned index_offset = 0;461enum d3d12_surface_conversion_mode conversion_modes[PIPE_MAX_COLOR_BUFS] = {};462463if (!prim_supported(dinfo->mode) ||464dinfo->index_size == 1 ||465(dinfo->primitive_restart && dinfo->restart_index != 0xffff &&466dinfo->restart_index != 0xffffffff)) {467468if (!dinfo->primitive_restart &&469!u_trim_pipe_prim(dinfo->mode, (unsigned *)&draws[0].count))470return;471472ctx->initial_api_prim = dinfo->mode;473util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base);474util_primconvert_draw_vbo(ctx->primconvert, dinfo, drawid_offset, indirect, draws, num_draws);475return;476}477478for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {479if (ctx->fb.cbufs[i]) {480struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);481conversion_modes[i] = d3d12_surface_update_pre_draw(surface, d3d12_rtv_format(ctx, i));482if (conversion_modes[i] != D3D12_SURFACE_CONVERSION_NONE)483ctx->cmdlist_dirty |= D3D12_DIRTY_FRAMEBUFFER;484}485}486487struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast;488if (rast->twoface_back) {489enum pipe_prim_type saved_mode = ctx->initial_api_prim;490twoface_emulation(ctx, rast, dinfo, &draws[0]);491ctx->initial_api_prim = saved_mode;492}493494if (ctx->pstipple.enabled)495ctx->shader_dirty[PIPE_SHADER_FRAGMENT] |= D3D12_SHADER_DIRTY_SAMPLER_VIEWS |496D3D12_SHADER_DIRTY_SAMPLERS;497498/* this should *really* be fixed at a higher level than here! */499enum pipe_prim_type reduced_prim = u_reduced_prim(dinfo->mode);500if (reduced_prim == PIPE_PRIM_TRIANGLES &&501ctx->gfx_pipeline_state.rast->base.cull_face == PIPE_FACE_FRONT_AND_BACK)502return;503504if (ctx->gfx_pipeline_state.prim_type != dinfo->mode) {505ctx->gfx_pipeline_state.prim_type = dinfo->mode;506ctx->state_dirty |= D3D12_DIRTY_PRIM_MODE;507}508509d3d12_select_shader_variants(ctx, dinfo);510d3d12_validate_queries(ctx);511for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i) {512struct d3d12_shader *shader = ctx->gfx_stages[i] ? ctx->gfx_stages[i]->current : NULL;513if (ctx->gfx_pipeline_state.stages[i] != shader) {514ctx->gfx_pipeline_state.stages[i] = shader;515ctx->state_dirty |= D3D12_DIRTY_SHADER;516}517}518519/* Reset to an invalid value after it's been used */520ctx->initial_api_prim = PIPE_PRIM_MAX;521522/* Copy the stream output info from the current vertex/geometry shader */523if (ctx->state_dirty & D3D12_DIRTY_SHADER) {524struct d3d12_shader_selector *sel = d3d12_last_vertex_stage(ctx);525if (sel) {526ctx->gfx_pipeline_state.so_info = sel->so_info;527} else {528memset(&ctx->gfx_pipeline_state.so_info, 0, sizeof(sel->so_info));529}530}531if (!validate_stream_output_targets(ctx)) {532debug_printf("validate_stream_output_targets() failed\n");533return;534}535536D3D12_INDEX_BUFFER_STRIP_CUT_VALUE ib_strip_cut_value =537D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;538if (dinfo->index_size > 0) {539assert(dinfo->index_size != 1);540541if (dinfo->has_user_indices) {542if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer,543&index_offset, 4)) {544debug_printf("util_upload_index_buffer() failed\n");545return;546}547} else {548index_buffer = dinfo->index.resource;549}550551if (dinfo->primitive_restart) {552assert(dinfo->restart_index == 0xffff ||553dinfo->restart_index == 0xffffffff);554ib_strip_cut_value = dinfo->restart_index == 0xffff ?555D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF :556D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;557}558}559560if (ctx->gfx_pipeline_state.ib_strip_cut_value != ib_strip_cut_value) {561ctx->gfx_pipeline_state.ib_strip_cut_value = ib_strip_cut_value;562ctx->state_dirty |= D3D12_DIRTY_STRIP_CUT_VALUE;563}564565if (!ctx->gfx_pipeline_state.root_signature || ctx->state_dirty & D3D12_DIRTY_SHADER) {566ID3D12RootSignature *root_signature = d3d12_get_root_signature(ctx);567if (ctx->gfx_pipeline_state.root_signature != root_signature) {568ctx->gfx_pipeline_state.root_signature = root_signature;569ctx->state_dirty |= D3D12_DIRTY_ROOT_SIGNATURE;570for (int i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)571ctx->shader_dirty[i] |= D3D12_SHADER_DIRTY_ALL;572}573}574575if (!ctx->current_pso || ctx->state_dirty & D3D12_DIRTY_PSO) {576ctx->current_pso = d3d12_get_gfx_pipeline_state(ctx);577assert(ctx->current_pso);578}579580ctx->cmdlist_dirty |= ctx->state_dirty;581582if (!check_descriptors_left(ctx))583d3d12_flush_cmdlist(ctx);584batch = d3d12_current_batch(ctx);585586if (ctx->cmdlist_dirty & D3D12_DIRTY_ROOT_SIGNATURE) {587d3d12_batch_reference_object(batch, ctx->gfx_pipeline_state.root_signature);588ctx->cmdlist->SetGraphicsRootSignature(ctx->gfx_pipeline_state.root_signature);589}590591if (ctx->cmdlist_dirty & D3D12_DIRTY_PSO) {592assert(ctx->current_pso);593d3d12_batch_reference_object(batch, ctx->current_pso);594ctx->cmdlist->SetPipelineState(ctx->current_pso);595}596597D3D12_GPU_DESCRIPTOR_HANDLE root_desc_tables[MAX_DESCRIPTOR_TABLES];598int root_desc_indices[MAX_DESCRIPTOR_TABLES];599unsigned num_root_desciptors = update_graphics_root_parameters(ctx, dinfo, &draws[0], root_desc_tables, root_desc_indices);600601bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx);602if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) {603ctx->cmdlist_dirty |= D3D12_DIRTY_VIEWPORT;604ctx->need_zero_one_depth_range = need_zero_one_depth_range;605}606607if (ctx->cmdlist_dirty & D3D12_DIRTY_VIEWPORT) {608if (ctx->need_zero_one_depth_range) {609D3D12_VIEWPORT viewports[PIPE_MAX_VIEWPORTS];610for (unsigned i = 0; i < ctx->num_viewports; ++i) {611viewports[i] = ctx->viewports[i];612viewports[i].MinDepth = 0.0f;613viewports[i].MaxDepth = 1.0f;614}615ctx->cmdlist->RSSetViewports(ctx->num_viewports, viewports);616} else617ctx->cmdlist->RSSetViewports(ctx->num_viewports, ctx->viewports);618}619620if (ctx->cmdlist_dirty & D3D12_DIRTY_SCISSOR) {621if (ctx->gfx_pipeline_state.rast->base.scissor && ctx->num_viewports > 0)622ctx->cmdlist->RSSetScissorRects(ctx->num_viewports, ctx->scissors);623else624ctx->cmdlist->RSSetScissorRects(1, &MAX_SCISSOR);625}626627if (ctx->cmdlist_dirty & D3D12_DIRTY_BLEND_COLOR) {628unsigned blend_factor_flags = ctx->gfx_pipeline_state.blend->blend_factor_flags;629if (blend_factor_flags & (D3D12_BLEND_FACTOR_COLOR | D3D12_BLEND_FACTOR_ANY)) {630ctx->cmdlist->OMSetBlendFactor(ctx->blend_factor);631} else if (blend_factor_flags & D3D12_BLEND_FACTOR_ALPHA) {632float alpha_const[4] = { ctx->blend_factor[3], ctx->blend_factor[3],633ctx->blend_factor[3], ctx->blend_factor[3] };634ctx->cmdlist->OMSetBlendFactor(alpha_const);635}636}637638if (ctx->cmdlist_dirty & D3D12_DIRTY_STENCIL_REF)639ctx->cmdlist->OMSetStencilRef(ctx->stencil_ref.ref_value[0]);640641if (ctx->cmdlist_dirty & D3D12_DIRTY_PRIM_MODE)642ctx->cmdlist->IASetPrimitiveTopology(topology(dinfo->mode));643644for (unsigned i = 0; i < ctx->num_vbs; ++i) {645if (ctx->vbs[i].buffer.resource) {646struct d3d12_resource *res = d3d12_resource(ctx->vbs[i].buffer.resource);647d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_BIND_INVALIDATE_NONE);648if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)649d3d12_batch_reference_resource(batch, res);650}651}652if (ctx->cmdlist_dirty & D3D12_DIRTY_VERTEX_BUFFERS)653ctx->cmdlist->IASetVertexBuffers(0, ctx->num_vbs, ctx->vbvs);654655if (index_buffer) {656D3D12_INDEX_BUFFER_VIEW ibv;657struct d3d12_resource *res = d3d12_resource(index_buffer);658ibv.BufferLocation = d3d12_resource_gpu_virtual_address(res) + index_offset;659ibv.SizeInBytes = res->base.width0 - index_offset;660ibv.Format = ib_format(dinfo->index_size);661d3d12_transition_resource_state(ctx, res, D3D12_RESOURCE_STATE_INDEX_BUFFER, D3D12_BIND_INVALIDATE_NONE);662if (ctx->cmdlist_dirty & D3D12_DIRTY_INDEX_BUFFER ||663memcmp(&ctx->ibv, &ibv, sizeof(D3D12_INDEX_BUFFER_VIEW)) != 0) {664ctx->ibv = ibv;665d3d12_batch_reference_resource(batch, res);666ctx->cmdlist->IASetIndexBuffer(&ibv);667}668669if (dinfo->has_user_indices)670pipe_resource_reference(&index_buffer, NULL);671}672673if (ctx->cmdlist_dirty & D3D12_DIRTY_FRAMEBUFFER) {674D3D12_CPU_DESCRIPTOR_HANDLE render_targets[PIPE_MAX_COLOR_BUFS] = {};675D3D12_CPU_DESCRIPTOR_HANDLE *depth_desc = NULL, tmp_desc;676for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {677if (ctx->fb.cbufs[i]) {678struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);679render_targets[i] = d3d12_surface_get_handle(surface, conversion_modes[i]);680d3d12_batch_reference_surface_texture(batch, surface);681} else682render_targets[i] = screen->null_rtv.cpu_handle;683}684if (ctx->fb.zsbuf) {685struct d3d12_surface *surface = d3d12_surface(ctx->fb.zsbuf);686tmp_desc = surface->desc_handle.cpu_handle;687d3d12_batch_reference_surface_texture(batch, surface);688depth_desc = &tmp_desc;689}690ctx->cmdlist->OMSetRenderTargets(ctx->fb.nr_cbufs, render_targets, FALSE, depth_desc);691}692693struct pipe_stream_output_target **so_targets = ctx->fake_so_buffer_factor ? ctx->fake_so_targets694: ctx->so_targets;695D3D12_STREAM_OUTPUT_BUFFER_VIEW *so_buffer_views = ctx->fake_so_buffer_factor ? ctx->fake_so_buffer_views696: ctx->so_buffer_views;697for (unsigned i = 0; i < ctx->gfx_pipeline_state.num_so_targets; ++i) {698struct d3d12_stream_output_target *target = (struct d3d12_stream_output_target *)so_targets[i];699700if (!target)701continue;702703struct d3d12_resource *so_buffer = d3d12_resource(target->base.buffer);704struct d3d12_resource *fill_buffer = d3d12_resource(target->fill_buffer);705706d3d12_resource_make_writeable(pctx, target->base.buffer);707708if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT) {709d3d12_batch_reference_resource(batch, so_buffer);710d3d12_batch_reference_resource(batch, fill_buffer);711}712713d3d12_transition_resource_state(ctx, so_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE);714d3d12_transition_resource_state(ctx, fill_buffer, D3D12_RESOURCE_STATE_STREAM_OUT, D3D12_BIND_INVALIDATE_NONE);715}716if (ctx->cmdlist_dirty & D3D12_DIRTY_STREAM_OUTPUT)717ctx->cmdlist->SOSetTargets(0, 4, so_buffer_views);718719for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {720struct pipe_surface *psurf = ctx->fb.cbufs[i];721if (!psurf)722continue;723724struct pipe_resource *pres = conversion_modes[i] == D3D12_SURFACE_CONVERSION_BGRA_UINT ?725d3d12_surface(psurf)->rgba_texture : psurf->texture;726transition_surface_subresources_state(ctx, psurf, pres,727D3D12_RESOURCE_STATE_RENDER_TARGET);728}729if (ctx->fb.zsbuf) {730struct pipe_surface *psurf = ctx->fb.zsbuf;731transition_surface_subresources_state(ctx, psurf, psurf->texture,732D3D12_RESOURCE_STATE_DEPTH_WRITE);733}734735d3d12_apply_resource_states(ctx);736737for (unsigned i = 0; i < num_root_desciptors; ++i)738ctx->cmdlist->SetGraphicsRootDescriptorTable(root_desc_indices[i], root_desc_tables[i]);739740if (dinfo->index_size > 0)741ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count,742draws[0].start, draws[0].index_bias,743dinfo->start_instance);744else745ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count,746draws[0].start, dinfo->start_instance);747748ctx->state_dirty = 0;749750if (index_buffer)751ctx->cmdlist_dirty = 0;752else753ctx->cmdlist_dirty &= D3D12_DIRTY_INDEX_BUFFER;754755for (unsigned i = 0; i < D3D12_GFX_SHADER_STAGES; ++i)756ctx->shader_dirty[i] = 0;757758for (int i = 0; i < ctx->fb.nr_cbufs; ++i) {759if (ctx->fb.cbufs[i]) {760struct d3d12_surface *surface = d3d12_surface(ctx->fb.cbufs[i]);761d3d12_surface_update_post_draw(surface, conversion_modes[i]);762}763}764}765766767