1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 00:48:44 +01:00

[dxvk] Rework DxvkShaderModule into DxvkShaderStageInfo

Separates the whole thing from DxvkShader instances so that we
can use this in other places too. Only creates a shader module
if necessary for the given pipeline or device.
This commit is contained in:
Philip Rebohle 2022-07-06 00:40:47 +02:00
parent 5019ce4b9c
commit e6470b6d10
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
5 changed files with 117 additions and 133 deletions

View File

@ -94,13 +94,13 @@ namespace dxvk {
VkSpecializationInfo specInfo = specData.getSpecInfo(); VkSpecializationInfo specInfo = specData.getSpecInfo();
DxvkShaderModuleCreateInfo moduleInfo; DxvkShaderStageInfo stageInfo(m_device);
moduleInfo.fsDualSrcBlend = false; stageInfo.addStage(VK_SHADER_STAGE_COMPUTE_BIT,
m_shaders.cs->getCode(m_bindings, DxvkShaderModuleCreateInfo()),
auto csm = m_shaders.cs->createShaderModule(vk, m_bindings, moduleInfo); &specInfo);
VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
info.stage = csm.stageInfo(&specInfo); info.stage = *stageInfo.getStageInfos();
info.layout = m_bindings->getPipelineLayout(); info.layout = m_bindings->getPipelineLayout();
info.basePipelineIndex = -1; info.basePipelineIndex = -1;

View File

@ -1,3 +1,5 @@
#include <optional>
#include "../util/util_time.h" #include "../util/util_time.h"
#include "dxvk_device.h" #include "dxvk_device.h"
@ -622,18 +624,18 @@ namespace dxvk {
VkSpecializationInfo specInfo = specData.getSpecInfo(); VkSpecializationInfo specInfo = specData.getSpecInfo();
auto vsm = createShaderModule(m_shaders.vs, state); // Build stage infos for all provided shaders
auto tcsm = createShaderModule(m_shaders.tcs, state); DxvkShaderStageInfo stageInfo(m_device);
auto tesm = createShaderModule(m_shaders.tes, state); stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, state), &specInfo);
auto gsm = createShaderModule(m_shaders.gs, state);
auto fsm = createShaderModule(m_shaders.fs, state);
std::vector<VkPipelineShaderStageCreateInfo> stages; if (m_shaders.tcs != nullptr)
if (vsm) stages.push_back(vsm.stageInfo(&specInfo)); stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, state), &specInfo);
if (tcsm) stages.push_back(tcsm.stageInfo(&specInfo)); if (m_shaders.tes != nullptr)
if (tesm) stages.push_back(tesm.stageInfo(&specInfo)); stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, state), &specInfo);
if (gsm) stages.push_back(gsm.stageInfo(&specInfo)); if (m_shaders.gs != nullptr)
if (fsm) stages.push_back(fsm.stageInfo(&specInfo)); stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, state), &specInfo);
if (m_shaders.fs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, state), &specInfo);
DxvkGraphicsPipelineVertexInputState viState(m_device, state); DxvkGraphicsPipelineVertexInputState viState(m_device, state);
DxvkGraphicsPipelinePreRasterizationState prState(m_device, state, m_shaders.gs.ptr()); DxvkGraphicsPipelinePreRasterizationState prState(m_device, state, m_shaders.gs.ptr());
@ -645,8 +647,8 @@ namespace dxvk {
dyInfo.pDynamicStates = dynamicStates.data(); dyInfo.pDynamicStates = dynamicStates.data();
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &foState.rtInfo }; VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &foState.rtInfo };
info.stageCount = stages.size(); info.stageCount = stageInfo.getStageCount();
info.pStages = stages.data(); info.pStages = stageInfo.getStageInfos();
info.pVertexInputState = &viState.viInfo; info.pVertexInputState = &viState.viInfo;
info.pInputAssemblyState = &viState.iaInfo; info.pInputAssemblyState = &viState.iaInfo;
info.pTessellationState = &prState.tsInfo; info.pTessellationState = &prState.tsInfo;
@ -692,14 +694,11 @@ namespace dxvk {
} }
DxvkShaderModule DxvkGraphicsPipeline::createShaderModule( SpirvCodeBuffer DxvkGraphicsPipeline::getShaderCode(
const Rc<DxvkShader>& shader, const Rc<DxvkShader>& shader,
const DxvkGraphicsPipelineStateInfo& state) const { const DxvkGraphicsPipelineStateInfo& state) const {
auto vk = m_device->vkd(); auto vk = m_device->vkd();
if (shader == nullptr)
return DxvkShaderModule();
const DxvkShaderCreateInfo& shaderInfo = shader->info(); const DxvkShaderCreateInfo& shaderInfo = shader->info();
DxvkShaderModuleCreateInfo info; DxvkShaderModuleCreateInfo info;
@ -729,7 +728,8 @@ namespace dxvk {
} }
info.undefinedInputs = (providedInputs & consumedInputs) ^ consumedInputs; info.undefinedInputs = (providedInputs & consumedInputs) ^ consumedInputs;
return shader->createShaderModule(vk, m_bindings, info);
return shader->getCode(m_bindings, info);
} }

