Add spirv-level support for splitting and combining sampler+image
- All of these objects are single pointers
- When consuming the result of OpSampledImage, look through to find the
pointer to the sampler descriptor
Remove the SampledImage kind as it's no longer necessary.
Test: dEQP-VK.image.*
Test: dEQP-VK.pipeline.*
Test: dEQP-VK.binding_model.*
Change-Id: I94f4cd8a3e5175c08f263fb464e61e5ba1043833
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29989
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Ben Clayton <bclayton@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 2c0a1ef..eb45c6c 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -559,14 +559,8 @@
case spv::StorageClassPushConstant:
case spv::StorageClassPrivate:
case spv::StorageClassFunction:
- break; // Correctly handled.
-
case spv::StorageClassUniformConstant:
- // This storage class is for data stored within the descriptor itself,
- // unlike StorageClassUniform which contains handles to buffers.
- // For Vulkan it corresponds with samplers, images, or combined image samplers.
- object.kind = Object::Kind::SampledImage;
- break;
+ break; // Correctly handled.
case spv::StorageClassWorkgroup:
case spv::StorageClassCrossWorkgroup:
@@ -711,6 +705,8 @@
case spv::OpLoad:
case spv::OpAccessChain:
case spv::OpInBoundsAccessChain:
+ case spv::OpSampledImage:
+ case spv::OpImage:
{
// Propagate the descriptor decorations to the result.
Object::ID resultId = insn.word(2);
@@ -2165,6 +2161,7 @@
case spv::OpTypeFunction:
case spv::OpTypeImage:
case spv::OpTypeSampledImage:
+ case spv::OpTypeSampler:
case spv::OpExecutionMode:
case spv::OpMemoryModel:
case spv::OpFunction:
@@ -2405,6 +2402,10 @@
case spv::OpImageTexelPointer:
return EmitImageTexelPointer(insn, state);
+ case spv::OpSampledImage:
+ case spv::OpImage:
+ return EmitSampledImageCombineOrSplit(insn, state);
+
default:
UNIMPLEMENTED("%s", OpcodeName(opcode).c_str());
break;
@@ -2508,10 +2509,8 @@
if(pointerTy.storageClass == spv::StorageClassUniformConstant)
{
// Just propagate the pointer.
- // TODO(b/129523279)
auto &ptr = routine->getPointer(pointerId);
routine->createPointer(resultId, ptr);
-
return EmitResult::Continue;
}
@@ -4484,13 +4483,18 @@
auto &resultType = getType(resultTypeId);
auto &result = state->routine->createIntermediate(resultId, resultType.sizeInComponents);
- auto &sampledImage = state->routine->getPointer(sampledImageId);
+ auto imageDescriptor = state->routine->getPointer(sampledImageId).base; // vk::SampledImageDescriptor*
+
+ // If using a separate sampler, look through the OpSampledImage instruction to find the sampler descriptor
+ auto &sampledImage = getObject(sampledImageId);
+ auto samplerDescriptor = (sampledImage.opcode() == spv::OpSampledImage) ?
+ state->routine->getPointer(sampledImage.definition.word(4)).base : imageDescriptor;
+
auto coordinate = GenericValue(this, state->routine, coordinateId);
auto &coordinateType = getType(coordinate.type);
- auto descriptor = sampledImage.base; // vk::SampledImageDescriptor*
- auto sampler = *Pointer<Pointer<Byte>>(descriptor + OFFSET(vk::SampledImageDescriptor, sampler)); // vk::Sampler*
- auto imageView = *Pointer<Pointer<Byte>>(descriptor + OFFSET(vk::SampledImageDescriptor, imageView)); // vk::ImageView*
+ auto sampler = *Pointer<Pointer<Byte>>(samplerDescriptor + OFFSET(vk::SampledImageDescriptor, sampler)); // vk::Sampler*
+ auto imageView = *Pointer<Pointer<Byte>>(imageDescriptor + OFFSET(vk::SampledImageDescriptor, imageView)); // vk::ImageView*
uint32_t imageOperands = spv::ImageOperandsMaskNone;
bool bias = false;
@@ -4607,7 +4611,7 @@
auto samplerFunc = Call(getImageSampler, instruction.parameters, imageView, sampler);
Array<SIMD::Float> out(4);
- Call<ImageSampler>(samplerFunc, sampledImage.base, &in[0], &out[0], state->routine->constants);
+ Call<ImageSampler>(samplerFunc, imageDescriptor, &in[0], &out[0], state->routine->constants);
for (int i = 0; i < 4; i++) { result.move(i, out[i]); }
@@ -5057,6 +5061,19 @@
return EmitResult::Continue;
}
+ SpirvShader::EmitResult SpirvShader::EmitSampledImageCombineOrSplit(InsnIterator insn, EmitState *state) const
+ {
+ // Propagate the image pointer in both cases.
+ // Consumers of OpSampledImage will look through to find the sampler pointer.
+
+ Object::ID resultId = insn.word(2);
+ Object::ID imageId = insn.word(3);
+
+ state->routine->createPointer(resultId, state->routine->getPointer(imageId));
+
+ return EmitResult::Continue;
+ }
+
SpirvShader::EmitResult SpirvShader::EmitAtomicOp(InsnIterator insn, EmitState *state) const
{
auto &resultType = getType(Type::ID(insn.word(1)));
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 0cc6e91..600547a 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -389,10 +389,6 @@
// A pointer to a vk::DescriptorSet*.
// Pointer held by SpirvRoutine::pointers.
DescriptorSet,
-
- // Pointer to an image/sampler descriptor.
- // Pointer held by SpirvRoutine::pointers.
- SampledImage,
};
Kind kind = Kind::Unknown;
@@ -880,6 +876,7 @@
EmitResult EmitImageTexelPointer(InsnIterator insn, EmitState *state) const;
EmitResult EmitAtomicOp(InsnIterator insn, EmitState *state) const;
EmitResult EmitAtomicCompareExchange(InsnIterator insn, EmitState *state) const;
+ EmitResult EmitSampledImageCombineOrSplit(InsnIterator insn, EmitState *state) const;
SIMD::Pointer GetTexelAddress(SpirvRoutine const * routine, SIMD::Pointer base, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize) const;