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
ASSERT(imageType.definition.opcode() == spv::OpTypeImage);
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);
auto descriptorType = routine->pipelineLayout->getDescriptorType(d.DescriptorSet, d.Binding);
Pointer<Byte> descriptor = state->getPointer(imageId).base;
Pointer<Int> extent;
Int arrayLayers;
Int width;
Int height;
Int depth;
switch(descriptorType)
{
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
{
extent = descriptor + OFFSET(vk::StorageImageDescriptor, extent); // int[3]*
arrayLayers = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, arrayLayers)); // uint32_t
width = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, width));
height = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, height));
depth = *Pointer<Int>(descriptor + OFFSET(vk::StorageImageDescriptor, depth));
break;
}
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
{
extent = descriptor + OFFSET(vk::SampledImageDescriptor, extent); // int[3]*
arrayLayers = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, arrayLayers)); // uint32_t
width = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, width));
height = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, height));
depth = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, depth));
break;
}
default:
UNREACHABLE("Image descriptorType: %d", int(descriptorType));
}
auto dimensions = resultTy.componentCount - (isArrayed ? 1 : 0);
std::vector<Int> out;
if(lodId != 0)
{
auto lodVal = Operand(this, state, lodId);
ASSERT(lodVal.componentCount == 1);
auto lod = lodVal.Int(0);
auto one = SIMD::Int(1);
for(uint32_t i = 0; i < dimensions; i++)
{
dst.move(i, Max(SIMD::Int(extent[i]) >> lod, one));
}
if(dimensions >= 1) dst.move(0, Max(SIMD::Int(width) >> 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
{
for(uint32_t i = 0; i < dimensions; i++)
{
dst.move(i, SIMD::Int(extent[i]));
}
if(dimensions >= 1) dst.move(0, SIMD::Int(width));
if(dimensions >= 2) dst.move(1, SIMD::Int(height));
if(dimensions >= 3) dst.move(2, SIMD::Int(depth));
}
if(isArrayed)
{
auto numElements = isCubeMap ? (arrayLayers / 6) : RValue<Int>(arrayLayers);
dst.move(dimensions, SIMD::Int(numElements));
dst.move(dimensions, SIMD::Int(depth));
}
}
......@@ -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.
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));
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));
}
if((dims > 2) || isArrayed)
{
auto depth = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, extent.depth));
auto arrayLayers = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, arrayLayers));
oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(w), SIMD::UInt(depth * arrayLayers))); // TODO: Precompute extent. 3D image can't have layers.
UInt depth = *Pointer<UInt>(descriptor + OFFSET(vk::StorageImageDescriptor, depth));
if(dim == spv::DimCube) { depth *= 6; }
oobMask |= As<SIMD::Int>(CmpNLT(As<SIMD::UInt>(w), SIMD::UInt(depth)));
}
if(sampleId.value())
......
......@@ -44,8 +44,9 @@ struct alignas(16) SampledImageDescriptor
VkFormat format;
VkComponentMapping swizzle;
alignas(16) sw::Texture texture;
VkExtent3D extent; // Of base mip-level.
int arrayLayers;
int width; // Of base mip-level.
int height;
int depth; // Layer/cube count for arrayed images
int mipLevels;
int sampleCount;
......@@ -57,11 +58,12 @@ struct alignas(16) StorageImageDescriptor
~StorageImageDescriptor() = delete;
void *ptr;
VkExtent3D extent;
int width;
int height;
int depth; // Layer/cube count for arrayed images
int rowPitchBytes;
int slicePitchBytes; // Layer pitch in case of array image
int samplePitchBytes;
int arrayLayers;
int sampleCount;
int sizeInBytes;
......
......@@ -13,6 +13,7 @@
// limitations under the License.
#include "VkImageView.hpp"
#include "VkImage.hpp"
#include "System/Math.hpp"
......@@ -286,6 +287,22 @@ VkExtent3D ImageView::getMipLevelExtent(uint32_t mipLevel) const
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
{
ASSERT(mipLevel < subresourceRange.levelCount);
......
......@@ -88,6 +88,7 @@ public:
int getMipLevelSize(VkImageAspectFlagBits aspect, uint32_t mipLevel, Usage usage = RAW) const;
int layerPitchBytes(VkImageAspectFlagBits aspect, Usage usage = RAW) const;
VkExtent3D getMipLevelExtent(uint32_t mipLevel) const;
int getDepthOrLayerCount(uint32_t mipLevel) 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