Support selection of correct aspect for D+S input attachments
Test: dEQP-VK.*d32_sfloat_s8_uint*
Bug: b/123244275
Bug: b/131171141
Change-Id: Ic13fee99754e78619c7769000a666c90a5c56218
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30748
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 2c912c7..b3baaba 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -4756,7 +4756,7 @@
return EmitResult::Continue;
}
- SIMD::Pointer SpirvShader::GetTexelAddress(SpirvRoutine const *routine, SIMD::Pointer ptr, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize, Object::ID sampleId) const
+ SIMD::Pointer SpirvShader::GetTexelAddress(SpirvRoutine const *routine, SIMD::Pointer ptr, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize, Object::ID sampleId, bool useStencilAspect) const
{
bool isArrayed = imageType.definition.word(5) != 0;
auto dim = static_cast<spv::Dim>(imageType.definition.word(3));
@@ -4770,28 +4770,44 @@
v += routine->windowSpacePosition[1];
}
+ if (useStencilAspect)
+ {
+ // Adjust addressing for quad layout. Pitches are already correct for the stencil aspect.
+ // In the quad-layout block, pixel order is [x0,y0 x1,y0 x0,y1 x1,y1]
+ u = ((v & SIMD::Int(1)) << 1) | ((u << 1) - (u & SIMD::Int(1)));
+ v &= SIMD::Int(~1);
+ }
+
+ auto rowPitch = SIMD::Int(*Pointer<Int>(descriptor + (useStencilAspect
+ ? OFFSET(vk::StorageImageDescriptor, stencilRowPitchBytes)
+ : OFFSET(vk::StorageImageDescriptor, rowPitchBytes))));
+ auto slicePitch = SIMD::Int(
+ *Pointer<Int>(descriptor + (useStencilAspect
+ ? OFFSET(vk::StorageImageDescriptor, stencilSlicePitchBytes)
+ : OFFSET(vk::StorageImageDescriptor, slicePitchBytes))));
+ auto samplePitch = SIMD::Int(
+ *Pointer<Int>(descriptor + (useStencilAspect
+ ? OFFSET(vk::StorageImageDescriptor, stencilSamplePitchBytes)
+ : OFFSET(vk::StorageImageDescriptor, samplePitchBytes))));
+
ptr += u * SIMD::Int(texelSize);
if (dims > 1)
{
- ptr += v * SIMD::Int(
- *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, rowPitchBytes)));
+ ptr += v * rowPitch;
}
if (dims > 2)
{
- ptr += coordinate.Int(2) * SIMD::Int(
- *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, slicePitchBytes)));
+ ptr += coordinate.Int(2) * slicePitch;
}
if (isArrayed)
{
- ptr += coordinate.Int(dims) * SIMD::Int(
- *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, slicePitchBytes)));
+ ptr += coordinate.Int(dims) * slicePitch;
}
if (sampleId.value())
{
GenericValue sample{this, routine, sampleId};
- ptr += sample.Int(0) * SIMD::Int(
- *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, samplePitchBytes)));
+ ptr += sample.Int(0) * samplePitch;
}
return ptr;
@@ -4825,23 +4841,37 @@
auto dim = static_cast<spv::Dim>(imageType.definition.word(3));
auto coordinate = GenericValue(this, state->routine, insn.word(4));
-
- auto pointer = state->routine->getPointer(imageId);
- Pointer<Byte> binding = pointer.base;
- Pointer<Byte> imageBase = *Pointer<Pointer<Byte>>(binding + OFFSET(vk::StorageImageDescriptor, ptr));
const DescriptorDecorations &d = descriptorDecorations.at(imageId);
- auto imageSizeInBytes = *Pointer<Int>(binding + OFFSET(vk::StorageImageDescriptor, sizeInBytes));
-
- auto &dst = state->routine->createIntermediate(resultId, resultType.sizeInComponents);
// For subpass data, format in the instruction is spv::ImageFormatUnknown. Get it from
// the renderpass data instead. In all other cases, we can use the format in the instruction.
auto vkFormat = (dim == spv::DimSubpassData)
? inputAttachmentFormats[d.InputAttachmentIndex]
: SpirvFormatToVulkanFormat(static_cast<spv::ImageFormat>(imageType.definition.word(8)));
+
+ // Depth+Stencil image attachments select aspect based on the Sampled Type of the
+ // OpTypeImage. If float, then we want the depth aspect. If int, we want the stencil aspect.
+ auto useStencilAspect = (vkFormat == VK_FORMAT_D32_SFLOAT_S8_UINT &&
+ getType(imageType.definition.word(2)).opcode() == spv::OpTypeInt);
+
+ if (useStencilAspect)
+ {
+ vkFormat = VK_FORMAT_S8_UINT;
+ }
+
+ auto pointer = state->routine->getPointer(imageId);
+ Pointer<Byte> binding = pointer.base;
+ Pointer<Byte> imageBase = *Pointer<Pointer<Byte>>(binding + (useStencilAspect
+ ? OFFSET(vk::StorageImageDescriptor, stencilPtr)
+ : OFFSET(vk::StorageImageDescriptor, ptr)));
+
+ auto imageSizeInBytes = *Pointer<Int>(binding + OFFSET(vk::StorageImageDescriptor, sizeInBytes));
+
+ auto &dst = state->routine->createIntermediate(resultId, resultType.sizeInComponents);
+
auto texelSize = vk::Format(vkFormat).bytes();
auto basePtr = SIMD::Pointer(imageBase, imageSizeInBytes);
- auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize, sampleId);
+ auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize, sampleId, useStencilAspect);
SIMD::Int packed[4];
// Round up texel size: for formats smaller than 32 bits per texel, we will emit a bunch
@@ -4876,7 +4906,7 @@
break;
case VK_FORMAT_R32_SFLOAT:
case VK_FORMAT_D32_SFLOAT:
- //case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
dst.move(0, packed[0]);
// Fill remaining channels with 0,0,1 (of the correct type)
dst.move(1, SIMD::Float(0));
@@ -4960,6 +4990,7 @@
dst.move(3, SIMD::Float(1));
break;
case VK_FORMAT_R8_UINT:
+ case VK_FORMAT_S8_UINT:
dst.move(0, (As<SIMD::UInt>(packed[0]) & SIMD::UInt(0xFF)));
dst.move(1, SIMD::UInt(0));
dst.move(2, SIMD::UInt(0));
@@ -5176,7 +5207,7 @@
}
auto basePtr = SIMD::Pointer(imageBase, imageSizeInBytes);
- auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize, 0);
+ auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize, 0, false);
for (auto i = 0u; i < numPackedElements; i++)
{
@@ -5208,7 +5239,7 @@
auto imageSizeInBytes = *Pointer<Int>(binding + OFFSET(vk::StorageImageDescriptor, sizeInBytes));
auto basePtr = SIMD::Pointer(imageBase, imageSizeInBytes);
- auto ptr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, sizeof(uint32_t), 0);
+ auto ptr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, sizeof(uint32_t), 0, false);
state->routine->createPointer(resultId, ptr);
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index b893073..de4c03b 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -909,7 +909,7 @@
EmitResult EmitCopyMemory(InsnIterator insn, EmitState *state) const;
EmitResult EmitGroupNonUniform(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, Object::ID sampleId) const;
+ SIMD::Pointer GetTexelAddress(SpirvRoutine const * routine, SIMD::Pointer base, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize, Object::ID sampleId, bool useStencilAspect) const;
spv::Scope GetScope(Object::ID id) const;
// OpcodeName() returns the name of the opcode op.
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index d44bbab..e0b9346 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -496,6 +496,16 @@
descriptor[i].slicePitchBytes = descriptor[i].samplePitchBytes * imageView->getSampleCount();
descriptor[i].arrayLayers = imageView->getSubresourceRange().layerCount;
descriptor[i].sizeInBytes = imageView->getImageSizeInBytes();
+
+ if (imageView->getFormat().isStencil())
+ {
+ descriptor[i].stencilPtr = imageView->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0);
+ descriptor[i].stencilRowPitchBytes = imageView->rowPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
+ descriptor[i].stencilSamplePitchBytes = imageView->getSubresourceRange().layerCount > 1
+ ? imageView->layerPitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT)
+ : imageView->slicePitchBytes(VK_IMAGE_ASPECT_STENCIL_BIT, 0);
+ descriptor[i].stencilSlicePitchBytes = descriptor[i].stencilSamplePitchBytes * imageView->getSampleCount();
+ }
}
}
else if (entry.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
diff --git a/src/Vulkan/VkDescriptorSetLayout.hpp b/src/Vulkan/VkDescriptorSetLayout.hpp
index 38722d5..4a1a444 100644
--- a/src/Vulkan/VkDescriptorSetLayout.hpp
+++ b/src/Vulkan/VkDescriptorSetLayout.hpp
@@ -47,6 +47,11 @@
int samplePitchBytes;
int arrayLayers;
int sizeInBytes;
+
+ void *stencilPtr;
+ int stencilRowPitchBytes;
+ int stencilSlicePitchBytes;
+ int stencilSamplePitchBytes;
};
struct alignas(16) BufferDescriptor