Commit b400b97d by Nicolas Capens Committed by Nicolas Capens

Refactor image query instructions

OpImageQuerySize[Lod] SPIR-V instructions were previously implemented by storing both the image depth and layer count in the descriptor. Since 3D textures can't be arrayed, we only need one field. Also avoid the division by 6 for cube array layers in the instruction implementation, by performing it during the descriptor update instead. This reflects a similar change made by https://swiftshader-review.googlesource.com/c/SwiftShader/+/47388 Bug: b/162315264 Change-Id: Iaa787e6c131eec2da7e4a404743ef722423305d5 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/47688 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com>
parent 622558b0
...@@ -374,62 +374,58 @@ void SpirvShader::GetImageDimensions(EmitState const *state, Type const &resultT ...@@ -374,62 +374,58 @@ void SpirvShader::GetImageDimensions(EmitState const *state, Type const &resultT
ASSERT(imageType.definition.opcode() == spv::OpTypeImage); ASSERT(imageType.definition.opcode() == spv::OpTypeImage);
bool isArrayed = imageType.definition.word(5) != 0; bool isArrayed = imageType.definition.word(5) != 0;
bool isCubeMap = imageType.definition.word(3) == spv::DimCube; uint32_t dimensions = resultTy.componentCount - (isArrayed ? 1 : 0);
const DescriptorDecorations &d = descriptorDecorations.at(imageId); const DescriptorDecorations &d = descriptorDecorations.at(imageId);
auto descriptorType = routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding); auto descriptorType = routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base; Pointer<Byte> descriptor = state->getPointer(imageId).base;
Pointer<Int> extent; Int width;
Int arrayLayers; Int height;
Int depth;
switch(descriptorType) switch(descriptorType)
{ {
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
{ width = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, width));
extent = descriptor + OFFSET(vk::StorageImageDescriptor, extent); // int[3]* height = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, height));
arrayLayers = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, arrayLayers)); // uint32_t depth = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, depth));
break; break;
}
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
{ width = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, width));
extent = descriptor + OFFSET(vk::SampledImageDescriptor, extent); // int[3]* height = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, height));
arrayLayers = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, arrayLayers)); // uint32_t depth = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, depth));
break; break;
}
default: default:
UNREACHABLE("Image descriptorType: %d", int(descriptorType)); UNREACHABLE("Image descriptorType: %d", int(descriptorType));
} }
auto dimensions = resultTy.componentCount - (isArrayed ? 1 : 0);
std::vector<Int> out;
if(lodId != 0) if(lodId != 0)
{ {
auto lodVal = Operand(this, state, lodId); auto lodVal = Operand(this, state, lodId);
ASSERT(lodVal.componentCount == 1); ASSERT(lodVal.componentCount == 1);
auto lod = lodVal.Int(0); auto lod = lodVal.Int(0);
auto one = SIMD::Int(1); auto one = SIMD::Int(1);
for(uint32_t i = 0; i < dimensions; i++)
{ if(dimensions >= 1) dst.move(0, Max(SIMD::Int(width) >> lod, one));
dst.move(i, Max(SIMD::Int(extent[i]) >> lod, one)); if(dimensions >= 2) dst.move(1, Max(SIMD::Int(height) >> lod, one));
} if(dimensions >= 3) dst.move(2, Max(SIMD::Int(depth) >> lod, one));
} }
else else
{ {
for(uint32_t i = 0; i < dimensions; i++)
{ if(dimensions >= 1) dst.move(0, SIMD::Int(width));
dst.move(i, SIMD::Int(extent[i])); if(dimensions >= 2) dst.move(1, SIMD::Int(height));
} if(dimensions >= 3) dst.move(2, SIMD::Int(depth));
} }
if(isArrayed) if(isArrayed)
{ {
auto numElements = isCubeMap ? (arrayLayers / 6) : RValue<Int>(arrayLayers); dst.move(dimensions, SIMD::Int(depth));
dst.move(dimensions, SIMD::Int(numElements));
} }
} }
...@@ -570,20 +566,20 @@ SIMD::Pointer SpirvShader::GetTexelAddress(EmitState const *state, Pointer<Byte> ...@@ -570,20 +566,20 @@ SIMD::Pointer SpirvShader::GetTexelAddress(EmitState const *state, Pointer<Byte>
// Other out-of-bounds behaviors work properly by just comparing the offset against the total size. // Other out-of-bounds behaviors work properly by just comparing the offset against the total size.
if(outOfBoundsBehavior == OutOfBoundsBehavior::Nullify) if(outOfBoundsBehavior == OutOfBoundsBehavior::Nullify)
{ {
auto width = SIMD::UInt(*Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, extent.width))); SIMD::UInt width = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, width));
SIMD::Int oobMask = As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(u), width)); SIMD::Int oobMask = As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(u), width));
if(dims > 1) if(dims > 1)
{ {
auto height = SIMD::UInt(*Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, extent.height))); SIMD::UInt height = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, height));
oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(v), height)); oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(v), height));
} }
if((dims > 2) || isArrayed) if((dims > 2) || isArrayed)
{ {
auto depth = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, extent.depth)); UInt depth = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, depth));
auto arrayLayers = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, arrayLayers)); if(dim == spv::DimCube) { depth *= 6; }
oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(w), SIMD::UInt(depth * arrayLayers))); // TODO: Precompute extent. 3D image can't have layers. oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(w), SIMD::UInt(depth)));
} }
if(sampleId.value()) if(sampleId.value())
......
...@@ -44,8 +44,9 @@ struct alignas(16) SampledImageDescriptor ...@@ -44,8 +44,9 @@ struct alignas(16) SampledImageDescriptor
VkFormat format; VkFormat format;
VkComponentMapping swizzle; VkComponentMapping swizzle;
alignas(16) sw::Texture texture; alignas(16) sw::Texture texture;
VkExtent3D extent; // Of base mip-level. int width; // Of base mip-level.
int arrayLayers; int height;
int depth; // Layer/cube count for arrayed images
int mipLevels; int mipLevels;
int sampleCount; int sampleCount;
...@@ -57,11 +58,12 @@ struct alignas(16) StorageImageDescriptor ...@@ -57,11 +58,12 @@ struct alignas(16) StorageImageDescriptor
~StorageImageDescriptor() = delete; ~StorageImageDescriptor() = delete;
void *ptr; void *ptr;
VkExtent3D extent; int width;
int height;
int depth; // Layer/cube count for arrayed images
int rowPitchBytes; int rowPitchBytes;
int slicePitchBytes; // Layer pitch in case of array image int slicePitchBytes; // Layer pitch in case of array image
int samplePitchBytes; int samplePitchBytes;
int arrayLayers;
int sampleCount; int sampleCount;
int sizeInBytes; int sizeInBytes;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "VkImageView.hpp" #include "VkImageView.hpp"
#include "VkImage.hpp" #include "VkImage.hpp"
#include "System/Math.hpp" #include "System/Math.hpp"
...@@ -286,6 +287,22 @@ VkExtent3D ImageView::getMipLevelExtent(uint32_t mipLevel) const ...@@ -286,6 +287,22 @@ VkExtent3D ImageView::getMipLevelExtent(uint32_t mipLevel) const
subresourceRange.baseMipLevel + mipLevel); subresourceRange.baseMipLevel + mipLevel);
} }
int ImageView::getDepthOrLayerCount(uint32_t mipLevel) const
{
VkExtent3D extent = getMipLevelExtent(mipLevel);
int layers = subresourceRange.layerCount;
int depthOrLayers = layers > 1 ? layers : extent.depth;
// For cube images the number of whole cubes is returned
if(viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
{
depthOrLayers /= 6;
}
return depthOrLayers;
}
void *ImageView::getOffsetPointer(const VkOffset3D &offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer, Usage usage) const void *ImageView::getOffsetPointer(const VkOffset3D &offset, VkImageAspectFlagBits aspect, uint32_t mipLevel, uint32_t layer, Usage usage) const
{ {
ASSERT(mipLevel < subresourceRange.levelCount); ASSERT(mipLevel < subresourceRange.levelCount);
......
...@@ -88,6 +88,7 @@ public: ...@@ -88,6 +88,7 @@ public:
int getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const; int getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
int layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage = RAW) const; int layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage = RAW) const;
VkExtent3D getMipLevelExtent(uint32_t mipLevel) const; VkExtent3D getMipLevelExtent(uint32_t mipLevel) const;
int getDepthOrLayerCount(uint32_t mipLevel) const;
int getSampleCount() const int getSampleCount() const
{ {
......
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