[v2] amd_compressed_atc_texture: add miptree test

Submitted by Jonathan Marek on April 9, 2019, 8:20 p.m.

Details

Message ID 20190409202030.12751-1-jonathan@marek.ca
State New
Headers show
Series "amd_compressed_atc_texture: add miptree test" ( rev: 2 ) in Piglit

Not browsing as part of any series.

Commit Message

Jonathan Marek April 9, 2019, 8:20 p.m.
This echoes the ETC1 miptree test, and even uses the same image.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 tests/spec/CMakeLists.txt                     |   1 +
 .../CMakeLists.gles2.txt                      |   6 +
 .../amd_compressed_atc_texture/CMakeLists.txt |   1 +
 .../spec/amd_compressed_atc_texture/miptree.c | 247 ++++++++++++++++++
 .../waffles-compressed-atc-64x32.ktx          | Bin 0 -> 1464 bytes
 .../waffles-decompressed-rgba-64x32.ktx       | Bin 0 -> 11008 bytes
 6 files changed, 255 insertions(+)
 create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
 create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.txt
 create mode 100644 tests/spec/amd_compressed_atc_texture/miptree.c
 create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
 create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx

diff --git a/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
new file mode 100644
index 0000000000000000000000000000000000000000..6d7acc71e060032c5eedd75927e3b43cbd567ad9
GIT binary patch
literal 1464
zcmZ8hZ%k8H6u(cU)jpSY3nL(Hq!SjHZ0G_DCUd-k=qfWQhPna4DHRNKQs)+<G6AvM
zG&7EE>b@A1Ni_&bjl*S|NKtSErb*qX@x$yZ@*agMTDSLl3--OU`)b&So#egWz4zR6
zekbS8?Jg<%AZ_*Pt1oDlX{ZGY7a<~)@+0!?F@zSUAjFV$8u{i$(W~Y+#DZ;PVP8y=
z*hT<k_4(o``K)mS00qkk`UzeP!8<l9*?1~dw#0VqpeQCQ&wGDB%gm`8eUM7{s?&xe
zD!LMivhR+y?AD<oy&ph|MxmM50SE}iG48j3EERqsECPunuJ}JHb|l<Y_F6w~&e75v
zD%^gmG+_C{G|C6W^VS<xkLA$hNn~somI0<a`2%Js&}Fn8PBTv;R1Y=guOqQom#SnB
zi9?p6^ZfJpXG5Gf$E@ffl{r#>4TA@voz<r?NC*{WAHd+Im>v1LNqc46od@|hd!dU;
zI+Q-q4Xr4_Xg(UDbl0Mcb%!WR!g%X}pfua>NDA(?0P2ihE2=6Hsb2us?d``=f#YP7
zN06ic#nBV#$K6RPl}&ftC+oJgeXdvC1}Qw=k?$NT$Z@0^^;6dwl<=!9b3_~%2%K=%
zJdLO}mo#zj?i5m9(l&Nv2d{=vNeX2ee8f%7{ye_UDSDb!R#Rzqq`!}InfLZ#Wbp=e
zH=oAdfkUlI9cLve_Pidk*p8(mw`iJ9Em~T7EKCwzqzm=jU@U?$eSN2zqSVIhoxfjk
zA@87t7j>2>)NC4^iG>$vUnw6E9=a1cRcn?75he2LO@54!3l>+iI8jG+XV&k>3}WD`
zJ%3>#ItQ1VSupX>`zR)gSmC!?4;lv3&3)=xw6Im5VYm1KURU0(D}u{fR-Jrvh<+I2
zALKj5D9PCMx=zWnT!n0#E{Hj@h+K6~BRWLaxjw#!y#b!T*LWY#A|yr|{TR3y9JCVz
z&yTr<Rlzg=>>K@Qb31+}v2RZ6`^kAKnojm(4;h4s+^nGjQj&9-M>#|ROk|I6WvCJ+
za*uE=DC=2A<{$?$_x(gojp%mJs)<$3G1?ALye7-n8}PV$8vGy#F<Gf=nJoA3$|C+f
zTGjEat-<j+r|C80+MoxL7HABgI<;i@G=@JuA!+umG^`DxbtlD(#qF4(XsFM7G)8#n
zBgGn$B{;FMc1G+Db)g4uYj~O*ILkGBOa}MVc72c`_S5Bl+~SpBV+KpKkTaafg2%B1
z{g(WOZTpAoVTtj@&z5gPl*ag-lkkN#hTdbB&en%6z0P99aB^-Ti%DKVc`)KL?z8&l
zXU|@%_-rn4=__!K`egYnb6q4X0B=j*5Gka!o+TAB$T1<H)Ubfu4F64X?cQSIOB*q~
zjF4?r$`c2}Fddmo#EJyF=ZD-yGved1J1a`3M1W`Cs2kqL-Z4&!&jNXSY)gmF9bQ;@
z%9i$JPhxUYsG4z#>jJXdS@nqjh}zius%bw)GqaMpp7hu$fJn6;pO!<GX+2BW9n@g9
z#iyAIxmV<Ac+?GZMP@ZG_Xa_|wTbj(i(t=UL6$vqNk-F?Gn<tf7}(_$Q?}CB{sgs&
zGRY^pU{-u}qjVDsIh6^zoB10ehNjuh`aPuiVo_lzy=RE(umfN7)?ISlSCY|(t+GSC
v(n#KkhC)t94$qhRp*aCDqs0K@V_k)d$yu=c-sJGv;j_y6y{(sT-y-ragh?$X

literal 0
HcmV?d00001

diff --git a/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx
new file mode 100644
index 0000000000000000000000000000000000000000..8532ca92b5e3d13582eb89597bbfef2f2da5ae27
GIT binary patch
literal 11008
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
ZBtGBpHb!vxwQ2<~S4)!d5T)DW^j`oN)ARrU

literal 0
HcmV?d00001

Patch hide | download patch | download mbox

diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
index 7f0d3a44e..6169041ff 100644
--- a/tests/spec/CMakeLists.txt
+++ b/tests/spec/CMakeLists.txt
@@ -1,5 +1,6 @@ 
 add_subdirectory (amd_framebuffer_multisample_advanced)
 add_subdirectory (amd_depth_clamp_separate)
+add_subdirectory (amd_compressed_atc_texture)
 add_subdirectory (amd_performance_monitor)
 add_subdirectory (amd_pinned_memory)
 add_subdirectory (arb_arrays_of_arrays)
diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
new file mode 100644
index 000000000..0509e44ae
--- /dev/null
+++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
@@ -0,0 +1,6 @@ 
+include_directories(
+	${GLEXT_INCLUDE_DIR}
+	${OPENGL_INCLUDE_PATH}
+)
+link_libraries(piglitutil_${piglit_target_api})
+piglit_add_executable(amd_compressed_atc_texture-miptree miptree.c)
diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
new file mode 100644
index 000000000..144a306f4
--- /dev/null
+++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
@@ -0,0 +1 @@ 
+piglit_include_target_api()
diff --git a/tests/spec/amd_compressed_atc_texture/miptree.c b/tests/spec/amd_compressed_atc_texture/miptree.c
new file mode 100644
index 000000000..386ca9811
--- /dev/null
+++ b/tests/spec/amd_compressed_atc_texture/miptree.c
@@ -0,0 +1,247 @@ 
+/*
+ * Copyright 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file
+ * \brief Test texturing from an ATC miptree of a real image.
+ *
+ * Copied from identical ETC1 test.
+ *
+ * This test uses two data files. The file waffles-compressed-atc-64x32.ktx
+ * contains a full miptree in GL_ATC_RGB_AMD format of a 2D texture of
+ * waffles and fruit [1].  The base level size is 64x32 pixels. The file
+ * waffles-decompressed-rgba-64x32.ktx contains a parallel miptree in GL_RGBA
+ * format. Each of its RGBA images was obtained by decompressing the corresponding
+ * ATC image with AMD's Compressonator tool [2].
+ *
+ * This test draws each miplevel i of the ATC texture such that the image's
+ * lower left corner is at (x=0, y=sum(height of miplevel j for j=0 to i-1)),
+ * and it draws each miplevel of the RGB texture to the right of its
+ * corresponding ATC image. Then it compares that the images are identical.
+ *
+ * [1] The reference image is located at http://people.freedesktop.org/~chadversary/permalink/2012-07-09/1574cff2-d091-4421-a3cf-b56c7943d060.jpg.
+ * [2] https://github.com/GPUOpen-Tools/Compressonator
+ *
+ * Compressonator tool is not perfect:
+ * -RGBA is used for the decompressed image because the tool is buggy with RGB.
+ * -red/blue swapped when decompressing ATC (used script to swap red/blue back for test image)
+ * -7th 1x1 mipmap isn't generated (num_levels 6 instead of 7)
+ */
+
+#include "piglit-util-gl.h"
+#include "piglit_ktx.h"
+
+#define num_levels 6
+#define level0_width 64
+#define level0_height 32
+
+#define num_vertices 4
+
+static const int window_width = 2 * level0_width;
+static const int window_height = 2 * level0_height;
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+	config.supports_gl_es_version = 20;
+
+	config.window_width = window_width;
+	config.window_height = window_height;
+	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+
+static GLuint prog;
+
+/* Texture objects. */
+static GLuint compressed_tex;
+static GLuint decompressed_tex;
+
+/**
+ * The \a filename is relative to the current test's source directory.
+ *
+ * A new texture is created and returned in \a tex_name.
+ */
+static void
+load_texture(const char *filename, GLuint *tex_name)
+{
+	struct piglit_ktx *ktx;
+	const struct piglit_ktx_info *info;
+	char filepath[4096];
+	bool ok = true;
+
+	piglit_join_paths(filepath, sizeof(filepath), 5,
+	                  piglit_source_dir(),
+	                  "tests",
+	                  "spec",
+	                  "amd_compressed_atc_texture",
+	                  filename);
+
+	ktx = piglit_ktx_read_file(filepath);
+	if (ktx == NULL)
+		piglit_report_result(PIGLIT_FAIL);
+
+	info = piglit_ktx_get_info(ktx);
+	assert(info->num_miplevels == num_levels);
+	assert(info->target == GL_TEXTURE_2D);
+	assert(info->pixel_width == level0_width);
+	assert(info->pixel_height== level0_height);
+
+	*tex_name = 0;
+	ok = piglit_ktx_load_texture(ktx, tex_name, NULL);
+	if (!ok)
+		piglit_report_result(PIGLIT_FAIL);
+
+	piglit_ktx_destroy(ktx);
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	static const char compressed_filename[] = "waffles-compressed-atc-64x32.ktx";
+	static const char decompressed_filename[] = "waffles-decompressed-rgba-64x32.ktx";
+
+	const char vs_source[] =
+		"#version 100\n"
+		"\n"
+		"uniform vec2 window_pixel_size;\n"
+		"uniform vec2 level_pixel_size;\n"
+		"uniform vec2 pixel_offset;\n"
+		"\n"
+		"// vertex is some corner of the unit square [0,1]^2 \n"
+		"attribute vec2 vertex;\n"
+		"varying vec2 tex_coord;\n"
+		"\n"
+		"void main()\n"
+		"{\n"
+		"    vec2 pos = vertex;\n"
+		"    pos *= level_pixel_size;\n"
+		"    pos += pixel_offset;\n"
+		"    pos /= 0.5 * window_pixel_size;\n"
+		"    pos -= vec2(1, 1);\n"
+		"    gl_Position = vec4(pos.xy, 0.0, 1.0);\n"
+		"\n"
+		"    tex_coord = vertex;\n"
+		"}\n";
+
+	const char fs_source[] =
+		"#version 100\n"
+		"precision highp float;\n"
+		"\n"
+		"uniform sampler2D tex;\n"
+		"varying vec2 tex_coord;\n"
+		"\n"
+		"void main()\n"
+		"{\n"
+		"    vec4 t = texture2D(tex, tex_coord);\n"
+		"    gl_FragColor = vec4(t.rgb, 1.0);\n"
+		"}\n";
+
+	/* Draw a square triangle strip. */
+	const GLfloat vertices[2 * num_vertices] = {
+		0, 0,
+		1, 0,
+		1, 1,
+		0, 1,
+	};
+
+	GLint vertex_loc;
+	GLuint vertex_buf;
+
+	piglit_require_extension("GL_AMD_compressed_ATC_texture");
+
+	load_texture(compressed_filename, &compressed_tex);
+	load_texture(decompressed_filename, &decompressed_tex);
+
+	glClearColor(1.0, 0.0, 0.0, 1.0);
+	glViewport(0, 0, window_width, window_height);
+
+	prog = piglit_build_simple_program(vs_source, fs_source);
+	glUseProgram(prog);
+
+	vertex_loc = glGetAttribLocation(prog, "vertex");
+	glGenBuffers(1, &vertex_buf);
+	glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
+	glEnableVertexAttribArray(vertex_loc);
+	glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
+	             GL_STATIC_DRAW);
+
+	glUniform1i(glGetUniformLocation(prog, "tex"), 0);
+	glActiveTexture(GL_TEXTURE0);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+	glUniform2f(glGetUniformLocation(prog, "window_pixel_size"),
+	            window_width, window_height);
+}
+
+static void
+minify(int *x)
+{
+	assert(*x > 0);
+
+	if (*x > 1)
+		*x >>= 1;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+	GLint pixel_offset_loc = glGetUniformLocation(prog, "pixel_offset");
+	GLint level_pixel_size_loc = glGetUniformLocation(prog, "level_pixel_size");
+
+	int level = 0;
+	int level_width = level0_width;
+	int level_height = level0_height;
+	int y_offset = 0;
+
+	bool pass = true;
+
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	for (level = 0; level < num_levels; ++level) {
+		glUniform2f(level_pixel_size_loc,
+		            (float) level_width,
+		            (float) level_height);
+
+		/* Draw miplevel of compressed texture. */
+		glBindTexture(GL_TEXTURE_2D, compressed_tex);
+		glUniform2f(pixel_offset_loc, 0, y_offset);
+		glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
+
+		/* Draw miplevel of decompressed texture. */
+		glBindTexture(GL_TEXTURE_2D, decompressed_tex);
+		glUniform2f(pixel_offset_loc, level0_width, y_offset);
+		glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
+
+		y_offset += level_height;
+		minify(&level_width);
+		minify(&level_height);
+	}
+
+	pass = piglit_probe_rect_halves_equal_rgba(0, 0, window_width, window_height);
+	piglit_present_results();
+
+	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}

Comments

Nice, this is now an exact copy of the etc1 miptree test (except for
the actual files, obviously).

Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>

Would probably good to glance at an apitrace and ensure that the ktx
really does contain ATC data and not ETC1 or whatever else...

  -ilia

