mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-13 16:08:50 +01:00
[dxvk] Introduce DxvkGraphicsPipelineShaderState
And factor out a bunch of related code.
This commit is contained in:
parent
30fa9df868
commit
63420c0cd7
@ -601,6 +601,112 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGraphicsPipelineShaderState::DxvkGraphicsPipelineShaderState() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkGraphicsPipelineShaderState::DxvkGraphicsPipelineShaderState(
|
||||||
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
|
const DxvkGraphicsPipelineStateInfo& state)
|
||||||
|
: vsInfo (getCreateInfo(shaders, shaders.vs, state)),
|
||||||
|
tcsInfo (getCreateInfo(shaders, shaders.tcs, state)),
|
||||||
|
tesInfo (getCreateInfo(shaders, shaders.tes, state)),
|
||||||
|
gsInfo (getCreateInfo(shaders, shaders.gs, state)),
|
||||||
|
fsInfo (getCreateInfo(shaders, shaders.fs, state)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool DxvkGraphicsPipelineShaderState::eq(const DxvkGraphicsPipelineShaderState& other) const {
|
||||||
|
return vsInfo.eq(other.vsInfo)
|
||||||
|
&& tcsInfo.eq(other.tcsInfo)
|
||||||
|
&& tesInfo.eq(other.tesInfo)
|
||||||
|
&& gsInfo.eq(other.gsInfo)
|
||||||
|
&& fsInfo.eq(other.fsInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t DxvkGraphicsPipelineShaderState::hash() const {
|
||||||
|
DxvkHashState hash;
|
||||||
|
hash.add(vsInfo.hash());
|
||||||
|
hash.add(tcsInfo.hash());
|
||||||
|
hash.add(tesInfo.hash());
|
||||||
|
hash.add(gsInfo.hash());
|
||||||
|
hash.add(fsInfo.hash());
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxvkShaderModuleCreateInfo DxvkGraphicsPipelineShaderState::getCreateInfo(
|
||||||
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
|
const Rc<DxvkShader>& shader,
|
||||||
|
const DxvkGraphicsPipelineStateInfo& state) {
|
||||||
|
DxvkShaderModuleCreateInfo info;
|
||||||
|
|
||||||
|
if (shader == nullptr)
|
||||||
|
return info;
|
||||||
|
|
||||||
|
// Fix up fragment shader outputs for dual-source blending
|
||||||
|
const DxvkShaderCreateInfo& shaderInfo = shader->info();
|
||||||
|
|
||||||
|
if (shaderInfo.stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
|
||||||
|
info.fsDualSrcBlend = state.useDualSourceBlending();
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||||
|
if ((shaderInfo.outputMask & (1u << i)) && state.writesRenderTarget(i))
|
||||||
|
info.rtSwizzles[i] = state.omSwizzle[i].mapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deal with undefined shader inputs
|
||||||
|
uint32_t consumedInputs = shaderInfo.inputMask;
|
||||||
|
uint32_t providedInputs = 0;
|
||||||
|
|
||||||
|
if (shaderInfo.stage == VK_SHADER_STAGE_VERTEX_BIT) {
|
||||||
|
for (uint32_t i = 0; i < state.il.attributeCount(); i++)
|
||||||
|
providedInputs |= 1u << state.ilAttributes[i].location();
|
||||||
|
} else if (shaderInfo.stage != VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
|
||||||
|
auto prevStage = getPrevStageShader(shaders, shaderInfo.stage);
|
||||||
|
providedInputs = prevStage->info().outputMask;
|
||||||
|
} else {
|
||||||
|
// Technically not correct, but this
|
||||||
|
// would need a lot of extra care
|
||||||
|
providedInputs = consumedInputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.undefinedInputs = (providedInputs & consumedInputs) ^ consumedInputs;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkShader> DxvkGraphicsPipelineShaderState::getPrevStageShader(
|
||||||
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
|
const VkShaderStageFlagBits stage) {
|
||||||
|
if (stage == VK_SHADER_STAGE_VERTEX_BIT)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
|
||||||
|
return shaders.tcs;
|
||||||
|
|
||||||
|
Rc<DxvkShader> result = shaders.vs;
|
||||||
|
|
||||||
|
if (stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (shaders.tes != nullptr)
|
||||||
|
result = shaders.tes;
|
||||||
|
|
||||||
|
if (stage == VK_SHADER_STAGE_GEOMETRY_BIT)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (shaders.gs != nullptr)
|
||||||
|
result = shaders.gs;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkPipelineSpecConstantState::DxvkPipelineSpecConstantState() {
|
DxvkPipelineSpecConstantState::DxvkPipelineSpecConstantState() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -888,7 +994,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Remapping fragment shader outputs would require spec constants
|
// Remapping fragment shader outputs would require spec constants
|
||||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||||
if (writesRenderTarget(state, i) && !util::isIdentityMapping(state.omSwizzle[i].mapping()))
|
if ((m_fsOut & (1u << i)) && state.writesRenderTarget(i)
|
||||||
|
&& !util::isIdentityMapping(state.omSwizzle[i].mapping()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -978,6 +1085,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up pipeline state
|
// Set up pipeline state
|
||||||
|
DxvkGraphicsPipelineShaderState shState(m_shaders, state);
|
||||||
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr());
|
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr());
|
||||||
DxvkGraphicsPipelinePreRasterizationState prState(m_device, state, m_shaders.gs.ptr());
|
DxvkGraphicsPipelinePreRasterizationState prState(m_device, state, m_shaders.gs.ptr());
|
||||||
DxvkGraphicsPipelineFragmentShaderState fsState(m_device, state);
|
DxvkGraphicsPipelineFragmentShaderState fsState(m_device, state);
|
||||||
@ -993,16 +1101,16 @@ namespace dxvk {
|
|||||||
if (m_shaders.fs != nullptr)
|
if (m_shaders.fs != nullptr)
|
||||||
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, m_fsLibrary->getModuleIdentifier(), &scState.scInfo);
|
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, m_fsLibrary->getModuleIdentifier(), &scState.scInfo);
|
||||||
} else {
|
} else {
|
||||||
stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, state), &scState.scInfo);
|
stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, shState.vsInfo), &scState.scInfo);
|
||||||
|
|
||||||
if (m_shaders.tcs != nullptr)
|
if (m_shaders.tcs != nullptr)
|
||||||
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, state), &scState.scInfo);
|
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, shState.tcsInfo), &scState.scInfo);
|
||||||
if (m_shaders.tes != nullptr)
|
if (m_shaders.tes != nullptr)
|
||||||
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, state), &scState.scInfo);
|
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, shState.tesInfo), &scState.scInfo);
|
||||||
if (m_shaders.gs != nullptr)
|
if (m_shaders.gs != nullptr)
|
||||||
stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, state), &scState.scInfo);
|
stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, shState.gsInfo), &scState.scInfo);
|
||||||
if (m_shaders.fs != nullptr)
|
if (m_shaders.fs != nullptr)
|
||||||
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, state), &scState.scInfo);
|
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, shState.fsInfo), &scState.scInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipelineDynamicStateCreateInfo dyInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
VkPipelineDynamicStateCreateInfo dyInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
||||||
@ -1053,82 +1161,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
SpirvCodeBuffer DxvkGraphicsPipeline::getShaderCode(
|
SpirvCodeBuffer DxvkGraphicsPipeline::getShaderCode(
|
||||||
const Rc<DxvkShader>& shader,
|
const Rc<DxvkShader>& shader,
|
||||||
const DxvkGraphicsPipelineStateInfo& state) const {
|
const DxvkShaderModuleCreateInfo& info) const {
|
||||||
auto vk = m_device->vkd();
|
|
||||||
|
|
||||||
const DxvkShaderCreateInfo& shaderInfo = shader->info();
|
|
||||||
DxvkShaderModuleCreateInfo info;
|
|
||||||
|
|
||||||
// Fix up fragment shader outputs for dual-source blending
|
|
||||||
if (shaderInfo.stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
|
|
||||||
info.fsDualSrcBlend = state.useDualSourceBlending();
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
|
||||||
if (writesRenderTarget(state, i))
|
|
||||||
info.rtSwizzles[i] = state.omSwizzle[i].mapping();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deal with undefined shader inputs
|
|
||||||
uint32_t consumedInputs = shaderInfo.inputMask;
|
|
||||||
uint32_t providedInputs = 0;
|
|
||||||
|
|
||||||
if (shaderInfo.stage == VK_SHADER_STAGE_VERTEX_BIT) {
|
|
||||||
for (uint32_t i = 0; i < state.il.attributeCount(); i++)
|
|
||||||
providedInputs |= 1u << state.ilAttributes[i].location();
|
|
||||||
} else if (shaderInfo.stage != VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
|
|
||||||
auto prevStage = getPrevStageShader(shaderInfo.stage);
|
|
||||||
providedInputs = prevStage->info().outputMask;
|
|
||||||
} else {
|
|
||||||
// Technically not correct, but this
|
|
||||||
// would need a lot of extra care
|
|
||||||
providedInputs = consumedInputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.undefinedInputs = (providedInputs & consumedInputs) ^ consumedInputs;
|
|
||||||
return shader->getCode(m_bindings, info);
|
return shader->getCode(m_bindings, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkShader> DxvkGraphicsPipeline::getPrevStageShader(VkShaderStageFlagBits stage) const {
|
|
||||||
if (stage == VK_SHADER_STAGE_VERTEX_BIT)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
|
|
||||||
return m_shaders.tcs;
|
|
||||||
|
|
||||||
Rc<DxvkShader> result = m_shaders.vs;
|
|
||||||
|
|
||||||
if (stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (m_shaders.tes != nullptr)
|
|
||||||
result = m_shaders.tes;
|
|
||||||
|
|
||||||
if (stage == VK_SHADER_STAGE_GEOMETRY_BIT)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (m_shaders.gs != nullptr)
|
|
||||||
result = m_shaders.gs;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool DxvkGraphicsPipeline::writesRenderTarget(
|
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
|
||||||
uint32_t target) const {
|
|
||||||
if (!(m_fsOut & (1u << target)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!state.omBlend[target].colorWriteMask())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
VkFormat rtFormat = state.rt.getColorFormat(target);
|
|
||||||
return rtFormat != VK_FORMAT_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t DxvkGraphicsPipeline::computeSpecConstantMask() const {
|
uint32_t DxvkGraphicsPipeline::computeSpecConstantMask() const {
|
||||||
uint32_t mask = m_shaders.vs->getSpecConstantMask();
|
uint32_t mask = m_shaders.vs->getSpecConstantMask();
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ namespace dxvk {
|
|||||||
class DxvkStateCache;
|
class DxvkStateCache;
|
||||||
class DxvkPipelineManager;
|
class DxvkPipelineManager;
|
||||||
class DxvkPipelineWorkers;
|
class DxvkPipelineWorkers;
|
||||||
|
|
||||||
|
struct DxvkGraphicsPipelineShaders;
|
||||||
struct DxvkPipelineStats;
|
struct DxvkPipelineStats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,6 +189,42 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Shader create info state for graphics pipelines
|
||||||
|
*
|
||||||
|
* Can only be used when all pipeline state is known.
|
||||||
|
*/
|
||||||
|
struct DxvkGraphicsPipelineShaderState {
|
||||||
|
DxvkGraphicsPipelineShaderState();
|
||||||
|
|
||||||
|
DxvkGraphicsPipelineShaderState(
|
||||||
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
|
const DxvkGraphicsPipelineStateInfo& state);
|
||||||
|
|
||||||
|
DxvkShaderModuleCreateInfo vsInfo;
|
||||||
|
DxvkShaderModuleCreateInfo tcsInfo;
|
||||||
|
DxvkShaderModuleCreateInfo tesInfo;
|
||||||
|
DxvkShaderModuleCreateInfo gsInfo;
|
||||||
|
DxvkShaderModuleCreateInfo fsInfo;
|
||||||
|
|
||||||
|
bool eq(const DxvkGraphicsPipelineShaderState& other) const;
|
||||||
|
|
||||||
|
size_t hash() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
DxvkShaderModuleCreateInfo getCreateInfo(
|
||||||
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
|
const Rc<DxvkShader>& shader,
|
||||||
|
const DxvkGraphicsPipelineStateInfo& state);
|
||||||
|
|
||||||
|
Rc<DxvkShader> getPrevStageShader(
|
||||||
|
const DxvkGraphicsPipelineShaders& shaders,
|
||||||
|
const VkShaderStageFlagBits stage);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Specialization constant state for pipelines
|
* \brief Specialization constant state for pipelines
|
||||||
*
|
*
|
||||||
@ -475,14 +513,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
SpirvCodeBuffer getShaderCode(
|
SpirvCodeBuffer getShaderCode(
|
||||||
const Rc<DxvkShader>& shader,
|
const Rc<DxvkShader>& shader,
|
||||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
const DxvkShaderModuleCreateInfo& info) const;
|
||||||
|
|
||||||
Rc<DxvkShader> getPrevStageShader(
|
|
||||||
VkShaderStageFlagBits stage) const;
|
|
||||||
|
|
||||||
bool writesRenderTarget(
|
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
|
||||||
uint32_t target) const;
|
|
||||||
|
|
||||||
uint32_t computeSpecConstantMask() const;
|
uint32_t computeSpecConstantMask() const;
|
||||||
|
|
||||||
|
@ -769,6 +769,16 @@ namespace dxvk {
|
|||||||
util::isDualSourceBlendFactor(omBlend[0].dstAlphaBlendFactor()));
|
util::isDualSourceBlendFactor(omBlend[0].dstAlphaBlendFactor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool writesRenderTarget(
|
||||||
|
uint32_t target) const {
|
||||||
|
if (!omBlend[target].colorWriteMask())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
VkFormat rtFormat = rt.getColorFormat(target);
|
||||||
|
return rtFormat != VK_FORMAT_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkIaInfo ia;
|
DxvkIaInfo ia;
|
||||||
DxvkIlInfo il;
|
DxvkIlInfo il;
|
||||||
DxvkRsInfo rs;
|
DxvkRsInfo rs;
|
||||||
|
Loading…
Reference in New Issue
Block a user