1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2022-2022 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */
20
21 /*!
22 * \file esextcFragmentShadingRateErrors.hpp
23 * \brief FragmentShadingRateEXT errors
24 */ /*-------------------------------------------------------------------*/
25
26 #include "esextcFragmentShadingRateErrors.hpp"
27 #include "gluContextInfo.hpp"
28 #include "gluDefs.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "tcuTestLog.hpp"
32 #include <cstddef>
33
34 namespace glcts
35 {
36
37 /// Constructor
38 ///
39 /// @param context Test context
40 /// @param name Test case's name
41 /// @param description Test case's description
FragmentShadingRateErrors(Context & context,const ExtParameters & extParams,const char * name,const char * description)42 FragmentShadingRateErrors::FragmentShadingRateErrors(Context& context, const ExtParameters& extParams, const char* name,
43 const char* description)
44 : TestCaseBase(context, extParams, name, description)
45 {
46 }
47
48 /// Initialize the test.
init(void)49 void FragmentShadingRateErrors::init(void)
50 {
51 TestCaseBase::init();
52
53 // Skip if required extensions are not supported.
54 if (!m_is_fragment_shading_rate_supported)
55 {
56 throw tcu::NotSupportedError(FRAGMENT_SHADING_RATE_NOT_SUPPORTED, "", __FILE__, __LINE__);
57 }
58 }
59
60 /// Deinitializes all GLES objects created for the test.
deinit(void)61 void FragmentShadingRateErrors::deinit(void)
62 {
63 // Deinitialize base class
64 TestCaseBase::deinit();
65 }
66
67 /// Test if the error code returned by glGetError is the same as expected.
68 /// If the error is different from expected description is logged.
69 ///
70 /// @param expected_error GLenum error which is expected
71 /// @param description Log message in the case of failure.
72 ///
73 /// @return true if error is equal to expected, false otherwise.
verifyError(const glw::GLenum expected_error,const char * description) const74 glw::GLboolean FragmentShadingRateErrors::verifyError(const glw::GLenum expected_error, const char* description) const
75 {
76 /* Retrieve GLES entry points. */
77 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
78
79 glw::GLboolean test_passed = true;
80 glw::GLenum error_code = gl.getError();
81
82 if (error_code != expected_error)
83 {
84 test_passed = false;
85
86 m_testCtx.getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage;
87 }
88
89 return test_passed;
90 }
91
92 /// Executes the test.
93 /// Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
94 /// Note the function throws exception should an error occur!
95 ///
96 /// @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
iterate(void)97 tcu::TestNode::IterateResult FragmentShadingRateErrors::iterate(void)
98 {
99 bool testPassed = true;
100
101 /* Retrieve GLES entry points. */
102 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
103
104 // Shading Rate Size
105 // ---------------------------- -----
106 // SHADING_RATE_1X1_PIXELS_EXT 1x1
107 // SHADING_RATE_1X2_PIXELS_EXT 1x2
108 // SHADING_RATE_1X4_PIXELS_EXT 1x4
109 // SHADING_RATE_2X1_PIXELS_EXT 2x1
110 // SHADING_RATE_2X2_PIXELS_EXT 2x2
111 // SHADING_RATE_2X4_PIXELS_EXT 2x4
112 // SHADING_RATE_4X1_PIXELS_EXT 4x1
113 // SHADING_RATE_4X2_PIXELS_EXT 4x2
114 // SHADING_RATE_4X4_PIXELS_EXT 4x4
115 // INVALID_ENUM is generated by ShadingRateEXT if <rate> is not a valid shading rate from table
116 gl.shadingRateEXT(GL_SAMPLE_SHADING);
117 testPassed = testPassed && verifyError(GL_INVALID_ENUM, "glShadingRateEXT <rate> is not valid");
118
119 if (m_is_fragment_shading_rate_attachment_supported)
120 {
121 // void FramebufferShadingRateEXT(enum target, enum attachment, uint texture, GLint baseLayer, GLsizei numLayers, GLsizei texelWidth, GLsizei texelHeight);
122 constexpr deUint32 kBaseLayer = 0;
123 constexpr deUint32 kNumLayer = 1;
124 constexpr deUint32 kTextureWidth = 256;
125 constexpr deUint32 kTextureHeight = 256;
126 constexpr deUint32 kTexelWidth = 16;
127 constexpr deUint32 kTexelHeight = 16;
128
129 glw::GLuint fbo_id;
130 /* Generate framebuffer objects */
131 gl.genFramebuffers(1, &fbo_id);
132 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting up framebuffer objects");
133
134 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
135 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding frame buffer object!");
136
137 glw::GLuint to_id;
138 glw::GLuint mutable_to_id;
139 /* Generate texture objects */
140 gl.genTextures(1, &to_id);
141 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture objects");
142
143 gl.genTextures(1, &mutable_to_id);
144 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture objects");
145
146 gl.bindTexture(GL_TEXTURE_2D, to_id);
147 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
148 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R8UI, kTextureWidth, kTextureHeight);
149 GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object!");
150
151 gl.bindTexture(GL_TEXTURE_2D, mutable_to_id);
152 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
153 gl.texImage2D(GL_TEXTURE_2D, 0, GL_R8, kTextureWidth, kTextureHeight, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
154 GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object!");
155
156 glw::GLint minTexelWidth = 0;
157 glw::GLint maxTexelWidth = 0;
158 glw::GLint minTexelHeight = 0;
159 glw::GLint maxTexelHeight = 0;
160 glw::GLint maxAttachAspectRatio = 0;
161 glw::GLint maxAttachLayerCount = 0;
162 gl.getIntegerv(GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT, &minTexelWidth);
163 GLU_EXPECT_NO_ERROR(gl.getError(),
164 "Error getIntegerv GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT!");
165 gl.getIntegerv(GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT, &maxTexelWidth);
166 GLU_EXPECT_NO_ERROR(gl.getError(),
167 "Error getIntegerv GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT!");
168 gl.getIntegerv(GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT, &minTexelHeight);
169 GLU_EXPECT_NO_ERROR(gl.getError(),
170 "Error getIntegerv GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT!");
171 gl.getIntegerv(GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT, &maxTexelHeight);
172 GLU_EXPECT_NO_ERROR(gl.getError(),
173 "Error getIntegerv GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT!");
174 gl.getIntegerv(GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT, &maxAttachAspectRatio);
175 GLU_EXPECT_NO_ERROR(gl.getError(),
176 "Error getIntegerv GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT!");
177 gl.getIntegerv(GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT, &maxAttachLayerCount);
178 GLU_EXPECT_NO_ERROR(gl.getError(), "Error getIntegerv GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT!");
179
180 // An INVALID_ENUM error is generated if <target> is not DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or FRAMEBUFFER.
181 gl.framebufferShadingRateEXT(GL_RENDERBUFFER, GL_SHADING_RATE_ATTACHMENT_EXT, to_id, kBaseLayer, kNumLayer,
182 kTexelWidth, kTexelHeight);
183 testPassed = testPassed && verifyError(GL_INVALID_ENUM, "framebufferShadingRateEXT <target> is not valid");
184
185 // An INVALID_ENUM error is generated if <attachment> is not SHADING_RATE_ATTACHMENT_EXT.
186 gl.framebufferShadingRateEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, kBaseLayer, kNumLayer, kTexelWidth,
187 kTexelHeight);
188 testPassed = testPassed && verifyError(GL_INVALID_ENUM, "framebufferShadingRateEXT <attachment> is not valid");
189
190 // An INVALID_VALUE error is generated if <texture> is not zero and is not the name of an immutable texture object.
191 gl.framebufferShadingRateEXT(GL_FRAMEBUFFER, GL_SHADING_RATE_ATTACHMENT_EXT, mutable_to_id, kBaseLayer,
192 kNumLayer, kTexelWidth, kTexelHeight);
193 testPassed = testPassed && verifyError(GL_INVALID_VALUE, "framebufferShadingRateEXT <texture> is not valid");
194
195 // An INVALID_VALUE error is generated if <baseLayer> is greater than or equal to the value of MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT.
196 gl.framebufferShadingRateEXT(GL_FRAMEBUFFER, GL_SHADING_RATE_ATTACHMENT_EXT, to_id,
197 GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT, kNumLayer, kTexelWidth,
198 kTexelHeight);
199 testPassed = testPassed && verifyError(GL_INVALID_VALUE, "framebufferShadingRateEXT <baseLayer> is not valid");
200
201 // An INVALID_VALUE error is generated if <numLayers> is greater than the value of MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT.
202 gl.framebufferShadingRateEXT(GL_FRAMEBUFFER, GL_SHADING_RATE_ATTACHMENT_EXT, to_id, 0,
203 GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT + 1, kTexelWidth, kTexelHeight);
204 testPassed = testPassed && verifyError(GL_INVALID_VALUE, "framebufferShadingRateEXT <numLayers> is not valid");
205
206 // An INVALID_VALUE error is generated if <texelWidth> / <texelHeight> is larger than MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT.
207 gl.framebufferShadingRateEXT(GL_FRAMEBUFFER, GL_SHADING_RATE_ATTACHMENT_EXT, to_id, 0,
208 GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT + 1, minTexelWidth,
209 (minTexelWidth * GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT)
210 << 1);
211 testPassed = testPassed &&
212 verifyError(GL_INVALID_VALUE, "framebufferShadingRateEXT <texelWidth, texelHeight> is not valid");
213
214 // An INVALID_VALUE error is generated if <texelHeight> / <texelWidth> is larger than MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT.
215 gl.framebufferShadingRateEXT(
216 GL_FRAMEBUFFER, GL_SHADING_RATE_ATTACHMENT_EXT, to_id, 0,
217 GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT + 1,
218 (minTexelHeight * GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT) << 1, minTexelHeight);
219 testPassed = testPassed &&
220 verifyError(GL_INVALID_VALUE, "framebufferShadingRateEXT <texelWidth, texelHeight> is not valid");
221
222 gl.deleteFramebuffers(1, &fbo_id);
223 gl.deleteFramebuffers(1, &to_id);
224 gl.deleteFramebuffers(1, &mutable_to_id);
225 }
226
227 // void ShadingRateCombinerOpsEXT(enum combinerOp0, enum combinerOp1)
228 //
229 // An INVALID_ENUM error is generated if <combinerOp0> is not
230 // An INVALID_ENUM error is generated if <combinerOp1> is not
231 // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT,
232 // FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT,
233 // FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT,
234 // FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT, or
235 // FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT
236 gl.shadingRateCombinerOpsEXT(GL_SHADING_RATE_EXT, GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT);
237 testPassed = testPassed && verifyError(GL_INVALID_ENUM, "shadingRateCombinerOpsEXT <combinerOp0> is not valid");
238 gl.shadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT,
239 GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT);
240 testPassed = testPassed && verifyError(GL_INVALID_ENUM, "shadingRateCombinerOpsEXT <combinerOp1> is not valid");
241
242 glw::GLboolean supportNonTrivialCombiner = false;
243 gl.getBooleanv(GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT, &supportNonTrivialCombiner);
244 GLU_EXPECT_NO_ERROR(gl.getError(), "Error getBooleanv non trivial combiner");
245
246 // An INVALID_OPERATION error is generated if the value of FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT
247 // is FALSE and <combinerOp0> is not
248 // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT or FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT
249 // is FALSE and <combinerOp1> is not
250 // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT or FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT
251 if (!supportNonTrivialCombiner)
252 {
253 gl.shadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT,
254 GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT);
255 testPassed = testPassed && verifyError(GL_INVALID_OPERATION, "<combinerOp0> combiner is non trivial combiner");
256
257 gl.shadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT,
258 GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT);
259 testPassed = testPassed && verifyError(GL_INVALID_OPERATION, "<combinerOp1> combiner is non trivial combiner");
260 }
261 // [[If GL_EXT_fragment_shading_rate_primitive is not supported]]
262 // An INVALID_OPERATION error is generated if <combinerOp0> is not
263 // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT
264 if (!m_is_fragment_shading_rate_primitive_supported)
265 {
266 gl.shadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT,
267 GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT);
268 testPassed = testPassed && verifyError(GL_INVALID_ENUM, "shadingRateCombinerOpsEXT <combinerOp0> is not valid");
269 }
270
271 // [[If GL_EXT_fragment_shading_rate_attachment is not supported]]
272 // An INVALID_OPERATION error is generated if <combinerOp1> is not
273 // FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT
274 if (!m_is_fragment_shading_rate_attachment_supported)
275 {
276 gl.shadingRateCombinerOpsEXT(GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT,
277 GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT);
278 testPassed = testPassed && verifyError(GL_INVALID_ENUM, "shadingRateCombinerOpsEXT <combinerOp0> is not valid");
279 }
280
281 /* All done */
282 if (testPassed)
283 {
284 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
285 }
286 else
287 {
288 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
289 }
290
291 return STOP;
292 }
293
294 } // namespace glcts
295