Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 6eeb3d8

Browse files
vontureCommit Bot
authored andcommitted
Support DXT textures with non-block sized mip levels.
The block size requirement for each mip level meant that all DXT textures had to be POT sized. Relax these restrictions for non-zero mip levels to allow NPOT DXT textures. Increase the size of the D3D11 staging textures to the nearest block size to make sure allocation succeeds. Bug: angleproject:4841 Change-Id: I42fa295a0965241d77f81e57b17454091fda9376 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2380237 Reviewed-by: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: back sept 10 - Jamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
1 parent 7e815c7 commit 6eeb3d8

File tree

4 files changed

+245
-14
lines changed

4 files changed

+245
-14
lines changed

src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,6 +2143,20 @@ void MakeValidSize(bool isImage,
21432143
upsampleCount++;
21442144
}
21452145
}
2146+
else
2147+
{
2148+
if (*requestWidth % dxgiFormatInfo.blockWidth != 0)
2149+
{
2150+
*requestWidth = roundUp(*requestWidth, static_cast<GLsizei>(dxgiFormatInfo.blockWidth));
2151+
}
2152+
2153+
if (*requestHeight % dxgiFormatInfo.blockHeight != 0)
2154+
{
2155+
*requestHeight =
2156+
roundUp(*requestHeight, static_cast<GLsizei>(dxgiFormatInfo.blockHeight));
2157+
}
2158+
}
2159+
21462160
if (levelOffset)
21472161
{
21482162
*levelOffset = upsampleCount;

src/libANGLE/validationES.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -914,10 +914,9 @@ bool ValidImageSizeParameters(const Context *context,
914914
return true;
915915
}
916916

917-
bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
917+
bool ValidCompressedDimension(GLsizei size, GLuint blockSize, GLint level)
918918
{
919-
return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
920-
(size % blockSize == 0);
919+
return (level > 0) || (size % blockSize == 0);
921920
}
922921

923922
bool ValidCompressedImageSize(const Context *context,
@@ -940,17 +939,9 @@ bool ValidCompressedImageSize(const Context *context,
940939

941940
if (CompressedTextureFormatRequiresExactSize(internalFormat))
942941
{
943-
// The ANGLE extensions allow specifying compressed textures with sizes smaller than the
944-
// block size for level 0 but WebGL disallows this.
945-
bool smallerThanBlockSizeAllowed =
946-
level > 0 || !context->getExtensions().webglCompatibility;
947-
948-
if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
949-
smallerThanBlockSizeAllowed) ||
950-
!ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
951-
smallerThanBlockSizeAllowed) ||
952-
!ValidCompressedDimension(depth, formatInfo.compressedBlockDepth,
953-
smallerThanBlockSizeAllowed))
942+
if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth, level) ||
943+
!ValidCompressedDimension(height, formatInfo.compressedBlockHeight, level) ||
944+
!ValidCompressedDimension(depth, formatInfo.compressedBlockDepth, level))
954945
{
955946
return false;
956947
}

