Commit 52a3bba8 by Chris Forbes

Add support for Sample image operand in OpImageRead

Enables reading from multisampled input attachments and storage images Bug: b/131171141 Test: dEQP-VK.renderpass.*.multisample.* Change-Id: I719d54c31eb12f58ba7fbdd614ecf3073bfc6d40 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30553 Presubmit-Ready: Chris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarChris Forbes <chrisforbes@google.com>
parent c958b171
......@@ -4756,7 +4756,7 @@ namespace sw
return EmitResult::Continue;
}
SIMD::Pointer SpirvShader::GetTexelAddress(SpirvRoutine const *routine, SIMD::Pointer ptr, GenericValue const & coordinate, Type const & imageType, Pointer<Byte> descriptor, int texelSize) 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) const
{
bool isArrayed = imageType.definition.word(5) != 0;
auto dim = static_cast<spv::Dim>(imageType.definition.word(3));
......@@ -4787,6 +4787,13 @@ namespace sw
*Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, slicePitchBytes)));
}
if (sampleId.value())
{
GenericValue sample{this, routine, sampleId};
ptr += sample.Int(0) * SIMD::Int(
*Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, samplePitchBytes)));
}
return ptr;
}
......@@ -4798,8 +4805,21 @@ namespace sw
auto &imageType = getType(image.type);
Object::ID resultId = insn.word(2);
// Not handling any image operands yet.
ASSERT(insn.wordCount() == 5);
Object::ID sampleId = 0;
if (insn.wordCount() > 5)
{
int operand = 6;
auto imageOperands = insn.word(5);
if (imageOperands & spv::ImageOperandsSampleMask)
{
sampleId = insn.word(operand++);
imageOperands &= ~spv::ImageOperandsSampleMask;
}
// Should be no remaining image operands.
ASSERT(!imageOperands);
}
ASSERT(imageType.definition.opcode() == spv::OpTypeImage);
auto dim = static_cast<spv::Dim>(imageType.definition.word(3));
......@@ -4821,7 +4841,7 @@ namespace sw
: SpirvFormatToVulkanFormat(static_cast<spv::ImageFormat>(imageType.definition.word(8)));
auto texelSize = vk::Format(vkFormat).bytes();
auto basePtr = SIMD::Pointer(imageBase, imageSizeInBytes);
auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize);
auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize, sampleId);
SIMD::Int packed[4];
// Round up texel size: for formats smaller than 32 bits per texel, we will emit a bunch
......@@ -5156,7 +5176,7 @@ namespace sw
}
auto basePtr = SIMD::Pointer(imageBase, imageSizeInBytes);
auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize);
auto texelPtr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, texelSize, 0);
for (auto i = 0u; i < numPackedElements; i++)
{
......@@ -5188,7 +5208,7 @@ namespace sw
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));
auto ptr = GetTexelAddress(state->routine, basePtr, coordinate, imageType, binding, sizeof(uint32_t), 0);
state->routine->createPointer(resultId, ptr);
......
......@@ -909,7 +909,7 @@ namespace sw
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) 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;
spv::Scope GetScope(Object::ID id) const;
// OpcodeName() returns the name of the opcode op.
......
......@@ -490,9 +490,10 @@ void DescriptorSetLayout::WriteDescriptorSet(DescriptorSet *dstSet, VkDescriptor
descriptor[i].ptr = imageView->getOffsetPointer({0, 0, 0}, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0);
descriptor[i].extent = imageView->getMipLevelExtent(0);
descriptor[i].rowPitchBytes = imageView->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
descriptor[i].slicePitchBytes = imageView->getSubresourceRange().layerCount > 1
? imageView->layerPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT)
: imageView->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
descriptor[i].samplePitchBytes = imageView->getSubresourceRange().layerCount > 1
? imageView->layerPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT)
: imageView->slicePitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
descriptor[i].slicePitchBytes = descriptor[i].samplePitchBytes * imageView->getSampleCount();
descriptor[i].arrayLayers = imageView->getSubresourceRange().layerCount;
descriptor[i].sizeInBytes = imageView->getImageSizeInBytes();
}
......@@ -508,6 +509,7 @@ void DescriptorSetLayout::WriteDescriptorSet(DescriptorSet *dstSet, VkDescriptor
descriptor[i].extent = {bufferView->getElementCount(), 1, 1};
descriptor[i].rowPitchBytes = 0;
descriptor[i].slicePitchBytes = 0;
descriptor[i].samplePitchBytes = 0;
descriptor[i].arrayLayers = 1;
descriptor[i].sizeInBytes = bufferView->getRangeInBytes();
}
......
......@@ -44,6 +44,7 @@ struct alignas(16) StorageImageDescriptor
VkExtent3D extent;
int rowPitchBytes;
int slicePitchBytes;
int samplePitchBytes;
int arrayLayers;
int sizeInBytes;
};
......
......@@ -45,12 +45,23 @@ public:
VkImageViewType getType() const { return viewType; }
Format getFormat(Usage usage = RAW) const;
int getSampleCount() const { return image->getSampleCountFlagBits(); }
int rowPitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
int slicePitchBytes(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
int layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage = RAW) const;
VkExtent3D getMipLevelExtent(uint32_t mipLevel) const;
int getSampleCount() const
{
switch (image->getSampleCountFlagBits())
{
case VK_SAMPLE_COUNT_1_BIT: return 1;
case VK_SAMPLE_COUNT_4_BIT: return 4;
default:
UNIMPLEMENTED("Sample count flags %d", image->getSampleCountFlagBits());
return 1;
}
}
void *getOffsetPointer(const VkOffset3D& offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer, Usage usage = RAW) const;
bool hasDepthAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; }
bool hasStencilAspect() const { return (subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment