diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 656f5677..9dbee21e 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -50,7 +50,7 @@ namespace dxvk { } - Rc DxbcCompiler::finalize() { + SpirvCodeBuffer DxbcCompiler::finalize() { return m_gen->finalize(); } diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 4edfcc9b..a40a8f5c 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -21,7 +21,7 @@ namespace dxvk { void processInstruction( const DxbcInstruction& ins); - Rc finalize(); + SpirvCodeBuffer finalize(); private: diff --git a/src/dxbc/dxbc_module.cpp b/src/dxbc/dxbc_module.cpp index 4555c4fa..e1d1b6f8 100644 --- a/src/dxbc/dxbc_module.cpp +++ b/src/dxbc/dxbc_module.cpp @@ -40,7 +40,7 @@ namespace dxvk { } - Rc DxbcModule::compile() const { + SpirvCodeBuffer DxbcModule::compile() const { if (m_shexChunk == nullptr) throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk"); diff --git a/src/dxbc/dxbc_module.h b/src/dxbc/dxbc_module.h index 4c23fbf5..3d5be120 100644 --- a/src/dxbc/dxbc_module.h +++ b/src/dxbc/dxbc_module.h @@ -31,7 +31,7 @@ namespace dxvk { * \brief Compiles DXBC shader to SPIR-V module * \returns The compiled DXVK shader object */ - Rc compile() const; + SpirvCodeBuffer compile() const; private: diff --git a/src/dxbc/gen/dxbc_gen_common.h b/src/dxbc/gen/dxbc_gen_common.h index 61a62fd4..b643da63 100644 --- a/src/dxbc/gen/dxbc_gen_common.h +++ b/src/dxbc/gen/dxbc_gen_common.h @@ -109,7 +109,7 @@ namespace dxvk { uint32_t regId, const DxbcValue& index) = 0; - virtual Rc finalize() = 0; + virtual SpirvCodeBuffer finalize() = 0; static Rc create( const DxbcProgramVersion& version); diff --git a/src/dxbc/gen/dxbc_gen_pixel.cpp b/src/dxbc/gen/dxbc_gen_pixel.cpp index 0b84db48..296183e7 100644 --- a/src/dxbc/gen/dxbc_gen_pixel.cpp +++ b/src/dxbc/gen/dxbc_gen_pixel.cpp @@ -88,7 +88,7 @@ namespace dxvk { } - Rc DxbcPsCodeGen::finalize() { + SpirvCodeBuffer DxbcPsCodeGen::finalize() { m_module.functionBegin( m_module.defVoidType(), m_entryPointId, @@ -112,9 +112,7 @@ namespace dxvk { m_entryPointInterfaces.data()); m_module.setDebugName(m_entryPointId, "main"); - return new DxvkShader( - VK_SHADER_STAGE_FRAGMENT_BIT, - m_module.compile()); + return m_module.compile(); } diff --git a/src/dxbc/gen/dxbc_gen_pixel.h b/src/dxbc/gen/dxbc_gen_pixel.h index 226c745a..915d659e 100644 --- a/src/dxbc/gen/dxbc_gen_pixel.h +++ b/src/dxbc/gen/dxbc_gen_pixel.h @@ -30,7 +30,7 @@ namespace dxvk { uint32_t regId, const DxbcValue& index); - Rc finalize() final; + SpirvCodeBuffer finalize() final; private: diff --git a/src/dxbc/gen/dxbc_gen_vertex.cpp b/src/dxbc/gen/dxbc_gen_vertex.cpp index 9bd1f671..2c78d938 100644 --- a/src/dxbc/gen/dxbc_gen_vertex.cpp +++ b/src/dxbc/gen/dxbc_gen_vertex.cpp @@ -95,7 +95,7 @@ namespace dxvk { } - Rc DxbcVsCodeGen::finalize() { + SpirvCodeBuffer DxbcVsCodeGen::finalize() { m_module.functionBegin( m_module.defVoidType(), m_entryPointId, @@ -119,9 +119,7 @@ namespace dxvk { m_entryPointInterfaces.data()); m_module.setDebugName(m_entryPointId, "main"); - return new DxvkShader( - VK_SHADER_STAGE_VERTEX_BIT, - m_module.compile()); + return m_module.compile(); } diff --git a/src/dxbc/gen/dxbc_gen_vertex.h b/src/dxbc/gen/dxbc_gen_vertex.h index 890065c3..9b2586ef 100644 --- a/src/dxbc/gen/dxbc_gen_vertex.h +++ b/src/dxbc/gen/dxbc_gen_vertex.h @@ -30,7 +30,7 @@ namespace dxvk { uint32_t regId, const DxbcValue& index); - Rc finalize() final; + SpirvCodeBuffer finalize() final; private: diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp index dd4f13e1..f503fa7f 100644 --- a/src/dxvk/dxvk_compute.cpp +++ b/src/dxvk/dxvk_compute.cpp @@ -5,7 +5,7 @@ namespace dxvk { DxvkComputePipeline::DxvkComputePipeline( const Rc& vkd, const Rc& shader) - : m_vkd(vkd) { + : m_vkd(vkd), m_shader(shader) { TRACE(this, shader); std::vector bindings; @@ -40,27 +40,12 @@ namespace dxvk { throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create pipeline layout"); } - SpirvCodeBuffer code = shader->code(); - - VkShaderModuleCreateInfo minfo; - minfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - minfo.pNext = nullptr; - minfo.flags = 0; - minfo.codeSize = code.size(); - minfo.pCode = code.data(); - - if (m_vkd->vkCreateShaderModule(m_vkd->device(), - &minfo, nullptr, &m_module) != VK_SUCCESS) { - this->destroyObjects(); - throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create shader module"); - } - VkPipelineShaderStageCreateInfo sinfo; sinfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; sinfo.pNext = nullptr; sinfo.flags = 0; sinfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; - sinfo.module = m_module; + sinfo.module = m_shader->module(); sinfo.pName = "main"; sinfo.pSpecializationInfo = nullptr; @@ -91,9 +76,6 @@ namespace dxvk { if (m_pipeline != VK_NULL_HANDLE) m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr); - if (m_module != VK_NULL_HANDLE) - m_vkd->vkDestroyShaderModule(m_vkd->device(), m_module, nullptr); - if (m_pipelineLayout != VK_NULL_HANDLE) m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipelineLayout, nullptr); diff --git a/src/dxvk/dxvk_compute.h b/src/dxvk/dxvk_compute.h index a2f210cf..8765652a 100644 --- a/src/dxvk/dxvk_compute.h +++ b/src/dxvk/dxvk_compute.h @@ -55,9 +55,10 @@ namespace dxvk { private: Rc m_vkd; + Rc m_shader; + VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE; VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; - VkShaderModule m_module = VK_NULL_HANDLE; VkPipeline m_pipeline = VK_NULL_HANDLE; void destroyObjects(); diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 4ebcfc5e..ddc0b2ff 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -72,7 +72,72 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::compilePipeline( const DxvkGraphicsPipelineStateInfo& state) const { + std::array dynamicStates = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_BLEND_CONSTANTS, + VK_DYNAMIC_STATE_STENCIL_REFERENCE, + }; + std::vector stages; + + if (m_vs != nullptr) stages.push_back(m_vs->stageInfo()); + if (m_tcs != nullptr) stages.push_back(m_tcs->stageInfo()); + if (m_tes != nullptr) stages.push_back(m_tes->stageInfo()); + if (m_gs != nullptr) stages.push_back(m_gs->stageInfo()); + if (m_fs != nullptr) stages.push_back(m_fs->stageInfo()); + + VkPipelineViewportStateCreateInfo vpInfo; + vpInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + vpInfo.pNext = nullptr; + vpInfo.flags = 0; + vpInfo.viewportCount = state.viewportCount; + vpInfo.pViewports = nullptr; + vpInfo.scissorCount = state.viewportCount; + vpInfo.pViewports = nullptr; + + VkPipelineDynamicStateCreateInfo dsInfo; + dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dsInfo.pNext = nullptr; + dsInfo.flags = 0; + dsInfo.dynamicStateCount = dynamicStates.size(); + dsInfo.pDynamicStates = dynamicStates.data(); + + VkGraphicsPipelineCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stageCount = stages.size(); + info.pStages = stages.data(); + info.pVertexInputState = &state.inputLayout->info(); + info.pInputAssemblyState = &state.inputAssemblyState->info(); + info.pTessellationState = nullptr; // TODO implement + info.pViewportState = &vpInfo; + info.pRasterizationState = &state.rasterizerState->info(); + info.pMultisampleState = &state.multisampleState->info(); + info.pDepthStencilState = &state.depthStencilState->info(); + info.pColorBlendState = &state.blendState->info(); + info.pDynamicState = &dsInfo; + info.layout = m_pipelineLayout; + info.renderPass = state.renderPass; + info.subpass = 0; + info.basePipelineHandle = VK_NULL_HANDLE; + info.basePipelineIndex = 0; + + VkPipeline pipeline = VK_NULL_HANDLE; + if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(), + VK_NULL_HANDLE, 1, &info, nullptr, &pipeline) != VK_SUCCESS) + throw DxvkError("DxvkGraphicsPipeline::DxvkGraphicsPipeline: Failed to compile pipeline"); + return pipeline; + } + + + void DxvkGraphicsPipeline::destroyObjects() { + if (m_pipelineLayout != VK_NULL_HANDLE) + m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipelineLayout, nullptr); + + if (m_descriptorSetLayout != VK_NULL_HANDLE) + m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr); } } \ No newline at end of file diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index c62bf81a..0d85e65c 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -84,6 +84,8 @@ namespace dxvk { VkPipeline compilePipeline( const DxvkGraphicsPipelineStateInfo& state) const; + void destroyObjects(); + }; } \ No newline at end of file diff --git a/src/dxvk/dxvk_shader.cpp b/src/dxvk/dxvk_shader.cpp index fe8466d5..2053b6de 100644 --- a/src/dxvk/dxvk_shader.cpp +++ b/src/dxvk/dxvk_shader.cpp @@ -3,16 +3,44 @@ namespace dxvk { DxvkShader::DxvkShader( + const Rc& vkd, VkShaderStageFlagBits stage, - SpirvCodeBuffer&& code) - : m_stage (stage), - m_code (std::move(code)) { + const SpirvCodeBuffer& code) + : m_vkd(vkd), m_stage(stage) { TRACE(this, stage); + + VkShaderModuleCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.codeSize = code.size(); + info.pCode = code.data(); + + if (m_vkd->vkCreateShaderModule(m_vkd->device(), + &info, nullptr, &m_module) != VK_SUCCESS) + throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create shader module"); } DxvkShader::~DxvkShader() { TRACE(this); + + m_vkd->vkDestroyShaderModule( + m_vkd->device(), m_module, nullptr); + } + + + VkPipelineShaderStageCreateInfo DxvkShader::stageInfo() const { + VkPipelineShaderStageCreateInfo info; + + info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.stage = m_stage; + info.module = m_module; + info.pName = "main"; + info.pSpecializationInfo = nullptr; + return info; } } \ No newline at end of file diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h index 508848c4..10f40d1e 100644 --- a/src/dxvk/dxvk_shader.h +++ b/src/dxvk/dxvk_shader.h @@ -38,22 +38,22 @@ namespace dxvk { public: DxvkShader( + const Rc& vkd, VkShaderStageFlagBits stage, - SpirvCodeBuffer&& code); + const SpirvCodeBuffer& code); ~DxvkShader(); - /** - * \brief Retrieves shader code - * \returns Shader code buffer - */ - const SpirvCodeBuffer& code() const { - return m_code; + VkShaderModule module() const { + return m_module; } + VkPipelineShaderStageCreateInfo stageInfo() const; + private: + Rc m_vkd; VkShaderStageFlagBits m_stage; - SpirvCodeBuffer m_code; + VkShaderModule m_module; }; diff --git a/tests/dxbc/test_dxbc_compiler.cpp b/tests/dxbc/test_dxbc_compiler.cpp index bb6724ee..09246ac6 100644 --- a/tests/dxbc/test_dxbc_compiler.cpp +++ b/tests/dxbc/test_dxbc_compiler.cpp @@ -37,7 +37,7 @@ int WINAPI WinMain(HINSTANCE hInstance, DxbcModule module(reader); auto shader = module.compile(); - shader->code().store(std::ofstream( + shader.store(std::ofstream( str::fromws(argv[2]), std::ios::binary)); return 0; } catch (const DxvkError& e) {