Add workaround to avoid non-2D Dref explicit lod samples on Qualcomm

This commit is contained in:
baldurk
2020-05-15 11:33:40 +01:00
parent e37c420263
commit 96e34db93d
3 changed files with 80 additions and 56 deletions
+2 -1
View File
@@ -942,7 +942,8 @@ VkDriverInfo::VkDriverInfo(const VkPhysicalDeviceProperties &physProps)
#endif
// not fixed yet
qualcommLeakingUBOOffsets = m_Vendor == GPUVendor::Qualcomm;
qualcommLeakingUBOOffsets = (m_Vendor == GPUVendor::Qualcomm);
qualcommDrefNon2DCompileCrash = (m_Vendor == GPUVendor::Qualcomm);
}
FrameRefType GetRefType(VkDescriptorType descType)
+4
View File
@@ -252,6 +252,9 @@ public:
// On Qualcomm it seems like binding a descriptor set with a dynamic offset will 'leak' and affect
// rendering on other descriptor sets that don't use offsets at all.
bool QualcommLeakingUBOOffsets() { return qualcommLeakingUBOOffsets; }
// On Qualcomm emitting an image sample operation with DRef and explicit lod will crash on non-2D
// textures. Since 2D is the common/expected case, we avoid compiling that case entirely.
bool QualcommDrefNon2DCompileCrash() { return qualcommDrefNon2DCompileCrash; }
private:
GPUVendor m_Vendor;
@@ -262,6 +265,7 @@ private:
bool unreliableImgMemReqs = false;
bool amdStorageMSAABrokenDriver = false;
bool qualcommLeakingUBOOffsets = false;
bool qualcommDrefNon2DCompileCrash = false;
};
enum
+74 -55
View File
@@ -811,6 +811,15 @@ public:
case rdcspv::Op::ImageSampleProjDrefImplicitLod:
{
useCompare = true;
if(m_pDriver->GetDriverInfo().QualcommDrefNon2DCompileCrash() &&
constParams.dim != ShaderDebugBind::Tex2D)
{
m_pDriver->AddDebugMessage(
MessageCategory::Execution, MessageSeverity::High, MessageSource::RuntimeWarning,
"Dref sample against non-2D texture, this cannot be debugged due to a driver bug");
}
break;
}
default: break;
@@ -2305,66 +2314,76 @@ private:
cases.add(rdcspv::OpBranch(breakLabel));
}
for(rdcspv::Op op :
{rdcspv::Op::ImageSampleDrefExplicitLod, rdcspv::Op::ImageSampleDrefImplicitLod})
bool emitDRef = true;
// on Qualcomm we only emit Dref instructions against 2D textures, otherwise the compiler may
// crash.
if(m_pDriver->GetDriverInfo().QualcommDrefNon2DCompileCrash())
emitDRef = (i == (uint32_t)ShaderDebugBind::Tex2D);
if(emitDRef)
{
rdcspv::Id label = editor.MakeId();
targets.push_back({(uint32_t)op * 10 + i, label});
rdcspv::ImageOperandsAndParamDatas imageOperands;
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended && offsets[i] != rdcspv::Id())
imageOperands.setOffset(offsets[i]);
cases.add(rdcspv::OpLabel(label));
rdcspv::Id loadedImage =
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), bindVars[i]));
rdcspv::Id loadedSampler =
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), bindVars[sampIdx]));
rdcspv::Id mergeLabel = editor.MakeId();
rdcspv::Id gradCase = editor.MakeId();
rdcspv::Id lodCase = editor.MakeId();
cases.add(rdcspv::OpSelectionMerge(mergeLabel, rdcspv::SelectionControl::None));
cases.add(rdcspv::OpBranchConditional(useGradOrGatherOffsets, gradCase, lodCase));
rdcspv::Id lodResult;
for(rdcspv::Op op :
{rdcspv::Op::ImageSampleDrefExplicitLod, rdcspv::Op::ImageSampleDrefImplicitLod})
{
cases.add(rdcspv::OpLabel(lodCase));
rdcspv::ImageOperandsAndParamDatas operands = imageOperands;
operands.setLod(lod);
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
rdcspv::Id label = editor.MakeId();
targets.push_back({(uint32_t)op * 10 + i, label});
lodResult = cases.add(rdcspv::OpImageSampleDrefExplicitLod(
scalarResultType, editor.MakeId(), combined, coord[i], compare, operands));
rdcspv::ImageOperandsAndParamDatas imageOperands;
cases.add(rdcspv::OpBranch(mergeLabel));
if(m_pDriver->GetDeviceFeatures().shaderImageGatherExtended && offsets[i] != rdcspv::Id())
imageOperands.setOffset(offsets[i]);
cases.add(rdcspv::OpLabel(label));
rdcspv::Id loadedImage =
cases.add(rdcspv::OpLoad(texSampTypes[i], editor.MakeId(), bindVars[i]));
rdcspv::Id loadedSampler =
cases.add(rdcspv::OpLoad(texSampTypes[sampIdx], editor.MakeId(), bindVars[sampIdx]));
rdcspv::Id mergeLabel = editor.MakeId();
rdcspv::Id gradCase = editor.MakeId();
rdcspv::Id lodCase = editor.MakeId();
cases.add(rdcspv::OpSelectionMerge(mergeLabel, rdcspv::SelectionControl::None));
cases.add(rdcspv::OpBranchConditional(useGradOrGatherOffsets, gradCase, lodCase));
rdcspv::Id lodResult;
{
cases.add(rdcspv::OpLabel(lodCase));
rdcspv::ImageOperandsAndParamDatas operands = imageOperands;
operands.setLod(lod);
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
lodResult = cases.add(rdcspv::OpImageSampleDrefExplicitLod(
scalarResultType, editor.MakeId(), combined, coord[i], compare, operands));
cases.add(rdcspv::OpBranch(mergeLabel));
}
rdcspv::Id gradResult;
{
cases.add(rdcspv::OpLabel(gradCase));
rdcspv::ImageOperandsAndParamDatas operands = imageOperands;
operands.setGrad(ddxs[i], ddys[i]);
if(m_pDriver->GetDeviceFeatures().shaderResourceMinLod)
operands.setMinLod(minlod);
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
gradResult = cases.add(rdcspv::OpImageSampleDrefExplicitLod(
scalarResultType, editor.MakeId(), combined, coord[i], compare, operands));
cases.add(rdcspv::OpBranch(mergeLabel));
}
cases.add(rdcspv::OpLabel(mergeLabel));
rdcspv::Id scalarSampleResult = cases.add(rdcspv::OpPhi(
scalarResultType, editor.MakeId(), {{lodResult, lodCase}, {gradResult, gradCase}}));
rdcspv::Id sampleResult = cases.add(rdcspv::OpCompositeConstruct(
resultType, editor.MakeId(), {scalarSampleResult, zerof, zerof, zerof}));
cases.add(rdcspv::OpStore(outVar, sampleResult));
cases.add(rdcspv::OpBranch(breakLabel));
}
rdcspv::Id gradResult;
{
cases.add(rdcspv::OpLabel(gradCase));
rdcspv::ImageOperandsAndParamDatas operands = imageOperands;
operands.setGrad(ddxs[i], ddys[i]);
if(m_pDriver->GetDeviceFeatures().shaderResourceMinLod)
operands.setMinLod(minlod);
rdcspv::Id combined = cases.add(rdcspv::OpSampledImage(
texSampCombinedTypes[i], editor.MakeId(), loadedImage, loadedSampler));
gradResult = cases.add(rdcspv::OpImageSampleDrefExplicitLod(
scalarResultType, editor.MakeId(), combined, coord[i], compare, operands));
cases.add(rdcspv::OpBranch(mergeLabel));
}
cases.add(rdcspv::OpLabel(mergeLabel));
rdcspv::Id scalarSampleResult = cases.add(rdcspv::OpPhi(
scalarResultType, editor.MakeId(), {{lodResult, lodCase}, {gradResult, gradCase}}));
rdcspv::Id sampleResult = cases.add(rdcspv::OpCompositeConstruct(
resultType, editor.MakeId(), {scalarSampleResult, zerof, zerof, zerof}));
cases.add(rdcspv::OpStore(outVar, sampleResult));
cases.add(rdcspv::OpBranch(breakLabel));
}
// can only gather with 2D/Cube textures