Determine SPIR-V zero constants from SPIR-V binary only
Previously the Operand::isConstantZero() method would tell us whether
an operand passed to an instruction is actually a constant expression
with a value of zero. However, the Operand class is a wrapper for
Reactor variables, which also supports constants, so we need to be
actively emitting the Reactor routine that compiles the SPIR-V code, to
use it.
Since determining whether an object represents a value of zero can be
done entirely from the SPIR-V code alone, this change moves this method
to the Object class.
Concretely it has the advantage of being able to tell whether an image
instruction has a Sample operand which is zero, so it ca be ignored,
without passing around the EmitState pointer.
Bug: b/203730083
Change-Id: Ie8e6eb819802d5f9662c727ef81d04f47a9610ad
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/59409
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 2666ef5..59a2c0c 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -940,7 +940,7 @@
uint32_t packedInterpolant = 0;
for(uint32_t i = 0; i < maxInterpolant; ++i)
{
- if (inputs[i].Type != ATTRIBTYPE_UNUSED)
+ if(inputs[i].Type != ATTRIBTYPE_UNUSED)
{
++packedInterpolant;
}
@@ -2564,16 +2564,16 @@
{
}
-bool SpirvShader::Operand::isConstantZero() const
+bool SpirvShader::Object::isConstantZero() const
{
- if(!constant)
+ if(kind != Kind::Constant)
{
return false;
}
- for(uint32_t i = 0; i < componentCount; i++)
+ for(uint32_t i = 0; i < constantValue.size(); i++)
{
- if(constant[i] != 0)
+ if(constantValue[i] != 0)
{
return false;
}
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 1d8e5f6..26b3b6a 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -327,6 +327,8 @@
Type::ID typeId() const { return definition.resultTypeId(); }
Object::ID id() const { return definition.resultId(); }
+ bool isConstantZero() const;
+
InsnIterator definition;
std::vector<uint32_t> constantValue;
@@ -1158,8 +1160,6 @@
return SIMD::UInt(constant[i]);
}
- bool isConstantZero() const;
-
private:
RR_PRINT_ONLY(friend struct rr::PrintValue::Ty<Operand>;)
diff --git a/src/Pipeline/SpirvShaderImage.cpp b/src/Pipeline/SpirvShaderImage.cpp
index c048426..4c59e71 100644
--- a/src/Pipeline/SpirvShaderImage.cpp
+++ b/src/Pipeline/SpirvShaderImage.cpp
@@ -167,7 +167,7 @@
operandsIndex += 1;
imageOperands &= ~spv::ImageOperandsSampleMask;
- sample = true;
+ sample = !spirv.getObject(sampleId).isConstantZero();
}
// TODO(b/174475384)
@@ -619,9 +619,9 @@
SIMD::Int n = 0;
if(sampleId != 0)
{
- Operand sample(this, state, sampleId);
- if(!sample.isConstantZero())
+ if(!getObject(sampleId).isConstantZero())
{
+ Operand sample(this, state, sampleId);
n = sample.Int(0);
ptrOffset += n * samplePitch;
}
@@ -649,8 +649,7 @@
if(sampleId != 0)
{
- Operand sample(this, state, sampleId);
- if(!sample.isConstantZero())
+ if(!getObject(sampleId).isConstantZero())
{
SIMD::UInt sampleCount = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, sampleCount));
oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(n), sampleCount));