On Tue, Apr 9, 2019 at 4:21 PM Jonathan Marek <jonathan@marek.ca> wrote:
>
> This echoes the ETC1 miptree test, and even uses the same image.
>
> Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
> ---
>  tests/spec/CMakeLists.txt                     |   1 +
>  .../CMakeLists.gles2.txt                      |   6 +
>  .../amd_compressed_atc_texture/CMakeLists.txt |   1 +
>  .../spec/amd_compressed_atc_texture/miptree.c | 247 ++++++++++++++++++
>  .../waffles-compressed-atc-64x32.ktx          | Bin 0 -> 1464 bytes
>  .../waffles-decompressed-rgba-64x32.ktx       | Bin 0 -> 11008 bytes
>  6 files changed, 255 insertions(+)
>  create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
>  create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.txt
>  create mode 100644 tests/spec/amd_compressed_atc_texture/miptree.c
>  create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
>  create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx
>
> diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
> index 7f0d3a44e..6169041ff 100644
> --- a/tests/spec/CMakeLists.txt
> +++ b/tests/spec/CMakeLists.txt
> @@ -1,5 +1,6 @@
>  add_subdirectory (amd_framebuffer_multisample_advanced)
>  add_subdirectory (amd_depth_clamp_separate)
> +add_subdirectory (amd_compressed_atc_texture)
>  add_subdirectory (amd_performance_monitor)
>  add_subdirectory (amd_pinned_memory)
>  add_subdirectory (arb_arrays_of_arrays)
> diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
> new file mode 100644
> index 000000000..0509e44ae
> --- /dev/null
> +++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
> @@ -0,0 +1,6 @@
> +include_directories(
> +       ${GLEXT_INCLUDE_DIR}
> +       ${OPENGL_INCLUDE_PATH}
> +)
> +link_libraries(piglitutil_${piglit_target_api})
> +piglit_add_executable(amd_compressed_atc_texture-miptree miptree.c)
> diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
> new file mode 100644
> index 000000000..144a306f4
> --- /dev/null
> +++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
> @@ -0,0 +1 @@
> +piglit_include_target_api()
> diff --git a/tests/spec/amd_compressed_atc_texture/miptree.c b/tests/spec/amd_compressed_atc_texture/miptree.c
> new file mode 100644
> index 000000000..386ca9811
> --- /dev/null
> +++ b/tests/spec/amd_compressed_atc_texture/miptree.c
> @@ -0,0 +1,247 @@
> +/*
> + * Copyright 2012 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +/**
> + * \file
> + * \brief Test texturing from an ATC miptree of a real image.
> + *
> + * Copied from identical ETC1 test.
> + *
> + * This test uses two data files. The file waffles-compressed-atc-64x32.ktx
> + * contains a full miptree in GL_ATC_RGB_AMD format of a 2D texture of
> + * waffles and fruit [1].  The base level size is 64x32 pixels. The file
> + * waffles-decompressed-rgba-64x32.ktx contains a parallel miptree in GL_RGBA
> + * format. Each of its RGBA images was obtained by decompressing the corresponding
> + * ATC image with AMD's Compressonator tool [2].
> + *
> + * This test draws each miplevel i of the ATC texture such that the image's
> + * lower left corner is at (x=0, y=sum(height of miplevel j for j=0 to i-1)),
> + * and it draws each miplevel of the RGB texture to the right of its
> + * corresponding ATC image. Then it compares that the images are identical.
> + *
> + * [1] The reference image is located at http://people.freedesktop.org/~chadversary/permalink/2012-07-09/1574cff2-d091-4421-a3cf-b56c7943d060.jpg.
> + * [2] https://github.com/GPUOpen-Tools/Compressonator
> + *
> + * Compressonator tool is not perfect:
> + * -RGBA is used for the decompressed image because the tool is buggy with RGB.
> + * -red/blue swapped when decompressing ATC (used script to swap red/blue back for test image)
> + * -7th 1x1 mipmap isn't generated (num_levels 6 instead of 7)
> + */
> +
> +#include "piglit-util-gl.h"
> +#include "piglit_ktx.h"
> +
> +#define num_levels 6
> +#define level0_width 64
> +#define level0_height 32
> +
> +#define num_vertices 4
> +
> +static const int window_width = 2 * level0_width;
> +static const int window_height = 2 * level0_height;
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +       config.supports_gl_es_version = 20;
> +
> +       config.window_width = window_width;
> +       config.window_height = window_height;
> +       config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +
> +static GLuint prog;
> +
> +/* Texture objects. */
> +static GLuint compressed_tex;
> +static GLuint decompressed_tex;
> +
> +/**
> + * The \a filename is relative to the current test's source directory.
> + *
> + * A new texture is created and returned in \a tex_name.
> + */
> +static void
> +load_texture(const char *filename, GLuint *tex_name)
> +{
> +       struct piglit_ktx *ktx;
> +       const struct piglit_ktx_info *info;
> +       char filepath[4096];
> +       bool ok = true;
> +
> +       piglit_join_paths(filepath, sizeof(filepath), 5,
> +                         piglit_source_dir(),
> +                         "tests",
> +                         "spec",
> +                         "amd_compressed_atc_texture",
> +                         filename);
> +
> +       ktx = piglit_ktx_read_file(filepath);
> +       if (ktx == NULL)
> +               piglit_report_result(PIGLIT_FAIL);
> +
> +       info = piglit_ktx_get_info(ktx);
> +       assert(info->num_miplevels == num_levels);
> +       assert(info->target == GL_TEXTURE_2D);
> +       assert(info->pixel_width == level0_width);
> +       assert(info->pixel_height== level0_height);
> +
> +       *tex_name = 0;
> +       ok = piglit_ktx_load_texture(ktx, tex_name, NULL);
> +       if (!ok)
> +               piglit_report_result(PIGLIT_FAIL);
> +
> +       piglit_ktx_destroy(ktx);
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +       static const char compressed_filename[] = "waffles-compressed-atc-64x32.ktx";
> +       static const char decompressed_filename[] = "waffles-decompressed-rgba-64x32.ktx";
> +
> +       const char vs_source[] =
> +               "#version 100\n"
> +               "\n"
> +               "uniform vec2 window_pixel_size;\n"
> +               "uniform vec2 level_pixel_size;\n"
> +               "uniform vec2 pixel_offset;\n"
> +               "\n"
> +               "// vertex is some corner of the unit square [0,1]^2 \n"
> +               "attribute vec2 vertex;\n"
> +               "varying vec2 tex_coord;\n"
> +               "\n"
> +               "void main()\n"
> +               "{\n"
> +               "    vec2 pos = vertex;\n"
> +               "    pos *= level_pixel_size;\n"
> +               "    pos += pixel_offset;\n"
> +               "    pos /= 0.5 * window_pixel_size;\n"
> +               "    pos -= vec2(1, 1);\n"
> +               "    gl_Position = vec4(pos.xy, 0.0, 1.0);\n"
> +               "\n"
> +               "    tex_coord = vertex;\n"
> +               "}\n";
> +
> +       const char fs_source[] =
> +               "#version 100\n"
> +               "precision highp float;\n"
> +               "\n"
> +               "uniform sampler2D tex;\n"
> +               "varying vec2 tex_coord;\n"
> +               "\n"
> +               "void main()\n"
> +               "{\n"
> +               "    vec4 t = texture2D(tex, tex_coord);\n"
> +               "    gl_FragColor = vec4(t.rgb, 1.0);\n"
> +               "}\n";
> +
> +       /* Draw a square triangle strip. */
> +       const GLfloat vertices[2 * num_vertices] = {
> +               0, 0,
> +               1, 0,
> +               1, 1,
> +               0, 1,
> +       };
> +
> +       GLint vertex_loc;
> +       GLuint vertex_buf;
> +
> +       piglit_require_extension("GL_AMD_compressed_ATC_texture");
> +
> +       load_texture(compressed_filename, &compressed_tex);
> +       load_texture(decompressed_filename, &decompressed_tex);
> +
> +       glClearColor(1.0, 0.0, 0.0, 1.0);
> +       glViewport(0, 0, window_width, window_height);
> +
> +       prog = piglit_build_simple_program(vs_source, fs_source);
> +       glUseProgram(prog);
> +
> +       vertex_loc = glGetAttribLocation(prog, "vertex");
> +       glGenBuffers(1, &vertex_buf);
> +       glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
> +       glEnableVertexAttribArray(vertex_loc);
> +       glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
> +       glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
> +                    GL_STATIC_DRAW);
> +
> +       glUniform1i(glGetUniformLocation(prog, "tex"), 0);
> +       glActiveTexture(GL_TEXTURE0);
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
> +
> +       glUniform2f(glGetUniformLocation(prog, "window_pixel_size"),
> +                   window_width, window_height);
> +}
> +
> +static void
> +minify(int *x)
> +{
> +       assert(*x > 0);
> +
> +       if (*x > 1)
> +               *x >>= 1;
> +}
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +       GLint pixel_offset_loc = glGetUniformLocation(prog, "pixel_offset");
> +       GLint level_pixel_size_loc = glGetUniformLocation(prog, "level_pixel_size");
> +
> +       int level = 0;
> +       int level_width = level0_width;
> +       int level_height = level0_height;
> +       int y_offset = 0;
> +
> +       bool pass = true;
> +
> +       glClear(GL_COLOR_BUFFER_BIT);
> +
> +       for (level = 0; level < num_levels; ++level) {
> +               glUniform2f(level_pixel_size_loc,
> +                           (float) level_width,
> +                           (float) level_height);
> +
> +               /* Draw miplevel of compressed texture. */
> +               glBindTexture(GL_TEXTURE_2D, compressed_tex);
> +               glUniform2f(pixel_offset_loc, 0, y_offset);
> +               glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
> +
> +               /* Draw miplevel of decompressed texture. */
> +               glBindTexture(GL_TEXTURE_2D, decompressed_tex);
> +               glUniform2f(pixel_offset_loc, level0_width, y_offset);
> +               glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
> +
> +               y_offset += level_height;
> +               minify(&level_width);
> +               minify(&level_height);
> +       }
> +
> +       pass = piglit_probe_rect_halves_equal_rgba(0, 0, window_width, window_height);
> +       piglit_present_results();
> +
> +       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> diff --git a/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
> new file mode 100644
> index 0000000000000000000000000000000000000000..6d7acc71e060032c5eedd75927e3b43cbd567ad9
> GIT binary patch
> literal 1464
> zcmZ8hZ%k8H6u(cU)jpSY3nL(Hq!SjHZ0G_DCUd-k=qfWQhPna4DHRNKQs)+<G6AvM
> zG&7EE>b@A1Ni_&bjl*S|NKtSErb*qX@x$yZ@*agMTDSLl3--OU`)b&So#egWz4zR6
> zekbS8?Jg<%AZ_*Pt1oDlX{ZGY7a<~)@+0!?F@zSUAjFV$8u{i$(W~Y+#DZ;PVP8y=
> z*hT<k_4(o``K)mS00qkk`UzeP!8<l9*?1~dw#0VqpeQCQ&wGDB%gm`8eUM7{s?&xe
> zD!LMivhR+y?AD<oy&ph|MxmM50SE}iG48j3EERqsECPunuJ}JHb|l<Y_F6w~&e75v
> zD%^gmG+_C{G|C6W^VS<xkLA$hNn~somI0<a`2%Js&}Fn8PBTv;R1Y=guOqQom#SnB
> zi9?p6^ZfJpXG5Gf$E@ffl{r#>4TA@voz<r?NC*{WAHd+Im>v1LNqc46od@|hd!dU;
> zI+Q-q4Xr4_Xg(UDbl0Mcb%!WR!g%X}pfua>NDA(?0P2ihE2=6Hsb2us?d``=f#YP7
> zN06ic#nBV#$K6RPl}&ftC+oJgeXdvC1}Qw=k?$NT$Z@0^^;6dwl<=!9b3_~%2%K=%
> zJdLO}mo#zj?i5m9(l&Nv2d{=vNeX2ee8f%7{ye_UDSDb!R#Rzqq`!}InfLZ#Wbp=e
> zH=oAdfkUlI9cLve_Pidk*p8(mw`iJ9Em~T7EKCwzqzm=jU@U?$eSN2zqSVIhoxfjk
> zA@87t7j>2>)NC4^iG>$vUnw6E9=a1cRcn?75he2LO@54!3l>+iI8jG+XV&k>3}WD`
> zJ%3>#ItQ1VSupX>`zR)gSmC!?4;lv3&3)=xw6Im5VYm1KURU0(D}u{fR-Jrvh<+I2
> zALKj5D9PCMx=zWnT!n0#E{Hj@h+K6~BRWLaxjw#!y#b!T*LWY#A|yr|{TR3y9JCVz
> z&yTr<Rlzg=>>K@Qb31+}v2RZ6`^kAKnojm(4;h4s+^nGjQj&9-M>#|ROk|I6WvCJ+
> za*uE=DC=2A<{$?$_x(gojp%mJs)<$3G1?ALye7-n8}PV$8vGy#F<Gf=nJoA3$|C+f
> zTGjEat-<j+r|C80+MoxL7HABgI<;i@G=@JuA!+umG^`DxbtlD(#qF4(XsFM7G)8#n
> zBgGn$B{;FMc1G+Db)g4uYj~O*ILkGBOa}MVc72c`_S5Bl+~SpBV+KpKkTaafg2%B1
> z{g(WOZTpAoVTtj@&z5gPl*ag-lkkN#hTdbB&en%6z0P99aB^-Ti%DKVc`)KL?z8&l
> zXU|@%_-rn4=__!K`egYnb6q4X0B=j*5Gka!o+TAB$T1<H)Ubfu4F64X?cQSIOB*q~
> zjF4?r$`c2}Fddmo#EJyF=ZD-yGved1J1a`3M1W`Cs2kqL-Z4&!&jNXSY)gmF9bQ;@
> z%9i$JPhxUYsG4z#>jJXdS@nqjh}zius%bw)GqaMpp7hu$fJn6;pO!<GX+2BW9n@g9
> z#iyAIxmV<Ac+?GZMP@ZG_Xa_|wTbj(i(t=UL6$vqNk-F?Gn<tf7}(_$Q?}CB{sgs&
> zGRY^pU{-u}qjVDsIh6^zoB10ehNjuh`aPuiVo_lzy=RE(umfN7)?ISlSCY|(t+GSC
> v(n#KkhC)t94$qhRp*aCDqs0K@V_k)d$yu=c-sJGv;j_y6y{(sT-y-ragh?$X
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx
> new file mode 100644
> index 0000000000000000000000000000000000000000..8532ca92b5e3d13582eb89597bbfef2f2da5ae27
> GIT binary patch
> literal 11008
> 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
> ZBtGBpHb!vxwQ2<~S4)!d5T)DW^j`oN)ARrU
>
> literal 0
> HcmV?d00001
>
> --
> 2.17.1
>
The gl_internal_format field in the ktx file is 0x8C92 (ATC_RGB_AMD) so 
it should be good.

