Commit 73c24e4d by Nicolas Capens Committed by Nicolas Capens

Specialize 1D sampling LOD calculation

Instead of reusing the 2D mipmap LOD calculation, this change adds a separate method for computing the LOD for 1D sampling operations. This also revealed that we would perform the anisotropic filtering calculations on 1D sampling operations if enabled, which makes no sense. This change limits it to 2D sampling only. Bug: b/134669567 Change-Id: I05dd3fe358eccfcd01ebcff35872f56c6f0b0b70 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/47488 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
parent 3087370e
......@@ -63,16 +63,17 @@ Vector4f SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 uvwa[4], Floa
if(function == Implicit || function == Bias || function == Grad || function == Query)
{
if(state.textureType != VK_IMAGE_VIEW_TYPE_3D)
if(state.addressingModeV == ADDRESSING_UNUSED)
{
if(!isCube())
{
computeLod(texture, lod, anisotropy, uDelta, vDelta, u, v, dsx, dsy, function);
}
else
{
computeLodCube(texture, lod, uvwa[0], uvwa[1], uvwa[2], dsx, dsy, M, function);
}
computeLod1D(texture, lod, u, dsx, dsy, function);
}
else if(state.addressingModeW == ADDRESSING_UNUSED)
{
computeLod2D(texture, lod, anisotropy, uDelta, vDelta, u, v, dsx, dsy, function);
}
else if(isCube())
{
computeLodCube(texture, lod, uvwa[0], uvwa[1], uvwa[2], dsx, dsy, M, function);
}
else
{
......@@ -423,7 +424,7 @@ Vector4s SamplerCore::sampleAniso(Pointer<Byte> &texture, Float4 &u, Float4 &v,
{
Vector4s c;
if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
if(state.textureFilter != FILTER_ANISOTROPIC)
{
c = sampleQuad(texture, u, v, w, a, offset, sample, lod, secondLOD, function);
}
......@@ -895,7 +896,7 @@ Vector4f SamplerCore::sampleFloatAniso(Pointer<Byte> &texture, Float4 &u, Float4
{
Vector4f c;
if(state.textureFilter != FILTER_ANISOTROPIC || function == Lod || function == Fetch)
if(state.textureFilter != FILTER_ANISOTROPIC)
{
c = sampleFloat(texture, u, v, w, a, dRef, offset, sample, lod, secondLOD, function);
}
......@@ -1137,9 +1138,9 @@ Vector4f SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Float4 &u, Float4 &v
return c;
}
Float SamplerCore::log2sqrt(Float lod)
static Float log2sqrt(Float lod)
{
// log2(sqrt(lod)) // Equals 0.25 * log2(lod^2).
// log2(sqrt(lod)) // Equals 0.25 * log2(lod^2).
lod *= lod; // Squaring doubles the exponent and produces an extra bit of precision.
lod = Float(As<Int>(lod)) - Float(0x3F800000); // Interpret as integer and subtract the exponent bias.
lod *= As<Float>(Int(0x33000000)); // Scale by 0.25 * 2^-23 (mantissa length).
......@@ -1147,7 +1148,7 @@ Float SamplerCore::log2sqrt(Float lod)
return lod;
}
Float SamplerCore::log2(Float lod)
static Float log2(Float lod)
{
lod *= lod; // Squaring doubles the exponent and produces an extra bit of precision.
lod = Float(As<Int>(lod)) - Float(0x3F800000); // Interpret as integer and subtract the exponent bias.
......@@ -1156,7 +1157,31 @@ Float SamplerCore::log2(Float lod)
return lod;
}
void SamplerCore::computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, Float4 &dsx, Float4 &dsy, SamplerFunction function)
void SamplerCore::computeLod1D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &dsx, Float4 &dsy, SamplerFunction function)
{
Float4 dudxy;
if(function != Grad) // Implicit
{
dudxy = uuuu.yz - uuuu.xx;
}
else
{
dudxy = UnpackLow(dsx, dsy);
}
// Scale by texture dimensions.
Float4 dUdxy = dudxy * *Pointer<Float4>(texture + OFFSET(Texture, widthWidthHeightHeight));
// Note we could take the absolute value here and omit the square root below,
// but this is more consistent with the 2D calculation and still cheap.
Float4 dU2dxy = dUdxy * dUdxy;
lod = Max(Float(dU2dxy.x), Float(dU2dxy.y));
lod = log2sqrt(lod);
}
void SamplerCore::computeLod2D(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, Float4 &dsx, Float4 &dsy, SamplerFunction function)
{
Float4 duvdxy;
......
......@@ -73,9 +73,8 @@ private:
Vector4f sampleFloat(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, const Float4 &a, Float4 &dRef, Vector4i &offset, const Int4 &sample, Float &lod, bool secondLOD, SamplerFunction function);
Vector4f sampleFloat2D(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, const Float4 &a, Float4 &dRef, Vector4i &offset, const Int4 &sample, Float &lod, bool secondLOD, SamplerFunction function);
Vector4f sampleFloat3D(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Float4 &dRef, Vector4i &offset, const Int4 &sample, Float &lod, bool secondLOD, SamplerFunction function);
Float log2sqrt(Float lod);
Float log2(Float lod);
void computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, Float4 &dsx, Float4 &dsy, SamplerFunction function);
void computeLod1D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &dsx, Float4 &dsy, SamplerFunction function);
void computeLod2D(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, Float4 &dsx, Float4 &dsy, SamplerFunction function);
void computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, Float4 &dsx, Float4 &dsy, Float4 &M, SamplerFunction function);
void computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, Float4 &dsx, Float4 &dsy, SamplerFunction function);
Int4 cubeFace(Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M);
......
......@@ -1272,7 +1272,7 @@ private:
static std::shared_ptr<rr::Routine> emitSamplerRoutine(ImageInstruction instruction, const Sampler &samplerState);
// TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly.
static sw::FilterType convertFilterMode(const vk::Sampler *sampler);
static sw::FilterType convertFilterMode(const vk::Sampler *sampler, VkImageViewType imageViewType, ImageInstruction instruction);
static sw::MipmapType convertMipmapMode(const vk::Sampler *sampler);
static sw::AddressingMode convertAddressingMode(int coordinateIndex, const vk::Sampler *sampler, VkImageViewType imageViewType);
......
......@@ -58,7 +58,7 @@ SpirvShader::ImageSampler *SpirvShader::getImageSampler(uint32_t inst, vk::Sampl
if(sampler)
{
samplerState.textureFilter = (instruction.samplerMethod == Gather) ? FILTER_GATHER : convertFilterMode(sampler);
samplerState.textureFilter = convertFilterMode(sampler, type, instruction);
samplerState.border = sampler->borderColor;
samplerState.mipmapFilter = convertMipmapMode(sampler);
......@@ -185,13 +185,6 @@ std::shared_ptr<rr::Routine> SpirvShader::emitSamplerRoutine(ImageInstruction in
dPdy.y = Pointer<Float>(&dsy.y)[i];
dPdy.z = Pointer<Float>(&dsy.z)[i];
// 1D textures are treated as 2D texture with second coordinate 0, so we also need to zero out the second grad component. TODO(b/134669567)
if(samplerState.textureType == VK_IMAGE_VIEW_TYPE_1D || samplerState.textureType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
{
dPdx.y = Float(0.0f);
dPdy.y = Float(0.0f);
}
Vector4f sample = s.sampleTexture(texture, uvwa, dRef, lod[i], dPdx, dPdy, offset, sampleId, samplerFunction);
Pointer<Float> rgba = out;
......@@ -216,11 +209,27 @@ std::shared_ptr<rr::Routine> SpirvShader::emitSamplerRoutine(ImageInstruction in
return function("sampler");
}
sw::FilterType SpirvShader::convertFilterMode(const vk::Sampler *sampler)
sw::FilterType SpirvShader::convertFilterMode(const vk::Sampler *sampler, VkImageViewType imageViewType, ImageInstruction instruction)
{
if(instruction.samplerMethod == Gather)
{
return FILTER_GATHER;
}
if(instruction.samplerMethod == Fetch)
{
return FILTER_POINT;
}
if(sampler->anisotropyEnable != VK_FALSE)
{
return FILTER_ANISOTROPIC;
if(imageViewType == VK_IMAGE_VIEW_TYPE_2D || imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
{
if(instruction.samplerMethod != Lod) // TODO(b/162926129): Support anisotropic filtering with explicit LOD.
{
return FILTER_ANISOTROPIC;
}
}
}
switch(sampler->magFilter)
......
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