Commit 977a0a43 by Nicolas Capens Committed by Nicolas Capens

Implement OpImageQueryLod

Vulkan 1.1 spec section 15.6.7. Scale Factor Operation, Level-of-Detail Operation and Image Level(s) Selection clarifies that the first returned parameter is the clamped LOD, rounded to the nearest integer if mipmapMode is VK_SAMPLER_MIPMAP_MODE_NEAREST, and the second parameter is the unclamped LOD with base level and sampler bias applied (we don't take maxSamplerLodBias into account, it is infinite). Bug: b/129523279 Tests: dEQP-VK.glsl.texture_functions.query.texturequerylod.* Tests: dEQP-VK.ycbcr.query.lod.* Change-Id: I4aa2f16716e1e23548b6fb3e0862e7cc442e3678 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31629 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent f4f427ad
...@@ -83,7 +83,7 @@ namespace sw ...@@ -83,7 +83,7 @@ namespace sw
cubeFace(face, uuuu, vvvv, u, v, w, M); cubeFace(face, uuuu, vvvv, u, v, w, M);
} }
if(function == Implicit || function == Bias || function == Grad) if(function == Implicit || function == Bias || function == Grad || function == Query)
{ {
if(state.textureType != TEXTURE_3D) if(state.textureType != TEXTURE_3D)
{ {
...@@ -124,8 +124,27 @@ namespace sw ...@@ -124,8 +124,27 @@ namespace sw
if(function != Base && function != Fetch) if(function != Base && function != Fetch)
{ {
lod += *Pointer<Float>(sampler + OFFSET(vk::Sampler, mipLodBias)); lod += *Pointer<Float>(sampler + OFFSET(vk::Sampler, mipLodBias));
if(function == Query)
{
c.y = Float4(lod); // Unclamped LOD.
}
lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod))); lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod))); lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
if(function == Query)
{
if(state.mipmapFilter == MIPMAP_POINT)
{
lod = Round(lod); // TODO: Preferred formula is ceil(lod + 0.5) - 1
}
c.x = lod;
// c.y contains unclamped LOD.
return c;
}
} }
bool force32BitFiltering = state.highPrecisionFiltering && !hasYuvFormat() && (state.textureFilter != FILTER_POINT); bool force32BitFiltering = state.highPrecisionFiltering && !hasYuvFormat() && (state.textureFilter != FILTER_POINT);
......
...@@ -35,7 +35,8 @@ namespace sw ...@@ -35,7 +35,8 @@ namespace sw
Grad, // Use provided gradients. Grad, // Use provided gradients.
Fetch, // Use provided integer coordinates. Fetch, // Use provided integer coordinates.
Base, // Sample base level. Base, // Sample base level.
SAMPLER_METHOD_LAST = Base, Query, // Return implicit LOD.
SAMPLER_METHOD_LAST = Query,
}; };
enum SamplerOption enum SamplerOption
......
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
#include "SpirvShader.hpp" #include "SpirvShader.hpp"
#include "SamplerCore.hpp"
#include "SamplerCore.hpp"
#include "Reactor/Coroutine.hpp" #include "Reactor/Coroutine.hpp"
#include "System/Math.hpp" #include "System/Math.hpp"
#include "Vulkan/VkBuffer.hpp" #include "Vulkan/VkBuffer.hpp"
...@@ -919,8 +919,9 @@ namespace sw ...@@ -919,8 +919,9 @@ namespace sw
case spv::OpImageSampleProjDrefImplicitLod: case spv::OpImageSampleProjDrefImplicitLod:
case spv::OpImageSampleProjDrefExplicitLod: case spv::OpImageSampleProjDrefExplicitLod:
case spv::OpImageFetch: case spv::OpImageFetch:
case spv::OpImageQuerySize:
case spv::OpImageQuerySizeLod: case spv::OpImageQuerySizeLod:
case spv::OpImageQuerySize:
case spv::OpImageQueryLod:
case spv::OpImageQueryLevels: case spv::OpImageQueryLevels:
case spv::OpImageQuerySamples: case spv::OpImageQuerySamples:
case spv::OpImageRead: case spv::OpImageRead:
...@@ -2471,11 +2472,14 @@ namespace sw ...@@ -2471,11 +2472,14 @@ namespace sw
case spv::OpImageFetch: case spv::OpImageFetch:
return EmitImageFetch(insn, state); return EmitImageFetch(insn, state);
case spv::OpImageQuerySizeLod:
return EmitImageQuerySizeLod(insn, state);
case spv::OpImageQuerySize: case spv::OpImageQuerySize:
return EmitImageQuerySize(insn, state); return EmitImageQuerySize(insn, state);
case spv::OpImageQuerySizeLod: case spv::OpImageQueryLod:
return EmitImageQuerySizeLod(insn, state); return EmitImageQueryLod(insn, state);
case spv::OpImageQueryLevels: case spv::OpImageQueryLevels:
return EmitImageQueryLevels(insn, state); return EmitImageQueryLevels(insn, state);
...@@ -4839,12 +4843,12 @@ namespace sw ...@@ -4839,12 +4843,12 @@ namespace sw
return EmitResult::Continue; return EmitResult::Continue;
} }
SpirvShader::EmitResult SpirvShader::EmitImageQuerySize(InsnIterator insn, EmitState *state) const SpirvShader::EmitResult SpirvShader::EmitImageQuerySizeLod(InsnIterator insn, EmitState *state) const
{ {
auto &resultTy = getType(Type::ID(insn.word(1))); auto &resultTy = getType(Type::ID(insn.word(1)));
auto resultId = Object::ID(insn.word(2)); auto resultId = Object::ID(insn.word(2));
auto imageId = Object::ID(insn.word(3)); auto imageId = Object::ID(insn.word(3));
auto lodId = Object::ID(0); auto lodId = Object::ID(insn.word(4));
auto &dst = state->routine->createIntermediate(resultId, resultTy.sizeInComponents); auto &dst = state->routine->createIntermediate(resultId, resultTy.sizeInComponents);
GetImageDimensions(state->routine, resultTy, imageId, lodId, dst); GetImageDimensions(state->routine, resultTy, imageId, lodId, dst);
...@@ -4852,12 +4856,12 @@ namespace sw ...@@ -4852,12 +4856,12 @@ namespace sw
return EmitResult::Continue; return EmitResult::Continue;
} }
SpirvShader::EmitResult SpirvShader::EmitImageQuerySizeLod(InsnIterator insn, EmitState *state) const SpirvShader::EmitResult SpirvShader::EmitImageQuerySize(InsnIterator insn, EmitState *state) const
{ {
auto &resultTy = getType(Type::ID(insn.word(1))); auto &resultTy = getType(Type::ID(insn.word(1)));
auto resultId = Object::ID(insn.word(2)); auto resultId = Object::ID(insn.word(2));
auto imageId = Object::ID(insn.word(3)); auto imageId = Object::ID(insn.word(3));
auto lodId = Object::ID(insn.word(4)); auto lodId = Object::ID(0);
auto &dst = state->routine->createIntermediate(resultId, resultTy.sizeInComponents); auto &dst = state->routine->createIntermediate(resultId, resultTy.sizeInComponents);
GetImageDimensions(state->routine, resultTy, imageId, lodId, dst); GetImageDimensions(state->routine, resultTy, imageId, lodId, dst);
...@@ -4865,6 +4869,11 @@ namespace sw ...@@ -4865,6 +4869,11 @@ namespace sw
return EmitResult::Continue; return EmitResult::Continue;
} }
SpirvShader::EmitResult SpirvShader::EmitImageQueryLod(InsnIterator insn, EmitState *state) const
{
return EmitImageSample({None, Query}, insn, state);
}
void SpirvShader::GetImageDimensions(SpirvRoutine const *routine, Type const &resultTy, Object::ID imageId, Object::ID lodId, Intermediate &dst) const void SpirvShader::GetImageDimensions(SpirvRoutine const *routine, Type const &resultTy, Object::ID imageId, Object::ID lodId, Intermediate &dst) const
{ {
auto &image = getObject(imageId); auto &image = getObject(imageId);
......
...@@ -480,7 +480,7 @@ namespace sw ...@@ -480,7 +480,7 @@ namespace sw
// OpImageSample variants // OpImageSample variants
enum Variant enum Variant
{ {
None, None, // No Dref or Proj. Also used by OpImageFetch and OpImageQueryLod.
Dref, Dref,
Proj, Proj,
ProjDref, ProjDref,
...@@ -938,8 +938,9 @@ namespace sw ...@@ -938,8 +938,9 @@ namespace sw
EmitResult EmitImageSampleExplicitLod(Variant variant, InsnIterator insn, EmitState *state) const; EmitResult EmitImageSampleExplicitLod(Variant variant, InsnIterator insn, EmitState *state) const;
EmitResult EmitImageFetch(InsnIterator insn, EmitState *state) const; EmitResult EmitImageFetch(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageSample(ImageInstruction instruction, InsnIterator insn, EmitState *state) const; EmitResult EmitImageSample(ImageInstruction instruction, InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQuerySize(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQuerySizeLod(InsnIterator insn, EmitState *state) const; EmitResult EmitImageQuerySizeLod(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQuerySize(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQueryLod(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQueryLevels(InsnIterator insn, EmitState *state) const; EmitResult EmitImageQueryLevels(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQuerySamples(InsnIterator insn, EmitState *state) const; EmitResult EmitImageQuerySamples(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageRead(InsnIterator insn, EmitState *state) const; EmitResult EmitImageRead(InsnIterator insn, EmitState *state) const;
......
...@@ -89,8 +89,6 @@ SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction ins ...@@ -89,8 +89,6 @@ SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction ins
Pointer<SIMD::Float> out = function.Arg<3>(); Pointer<SIMD::Float> out = function.Arg<3>();
Pointer<Byte> constants = function.Arg<4>(); Pointer<Byte> constants = function.Arg<4>();
SamplerCore s(constants, samplerState);
SIMD::Float uvw[4]; SIMD::Float uvw[4];
SIMD::Float q; SIMD::Float q;
SIMD::Float lodOrBias; // Explicit level-of-detail, or bias added to the implicit level-of-detail (depending on samplerMethod). SIMD::Float lodOrBias; // Explicit level-of-detail, or bias added to the implicit level-of-detail (depending on samplerMethod).
...@@ -149,6 +147,7 @@ SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction ins ...@@ -149,6 +147,7 @@ SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction ins
} }
} }
SamplerCore s(constants, samplerState);
Vector4f sample = s.sampleTexture(texture, sampler, uvw[0], uvw[1], uvw[2], q, lodOrBias, dsx, dsy, offset, samplerFunction); Vector4f sample = s.sampleTexture(texture, sampler, uvw[0], uvw[1], uvw[2], q, lodOrBias, dsx, dsy, offset, samplerFunction);
Pointer<SIMD::Float> rgba = out; Pointer<SIMD::Float> rgba = out;
......
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