On 4/9/19 6:50 PM, Ilia Mirkin wrote:
> Nice, this is now an exact copy of the etc1 miptree test (except for
> the actual files, obviously).
> 
> Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>
> 
> Would probably good to glance at an apitrace and ensure that the ktx
> really does contain ATC data and not ETC1 or whatever else...
> 
>    -ilia
> 
> On Tue, Apr 9, 2019 at 4:21 PM Jonathan Marek <jonathan@marek.ca> wrote:
>>
>> This echoes the ETC1 miptree test, and even uses the same image.
>>
>> Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
>> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
>> ---
>>   tests/spec/CMakeLists.txt                     |   1 +
>>   .../CMakeLists.gles2.txt                      |   6 +
>>   .../amd_compressed_atc_texture/CMakeLists.txt |   1 +
>>   .../spec/amd_compressed_atc_texture/miptree.c | 247 ++++++++++++++++++
>>   .../waffles-compressed-atc-64x32.ktx          | Bin 0 -> 1464 bytes
>>   .../waffles-decompressed-rgba-64x32.ktx       | Bin 0 -> 11008 bytes
>>   6 files changed, 255 insertions(+)
>>   create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
>>   create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.txt
>>   create mode 100644 tests/spec/amd_compressed_atc_texture/miptree.c
>>   create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
>>   create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx
>>
>> diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
>> index 7f0d3a44e..6169041ff 100644
>> --- a/tests/spec/CMakeLists.txt
>> +++ b/tests/spec/CMakeLists.txt
>> @@ -1,5 +1,6 @@
>>   add_subdirectory (amd_framebuffer_multisample_advanced)
>>   add_subdirectory (amd_depth_clamp_separate)
>> +add_subdirectory (amd_compressed_atc_texture)
>>   add_subdirectory (amd_performance_monitor)
>>   add_subdirectory (amd_pinned_memory)
>>   add_subdirectory (arb_arrays_of_arrays)
>> diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
>> new file mode 100644
>> index 000000000..0509e44ae
>> --- /dev/null
>> +++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
>> @@ -0,0 +1,6 @@
>> +include_directories(
>> +       ${GLEXT_INCLUDE_DIR}
>> +       ${OPENGL_INCLUDE_PATH}
>> +)
>> +link_libraries(piglitutil_${piglit_target_api})
>> +piglit_add_executable(amd_compressed_atc_texture-miptree miptree.c)
>> diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
>> new file mode 100644
>> index 000000000..144a306f4
>> --- /dev/null
>> +++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
>> @@ -0,0 +1 @@
>> +piglit_include_target_api()
>> diff --git a/tests/spec/amd_compressed_atc_texture/miptree.c b/tests/spec/amd_compressed_atc_texture/miptree.c
>> new file mode 100644
>> index 000000000..386ca9811
>> --- /dev/null
>> +++ b/tests/spec/amd_compressed_atc_texture/miptree.c
>> @@ -0,0 +1,247 @@
>> +/*
>> + * Copyright 2012 Intel Corporation
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including the next
>> + * paragraph) shall be included in all copies or substantial portions of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> + * DEALINGS IN THE SOFTWARE.
>> + */
>> +
>> +/**
>> + * \file
>> + * \brief Test texturing from an ATC miptree of a real image.
>> + *
>> + * Copied from identical ETC1 test.
>> + *
>> + * This test uses two data files. The file waffles-compressed-atc-64x32.ktx
>> + * contains a full miptree in GL_ATC_RGB_AMD format of a 2D texture of
>> + * waffles and fruit [1].  The base level size is 64x32 pixels. The file
>> + * waffles-decompressed-rgba-64x32.ktx contains a parallel miptree in GL_RGBA
>> + * format. Each of its RGBA images was obtained by decompressing the corresponding
>> + * ATC image with AMD's Compressonator tool [2].
>> + *
>> + * This test draws each miplevel i of the ATC texture such that the image's
>> + * lower left corner is at (x=0, y=sum(height of miplevel j for j=0 to i-1)),
>> + * and it draws each miplevel of the RGB texture to the right of its
>> + * corresponding ATC image. Then it compares that the images are identical.
>> + *
>> + * [1] The reference image is located at http://people.freedesktop.org/~chadversary/permalink/2012-07-09/1574cff2-d091-4421-a3cf-b56c7943d060.jpg.
>> + * [2] https://github.com/GPUOpen-Tools/Compressonator
>> + *
>> + * Compressonator tool is not perfect:
>> + * -RGBA is used for the decompressed image because the tool is buggy with RGB.
>> + * -red/blue swapped when decompressing ATC (used script to swap red/blue back for test image)
>> + * -7th 1x1 mipmap isn't generated (num_levels 6 instead of 7)
>> + */
>> +
>> +#include "piglit-util-gl.h"
>> +#include "piglit_ktx.h"
>> +
>> +#define num_levels 6
>> +#define level0_width 64
>> +#define level0_height 32
>> +
>> +#define num_vertices 4
>> +
>> +static const int window_width = 2 * level0_width;
>> +static const int window_height = 2 * level0_height;
>> +
>> +PIGLIT_GL_TEST_CONFIG_BEGIN
>> +
>> +       config.supports_gl_es_version = 20;
>> +
>> +       config.window_width = window_width;
>> +       config.window_height = window_height;
>> +       config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
>> +
>> +PIGLIT_GL_TEST_CONFIG_END
>> +
>> +
>> +static GLuint prog;
>> +
>> +/* Texture objects. */
>> +static GLuint compressed_tex;
>> +static GLuint decompressed_tex;
>> +
>> +/**
>> + * The \a filename is relative to the current test's source directory.
>> + *
>> + * A new texture is created and returned in \a tex_name.
>> + */
>> +static void
>> +load_texture(const char *filename, GLuint *tex_name)
>> +{
>> +       struct piglit_ktx *ktx;
>> +       const struct piglit_ktx_info *info;
>> +       char filepath[4096];
>> +       bool ok = true;
>> +
>> +       piglit_join_paths(filepath, sizeof(filepath), 5,
>> +                         piglit_source_dir(),
>> +                         "tests",
>> +                         "spec",
>> +                         "amd_compressed_atc_texture",
>> +                         filename);
>> +
>> +       ktx = piglit_ktx_read_file(filepath);
>> +       if (ktx == NULL)
>> +               piglit_report_result(PIGLIT_FAIL);
>> +
>> +       info = piglit_ktx_get_info(ktx);
>> +       assert(info->num_miplevels == num_levels);
>> +       assert(info->target == GL_TEXTURE_2D);
>> +       assert(info->pixel_width == level0_width);
>> +       assert(info->pixel_height== level0_height);
>> +
>> +       *tex_name = 0;
>> +       ok = piglit_ktx_load_texture(ktx, tex_name, NULL);
>> +       if (!ok)
>> +               piglit_report_result(PIGLIT_FAIL);
>> +
>> +       piglit_ktx_destroy(ktx);
>> +}
>> +
>> +void
>> +piglit_init(int argc, char **argv)
>> +{
>> +       static const char compressed_filename[] = "waffles-compressed-atc-64x32.ktx";
>> +       static const char decompressed_filename[] = "waffles-decompressed-rgba-64x32.ktx";
>> +
>> +       const char vs_source[] =
>> +               "#version 100\n"
>> +               "\n"
>> +               "uniform vec2 window_pixel_size;\n"
>> +               "uniform vec2 level_pixel_size;\n"
>> +               "uniform vec2 pixel_offset;\n"
>> +               "\n"
>> +               "// vertex is some corner of the unit square [0,1]^2 \n"
>> +               "attribute vec2 vertex;\n"
>> +               "varying vec2 tex_coord;\n"
>> +               "\n"
>> +               "void main()\n"
>> +               "{\n"
>> +               "    vec2 pos = vertex;\n"
>> +               "    pos *= level_pixel_size;\n"
>> +               "    pos += pixel_offset;\n"
>> +               "    pos /= 0.5 * window_pixel_size;\n"
>> +               "    pos -= vec2(1, 1);\n"
>> +               "    gl_Position = vec4(pos.xy, 0.0, 1.0);\n"
>> +               "\n"
>> +               "    tex_coord = vertex;\n"
>> +               "}\n";
>> +
>> +       const char fs_source[] =
>> +               "#version 100\n"
>> +               "precision highp float;\n"
>> +               "\n"
>> +               "uniform sampler2D tex;\n"
>> +               "varying vec2 tex_coord;\n"
>> +               "\n"
>> +               "void main()\n"
>> +               "{\n"
>> +               "    vec4 t = texture2D(tex, tex_coord);\n"
>> +               "    gl_FragColor = vec4(t.rgb, 1.0);\n"
>> +               "}\n";
>> +
>> +       /* Draw a square triangle strip. */
>> +       const GLfloat vertices[2 * num_vertices] = {
>> +               0, 0,
>> +               1, 0,
>> +               1, 1,
>> +               0, 1,
>> +       };
>> +
>> +       GLint vertex_loc;
>> +       GLuint vertex_buf;
>> +
>> +       piglit_require_extension("GL_AMD_compressed_ATC_texture");
>> +
>> +       load_texture(compressed_filename, &compressed_tex);
>> +       load_texture(decompressed_filename, &decompressed_tex);
>> +
>> +       glClearColor(1.0, 0.0, 0.0, 1.0);
>> +       glViewport(0, 0, window_width, window_height);
>> +
>> +       prog = piglit_build_simple_program(vs_source, fs_source);
>> +       glUseProgram(prog);
>> +
>> +       vertex_loc = glGetAttribLocation(prog, "vertex");
>> +       glGenBuffers(1, &vertex_buf);
>> +       glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
>> +       glEnableVertexAttribArray(vertex_loc);
>> +       glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
>> +       glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
>> +                    GL_STATIC_DRAW);
>> +
>> +       glUniform1i(glGetUniformLocation(prog, "tex"), 0);
>> +       glActiveTexture(GL_TEXTURE0);
>> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
>> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
>> +
>> +       glUniform2f(glGetUniformLocation(prog, "window_pixel_size"),
>> +                   window_width, window_height);
>> +}
>> +
>> +static void
>> +minify(int *x)
>> +{
>> +       assert(*x > 0);
>> +
>> +       if (*x > 1)
>> +               *x >>= 1;
>> +}
>> +
>> +enum piglit_result
>> +piglit_display(void)
>> +{
>> +       GLint pixel_offset_loc = glGetUniformLocation(prog, "pixel_offset");
>> +       GLint level_pixel_size_loc = glGetUniformLocation(prog, "level_pixel_size");
>> +
>> +       int level = 0;
>> +       int level_width = level0_width;
>> +       int level_height = level0_height;
>> +       int y_offset = 0;
>> +
>> +       bool pass = true;
>> +
>> +       glClear(GL_COLOR_BUFFER_BIT);
>> +
>> +       for (level = 0; level < num_levels; ++level) {
>> +               glUniform2f(level_pixel_size_loc,
>> +                           (float) level_width,
>> +                           (float) level_height);
>> +
>> +               /* Draw miplevel of compressed texture. */
>> +               glBindTexture(GL_TEXTURE_2D, compressed_tex);
>> +               glUniform2f(pixel_offset_loc, 0, y_offset);
>> +               glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
>> +
>> +               /* Draw miplevel of decompressed texture. */
>> +               glBindTexture(GL_TEXTURE_2D, decompressed_tex);
>> +               glUniform2f(pixel_offset_loc, level0_width, y_offset);
>> +               glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
>> +
>> +               y_offset += level_height;
>> +               minify(&level_width);
>> +               minify(&level_height);
>> +       }
>> +
>> +       pass = piglit_probe_rect_halves_equal_rgba(0, 0, window_width, window_height);
>> +       piglit_present_results();
>> +
>> +       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
>> +}
>> diff --git a/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..6d7acc71e060032c5eedd75927e3b43cbd567ad9
>> GIT binary patch
>> literal 1464
>> zcmZ8hZ%k8H6u(cU)jpSY3nL(Hq!SjHZ0G_DCUd-k=qfWQhPna4DHRNKQs)+<G6AvM
>> zG&7EE>b@A1Ni_&bjl*S|NKtSErb*qX@x$yZ@*agMTDSLl3--OU`)b&So#egWz4zR6
>> zekbS8?Jg<%AZ_*Pt1oDlX{ZGY7a<~)@+0!?F@zSUAjFV$8u{i$(W~Y+#DZ;PVP8y=
>> z*hT<k_4(o``K)mS00qkk`UzeP!8<l9*?1~dw#0VqpeQCQ&wGDB%gm`8eUM7{s?&xe
>> zD!LMivhR+y?AD<oy&ph|MxmM50SE}iG48j3EERqsECPunuJ}JHb|l<Y_F6w~&e75v
>> zD%^gmG+_C{G|C6W^VS<xkLA$hNn~somI0<a`2%Js&}Fn8PBTv;R1Y=guOqQom#SnB
>> zi9?p6^ZfJpXG5Gf$E@ffl{r#>4TA@voz<r?NC*{WAHd+Im>v1LNqc46od@|hd!dU;
>> zI+Q-q4Xr4_Xg(UDbl0Mcb%!WR!g%X}pfua>NDA(?0P2ihE2=6Hsb2us?d``=f#YP7
>> zN06ic#nBV#$K6RPl}&ftC+oJgeXdvC1}Qw=k?$NT$Z@0^^;6dwl<=!9b3_~%2%K=%
>> zJdLO}mo#zj?i5m9(l&Nv2d{=vNeX2ee8f%7{ye_UDSDb!R#Rzqq`!}InfLZ#Wbp=e
>> zH=oAdfkUlI9cLve_Pidk*p8(mw`iJ9Em~T7EKCwzqzm=jU@U?$eSN2zqSVIhoxfjk
>> zA@87t7j>2>)NC4^iG>$vUnw6E9=a1cRcn?75he2LO@54!3l>+iI8jG+XV&k>3}WD`
>> zJ%3>#ItQ1VSupX>`zR)gSmC!?4;lv3&3)=xw6Im5VYm1KURU0(D}u{fR-Jrvh<+I2
>> zALKj5D9PCMx=zWnT!n0#E{Hj@h+K6~BRWLaxjw#!y#b!T*LWY#A|yr|{TR3y9JCVz
>> z&yTr<Rlzg=>>K@Qb31+}v2RZ6`^kAKnojm(4;h4s+^nGjQj&9-M>#|ROk|I6WvCJ+
>> za*uE=DC=2A<{$?$_x(gojp%mJs)<$3G1?ALye7-n8}PV$8vGy#F<Gf=nJoA3$|C+f
>> zTGjEat-<j+r|C80+MoxL7HABgI<;i@G=@JuA!+umG^`DxbtlD(#qF4(XsFM7G)8#n
>> zBgGn$B{;FMc1G+Db)g4uYj~O*ILkGBOa}MVc72c`_S5Bl+~SpBV+KpKkTaafg2%B1
>> z{g(WOZTpAoVTtj@&z5gPl*ag-lkkN#hTdbB&en%6z0P99aB^-Ti%DKVc`)KL?z8&l
>> zXU|@%_-rn4=__!K`egYnb6q4X0B=j*5Gka!o+TAB$T1<H)Ubfu4F64X?cQSIOB*q~
>> zjF4?r$`c2}Fddmo#EJyF=ZD-yGved1J1a`3M1W`Cs2kqL-Z4&!&jNXSY)gmF9bQ;@
>> z%9i$JPhxUYsG4z#>jJXdS@nqjh}zius%bw)GqaMpp7hu$fJn6;pO!<GX+2BW9n@g9
>> z#iyAIxmV<Ac+?GZMP@ZG_Xa_|wTbj(i(t=UL6$vqNk-F?Gn<tf7}(_$Q?}CB{sgs&
>> zGRY^pU{-u}qjVDsIh6^zoB10ehNjuh`aPuiVo_lzy=RE(umfN7)?ISlSCY|(t+GSC
>> v(n#KkhC)t94$qhRp*aCDqs0K@V_k)d$yu=c-sJGv;j_y6y{(sT-y-ragh?$X
>>
>> literal 0
>> HcmV?d00001
>>
>> diff --git a/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..8532ca92b5e3d13582eb89597bbfef2f2da5ae27
>> GIT binary patch
>> literal 11008
>> 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
>> ZBtGBpHb!vxwQ2<~S4)!d5T)DW^j`oN)ARrU
>>
>> literal 0
>> HcmV?d00001
>>
>> --
>> 2.17.1
>>
I'm going to push this tonight unless someone objects. (With a small
fixup to add the test to the opengl.py list.)

