SpirvShader: Implement OpImageQueryLevels
Tests: dEQP-VK.glsl.texture_functions.query.texturequerylevels.*
Bug: b/129523279
Change-Id: I385eaa4a8d5fc50c12c7cf284c26037ed93aa469
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31109
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 3999d3d..6d17256 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -901,6 +901,7 @@
case spv::OpImageFetch:
case spv::OpImageQuerySize:
case spv::OpImageQuerySizeLod:
+ case spv::OpImageQueryLevels:
case spv::OpImageRead:
case spv::OpImageTexelPointer:
case spv::OpGroupNonUniformElect:
@@ -2490,6 +2491,9 @@
case spv::OpImageQuerySizeLod:
return EmitImageQuerySizeLod(insn, state);
+ case spv::OpImageQueryLevels:
+ return EmitImageQueryLevels(insn, state);
+
case spv::OpImageRead:
return EmitImageRead(insn, state);
@@ -4895,6 +4899,38 @@
}
}
+ SpirvShader::EmitResult SpirvShader::EmitImageQueryLevels(InsnIterator insn, EmitState *state) const
+ {
+ auto &resultTy = getType(Type::ID(insn.word(1)));
+ ASSERT(resultTy.sizeInComponents == 1);
+ auto resultId = Object::ID(insn.word(2));
+ auto imageId = Object::ID(insn.word(3));
+
+ const DescriptorDecorations &d = descriptorDecorations.at(imageId);
+ auto setLayout = state->routine->pipelineLayout->getDescriptorSetLayout(d.DescriptorSet);
+ auto &bindingLayout = setLayout->getBindingLayout(d.Binding);
+
+ Pointer<Byte> descriptor = state->routine->getPointer(imageId).base;
+ Int mipLevels = 0;
+ switch (bindingLayout.descriptorType)
+ {
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ {
+ mipLevels = *Pointer<Int>(descriptor + OFFSET(vk::SampledImageDescriptor, mipLevels)); // uint32_t
+ break;
+ }
+ default:
+ UNREACHABLE("Image descriptorType: %d", int(bindingLayout.descriptorType));
+ }
+
+ auto &dst = state->routine->createIntermediate(resultId, 1);
+ dst.move(0, SIMD::Int(mipLevels));
+
+ 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, bool useStencilAspect) const
{
bool isArrayed = imageType.definition.word(5) != 0;
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 21a9d5a..2c98e4f 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -941,6 +941,7 @@
EmitResult EmitImageSample(ImageInstruction instruction, InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQuerySize(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQuerySizeLod(InsnIterator insn, EmitState *state) const;
+ EmitResult EmitImageQueryLevels(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageRead(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageWrite(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageTexelPointer(InsnIterator insn, EmitState *state) const;
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index 5356880..dfb8362 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -314,6 +314,7 @@
auto numElements = bufferView->getElementCount();
imageSampler[i].extent = { numElements, 1, 1 };
imageSampler[i].arrayLayers = 1;
+ imageSampler[i].mipLevels = 1;
imageSampler[i].texture.widthWidthHeightHeight = sw::vector(numElements, numElements, 1, 1);
imageSampler[i].texture.width = sw::replicate(numElements);
imageSampler[i].texture.height = sw::replicate(1);
@@ -351,6 +352,7 @@
imageSampler[i].imageViewId = imageView->id;
imageSampler[i].extent = imageView->getMipLevelExtent(0);
imageSampler[i].arrayLayers = imageView->getSubresourceRange().layerCount;
+ imageSampler[i].mipLevels = imageView->getSubresourceRange().levelCount;
imageSampler[i].type = imageView->getType();
imageSampler[i].swizzle = imageView->getComponentMapping();
imageSampler[i].format = imageView->getFormat(ImageView::SAMPLING);
diff --git a/src/Vulkan/VkDescriptorSetLayout.hpp b/src/Vulkan/VkDescriptorSetLayout.hpp
index 7a96b44..c368b1d 100644
--- a/src/Vulkan/VkDescriptorSetLayout.hpp
+++ b/src/Vulkan/VkDescriptorSetLayout.hpp
@@ -41,6 +41,7 @@
alignas(16) sw::Texture texture;
VkExtent3D extent; // Of base mip-level.
int arrayLayers;
+ int mipLevels;
};
struct alignas(16) StorageImageDescriptor