1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*
22 * \file vktPipelineMultisampleInterpolationTests.cpp
23 * \brief Multisample Interpolation Tests
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktPipelineMultisampleInterpolationTests.hpp"
27 #include "vktPipelineMultisampleBaseResolve.hpp"
28 #include "vktPipelineMultisampleTestsUtil.hpp"
29 #include "vktPipelineMakeUtil.hpp"
30 #include "vktAmberTestCase.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "tcuTestLog.hpp"
33 #include <vector>
34
35 namespace vkt
36 {
37 namespace pipeline
38 {
39 namespace multisample
40 {
41
42 using namespace vk;
43
44 struct VertexDataNdc
45 {
VertexDataNdcvkt::pipeline::multisample::VertexDataNdc46 VertexDataNdc(const tcu::Vec4 &posNdc) : positionNdc(posNdc)
47 {
48 }
49
50 tcu::Vec4 positionNdc;
51 };
52
53 struct VertexDataNdcScreen
54 {
VertexDataNdcScreenvkt::pipeline::multisample::VertexDataNdcScreen55 VertexDataNdcScreen(const tcu::Vec4 &posNdc, const tcu::Vec2 &posScreen)
56 : positionNdc(posNdc)
57 , positionScreen(posScreen)
58 {
59 }
60
61 tcu::Vec4 positionNdc;
62 tcu::Vec2 positionScreen;
63 };
64
65 struct VertexDataNdcBarycentric
66 {
VertexDataNdcBarycentricvkt::pipeline::multisample::VertexDataNdcBarycentric67 VertexDataNdcBarycentric(const tcu::Vec4 &posNdc, const tcu::Vec3 &barCoord)
68 : positionNdc(posNdc)
69 , barycentricCoord(barCoord)
70 {
71 }
72
73 tcu::Vec4 positionNdc;
74 tcu::Vec3 barycentricCoord;
75 };
76
checkForError(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS,const uint32_t errorCompNdx)77 bool checkForError(const vk::VkImageCreateInfo &imageRSInfo, const tcu::ConstPixelBufferAccess &dataRS,
78 const uint32_t errorCompNdx)
79 {
80 for (uint32_t z = 0u; z < imageRSInfo.extent.depth; ++z)
81 for (uint32_t y = 0u; y < imageRSInfo.extent.height; ++y)
82 for (uint32_t x = 0u; x < imageRSInfo.extent.width; ++x)
83 {
84 const uint32_t errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
85
86 if (errorComponent > 0)
87 return true;
88 }
89
90 return false;
91 }
92
93 template <typename CaseClassName>
94 class MSCase : public MultisampleCaseBase
95 {
96 public:
MSCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)97 MSCase(tcu::TestContext &testCtx, const std::string &name, const ImageMSParams &imageMSParams)
98 : MultisampleCaseBase(testCtx, name, imageMSParams)
99 {
100 }
101
102 void init(void);
103 void initPrograms(vk::SourceCollections &programCollection) const;
104 void checkSupport(Context &context) const;
105 TestInstance *createInstance(Context &context) const;
106 static MultisampleCaseBase *createCase(tcu::TestContext &testCtx, const std::string &name,
107 const ImageMSParams &imageMSParams);
108 };
109
110 template <typename CaseClassName>
checkSupport(Context & context) const111 void MSCase<CaseClassName>::checkSupport(Context &context) const
112 {
113 checkGraphicsPipelineLibrarySupport(context);
114
115 #ifndef CTS_USES_VULKANSC
116 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
117 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
118 {
119 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not "
120 "supported by this implementation");
121 }
122 #endif // CTS_USES_VULKANSC
123
124 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
125 }
126
127 template <typename CaseClassName>
createCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)128 MultisampleCaseBase *MSCase<CaseClassName>::createCase(tcu::TestContext &testCtx, const std::string &name,
129 const ImageMSParams &imageMSParams)
130 {
131 return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
132 }
133
134 template <typename InstanceClassName>
135 class MSInstance : public MSInstanceBaseResolve
136 {
137 public:
MSInstance(Context & context,const ImageMSParams & imageMSParams)138 MSInstance(Context &context, const ImageMSParams &imageMSParams) : MSInstanceBaseResolve(context, imageMSParams)
139 {
140 }
141
142 VertexDataDesc getVertexDataDescripton(void) const;
143 void uploadVertexData(const Allocation &vertexBufferAllocation, const VertexDataDesc &vertexDataDescripton) const;
144 tcu::TestStatus verifyImageData(const vk::VkImageCreateInfo &imageRSInfo,
145 const tcu::ConstPixelBufferAccess &dataRS) const;
146 };
147
148 class MSInstanceDistinctValues;
149
150 template <>
getVertexDataDescripton(void) const151 MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceDistinctValues>::getVertexDataDescripton(void) const
152 {
153 VertexDataDesc vertexDataDesc;
154
155 vertexDataDesc.verticesCount = 3u;
156 vertexDataDesc.dataStride = sizeof(VertexDataNdc);
157 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
158 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
159
160 const VkVertexInputAttributeDescription vertexAttribPositionNdc = {
161 0u, // uint32_t location;
162 0u, // uint32_t binding;
163 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
164 offsetof(VertexDataNdc, positionNdc), // uint32_t offset;
165 };
166
167 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
168
169 return vertexDataDesc;
170 }
171
172 template <>
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const173 void MSInstance<MSInstanceDistinctValues>::uploadVertexData(const Allocation &vertexBufferAllocation,
174 const VertexDataDesc &vertexDataDescripton) const
175 {
176 std::vector<VertexDataNdc> vertices;
177
178 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
179 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)));
180 vertices.push_back(VertexDataNdc(tcu::Vec4(4.0f, -1.0f, 0.0f, 1.0f)));
181
182 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices),
183 static_cast<std::size_t>(vertexDataDescripton.dataSize));
184 }
185
186 template <>
verifyImageData(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS) const187 tcu::TestStatus MSInstance<MSInstanceDistinctValues>::verifyImageData(const vk::VkImageCreateInfo &imageRSInfo,
188 const tcu::ConstPixelBufferAccess &dataRS) const
189 {
190 const uint32_t distinctValuesExpected = static_cast<uint32_t>(m_imageMSParams.numSamples) + 1u;
191
192 std::vector<tcu::IVec4> distinctValues;
193
194 for (uint32_t z = 0u; z < imageRSInfo.extent.depth; ++z)
195 for (uint32_t y = 0u; y < imageRSInfo.extent.height; ++y)
196 for (uint32_t x = 0u; x < imageRSInfo.extent.width; ++x)
197 {
198 const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z);
199
200 if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
201 distinctValues.push_back(pixel);
202 }
203
204 if (distinctValues.size() >= distinctValuesExpected)
205 return tcu::TestStatus::pass("Passed");
206 else
207 return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image");
208 }
209
210 class MSCaseSampleQualifierDistinctValues;
211
212 template <>
init(void)213 void MSCase<MSCaseSampleQualifierDistinctValues>::init(void)
214 {
215 m_testCtx.getLog()
216 << tcu::TestLog::Message
217 << "Verifying that a sample qualified varying is given different values for different samples.\n"
218 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
219 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
220 << tcu::TestLog::EndMessage;
221
222 MultisampleCaseBase::init();
223 }
224
225 template <>
initPrograms(vk::SourceCollections & programCollection) const226 void MSCase<MSCaseSampleQualifierDistinctValues>::initPrograms(vk::SourceCollections &programCollection) const
227 {
228 // Create vertex shader
229 std::ostringstream vs;
230
231 vs << "#version 440\n"
232 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
233 << "\n"
234 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
235 << "\n"
236 << "out gl_PerVertex {\n"
237 << " vec4 gl_Position;\n"
238 << "};\n"
239 << "void main (void)\n"
240 << "{\n"
241 << " gl_Position = vs_in_position_ndc;\n"
242 << " vs_out_position_ndc = vs_in_position_ndc;\n"
243 << "}\n";
244
245 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
246
247 // Create fragment shader
248 std::ostringstream fs;
249
250 fs << "#version 440\n"
251 << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
252 << "\n"
253 << "layout(location = 0) out vec4 fs_out_color;\n"
254 << "\n"
255 << "void main (void)\n"
256 << "{\n"
257 << " if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
258 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
259 << " else\n"
260 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
261 << "}\n";
262
263 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
264 }
265
266 template <>
checkSupport(Context & context) const267 void MSCase<MSCaseSampleQualifierDistinctValues>::checkSupport(Context &context) const
268 {
269 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
270 m_imageMSParams.pipelineConstructionType);
271
272 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
273 }
274
275 template <>
createInstance(Context & context) const276 TestInstance *MSCase<MSCaseSampleQualifierDistinctValues>::createInstance(Context &context) const
277 {
278 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
279 }
280
281 class MSCaseInterpolateAtSampleDistinctValues;
282
283 template <>
init(void)284 void MSCase<MSCaseInterpolateAtSampleDistinctValues>::init(void)
285 {
286 m_testCtx.getLog()
287 << tcu::TestLog::Message
288 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
289 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
290 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
291 << tcu::TestLog::EndMessage;
292
293 MultisampleCaseBase::init();
294 }
295
296 template <>
initPrograms(vk::SourceCollections & programCollection) const297 void MSCase<MSCaseInterpolateAtSampleDistinctValues>::initPrograms(vk::SourceCollections &programCollection) const
298 {
299 // Create vertex shader
300 std::ostringstream vs;
301
302 vs << "#version 440\n"
303 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
304 << "\n"
305 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
306 << "\n"
307 << "out gl_PerVertex {\n"
308 << " vec4 gl_Position;\n"
309 << "};\n"
310 << "void main (void)\n"
311 << "{\n"
312 << " gl_Position = vs_in_position_ndc;\n"
313 << " vs_out_position_ndc = vs_in_position_ndc;\n"
314 << "}\n";
315
316 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
317
318 // Create fragment shader
319 std::ostringstream fs;
320
321 fs << "#version 440\n"
322 << "layout(location = 0) in vec4 fs_in_position_ndc;\n"
323 << "\n"
324 << "layout(location = 0) out vec4 fs_out_color;\n"
325 << "\n"
326 << "void main (void)\n"
327 << "{\n"
328 << " const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
329 << " if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
330 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
331 << " else\n"
332 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
333 << "}\n";
334
335 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
336 }
337
338 template <>
createInstance(Context & context) const339 TestInstance *MSCase<MSCaseInterpolateAtSampleDistinctValues>::createInstance(Context &context) const
340 {
341 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
342 }
343
344 class MSInstanceInterpolateScreenPosition;
345
346 template <>
getVertexDataDescripton(void) const347 MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateScreenPosition>::getVertexDataDescripton(
348 void) const
349 {
350 VertexDataDesc vertexDataDesc;
351
352 vertexDataDesc.verticesCount = 4u;
353 vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen);
354 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
355 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
356
357 const VkVertexInputAttributeDescription vertexAttribPositionNdc = {
358 0u, // uint32_t location;
359 0u, // uint32_t binding;
360 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
361 offsetof(VertexDataNdcScreen, positionNdc), // uint32_t offset;
362 };
363
364 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
365
366 const VkVertexInputAttributeDescription vertexAttribPositionScreen = {
367 1u, // uint32_t location;
368 0u, // uint32_t binding;
369 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
370 offsetof(VertexDataNdcScreen, positionScreen), // uint32_t offset;
371 };
372
373 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
374
375 return vertexDataDesc;
376 }
377
378 template <>
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const379 void MSInstance<MSInstanceInterpolateScreenPosition>::uploadVertexData(const Allocation &vertexBufferAllocation,
380 const VertexDataDesc &vertexDataDescripton) const
381 {
382 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
383 const float screenSizeX = static_cast<float>(layerSize.x());
384 const float screenSizeY = static_cast<float>(layerSize.y());
385
386 std::vector<VertexDataNdcScreen> vertices;
387
388 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
389 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
390 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY)));
391 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
392
393 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices),
394 static_cast<std::size_t>(vertexDataDescripton.dataSize));
395 }
396
397 template <>
verifyImageData(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS) const398 tcu::TestStatus MSInstance<MSInstanceInterpolateScreenPosition>::verifyImageData(
399 const vk::VkImageCreateInfo &imageRSInfo, const tcu::ConstPixelBufferAccess &dataRS) const
400 {
401 if (checkForError(imageRSInfo, dataRS, 0))
402 return tcu::TestStatus::fail("Failed");
403
404 return tcu::TestStatus::pass("Passed");
405 }
406
407 class MSCaseInterpolateAtSampleSingleSample;
408
409 template <>
init(void)410 void MSCase<MSCaseInterpolateAtSampleSingleSample>::init(void)
411 {
412 m_testCtx.getLog() << tcu::TestLog::Message
413 << "Verifying that using interpolateAtSample with multisample buffers not available returns "
414 "sample evaluated at the center of the pixel.\n"
415 << " Interpolate varying containing screen space location.\n"
416 << " => fract(screen space location) should be (about) (0.5, 0.5)\n"
417 << tcu::TestLog::EndMessage;
418
419 MultisampleCaseBase::init();
420 }
421
422 template <>
initPrograms(vk::SourceCollections & programCollection) const423 void MSCase<MSCaseInterpolateAtSampleSingleSample>::initPrograms(vk::SourceCollections &programCollection) const
424 {
425 // Create vertex shader
426 std::ostringstream vs;
427
428 vs << "#version 440\n"
429 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
430 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
431 << "\n"
432 << "layout(location = 0) out vec2 vs_out_position_screen;\n"
433 << "\n"
434 << "out gl_PerVertex {\n"
435 << " vec4 gl_Position;\n"
436 << "};\n"
437 << "void main (void)\n"
438 << "{\n"
439 << " gl_Position = vs_in_position_ndc;\n"
440 << " vs_out_position_screen = vs_in_position_screen;\n"
441 << "}\n";
442
443 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
444
445 // Create fragment shader
446 std::ostringstream fs;
447
448 fs << "#version 440\n"
449 << "layout(location = 0) in vec2 fs_in_position_screen;\n"
450 << "\n"
451 << "layout(location = 0) out vec4 fs_out_color;\n"
452 << "\n"
453 << "void main (void)\n"
454 << "{\n"
455 << " const float threshold = 0.15625;\n"
456 << " const vec2 position_screen_at_sample = interpolateAtSample(fs_in_position_screen, 0);\n"
457 << " const vec2 position_inside_pixel = fract(position_screen_at_sample);\n"
458 << "\n"
459 << " if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= "
460 "threshold)\n"
461 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
462 << " else\n"
463 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
464 << "}\n";
465
466 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
467 }
468
469 template <>
createInstance(Context & context) const470 TestInstance *MSCase<MSCaseInterpolateAtSampleSingleSample>::createInstance(Context &context) const
471 {
472 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
473 }
474
475 class MSCaseInterpolateAtSampleIgnoresCentroid;
476
477 template <>
init(void)478 void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::init(void)
479 {
480 m_testCtx.getLog()
481 << tcu::TestLog::Message << "Verifying that interpolateAtSample ignores centroid qualifier.\n"
482 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
483 << " => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
484 << tcu::TestLog::EndMessage;
485
486 MultisampleCaseBase::init();
487 }
488
489 template <>
initPrograms(vk::SourceCollections & programCollection) const490 void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::initPrograms(vk::SourceCollections &programCollection) const
491 {
492 // Create vertex shader
493 std::ostringstream vs;
494
495 vs << "#version 440\n"
496 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
497 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
498 << "\n"
499 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
500 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
501 << "\n"
502 << "out gl_PerVertex {\n"
503 << " vec4 gl_Position;\n"
504 << "};\n"
505 << "void main (void)\n"
506 << "{\n"
507 << " gl_Position = vs_in_position_ndc;\n"
508 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
509 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
510 << "}\n";
511
512 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
513
514 // Create fragment shader
515 std::ostringstream fs;
516
517 fs << "#version 440\n"
518 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
519 << "layout(location = 1) in vec2 fs_in_pos_screen_fragment;\n"
520 << "\n"
521 << "layout(location = 0) out vec4 fs_out_color;\n"
522 << "\n"
523 << "void main (void)\n"
524 << "{\n"
525 << " const float threshold = 0.0005;\n"
526 << "\n"
527 << " const vec2 position_a = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
528 << " const vec2 position_b = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
529 << " const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
530 << "\n"
531 << " if (valuesEqual)\n"
532 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
533 << " else\n"
534 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
535 << "}\n";
536
537 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
538 }
539
540 template <>
createInstance(Context & context) const541 TestInstance *MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::createInstance(Context &context) const
542 {
543 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
544 }
545
546 class MSCaseInterpolateAtSampleConsistency;
547
548 template <>
init(void)549 void MSCase<MSCaseInterpolateAtSampleConsistency>::init(void)
550 {
551 const std::string indexStr = de::toString(m_imageMSParams.componentData.index);
552 std::string componentMsg;
553
554 switch (m_imageMSParams.componentData.source)
555 {
556 case multisample::ComponentSource::CONSTANT:
557 componentMsg = "Using single constant component " + indexStr;
558 break;
559 case multisample::ComponentSource::PUSH_CONSTANT:
560 componentMsg = "Using single component via push constant " + indexStr;
561 break;
562 default:
563 break;
564 }
565
566 m_testCtx.getLog()
567 << tcu::TestLog::Message
568 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
569 << (componentMsg.empty() ? std::string() : componentMsg + "\n")
570 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
571 << " => interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
572 << tcu::TestLog::EndMessage;
573
574 MultisampleCaseBase::init();
575 }
576
577 template <>
initPrograms(vk::SourceCollections & programCollection) const578 void MSCase<MSCaseInterpolateAtSampleConsistency>::initPrograms(vk::SourceCollections &programCollection) const
579 {
580 // Create vertex shader
581 std::ostringstream vs;
582
583 vs << "#version 440\n"
584 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
585 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
586 << "\n"
587 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
588 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
589 << "\n"
590 << "out gl_PerVertex {\n"
591 << " vec4 gl_Position;\n"
592 << "};\n"
593 << "void main (void)\n"
594 << "{\n"
595 << " gl_Position = vs_in_position_ndc;\n"
596 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
597 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
598 << "}\n";
599
600 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
601
602 // Create fragment shader
603 std::ostringstream fs;
604
605 fs << "#version 440\n"
606 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
607 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
608 << "\n"
609 << "layout(location = 0) out vec4 fs_out_color;\n"
610 << "\n";
611
612 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
613 {
614 fs << "layout(push_constant) uniform PushConstants {\n"
615 << " uint component;\n"
616 << "};\n"
617 << "\n";
618 }
619
620 fs << "void main (void)\n"
621 << "{\n"
622 << " const float threshold = 0.15625;\n"
623 << "\n";
624
625 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
626 {
627 fs << " const vec2 pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, "
628 "gl_SampleID);\n"
629 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_sample - "
630 "fs_in_pos_screen_sample), vec2(threshold)));\n";
631 }
632 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
633 {
634 const auto &index = m_imageMSParams.componentData.index;
635 fs << " const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[" << index
636 << "], gl_SampleID);\n"
637 << " const bool valuesEqual = (abs(pos_interpolated_at_sample - fs_in_pos_screen_sample["
638 << index << "]) < threshold);\n";
639 }
640 else // multisample::ComponentSource::PUSH_CONSTANT
641 {
642 fs << " const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[component], "
643 "gl_SampleID);\n"
644 << " const bool valuesEqual = (abs(pos_interpolated_at_sample - "
645 "fs_in_pos_screen_sample[component]) < threshold);\n";
646 }
647
648 fs << "\n"
649 << " if (valuesEqual)\n"
650 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
651 << " else\n"
652 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
653 << "}\n";
654
655 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
656 }
657
658 template <>
createInstance(Context & context) const659 TestInstance *MSCase<MSCaseInterpolateAtSampleConsistency>::createInstance(Context &context) const
660 {
661 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
662 }
663
664 class MSCaseInterpolateAtCentroidConsistency;
665
666 template <>
init(void)667 void MSCase<MSCaseInterpolateAtCentroidConsistency>::init(void)
668 {
669 const std::string indexStr = de::toString(m_imageMSParams.componentData.index);
670 std::string componentMsg;
671
672 switch (m_imageMSParams.componentData.source)
673 {
674 case multisample::ComponentSource::CONSTANT:
675 componentMsg = "Using single constant component " + indexStr;
676 break;
677 case multisample::ComponentSource::PUSH_CONSTANT:
678 componentMsg = "Using single component via push constant " + indexStr;
679 break;
680 default:
681 break;
682 }
683
684 m_testCtx.getLog()
685 << tcu::TestLog::Message
686 << "Verifying that interpolateAtCentroid does not return different values than a corresponding "
687 "centroid qualified varying.\n"
688 << (componentMsg.empty() ? std::string() : componentMsg + "\n")
689 << " Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
690 << " => interpolateAtCentroid(screenSample) = screenCentroid\n"
691 << tcu::TestLog::EndMessage;
692
693 MultisampleCaseBase::init();
694 }
695
696 template <>
initPrograms(vk::SourceCollections & programCollection) const697 void MSCase<MSCaseInterpolateAtCentroidConsistency>::initPrograms(vk::SourceCollections &programCollection) const
698 {
699 // Create vertex shader
700 std::ostringstream vs;
701
702 vs << "#version 440\n"
703 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
704 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
705 << "\n"
706 << "layout(location = 0) out vec2 vs_out_pos_screen_sample[2];\n"
707 << "layout(location = 2) out vec2 vs_out_pos_screen_centroid[2];\n"
708 << "\n"
709 << "out gl_PerVertex {\n"
710 << " vec4 gl_Position;\n"
711 << "};\n"
712 << "void main (void)\n"
713 << "{\n"
714 << " gl_Position = vs_in_position_ndc;\n"
715 // Index 0 is never read, so we'll populate them with bad values
716 << " vs_out_pos_screen_sample[0] = vec2(-70.3, 42.1);\n"
717 << " vs_out_pos_screen_centroid[0] = vec2(7.7, -3.2);\n"
718 // Actual coordinates in index 1:
719 << " vs_out_pos_screen_sample[1] = vs_in_position_screen;\n"
720 << " vs_out_pos_screen_centroid[1] = vs_in_position_screen;\n"
721 << "}\n";
722
723 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
724
725 // Create fragment shader
726 std::ostringstream fs;
727
728 fs << "#version 440\n"
729 << "layout(location = 0) sample in vec2 fs_in_pos_screen_sample[2];\n"
730 << "layout(location = 2) centroid in vec2 fs_in_pos_screen_centroid[2];\n"
731 << "\n"
732 << "layout(location = 0) out vec4 fs_out_color;\n"
733 << "\n";
734
735 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
736 {
737 fs << "layout(push_constant) uniform PushConstants {\n"
738 << " uint component;\n"
739 << "};\n"
740 << "\n";
741 }
742
743 fs << "void main (void)\n"
744 << "{\n"
745 << " const float threshold = 0.0005;\n"
746 << "\n";
747
748 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
749 {
750 fs << " const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1]);\n"
751 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_centroid - "
752 "fs_in_pos_screen_centroid[1]), vec2(threshold)));\n";
753 }
754 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
755 {
756 const auto &index = m_imageMSParams.componentData.index;
757 fs << " const float pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1]["
758 << index << "]);\n"
759 << " const bool valuesEqual = (abs(pos_interpolated_at_centroid - "
760 "fs_in_pos_screen_centroid[1]["
761 << index << "]) < threshold);\n";
762 }
763 else // multisample::ComponentSource::PUSH_CONSTANT
764 {
765 fs << " const float pos_interpolated_at_centroid = "
766 "interpolateAtCentroid(fs_in_pos_screen_sample[1][component]);\n"
767 << " const bool valuesEqual = (abs(pos_interpolated_at_centroid - "
768 "fs_in_pos_screen_centroid[1][component]) < threshold);\n";
769 }
770
771 fs << "\n"
772 << " if (valuesEqual)\n"
773 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
774 << " else\n"
775 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
776 << "}\n";
777
778 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
779 }
780
781 template <>
createInstance(Context & context) const782 TestInstance *MSCase<MSCaseInterpolateAtCentroidConsistency>::createInstance(Context &context) const
783 {
784 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
785 }
786
787 class MSCaseInterpolateAtOffsetPixelCenter;
788
789 template <>
init(void)790 void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::init(void)
791 {
792 m_testCtx.getLog()
793 << tcu::TestLog::Message
794 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
795 << " Interpolate varying containing screen space location.\n"
796 << " => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
797 << tcu::TestLog::EndMessage;
798
799 MultisampleCaseBase::init();
800 }
801
802 template <>
initPrograms(vk::SourceCollections & programCollection) const803 void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::initPrograms(vk::SourceCollections &programCollection) const
804 {
805 // Create vertex shader
806 std::ostringstream vs;
807
808 vs << "#version 440\n"
809 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
810 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
811 << "\n"
812 << "layout(location = 0) out vec2 vs_out_pos_screen;\n"
813 << "layout(location = 1) out vec2 vs_out_offset;\n"
814 << "\n"
815 << "out gl_PerVertex {\n"
816 << " vec4 gl_Position;\n"
817 << "};\n"
818 << "void main (void)\n"
819 << "{\n"
820 << " gl_Position = vs_in_position_ndc;\n"
821 << " vs_out_pos_screen = vs_in_position_screen;\n"
822 << " vs_out_offset = vs_in_position_ndc.xy * 0.5;\n"
823 << "}\n";
824
825 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
826
827 // Create fragment shader
828 std::ostringstream fs;
829
830 fs << "#version 440\n"
831 << "layout(location = 0) in vec2 fs_in_pos_screen;\n"
832 << "layout(location = 1) in vec2 fs_in_offset;\n"
833 << "\n"
834 << "layout(location = 0) out vec4 fs_out_color;\n"
835 << "\n"
836 << "void main (void)\n"
837 << "{\n"
838 << " const vec2 frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
839 << " const vec2 center_diff = abs(frag_center - fs_in_pos_screen);\n"
840 << " const float threshold = 0.125;\n"
841 << " bool valuesEqual = false;\n"
842 << "\n"
843 << " if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
844 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
845 << " const vec2 reference_value = frag_center + fs_in_offset;\n"
846 << "\n"
847 << " valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
848 << " }\n"
849 << "\n"
850 << " if (valuesEqual)\n"
851 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
852 << " else\n"
853 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
854 << "}\n";
855
856 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
857 }
858
859 template <>
createInstance(Context & context) const860 TestInstance *MSCase<MSCaseInterpolateAtOffsetPixelCenter>::createInstance(Context &context) const
861 {
862 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
863 }
864
865 class MSCaseInterpolateAtOffsetSamplePosition;
866
867 template <>
init(void)868 void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::init(void)
869 {
870 const std::string indexStr = de::toString(m_imageMSParams.componentData.index);
871 std::string componentMsg;
872
873 switch (m_imageMSParams.componentData.source)
874 {
875 case multisample::ComponentSource::CONSTANT:
876 componentMsg = "Using single constant component " + indexStr;
877 break;
878 case multisample::ComponentSource::PUSH_CONSTANT:
879 componentMsg = "Using single component via push constant " + indexStr;
880 break;
881 default:
882 break;
883 }
884
885 m_testCtx.getLog()
886 << tcu::TestLog::Message
887 << "Verifying that interpolateAtOffset of screen position with the offset of current sample "
888 "position returns value "
889 << "similar to screen position interpolated at sample.\n"
890 << (componentMsg.empty() ? std::string() : componentMsg + "\n")
891 << " Interpolate varying containing screen space location with and without sample qualifier.\n"
892 << " => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
893 << tcu::TestLog::EndMessage;
894
895 MultisampleCaseBase::init();
896 }
897
898 template <>
initPrograms(vk::SourceCollections & programCollection) const899 void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::initPrograms(vk::SourceCollections &programCollection) const
900 {
901 // Create vertex shader
902 std::ostringstream vs;
903
904 vs << "#version 440\n"
905 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
906 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
907 << "\n"
908 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
909 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
910 << "\n"
911 << "out gl_PerVertex {\n"
912 << " vec4 gl_Position;\n"
913 << "};\n"
914 << "void main (void)\n"
915 << "{\n"
916 << " gl_Position = vs_in_position_ndc;\n"
917 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
918 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
919 << "}\n";
920
921 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
922
923 // Create fragment shader
924 std::ostringstream fs;
925
926 fs << "#version 440\n"
927 << "layout(location = 0) in vec2 fs_in_pos_screen_fragment;\n"
928 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
929 << "\n"
930 << "layout(location = 0) out vec4 fs_out_color;\n"
931 << "\n";
932
933 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
934 {
935 fs << "layout(push_constant) uniform PushConstants {\n"
936 << " uint component;\n"
937 << "};\n"
938 << "\n";
939 }
940
941 fs << "void main (void)\n"
942 << "{\n"
943 << " const float threshold = 0.15625;\n"
944 << "\n"
945 << " const vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n";
946
947 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
948 {
949 fs << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
950 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - "
951 "fs_in_pos_screen_sample), vec2(threshold)));\n";
952 }
953 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
954 {
955 const auto &index = m_imageMSParams.componentData.index;
956 fs << " const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[" << index
957 << "], offset);\n"
958 << " const bool valuesEqual = (abs(pos_interpolated_at_offset - fs_in_pos_screen_sample["
959 << index << "]) < threshold);\n";
960 }
961 else // multisample::ComponentSource::PUSH_CONSTANT
962 {
963 fs << " const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[component], "
964 "offset);\n"
965 << " const bool valuesEqual = (abs(pos_interpolated_at_offset - "
966 "fs_in_pos_screen_sample[component]) < threshold);\n";
967 }
968
969 fs << "\n"
970 << " if (valuesEqual)\n"
971 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
972 << " else\n"
973 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
974 << "}\n";
975
976 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
977 }
978
979 template <>
createInstance(Context & context) const980 TestInstance *MSCase<MSCaseInterpolateAtOffsetSamplePosition>::createInstance(Context &context) const
981 {
982 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
983 }
984
985 class MSInstanceInterpolateBarycentricCoordinates;
986
987 template <>
getVertexDataDescripton(void) const988 MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateBarycentricCoordinates>::getVertexDataDescripton(
989 void) const
990 {
991 VertexDataDesc vertexDataDesc;
992
993 vertexDataDesc.verticesCount = 3u;
994 vertexDataDesc.dataStride = sizeof(VertexDataNdcBarycentric);
995 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
996 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
997
998 const VkVertexInputAttributeDescription vertexAttribPositionNdc = {
999 0u, // uint32_t location;
1000 0u, // uint32_t binding;
1001 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1002 offsetof(VertexDataNdcBarycentric, positionNdc), // uint32_t offset;
1003 };
1004
1005 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1006
1007 const VkVertexInputAttributeDescription vertexAttrBarCoord = {
1008 1u, // uint32_t location;
1009 0u, // uint32_t binding;
1010 VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
1011 offsetof(VertexDataNdcBarycentric, barycentricCoord), // uint32_t offset;
1012 };
1013
1014 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
1015
1016 return vertexDataDesc;
1017 }
1018
1019 template <>
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const1020 void MSInstance<MSInstanceInterpolateBarycentricCoordinates>::uploadVertexData(
1021 const Allocation &vertexBufferAllocation, const VertexDataDesc &vertexDataDescripton) const
1022 {
1023 // Create buffer storing vertex data
1024 std::vector<VertexDataNdcBarycentric> vertices;
1025
1026 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
1027 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
1028 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
1029
1030 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices),
1031 static_cast<std::size_t>(vertexDataDescripton.dataSize));
1032 }
1033
1034 template <>
verifyImageData(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS) const1035 tcu::TestStatus MSInstance<MSInstanceInterpolateBarycentricCoordinates>::verifyImageData(
1036 const vk::VkImageCreateInfo &imageRSInfo, const tcu::ConstPixelBufferAccess &dataRS) const
1037 {
1038 if (checkForError(imageRSInfo, dataRS, 0))
1039 return tcu::TestStatus::fail("Failed");
1040
1041 return tcu::TestStatus::pass("Passed");
1042 }
1043
1044 class MSCaseCentroidQualifierInsidePrimitive;
1045
1046 template <>
init(void)1047 void MSCase<MSCaseCentroidQualifierInsidePrimitive>::init(void)
1048 {
1049 m_testCtx.getLog() << tcu::TestLog::Message
1050 << "Verifying that varying qualified with centroid is interpolated at location inside both the "
1051 "pixel and the primitive being processed.\n"
1052 << " Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
1053 << " => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
1054 << tcu::TestLog::EndMessage;
1055
1056 MultisampleCaseBase::init();
1057 }
1058
1059 template <>
initPrograms(vk::SourceCollections & programCollection) const1060 void MSCase<MSCaseCentroidQualifierInsidePrimitive>::initPrograms(vk::SourceCollections &programCollection) const
1061 {
1062 // Create vertex shader
1063 std::ostringstream vs;
1064
1065 vs << "#version 440\n"
1066 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1067 << "layout(location = 1) in vec3 vs_in_barCoord;\n"
1068 << "\n"
1069 << "layout(location = 0) out vec3 vs_out_barCoord;\n"
1070 << "\n"
1071 << "out gl_PerVertex {\n"
1072 << " vec4 gl_Position;\n"
1073 << "};\n"
1074 << "void main (void)\n"
1075 << "{\n"
1076 << " gl_Position = vs_in_position_ndc;\n"
1077 << " vs_out_barCoord = vs_in_barCoord;\n"
1078 << "}\n";
1079
1080 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1081
1082 // Create fragment shader
1083 std::ostringstream fs;
1084
1085 fs << "#version 440\n"
1086 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
1087 << "\n"
1088 << "layout(location = 0) out vec4 fs_out_color;\n"
1089 << "\n"
1090 << "void main (void)\n"
1091 << "{\n"
1092 << " if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) "
1093 ")\n"
1094 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1095 << " else\n"
1096 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1097 << "}\n";
1098
1099 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1100 }
1101
1102 template <>
checkSupport(Context & context) const1103 void MSCase<MSCaseCentroidQualifierInsidePrimitive>::checkSupport(Context &context) const
1104 {
1105 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1106 m_imageMSParams.pipelineConstructionType);
1107 }
1108
1109 template <>
createInstance(Context & context) const1110 TestInstance *MSCase<MSCaseCentroidQualifierInsidePrimitive>::createInstance(Context &context) const
1111 {
1112 return new MSInstance<MSInstanceInterpolateBarycentricCoordinates>(context, m_imageMSParams);
1113 }
1114
1115 } // namespace multisample
1116
createMultisampleInterpolationTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)1117 tcu::TestCaseGroup *createMultisampleInterpolationTests(tcu::TestContext &testCtx,
1118 vk::PipelineConstructionType pipelineConstructionType)
1119 {
1120 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation"));
1121
1122 const tcu::UVec3 imageSizes[] = {
1123 tcu::UVec3(128u, 128u, 1u),
1124 tcu::UVec3(137u, 191u, 1u),
1125 };
1126
1127 const uint32_t sizesElemCount = static_cast<uint32_t>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1128
1129 const vk::VkSampleCountFlagBits imageSamples[] = {
1130 vk::VK_SAMPLE_COUNT_2_BIT, vk::VK_SAMPLE_COUNT_4_BIT, vk::VK_SAMPLE_COUNT_8_BIT,
1131 vk::VK_SAMPLE_COUNT_16_BIT, vk::VK_SAMPLE_COUNT_32_BIT, vk::VK_SAMPLE_COUNT_64_BIT,
1132 };
1133
1134 const uint32_t samplesElemCount = static_cast<uint32_t>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
1135
1136 de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample"));
1137
1138 for (uint32_t imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
1139 {
1140 const tcu::UVec3 imageSize = imageSizes[imageSizeNdx];
1141 std::ostringstream imageSizeStream;
1142
1143 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1144
1145 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str()));
1146
1147 multisample::ImageMSParams imageParams{
1148 pipelineConstructionType, vk::VK_SAMPLE_COUNT_1_BIT, imageSize, multisample::ComponentData{}, 1.0f,
1149 };
1150 sizeGroup->addChild(multisample::MSCase<multisample::MSCaseInterpolateAtSampleSingleSample>::createCase(
1151 testCtx, "samples_" + de::toString(1), imageParams));
1152
1153 caseGroup->addChild(sizeGroup.release());
1154 }
1155
1156 testGroup->addChild(caseGroup.release());
1157
1158 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleDistinctValues>>(
1159 testCtx, "sample_interpolate_at_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount,
1160 imageSamples, samplesElemCount));
1161 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleIgnoresCentroid>>(
1162 testCtx, "sample_interpolate_at_ignores_centroid", pipelineConstructionType, imageSizes, sizesElemCount,
1163 imageSamples, samplesElemCount));
1164
1165 // Test consistency in sample interpolation function
1166 de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolation_consistency"));
1167 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency>>(
1168 testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1169 samplesElemCount));
1170 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency>>(
1171 testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount,
1172 multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1173 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency>>(
1174 testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount,
1175 multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1176 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency>>(
1177 testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1178 samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1179 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency>>(
1180 testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1181 samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1182 testGroup->addChild(sampleGroup.release());
1183
1184 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleQualifierDistinctValues>>(
1185 testCtx, "sample_qualifier_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1186 samplesElemCount));
1187
1188 // Test consistency in centroid interpolation function
1189 de::MovePtr<tcu::TestCaseGroup> centroidGroup(
1190 new tcu::TestCaseGroup(testCtx, "centroid_interpolation_consistency"));
1191 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency>>(
1192 testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1193 samplesElemCount));
1194 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency>>(
1195 testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount,
1196 multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1197 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency>>(
1198 testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount,
1199 multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1200 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency>>(
1201 testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1202 samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1203 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency>>(
1204 testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1205 samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1206 testGroup->addChild(centroidGroup.release());
1207
1208 #ifndef CTS_USES_VULKANSC
1209 // there is no support for pipelineConstructionType in amber
1210 if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1211 {
1212 de::MovePtr<tcu::TestCaseGroup> reInterpolationGroup(
1213 new tcu::TestCaseGroup(testCtx, "reinterpolation_consistency"));
1214 std::vector<std::string> requirements;
1215 requirements.push_back("Features.sampleRateShading");
1216 reInterpolationGroup->addChild(cts_amber::createAmberTestCase(
1217 testCtx, "interpolate_at_centroid", "", "pipeline", "reinterpolate_at_centroid.amber", requirements));
1218 reInterpolationGroup->addChild(cts_amber::createAmberTestCase(testCtx, "interpolate_at_sample", "", "pipeline",
1219 "reinterpolate_at_sample.amber", requirements));
1220 testGroup->addChild(reInterpolationGroup.release());
1221
1222 de::MovePtr<tcu::TestCaseGroup> nonuniformInterpolantIndexingGroup(
1223 new tcu::TestCaseGroup(testCtx, "nonuniform_interpolant_indexing"));
1224 std::vector<std::string> requirementsNonuniformIntepolantIndexing;
1225 requirementsNonuniformIntepolantIndexing.push_back("Features.sampleRateShading");
1226 nonuniformInterpolantIndexingGroup->addChild(
1227 cts_amber::createAmberTestCase(testCtx, "centroid", "pipeline/nonuniform_interpolant_indexing",
1228 "centroid.amber", requirementsNonuniformIntepolantIndexing));
1229 nonuniformInterpolantIndexingGroup->addChild(
1230 cts_amber::createAmberTestCase(testCtx, "sample", "pipeline/nonuniform_interpolant_indexing",
1231 "sample.amber", requirementsNonuniformIntepolantIndexing));
1232 nonuniformInterpolantIndexingGroup->addChild(
1233 cts_amber::createAmberTestCase(testCtx, "offset", "pipeline/nonuniform_interpolant_indexing",
1234 "offset.amber", requirementsNonuniformIntepolantIndexing));
1235 testGroup->addChild(nonuniformInterpolantIndexingGroup.release());
1236 }
1237
1238 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseCentroidQualifierInsidePrimitive>>(
1239 testCtx, "centroid_qualifier_inside_primitive", pipelineConstructionType, imageSizes, sizesElemCount,
1240 imageSamples, samplesElemCount));
1241 #endif // CTS_USES_VULKANSC
1242 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetPixelCenter>>(
1243 testCtx, "offset_interpolate_at_pixel_center", pipelineConstructionType, imageSizes, sizesElemCount,
1244 imageSamples, samplesElemCount));
1245
1246 de::MovePtr<tcu::TestCaseGroup> offsetGroup(
1247 new tcu::TestCaseGroup(testCtx, "offset_interpolation_at_sample_position"));
1248 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition>>(
1249 testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1250 samplesElemCount));
1251 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition>>(
1252 testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount,
1253 multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1254 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition>>(
1255 testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount,
1256 multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1257 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition>>(
1258 testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1259 samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1260 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition>>(
1261 testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples,
1262 samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1263 testGroup->addChild(offsetGroup.release());
1264
1265 return testGroup.release();
1266 }
1267
1268 } // namespace pipeline
1269 } // namespace vkt
1270