src/tests/angle_end2end_tests.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ angle_end2end_tests_sources = [
110110
"gl_tests/RobustBufferAccessBehaviorTest.cpp",
111111
"gl_tests/RobustClientMemoryTest.cpp",
112112
"gl_tests/RobustResourceInitTest.cpp",
113+
"gl_tests/S3TCTextureSizesTest.cpp",
113114
"gl_tests/SRGBFramebufferTest.cpp",
114115
"gl_tests/SRGBTextureTest.cpp",
115116
"gl_tests/SamplersTest.cpp",
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
//
2+
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
3+
// Use of this source code is governed by a BSD-style license that can be
4+
// found in the LICENSE file.
5+
//
6+
// Tests of DXT texture mipmap sizes required by WebGL.
7+
8+
#include "test_utils/ANGLETest.h"
9+
#include "test_utils/gl_raii.h"
10+
11+
#include "media/pixel.inc"
12+
13+
using namespace angle;
14+
15+
std::array<uint8_t, 72> k12x12DXT1Data = {
16+
0xe0, 0x03, 0x00, 0x78, 0x13, 0x10, 0x15, 0x00, 0x0f, 0x00, 0xe0, 0x7b, 0x11, 0x10, 0x15,
17+
0x00, 0xe0, 0x03, 0x0f, 0x78, 0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03, 0x44, 0x45,
18+
0x40, 0x55, 0xe0, 0x03, 0x00, 0x78, 0x13, 0x10, 0x15, 0x00, 0x0f, 0x00, 0xe0, 0x7b, 0x11,
19+
0x10, 0x15, 0x00, 0xe0, 0x03, 0x0f, 0x78, 0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03,
20+
0x44, 0x45, 0x40, 0x55, 0x0f, 0x00, 0xef, 0x03, 0x44, 0x45, 0x40, 0x55,
21+
};
22+
23+
class S3TCTextureSizesTest : public ANGLETest
24+
{
25+
protected:
26+
S3TCTextureSizesTest()
27+
{
28+
setWindowWidth(512);
29+
setWindowHeight(512);
30+
setConfigRedBits(8);
31+
setConfigGreenBits(8);
32+
setConfigBlueBits(8);
33+
setConfigAlphaBits(8);
34+
}
35+
36+
void testSetUp() override
37+
{
38+
constexpr char kVS[] = R"(precision highp float;
39+
attribute vec4 position;
40+
varying vec2 texcoord;
41+
42+
void main()
43+
{
44+
gl_Position = position;
45+
texcoord = (position.xy * 0.5) + 0.5;
46+
texcoord.y = 1.0 - texcoord.y;
47+
})";
48+
49+
constexpr char kFS[] = R"(precision highp float;
50+
uniform sampler2D tex;
51+
varying vec2 texcoord;
52+
53+
void main()
54+
{
55+
gl_FragColor = texture2D(tex, texcoord);
56+
})";
57+
58+
mTextureProgram = CompileProgram(kVS, kFS);
59+
if (mTextureProgram == 0)
60+
{
61+
FAIL() << "shader compilation failed.";
62+
}
63+
64+
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
65+
66+
ASSERT_GL_NO_ERROR();
67+
}
68+
69+
void testTearDown() override { glDeleteProgram(mTextureProgram); }
70+
71+
GLuint mTextureProgram;
72+
GLint mTextureUniformLocation;
73+
};
74+
75+
// Test DXT1 formats with POT sizes on all mips
76+
TEST_P(S3TCTextureSizesTest, POT)
77+
{
78+
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
79+
80+
GLTexture texture;
81+
glBindTexture(GL_TEXTURE_2D, texture);
82+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
83+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
84+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
85+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
86+
87+
glUseProgram(mTextureProgram);
88+
glUniform1i(mTextureUniformLocation, 0);
89+
90+
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 8, 0, 32,
91+
k12x12DXT1Data.data());
92+
drawQuad(mTextureProgram, "position", 0.5f);
93+
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
94+
95+
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 4, 0, 16,
96+
k12x12DXT1Data.data());
97+
drawQuad(mTextureProgram, "position", 0.5f);
98+
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
99+
100+
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 4, 0, 16,
101+
k12x12DXT1Data.data());
102+
drawQuad(mTextureProgram, "position", 0.5f);
103+
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(0, 0, 123, 255));
104+
105+
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 0, 8,
106+
k12x12DXT1Data.data());
107+
drawQuad(mTextureProgram, "position", 0.5f);
108+
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor(123, 0, 0, 255));
109+
110+
EXPECT_GL_NO_ERROR();
111+
}
112+
113+
// Test DXT1 formats with NPOT sizes with glTexStorage
114+
TEST_P(S3TCTextureSizesTest, NPOTTexStorage)
115+
{
116+
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
117+
118+
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
119+
(!IsGLExtensionEnabled("GL_EXT_texture_storage") ||
120+
!IsGLExtensionEnabled("GL_OES_rgb8_rgba8")));
121+
122+
GLTexture texture;
123+
glBindTexture(GL_TEXTURE_2D, texture);
124+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
125+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
126+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
127+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
128+
129+
glUseProgram(mTextureProgram);
130+
glUniform1i(mTextureUniformLocation, 0);
131+
132+
if (getClientMajorVersion() < 3)
133+
{
134+
glTexStorage2DEXT(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 12, 12);
135+
}
136+
else
137+
{
138+
glTexStorage2D(GL_TEXTURE_2D, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 12, 12);
139+
}
140+
141+
struct levelInfo
142+
{
143+
size_t width;
144+
size_t height;
145+
size_t size;
146+
GLColor expectedColor;
147+
};
148+
std::array<levelInfo, 4> levels{{
149+
{12, 12, 72, GLColor(123, 0, 123, 255)},
150+
{6, 6, 32, GLColor(123, 0, 123, 255)},
151+
{3, 3, 8, GLColor(123, 0, 0, 255)},
152+
{1, 1, 8, GLColor(0, 0, 0, 0)},
153+
}};
154+
155+
for (size_t i = 0; i < levels.size(); i++)
156+
{
157+
const levelInfo &level = levels[i];
158+
glCompressedTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, level.width, level.height,
159+
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, level.size,
160+
k12x12DXT1Data.data());
161+
}
162+
EXPECT_GL_NO_ERROR();
163+
164+
for (size_t i = 0; i < levels.size(); i++)
165+
{
166+
const levelInfo &level = levels[i];
167+
glViewport(0, 0, level.width, level.height);
168+
drawQuad(mTextureProgram, "position", 0.5f);
169+
EXPECT_PIXEL_COLOR_EQ(0, 0, level.expectedColor) << " failed on level " << i;
170+
}
171+
172+
EXPECT_GL_NO_ERROR();
173+
}
174+
175+
// Test DXT1 formats with NPOT sizes with glTex[Sub]Image
176+
TEST_P(S3TCTextureSizesTest, NPOTTexImage)
177+
{
178+
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_dxt1"));
179+
180+
GLTexture texture;
181+
glBindTexture(GL_TEXTURE_2D, texture);
182+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
183+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
184+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
185+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
186+
187+
glUseProgram(mTextureProgram);
188+
glUniform1i(mTextureUniformLocation, 0);
189+
190+
struct levelInfo
191+
{
192+
size_t width;
193+
size_t height;
194+
size_t size;
195+
GLColor expectedColor;
196+
};
197+
std::array<levelInfo, 4> levels{{
198+
{12, 12, 72, GLColor(123, 0, 123, 255)},
199+
{6, 6, 32, GLColor(123, 0, 123, 255)},
200+
{3, 3, 8, GLColor(123, 0, 0, 255)},
201+
{1, 1, 8, GLColor(0, 0, 0, 0)},
202+
}};
203+
204+
for (size_t i = 0; i < levels.size(); i++)
205+
{
206+
const levelInfo &level = levels[i];
207+
glCompressedTexImage2D(GL_TEXTURE_2D, i, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, level.width,
208+
level.height, 0, level.size, k12x12DXT1Data.data());
209+
}
210+
EXPECT_GL_NO_ERROR();
211+
212+
for (size_t i = 0; i < levels.size(); i++)
213+
{
214+
const levelInfo &level = levels[i];
215+
glViewport(0, 0, level.width, level.height);
216+
drawQuad(mTextureProgram, "position", 0.5f);
217+
EXPECT_PIXEL_COLOR_EQ(0, 0, level.expectedColor) << " failed on level " << i;
218+
}
219+
220+
EXPECT_GL_NO_ERROR();
221+
}
222+
223+
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
224+
// tests should be run against.
225+
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(S3TCTextureSizesTest);

0 commit comments

Comments
 (0)