Factor out GetTexelOffset from EmitImageRead/EmitImageWrite
Also fix the addressing to correctly use the slice pitch to advance to the correct layer in an arrayed 1D texture, rather than using the row pitch.
Bug: b/130768731
Test: dEQP-VK.image.*
Change-Id: I46b8c4eb353d7901d5953df46138ff9e01f87ead
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29411
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 301c0d6..c5df163 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -4412,6 +4412,32 @@
return EmitResult::Continue;
}
+ SIMD::Int SpirvShader::GetTexelOffset(GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize) const
+ {
+ // returns a (lane-divergent) byte offset to a texel within a storage image.
+ bool isArrayed = imageType.definition.word(5) != 0;
+ int dims = getType(coordinate.type).sizeInComponents - (isArrayed ? 1 : 0);
+
+ SIMD::Int texelOffset = coordinate.Int(0) * SIMD::Int(texelSize);
+ if (dims > 1)
+ {
+ texelOffset += coordinate.Int(1) * SIMD::Int(
+ *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, rowPitchBytes)));
+ }
+ if (dims > 2)
+ {
+ texelOffset += coordinate.Int(2) * SIMD::Int(
+ *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, slicePitchBytes)));
+ }
+ if (isArrayed)
+ {
+ texelOffset += coordinate.Int(dims) * SIMD::Int(
+ *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, slicePitchBytes)));
+ }
+
+ return texelOffset;
+ }
+
SpirvShader::EmitResult SpirvShader::EmitImageRead(InsnIterator insn, EmitState *state) const
{
auto &resultType = getType(Type::ID(insn.word(1)));
@@ -4438,7 +4464,6 @@
auto &dst = state->routine->createIntermediate(resultId, resultType.sizeInComponents);
-
SIMD::Int packed[4];
auto numPackedElements = 0u;
int texelSize = 0;
@@ -4483,17 +4508,7 @@
UNIMPLEMENTED("spv::ImageFormat %u", format);
}
- SIMD::Int texelOffset = coordinate.Int(0) * SIMD::Int(texelSize);
- if (getType(coordinate.type).sizeInComponents > 1)
- {
- texelOffset += coordinate.Int(1) * SIMD::Int(
- *Pointer<Int>(binding + OFFSET(vk::StorageImageDescriptor, rowPitchBytes)));
- }
- if (getType(coordinate.type).sizeInComponents > 2)
- {
- texelOffset += coordinate.Int(2) * SIMD::Int(
- *Pointer<Int>(binding + OFFSET(vk::StorageImageDescriptor, slicePitchBytes)));
- }
+ SIMD::Int texelOffset = GetTexelOffset(coordinate, imageType, binding, texelSize);
for (auto i = 0u; i < numPackedElements; i++)
{
@@ -4674,17 +4689,7 @@
UNIMPLEMENTED("spv::ImageFormat %u", format);
}
- SIMD::Int texelOffset = coordinate.Int(0) * SIMD::Int(texelSize);
- if (getType(coordinate.type).sizeInComponents > 1)
- {
- texelOffset += coordinate.Int(1) * SIMD::Int(
- *Pointer<Int>(binding + OFFSET(vk::StorageImageDescriptor, rowPitchBytes)));
- }
- if (getType(coordinate.type).sizeInComponents > 2)
- {
- texelOffset += coordinate.Int(2) * SIMD::Int(
- *Pointer<Int>(binding + OFFSET(vk::StorageImageDescriptor, slicePitchBytes)));
- }
+ SIMD::Int texelOffset = GetTexelOffset(coordinate, imageType, binding, texelSize);
for (auto i = 0u; i < numPackedElements; i++)
{
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index e394db1..69dd01e 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -727,6 +727,8 @@
EmitResult EmitImageRead(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageWrite(InsnIterator insn, EmitState *state) const;
+ SIMD::Int GetTexelOffset(GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize) const;
+
// OpcodeName() returns the name of the opcode op.
// If NDEBUG is defined, then OpcodeName() will only return the numerical code.
static std::string OpcodeName(spv::Op op);