mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +01:00
[dxvk] Patch fragment shader for dual-source blending
This commit is contained in:
parent
f69c5e4c4e
commit
e744117042
@ -36,7 +36,10 @@ namespace dxvk {
|
||||
slotMapping.bindingInfos(),
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE);
|
||||
|
||||
m_cs = cs->createShaderModule(m_vkd, slotMapping);
|
||||
DxvkShaderModuleCreateInfo moduleInfo;
|
||||
moduleInfo.fsDualSrcBlend = false;
|
||||
|
||||
m_cs = cs->createShaderModule(m_vkd, slotMapping, moduleInfo);
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,11 +61,18 @@ namespace dxvk {
|
||||
slotMapping.bindingInfos(),
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS);
|
||||
|
||||
if (vs != nullptr) m_vs = vs ->createShaderModule(m_vkd, slotMapping);
|
||||
if (tcs != nullptr) m_tcs = tcs->createShaderModule(m_vkd, slotMapping);
|
||||
if (tes != nullptr) m_tes = tes->createShaderModule(m_vkd, slotMapping);
|
||||
if (gs != nullptr) m_gs = gs ->createShaderModule(m_vkd, slotMapping);
|
||||
if (fs != nullptr) m_fs = fs ->createShaderModule(m_vkd, slotMapping);
|
||||
DxvkShaderModuleCreateInfo moduleInfo;
|
||||
moduleInfo.fsDualSrcBlend = true;
|
||||
|
||||
DxvkShaderModuleCreateInfo moduleInfoDualSrc;
|
||||
moduleInfoDualSrc.fsDualSrcBlend = true;
|
||||
|
||||
if (vs != nullptr) m_vs = vs ->createShaderModule(m_vkd, slotMapping, moduleInfo);
|
||||
if (tcs != nullptr) m_tcs = tcs->createShaderModule(m_vkd, slotMapping, moduleInfo);
|
||||
if (tes != nullptr) m_tes = tes->createShaderModule(m_vkd, slotMapping, moduleInfo);
|
||||
if (gs != nullptr) m_gs = gs ->createShaderModule(m_vkd, slotMapping, moduleInfo);
|
||||
if (fs != nullptr) m_fs = fs ->createShaderModule(m_vkd, slotMapping, moduleInfo);
|
||||
if (fs != nullptr) m_fs2 = fs ->createShaderModule(m_vkd, slotMapping, moduleInfoDualSrc);
|
||||
|
||||
m_vsIn = vs != nullptr ? vs->interfaceSlots().inputSlots : 0;
|
||||
m_fsOut = fs != nullptr ? fs->interfaceSlots().outputSlots : 0;
|
||||
@ -200,12 +207,20 @@ namespace dxvk {
|
||||
specInfo.pData = &specData;
|
||||
|
||||
std::vector<VkPipelineShaderStageCreateInfo> stages;
|
||||
|
||||
|
||||
bool useDualSrcBlend = state.omBlendAttachments[0].blendEnable && (
|
||||
util::isDualSourceBlendFactor(state.omBlendAttachments[0].srcColorBlendFactor) ||
|
||||
util::isDualSourceBlendFactor(state.omBlendAttachments[0].dstColorBlendFactor) ||
|
||||
util::isDualSourceBlendFactor(state.omBlendAttachments[0].srcAlphaBlendFactor) ||
|
||||
util::isDualSourceBlendFactor(state.omBlendAttachments[0].dstAlphaBlendFactor));
|
||||
|
||||
Rc<DxvkShaderModule> fs = useDualSrcBlend ? m_fs2 : m_fs;
|
||||
|
||||
if (m_vs != nullptr) stages.push_back(m_vs->stageInfo(&specInfo));
|
||||
if (m_tcs != nullptr) stages.push_back(m_tcs->stageInfo(&specInfo));
|
||||
if (m_tes != nullptr) stages.push_back(m_tes->stageInfo(&specInfo));
|
||||
if (m_gs != nullptr) stages.push_back(m_gs->stageInfo(&specInfo));
|
||||
if (m_fs != nullptr) stages.push_back(m_fs->stageInfo(&specInfo));
|
||||
if (fs != nullptr) stages.push_back(fs->stageInfo(&specInfo));
|
||||
|
||||
// Fix up color write masks using the component mappings
|
||||
std::array<VkPipelineColorBlendAttachmentState, MaxNumRenderTargets> omBlendAttachments;
|
||||
|
@ -229,6 +229,7 @@ namespace dxvk {
|
||||
Rc<DxvkShaderModule> m_tes;
|
||||
Rc<DxvkShaderModule> m_gs;
|
||||
Rc<DxvkShaderModule> m_fs;
|
||||
Rc<DxvkShaderModule> m_fs2;
|
||||
|
||||
uint32_t m_vsIn = 0;
|
||||
uint32_t m_fsOut = 0;
|
||||
|
@ -91,11 +91,22 @@ namespace dxvk {
|
||||
|
||||
// Gather the offsets where the binding IDs
|
||||
// are stored so we can quickly remap them.
|
||||
uint32_t o1VarId = 0;
|
||||
|
||||
for (auto ins : m_code) {
|
||||
if (ins.opCode() == spv::OpDecorate
|
||||
&& ((ins.arg(2) == spv::DecorationBinding)
|
||||
|| (ins.arg(2) == spv::DecorationSpecId)))
|
||||
m_idOffsets.push_back(ins.offset() + 3);
|
||||
if (ins.opCode() == spv::OpDecorate) {
|
||||
if (ins.arg(2) == spv::DecorationBinding
|
||||
|| ins.arg(2) == spv::DecorationSpecId)
|
||||
m_idOffsets.push_back(ins.offset() + 3);
|
||||
|
||||
if (ins.arg(2) == spv::DecorationLocation && ins.arg(3) == 1) {
|
||||
m_o1LocOffset = ins.offset() + 3;
|
||||
o1VarId = ins.arg(1);
|
||||
}
|
||||
|
||||
if (ins.arg(2) == spv::DecorationIndex && ins.arg(1) == o1VarId)
|
||||
m_o1IdxOffset = ins.offset() + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,15 +139,21 @@ namespace dxvk {
|
||||
|
||||
Rc<DxvkShaderModule> DxvkShader::createShaderModule(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkDescriptorSlotMapping& mapping) {
|
||||
const DxvkDescriptorSlotMapping& mapping,
|
||||
const DxvkShaderModuleCreateInfo& info) {
|
||||
SpirvCodeBuffer spirvCode = m_code;
|
||||
uint32_t* code = spirvCode.data();
|
||||
|
||||
// Remap resource binding IDs
|
||||
uint32_t* code = spirvCode.data();
|
||||
for (uint32_t ofs : m_idOffsets) {
|
||||
if (code[ofs] < MaxNumResourceSlots)
|
||||
code[ofs] = mapping.getBindingId(code[ofs]);
|
||||
}
|
||||
|
||||
// For dual-source blending we need to re-map
|
||||
// location 1, index 0 to location 0, index 1
|
||||
if (info.fsDualSrcBlend && m_o1IdxOffset && m_o1LocOffset)
|
||||
std::swap(code[m_o1IdxOffset], code[m_o1LocOffset]);
|
||||
|
||||
return new DxvkShaderModule(vkd, this, spirvCode);
|
||||
}
|
||||
|
@ -101,6 +101,14 @@ namespace dxvk {
|
||||
uint32_t* m_data = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Shader module create info
|
||||
*/
|
||||
struct DxvkShaderModuleCreateInfo {
|
||||
bool fsDualSrcBlend;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -162,11 +170,13 @@ namespace dxvk {
|
||||
* Maps the binding slot numbers
|
||||
* \param [in] vkd Vulkan device functions
|
||||
* \param [in] mapping Resource slot mapping
|
||||
* \param [in] info Module create info
|
||||
* \returns The shader module
|
||||
*/
|
||||
Rc<DxvkShaderModule> createShaderModule(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkDescriptorSlotMapping& mapping);
|
||||
const DxvkDescriptorSlotMapping& mapping,
|
||||
const DxvkShaderModuleCreateInfo& info);
|
||||
|
||||
/**
|
||||
* \brief Inter-stage interface slots
|
||||
@ -242,6 +252,9 @@ namespace dxvk {
|
||||
DxvkShaderOptions m_options;
|
||||
DxvkShaderConstData m_constData;
|
||||
DxvkShaderKey m_key;
|
||||
|
||||
size_t m_o1IdxOffset = 0;
|
||||
size_t m_o1LocOffset = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -149,4 +149,12 @@ namespace dxvk::util {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool isDualSourceBlendFactor(VkBlendFactor factor) {
|
||||
return factor == VK_BLEND_FACTOR_SRC1_COLOR
|
||||
|| factor == VK_BLEND_FACTOR_SRC1_ALPHA
|
||||
|| factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
|
||||
|| factor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -212,4 +212,7 @@ namespace dxvk::util {
|
||||
VkComponentSwizzle component,
|
||||
uint32_t identity);
|
||||
|
||||
bool isDualSourceBlendFactor(
|
||||
VkBlendFactor factor);
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user