Module: Mesa Branch: main Commit: 81fb1cfdad4de4fc0231774ee97e971447bc9f21 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=81fb1cfdad4de4fc0231774ee97e971447bc9f21
Author: Boris Brezillon <[email protected]> Date: Fri Jun 10 12:41:45 2022 +0200 dzn: Prepare support for pipeline variants Some D3D12 states can't be updated dynamically and require the creation of a new pipeline state. In order to support setting those dynamically we will have to support creating pipeline variants at draw time. Reviewed-by: Jesse Natalie <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16971> --- src/microsoft/vulkan/dzn_cmd_buffer.c | 12 +- src/microsoft/vulkan/dzn_pipeline.c | 213 +++++++++++++++++++++++----------- src/microsoft/vulkan/dzn_private.h | 62 ++++++++++ 3 files changed, 215 insertions(+), 72 deletions(-) diff --git a/src/microsoft/vulkan/dzn_cmd_buffer.c b/src/microsoft/vulkan/dzn_cmd_buffer.c index e53b593eec8..3d3d081e1a2 100644 --- a/src/microsoft/vulkan/dzn_cmd_buffer.c +++ b/src/microsoft/vulkan/dzn_cmd_buffer.c @@ -2135,18 +2135,24 @@ dzn_cmd_buffer_update_pipeline(struct dzn_cmd_buffer *cmdbuf, uint32_t bindpoint if (!pipeline) return; + ID3D12PipelineState *old_pipeline_state = + cmdbuf->state.pipeline ? cmdbuf->state.pipeline->state : NULL; + if (cmdbuf->state.bindpoint[bindpoint].dirty & DZN_CMD_BINDPOINT_DIRTY_PIPELINE) { if (bindpoint == VK_PIPELINE_BIND_POINT_GRAPHICS) { - const struct dzn_graphics_pipeline *gfx = - (const struct dzn_graphics_pipeline *)pipeline; + struct dzn_graphics_pipeline *gfx = + (struct dzn_graphics_pipeline *)pipeline; ID3D12GraphicsCommandList1_SetGraphicsRootSignature(cmdbuf->cmdlist, pipeline->root.sig); ID3D12GraphicsCommandList1_IASetPrimitiveTopology(cmdbuf->cmdlist, gfx->ia.topology); + dzn_graphics_pipeline_get_state(gfx, &cmdbuf->state.pipeline_variant); } else { ID3D12GraphicsCommandList1_SetComputeRootSignature(cmdbuf->cmdlist, pipeline->root.sig); } } - if (cmdbuf->state.pipeline != pipeline) { + ID3D12PipelineState *new_pipeline_state = pipeline->state; + + if (old_pipeline_state != new_pipeline_state) { ID3D12GraphicsCommandList1_SetPipelineState(cmdbuf->cmdlist, pipeline->state); cmdbuf->state.pipeline = pipeline; } diff --git a/src/microsoft/vulkan/dzn_pipeline.c b/src/microsoft/vulkan/dzn_pipeline.c index 7c44d63630b..11e5b3766ab 100644 --- a/src/microsoft/vulkan/dzn_pipeline.c +++ b/src/microsoft/vulkan/dzn_pipeline.c @@ -38,32 +38,6 @@ #include "util/u_debug.h" -#define D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(__type) \ - ALIGN_POT(ALIGN_POT(sizeof(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE), alignof(__type)) + sizeof(__type), alignof(void *)) - -#define MAX_GFX_PIPELINE_STATE_STREAM_SIZE \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(ID3D12RootSignature *) + \ - (D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_SHADER_BYTECODE) * 5) + /* VS, PS, DS, HS, GS */ \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_STREAM_OUTPUT_DESC) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_BLEND_DESC) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(UINT) + /* SampleMask */ \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_RASTERIZER_DESC) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_INPUT_LAYOUT_DESC) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_PRIMITIVE_TOPOLOGY_TYPE) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(struct D3D12_RT_FORMAT_ARRAY) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(DXGI_FORMAT) + /* DS format */ \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(DXGI_SAMPLE_DESC) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_NODE_MASK) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_CACHED_PIPELINE_STATE) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_PIPELINE_STATE_FLAGS) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_DEPTH_STENCIL_DESC1) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_VIEW_INSTANCING_DESC) - -#define MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(ID3D12RootSignature *) + \ - D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_SHADER_BYTECODE) - #define d3d12_pipeline_state_stream_new_desc(__stream, __pipetype, __id, __type, __desc) \ __type *__desc; \ do { \ @@ -86,6 +60,35 @@ #define d3d12_compute_pipeline_state_stream_new_desc(__stream, __id, __type, __desc) \ d3d12_pipeline_state_stream_new_desc(__stream, COMPUTE, __id, __type, __desc) +static bool +gfx_pipeline_variant_key_equal(const void *a, const void *b) +{ + return !memcmp(a, b, sizeof(struct dzn_graphics_pipeline_variant_key)); +} + +static uint32_t +gfx_pipeline_variant_key_hash(const void *key) +{ + return _mesa_hash_data(key, sizeof(struct dzn_graphics_pipeline_variant_key)); +} + +static VkResult +dzn_graphics_pipeline_prepare_for_variants(struct dzn_device *device, + struct dzn_graphics_pipeline *pipeline) +{ + if (pipeline->variants) + return VK_SUCCESS; + + pipeline->variants = + _mesa_hash_table_create(NULL, + gfx_pipeline_variant_key_hash, + gfx_pipeline_variant_key_equal); + if (!pipeline->variants) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + return VK_SUCCESS; +} + static dxil_spirv_shader_stage to_dxil_shader_stage(VkShaderStageFlagBits in) { @@ -271,13 +274,11 @@ dzn_pipeline_get_gfx_shader_slot(D3D12_PIPELINE_STATE_STREAM_DESC *stream, static VkResult dzn_graphics_pipeline_compile_shaders(struct dzn_device *device, - const struct dzn_graphics_pipeline *pipeline, + struct dzn_graphics_pipeline *pipeline, const struct dzn_pipeline_layout *layout, D3D12_PIPELINE_STATE_STREAM_DESC *out, D3D12_INPUT_ELEMENT_DESC *attribs, - D3D12_INPUT_ELEMENT_DESC *inputs, enum pipe_format *vi_conversions, - D3D12_SHADER_BYTECODE **shaders, const VkGraphicsPipelineCreateInfo *info) { const VkPipelineViewportStateCreateInfo *vp_info = @@ -289,7 +290,7 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device, } stages[MESA_VULKAN_SHADER_STAGES] = { 0 }; gl_shader_stage yz_flip_stage = MESA_SHADER_NONE; uint32_t active_stage_mask = 0; - VkResult ret = VK_SUCCESS; + VkResult ret; /* First step: collect stage info in a table indexed by gl_shader_stage * so we can iterate over stages in pipeline order or reverse pipeline @@ -378,7 +379,7 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device, vi_conversions, &nir_opts, &stages[stage].nir); if (ret != VK_SUCCESS) - goto out; + return ret; } /* Third step: link those NIR shaders. We iterate in reverse order @@ -407,14 +408,14 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device, assert(drv_loc < D3D12_VS_INPUT_REGISTER_COUNT); assert(loc < MAX_VERTEX_GENERIC_ATTRIBS); - inputs[drv_loc] = attribs[loc]; - inputs[drv_loc].SemanticIndex = drv_loc; + pipeline->templates.inputs[drv_loc] = attribs[loc]; + pipeline->templates.inputs[drv_loc].SemanticIndex = drv_loc; var->data.driver_location = drv_loc++; } if (drv_loc > 0) { d3d12_gfx_pipeline_state_stream_new_desc(out, INPUT_LAYOUT, D3D12_INPUT_LAYOUT_DESC, desc); - desc->pInputElementDescs = inputs; + desc->pInputElementDescs = pipeline->templates.inputs; desc->NumElements = drv_loc; } } @@ -426,16 +427,13 @@ dzn_graphics_pipeline_compile_shaders(struct dzn_device *device, ret = dzn_pipeline_compile_shader(device, stages[stage].nir, slot); if (ret != VK_SUCCESS) - goto out; + return ret; - shaders[stage] = slot; + pipeline->templates.shaders[stage].bc = slot; + pipeline->templates.shaders[stage].nir = stages[stage].nir; } -out: - u_foreach_bit(stage, active_stage_mask) - ralloc_free(stages[stage].nir); - - return ret; + return VK_SUCCESS; } VkFormat @@ -1037,6 +1035,34 @@ dzn_pipeline_finish(struct dzn_pipeline *pipeline) vk_object_base_finish(&pipeline->base); } +static void dzn_graphics_pipeline_delete_variant(struct hash_entry *he) +{ + struct dzn_graphics_pipeline_variant *variant = he->data; + + if (variant->state) + ID3D12PipelineState_Release(variant->state); +} + +static void +dzn_graphics_pipeline_cleanup_nir_shaders(struct dzn_graphics_pipeline *pipeline) +{ + for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->templates.shaders); i++) { + ralloc_free(pipeline->templates.shaders[i].nir); + pipeline->templates.shaders[i].nir = NULL; + } +} + +static void +dzn_graphics_pipeline_cleanup_dxil_shaders(struct dzn_graphics_pipeline *pipeline) +{ + for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->templates.shaders); i++) { + if (pipeline->templates.shaders[i].bc) { + free((void *)pipeline->templates.shaders[i].bc->pShaderBytecode); + pipeline->templates.shaders[i].bc = NULL; + } + } +} + static void dzn_graphics_pipeline_destroy(struct dzn_graphics_pipeline *pipeline, const VkAllocationCallbacks *alloc) @@ -1044,6 +1070,12 @@ dzn_graphics_pipeline_destroy(struct dzn_graphics_pipeline *pipeline, if (!pipeline) return; + _mesa_hash_table_destroy(pipeline->variants, + dzn_graphics_pipeline_delete_variant); + + dzn_graphics_pipeline_cleanup_nir_shaders(pipeline); + dzn_graphics_pipeline_cleanup_dxil_shaders(pipeline); + for (uint32_t i = 0; i < ARRAY_SIZE(pipeline->indirect_cmd_sigs); i++) { if (pipeline->indirect_cmd_sigs[i]) ID3D12CommandSignature_Release(pipeline->indirect_cmd_sigs[i]); @@ -1076,18 +1108,14 @@ dzn_graphics_pipeline_create(struct dzn_device *device, if (!pipeline) return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - uintptr_t state_buf[MAX_GFX_PIPELINE_STATE_STREAM_SIZE / sizeof(uintptr_t)]; - D3D12_PIPELINE_STATE_STREAM_DESC stream_desc = { - .pPipelineStateSubobjectStream = state_buf, - }; + D3D12_PIPELINE_STATE_STREAM_DESC *stream_desc = &pipeline->templates.stream_desc; + stream_desc->pPipelineStateSubobjectStream = pipeline->templates.stream_buf; dzn_pipeline_init(&pipeline->base, device, VK_PIPELINE_BIND_POINT_GRAPHICS, layout); D3D12_INPUT_ELEMENT_DESC attribs[MAX_VERTEX_GENERIC_ATTRIBS] = { 0 }; - D3D12_INPUT_ELEMENT_DESC inputs[D3D12_VS_INPUT_REGISTER_COUNT] = { 0 }; enum pipe_format vi_conversions[MAX_VERTEX_GENERIC_ATTRIBS] = { 0 }; - D3D12_SHADER_BYTECODE *shaders[MESA_VULKAN_SHADER_STAGES] = { 0 }; const VkPipelineViewportStateCreateInfo *vp_info = pCreateInfo->pRasterizationState->rasterizerDiscardEnable ? @@ -1127,11 +1155,11 @@ dzn_graphics_pipeline_create(struct dzn_device *device, } } - dzn_graphics_pipeline_translate_ia(pipeline, &stream_desc, pCreateInfo); - dzn_graphics_pipeline_translate_rast(pipeline, &stream_desc, pCreateInfo); - dzn_graphics_pipeline_translate_ms(pipeline, &stream_desc, pCreateInfo); - dzn_graphics_pipeline_translate_zsa(pipeline, &stream_desc, pCreateInfo); - dzn_graphics_pipeline_translate_blend(pipeline, &stream_desc, pCreateInfo); + dzn_graphics_pipeline_translate_ia(pipeline, stream_desc, pCreateInfo); + dzn_graphics_pipeline_translate_rast(pipeline, stream_desc, pCreateInfo); + dzn_graphics_pipeline_translate_ms(pipeline, stream_desc, pCreateInfo); + dzn_graphics_pipeline_translate_zsa(pipeline, stream_desc, pCreateInfo); + dzn_graphics_pipeline_translate_blend(pipeline, stream_desc, pCreateInfo); if (pass) { const struct vk_subpass *subpass = &pass->subpasses[pCreateInfo->subpass]; @@ -1165,7 +1193,7 @@ dzn_graphics_pipeline_create(struct dzn_device *device, } if (color_count > 0) { - d3d12_gfx_pipeline_state_stream_new_desc(&stream_desc, RENDER_TARGET_FORMATS, struct D3D12_RT_FORMAT_ARRAY, rts); + d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, RENDER_TARGET_FORMATS, struct D3D12_RT_FORMAT_ARRAY, rts); rts->NumRenderTargets = color_count; for (uint32_t i = 0; i < color_count; i++) { rts->RTFormats[i] = @@ -1176,7 +1204,7 @@ dzn_graphics_pipeline_create(struct dzn_device *device, } if (zs_fmt != VK_FORMAT_UNDEFINED) { - d3d12_gfx_pipeline_state_stream_new_desc(&stream_desc, DEPTH_STENCIL_FORMAT, DXGI_FORMAT, ds_fmt); + d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, DEPTH_STENCIL_FORMAT, DXGI_FORMAT, ds_fmt); *ds_fmt = dzn_image_get_dxgi_format(zs_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, @@ -1185,31 +1213,31 @@ dzn_graphics_pipeline_create(struct dzn_device *device, } ret = dzn_graphics_pipeline_compile_shaders(device, pipeline, layout, - &stream_desc, - attribs, inputs, vi_conversions, - shaders, pCreateInfo); + stream_desc, + attribs, vi_conversions, + pCreateInfo); if (ret != VK_SUCCESS) goto out; - d3d12_gfx_pipeline_state_stream_new_desc(&stream_desc, ROOT_SIGNATURE, ID3D12RootSignature*, root_sig); + d3d12_gfx_pipeline_state_stream_new_desc(stream_desc, ROOT_SIGNATURE, ID3D12RootSignature*, root_sig); *root_sig = pipeline->base.root.sig; - hres = ID3D12Device2_CreatePipelineState(device->dev, &stream_desc, - &IID_ID3D12PipelineState, - (void **)&pipeline->base.state); - if (FAILED(hres)) { - ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - goto out; + if (!pipeline->variants) { + hres = ID3D12Device2_CreatePipelineState(device->dev, stream_desc, + &IID_ID3D12PipelineState, + (void **)&pipeline->base.state); + if (FAILED(hres)) { + ret = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + goto out; + } + + dzn_graphics_pipeline_cleanup_dxil_shaders(pipeline); } + dzn_graphics_pipeline_cleanup_nir_shaders(pipeline); ret = VK_SUCCESS; out: - for (uint32_t i = 0; i < ARRAY_SIZE(shaders); i++) { - if (shaders[i]) - free((void *)shaders[i]->pShaderBytecode); - } - if (ret != VK_SUCCESS) dzn_graphics_pipeline_destroy(pipeline, pAllocator); else @@ -1218,6 +1246,53 @@ out: return ret; } +ID3D12PipelineState * +dzn_graphics_pipeline_get_state(struct dzn_graphics_pipeline *pipeline, + const struct dzn_graphics_pipeline_variant_key *key) +{ + if (!pipeline->variants) + return pipeline->base.state; + + struct dzn_graphics_pipeline_variant_key masked_key = { 0 }; + struct dzn_device *device = + container_of(pipeline->base.base.device, struct dzn_device, vk); + struct hash_entry *he = + _mesa_hash_table_search(pipeline->variants, &masked_key); + + struct dzn_graphics_pipeline_variant *variant; + + if (!he) { + variant = rzalloc(pipeline->variants, struct dzn_graphics_pipeline_variant); + variant->key = masked_key; + + uintptr_t stream_buf[MAX_GFX_PIPELINE_STATE_STREAM_SIZE / sizeof(uintptr_t)]; + D3D12_PIPELINE_STATE_STREAM_DESC stream_desc = { + .SizeInBytes = pipeline->templates.stream_desc.SizeInBytes, + .pPipelineStateSubobjectStream = stream_buf, + }; + + memcpy(stream_buf, pipeline->templates.stream_buf, stream_desc.SizeInBytes); + + HRESULT hres = ID3D12Device2_CreatePipelineState(device->dev, &stream_desc, + &IID_ID3D12PipelineState, + &variant->state); + assert(!FAILED(hres)); + he = _mesa_hash_table_insert(pipeline->variants, &variant->key, variant); + assert(he); + } else { + variant = he->data; + } + + if (variant->state) + ID3D12PipelineState_AddRef(variant->state); + + if (pipeline->base.state) + ID3D12PipelineState_Release(pipeline->base.state); + + pipeline->base.state = variant->state; + return variant->state; +} + #define DZN_INDIRECT_CMD_SIG_MAX_ARGS 4 ID3D12CommandSignature * diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h index ab594ee682a..461f8922e2c 100644 --- a/src/microsoft/vulkan/dzn_private.h +++ b/src/microsoft/vulkan/dzn_private.h @@ -447,11 +447,21 @@ struct dzn_rendering_attachment { VkAttachmentStoreOp store_op; }; +struct dzn_graphics_pipeline_variant_key { + uint32_t dummy; +}; + +struct dzn_graphics_pipeline_variant { + struct dzn_graphics_pipeline_variant_key key; + ID3D12PipelineState *state; +}; + #define MAX_RTS D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT struct dzn_cmd_buffer_state { const struct dzn_pipeline *pipeline; struct dzn_descriptor_heap *heaps[NUM_POOL_TYPES]; + struct dzn_graphics_pipeline_variant_key pipeline_variant; struct { VkRenderingFlags flags; D3D12_RECT area; @@ -673,6 +683,32 @@ enum dzn_register_space { DZN_REGISTER_SPACE_PUSH_CONSTANT, }; +#define D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(__type) \ + ALIGN_POT(ALIGN_POT(sizeof(D3D12_PIPELINE_STATE_SUBOBJECT_TYPE), alignof(__type)) + sizeof(__type), alignof(void *)) + +#define MAX_GFX_PIPELINE_STATE_STREAM_SIZE \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(ID3D12RootSignature *) + \ + (D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_SHADER_BYTECODE) * 5) + /* VS, PS, DS, HS, GS */ \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_STREAM_OUTPUT_DESC) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_BLEND_DESC) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(UINT) + /* SampleMask */ \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_RASTERIZER_DESC) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_INPUT_LAYOUT_DESC) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_PRIMITIVE_TOPOLOGY_TYPE) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(struct D3D12_RT_FORMAT_ARRAY) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(DXGI_FORMAT) + /* DS format */ \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(DXGI_SAMPLE_DESC) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_NODE_MASK) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_CACHED_PIPELINE_STATE) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_PIPELINE_STATE_FLAGS) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_DEPTH_STENCIL_DESC1) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_VIEW_INSTANCING_DESC) + +#define MAX_COMPUTE_PIPELINE_STATE_STREAM_SIZE \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(ID3D12RootSignature *) + \ + D3D12_PIPELINE_STATE_STREAM_DESC_SIZE(D3D12_SHADER_BYTECODE) + struct dzn_pipeline { struct vk_object_base base; VkPipelineBindPoint type; @@ -753,9 +789,35 @@ struct dzn_graphics_pipeline { float constants[4]; } blend; + struct { + uintptr_t stream_buf[MAX_GFX_PIPELINE_STATE_STREAM_SIZE / sizeof(uintptr_t)]; + D3D12_PIPELINE_STATE_STREAM_DESC stream_desc; + struct { + uint32_t dummy; + } desc_offsets; + D3D12_INPUT_ELEMENT_DESC inputs[D3D12_VS_INPUT_REGISTER_COUNT]; + struct { + D3D12_SHADER_BYTECODE *bc; + nir_shader *nir; + } shaders[MESA_VULKAN_SHADER_STAGES]; + } templates; + + struct hash_table *variants; + ID3D12CommandSignature *indirect_cmd_sigs[DZN_NUM_INDIRECT_DRAW_CMD_SIGS]; }; +#define dzn_graphics_pipeline_get_desc(pipeline, streambuf, name) \ + (void *)(pipeline->templates.desc_offsets.name == 0 ? NULL : \ + (uint8_t *)streambuf + pipeline->templates.desc_offsets.name) + +#define dzn_graphics_pipeline_get_desc_template(pipeline, name) \ + (const void *)dzn_graphics_pipeline_get_desc(pipeline, pipeline->templates.stream_buf, name) + +ID3D12PipelineState * +dzn_graphics_pipeline_get_state(struct dzn_graphics_pipeline *pipeline, + const struct dzn_graphics_pipeline_variant_key *key); + ID3D12CommandSignature * dzn_graphics_pipeline_get_indirect_cmd_sig(struct dzn_graphics_pipeline *pipeline, enum dzn_indirect_draw_cmd_sig_type cmd_sig_type);
