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 tcu::Vec4 positionNdc;
49 };
50
51 struct VertexDataNdcScreen
52 {
VertexDataNdcScreenvkt::pipeline::multisample::VertexDataNdcScreen53 VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
54
55 tcu::Vec4 positionNdc;
56 tcu::Vec2 positionScreen;
57 };
58
59 struct VertexDataNdcBarycentric
60 {
VertexDataNdcBarycentricvkt::pipeline::multisample::VertexDataNdcBarycentric61 VertexDataNdcBarycentric (const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
62
63 tcu::Vec4 positionNdc;
64 tcu::Vec3 barycentricCoord;
65 };
66
checkForError(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS,const deUint32 errorCompNdx)67 bool checkForError (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
68 {
69 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z)
70 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
71 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x)
72 {
73 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
74
75 if (errorComponent > 0)
76 return true;
77 }
78
79 return false;
80 }
81
82 template <typename CaseClassName>
83 class MSCase : public MultisampleCaseBase
84 {
85 public:
MSCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)86 MSCase (tcu::TestContext& testCtx,
87 const std::string& name,
88 const ImageMSParams& imageMSParams)
89 : MultisampleCaseBase(testCtx, name, imageMSParams) {}
90
91 void init (void);
92 void initPrograms (vk::SourceCollections& programCollection) const;
93 void checkSupport (Context& context) const;
94 TestInstance* createInstance (Context& context) const;
95 static MultisampleCaseBase* createCase (tcu::TestContext& testCtx,
96 const std::string& name,
97 const ImageMSParams& imageMSParams);
98 };
99
100 template <typename CaseClassName>
checkSupport(Context & context) const101 void MSCase<CaseClassName>::checkSupport (Context& context) const
102 {
103 checkGraphicsPipelineLibrarySupport(context);
104
105 #ifndef CTS_USES_VULKANSC
106 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
107 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
108 {
109 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
110 }
111 #endif // CTS_USES_VULKANSC
112
113 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
114 }
115
116 template <typename CaseClassName>
createCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)117 MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
118 {
119 return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
120 }
121
122 template <typename InstanceClassName>
123 class MSInstance : public MSInstanceBaseResolve
124 {
125 public:
MSInstance(Context & context,const ImageMSParams & imageMSParams)126 MSInstance (Context& context,
127 const ImageMSParams& imageMSParams)
128 : MSInstanceBaseResolve(context, imageMSParams) {}
129
130 VertexDataDesc getVertexDataDescripton (void) const;
131 void uploadVertexData (const Allocation& vertexBufferAllocation,
132 const VertexDataDesc& vertexDataDescripton) const;
133 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageRSInfo,
134 const tcu::ConstPixelBufferAccess& dataRS) const;
135 };
136
137 class MSInstanceDistinctValues;
138
getVertexDataDescripton(void) const139 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceDistinctValues>::getVertexDataDescripton (void) const
140 {
141 VertexDataDesc vertexDataDesc;
142
143 vertexDataDesc.verticesCount = 3u;
144 vertexDataDesc.dataStride = sizeof(VertexDataNdc);
145 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
146 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
147
148 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
149 {
150 0u, // deUint32 location;
151 0u, // deUint32 binding;
152 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
153 DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset;
154 };
155
156 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
157
158 return vertexDataDesc;
159 }
160
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const161 template<> void MSInstance<MSInstanceDistinctValues>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
162 {
163 std::vector<VertexDataNdc> vertices;
164
165 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
166 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)));
167 vertices.push_back(VertexDataNdc(tcu::Vec4( 4.0f, -1.0f, 0.0f, 1.0f)));
168
169 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
170 }
171
verifyImageData(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS) const172 template<> tcu::TestStatus MSInstance<MSInstanceDistinctValues>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
173 {
174 const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u;
175
176 std::vector<tcu::IVec4> distinctValues;
177
178 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z)
179 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
180 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x)
181 {
182 const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z);
183
184 if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
185 distinctValues.push_back(pixel);
186 }
187
188 if (distinctValues.size() >= distinctValuesExpected)
189 return tcu::TestStatus::pass("Passed");
190 else
191 return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image");
192 }
193
194 class MSCaseSampleQualifierDistinctValues;
195
init(void)196 template<> void MSCase<MSCaseSampleQualifierDistinctValues>::init (void)
197 {
198 m_testCtx.getLog()
199 << tcu::TestLog::Message
200 << "Verifying that a sample qualified varying is given different values for different samples.\n"
201 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
202 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
203 << tcu::TestLog::EndMessage;
204
205 MultisampleCaseBase::init();
206 }
207
initPrograms(vk::SourceCollections & programCollection) const208 template<> void MSCase<MSCaseSampleQualifierDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
209 {
210 // Create vertex shader
211 std::ostringstream vs;
212
213 vs << "#version 440\n"
214 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
215 << "\n"
216 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
217 << "\n"
218 << "out gl_PerVertex {\n"
219 << " vec4 gl_Position;\n"
220 << "};\n"
221 << "void main (void)\n"
222 << "{\n"
223 << " gl_Position = vs_in_position_ndc;\n"
224 << " vs_out_position_ndc = vs_in_position_ndc;\n"
225 << "}\n";
226
227 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
228
229 // Create fragment shader
230 std::ostringstream fs;
231
232 fs << "#version 440\n"
233 << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
234 << "\n"
235 << "layout(location = 0) out vec4 fs_out_color;\n"
236 << "\n"
237 << "void main (void)\n"
238 << "{\n"
239 << " if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
240 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
241 << " else\n"
242 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
243 << "}\n";
244
245 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
246 }
247
checkSupport(Context & context) const248 template<> void MSCase<MSCaseSampleQualifierDistinctValues>::checkSupport (Context& context) const
249 {
250 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_imageMSParams.pipelineConstructionType);
251
252 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
253 }
254
createInstance(Context & context) const255 template<> TestInstance* MSCase<MSCaseSampleQualifierDistinctValues>::createInstance (Context& context) const
256 {
257 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
258 }
259
260 class MSCaseInterpolateAtSampleDistinctValues;
261
init(void)262 template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::init (void)
263 {
264 m_testCtx.getLog()
265 << tcu::TestLog::Message
266 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
267 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
268 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
269 << tcu::TestLog::EndMessage;
270
271 MultisampleCaseBase::init();
272 }
273
initPrograms(vk::SourceCollections & programCollection) const274 template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
275 {
276 // Create vertex shader
277 std::ostringstream vs;
278
279 vs << "#version 440\n"
280 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
281 << "\n"
282 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
283 << "\n"
284 << "out gl_PerVertex {\n"
285 << " vec4 gl_Position;\n"
286 << "};\n"
287 << "void main (void)\n"
288 << "{\n"
289 << " gl_Position = vs_in_position_ndc;\n"
290 << " vs_out_position_ndc = vs_in_position_ndc;\n"
291 << "}\n";
292
293 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
294
295 // Create fragment shader
296 std::ostringstream fs;
297
298 fs << "#version 440\n"
299 << "layout(location = 0) in vec4 fs_in_position_ndc;\n"
300 << "\n"
301 << "layout(location = 0) out vec4 fs_out_color;\n"
302 << "\n"
303 << "void main (void)\n"
304 << "{\n"
305 << " const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
306 << " if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
307 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
308 << " else\n"
309 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
310 << "}\n";
311
312 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
313 }
314
createInstance(Context & context) const315 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleDistinctValues>::createInstance (Context& context) const
316 {
317 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
318 }
319
320 class MSInstanceInterpolateScreenPosition;
321
getVertexDataDescripton(void) const322 template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateScreenPosition>::getVertexDataDescripton (void) const
323 {
324 VertexDataDesc vertexDataDesc;
325
326 vertexDataDesc.verticesCount = 4u;
327 vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen);
328 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
329 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
330
331 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
332 {
333 0u, // deUint32 location;
334 0u, // deUint32 binding;
335 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
336 DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset;
337 };
338
339 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
340
341 const VkVertexInputAttributeDescription vertexAttribPositionScreen =
342 {
343 1u, // deUint32 location;
344 0u, // deUint32 binding;
345 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
346 DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset;
347 };
348
349 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
350
351 return vertexDataDesc;
352 }
353
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const354 template<> void MSInstance<MSInstanceInterpolateScreenPosition>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
355 {
356 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
357 const float screenSizeX = static_cast<float>(layerSize.x());
358 const float screenSizeY = static_cast<float>(layerSize.y());
359
360 std::vector<VertexDataNdcScreen> vertices;
361
362 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
363 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
364 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY)));
365 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
366
367 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
368 }
369
verifyImageData(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS) const370 template<> tcu::TestStatus MSInstance<MSInstanceInterpolateScreenPosition>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
371 {
372 if (checkForError(imageRSInfo, dataRS, 0))
373 return tcu::TestStatus::fail("Failed");
374
375 return tcu::TestStatus::pass("Passed");
376 }
377
378 class MSCaseInterpolateAtSampleSingleSample;
379
init(void)380 template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::init (void)
381 {
382 m_testCtx.getLog()
383 << tcu::TestLog::Message
384 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
385 << " Interpolate varying containing screen space location.\n"
386 << " => fract(screen space location) should be (about) (0.5, 0.5)\n"
387 << tcu::TestLog::EndMessage;
388
389 MultisampleCaseBase::init();
390 }
391
initPrograms(vk::SourceCollections & programCollection) const392 template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::initPrograms (vk::SourceCollections& programCollection) const
393 {
394 // Create vertex shader
395 std::ostringstream vs;
396
397 vs << "#version 440\n"
398 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
399 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
400 << "\n"
401 << "layout(location = 0) out vec2 vs_out_position_screen;\n"
402 << "\n"
403 << "out gl_PerVertex {\n"
404 << " vec4 gl_Position;\n"
405 << "};\n"
406 << "void main (void)\n"
407 << "{\n"
408 << " gl_Position = vs_in_position_ndc;\n"
409 << " vs_out_position_screen = vs_in_position_screen;\n"
410 << "}\n";
411
412 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
413
414 // Create fragment shader
415 std::ostringstream fs;
416
417 fs << "#version 440\n"
418 << "layout(location = 0) in vec2 fs_in_position_screen;\n"
419 << "\n"
420 << "layout(location = 0) out vec4 fs_out_color;\n"
421 << "\n"
422 << "void main (void)\n"
423 << "{\n"
424 << " const float threshold = 0.15625;\n"
425 << " const vec2 position_screen_at_sample = interpolateAtSample(fs_in_position_screen, 0);\n"
426 << " const vec2 position_inside_pixel = fract(position_screen_at_sample);\n"
427 << "\n"
428 << " if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
429 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
430 << " else\n"
431 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
432 << "}\n";
433
434 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
435 }
436
createInstance(Context & context) const437 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleSingleSample>::createInstance (Context& context) const
438 {
439 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
440 }
441
442 class MSCaseInterpolateAtSampleIgnoresCentroid;
443
init(void)444 template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::init (void)
445 {
446 m_testCtx.getLog()
447 << tcu::TestLog::Message
448 << "Verifying that interpolateAtSample ignores centroid qualifier.\n"
449 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
450 << " => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
451 << tcu::TestLog::EndMessage;
452
453 MultisampleCaseBase::init();
454 }
455
initPrograms(vk::SourceCollections & programCollection) const456 template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::initPrograms (vk::SourceCollections& programCollection) const
457 {
458 // Create vertex shader
459 std::ostringstream vs;
460
461 vs << "#version 440\n"
462 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
463 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
464 << "\n"
465 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
466 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
467 << "\n"
468 << "out gl_PerVertex {\n"
469 << " vec4 gl_Position;\n"
470 << "};\n"
471 << "void main (void)\n"
472 << "{\n"
473 << " gl_Position = vs_in_position_ndc;\n"
474 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
475 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
476 << "}\n";
477
478 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
479
480 // Create fragment shader
481 std::ostringstream fs;
482
483 fs << "#version 440\n"
484 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
485 << "layout(location = 1) in vec2 fs_in_pos_screen_fragment;\n"
486 << "\n"
487 << "layout(location = 0) out vec4 fs_out_color;\n"
488 << "\n"
489 << "void main (void)\n"
490 << "{\n"
491 << " const float threshold = 0.0005;\n"
492 << "\n"
493 << " const vec2 position_a = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
494 << " const vec2 position_b = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
495 << " const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
496 << "\n"
497 << " if (valuesEqual)\n"
498 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
499 << " else\n"
500 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
501 << "}\n";
502
503 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
504 }
505
createInstance(Context & context) const506 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::createInstance (Context& context) const
507 {
508 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
509 }
510
511 class MSCaseInterpolateAtSampleConsistency;
512
init(void)513 template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::init (void)
514 {
515 const std::string indexStr = de::toString(m_imageMSParams.componentData.index);
516 std::string componentMsg;
517
518 switch (m_imageMSParams.componentData.source)
519 {
520 case multisample::ComponentSource::CONSTANT: componentMsg = "Using single constant component " + indexStr; break;
521 case multisample::ComponentSource::PUSH_CONSTANT: componentMsg = "Using single component via push constant " + indexStr; break;
522 default: break;
523 }
524
525 m_testCtx.getLog()
526 << tcu::TestLog::Message
527 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
528 << (componentMsg.empty() ? std::string() : componentMsg + "\n")
529 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
530 << " => interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
531 << tcu::TestLog::EndMessage;
532
533 MultisampleCaseBase::init();
534 }
535
initPrograms(vk::SourceCollections & programCollection) const536 template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::initPrograms (vk::SourceCollections& programCollection) const
537 {
538 // Create vertex shader
539 std::ostringstream vs;
540
541 vs << "#version 440\n"
542 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
543 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
544 << "\n"
545 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
546 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
547 << "\n"
548 << "out gl_PerVertex {\n"
549 << " vec4 gl_Position;\n"
550 << "};\n"
551 << "void main (void)\n"
552 << "{\n"
553 << " gl_Position = vs_in_position_ndc;\n"
554 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
555 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
556 << "}\n";
557
558 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
559
560 // Create fragment shader
561 std::ostringstream fs;
562
563 fs << "#version 440\n"
564 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
565 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
566 << "\n"
567 << "layout(location = 0) out vec4 fs_out_color;\n"
568 << "\n";
569
570 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
571 {
572 fs << "layout(push_constant) uniform PushConstants {\n"
573 << " uint component;\n"
574 << "};\n"
575 << "\n";
576 }
577
578 fs << "void main (void)\n"
579 << "{\n"
580 << " const float threshold = 0.15625;\n"
581 << "\n";
582
583 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
584 {
585 fs << " const vec2 pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
586 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n";
587 }
588 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
589 {
590 const auto& index = m_imageMSParams.componentData.index;
591 fs << " const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[" << index << "], gl_SampleID);\n"
592 << " const bool valuesEqual = (abs(pos_interpolated_at_sample - fs_in_pos_screen_sample[" << index << "]) < threshold);\n";
593 }
594 else // multisample::ComponentSource::PUSH_CONSTANT
595 {
596 fs << " const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[component], gl_SampleID);\n"
597 << " const bool valuesEqual = (abs(pos_interpolated_at_sample - fs_in_pos_screen_sample[component]) < threshold);\n";
598 }
599
600 fs << "\n"
601 << " if (valuesEqual)\n"
602 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
603 << " else\n"
604 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
605 << "}\n";
606
607 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
608 }
609
createInstance(Context & context) const610 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleConsistency>::createInstance (Context& context) const
611 {
612 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
613 }
614
615 class MSCaseInterpolateAtCentroidConsistency;
616
init(void)617 template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::init (void)
618 {
619 const std::string indexStr = de::toString(m_imageMSParams.componentData.index);
620 std::string componentMsg;
621
622 switch (m_imageMSParams.componentData.source)
623 {
624 case multisample::ComponentSource::CONSTANT: componentMsg = "Using single constant component " + indexStr; break;
625 case multisample::ComponentSource::PUSH_CONSTANT: componentMsg = "Using single component via push constant " + indexStr; break;
626 default: break;
627 }
628
629 m_testCtx.getLog()
630 << tcu::TestLog::Message
631 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n"
632 << (componentMsg.empty() ? std::string() : componentMsg + "\n")
633 << " Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
634 << " => interpolateAtCentroid(screenSample) = screenCentroid\n"
635 << tcu::TestLog::EndMessage;
636
637 MultisampleCaseBase::init();
638 }
639
initPrograms(vk::SourceCollections & programCollection) const640 template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::initPrograms (vk::SourceCollections& programCollection) const
641 {
642 // Create vertex shader
643 std::ostringstream vs;
644
645 vs << "#version 440\n"
646 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
647 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
648 << "\n"
649 << "layout(location = 0) out vec2 vs_out_pos_screen_sample[2];\n"
650 << "layout(location = 2) out vec2 vs_out_pos_screen_centroid[2];\n"
651 << "\n"
652 << "out gl_PerVertex {\n"
653 << " vec4 gl_Position;\n"
654 << "};\n"
655 << "void main (void)\n"
656 << "{\n"
657 << " gl_Position = vs_in_position_ndc;\n"
658 // Index 0 is never read, so we'll populate them with bad values
659 << " vs_out_pos_screen_sample[0] = vec2(-70.3, 42.1);\n"
660 << " vs_out_pos_screen_centroid[0] = vec2(7.7, -3.2);\n"
661 // Actual coordinates in index 1:
662 << " vs_out_pos_screen_sample[1] = vs_in_position_screen;\n"
663 << " vs_out_pos_screen_centroid[1] = vs_in_position_screen;\n"
664 << "}\n";
665
666 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
667
668 // Create fragment shader
669 std::ostringstream fs;
670
671 fs << "#version 440\n"
672 << "layout(location = 0) sample in vec2 fs_in_pos_screen_sample[2];\n"
673 << "layout(location = 2) centroid in vec2 fs_in_pos_screen_centroid[2];\n"
674 << "\n"
675 << "layout(location = 0) out vec4 fs_out_color;\n"
676 << "\n";
677
678 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
679 {
680 fs << "layout(push_constant) uniform PushConstants {\n"
681 << " uint component;\n"
682 << "};\n"
683 << "\n";
684 }
685
686 fs << "void main (void)\n"
687 << "{\n"
688 << " const float threshold = 0.0005;\n"
689 << "\n";
690
691 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
692 {
693 fs << " const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1]);\n"
694 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1]), vec2(threshold)));\n";
695 }
696 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
697 {
698 const auto& index = m_imageMSParams.componentData.index;
699 fs << " const float pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1][" << index << "]);\n"
700 << " const bool valuesEqual = (abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1][" << index << "]) < threshold);\n";
701 }
702 else // multisample::ComponentSource::PUSH_CONSTANT
703 {
704 fs << " const float pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1][component]);\n"
705 << " const bool valuesEqual = (abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1][component]) < threshold);\n";
706 }
707
708 fs << "\n"
709 << " if (valuesEqual)\n"
710 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
711 << " else\n"
712 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
713 << "}\n";
714
715 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
716 }
717
createInstance(Context & context) const718 template<> TestInstance* MSCase<MSCaseInterpolateAtCentroidConsistency>::createInstance (Context& context) const
719 {
720 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
721 }
722
723 class MSCaseInterpolateAtOffsetPixelCenter;
724
init(void)725 template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::init (void)
726 {
727 m_testCtx.getLog()
728 << tcu::TestLog::Message
729 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
730 << " Interpolate varying containing screen space location.\n"
731 << " => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
732 << tcu::TestLog::EndMessage;
733
734 MultisampleCaseBase::init();
735 }
736
initPrograms(vk::SourceCollections & programCollection) const737 template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::initPrograms (vk::SourceCollections& programCollection) const
738 {
739 // Create vertex shader
740 std::ostringstream vs;
741
742 vs << "#version 440\n"
743 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
744 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
745 << "\n"
746 << "layout(location = 0) out vec2 vs_out_pos_screen;\n"
747 << "layout(location = 1) out vec2 vs_out_offset;\n"
748 << "\n"
749 << "out gl_PerVertex {\n"
750 << " vec4 gl_Position;\n"
751 << "};\n"
752 << "void main (void)\n"
753 << "{\n"
754 << " gl_Position = vs_in_position_ndc;\n"
755 << " vs_out_pos_screen = vs_in_position_screen;\n"
756 << " vs_out_offset = vs_in_position_ndc.xy * 0.5;\n"
757 << "}\n";
758
759 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
760
761 // Create fragment shader
762 std::ostringstream fs;
763
764 fs << "#version 440\n"
765 << "layout(location = 0) in vec2 fs_in_pos_screen;\n"
766 << "layout(location = 1) in vec2 fs_in_offset;\n"
767 << "\n"
768 << "layout(location = 0) out vec4 fs_out_color;\n"
769 << "\n"
770 << "void main (void)\n"
771 << "{\n"
772 << " const vec2 frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
773 << " const vec2 center_diff = abs(frag_center - fs_in_pos_screen);\n"
774 << " const float threshold = 0.125;\n"
775 << " bool valuesEqual = false;\n"
776 << "\n"
777 << " if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
778 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
779 << " const vec2 reference_value = frag_center + fs_in_offset;\n"
780 << "\n"
781 << " valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
782 << " }\n"
783 << "\n"
784 << " if (valuesEqual)\n"
785 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
786 << " else\n"
787 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
788 << "}\n";
789
790 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
791 }
792
createInstance(Context & context) const793 template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetPixelCenter>::createInstance (Context& context) const
794 {
795 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
796 }
797
798 class MSCaseInterpolateAtOffsetSamplePosition;
799
init(void)800 template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::init (void)
801 {
802 const std::string indexStr = de::toString(m_imageMSParams.componentData.index);
803 std::string componentMsg;
804
805 switch (m_imageMSParams.componentData.source)
806 {
807 case multisample::ComponentSource::CONSTANT: componentMsg = "Using single constant component " + indexStr; break;
808 case multisample::ComponentSource::PUSH_CONSTANT: componentMsg = "Using single component via push constant " + indexStr; break;
809 default: break;
810 }
811
812 m_testCtx.getLog()
813 << tcu::TestLog::Message
814 << "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value "
815 << "similar to screen position interpolated at sample.\n"
816 << (componentMsg.empty() ? std::string() : componentMsg + "\n")
817 << " Interpolate varying containing screen space location with and without sample qualifier.\n"
818 << " => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
819 << tcu::TestLog::EndMessage;
820
821 MultisampleCaseBase::init();
822 }
823
initPrograms(vk::SourceCollections & programCollection) const824 template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::initPrograms (vk::SourceCollections& programCollection) const
825 {
826 // Create vertex shader
827 std::ostringstream vs;
828
829 vs << "#version 440\n"
830 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
831 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
832 << "\n"
833 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
834 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
835 << "\n"
836 << "out gl_PerVertex {\n"
837 << " vec4 gl_Position;\n"
838 << "};\n"
839 << "void main (void)\n"
840 << "{\n"
841 << " gl_Position = vs_in_position_ndc;\n"
842 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
843 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
844 << "}\n";
845
846 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
847
848 // Create fragment shader
849 std::ostringstream fs;
850
851 fs << "#version 440\n"
852 << "layout(location = 0) in vec2 fs_in_pos_screen_fragment;\n"
853 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
854 << "\n"
855 << "layout(location = 0) out vec4 fs_out_color;\n"
856 << "\n";
857
858 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT)
859 {
860 fs << "layout(push_constant) uniform PushConstants {\n"
861 << " uint component;\n"
862 << "};\n"
863 << "\n";
864 }
865
866 fs << "void main (void)\n"
867 << "{\n"
868 << " const float threshold = 0.15625;\n"
869 << "\n"
870 << " const vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n";
871
872 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE)
873 {
874 fs << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
875 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n";
876 }
877 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT)
878 {
879 const auto& index = m_imageMSParams.componentData.index;
880 fs << " const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[" << index << "], offset);\n"
881 << " const bool valuesEqual = (abs(pos_interpolated_at_offset - fs_in_pos_screen_sample[" << index << "]) < threshold);\n";
882 }
883 else // multisample::ComponentSource::PUSH_CONSTANT
884 {
885 fs << " const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[component], offset);\n"
886 << " const bool valuesEqual = (abs(pos_interpolated_at_offset - fs_in_pos_screen_sample[component]) < threshold);\n";
887 }
888
889 fs << "\n"
890 << " if (valuesEqual)\n"
891 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
892 << " else\n"
893 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
894 << "}\n";
895
896 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
897 }
898
createInstance(Context & context) const899 template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetSamplePosition>::createInstance (Context& context) const
900 {
901 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
902 }
903
904 class MSInstanceInterpolateBarycentricCoordinates;
905
getVertexDataDescripton(void) const906 template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateBarycentricCoordinates>::getVertexDataDescripton (void) const
907 {
908 VertexDataDesc vertexDataDesc;
909
910 vertexDataDesc.verticesCount = 3u;
911 vertexDataDesc.dataStride = sizeof(VertexDataNdcBarycentric);
912 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
913 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
914
915 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
916 {
917 0u, // deUint32 location;
918 0u, // deUint32 binding;
919 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
920 DE_OFFSET_OF(VertexDataNdcBarycentric, positionNdc), // deUint32 offset;
921 };
922
923 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
924
925 const VkVertexInputAttributeDescription vertexAttrBarCoord =
926 {
927 1u, // deUint32 location;
928 0u, // deUint32 binding;
929 VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
930 DE_OFFSET_OF(VertexDataNdcBarycentric, barycentricCoord), // deUint32 offset;
931 };
932
933 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
934
935 return vertexDataDesc;
936 }
937
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const938 template<> void MSInstance<MSInstanceInterpolateBarycentricCoordinates>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
939 {
940 // Create buffer storing vertex data
941 std::vector<VertexDataNdcBarycentric> vertices;
942
943 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
944 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
945 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
946
947 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
948 }
949
verifyImageData(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS) const950 template<> tcu::TestStatus MSInstance<MSInstanceInterpolateBarycentricCoordinates>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
951 {
952 if (checkForError(imageRSInfo, dataRS, 0))
953 return tcu::TestStatus::fail("Failed");
954
955 return tcu::TestStatus::pass("Passed");
956 }
957
958 class MSCaseCentroidQualifierInsidePrimitive;
959
init(void)960 template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::init (void)
961 {
962 m_testCtx.getLog()
963 << tcu::TestLog::Message
964 << "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n"
965 << " Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
966 << " => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
967 << tcu::TestLog::EndMessage;
968
969 MultisampleCaseBase::init();
970 }
971
initPrograms(vk::SourceCollections & programCollection) const972 template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::initPrograms (vk::SourceCollections& programCollection) const
973 {
974 // Create vertex shader
975 std::ostringstream vs;
976
977 vs << "#version 440\n"
978 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
979 << "layout(location = 1) in vec3 vs_in_barCoord;\n"
980 << "\n"
981 << "layout(location = 0) out vec3 vs_out_barCoord;\n"
982 << "\n"
983 << "out gl_PerVertex {\n"
984 << " vec4 gl_Position;\n"
985 << "};\n"
986 << "void main (void)\n"
987 << "{\n"
988 << " gl_Position = vs_in_position_ndc;\n"
989 << " vs_out_barCoord = vs_in_barCoord;\n"
990 << "}\n";
991
992 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
993
994 // Create fragment shader
995 std::ostringstream fs;
996
997 fs << "#version 440\n"
998 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
999 << "\n"
1000 << "layout(location = 0) out vec4 fs_out_color;\n"
1001 << "\n"
1002 << "void main (void)\n"
1003 << "{\n"
1004 << " if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
1005 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
1006 << " else\n"
1007 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1008 << "}\n";
1009
1010 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1011 }
1012
checkSupport(Context & context) const1013 template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::checkSupport (Context& context) const
1014 {
1015 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_imageMSParams.pipelineConstructionType);
1016 }
1017
createInstance(Context & context) const1018 template<> TestInstance* MSCase<MSCaseCentroidQualifierInsidePrimitive>::createInstance (Context& context) const
1019 {
1020 return new MSInstance<MSInstanceInterpolateBarycentricCoordinates>(context, m_imageMSParams);
1021 }
1022
1023 } // multisample
1024
createMultisampleInterpolationTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)1025 tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
1026 {
1027 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation"));
1028
1029 const tcu::UVec3 imageSizes[] =
1030 {
1031 tcu::UVec3(128u, 128u, 1u),
1032 tcu::UVec3(137u, 191u, 1u),
1033 };
1034
1035 const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1036
1037 const vk::VkSampleCountFlagBits imageSamples[] =
1038 {
1039 vk::VK_SAMPLE_COUNT_2_BIT,
1040 vk::VK_SAMPLE_COUNT_4_BIT,
1041 vk::VK_SAMPLE_COUNT_8_BIT,
1042 vk::VK_SAMPLE_COUNT_16_BIT,
1043 vk::VK_SAMPLE_COUNT_32_BIT,
1044 vk::VK_SAMPLE_COUNT_64_BIT,
1045 };
1046
1047 const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
1048
1049 de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample"));
1050
1051 for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
1052 {
1053 const tcu::UVec3 imageSize = imageSizes[imageSizeNdx];
1054 std::ostringstream imageSizeStream;
1055
1056 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1057
1058 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str()));
1059
1060 multisample::ImageMSParams imageParams
1061 {
1062 pipelineConstructionType,
1063 vk::VK_SAMPLE_COUNT_1_BIT,
1064 imageSize,
1065 multisample::ComponentData{},
1066 1.0f,
1067 };
1068 sizeGroup->addChild(multisample::MSCase<multisample::MSCaseInterpolateAtSampleSingleSample>::createCase(testCtx, "samples_" + de::toString(1), imageParams));
1069
1070 caseGroup->addChild(sizeGroup.release());
1071 }
1072
1073 testGroup->addChild(caseGroup.release());
1074
1075 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleDistinctValues> > (testCtx, "sample_interpolate_at_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1076 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleIgnoresCentroid> >(testCtx, "sample_interpolate_at_ignores_centroid", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1077
1078 // Test consistency in sample interpolation function
1079 de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolation_consistency"));
1080 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1081 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1082 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1083 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1084 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1085 testGroup->addChild(sampleGroup.release());
1086
1087 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleQualifierDistinctValues> > (testCtx, "sample_qualifier_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1088
1089 de::MovePtr<tcu::TestCaseGroup> centroidGroup(new tcu::TestCaseGroup(testCtx, "centroid_interpolation_consistency", "Test consistency in centroid interpolation function"));
1090 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1091 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1092 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1093 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1094 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1095 testGroup->addChild(centroidGroup.release());
1096
1097 #ifndef CTS_USES_VULKANSC
1098 // there is no support for pipelineConstructionType in amber
1099 if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1100 {
1101 de::MovePtr<tcu::TestCaseGroup> reInterpolationGroup(new tcu::TestCaseGroup(testCtx, "reinterpolation_consistency", "Test consistency in reinterpolation"));
1102 std::vector<std::string> requirements;
1103 requirements.push_back("Features.sampleRateShading");
1104 reInterpolationGroup->addChild(cts_amber::createAmberTestCase(testCtx, "interpolate_at_centroid", "", "pipeline", "reinterpolate_at_centroid.amber", requirements));
1105 reInterpolationGroup->addChild(cts_amber::createAmberTestCase(testCtx, "interpolate_at_sample", "", "pipeline", "reinterpolate_at_sample.amber", requirements));
1106 testGroup->addChild(reInterpolationGroup.release());
1107
1108 de::MovePtr<tcu::TestCaseGroup> nonuniformInterpolantIndexingGroup(new tcu::TestCaseGroup(testCtx, "nonuniform_interpolant_indexing", "Test nonuniform interpolant indexing"));
1109 std::vector<std::string> requirementsNonuniformIntepolantIndexing;
1110 requirementsNonuniformIntepolantIndexing.push_back("Features.sampleRateShading");
1111 nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "centroid", "pipeline/nonuniform_interpolant_indexing", "centroid.amber", requirementsNonuniformIntepolantIndexing));
1112 nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "sample", "pipeline/nonuniform_interpolant_indexing", "sample.amber", requirementsNonuniformIntepolantIndexing));
1113 nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "offset", "pipeline/nonuniform_interpolant_indexing", "offset.amber", requirementsNonuniformIntepolantIndexing));
1114 testGroup->addChild(nonuniformInterpolantIndexingGroup.release());
1115 }
1116
1117 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseCentroidQualifierInsidePrimitive> > (testCtx, "centroid_qualifier_inside_primitive", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1118 #endif // CTS_USES_VULKANSC
1119 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetPixelCenter> > (testCtx, "offset_interpolate_at_pixel_center", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1120
1121 de::MovePtr<tcu::TestCaseGroup> offsetGroup(new tcu::TestCaseGroup(testCtx, "offset_interpolation_at_sample_position", "Test interpolation at offset function works for sample positions"));
1122 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1123 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u}));
1124 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u}));
1125 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u}));
1126 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u}));
1127 testGroup->addChild(offsetGroup.release());
1128
1129 return testGroup.release();
1130 }
1131
1132 } // pipeline
1133 } // vkt
1134