On Tue, Apr 9, 2019 at 6:56 PM Jonathan Marek <jonathan@marek.ca> wrote:
>
> The gl_internal_format field in the ktx file is 0x8C92 (ATC_RGB_AMD) so
> it should be good.
>
> On 4/9/19 6:50 PM, Ilia Mirkin wrote:
> > Nice, this is now an exact copy of the etc1 miptree test (except for
> > the actual files, obviously).
> >
> > Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>
> >
> > Would probably good to glance at an apitrace and ensure that the ktx
> > really does contain ATC data and not ETC1 or whatever else...
> >
> >    -ilia
> >
> > On Tue, Apr 9, 2019 at 4:21 PM Jonathan Marek <jonathan@marek.ca> wrote:
> >>
> >> This echoes the ETC1 miptree test, and even uses the same image.
> >>
> >> Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
> >> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
> >> ---
> >>   tests/spec/CMakeLists.txt                     |   1 +
> >>   .../CMakeLists.gles2.txt                      |   6 +
> >>   .../amd_compressed_atc_texture/CMakeLists.txt |   1 +
> >>   .../spec/amd_compressed_atc_texture/miptree.c | 247 ++++++++++++++++++
> >>   .../waffles-compressed-atc-64x32.ktx          | Bin 0 -> 1464 bytes
> >>   .../waffles-decompressed-rgba-64x32.ktx       | Bin 0 -> 11008 bytes
> >>   6 files changed, 255 insertions(+)
> >>   create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
> >>   create mode 100644 tests/spec/amd_compressed_atc_texture/CMakeLists.txt
> >>   create mode 100644 tests/spec/amd_compressed_atc_texture/miptree.c
> >>   create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
> >>   create mode 100644 tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx
> >>
> >> diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt
> >> index 7f0d3a44e..6169041ff 100644
> >> --- a/tests/spec/CMakeLists.txt
> >> +++ b/tests/spec/CMakeLists.txt
> >> @@ -1,5 +1,6 @@
> >>   add_subdirectory (amd_framebuffer_multisample_advanced)
> >>   add_subdirectory (amd_depth_clamp_separate)
> >> +add_subdirectory (amd_compressed_atc_texture)
> >>   add_subdirectory (amd_performance_monitor)
> >>   add_subdirectory (amd_pinned_memory)
> >>   add_subdirectory (arb_arrays_of_arrays)
> >> diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
> >> new file mode 100644
> >> index 000000000..0509e44ae
> >> --- /dev/null
> >> +++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.gles2.txt
> >> @@ -0,0 +1,6 @@
> >> +include_directories(
> >> +       ${GLEXT_INCLUDE_DIR}
> >> +       ${OPENGL_INCLUDE_PATH}
> >> +)
> >> +link_libraries(piglitutil_${piglit_target_api})
> >> +piglit_add_executable(amd_compressed_atc_texture-miptree miptree.c)
> >> diff --git a/tests/spec/amd_compressed_atc_texture/CMakeLists.txt b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
> >> new file mode 100644
> >> index 000000000..144a306f4
> >> --- /dev/null
> >> +++ b/tests/spec/amd_compressed_atc_texture/CMakeLists.txt
> >> @@ -0,0 +1 @@
> >> +piglit_include_target_api()
> >> diff --git a/tests/spec/amd_compressed_atc_texture/miptree.c b/tests/spec/amd_compressed_atc_texture/miptree.c
> >> new file mode 100644
> >> index 000000000..386ca9811
> >> --- /dev/null
> >> +++ b/tests/spec/amd_compressed_atc_texture/miptree.c
> >> @@ -0,0 +1,247 @@
> >> +/*
> >> + * Copyright 2012 Intel Corporation
> >> + *
> >> + * Permission is hereby granted, free of charge, to any person obtaining a
> >> + * copy of this software and associated documentation files (the "Software"),
> >> + * to deal in the Software without restriction, including without limitation
> >> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> >> + * and/or sell copies of the Software, and to permit persons to whom the
> >> + * Software is furnished to do so, subject to the following conditions:
> >> + *
> >> + * The above copyright notice and this permission notice (including the next
> >> + * paragraph) shall be included in all copies or substantial portions of the
> >> + * Software.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> >> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> >> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> >> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> >> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> >> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> >> + * DEALINGS IN THE SOFTWARE.
> >> + */
> >> +
> >> +/**
> >> + * \file
> >> + * \brief Test texturing from an ATC miptree of a real image.
> >> + *
> >> + * Copied from identical ETC1 test.
> >> + *
> >> + * This test uses two data files. The file waffles-compressed-atc-64x32.ktx
> >> + * contains a full miptree in GL_ATC_RGB_AMD format of a 2D texture of
> >> + * waffles and fruit [1].  The base level size is 64x32 pixels. The file
> >> + * waffles-decompressed-rgba-64x32.ktx contains a parallel miptree in GL_RGBA
> >> + * format. Each of its RGBA images was obtained by decompressing the corresponding
> >> + * ATC image with AMD's Compressonator tool [2].
> >> + *
> >> + * This test draws each miplevel i of the ATC texture such that the image's
> >> + * lower left corner is at (x=0, y=sum(height of miplevel j for j=0 to i-1)),
> >> + * and it draws each miplevel of the RGB texture to the right of its
> >> + * corresponding ATC image. Then it compares that the images are identical.
> >> + *
> >> + * [1] The reference image is located at http://people.freedesktop.org/~chadversary/permalink/2012-07-09/1574cff2-d091-4421-a3cf-b56c7943d060.jpg.
> >> + * [2] https://github.com/GPUOpen-Tools/Compressonator
> >> + *
> >> + * Compressonator tool is not perfect:
> >> + * -RGBA is used for the decompressed image because the tool is buggy with RGB.
> >> + * -red/blue swapped when decompressing ATC (used script to swap red/blue back for test image)
> >> + * -7th 1x1 mipmap isn't generated (num_levels 6 instead of 7)
> >> + */
> >> +
> >> +#include "piglit-util-gl.h"
> >> +#include "piglit_ktx.h"
> >> +
> >> +#define num_levels 6
> >> +#define level0_width 64
> >> +#define level0_height 32
> >> +
> >> +#define num_vertices 4
> >> +
> >> +static const int window_width = 2 * level0_width;
> >> +static const int window_height = 2 * level0_height;
> >> +
> >> +PIGLIT_GL_TEST_CONFIG_BEGIN
> >> +
> >> +       config.supports_gl_es_version = 20;
> >> +
> >> +       config.window_width = window_width;
> >> +       config.window_height = window_height;
> >> +       config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
> >> +
> >> +PIGLIT_GL_TEST_CONFIG_END
> >> +
> >> +
> >> +static GLuint prog;
> >> +
> >> +/* Texture objects. */
> >> +static GLuint compressed_tex;
> >> +static GLuint decompressed_tex;
> >> +
> >> +/**
> >> + * The \a filename is relative to the current test's source directory.
> >> + *
> >> + * A new texture is created and returned in \a tex_name.
> >> + */
> >> +static void
> >> +load_texture(const char *filename, GLuint *tex_name)
> >> +{
> >> +       struct piglit_ktx *ktx;
> >> +       const struct piglit_ktx_info *info;
> >> +       char filepath[4096];
> >> +       bool ok = true;
> >> +
> >> +       piglit_join_paths(filepath, sizeof(filepath), 5,
> >> +                         piglit_source_dir(),
> >> +                         "tests",
> >> +                         "spec",
> >> +                         "amd_compressed_atc_texture",
> >> +                         filename);
> >> +
> >> +       ktx = piglit_ktx_read_file(filepath);
> >> +       if (ktx == NULL)
> >> +               piglit_report_result(PIGLIT_FAIL);
> >> +
> >> +       info = piglit_ktx_get_info(ktx);
> >> +       assert(info->num_miplevels == num_levels);
> >> +       assert(info->target == GL_TEXTURE_2D);
> >> +       assert(info->pixel_width == level0_width);
> >> +       assert(info->pixel_height== level0_height);
> >> +
> >> +       *tex_name = 0;
> >> +       ok = piglit_ktx_load_texture(ktx, tex_name, NULL);
> >> +       if (!ok)
> >> +               piglit_report_result(PIGLIT_FAIL);
> >> +
> >> +       piglit_ktx_destroy(ktx);
> >> +}
> >> +
> >> +void
> >> +piglit_init(int argc, char **argv)
> >> +{
> >> +       static const char compressed_filename[] = "waffles-compressed-atc-64x32.ktx";
> >> +       static const char decompressed_filename[] = "waffles-decompressed-rgba-64x32.ktx";
> >> +
> >> +       const char vs_source[] =
> >> +               "#version 100\n"
> >> +               "\n"
> >> +               "uniform vec2 window_pixel_size;\n"
> >> +               "uniform vec2 level_pixel_size;\n"
> >> +               "uniform vec2 pixel_offset;\n"
> >> +               "\n"
> >> +               "// vertex is some corner of the unit square [0,1]^2 \n"
> >> +               "attribute vec2 vertex;\n"
> >> +               "varying vec2 tex_coord;\n"
> >> +               "\n"
> >> +               "void main()\n"
> >> +               "{\n"
> >> +               "    vec2 pos = vertex;\n"
> >> +               "    pos *= level_pixel_size;\n"
> >> +               "    pos += pixel_offset;\n"
> >> +               "    pos /= 0.5 * window_pixel_size;\n"
> >> +               "    pos -= vec2(1, 1);\n"
> >> +               "    gl_Position = vec4(pos.xy, 0.0, 1.0);\n"
> >> +               "\n"
> >> +               "    tex_coord = vertex;\n"
> >> +               "}\n";
> >> +
> >> +       const char fs_source[] =
> >> +               "#version 100\n"
> >> +               "precision highp float;\n"
> >> +               "\n"
> >> +               "uniform sampler2D tex;\n"
> >> +               "varying vec2 tex_coord;\n"
> >> +               "\n"
> >> +               "void main()\n"
> >> +               "{\n"
> >> +               "    vec4 t = texture2D(tex, tex_coord);\n"
> >> +               "    gl_FragColor = vec4(t.rgb, 1.0);\n"
> >> +               "}\n";
> >> +
> >> +       /* Draw a square triangle strip. */
> >> +       const GLfloat vertices[2 * num_vertices] = {
> >> +               0, 0,
> >> +               1, 0,
> >> +               1, 1,
> >> +               0, 1,
> >> +       };
> >> +
> >> +       GLint vertex_loc;
> >> +       GLuint vertex_buf;
> >> +
> >> +       piglit_require_extension("GL_AMD_compressed_ATC_texture");
> >> +
> >> +       load_texture(compressed_filename, &compressed_tex);
> >> +       load_texture(decompressed_filename, &decompressed_tex);
> >> +
> >> +       glClearColor(1.0, 0.0, 0.0, 1.0);
> >> +       glViewport(0, 0, window_width, window_height);
> >> +
> >> +       prog = piglit_build_simple_program(vs_source, fs_source);
> >> +       glUseProgram(prog);
> >> +
> >> +       vertex_loc = glGetAttribLocation(prog, "vertex");
> >> +       glGenBuffers(1, &vertex_buf);
> >> +       glBindBuffer(GL_ARRAY_BUFFER, vertex_buf);
> >> +       glEnableVertexAttribArray(vertex_loc);
> >> +       glVertexAttribPointer(vertex_loc, 2, GL_FLOAT, GL_FALSE, 0, NULL);
> >> +       glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
> >> +                    GL_STATIC_DRAW);
> >> +
> >> +       glUniform1i(glGetUniformLocation(prog, "tex"), 0);
> >> +       glActiveTexture(GL_TEXTURE0);
> >> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
> >> +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
> >> +
> >> +       glUniform2f(glGetUniformLocation(prog, "window_pixel_size"),
> >> +                   window_width, window_height);
> >> +}
> >> +
> >> +static void
> >> +minify(int *x)
> >> +{
> >> +       assert(*x > 0);
> >> +
> >> +       if (*x > 1)
> >> +               *x >>= 1;
> >> +}
> >> +
> >> +enum piglit_result
> >> +piglit_display(void)
> >> +{
> >> +       GLint pixel_offset_loc = glGetUniformLocation(prog, "pixel_offset");
> >> +       GLint level_pixel_size_loc = glGetUniformLocation(prog, "level_pixel_size");
> >> +
> >> +       int level = 0;
> >> +       int level_width = level0_width;
> >> +       int level_height = level0_height;
> >> +       int y_offset = 0;
> >> +
> >> +       bool pass = true;
> >> +
> >> +       glClear(GL_COLOR_BUFFER_BIT);
> >> +
> >> +       for (level = 0; level < num_levels; ++level) {
> >> +               glUniform2f(level_pixel_size_loc,
> >> +                           (float) level_width,
> >> +                           (float) level_height);
> >> +
> >> +               /* Draw miplevel of compressed texture. */
> >> +               glBindTexture(GL_TEXTURE_2D, compressed_tex);
> >> +               glUniform2f(pixel_offset_loc, 0, y_offset);
> >> +               glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
> >> +
> >> +               /* Draw miplevel of decompressed texture. */
> >> +               glBindTexture(GL_TEXTURE_2D, decompressed_tex);
> >> +               glUniform2f(pixel_offset_loc, level0_width, y_offset);
> >> +               glDrawArrays(GL_TRIANGLE_FAN, 0, num_vertices);
> >> +
> >> +               y_offset += level_height;
> >> +               minify(&level_width);
> >> +               minify(&level_height);
> >> +       }
> >> +
> >> +       pass = piglit_probe_rect_halves_equal_rgba(0, 0, window_width, window_height);
> >> +       piglit_present_results();
> >> +
> >> +       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> >> +}
> >> diff --git a/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-compressed-atc-64x32.ktx
> >> new file mode 100644
> >> index 0000000000000000000000000000000000000000..6d7acc71e060032c5eedd75927e3b43cbd567ad9
> >> GIT binary patch
> >> literal 1464
> >> zcmZ8hZ%k8H6u(cU)jpSY3nL(Hq!SjHZ0G_DCUd-k=qfWQhPna4DHRNKQs)+<G6AvM
> >> zG&7EE>b@A1Ni_&bjl*S|NKtSErb*qX@x$yZ@*agMTDSLl3--OU`)b&So#egWz4zR6
> >> zekbS8?Jg<%AZ_*Pt1oDlX{ZGY7a<~)@+0!?F@zSUAjFV$8u{i$(W~Y+#DZ;PVP8y=
> >> z*hT<k_4(o``K)mS00qkk`UzeP!8<l9*?1~dw#0VqpeQCQ&wGDB%gm`8eUM7{s?&xe
> >> zD!LMivhR+y?AD<oy&ph|MxmM50SE}iG48j3EERqsECPunuJ}JHb|l<Y_F6w~&e75v
> >> zD%^gmG+_C{G|C6W^VS<xkLA$hNn~somI0<a`2%Js&}Fn8PBTv;R1Y=guOqQom#SnB
> >> zi9?p6^ZfJpXG5Gf$E@ffl{r#>4TA@voz<r?NC*{WAHd+Im>v1LNqc46od@|hd!dU;
> >> zI+Q-q4Xr4_Xg(UDbl0Mcb%!WR!g%X}pfua>NDA(?0P2ihE2=6Hsb2us?d``=f#YP7
> >> zN06ic#nBV#$K6RPl}&ftC+oJgeXdvC1}Qw=k?$NT$Z@0^^;6dwl<=!9b3_~%2%K=%
> >> zJdLO}mo#zj?i5m9(l&Nv2d{=vNeX2ee8f%7{ye_UDSDb!R#Rzqq`!}InfLZ#Wbp=e
> >> zH=oAdfkUlI9cLve_Pidk*p8(mw`iJ9Em~T7EKCwzqzm=jU@U?$eSN2zqSVIhoxfjk
> >> zA@87t7j>2>)NC4^iG>$vUnw6E9=a1cRcn?75he2LO@54!3l>+iI8jG+XV&k>3}WD`
> >> zJ%3>#ItQ1VSupX>`zR)gSmC!?4;lv3&3)=xw6Im5VYm1KURU0(D}u{fR-Jrvh<+I2
> >> zALKj5D9PCMx=zWnT!n0#E{Hj@h+K6~BRWLaxjw#!y#b!T*LWY#A|yr|{TR3y9JCVz
> >> z&yTr<Rlzg=>>K@Qb31+}v2RZ6`^kAKnojm(4;h4s+^nGjQj&9-M>#|ROk|I6WvCJ+
> >> za*uE=DC=2A<{$?$_x(gojp%mJs)<$3G1?ALye7-n8}PV$8vGy#F<Gf=nJoA3$|C+f
> >> zTGjEat-<j+r|C80+MoxL7HABgI<;i@G=@JuA!+umG^`DxbtlD(#qF4(XsFM7G)8#n
> >> zBgGn$B{;FMc1G+Db)g4uYj~O*ILkGBOa}MVc72c`_S5Bl+~SpBV+KpKkTaafg2%B1
> >> z{g(WOZTpAoVTtj@&z5gPl*ag-lkkN#hTdbB&en%6z0P99aB^-Ti%DKVc`)KL?z8&l
> >> zXU|@%_-rn4=__!K`egYnb6q4X0B=j*5Gka!o+TAB$T1<H)Ubfu4F64X?cQSIOB*q~
> >> zjF4?r$`c2}Fddmo#EJyF=ZD-yGved1J1a`3M1W`Cs2kqL-Z4&!&jNXSY)gmF9bQ;@
> >> z%9i$JPhxUYsG4z#>jJXdS@nqjh}zius%bw)GqaMpp7hu$fJn6;pO!<GX+2BW9n@g9
> >> z#iyAIxmV<Ac+?GZMP@ZG_Xa_|wTbj(i(t=UL6$vqNk-F?Gn<tf7}(_$Q?}CB{sgs&
> >> zGRY^pU{-u}qjVDsIh6^zoB10ehNjuh`aPuiVo_lzy=RE(umfN7)?ISlSCY|(t+GSC
> >> v(n#KkhC)t94$qhRp*aCDqs0K@V_k)d$yu=c-sJGv;j_y6y{(sT-y-ragh?$X
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> diff --git a/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx b/tests/spec/amd_compressed_atc_texture/waffles-decompressed-rgba-64x32.ktx
> >> new file mode 100644
> >> index 0000000000000000000000000000000000000000..8532ca92b5e3d13582eb89597bbfef2f2da5ae27
> >> GIT binary patch
> >> literal 11008
> >> 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
> >> ZBtGBpHb!vxwQ2<~S4)!d5T)DW^j`oN)ARrU
> >>
> >> literal 0
> >> HcmV?d00001
> >>
> >> --
> >> 2.17.1
> >>