diff --git a/README.md b/README.md index e3334623e..cb6fecb0a 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ DXVK will create a file `dxgi.log` in the current working directory and may prin The behaviour of DXVK can be modified with environment variables. - `DXVK_SHADER_DUMP_PATH=directory` Writes all DXBC and SPIR-V shaders to the given directory -- `DXVK_SHADER_READS_PATH=directory` Reads SPIR-V shaders from the given directory instead of compiling the DXBC shader. - `DXVK_DEBUG_LAYERS=1` Enables Vulkan debug layers. Highly recommended for troubleshooting and debugging purposes. ## Samples and executables diff --git a/src/d3d11/d3d11_shader.cpp b/src/d3d11/d3d11_shader.cpp index f5aef5ed4..3e172936c 100644 --- a/src/d3d11/d3d11_shader.cpp +++ b/src/d3d11/d3d11_shader.cpp @@ -17,16 +17,12 @@ namespace dxvk { BytecodeLength); DxbcModule module(reader); - - SpirvCodeBuffer spirvCode = module.compile(); - - // TODO pre-process shader bindings - std::vector resourceSlots; + m_shader = module.compile(); // If requested by the user, dump both the raw DXBC // shader and the compiled SPIR-V module to a file. - const std::string dumpPath = env::getEnvVar(L"DXVK_SHADER_DUMP_PATH"); - const std::string readPath = env::getEnvVar(L"DXVK_SHADER_READ_PATH"); + const std::string dumpPath + = env::getEnvVar(L"DXVK_SHADER_DUMP_PATH"); if (dumpPath.size() != 0) { const std::string baseName = str::format(dumpPath, "/", @@ -36,25 +32,9 @@ namespace dxvk { reader.store(std::ofstream(str::format(baseName, ".dxbc"), std::ios_base::binary | std::ios_base::trunc)); - spirvCode.store(std::ofstream(str::format(baseName, ".spv"), + m_shader->dump(std::ofstream(str::format(baseName, ".spv"), std::ios_base::binary | std::ios_base::trunc)); } - - if (readPath.size() != 0) { - const std::string baseName = str::format(readPath, "/", - ConstructFileName(ComputeShaderHash(pShaderBytecode, BytecodeLength), - module.version().type())); - - spirvCode = SpirvCodeBuffer(std::ifstream( - str::format(baseName, ".spv"), - std::ios_base::binary)); - } - - m_shader = pDevice->GetDXVKDevice()->createShader( - module.version().shaderStage(), - resourceSlots.size(), - resourceSlots.data(), - spirvCode); } diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index eb7e682b7..3f5954618 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -64,7 +64,7 @@ namespace dxvk { } - SpirvCodeBuffer DxbcCompiler::finalize() { + Rc DxbcCompiler::finalize() { return m_gen->finalize(); } diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 701bb2195..adf6630fe 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -23,7 +23,7 @@ namespace dxvk { void processInstruction( const DxbcInstruction& ins); - SpirvCodeBuffer finalize(); + Rc finalize(); private: diff --git a/src/dxbc/dxbc_module.cpp b/src/dxbc/dxbc_module.cpp index c6819e373..8bfd2250e 100644 --- a/src/dxbc/dxbc_module.cpp +++ b/src/dxbc/dxbc_module.cpp @@ -40,7 +40,7 @@ namespace dxvk { } - SpirvCodeBuffer DxbcModule::compile() const { + Rc DxbcModule::compile() const { if (m_shexChunk == nullptr) throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk"); @@ -50,6 +50,7 @@ namespace dxvk { for (auto ins : *m_shexChunk) compiler.processInstruction(ins); + return compiler.finalize(); } diff --git a/src/dxbc/dxbc_module.h b/src/dxbc/dxbc_module.h index bada3f81e..a33eed92b 100644 --- a/src/dxbc/dxbc_module.h +++ b/src/dxbc/dxbc_module.h @@ -46,9 +46,9 @@ namespace dxvk { /** * \brief Compiles DXBC shader to SPIR-V module - * \returns The compiled DXVK shader object + * \returns The compiled shader object */ - SpirvCodeBuffer compile() const; + Rc compile() const; private: diff --git a/src/dxbc/gen/dxbc_gen_common.h b/src/dxbc/gen/dxbc_gen_common.h index fb647a5af..77bb014e8 100644 --- a/src/dxbc/gen/dxbc_gen_common.h +++ b/src/dxbc/gen/dxbc_gen_common.h @@ -135,7 +135,7 @@ namespace dxvk { uint32_t regId, const DxbcValue& index) = 0; - virtual SpirvCodeBuffer finalize() = 0; + virtual Rc 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 ab7bf3b08..6bf9afcd0 100644 --- a/src/dxbc/gen/dxbc_gen_pixel.cpp +++ b/src/dxbc/gen/dxbc_gen_pixel.cpp @@ -141,7 +141,7 @@ namespace dxvk { } - SpirvCodeBuffer DxbcPsCodeGen::finalize() { + Rc DxbcPsCodeGen::finalize() { m_module.functionBegin( m_module.defVoidType(), m_entryPointId, @@ -166,7 +166,10 @@ namespace dxvk { m_module.setOriginUpperLeft(m_entryPointId); m_module.setDebugName(m_entryPointId, "main"); - return m_module.compile(); + return new DxvkShader( + VK_SHADER_STAGE_FRAGMENT_BIT, + 0, nullptr, + m_module.compile()); } diff --git a/src/dxbc/gen/dxbc_gen_pixel.h b/src/dxbc/gen/dxbc_gen_pixel.h index 2b02d1280..70156ab65 100644 --- a/src/dxbc/gen/dxbc_gen_pixel.h +++ b/src/dxbc/gen/dxbc_gen_pixel.h @@ -32,7 +32,7 @@ namespace dxvk { uint32_t regId, const DxbcValue& index); - SpirvCodeBuffer finalize() final; + Rc finalize() final; private: diff --git a/src/dxbc/gen/dxbc_gen_vertex.cpp b/src/dxbc/gen/dxbc_gen_vertex.cpp index 40f6869db..6894df711 100644 --- a/src/dxbc/gen/dxbc_gen_vertex.cpp +++ b/src/dxbc/gen/dxbc_gen_vertex.cpp @@ -108,7 +108,7 @@ namespace dxvk { } - SpirvCodeBuffer DxbcVsCodeGen::finalize() { + Rc DxbcVsCodeGen::finalize() { m_module.functionBegin( m_module.defVoidType(), m_entryPointId, @@ -132,7 +132,10 @@ namespace dxvk { m_entryPointInterfaces.data()); m_module.setDebugName(m_entryPointId, "main"); - return m_module.compile(); + return new DxvkShader( + VK_SHADER_STAGE_VERTEX_BIT, + 0, nullptr, + m_module.compile()); } diff --git a/src/dxbc/gen/dxbc_gen_vertex.h b/src/dxbc/gen/dxbc_gen_vertex.h index 8a3096fb8..62338384e 100644 --- a/src/dxbc/gen/dxbc_gen_vertex.h +++ b/src/dxbc/gen/dxbc_gen_vertex.h @@ -32,7 +32,7 @@ namespace dxvk { uint32_t regId, const DxbcValue& index); - SpirvCodeBuffer finalize() final; + Rc finalize() final; private: diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp index 0fa2ce49e..ea7253d29 100644 --- a/src/dxvk/dxvk_compute.cpp +++ b/src/dxvk/dxvk_compute.cpp @@ -13,7 +13,7 @@ namespace dxvk { slotMapping.bindingCount(), slotMapping.bindingInfos()); - m_cs = cs->createShaderModule(slotMapping); + m_cs = cs->createShaderModule(vkd, slotMapping); this->compilePipeline(); } diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index 91e92a705..2872245d2 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -97,7 +97,7 @@ namespace dxvk { uint32_t slotCount, const DxvkResourceSlot* slotInfos, const SpirvCodeBuffer& code) { - return new DxvkShader(m_vkd, stage, + return new DxvkShader(stage, slotCount, slotInfos, code); } diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 5e69da581..b4681fb3f 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -55,11 +55,11 @@ namespace dxvk { slotMapping.bindingCount(), slotMapping.bindingInfos()); - if (vs != nullptr) m_vs = vs ->createShaderModule(slotMapping); - if (tcs != nullptr) m_tcs = tcs->createShaderModule(slotMapping); - if (tes != nullptr) m_tes = tes->createShaderModule(slotMapping); - if (gs != nullptr) m_gs = gs ->createShaderModule(slotMapping); - if (fs != nullptr) m_fs = fs ->createShaderModule(slotMapping); + if (vs != nullptr) m_vs = vs ->createShaderModule(vkd, slotMapping); + if (tcs != nullptr) m_tcs = tcs->createShaderModule(vkd, slotMapping); + if (tes != nullptr) m_tes = tes->createShaderModule(vkd, slotMapping); + if (gs != nullptr) m_gs = gs ->createShaderModule(vkd, slotMapping); + if (fs != nullptr) m_fs = fs ->createShaderModule(vkd, slotMapping); } diff --git a/src/dxvk/dxvk_shader.cpp b/src/dxvk/dxvk_shader.cpp index d9c1e1c6d..25ec379c2 100644 --- a/src/dxvk/dxvk_shader.cpp +++ b/src/dxvk/dxvk_shader.cpp @@ -41,12 +41,11 @@ namespace dxvk { DxvkShader::DxvkShader( - const Rc& vkd, - VkShaderStageFlagBits stage, - uint32_t slotCount, - const DxvkResourceSlot* slotInfos, - const SpirvCodeBuffer& code) - : m_vkd(vkd), m_stage(stage), m_code(code) { + VkShaderStageFlagBits stage, + uint32_t slotCount, + const DxvkResourceSlot* slotInfos, + const SpirvCodeBuffer& code) + : m_stage(stage), m_code(code) { for (uint32_t i = 0; i < slotCount; i++) m_slots.push_back(slotInfos[i]); } @@ -65,9 +64,15 @@ namespace dxvk { Rc DxvkShader::createShaderModule( + const Rc& vkd, const DxvkDescriptorSlotMapping& mapping) const { // TODO apply mapping - return new DxvkShaderModule(m_vkd, m_stage, m_code); + return new DxvkShaderModule(vkd, m_stage, m_code); + } + + + void DxvkShader::dump(std::ostream&& outputStream) const { + m_code.store(std::move(outputStream)); } } \ No newline at end of file diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h index 22dac7bad..d97e9511e 100644 --- a/src/dxvk/dxvk_shader.h +++ b/src/dxvk/dxvk_shader.h @@ -68,15 +68,19 @@ namespace dxvk { public: DxvkShader( - const Rc& vkd, VkShaderStageFlagBits stage, uint32_t slotCount, const DxvkResourceSlot* slotInfos, const SpirvCodeBuffer& code); + ~DxvkShader(); /** - * \brief + * \brief Adds resource slots definitions to a mapping + * + * Used to generate the exact descriptor set layout when + * compiling a graphics or compute pipeline. Slot indices + * have to be mapped to actual binding numbers. */ void defineResourceSlots( DxvkDescriptorSlotMapping& mapping) const; @@ -85,15 +89,24 @@ namespace dxvk { * \brief Creates a shader module * * Maps the binding slot numbers + * \param [in] vkd Vulkan device functions * \param [in] mapping Resource slot mapping * \returns The shader module */ Rc createShaderModule( + const Rc& vkd, const DxvkDescriptorSlotMapping& mapping) const; + /** + * \brief Dumps SPIR-V shader + * + * Can be used to store the SPIR-V code in a file. + * \param [in] outputStream Stream to write to + */ + void dump(std::ostream&& outputStream) const; + private: - Rc m_vkd; VkShaderStageFlagBits m_stage; SpirvCodeBuffer m_code; diff --git a/tests/dxbc/test_dxbc_compiler.cpp b/tests/dxbc/test_dxbc_compiler.cpp index e6f5da628..88ee24241 100644 --- a/tests/dxbc/test_dxbc_compiler.cpp +++ b/tests/dxbc/test_dxbc_compiler.cpp @@ -40,8 +40,8 @@ int WINAPI WinMain(HINSTANCE hInstance, DxbcReader reader(dxbcCode.data(), dxbcCode.size()); DxbcModule module(reader); - auto shader = module.compile(); - shader.store(std::ofstream( + Rc shader = module.compile(); + shader->dump(std::ofstream( str::fromws(argv[2]), std::ios::binary)); return 0; } catch (const DxvkError& e) {