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