1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 * \file vktPipelineMultisampleInterpolationTests.cpp
21 * \brief Multisample Interpolation Tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktPipelineMultisampleInterpolationTests.hpp"
25 #include "vktPipelineMultisampleBaseResolve.hpp"
26 #include "vktPipelineMultisampleTestsUtil.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "tcuTestLog.hpp"
43 VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
45 tcu::Vec4 positionNdc;
48 struct VertexDataNdcScreen
50 VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
52 tcu::Vec4 positionNdc;
53 tcu::Vec2 positionScreen;
56 struct VertexDataNdcBarycentric
58 VertexDataNdcBarycentric (const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
60 tcu::Vec4 positionNdc;
61 tcu::Vec3 barycentricCoord;
64 bool checkForError (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
66 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z)
67 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
68 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x)
70 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
72 if (errorComponent > 0)
79 template <typename CaseClassName>
80 class MSCase : public MultisampleCaseBase
83 MSCase (tcu::TestContext& testCtx,
84 const std::string& name,
85 const ImageMSParams& imageMSParams)
86 : MultisampleCaseBase(testCtx, name, imageMSParams) {}
89 void initPrograms (vk::SourceCollections& programCollection) const;
90 TestInstance* createInstance (Context& context) const;
91 static MultisampleCaseBase* createCase (tcu::TestContext& testCtx,
92 const std::string& name,
93 const ImageMSParams& imageMSParams);
96 template <typename CaseClassName>
97 MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
99 return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
102 template <typename InstanceClassName>
103 class MSInstance : public MSInstanceBaseResolve
106 MSInstance (Context& context,
107 const ImageMSParams& imageMSParams)
108 : MSInstanceBaseResolve(context, imageMSParams) {}
110 VertexDataDesc getVertexDataDescripton (void) const;
111 void uploadVertexData (const Allocation& vertexBufferAllocation,
112 const VertexDataDesc& vertexDataDescripton) const;
113 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageRSInfo,
114 const tcu::ConstPixelBufferAccess& dataRS) const;
117 class MSInstanceDistinctValues;
119 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceDistinctValues>::getVertexDataDescripton (void) const
121 VertexDataDesc vertexDataDesc;
123 vertexDataDesc.verticesCount = 3u;
124 vertexDataDesc.dataStride = sizeof(VertexDataNdc);
125 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
126 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
128 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
130 0u, // deUint32 location;
131 0u, // deUint32 binding;
132 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
133 DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset;
136 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
138 return vertexDataDesc;
141 template<> void MSInstance<MSInstanceDistinctValues>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
143 std::vector<VertexDataNdc> vertices;
145 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
146 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)));
147 vertices.push_back(VertexDataNdc(tcu::Vec4( 4.0f, -1.0f, 0.0f, 1.0f)));
149 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
152 template<> tcu::TestStatus MSInstance<MSInstanceDistinctValues>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
154 const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u;
156 std::vector<tcu::IVec4> distinctValues;
158 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z)
159 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
160 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x)
162 const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z);
164 if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
165 distinctValues.push_back(pixel);
168 if (distinctValues.size() >= distinctValuesExpected)
169 return tcu::TestStatus::pass("Passed");
171 return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image");
174 class MSCaseSampleQualifierDistinctValues;
176 template<> void MSCase<MSCaseSampleQualifierDistinctValues>::init (void)
179 << tcu::TestLog::Message
180 << "Verifying that a sample qualified varying is given different values for different samples.\n"
181 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
182 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
183 << tcu::TestLog::EndMessage;
185 MultisampleCaseBase::init();
188 template<> void MSCase<MSCaseSampleQualifierDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
190 // Create vertex shader
191 std::ostringstream vs;
193 vs << "#version 440\n"
194 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
196 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
198 << "out gl_PerVertex {\n"
199 << " vec4 gl_Position;\n"
201 << "void main (void)\n"
203 << " gl_Position = vs_in_position_ndc;\n"
204 << " vs_out_position_ndc = vs_in_position_ndc;\n"
207 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
209 // Create fragment shader
210 std::ostringstream fs;
212 fs << "#version 440\n"
213 << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
215 << "layout(location = 0) out vec4 fs_out_color;\n"
217 << "void main (void)\n"
219 << " if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
220 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
222 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
225 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
228 template<> TestInstance* MSCase<MSCaseSampleQualifierDistinctValues>::createInstance (Context& context) const
230 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
233 class MSCaseInterpolateAtSampleDistinctValues;
235 template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::init (void)
238 << tcu::TestLog::Message
239 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
240 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
241 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
242 << tcu::TestLog::EndMessage;
244 MultisampleCaseBase::init();
247 template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const
249 // Create vertex shader
250 std::ostringstream vs;
252 vs << "#version 440\n"
253 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
255 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
257 << "out gl_PerVertex {\n"
258 << " vec4 gl_Position;\n"
260 << "void main (void)\n"
262 << " gl_Position = vs_in_position_ndc;\n"
263 << " vs_out_position_ndc = vs_in_position_ndc;\n"
266 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
268 // Create fragment shader
269 std::ostringstream fs;
271 fs << "#version 440\n"
272 << "layout(location = 0) in vec4 fs_in_position_ndc;\n"
274 << "layout(location = 0) out vec4 fs_out_color;\n"
276 << "void main (void)\n"
278 << " const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
279 << " if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
280 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
282 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
285 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
288 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleDistinctValues>::createInstance (Context& context) const
290 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams);
293 class MSInstanceInterpolateScreenPosition;
295 template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateScreenPosition>::getVertexDataDescripton (void) const
297 VertexDataDesc vertexDataDesc;
299 vertexDataDesc.verticesCount = 4u;
300 vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen);
301 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
302 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
304 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
306 0u, // deUint32 location;
307 0u, // deUint32 binding;
308 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
309 DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset;
312 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
314 const VkVertexInputAttributeDescription vertexAttribPositionScreen =
316 1u, // deUint32 location;
317 0u, // deUint32 binding;
318 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
319 DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset;
322 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
324 return vertexDataDesc;
327 template<> void MSInstance<MSInstanceInterpolateScreenPosition>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
329 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
330 const float screenSizeX = static_cast<float>(layerSize.x());
331 const float screenSizeY = static_cast<float>(layerSize.y());
333 std::vector<VertexDataNdcScreen> vertices;
335 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
336 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
337 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY)));
338 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
340 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
343 template<> tcu::TestStatus MSInstance<MSInstanceInterpolateScreenPosition>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
345 if (checkForError(imageRSInfo, dataRS, 0))
346 return tcu::TestStatus::fail("Failed");
348 return tcu::TestStatus::pass("Passed");
351 class MSCaseInterpolateAtSampleSingleSample;
353 template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::init (void)
356 << tcu::TestLog::Message
357 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
358 << " Interpolate varying containing screen space location.\n"
359 << " => fract(screen space location) should be (about) (0.5, 0.5)\n"
360 << tcu::TestLog::EndMessage;
362 MultisampleCaseBase::init();
365 template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::initPrograms (vk::SourceCollections& programCollection) const
367 // Create vertex shader
368 std::ostringstream vs;
370 vs << "#version 440\n"
371 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
372 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
374 << "layout(location = 0) out vec2 vs_out_position_screen;\n"
376 << "out gl_PerVertex {\n"
377 << " vec4 gl_Position;\n"
379 << "void main (void)\n"
381 << " gl_Position = vs_in_position_ndc;\n"
382 << " vs_out_position_screen = vs_in_position_screen;\n"
385 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
387 // Create fragment shader
388 std::ostringstream fs;
390 fs << "#version 440\n"
391 << "layout(location = 0) in vec2 fs_in_position_screen;\n"
393 << "layout(location = 0) out vec4 fs_out_color;\n"
395 << "void main (void)\n"
397 << " const float threshold = 0.15625;\n"
398 << " const vec2 position_screen_at_sample = interpolateAtSample(fs_in_position_screen, 0);\n"
399 << " const vec2 position_inside_pixel = fract(position_screen_at_sample);\n"
401 << " if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
402 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
404 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
407 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
410 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleSingleSample>::createInstance (Context& context) const
412 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
415 class MSCaseInterpolateAtSampleIgnoresCentroid;
417 template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::init (void)
420 << tcu::TestLog::Message
421 << "Verifying that interpolateAtSample ignores centroid qualifier.\n"
422 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
423 << " => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
424 << tcu::TestLog::EndMessage;
426 MultisampleCaseBase::init();
429 template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::initPrograms (vk::SourceCollections& programCollection) const
431 // Create vertex shader
432 std::ostringstream vs;
434 vs << "#version 440\n"
435 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
436 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
438 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
439 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
441 << "out gl_PerVertex {\n"
442 << " vec4 gl_Position;\n"
444 << "void main (void)\n"
446 << " gl_Position = vs_in_position_ndc;\n"
447 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
448 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
451 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
453 // Create fragment shader
454 std::ostringstream fs;
456 fs << "#version 440\n"
457 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
458 << "layout(location = 1) in vec2 fs_in_pos_screen_fragment;\n"
460 << "layout(location = 0) out vec4 fs_out_color;\n"
462 << "void main (void)\n"
464 << " const float threshold = 0.0005;\n"
466 << " const vec2 position_a = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
467 << " const vec2 position_b = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
468 << " const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
470 << " if (valuesEqual)\n"
471 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
473 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
476 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
479 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::createInstance (Context& context) const
481 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
484 class MSCaseInterpolateAtSampleConsistency;
486 template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::init (void)
489 << tcu::TestLog::Message
490 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
491 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
492 << " => interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
493 << tcu::TestLog::EndMessage;
495 MultisampleCaseBase::init();
498 template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::initPrograms (vk::SourceCollections& programCollection) const
500 // Create vertex shader
501 std::ostringstream vs;
503 vs << "#version 440\n"
504 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
505 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
507 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
508 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
510 << "out gl_PerVertex {\n"
511 << " vec4 gl_Position;\n"
513 << "void main (void)\n"
515 << " gl_Position = vs_in_position_ndc;\n"
516 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
517 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
520 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
522 // Create fragment shader
523 std::ostringstream fs;
525 fs << "#version 440\n"
526 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
527 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
529 << "layout(location = 0) out vec4 fs_out_color;\n"
531 << "void main (void)\n"
533 << " const float threshold = 0.15625;\n"
535 << " const vec2 pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
536 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n"
538 << " if (valuesEqual)\n"
539 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
541 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
544 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
547 template<> TestInstance* MSCase<MSCaseInterpolateAtSampleConsistency>::createInstance (Context& context) const
549 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
552 class MSCaseInterpolateAtCentroidConsistency;
554 template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::init (void)
557 << tcu::TestLog::Message
558 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n"
559 << " Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
560 << " => interpolateAtCentroid(screenSample) = screenCentroid\n"
561 << tcu::TestLog::EndMessage;
563 MultisampleCaseBase::init();
566 template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::initPrograms (vk::SourceCollections& programCollection) const
568 // Create vertex shader
569 std::ostringstream vs;
571 vs << "#version 440\n"
572 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
573 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
575 << "layout(location = 0) out vec2 vs_out_pos_screen_sample;\n"
576 << "layout(location = 1) out vec2 vs_out_pos_screen_centroid;\n"
578 << "out gl_PerVertex {\n"
579 << " vec4 gl_Position;\n"
581 << "void main (void)\n"
583 << " gl_Position = vs_in_position_ndc;\n"
584 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
585 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
588 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
590 // Create fragment shader
591 std::ostringstream fs;
593 fs << "#version 440\n"
594 << "layout(location = 0) sample in vec2 fs_in_pos_screen_sample;\n"
595 << "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n"
597 << "layout(location = 0) out vec4 fs_out_color;\n"
599 << "void main (void)\n"
601 << " const float threshold = 0.0005;\n"
603 << " const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample);\n"
604 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n"
606 << " if (valuesEqual)\n"
607 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
609 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
612 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
615 template<> TestInstance* MSCase<MSCaseInterpolateAtCentroidConsistency>::createInstance (Context& context) const
617 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
620 class MSCaseInterpolateAtOffsetPixelCenter;
622 template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::init (void)
625 << tcu::TestLog::Message
626 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
627 << " Interpolate varying containing screen space location.\n"
628 << " => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
629 << tcu::TestLog::EndMessage;
631 MultisampleCaseBase::init();
634 template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::initPrograms (vk::SourceCollections& programCollection) const
636 // Create vertex shader
637 std::ostringstream vs;
639 vs << "#version 440\n"
640 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
641 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
643 << "layout(location = 0) out vec2 vs_out_pos_screen;\n"
644 << "layout(location = 1) out vec2 vs_out_offset;\n"
646 << "out gl_PerVertex {\n"
647 << " vec4 gl_Position;\n"
649 << "void main (void)\n"
651 << " gl_Position = vs_in_position_ndc;\n"
652 << " vs_out_pos_screen = vs_in_position_screen;\n"
653 << " vs_out_offset = vs_in_position_ndc.xy * 0.5;\n"
656 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
658 // Create fragment shader
659 std::ostringstream fs;
661 fs << "#version 440\n"
662 << "layout(location = 0) in vec2 fs_in_pos_screen;\n"
663 << "layout(location = 1) in vec2 fs_in_offset;\n"
665 << "layout(location = 0) out vec4 fs_out_color;\n"
667 << "void main (void)\n"
669 << " const vec2 frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
670 << " const vec2 center_diff = abs(frag_center - fs_in_pos_screen);\n"
671 << " const float threshold = 0.125;\n"
672 << " bool valuesEqual = false;\n"
674 << " if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
675 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
676 << " const vec2 reference_value = frag_center + fs_in_offset;\n"
678 << " valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
681 << " if (valuesEqual)\n"
682 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
684 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
687 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
690 template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetPixelCenter>::createInstance (Context& context) const
692 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
695 class MSCaseInterpolateAtOffsetSamplePosition;
697 template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::init (void)
700 << tcu::TestLog::Message
701 << "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value "
702 << "similar to screen position interpolated at sample.\n"
703 << " Interpolate varying containing screen space location with and without sample qualifier.\n"
704 << " => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
705 << tcu::TestLog::EndMessage;
707 MultisampleCaseBase::init();
710 template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::initPrograms (vk::SourceCollections& programCollection) const
712 // Create vertex shader
713 std::ostringstream vs;
715 vs << "#version 440\n"
716 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
717 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
719 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
720 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
722 << "out gl_PerVertex {\n"
723 << " vec4 gl_Position;\n"
725 << "void main (void)\n"
727 << " gl_Position = vs_in_position_ndc;\n"
728 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
729 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
732 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
734 // Create fragment shader
735 std::ostringstream fs;
737 fs << "#version 440\n"
738 << "layout(location = 0) in vec2 fs_in_pos_screen_fragment;\n"
739 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
741 << "layout(location = 0) out vec4 fs_out_color;\n"
743 << "void main (void)\n"
745 << " const float threshold = 0.15625;\n"
747 << " const vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n"
748 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
749 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n"
751 << " if (valuesEqual)\n"
752 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
754 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
757 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
760 template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetSamplePosition>::createInstance (Context& context) const
762 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams);
765 class MSInstanceInterpolateBarycentricCoordinates;
767 template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateBarycentricCoordinates>::getVertexDataDescripton (void) const
769 VertexDataDesc vertexDataDesc;
771 vertexDataDesc.verticesCount = 3u;
772 vertexDataDesc.dataStride = sizeof(VertexDataNdcBarycentric);
773 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
774 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
776 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
778 0u, // deUint32 location;
779 0u, // deUint32 binding;
780 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
781 DE_OFFSET_OF(VertexDataNdcBarycentric, positionNdc), // deUint32 offset;
784 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
786 const VkVertexInputAttributeDescription vertexAttrBarCoord =
788 1u, // deUint32 location;
789 0u, // deUint32 binding;
790 VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
791 DE_OFFSET_OF(VertexDataNdcBarycentric, barycentricCoord), // deUint32 offset;
794 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
796 return vertexDataDesc;
799 template<> void MSInstance<MSInstanceInterpolateBarycentricCoordinates>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
801 // Create buffer storing vertex data
802 std::vector<VertexDataNdcBarycentric> vertices;
804 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
805 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
806 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
808 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
811 template<> tcu::TestStatus MSInstance<MSInstanceInterpolateBarycentricCoordinates>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const
813 if (checkForError(imageRSInfo, dataRS, 0))
814 return tcu::TestStatus::fail("Failed");
816 return tcu::TestStatus::pass("Passed");
819 class MSCaseCentroidQualifierInsidePrimitive;
821 template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::init (void)
824 << tcu::TestLog::Message
825 << "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n"
826 << " Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
827 << " => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
828 << tcu::TestLog::EndMessage;
830 MultisampleCaseBase::init();
833 template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::initPrograms (vk::SourceCollections& programCollection) const
835 // Create vertex shader
836 std::ostringstream vs;
838 vs << "#version 440\n"
839 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
840 << "layout(location = 1) in vec3 vs_in_barCoord;\n"
842 << "layout(location = 0) out vec3 vs_out_barCoord;\n"
844 << "out gl_PerVertex {\n"
845 << " vec4 gl_Position;\n"
847 << "void main (void)\n"
849 << " gl_Position = vs_in_position_ndc;\n"
850 << " vs_out_barCoord = vs_in_barCoord;\n"
853 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
855 // Create fragment shader
856 std::ostringstream fs;
858 fs << "#version 440\n"
859 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
861 << "layout(location = 0) out vec4 fs_out_color;\n"
863 << "void main (void)\n"
865 << " if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
866 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
868 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
871 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
874 template<> TestInstance* MSCase<MSCaseCentroidQualifierInsidePrimitive>::createInstance (Context& context) const
876 return new MSInstance<MSInstanceInterpolateBarycentricCoordinates>(context, m_imageMSParams);
881 tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx)
883 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation"));
885 const tcu::UVec3 imageSizes[] =
887 tcu::UVec3(128u, 128u, 1u),
888 tcu::UVec3(137u, 191u, 1u),
891 const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
893 const vk::VkSampleCountFlagBits imageSamples[] =
895 vk::VK_SAMPLE_COUNT_2_BIT,
896 vk::VK_SAMPLE_COUNT_4_BIT,
897 vk::VK_SAMPLE_COUNT_8_BIT,
898 vk::VK_SAMPLE_COUNT_16_BIT,
899 vk::VK_SAMPLE_COUNT_32_BIT,
900 vk::VK_SAMPLE_COUNT_64_BIT,
903 const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
905 de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample_", ""));
907 for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
909 const tcu::UVec3 imageSize = imageSizes[imageSizeNdx];
910 std::ostringstream imageSizeStream;
912 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
914 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
916 sizeGroup->addChild(multisample::MSCase<multisample::MSCaseInterpolateAtSampleSingleSample>::createCase(testCtx, "samples_" + de::toString(1), multisample::ImageMSParams(vk::VK_SAMPLE_COUNT_1_BIT, imageSize)));
918 caseGroup->addChild(sizeGroup.release());
921 testGroup->addChild(caseGroup.release());
923 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleDistinctValues> > (testCtx, "sample_interpolate_at_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
924 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleIgnoresCentroid> >(testCtx, "sample_interpolate_at_ignores_centroid", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
925 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "sample_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
926 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleQualifierDistinctValues> > (testCtx, "sample_qualifier_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
927 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "centroid_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
928 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseCentroidQualifierInsidePrimitive> > (testCtx, "centroid_qualifier_inside_primitive", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
929 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetPixelCenter> > (testCtx, "offset_interpolate_at_pixel_center", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
930 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "offset_interpolate_at_sample_position", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
932 return testGroup.release();