View File

@ -401,7 +401,7 @@ namespace dxvk {
void destroyPipeline( void destroyPipeline(
VkPipeline pipeline) const; VkPipeline pipeline) const;
DxvkShaderModule createShaderModule( SpirvCodeBuffer getShaderCode(
const Rc<DxvkShader>& shader, const Rc<DxvkShader>& shader,
const DxvkGraphicsPipelineStateInfo& state) const; const DxvkGraphicsPipelineStateInfo& state) const;

View File

@ -7,60 +7,6 @@
namespace dxvk { namespace dxvk {
DxvkShaderModule::DxvkShaderModule()
: m_vkd(nullptr), m_stage() {
}
DxvkShaderModule::DxvkShaderModule(DxvkShaderModule&& other)
: m_vkd(std::move(other.m_vkd)) {
this->m_stage = other.m_stage;
other.m_stage = VkPipelineShaderStageCreateInfo();
}
DxvkShaderModule::DxvkShaderModule(
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkShader>& shader,
const SpirvCodeBuffer& code)
: m_vkd(vkd), m_stage() {
m_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
m_stage.pNext = nullptr;
m_stage.flags = 0;
m_stage.stage = shader->info().stage;
m_stage.module = VK_NULL_HANDLE;
m_stage.pName = "main";
m_stage.pSpecializationInfo = nullptr;
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_stage.module) != VK_SUCCESS)
throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to create shader module");
}
DxvkShaderModule::~DxvkShaderModule() {
if (m_vkd != nullptr) {
m_vkd->vkDestroyShaderModule(
m_vkd->device(), m_stage.module, nullptr);
}
}
DxvkShaderModule& DxvkShaderModule::operator = (DxvkShaderModule&& other) {
this->m_vkd = std::move(other.m_vkd);
this->m_stage = other.m_stage;
other.m_stage = VkPipelineShaderStageCreateInfo();
return *this;
}
DxvkShader::DxvkShader( DxvkShader::DxvkShader(
const DxvkShaderCreateInfo& info, const DxvkShaderCreateInfo& info,
SpirvCodeBuffer&& spirv) SpirvCodeBuffer&& spirv)
@ -194,14 +140,6 @@ namespace dxvk {
} }
DxvkShaderModule DxvkShader::createShaderModule(
const Rc<vk::DeviceFn>& vkd,
const DxvkBindingLayoutObjects* layout,
const DxvkShaderModuleCreateInfo& info) {
return DxvkShaderModule(vkd, this, getCode(layout, info));
}
bool DxvkShader::canUsePipelineLibrary() const { bool DxvkShader::canUsePipelineLibrary() const {
// Pipeline libraries are unsupported for geometry and // Pipeline libraries are unsupported for geometry and
// tessellation stages since we'd need to compile them // tessellation stages since we'd need to compile them
@ -428,6 +366,62 @@ namespace dxvk {
} }
DxvkShaderStageInfo::DxvkShaderStageInfo(const DxvkDevice* device)
: m_device(device) {
}
void DxvkShaderStageInfo::addStage(
VkShaderStageFlagBits stage,
SpirvCodeBuffer&& code,
const VkSpecializationInfo* specInfo) {
// Take ownership of the SPIR-V code buffer
auto& codeBuffer = m_codeBuffers[m_stageCount];
codeBuffer = std::move(code);
// For graphics pipelines, as long as graphics pipeline libraries are
// enabled, we do not need to create a shader module object and can
// instead chain the create info to the shader stage info struct.
// For compute pipelines, this doesn't work and we still need a module.
auto& moduleInfo = m_moduleInfos[m_stageCount];
moduleInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
moduleInfo.codeSize = codeBuffer.size();
moduleInfo.pCode = codeBuffer.data();
VkShaderModule shaderModule = VK_NULL_HANDLE;
if (!m_device->features().extGraphicsPipelineLibrary.graphicsPipelineLibrary || stage == VK_SHADER_STAGE_COMPUTE_BIT) {
auto vk = m_device->vkd();
if (vk->vkCreateShaderModule(vk->device(), &moduleInfo, nullptr, &shaderModule))
throw DxvkError("DxvkShaderStageInfo: Failed to create shader module");
}
// Set up shader stage info with the data provided
auto& stageInfo = m_stageInfos[m_stageCount];
stageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
if (!stageInfo.module)
stageInfo.pNext = &moduleInfo;
stageInfo.stage = stage;
stageInfo.module = shaderModule;
stageInfo.pName = "main";
stageInfo.pSpecializationInfo = specInfo;
m_stageCount++;
}
DxvkShaderStageInfo::~DxvkShaderStageInfo() {
auto vk = m_device->vkd();
for (uint32_t i = 0; i < m_stageCount; i++) {
if (m_stageInfos[i].module)
vk->vkDestroyShaderModule(vk->device(), m_stageInfos[i].module, nullptr);
}
}
DxvkShaderPipelineLibrary::DxvkShaderPipelineLibrary( DxvkShaderPipelineLibrary::DxvkShaderPipelineLibrary(
const DxvkDevice* device, const DxvkDevice* device,
const DxvkShader* shader, const DxvkShader* shader,

View File

@ -135,21 +135,6 @@ namespace dxvk {
const DxvkBindingLayoutObjects* layout, const DxvkBindingLayoutObjects* layout,
const DxvkShaderModuleCreateInfo& state) const; const DxvkShaderModuleCreateInfo& state) const;
/**
* \brief Creates a shader module
*
* Remaps resource binding and descriptor set
* numbers to match the given binding layout.
* \param [in] vkd Vulkan device functions
* \param [in] layout Binding layout
* \param [in] info Module create info
* \returns The shader module
*/
DxvkShaderModule createShaderModule(
const Rc<vk::DeviceFn>& vkd,
const DxvkBindingLayoutObjects* layout,
const DxvkShaderModuleCreateInfo& info);
/** /**
* \brief Tests whether this shader supports pipeline libraries * \brief Tests whether this shader supports pipeline libraries
* *
@ -252,48 +237,53 @@ namespace dxvk {
* context will create pipeline objects on the * context will create pipeline objects on the
* fly when executing draw calls. * fly when executing draw calls.
*/ */
class DxvkShaderModule { class DxvkShaderStageInfo {
public: public:
DxvkShaderModule(); DxvkShaderStageInfo(const DxvkDevice* device);
DxvkShaderModule(DxvkShaderModule&& other); DxvkShaderStageInfo (DxvkShaderStageInfo&& other) = delete;
DxvkShaderStageInfo& operator = (DxvkShaderStageInfo&& other) = delete;
DxvkShaderModule( ~DxvkShaderStageInfo();
const Rc<vk::DeviceFn>& vkd,
const Rc<DxvkShader>& shader,
const SpirvCodeBuffer& code);
~DxvkShaderModule();
DxvkShaderModule& operator = (DxvkShaderModule&& other);
/** /**
* \brief Shader stage creation info * \brief Counts shader stages
* \returns Shader stage count
*/
uint32_t getStageCount() const {
return m_stageCount;
}
/**
* \brief Queries shader stage infos
* \returns Pointer to shader stage infos
*/
const VkPipelineShaderStageCreateInfo* getStageInfos() const {
return m_stageInfos.data();
}
/**
* \brief Adds a shader stage with specialization info
* *
* \param [in] specInfo Specialization info * \param [in] stage Shader stage
* \returns Shader stage create info * \param [in] code SPIR-V code
* \param [in] specinfo Specialization info
*/ */
VkPipelineShaderStageCreateInfo stageInfo( void addStage(
const VkSpecializationInfo* specInfo) const { VkShaderStageFlagBits stage,
VkPipelineShaderStageCreateInfo stage = m_stage; SpirvCodeBuffer&& code,
stage.pSpecializationInfo = specInfo; const VkSpecializationInfo* specInfo);
return stage;
}
/**
* \brief Checks whether module is valid
* \returns \c true if module is valid
*/
operator bool () const {
return m_stage.module != VK_NULL_HANDLE;
}
private: private:
Rc<vk::DeviceFn> m_vkd; const DxvkDevice* m_device;
VkPipelineShaderStageCreateInfo m_stage;
std::array<SpirvCodeBuffer, 5> m_codeBuffers;
std::array<VkShaderModuleCreateInfo, 5> m_moduleInfos = { };
std::array<VkPipelineShaderStageCreateInfo, 5> m_stageInfos = { };
uint32_t m_stageCount = 0;
}; };