18a12eecf2f6e68b667cbd3e6d053ba02a464a16
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineMultisampleShaderBuiltInTests.cpp
1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*
20 * \file vktPipelineMultisampleShaderBuiltInTests.cpp
21 * \brief Multisample Shader BuiltIn Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineMultisampleShaderBuiltInTests.hpp"
25 #include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vkBuilderUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "tcuVectorUtil.hpp"
30 #include "tcuTestLog.hpp"
31
32 namespace vkt
33 {
34 namespace pipeline
35 {
36 namespace multisample
37 {
38
39 using namespace vk;
40
41 struct VertexDataNdc
42 {
43         VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
44
45         tcu::Vec4 positionNdc;
46 };
47
48 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void)
49 {
50         MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
51
52         vertexDataDesc.verticesCount     = 4u;
53         vertexDataDesc.dataStride                = sizeof(VertexDataNdc);
54         vertexDataDesc.dataSize                  = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
55         vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
56
57         const VkVertexInputAttributeDescription vertexAttribPositionNdc =
58         {
59                 0u,                                                                                     // deUint32     location;
60                 0u,                                                                                     // deUint32     binding;
61                 VK_FORMAT_R32G32B32A32_SFLOAT,                          // VkFormat     format;
62                 DE_OFFSET_OF(VertexDataNdc, positionNdc),       // deUint32     offset;
63         };
64
65         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
66
67         return vertexDataDesc;
68 }
69
70 void uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton)
71 {
72         std::vector<VertexDataNdc> vertices;
73
74         vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
75         vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)));
76         vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f)));
77         vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f)));
78
79         deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
80 }
81
82 struct VertexDataNdcScreen
83 {
84         VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
85
86         tcu::Vec4 positionNdc;
87         tcu::Vec2 positionScreen;
88 };
89
90 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void)
91 {
92         MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
93
94         vertexDataDesc.verticesCount     = 4u;
95         vertexDataDesc.dataStride                = sizeof(VertexDataNdcScreen);
96         vertexDataDesc.dataSize                  = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
97         vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
98
99         const VkVertexInputAttributeDescription vertexAttribPositionNdc =
100         {
101                 0u,                                                                                                     // deUint32     location;
102                 0u,                                                                                                     // deUint32     binding;
103                 VK_FORMAT_R32G32B32A32_SFLOAT,                                          // VkFormat     format;
104                 DE_OFFSET_OF(VertexDataNdcScreen, positionNdc),         // deUint32     offset;
105         };
106
107         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
108
109         const VkVertexInputAttributeDescription vertexAttribPositionScreen =
110         {
111                 1u,                                                                                                     // deUint32     location;
112                 0u,                                                                                                     // deUint32     binding;
113                 VK_FORMAT_R32G32_SFLOAT,                                                        // VkFormat     format;
114                 DE_OFFSET_OF(VertexDataNdcScreen, positionScreen),      // deUint32     offset;
115         };
116
117         vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
118
119         return vertexDataDesc;
120 }
121
122 void uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize)
123 {
124         std::vector<VertexDataNdcScreen> vertices;
125
126         vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
127         vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f)));
128         vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y())));
129         vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y())));
130
131         deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
132 }
133
134 bool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx)
135 {
136         const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
137
138         for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
139         for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
140         for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
141         {
142                 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
143                 {
144                         const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx];
145
146                         if (errorComponent > 0)
147                                 return true;
148                 }
149         }
150
151         return false;
152 }
153
154 bool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
155 {
156         for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
157         for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
158         for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
159         {
160                 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
161
162                 if (errorComponent > 0)
163                         return true;
164         }
165
166         return false;
167 }
168
169 template <typename CaseClassName>
170 class MSCase : public MSCaseBaseResolveAndPerSampleFetch
171 {
172 public:
173                                                                 MSCase                  (tcu::TestContext&              testCtx,
174                                                                                                  const std::string&             name,
175                                                                                                  const ImageMSParams&   imageMSParams)
176                                                                 : MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {}
177
178         virtual void                            checkSupport    (Context&) const {}
179         void                                            init                    (void);
180         void                                            initPrograms    (vk::SourceCollections& programCollection) const;
181         TestInstance*                           createInstance  (Context&                               context) const;
182         static MultisampleCaseBase*     createCase              (tcu::TestContext&              testCtx,
183                                                                                                  const std::string&             name,
184                                                                                                  const ImageMSParams&   imageMSParams);
185 };
186
187 template <typename CaseClassName>
188 MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
189 {
190         return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
191 }
192
193 template <typename InstanceClassName>
194 class MSInstance : public MSInstanceBaseResolveAndPerSampleFetch
195 {
196 public:
197                                         MSInstance                              (Context&                                                                                       context,
198                                                                                          const ImageMSParams&                                                           imageMSParams)
199                                         : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {}
200
201         VertexDataDesc  getVertexDataDescripton (void) const;
202         void                    uploadVertexData                (const Allocation&                                                                      vertexBufferAllocation,
203                                                                                          const VertexDataDesc&                                                          vertexDataDescripton) const;
204
205         tcu::TestStatus verifyImageData                 (const vk::VkImageCreateInfo&                                           imageMSInfo,
206                                                                                          const vk::VkImageCreateInfo&                                           imageRSInfo,
207                                                                                          const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
208                                                                                          const tcu::ConstPixelBufferAccess&                                     dataRS) const;
209 };
210
211 class MSInstanceSampleID;
212
213 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const
214 {
215         return getVertexDataDescriptonNdc();
216 }
217
218 template<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
219 {
220         uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
221 }
222
223 template<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData      (const vk::VkImageCreateInfo&                                           imageMSInfo,
224                                                                                                                                                          const vk::VkImageCreateInfo&                                           imageRSInfo,
225                                                                                                                                                          const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
226                                                                                                                                                          const tcu::ConstPixelBufferAccess&                                     dataRS) const
227 {
228         DE_UNREF(imageRSInfo);
229         DE_UNREF(dataRS);
230
231         const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
232
233         for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
234         {
235                 for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
236                 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
237                 for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
238                 {
239                         const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x();
240
241                         if (sampleID != sampleNdx)
242                                 return tcu::TestStatus::fail("gl_SampleID does not have correct value");
243                 }
244         }
245
246         return tcu::TestStatus::pass("Passed");
247 }
248
249 class MSCaseSampleID;
250
251 template<> void MSCase<MSCaseSampleID>::checkSupport (Context& context) const
252 {
253         if (!context.getDeviceFeatures().sampleRateShading)
254                 TCU_THROW(NotSupportedError, "sampleRateShading not supported");
255 }
256
257 template<> void MSCase<MSCaseSampleID>::init (void)
258 {
259         m_testCtx.getLog()
260                 << tcu::TestLog::Message
261                 << "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n"
262                 << "Expecting value N at sample index N of a multisample texture.\n"
263                 << tcu::TestLog::EndMessage;
264
265         MultisampleCaseBase::init();
266 }
267
268 template<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const
269 {
270         MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
271
272         // Create vertex shader
273         std::ostringstream vs;
274
275         vs << "#version 440\n"
276                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
277                 << "\n"
278                 << "out gl_PerVertex {\n"
279                 << "    vec4  gl_Position;\n"
280                 << "};\n"
281                 << "void main (void)\n"
282                 << "{\n"
283                 << "    gl_Position     = vs_in_position_ndc;\n"
284                 << "}\n";
285
286         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
287
288         // Create fragment shader
289         std::ostringstream fs;
290
291         fs << "#version 440\n"
292                 << "\n"
293                 << "layout(location = 0) out vec4 fs_out_color;\n"
294                 << "\n"
295                 << "void main (void)\n"
296                 << "{\n"
297                 << "    fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n"
298                 << "}\n";
299
300         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
301 }
302
303 template<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const
304 {
305         return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams);
306 }
307
308 class MSInstanceSamplePosDistribution;
309
310 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const
311 {
312         return getVertexDataDescriptonNdc();
313 }
314
315 template<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
316 {
317         uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
318 }
319
320 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData (const vk::VkImageCreateInfo&                                           imageMSInfo,
321                                                                                                                                                                                  const vk::VkImageCreateInfo&                                           imageRSInfo,
322                                                                                                                                                                                  const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
323                                                                                                                                                                                  const tcu::ConstPixelBufferAccess&                                     dataRS) const
324 {
325         const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
326
327         // approximate Bates distribution as normal
328         const float variance = (1.0f / (12.0f * (float)numSamples));
329         const float standardDeviation = deFloatSqrt(variance);
330
331         // 95% of means of sample positions are within 2 standard deviations if
332         // they were randomly assigned. Sample patterns are expected to be more
333         // uniform than a random pattern.
334         const float distanceThreshold = 2.0f * standardDeviation;
335
336         for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
337         for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
338         for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
339         {
340                 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z();
341
342                 if (errorComponent > 0)
343                         return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
344
345                 if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
346                 {
347                         const tcu::Vec2 averageSamplePos        = tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f);
348                         const tcu::Vec2 distanceFromCenter      = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
349
350                         if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
351                                 return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
352                 }
353         }
354
355         for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
356         for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
357         for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
358         {
359                 std::vector<tcu::Vec2> samplePositions(numSamples);
360
361                 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
362                 {
363                         const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z();
364
365                         if (errorComponent > 0)
366                                 return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
367
368                         samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f,
369                                                                                                         (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f);
370                 }
371
372                 for (deUint32 sampleNdxA = 0u;                          sampleNdxA < numSamples; ++sampleNdxA)
373                 for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB)
374                 {
375                         if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
376                                 return tcu::TestStatus::fail("Two samples have the same position");
377                 }
378
379                 if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
380                 {
381                         tcu::Vec2 averageSamplePos(0.0f, 0.0f);
382
383                         for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
384                         {
385                                 averageSamplePos.x() += samplePositions[sampleNdx].x();
386                                 averageSamplePos.y() += samplePositions[sampleNdx].y();
387                         }
388
389                         averageSamplePos.x() /= (float)numSamples;
390                         averageSamplePos.y() /= (float)numSamples;
391
392                         const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
393
394                         if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
395                                 return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
396                 }
397         }
398
399         return tcu::TestStatus::pass("Passed");
400 }
401
402 class MSCaseSamplePosDistribution;
403
404 template<> void MSCase<MSCaseSamplePosDistribution>::checkSupport (Context& context) const
405 {
406         if (!context.getDeviceFeatures().sampleRateShading)
407                 TCU_THROW(NotSupportedError, "sampleRateShading not supported");
408 }
409
410 template<> void MSCase<MSCaseSamplePosDistribution>::init (void)
411 {
412         m_testCtx.getLog()
413                 << tcu::TestLog::Message
414                 << "Verifying gl_SamplePosition value with multisample targets:\n"
415                 << "    a) Expect legal sample position.\n"
416                 << "    b) Sample position is unique within the set of all sample positions of a pixel.\n"
417                 << "    c) Sample position distribution is uniform or almost uniform.\n"
418                 << tcu::TestLog::EndMessage;
419
420         MultisampleCaseBase::init();
421 }
422
423 template<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const
424 {
425         MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
426
427         // Create vertex shader
428         std::ostringstream vs;
429
430         vs << "#version 440\n"
431                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
432                 << "\n"
433                 << "out gl_PerVertex {\n"
434                 << "    vec4  gl_Position;\n"
435                 << "};\n"
436                 << "void main (void)\n"
437                 << "{\n"
438                 << "    gl_Position     = vs_in_position_ndc;\n"
439                 << "}\n";
440
441         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
442
443         // Create fragment shader
444         std::ostringstream fs;
445
446         fs << "#version 440\n"
447                 << "\n"
448                 << "layout(location = 0) out vec4 fs_out_color;\n"
449                 << "\n"
450                 << "void main (void)\n"
451                 << "{\n"
452                 << "    if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n"
453                 "               fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
454                 "       else\n"
455                 "               fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n"
456                 "}\n";
457
458         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
459 }
460
461 template<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const
462 {
463         return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams);
464 }
465
466 class MSInstanceSamplePosCorrectness;
467
468 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const
469 {
470         return getVertexDataDescriptonNdcScreen();
471 }
472
473 template<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
474 {
475         const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
476
477         uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y())));
478 }
479
480 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData  (const vk::VkImageCreateInfo&                                           imageMSInfo,
481                                                                                                                                                                                  const vk::VkImageCreateInfo&                                           imageRSInfo,
482                                                                                                                                                                                  const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
483                                                                                                                                                                                  const tcu::ConstPixelBufferAccess&                                     dataRS) const
484 {
485         if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
486                 return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
487
488         if (checkForErrorRS(imageRSInfo, dataRS, 0))
489                 return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
490
491         return tcu::TestStatus::pass("Passed");
492 }
493
494 class MSCaseSamplePosCorrectness;
495
496 template<> void MSCase<MSCaseSamplePosCorrectness>::checkSupport (Context& context) const
497 {
498         if (!context.getDeviceFeatures().sampleRateShading)
499                 TCU_THROW(NotSupportedError, "sampleRateShading not supported");
500 }
501
502 template<> void MSCase<MSCaseSamplePosCorrectness>::init (void)
503 {
504         m_testCtx.getLog()
505                 << tcu::TestLog::Message
506                 << "Verifying gl_SamplePosition correctness:\n"
507                 << "    1) Varying values should be sampled at the sample position.\n"
508                 << "            => fract(position_screen) == gl_SamplePosition\n"
509                 << tcu::TestLog::EndMessage;
510
511         MultisampleCaseBase::init();
512 }
513
514 template<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const
515 {
516         MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
517
518         // Create vertex shaders
519         std::ostringstream vs;
520
521         vs      << "#version 440\n"
522                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
523                 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
524                 << "\n"
525                 << "layout(location = 0) sample out vec2 vs_out_position_screen;\n"
526                 << "\n"
527                 << "out gl_PerVertex {\n"
528                 << "    vec4  gl_Position;\n"
529                 << "};\n"
530                 << "void main (void)\n"
531                 << "{\n"
532                 << "    gl_Position                             = vs_in_position_ndc;\n"
533                 << "    vs_out_position_screen  = vs_in_position_screen;\n"
534                 << "}\n";
535
536         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
537
538         // Create fragment shader
539         std::ostringstream fs;
540
541         fs      << "#version 440\n"
542                 << "layout(location = 0) sample in vec2 fs_in_position_screen;\n"
543                 << "\n"
544                 << "layout(location = 0) out vec4 fs_out_color;\n"
545                 << "\n"
546                 << "void main (void)\n"
547                 << "{\n"
548                 << "    const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"
549                 << "    const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n"
550                 << "    bool ok = false;\n"
551                 << "\n"
552                 << "    // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n"
553                 << "    // check all neighbors for any match\n"
554                 << "    for (int dy = -1; dy <= 1; ++dy)\n"
555                 << "    for (int dx = -1; dx <= 1; ++dx)\n"
556                 << "    {\n"
557                 << "            ivec2 current_pixel                     = nearby_pixel + ivec2(dx, dy);\n"
558                 << "            vec2 position_inside_pixel      = vec2(current_pixel) + gl_SamplePosition;\n"
559                 << "            vec2 position_diff                      = abs(position_inside_pixel - fs_in_position_screen);\n"
560                 << "\n"
561                 << "            if (all(lessThan(position_diff, vec2(threshold))))\n"
562                 << "                    ok = true;\n"
563                 << "    }\n"
564                 << "\n"
565                 << "    if (ok)\n"
566                 << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
567                 << "    else\n"
568                 << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
569                 << "}\n";
570
571         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
572 }
573
574 template<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const
575 {
576         return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams);
577 }
578
579 class MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch
580 {
581 public:
582                                                                                         MSInstanceSampleMaskPattern     (Context&                                                                                       context,
583                                                                                                                                                  const ImageMSParams&                                                           imageMSParams);
584
585         VkPipelineMultisampleStateCreateInfo    getMSStateCreateInfo            (const ImageMSParams&                                                           imageMSParams) const;
586
587         const VkDescriptorSetLayout*                    createMSPassDescSetLayout       (const ImageMSParams&                                                           imageMSParams);
588
589         const VkDescriptorSet*                                  createMSPassDescSet                     (const ImageMSParams&                                                           imageMSParams,
590                                                                                                                                                  const VkDescriptorSetLayout*                                           descSetLayout);
591
592         VertexDataDesc                                                  getVertexDataDescripton         (void) const;
593
594         void                                                                    uploadVertexData                        (const Allocation&                                                                      vertexBufferAllocation,
595                                                                                                                                                  const VertexDataDesc&                                                          vertexDataDescripton) const;
596
597         tcu::TestStatus                                                 verifyImageData                         (const vk::VkImageCreateInfo&                                           imageMSInfo,
598                                                                                                                                                  const vk::VkImageCreateInfo&                                           imageRSInfo,
599                                                                                                                                                  const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
600                                                                                                                                                  const tcu::ConstPixelBufferAccess&                                     dataRS) const;
601 protected:
602
603         VkSampleMask                            m_sampleMask;
604         Move<VkDescriptorSetLayout>     m_descriptorSetLayout;
605         Move<VkDescriptorPool>          m_descriptorPool;
606         Move<VkDescriptorSet>           m_descriptorSet;
607         de::MovePtr<Buffer>                     m_buffer;
608 };
609
610 MSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams)
611 {
612         m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u);
613 }
614
615 VkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
616 {
617         const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
618         {
619                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
620                 DE_NULL,                                                                                                                // const void*                                                          pNext;
621                 (VkPipelineMultisampleStateCreateFlags)0u,                                              // VkPipelineMultisampleStateCreateFlags        flags;
622                 imageMSParams.numSamples,                                                                               // VkSampleCountFlagBits                                        rasterizationSamples;
623                 VK_TRUE,                                                                                                                // VkBool32                                                                     sampleShadingEnable;
624                 1.0f,                                                                                                                   // float                                                                        minSampleShading;
625                 &m_sampleMask,                                                                                                  // const VkSampleMask*                                          pSampleMask;
626                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
627                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToOneEnable;
628         };
629
630         return multisampleStateInfo;
631 }
632
633 const VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams)
634 {
635         DE_UNREF(imageMSParams);
636
637         const DeviceInterface&          deviceInterface = m_context.getDeviceInterface();
638         const VkDevice                          device                  = m_context.getDevice();
639
640         // Create descriptor set layout
641         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
642                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
643                 .build(deviceInterface, device);
644
645         return &m_descriptorSetLayout.get();
646 }
647
648 const VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
649 {
650         DE_UNREF(imageMSParams);
651
652         const DeviceInterface&          deviceInterface = m_context.getDeviceInterface();
653         const VkDevice                          device                  = m_context.getDevice();
654         Allocator&                                      allocator               = m_context.getDefaultAllocator();
655
656         // Create descriptor pool
657         m_descriptorPool = DescriptorPoolBuilder()
658                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
659                 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
660
661         // Create descriptor set
662         m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout);
663
664         const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
665
666         m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible));
667
668         deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask));
669
670         flushAlloc(deviceInterface, device, m_buffer->getAllocation());
671
672         const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask));
673
674         DescriptorSetUpdateBuilder()
675                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo)
676                 .update(deviceInterface, device);
677
678         return &m_descriptorSet.get();
679 }
680
681 MultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const
682 {
683         return getVertexDataDescriptonNdc();
684 }
685
686 void MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
687 {
688         uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
689 }
690
691 tcu::TestStatus MSInstanceSampleMaskPattern::verifyImageData    (const vk::VkImageCreateInfo&                                           imageMSInfo,
692                                                                                                                                  const vk::VkImageCreateInfo&                                           imageRSInfo,
693                                                                                                                                  const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
694                                                                                                                                  const tcu::ConstPixelBufferAccess&                                     dataRS) const
695 {
696         DE_UNREF(imageRSInfo);
697         DE_UNREF(dataRS);
698
699         if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
700                 return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state");
701
702         return tcu::TestStatus::pass("Passed");
703 }
704
705 class MSCaseSampleMaskPattern;
706
707 template<> void MSCase<MSCaseSampleMaskPattern>::init (void)
708 {
709         m_testCtx.getLog()
710                 << tcu::TestLog::Message
711                 << "Verifying gl_SampleMaskIn value with pSampleMask state. gl_SampleMaskIn does not contain any bits set that are have been killed by pSampleMask state. Expecting:\n"
712                 << "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n"
713                 << tcu::TestLog::EndMessage;
714
715         MultisampleCaseBase::init();
716 }
717
718 template<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const
719 {
720         MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
721
722         // Create vertex shader
723         std::ostringstream vs;
724
725         vs << "#version 440\n"
726                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
727                 << "\n"
728                 << "out gl_PerVertex {\n"
729                 << "    vec4  gl_Position;\n"
730                 << "};\n"
731                 << "void main (void)\n"
732                 << "{\n"
733                 << "    gl_Position     = vs_in_position_ndc;\n"
734                 << "}\n";
735
736         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
737
738         // Create fragment shader
739         std::ostringstream fs;
740
741         fs << "#version 440\n"
742                 << "\n"
743                 << "layout(location = 0) out vec4 fs_out_color;\n"
744                 << "\n"
745                 << "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n"
746                 << "{\n"
747                 << "    int sampleMaskPattern;\n"
748                 << "};"
749                 << "\n"
750                 << "void main (void)\n"
751                 << "{\n"
752                 << "    if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n"
753                 << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
754                 << "    else\n"
755                 << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
756                 << "}\n";
757
758         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
759 }
760
761 template<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const
762 {
763         return new MSInstanceSampleMaskPattern(context, m_imageMSParams);
764 }
765
766 class MSInstanceSampleMaskBitCount;
767
768 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const
769 {
770         return getVertexDataDescriptonNdc();
771 }
772
773 template<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
774 {
775         uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
776 }
777
778 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData    (const vk::VkImageCreateInfo&                                           imageMSInfo,
779                                                                                                                                                                                  const vk::VkImageCreateInfo&                                           imageRSInfo,
780                                                                                                                                                                                  const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
781                                                                                                                                                                                  const tcu::ConstPixelBufferAccess&                                     dataRS) const
782 {
783         DE_UNREF(imageRSInfo);
784         DE_UNREF(dataRS);
785
786         if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
787                 return tcu::TestStatus::fail("gl_SampleMaskIn has more than one bit set for some shader invocations");
788
789         return tcu::TestStatus::pass("Passed");
790 }
791
792 class MSCaseSampleMaskBitCount;
793
794 template<> void MSCase<MSCaseSampleMaskBitCount>::init (void)
795 {
796         m_testCtx.getLog()
797                 << tcu::TestLog::Message
798                 << "Verifying gl_SampleMaskIn.\n"
799                 << "    Fragment shader will be invoked numSamples times.\n"
800                 << "    => gl_SampleMaskIn should have only one bit set for each shader invocation.\n"
801                 << tcu::TestLog::EndMessage;
802
803         MultisampleCaseBase::init();
804 }
805
806 template<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const
807 {
808         MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
809
810         // Create vertex shader
811         std::ostringstream vs;
812
813         vs << "#version 440\n"
814                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
815                 << "\n"
816                 << "out gl_PerVertex {\n"
817                 << "    vec4  gl_Position;\n"
818                 << "};\n"
819                 << "void main (void)\n"
820                 << "{\n"
821                 << "    gl_Position     = vs_in_position_ndc;\n"
822                 << "}\n";
823
824         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
825
826         // Create fragment shader
827         std::ostringstream fs;
828
829         fs << "#version 440\n"
830                 << "\n"
831                 << "layout(location = 0) out vec4 fs_out_color;\n"
832                 << "\n"
833                 << "void main (void)\n"
834                 << "{\n"
835                 << "    uint maskBitCount = 0u;\n"
836                 << "\n"
837                 << "    for (int i = 0; i < 32; ++i)\n"
838                 << "            if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
839                 << "                    ++maskBitCount;\n"
840                 << "\n"
841                 << "    if (maskBitCount != 1u)\n"
842                 << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
843                 << "    else\n"
844                 << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
845                 << "}\n";
846
847         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
848 }
849
850 template<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const
851 {
852         return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams);
853 }
854
855 class MSInstanceSampleMaskCorrectBit;
856
857 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const
858 {
859         return getVertexDataDescriptonNdc();
860 }
861
862 template<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
863 {
864         uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
865 }
866
867 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData  (const vk::VkImageCreateInfo&                                           imageMSInfo,
868                                                                                                                                                                                  const vk::VkImageCreateInfo&                                           imageRSInfo,
869                                                                                                                                                                                  const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
870                                                                                                                                                                                  const tcu::ConstPixelBufferAccess&                                     dataRS) const
871 {
872         DE_UNREF(imageRSInfo);
873         DE_UNREF(dataRS);
874
875         if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
876                 return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn");
877
878         return tcu::TestStatus::pass("Passed");
879 }
880
881 class MSCaseSampleMaskCorrectBit;
882
883 template<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void)
884 {
885         m_testCtx.getLog()
886                 << tcu::TestLog::Message
887                 << "Verifying gl_SampleMaskIn.\n"
888                 << "    Fragment shader will be invoked numSamples times.\n"
889                 << "    => In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n"
890                 << tcu::TestLog::EndMessage;
891
892         MultisampleCaseBase::init();
893 }
894
895 template<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const
896 {
897         MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
898
899         // Create vertex shader
900         std::ostringstream vs;
901
902         vs << "#version 440\n"
903                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
904                 << "\n"
905                 << "out gl_PerVertex {\n"
906                 << "    vec4  gl_Position;\n"
907                 << "};\n"
908                 << "void main (void)\n"
909                 << "{\n"
910                 << "    gl_Position     = vs_in_position_ndc;\n"
911                 << "}\n";
912
913         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
914
915         // Create fragment shader
916         std::ostringstream fs;
917
918         fs << "#version 440\n"
919                 << "\n"
920                 << "layout(location = 0) out vec4 fs_out_color;\n"
921                 << "\n"
922                 << "void main (void)\n"
923                 << "{\n"
924                 << "    if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n"
925                 << "            fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
926                 << "    else\n"
927                 << "            fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
928                 << "}\n";
929
930         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
931 }
932
933 template<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const
934 {
935         return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams);
936 }
937
938 class MSInstanceSampleMaskWrite;
939
940 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const
941 {
942         return getVertexDataDescriptonNdc();
943 }
944
945 template<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
946 {
947         uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
948 }
949
950 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData       (const vk::VkImageCreateInfo&                                           imageMSInfo,
951                                                                                                                                                                          const vk::VkImageCreateInfo&                                           imageRSInfo,
952                                                                                                                                                                          const std::vector<tcu::ConstPixelBufferAccess>&        dataPerSample,
953                                                                                                                                                                          const tcu::ConstPixelBufferAccess&                                     dataRS) const
954 {
955         const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
956
957         for (deUint32 z = 0u; z < imageMSInfo.extent.depth;  ++z)
958         for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
959         for (deUint32 x = 0u; x < imageMSInfo.extent.width;  ++x)
960         {
961                 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
962                 {
963                         const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0];
964
965                         if (firstComponent != 0u && firstComponent != 255u)
966                                 return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel");
967                 }
968         }
969
970         for (deUint32 z = 0u; z < imageRSInfo.extent.depth;  ++z)
971         for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
972         for (deUint32 x = 0u; x < imageRSInfo.extent.width;  ++x)
973         {
974                 const float firstComponent = dataRS.getPixel(x, y, z)[0];
975
976                 if (deFloatAbs(firstComponent - 0.5f) > 0.02f)
977                         return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel");
978         }
979
980         return tcu::TestStatus::pass("Passed");
981 }
982
983 class MSCaseSampleMaskWrite;
984
985 template<> void MSCase<MSCaseSampleMaskWrite>::init (void)
986 {
987         m_testCtx.getLog()
988                 << tcu::TestLog::Message
989                 << "Discarding half of the samples using gl_SampleMask."
990                 << "Expecting half intensity on multisample targets (numSamples > 1)\n"
991                 << tcu::TestLog::EndMessage;
992
993         MultisampleCaseBase::init();
994 }
995
996 template<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const
997 {
998         MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
999
1000         // Create vertex shader
1001         std::ostringstream vs;
1002
1003         vs << "#version 440\n"
1004                 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1005                 << "\n"
1006                 << "out gl_PerVertex {\n"
1007                 << "    vec4  gl_Position;\n"
1008                 << "};\n"
1009                 << "void main (void)\n"
1010                 << "{\n"
1011                 << "    gl_Position     = vs_in_position_ndc;\n"
1012                 << "}\n";
1013
1014         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1015
1016         // Create fragment shader
1017         std::ostringstream fs;
1018
1019         fs << "#version 440\n"
1020                 << "\n"
1021                 << "layout(location = 0) out vec4 fs_out_color;\n"
1022                 << "\n"
1023                 << "void main (void)\n"
1024                 << "{\n"
1025                 << "    gl_SampleMask[0] = 0xAAAAAAAA;\n"
1026                 << "\n"
1027                 << "    fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1028                 << "}\n";
1029
1030         programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1031 }
1032
1033 template<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const
1034 {
1035         return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams);
1036 }
1037
1038 } // multisample
1039
1040 tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx)
1041 {
1042         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin", "Multisample Shader BuiltIn Tests"));
1043
1044         const tcu::UVec3 imageSizes[] =
1045         {
1046                 tcu::UVec3(128u, 128u, 1u),
1047                 tcu::UVec3(137u, 191u, 1u),
1048         };
1049
1050         const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1051
1052         const vk::VkSampleCountFlagBits samplesSetFull[] =
1053         {
1054                 vk::VK_SAMPLE_COUNT_2_BIT,
1055                 vk::VK_SAMPLE_COUNT_4_BIT,
1056                 vk::VK_SAMPLE_COUNT_8_BIT,
1057                 vk::VK_SAMPLE_COUNT_16_BIT,
1058                 vk::VK_SAMPLE_COUNT_32_BIT,
1059                 vk::VK_SAMPLE_COUNT_64_BIT,
1060         };
1061
1062         const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits));
1063
1064         testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
1065
1066         de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position", "Sample Position Tests"));
1067
1068         samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
1069         samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness",  imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
1070
1071         testGroup->addChild(samplePositionGroup.release());
1072
1073         const vk::VkSampleCountFlagBits samplesSetReduced[] =
1074         {
1075                 vk::VK_SAMPLE_COUNT_2_BIT,
1076                 vk::VK_SAMPLE_COUNT_4_BIT,
1077                 vk::VK_SAMPLE_COUNT_8_BIT,
1078                 vk::VK_SAMPLE_COUNT_16_BIT,
1079                 vk::VK_SAMPLE_COUNT_32_BIT,
1080         };
1081
1082         const deUint32 samplesSetReducedCount = static_cast<deUint32>(sizeof(samplesSetReduced) / sizeof(vk::VkSampleCountFlagBits));
1083
1084         de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask", "Sample Mask Tests"));
1085
1086         sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> >       (testCtx, "pattern",    imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1087         sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> >      (testCtx, "bit_count",  imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1088         sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit",imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1089         sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> >         (testCtx, "write",              imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
1090
1091         testGroup->addChild(sampleMaskGroup.release());
1092
1093         return testGroup.release();
1094 }
1095
1096 } // pipeline
1097 } // vkt