diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-03-21 16:26:25 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2022-09-16 23:25:44 +0300 |
commit | 2505510d13137afa1858305f03d377a734c1dced (patch) | |
tree | d894ec26d46637a8c8f01e8219e97d26993a83cf | |
parent | f689188f2651d68eedff2ac2ce413e35f738e4ba (diff) |
vkd3d: Add helper for late compilation of DXBC -> SPIR-V.
To be used by EXT_shader_module_identifier implementation.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
-rw-r--r-- | libs/vkd3d/state.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 8ba87770..317b6a62 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -2418,6 +2418,90 @@ static HRESULT vkd3d_compile_shader_stage(struct d3d12_pipeline_state *state, st return S_OK; } +static bool vkd3d_shader_stages_require_work_locked(struct d3d12_pipeline_state *state) +{ + struct d3d12_graphics_pipeline_state *graphics = &state->graphics; + unsigned int i; + + for (i = 0; i < graphics->stage_count; i++) + { + if (!graphics->code[i].size && graphics->stages[i].module == VK_NULL_HANDLE && + graphics->cached_desc.bytecode[i].BytecodeLength) + { + return true; + } + } + + return false; +} + +static HRESULT vkd3d_late_compile_shader_stages(struct d3d12_pipeline_state *state) +{ + /* We are at risk of having to compile pipelines late if we return from CreatePipelineState without + * either code[i] or module being non-null. */ + struct d3d12_graphics_pipeline_state *graphics = &state->graphics; + bool need_compile; + unsigned int i; + HRESULT hr; + + rwlock_lock_read(&state->lock); + need_compile = vkd3d_shader_stages_require_work_locked(state); + rwlock_unlock_read(&state->lock); + + if (!need_compile) + return S_OK; + + /* Taking a writer lock here is kinda horrible, + * but we really shouldn't hit this path except in extreme circumstances. */ + hr = S_OK; + rwlock_lock_write(&state->lock); + + /* Need to verify that need_compile did not change between unlocking reader and locking writer. */ + need_compile = vkd3d_shader_stages_require_work_locked(state); + if (!need_compile) + goto early_out; + + for (i = 0; i < graphics->stage_count; i++) + { + if (graphics->stages[i].module == VK_NULL_HANDLE && !graphics->code[i].size && + graphics->cached_desc.bytecode[i].BytecodeLength) + { + if (FAILED(hr = vkd3d_compile_shader_stage(state, state->device, graphics->cached_desc.bytecode_stages[i], + &graphics->cached_desc.bytecode[i], &graphics->code[i]))) + break; + } + + if (graphics->stages[i].module == VK_NULL_HANDLE) + { + if (FAILED(hr = d3d12_pipeline_state_create_shader_module(state->device, + &graphics->stages[i].module, + &graphics->code[i]))) + { + break; + } + } + + /* We'll keep the module around here, no need to keep code/size pairs around for this. + * If we're in a situation where late compile is relevant, we're using PSO cached blobs, + * so we never expect to serialize out SPIR-V either way. */ + vkd3d_shader_free_shader_code(&graphics->code[i]); + graphics->code[i].code = NULL; + graphics->code[i].size = 0; + + /* Don't need the DXBC blob anymore either. */ + if (graphics->cached_desc.bytecode_duped_mask & (1u << i)) + { + vkd3d_free((void*)graphics->cached_desc.bytecode[i].pShaderBytecode); + memset(&graphics->cached_desc.bytecode[i], 0, sizeof(graphics->cached_desc.bytecode[i])); + graphics->cached_desc.bytecode_duped_mask &= ~(1u << i); + } + } + +early_out: + rwlock_unlock_write(&state->lock); + return hr; +} + static void vkd3d_report_pipeline_creation_feedback_results(const VkPipelineCreationFeedbackCreateInfoEXT *feedback) { uint32_t i; |