1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "d3d12_pipeline_state.h" 25bf215546Sopenharmony_ci#include "d3d12_compiler.h" 26bf215546Sopenharmony_ci#include "d3d12_context.h" 27bf215546Sopenharmony_ci#include "d3d12_screen.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "util/hash_table.h" 30bf215546Sopenharmony_ci#include "util/set.h" 31bf215546Sopenharmony_ci#include "util/u_memory.h" 32bf215546Sopenharmony_ci#include "util/u_prim.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include <dxguids/dxguids.h> 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_cistruct d3d12_gfx_pso_entry { 37bf215546Sopenharmony_ci struct d3d12_gfx_pipeline_state key; 38bf215546Sopenharmony_ci ID3D12PipelineState *pso; 39bf215546Sopenharmony_ci}; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistruct d3d12_compute_pso_entry { 42bf215546Sopenharmony_ci struct d3d12_compute_pipeline_state key; 43bf215546Sopenharmony_ci ID3D12PipelineState *pso; 44bf215546Sopenharmony_ci}; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistatic const char * 47bf215546Sopenharmony_ciget_semantic_name(int location, int driver_location, unsigned *index) 48bf215546Sopenharmony_ci{ 49bf215546Sopenharmony_ci *index = 0; /* Default index */ 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci switch (location) { 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci case VARYING_SLOT_POS: 54bf215546Sopenharmony_ci return "SV_Position"; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci case VARYING_SLOT_FACE: 57bf215546Sopenharmony_ci return "SV_IsFrontFace"; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci case VARYING_SLOT_CLIP_DIST1: 60bf215546Sopenharmony_ci *index = 1; 61bf215546Sopenharmony_ci FALLTHROUGH; 62bf215546Sopenharmony_ci case VARYING_SLOT_CLIP_DIST0: 63bf215546Sopenharmony_ci return "SV_ClipDistance"; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci case VARYING_SLOT_PRIMITIVE_ID: 66bf215546Sopenharmony_ci return "SV_PrimitiveID"; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci case VARYING_SLOT_VIEWPORT: 69bf215546Sopenharmony_ci return "SV_ViewportArrayIndex"; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci case VARYING_SLOT_LAYER: 72bf215546Sopenharmony_ci return "SV_RenderTargetArrayIndex"; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci default: { 75bf215546Sopenharmony_ci *index = driver_location; 76bf215546Sopenharmony_ci return "TEXCOORD"; 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic nir_variable * 82bf215546Sopenharmony_cifind_so_variable(nir_shader *s, int location, unsigned location_frac, unsigned num_components) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci nir_foreach_variable_with_modes(var, s, nir_var_shader_out) { 85bf215546Sopenharmony_ci if (var->data.location != location || var->data.location_frac > location_frac) 86bf215546Sopenharmony_ci continue; 87bf215546Sopenharmony_ci unsigned var_num_components = var->data.compact ? 88bf215546Sopenharmony_ci glsl_get_length(var->type) : glsl_get_components(var->type); 89bf215546Sopenharmony_ci if (var->data.location_frac <= location_frac && 90bf215546Sopenharmony_ci var->data.location_frac + var_num_components >= location_frac + num_components) 91bf215546Sopenharmony_ci return var; 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci return nullptr; 94bf215546Sopenharmony_ci} 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_cistatic void 97bf215546Sopenharmony_cifill_so_declaration(const struct pipe_stream_output_info *info, 98bf215546Sopenharmony_ci nir_shader *last_vertex_stage, 99bf215546Sopenharmony_ci D3D12_SO_DECLARATION_ENTRY *entries, UINT *num_entries, 100bf215546Sopenharmony_ci UINT *strides, UINT *num_strides) 101bf215546Sopenharmony_ci{ 102bf215546Sopenharmony_ci int next_offset[MAX_VERTEX_STREAMS] = { 0 }; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci *num_entries = 0; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci for (unsigned i = 0; i < info->num_outputs; i++) { 107bf215546Sopenharmony_ci const struct pipe_stream_output *output = &info->output[i]; 108bf215546Sopenharmony_ci const int buffer = output->output_buffer; 109bf215546Sopenharmony_ci unsigned index; 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci /* Mesa doesn't store entries for gl_SkipComponents in the Outputs[] 112bf215546Sopenharmony_ci * array. Instead, it simply increments DstOffset for the following 113bf215546Sopenharmony_ci * input by the number of components that should be skipped. 114bf215546Sopenharmony_ci * 115bf215546Sopenharmony_ci * DirectX12 requires that we create gap entries. 116bf215546Sopenharmony_ci */ 117bf215546Sopenharmony_ci int skip_components = output->dst_offset - next_offset[buffer]; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci if (skip_components > 0) { 120bf215546Sopenharmony_ci entries[*num_entries].Stream = output->stream; 121bf215546Sopenharmony_ci entries[*num_entries].SemanticName = NULL; 122bf215546Sopenharmony_ci entries[*num_entries].ComponentCount = skip_components; 123bf215546Sopenharmony_ci entries[*num_entries].OutputSlot = buffer; 124bf215546Sopenharmony_ci (*num_entries)++; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci next_offset[buffer] = output->dst_offset + output->num_components; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci entries[*num_entries].Stream = output->stream; 130bf215546Sopenharmony_ci nir_variable *var = find_so_variable(last_vertex_stage, 131bf215546Sopenharmony_ci output->register_index, output->start_component, output->num_components); 132bf215546Sopenharmony_ci assert((var->data.stream & ~NIR_STREAM_PACKED) == output->stream); 133bf215546Sopenharmony_ci entries[*num_entries].SemanticName = get_semantic_name(var->data.location, 134bf215546Sopenharmony_ci var->data.driver_location, &index); 135bf215546Sopenharmony_ci entries[*num_entries].SemanticIndex = index; 136bf215546Sopenharmony_ci entries[*num_entries].StartComponent = output->start_component - var->data.location_frac; 137bf215546Sopenharmony_ci entries[*num_entries].ComponentCount = output->num_components; 138bf215546Sopenharmony_ci entries[*num_entries].OutputSlot = buffer; 139bf215546Sopenharmony_ci (*num_entries)++; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci for (unsigned i = 0; i < MAX_VERTEX_STREAMS; i++) 143bf215546Sopenharmony_ci strides[i] = info->stride[i] * 4; 144bf215546Sopenharmony_ci *num_strides = MAX_VERTEX_STREAMS; 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_cistatic bool 148bf215546Sopenharmony_cidepth_bias(struct d3d12_rasterizer_state *state, enum pipe_prim_type reduced_prim) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci /* glPolygonOffset is supposed to be only enabled when rendering polygons. 151bf215546Sopenharmony_ci * In d3d12 case, all polygons (and quads) are lowered to triangles */ 152bf215546Sopenharmony_ci if (reduced_prim != PIPE_PRIM_TRIANGLES) 153bf215546Sopenharmony_ci return false; 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci unsigned fill_mode = state->base.cull_face == PIPE_FACE_FRONT ? state->base.fill_back 156bf215546Sopenharmony_ci : state->base.fill_front; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci switch (fill_mode) { 159bf215546Sopenharmony_ci case PIPE_POLYGON_MODE_FILL: 160bf215546Sopenharmony_ci return state->base.offset_tri; 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci case PIPE_POLYGON_MODE_LINE: 163bf215546Sopenharmony_ci return state->base.offset_line; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci case PIPE_POLYGON_MODE_POINT: 166bf215546Sopenharmony_ci return state->base.offset_point; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci default: 169bf215546Sopenharmony_ci unreachable("unexpected fill mode"); 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_cistatic D3D12_PRIMITIVE_TOPOLOGY_TYPE 174bf215546Sopenharmony_citopology_type(enum pipe_prim_type reduced_prim) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci switch (reduced_prim) { 177bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 178bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 181bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES: 184bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci case PIPE_PRIM_PATCHES: 187bf215546Sopenharmony_ci return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci default: 190bf215546Sopenharmony_ci debug_printf("pipe_prim_type: %s\n", u_prim_name(reduced_prim)); 191bf215546Sopenharmony_ci unreachable("unexpected enum pipe_prim_type"); 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci} 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ciDXGI_FORMAT 196bf215546Sopenharmony_cid3d12_rtv_format(struct d3d12_context *ctx, unsigned index) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci DXGI_FORMAT fmt = ctx->gfx_pipeline_state.rtv_formats[index]; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.blend->desc.RenderTarget[0].LogicOpEnable && 201bf215546Sopenharmony_ci !ctx->gfx_pipeline_state.has_float_rtv) { 202bf215546Sopenharmony_ci switch (fmt) { 203bf215546Sopenharmony_ci case DXGI_FORMAT_R8G8B8A8_SNORM: 204bf215546Sopenharmony_ci case DXGI_FORMAT_R8G8B8A8_UNORM: 205bf215546Sopenharmony_ci case DXGI_FORMAT_B8G8R8A8_UNORM: 206bf215546Sopenharmony_ci case DXGI_FORMAT_B8G8R8X8_UNORM: 207bf215546Sopenharmony_ci return DXGI_FORMAT_R8G8B8A8_UINT; 208bf215546Sopenharmony_ci default: 209bf215546Sopenharmony_ci unreachable("unsupported logic-op format"); 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci } 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci return fmt; 214bf215546Sopenharmony_ci} 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_cistatic ID3D12PipelineState * 217bf215546Sopenharmony_cicreate_gfx_pipeline_state(struct d3d12_context *ctx) 218bf215546Sopenharmony_ci{ 219bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 220bf215546Sopenharmony_ci struct d3d12_gfx_pipeline_state *state = &ctx->gfx_pipeline_state; 221bf215546Sopenharmony_ci enum pipe_prim_type reduced_prim = state->prim_type == PIPE_PRIM_PATCHES ? 222bf215546Sopenharmony_ci PIPE_PRIM_PATCHES : u_reduced_prim(state->prim_type); 223bf215546Sopenharmony_ci D3D12_SO_DECLARATION_ENTRY entries[PIPE_MAX_SO_OUTPUTS] = {}; 224bf215546Sopenharmony_ci UINT strides[PIPE_MAX_SO_OUTPUTS] = { 0 }; 225bf215546Sopenharmony_ci UINT num_entries = 0, num_strides = 0; 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = { 0 }; 228bf215546Sopenharmony_ci pso_desc.pRootSignature = state->root_signature; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci nir_shader *last_vertex_stage_nir = NULL; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci if (state->stages[PIPE_SHADER_VERTEX]) { 233bf215546Sopenharmony_ci auto shader = state->stages[PIPE_SHADER_VERTEX]; 234bf215546Sopenharmony_ci pso_desc.VS.BytecodeLength = shader->bytecode_length; 235bf215546Sopenharmony_ci pso_desc.VS.pShaderBytecode = shader->bytecode; 236bf215546Sopenharmony_ci last_vertex_stage_nir = shader->nir; 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci if (state->stages[PIPE_SHADER_TESS_CTRL]) { 240bf215546Sopenharmony_ci auto shader = state->stages[PIPE_SHADER_TESS_CTRL]; 241bf215546Sopenharmony_ci pso_desc.HS.BytecodeLength = shader->bytecode_length; 242bf215546Sopenharmony_ci pso_desc.HS.pShaderBytecode = shader->bytecode; 243bf215546Sopenharmony_ci last_vertex_stage_nir = shader->nir; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci if (state->stages[PIPE_SHADER_TESS_EVAL]) { 247bf215546Sopenharmony_ci auto shader = state->stages[PIPE_SHADER_TESS_EVAL]; 248bf215546Sopenharmony_ci pso_desc.DS.BytecodeLength = shader->bytecode_length; 249bf215546Sopenharmony_ci pso_desc.DS.pShaderBytecode = shader->bytecode; 250bf215546Sopenharmony_ci last_vertex_stage_nir = shader->nir; 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if (state->stages[PIPE_SHADER_GEOMETRY]) { 254bf215546Sopenharmony_ci auto shader = state->stages[PIPE_SHADER_GEOMETRY]; 255bf215546Sopenharmony_ci pso_desc.GS.BytecodeLength = shader->bytecode_length; 256bf215546Sopenharmony_ci pso_desc.GS.pShaderBytecode = shader->bytecode; 257bf215546Sopenharmony_ci last_vertex_stage_nir = shader->nir; 258bf215546Sopenharmony_ci } 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci bool last_vertex_stage_writes_pos = (last_vertex_stage_nir->info.outputs_written & VARYING_BIT_POS) != 0; 261bf215546Sopenharmony_ci if (last_vertex_stage_writes_pos && state->stages[PIPE_SHADER_FRAGMENT] && 262bf215546Sopenharmony_ci !state->rast->base.rasterizer_discard) { 263bf215546Sopenharmony_ci auto shader = state->stages[PIPE_SHADER_FRAGMENT]; 264bf215546Sopenharmony_ci pso_desc.PS.BytecodeLength = shader->bytecode_length; 265bf215546Sopenharmony_ci pso_desc.PS.pShaderBytecode = shader->bytecode; 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci if (state->num_so_targets) 269bf215546Sopenharmony_ci fill_so_declaration(&state->so_info, last_vertex_stage_nir, entries, &num_entries, strides, &num_strides); 270bf215546Sopenharmony_ci pso_desc.StreamOutput.NumEntries = num_entries; 271bf215546Sopenharmony_ci pso_desc.StreamOutput.pSODeclaration = entries; 272bf215546Sopenharmony_ci pso_desc.StreamOutput.RasterizedStream = state->rast->base.rasterizer_discard ? D3D12_SO_NO_RASTERIZED_STREAM : 0; 273bf215546Sopenharmony_ci pso_desc.StreamOutput.NumStrides = num_strides; 274bf215546Sopenharmony_ci pso_desc.StreamOutput.pBufferStrides = strides; 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci pso_desc.BlendState = state->blend->desc; 277bf215546Sopenharmony_ci if (state->has_float_rtv) 278bf215546Sopenharmony_ci pso_desc.BlendState.RenderTarget[0].LogicOpEnable = FALSE; 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci pso_desc.DepthStencilState = state->zsa->desc; 281bf215546Sopenharmony_ci pso_desc.SampleMask = state->sample_mask; 282bf215546Sopenharmony_ci pso_desc.RasterizerState = state->rast->desc; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci if (reduced_prim != PIPE_PRIM_TRIANGLES) 285bf215546Sopenharmony_ci pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci if (depth_bias(state->rast, reduced_prim)) { 288bf215546Sopenharmony_ci pso_desc.RasterizerState.DepthBias = state->rast->base.offset_units * 2; 289bf215546Sopenharmony_ci pso_desc.RasterizerState.DepthBiasClamp = state->rast->base.offset_clamp; 290bf215546Sopenharmony_ci pso_desc.RasterizerState.SlopeScaledDepthBias = state->rast->base.offset_scale; 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci pso_desc.InputLayout.pInputElementDescs = state->ves->elements; 294bf215546Sopenharmony_ci pso_desc.InputLayout.NumElements = state->ves->num_elements; 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci pso_desc.IBStripCutValue = state->ib_strip_cut_value; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci pso_desc.PrimitiveTopologyType = topology_type(reduced_prim); 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci pso_desc.NumRenderTargets = state->num_cbufs; 301bf215546Sopenharmony_ci for (unsigned i = 0; i < state->num_cbufs; ++i) 302bf215546Sopenharmony_ci pso_desc.RTVFormats[i] = d3d12_rtv_format(ctx, i); 303bf215546Sopenharmony_ci pso_desc.DSVFormat = state->dsv_format; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci if (state->num_cbufs || state->dsv_format != DXGI_FORMAT_UNKNOWN) { 306bf215546Sopenharmony_ci pso_desc.SampleDesc.Count = state->samples; 307bf215546Sopenharmony_ci if (!state->zsa->desc.DepthEnable && 308bf215546Sopenharmony_ci !state->zsa->desc.StencilEnable && 309bf215546Sopenharmony_ci !state->rast->desc.MultisampleEnable && 310bf215546Sopenharmony_ci state->samples > 1) { 311bf215546Sopenharmony_ci pso_desc.RasterizerState.ForcedSampleCount = 1; 312bf215546Sopenharmony_ci pso_desc.DSVFormat = DXGI_FORMAT_UNKNOWN; 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci } else if (state->samples > 1) { 315bf215546Sopenharmony_ci pso_desc.SampleDesc.Count = 1; 316bf215546Sopenharmony_ci pso_desc.RasterizerState.ForcedSampleCount = state->samples; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci pso_desc.SampleDesc.Quality = 0; 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci pso_desc.NodeMask = 0; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci pso_desc.CachedPSO.pCachedBlob = NULL; 323bf215546Sopenharmony_ci pso_desc.CachedPSO.CachedBlobSizeInBytes = 0; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci pso_desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci ID3D12PipelineState *ret; 328bf215546Sopenharmony_ci if (FAILED(screen->dev->CreateGraphicsPipelineState(&pso_desc, 329bf215546Sopenharmony_ci IID_PPV_ARGS(&ret)))) { 330bf215546Sopenharmony_ci debug_printf("D3D12: CreateGraphicsPipelineState failed!\n"); 331bf215546Sopenharmony_ci return NULL; 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci return ret; 335bf215546Sopenharmony_ci} 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_cistatic uint32_t 338bf215546Sopenharmony_cihash_gfx_pipeline_state(const void *key) 339bf215546Sopenharmony_ci{ 340bf215546Sopenharmony_ci return _mesa_hash_data(key, sizeof(struct d3d12_gfx_pipeline_state)); 341bf215546Sopenharmony_ci} 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_cistatic bool 344bf215546Sopenharmony_ciequals_gfx_pipeline_state(const void *a, const void *b) 345bf215546Sopenharmony_ci{ 346bf215546Sopenharmony_ci return memcmp(a, b, sizeof(struct d3d12_gfx_pipeline_state)) == 0; 347bf215546Sopenharmony_ci} 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ciID3D12PipelineState * 350bf215546Sopenharmony_cid3d12_get_gfx_pipeline_state(struct d3d12_context *ctx) 351bf215546Sopenharmony_ci{ 352bf215546Sopenharmony_ci uint32_t hash = hash_gfx_pipeline_state(&ctx->gfx_pipeline_state); 353bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ctx->pso_cache, hash, 354bf215546Sopenharmony_ci &ctx->gfx_pipeline_state); 355bf215546Sopenharmony_ci if (!entry) { 356bf215546Sopenharmony_ci struct d3d12_gfx_pso_entry *data = (struct d3d12_gfx_pso_entry *)MALLOC(sizeof(struct d3d12_gfx_pso_entry)); 357bf215546Sopenharmony_ci if (!data) 358bf215546Sopenharmony_ci return NULL; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci data->key = ctx->gfx_pipeline_state; 361bf215546Sopenharmony_ci data->pso = create_gfx_pipeline_state(ctx); 362bf215546Sopenharmony_ci if (!data->pso) { 363bf215546Sopenharmony_ci FREE(data); 364bf215546Sopenharmony_ci return NULL; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci entry = _mesa_hash_table_insert_pre_hashed(ctx->pso_cache, hash, &data->key, data); 368bf215546Sopenharmony_ci assert(entry); 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci return ((struct d3d12_gfx_pso_entry *)(entry->data))->pso; 372bf215546Sopenharmony_ci} 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_civoid 375bf215546Sopenharmony_cid3d12_gfx_pipeline_state_cache_init(struct d3d12_context *ctx) 376bf215546Sopenharmony_ci{ 377bf215546Sopenharmony_ci ctx->pso_cache = _mesa_hash_table_create(NULL, NULL, equals_gfx_pipeline_state); 378bf215546Sopenharmony_ci} 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_cistatic void 381bf215546Sopenharmony_cidelete_gfx_entry(struct hash_entry *entry) 382bf215546Sopenharmony_ci{ 383bf215546Sopenharmony_ci struct d3d12_gfx_pso_entry *data = (struct d3d12_gfx_pso_entry *)entry->data; 384bf215546Sopenharmony_ci data->pso->Release(); 385bf215546Sopenharmony_ci FREE(data); 386bf215546Sopenharmony_ci} 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_cistatic void 389bf215546Sopenharmony_ciremove_gfx_entry(struct d3d12_context *ctx, struct hash_entry *entry) 390bf215546Sopenharmony_ci{ 391bf215546Sopenharmony_ci struct d3d12_gfx_pso_entry *data = (struct d3d12_gfx_pso_entry *)entry->data; 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci if (ctx->current_gfx_pso == data->pso) 394bf215546Sopenharmony_ci ctx->current_gfx_pso = NULL; 395bf215546Sopenharmony_ci _mesa_hash_table_remove(ctx->pso_cache, entry); 396bf215546Sopenharmony_ci delete_gfx_entry(entry); 397bf215546Sopenharmony_ci} 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_civoid 400bf215546Sopenharmony_cid3d12_gfx_pipeline_state_cache_destroy(struct d3d12_context *ctx) 401bf215546Sopenharmony_ci{ 402bf215546Sopenharmony_ci _mesa_hash_table_destroy(ctx->pso_cache, delete_gfx_entry); 403bf215546Sopenharmony_ci} 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_civoid 406bf215546Sopenharmony_cid3d12_gfx_pipeline_state_cache_invalidate(struct d3d12_context *ctx, const void *state) 407bf215546Sopenharmony_ci{ 408bf215546Sopenharmony_ci hash_table_foreach(ctx->pso_cache, entry) { 409bf215546Sopenharmony_ci const struct d3d12_gfx_pipeline_state *key = (struct d3d12_gfx_pipeline_state *)entry->key; 410bf215546Sopenharmony_ci if (key->blend == state || key->zsa == state || key->rast == state) 411bf215546Sopenharmony_ci remove_gfx_entry(ctx, entry); 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci} 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_civoid 416bf215546Sopenharmony_cid3d12_gfx_pipeline_state_cache_invalidate_shader(struct d3d12_context *ctx, 417bf215546Sopenharmony_ci enum pipe_shader_type stage, 418bf215546Sopenharmony_ci struct d3d12_shader_selector *selector) 419bf215546Sopenharmony_ci{ 420bf215546Sopenharmony_ci struct d3d12_shader *shader = selector->first; 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci while (shader) { 423bf215546Sopenharmony_ci hash_table_foreach(ctx->pso_cache, entry) { 424bf215546Sopenharmony_ci const struct d3d12_gfx_pipeline_state *key = (struct d3d12_gfx_pipeline_state *)entry->key; 425bf215546Sopenharmony_ci if (key->stages[stage] == shader) 426bf215546Sopenharmony_ci remove_gfx_entry(ctx, entry); 427bf215546Sopenharmony_ci } 428bf215546Sopenharmony_ci shader = shader->next_variant; 429bf215546Sopenharmony_ci } 430bf215546Sopenharmony_ci} 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_cistatic ID3D12PipelineState * 433bf215546Sopenharmony_cicreate_compute_pipeline_state(struct d3d12_context *ctx) 434bf215546Sopenharmony_ci{ 435bf215546Sopenharmony_ci struct d3d12_screen *screen = d3d12_screen(ctx->base.screen); 436bf215546Sopenharmony_ci struct d3d12_compute_pipeline_state *state = &ctx->compute_pipeline_state; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci D3D12_COMPUTE_PIPELINE_STATE_DESC pso_desc = { 0 }; 439bf215546Sopenharmony_ci pso_desc.pRootSignature = state->root_signature; 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci if (state->stage) { 442bf215546Sopenharmony_ci auto shader = state->stage; 443bf215546Sopenharmony_ci pso_desc.CS.BytecodeLength = shader->bytecode_length; 444bf215546Sopenharmony_ci pso_desc.CS.pShaderBytecode = shader->bytecode; 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci pso_desc.NodeMask = 0; 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci pso_desc.CachedPSO.pCachedBlob = NULL; 450bf215546Sopenharmony_ci pso_desc.CachedPSO.CachedBlobSizeInBytes = 0; 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci pso_desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci ID3D12PipelineState *ret; 455bf215546Sopenharmony_ci if (FAILED(screen->dev->CreateComputePipelineState(&pso_desc, 456bf215546Sopenharmony_ci IID_PPV_ARGS(&ret)))) { 457bf215546Sopenharmony_ci debug_printf("D3D12: CreateComputePipelineState failed!\n"); 458bf215546Sopenharmony_ci return NULL; 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci return ret; 462bf215546Sopenharmony_ci} 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_cistatic uint32_t 465bf215546Sopenharmony_cihash_compute_pipeline_state(const void *key) 466bf215546Sopenharmony_ci{ 467bf215546Sopenharmony_ci return _mesa_hash_data(key, sizeof(struct d3d12_compute_pipeline_state)); 468bf215546Sopenharmony_ci} 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_cistatic bool 471bf215546Sopenharmony_ciequals_compute_pipeline_state(const void *a, const void *b) 472bf215546Sopenharmony_ci{ 473bf215546Sopenharmony_ci return memcmp(a, b, sizeof(struct d3d12_compute_pipeline_state)) == 0; 474bf215546Sopenharmony_ci} 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ciID3D12PipelineState * 477bf215546Sopenharmony_cid3d12_get_compute_pipeline_state(struct d3d12_context *ctx) 478bf215546Sopenharmony_ci{ 479bf215546Sopenharmony_ci uint32_t hash = hash_compute_pipeline_state(&ctx->compute_pipeline_state); 480bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ctx->compute_pso_cache, hash, 481bf215546Sopenharmony_ci &ctx->compute_pipeline_state); 482bf215546Sopenharmony_ci if (!entry) { 483bf215546Sopenharmony_ci struct d3d12_compute_pso_entry *data = (struct d3d12_compute_pso_entry *)MALLOC(sizeof(struct d3d12_compute_pso_entry)); 484bf215546Sopenharmony_ci if (!data) 485bf215546Sopenharmony_ci return NULL; 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci data->key = ctx->compute_pipeline_state; 488bf215546Sopenharmony_ci data->pso = create_compute_pipeline_state(ctx); 489bf215546Sopenharmony_ci if (!data->pso) { 490bf215546Sopenharmony_ci FREE(data); 491bf215546Sopenharmony_ci return NULL; 492bf215546Sopenharmony_ci } 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci entry = _mesa_hash_table_insert_pre_hashed(ctx->compute_pso_cache, hash, &data->key, data); 495bf215546Sopenharmony_ci assert(entry); 496bf215546Sopenharmony_ci } 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci return ((struct d3d12_compute_pso_entry *)(entry->data))->pso; 499bf215546Sopenharmony_ci} 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_civoid 502bf215546Sopenharmony_cid3d12_compute_pipeline_state_cache_init(struct d3d12_context *ctx) 503bf215546Sopenharmony_ci{ 504bf215546Sopenharmony_ci ctx->compute_pso_cache = _mesa_hash_table_create(NULL, NULL, equals_compute_pipeline_state); 505bf215546Sopenharmony_ci} 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_cistatic void 508bf215546Sopenharmony_cidelete_compute_entry(struct hash_entry *entry) 509bf215546Sopenharmony_ci{ 510bf215546Sopenharmony_ci struct d3d12_compute_pso_entry *data = (struct d3d12_compute_pso_entry *)entry->data; 511bf215546Sopenharmony_ci data->pso->Release(); 512bf215546Sopenharmony_ci FREE(data); 513bf215546Sopenharmony_ci} 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_cistatic void 516bf215546Sopenharmony_ciremove_compute_entry(struct d3d12_context *ctx, struct hash_entry *entry) 517bf215546Sopenharmony_ci{ 518bf215546Sopenharmony_ci struct d3d12_compute_pso_entry *data = (struct d3d12_compute_pso_entry *)entry->data; 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci if (ctx->current_compute_pso == data->pso) 521bf215546Sopenharmony_ci ctx->current_compute_pso = NULL; 522bf215546Sopenharmony_ci _mesa_hash_table_remove(ctx->compute_pso_cache, entry); 523bf215546Sopenharmony_ci delete_compute_entry(entry); 524bf215546Sopenharmony_ci} 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_civoid 527bf215546Sopenharmony_cid3d12_compute_pipeline_state_cache_destroy(struct d3d12_context *ctx) 528bf215546Sopenharmony_ci{ 529bf215546Sopenharmony_ci _mesa_hash_table_destroy(ctx->compute_pso_cache, delete_compute_entry); 530bf215546Sopenharmony_ci} 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_civoid 533bf215546Sopenharmony_cid3d12_compute_pipeline_state_cache_invalidate_shader(struct d3d12_context *ctx, 534bf215546Sopenharmony_ci struct d3d12_shader_selector *selector) 535bf215546Sopenharmony_ci{ 536bf215546Sopenharmony_ci struct d3d12_shader *shader = selector->first; 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci while (shader) { 539bf215546Sopenharmony_ci hash_table_foreach(ctx->compute_pso_cache, entry) { 540bf215546Sopenharmony_ci const struct d3d12_compute_pipeline_state *key = (struct d3d12_compute_pipeline_state *)entry->key; 541bf215546Sopenharmony_ci if (key->stage == shader) 542bf215546Sopenharmony_ci remove_compute_entry(ctx, entry); 543bf215546Sopenharmony_ci } 544bf215546Sopenharmony_ci shader = shader->next_variant; 545bf215546Sopenharmony_ci } 546bf215546Sopenharmony_ci} 547