Commit 1fe74c7e by Geoff Lang Committed by Commit Bot

Manually compute the mipmap size for the textureSize builtin.

There were two issues with the current implementation: * The GetDimensions function already takes into account the base level of the SRV. * The GetDimensions function returns doesn't return valid sizes for levels that don't exist in the SRV. Instead, manually do the lod offset. BUG=angleproject:931 BUG=angleproject:1316 TEST=dEQP-GLES3.functional.shaders.texture_functions.texturesize.sampler2d_fixed_vertex Change-Id: I63259b563a42b93b73949e0ef7ac412099a42f13 Reviewed-on: https://chromium-review.googlesource.com/376099Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent b0465313
......@@ -222,6 +222,11 @@ typedef enum {
// varying variables and built-in GLSL variables. This compiler
// option is enabled automatically when needed.
SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL = 0x1000000,
// Some drivers do not take into account the base level of the texture in the results of the
// HLSL GetDimensions builtin. This flag instructs the compiler to manually add the base level
// offsetting.
SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL = 0x2000000,
} ShCompileOptions;
// Defines alternate strategies for implementing array index clamping.
......
......@@ -605,7 +605,9 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
}
}
mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType);
bool getDimensionsIgnoresBaseLevel =
(mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0;
mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel);
if (mUsesFragCoord)
{
......
......@@ -473,22 +473,40 @@ void GetTextureReference(TInfoSinkBase &out,
void OutputTextureSizeFunctionBody(TInfoSinkBase &out,
const TextureFunctionHLSL::TextureFunction &textureFunction,
const TString &textureReference)
const TString &textureReference,
bool getDimensionsIgnoresBaseLevel)
{
out << "int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
if (getDimensionsIgnoresBaseLevel)
{
out << "int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
}
else
{
out << "int baseLevel = 0;\n";
}
if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
(IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler)))
{
// "depth" stores either the number of layers in an array texture or 3D depth
out << " uint width; uint height; uint depth; uint numberOfLevels;\n"
<< " " << textureReference
<< ".GetDimensions(baseLevel + lod, width, height, depth, numberOfLevels);\n";
<< ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n"
<< " width = max(width >> lod, 1);\n"
<< " height = max(height >> lod, 1);\n";
if (!IsSamplerArray(textureFunction.sampler))
{
out << " depth = max(depth >> lod, 1);\n";
}
}
else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler))
{
out << " uint width; uint height; uint numberOfLevels;\n"
<< " " << textureReference
<< ".GetDimensions(baseLevel + lod, width, height, numberOfLevels);\n";
<< ".GetDimensions(baseLevel, width, height, numberOfLevels);\n"
<< " width = max(width >> lod, 1);\n"
<< " height = max(height >> lod, 1);\n";
}
else
UNREACHABLE();
......@@ -1249,7 +1267,9 @@ TString TextureFunctionHLSL::useTextureFunction(const TString &name,
return textureFunction.name();
}
void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out, const ShShaderOutput outputType)
void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out,
const ShShaderOutput outputType,
bool getDimensionsIgnoresBaseLevel)
{
for (const TextureFunction &textureFunction : mUsesTexture)
{
......@@ -1272,7 +1292,8 @@ void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out, const ShShad
if (textureFunction.method == TextureFunction::SIZE)
{
OutputTextureSizeFunctionBody(out, textureFunction, textureReference);
OutputTextureSizeFunctionBody(out, textureFunction, textureReference,
getDimensionsIgnoresBaseLevel);
}
else
{
......
......@@ -62,7 +62,9 @@ class TextureFunctionHLSL final : angle::NonCopyable
bool lod0,
sh::GLenum shaderType);
void textureFunctionHeader(TInfoSinkBase &out, const ShShaderOutput outputType);
void textureFunctionHeader(TInfoSinkBase &out,
const ShShaderOutput outputType,
bool getDimensionsIgnoresBaseLevel);
private:
typedef std::set<TextureFunction> TextureFunctionSet;
......
......@@ -49,6 +49,10 @@ ShaderD3D::ShaderD3D(const gl::ShaderState &data, const WorkaroundsD3D &workarou
{
mAdditionalOptions |= SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS;
}
if (workarounds.getDimensionsIgnoresBaseLevel)
{
mAdditionalOptions |= SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL;
}
}
ShaderD3D::~ShaderD3D()
......
......@@ -63,6 +63,10 @@ struct WorkaroundsD3D
// NVIDIA drivers sometimes write out-of-order results to StreamOut buffers when transform
// feedback is used to repeatedly write to the same buffer positions.
bool flushAfterEndingTransformFeedback = false;
// Some drivers (NVIDIA) do not take into account the base level of the texture in the results
// of the HLSL GetDimensions builtin.
bool getDimensionsIgnoresBaseLevel = false;
};
} // namespace rx
......
......@@ -1538,6 +1538,7 @@ WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
workarounds.expandIntegerPowExpressions = true;
workarounds.flushAfterEndingTransformFeedback = (adapterDesc.VendorId == VENDOR_ID_NVIDIA);
workarounds.getDimensionsIgnoresBaseLevel = (adapterDesc.VendorId == VENDOR_ID_NVIDIA);
return workarounds;
}
......
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