Wrap integer textures with correct wrap mode in HLSL
The wrap mode information for all three dimensions is packed to a
single integer in order to conserve sampler metadata space. Only one
int4 vector is used for the metadata for a single sampler.
The sampler metadata is now packed into a struct instead of an array
of integers in order to make the code more readable and maintainable.
The internalFormatBits field is not removed in this patch. It's better
to remove it in a separate patch, so restoring it is easier in case it
will be used for optimizing some of the texture sampling functions.
The wrap mode passed in sampler metadata is used to wrap the texture
coordinates in the code generated to implement ESSL 3.00 integer
texture sampling built-ins.
Those dEQP-GLES3.functional.texture.units.* tests that sample from
integer cube maps still fail on Intel D3D after this change,
presumably due to driver issues.
BUG=angleproject:1244
BUG=angleproject:1095
BUG=angleproject:1092
TEST=dEQP-GLES3.functional.texture.units.* (all pass on NVIDIA),
dEQP-GLES3.functional.shaders.texture_functions.* (no regressions)
Change-Id: I4e31e5796086f9cc290c6f1f8c4380a768758d71
Reviewed-on: https://chromium-review.googlesource.com/336638
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index a5c9d2a..225f154 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -74,6 +74,42 @@
return constUnionIterated;
}
+void OutputIntTexCoordWrap(TInfoSinkBase &out,
+ const char *wrapMode,
+ const char *size,
+ const TString &texCoord,
+ const TString &texCoordOffset,
+ const char *texCoordOutName)
+{
+ // GLES 3.0.4 table 3.22 specifies how the wrap modes work. We don't use the formulas verbatim
+ // but rather use equivalent formulas that map better to HLSL.
+ out << "int " << texCoordOutName << ";\n";
+ out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset
+ << ") / " << size << ";\n";
+
+ // CLAMP_TO_EDGE
+ out << "if (" << wrapMode << " == 1)\n";
+ out << "{\n";
+ out << " " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName
+ << "Offset)), 0, int(" << size << ") - 1);\n";
+ out << "}\n";
+
+ // MIRRORED_REPEAT
+ out << "else if (" << wrapMode << " == 3)\n";
+ out << "{\n";
+ out << " float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName
+ << "Offset) * 0.5) * 2.0 - 1.0);\n";
+ out << " " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n";
+ out << "}\n";
+
+ // REPEAT
+ out << "else\n";
+ out << "{\n";
+ out << " " << texCoordOutName << " = int(floor(" << size << " * frac(" << texCoordOutName
+ << "Offset)));\n";
+ out << "}\n";
+}
+
} // namespace
namespace sh
@@ -864,7 +900,7 @@
if (textureFunction->method == TextureFunction::SIZE)
{
- out << "int baseLevel = samplerMetadata[samplerIndex].x;\n";
+ out << "int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
if (IsSampler2D(textureFunction->sampler) || IsSamplerCube(textureFunction->sampler))
{
if (IsSamplerArray(textureFunction->sampler) ||
@@ -1169,8 +1205,26 @@
else UNREACHABLE();
// Convert from normalized floating-point to integer
- texCoordX = "int(floor(width * frac(" + texCoordX + ")))";
- texCoordY = "int(floor(height * frac(" + texCoordY + ")))";
+ out << "int wrapS = samplerMetadata[samplerIndex].wrapModes & 0x3;\n";
+ if (textureFunction->offset)
+ {
+ OutputIntTexCoordWrap(out, "wrapS", "width", texCoordX, "offset.x", "tix");
+ }
+ else
+ {
+ OutputIntTexCoordWrap(out, "wrapS", "width", texCoordX, "0", "tix");
+ }
+ texCoordX = "tix";
+ out << "int wrapT = (samplerMetadata[samplerIndex].wrapModes >> 2) & 0x3;\n";
+ if (textureFunction->offset)
+ {
+ OutputIntTexCoordWrap(out, "wrapT", "height", texCoordY, "offset.y", "tiy");
+ }
+ else
+ {
+ OutputIntTexCoordWrap(out, "wrapT", "height", texCoordY, "0", "tiy");
+ }
+ texCoordY = "tiy";
if (IsSamplerArray(textureFunction->sampler))
{
@@ -1179,7 +1233,16 @@
else if (!IsSamplerCube(textureFunction->sampler) &&
!IsSampler2D(textureFunction->sampler))
{
- texCoordZ = "int(floor(depth * frac(" + texCoordZ + ")))";
+ out << "int wrapR = (samplerMetadata[samplerIndex].wrapModes >> 4) & 0x3;\n";
+ if (textureFunction->offset)
+ {
+ OutputIntTexCoordWrap(out, "wrapR", "depth", texCoordZ, "offset.z", "tiz");
+ }
+ else
+ {
+ OutputIntTexCoordWrap(out, "wrapR", "depth", texCoordZ, "0", "tiz");
+ }
+ texCoordZ = "tiz";
}
}
@@ -1421,7 +1484,8 @@
}
}
- if (textureFunction->offset)
+ if (textureFunction->offset && (!IsIntegerSampler(textureFunction->sampler) ||
+ textureFunction->method == TextureFunction::FETCH))
{
out << ", offset";
}