[dxbc] Refactored shader compiler to return a DxvkShader

This commit is contained in:
Philip Rebohle 2017-12-08 18:14:05 +01:00
parent a2f66025f8
commit e872448ca3
17 changed files with 60 additions and 56 deletions

View File

@ -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

View File

@ -17,16 +17,12 @@ namespace dxvk {
BytecodeLength);
DxbcModule module(reader);
SpirvCodeBuffer spirvCode = module.compile();
// TODO pre-process shader bindings
std::vector<DxvkResourceSlot> 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);
}

View File

@ -64,7 +64,7 @@ namespace dxvk {
}
SpirvCodeBuffer DxbcCompiler::finalize() {
Rc<DxvkShader> DxbcCompiler::finalize() {
return m_gen->finalize();
}

View File

@ -23,7 +23,7 @@ namespace dxvk {
void processInstruction(
const DxbcInstruction& ins);
SpirvCodeBuffer finalize();
Rc<DxvkShader> finalize();
private:

View File

@ -40,7 +40,7 @@ namespace dxvk {
}
SpirvCodeBuffer DxbcModule::compile() const {
Rc<DxvkShader> 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();
}

View File

@ -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<DxvkShader> compile() const;
private:

View File

@ -135,7 +135,7 @@ namespace dxvk {
uint32_t regId,
const DxbcValue& index) = 0;
virtual SpirvCodeBuffer finalize() = 0;
virtual Rc<DxvkShader> finalize() = 0;
static Rc<DxbcCodeGen> create(
const DxbcProgramVersion& version,

View File

@ -141,7 +141,7 @@ namespace dxvk {
}
SpirvCodeBuffer DxbcPsCodeGen::finalize() {
Rc<DxvkShader> 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());
}

View File

@ -32,7 +32,7 @@ namespace dxvk {
uint32_t regId,
const DxbcValue& index);
SpirvCodeBuffer finalize() final;
Rc<DxvkShader> finalize() final;
private:

View File

@ -108,7 +108,7 @@ namespace dxvk {
}
SpirvCodeBuffer DxbcVsCodeGen::finalize() {
Rc<DxvkShader> 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());
}

View File

@ -32,7 +32,7 @@ namespace dxvk {
uint32_t regId,
const DxbcValue& index);
SpirvCodeBuffer finalize() final;
Rc<DxvkShader> finalize() final;
private:

View File

@ -13,7 +13,7 @@ namespace dxvk {
slotMapping.bindingCount(),
slotMapping.bindingInfos());
m_cs = cs->createShaderModule(slotMapping);
m_cs = cs->createShaderModule(vkd, slotMapping);
this->compilePipeline();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -41,12 +41,11 @@ namespace dxvk {
DxvkShader::DxvkShader(
const Rc<vk::DeviceFn>& 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<DxvkShaderModule> DxvkShader::createShaderModule(
const Rc<vk::DeviceFn>& 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));
}
}

View File

@ -68,15 +68,19 @@ namespace dxvk {
public:
DxvkShader(
const Rc<vk::DeviceFn>& 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<DxvkShaderModule> createShaderModule(
const Rc<vk::DeviceFn>& 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<vk::DeviceFn> m_vkd;
VkShaderStageFlagBits m_stage;
SpirvCodeBuffer m_code;

View File

@ -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<DxvkShader> shader = module.compile();
shader->dump(std::ofstream(
str::fromws(argv[2]), std::ios::binary));
return 0;
} catch (const DxvkError& e) {