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
28 #include "vkBuilderUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkImageWithMemory.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkTypeUtil.hpp"
36
37 #include "tcuVectorUtil.hpp"
38 #include "tcuTestLog.hpp"
39
40 #include <set>
41
42 using std::set;
43
44 namespace vkt
45 {
46 namespace pipeline
47 {
48 namespace multisample
49 {
50
51 using namespace vk;
52
53 struct VertexDataNdc
54 {
VertexDataNdcvkt::pipeline::multisample::VertexDataNdc55 VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
56
57 tcu::Vec4 positionNdc;
58 };
59
getVertexDataDescriptonNdc(void)60 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void)
61 {
62 MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
63
64 vertexDataDesc.verticesCount = 4u;
65 vertexDataDesc.dataStride = sizeof(VertexDataNdc);
66 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
67 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
68
69 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
70 {
71 0u, // deUint32 location;
72 0u, // deUint32 binding;
73 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
74 DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset;
75 };
76
77 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
78
79 return vertexDataDesc;
80 }
81
uploadVertexDataNdc(const Allocation & vertexBufferAllocation,const MultisampleInstanceBase::VertexDataDesc & vertexDataDescripton)82 void uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton)
83 {
84 std::vector<VertexDataNdc> vertices;
85
86 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)));
87 vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)));
88 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f)));
89 vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f)));
90
91 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
92 }
93
94 struct VertexDataNdcScreen
95 {
VertexDataNdcScreenvkt::pipeline::multisample::VertexDataNdcScreen96 VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
97
98 tcu::Vec4 positionNdc;
99 tcu::Vec2 positionScreen;
100 };
101
getVertexDataDescriptonNdcScreen(void)102 MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void)
103 {
104 MultisampleInstanceBase::VertexDataDesc vertexDataDesc;
105
106 vertexDataDesc.verticesCount = 4u;
107 vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen);
108 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
109 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
110
111 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
112 {
113 0u, // deUint32 location;
114 0u, // deUint32 binding;
115 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
116 DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset;
117 };
118
119 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
120
121 const VkVertexInputAttributeDescription vertexAttribPositionScreen =
122 {
123 1u, // deUint32 location;
124 0u, // deUint32 binding;
125 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
126 DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset;
127 };
128
129 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
130
131 return vertexDataDesc;
132 }
133
uploadVertexDataNdcScreen(const Allocation & vertexBufferAllocation,const MultisampleInstanceBase::VertexDataDesc & vertexDataDescripton,const tcu::Vec2 & screenSize)134 void uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize)
135 {
136 std::vector<VertexDataNdcScreen> vertices;
137
138 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
139 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f)));
140 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y())));
141 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y())));
142
143 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
144 }
145
checkForErrorMS(const vk::VkImageCreateInfo & imageMSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const deUint32 errorCompNdx)146 bool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx)
147 {
148 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
149
150 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z)
151 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
152 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x)
153 {
154 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
155 {
156 const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx];
157
158 if (errorComponent > 0)
159 return true;
160 }
161 }
162
163 return false;
164 }
165
checkForErrorRS(const vk::VkImageCreateInfo & imageRSInfo,const tcu::ConstPixelBufferAccess & dataRS,const deUint32 errorCompNdx)166 bool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx)
167 {
168 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z)
169 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
170 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x)
171 {
172 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx];
173
174 if (errorComponent > 0)
175 return true;
176 }
177
178 return false;
179 }
180
181 template <typename CaseClassName>
182 class MSCase : public MSCaseBaseResolveAndPerSampleFetch
183 {
184 public:
MSCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)185 MSCase (tcu::TestContext& testCtx,
186 const std::string& name,
187 const ImageMSParams& imageMSParams)
188 : MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {}
189
checkSupport(Context &) const190 virtual void checkSupport (Context&) const {}
191 void init (void);
192 void initPrograms (vk::SourceCollections& programCollection) const;
193 TestInstance* createInstance (Context& context) const;
194 static MultisampleCaseBase* createCase (tcu::TestContext& testCtx,
195 const std::string& name,
196 const ImageMSParams& imageMSParams);
197 };
198
199 template <typename CaseClassName>
createCase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)200 MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
201 {
202 return new MSCase<CaseClassName>(testCtx, name, imageMSParams);
203 }
204
205 template <typename InstanceClassName>
206 class MSInstance : public MSInstanceBaseResolveAndPerSampleFetch
207 {
208 public:
MSInstance(Context & context,const ImageMSParams & imageMSParams)209 MSInstance (Context& context,
210 const ImageMSParams& imageMSParams)
211 : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {}
212
213 VertexDataDesc getVertexDataDescripton (void) const;
214 void uploadVertexData (const Allocation& vertexBufferAllocation,
215 const VertexDataDesc& vertexDataDescripton) const;
216
217 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
218 const vk::VkImageCreateInfo& imageRSInfo,
219 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
220 const tcu::ConstPixelBufferAccess& dataRS) const;
221
getMSStateCreateInfo(const ImageMSParams & imageMSParams) const222 virtual VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
223 {
224 return MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo(imageMSParams);
225 }
226 };
227
228 class MSInstanceSampleID;
229
getVertexDataDescripton(void) const230 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const
231 {
232 return getVertexDataDescriptonNdc();
233 }
234
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const235 template<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
236 {
237 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
238 }
239
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const240 template<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
241 const vk::VkImageCreateInfo& imageRSInfo,
242 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
243 const tcu::ConstPixelBufferAccess& dataRS) const
244 {
245 DE_UNREF(imageRSInfo);
246 DE_UNREF(dataRS);
247
248 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
249
250 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
251 {
252 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z)
253 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
254 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x)
255 {
256 const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x();
257
258 if (sampleID != sampleNdx)
259 return tcu::TestStatus::fail("gl_SampleID does not have correct value");
260 }
261 }
262
263 return tcu::TestStatus::pass("Passed");
264 }
265
266 class MSCaseSampleID;
267
checkSupport(Context & context) const268 template<> void MSCase<MSCaseSampleID>::checkSupport (Context& context) const
269 {
270 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
271 }
272
init(void)273 template<> void MSCase<MSCaseSampleID>::init (void)
274 {
275 m_testCtx.getLog()
276 << tcu::TestLog::Message
277 << "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n"
278 << "Expecting value N at sample index N of a multisample texture.\n"
279 << tcu::TestLog::EndMessage;
280
281 MultisampleCaseBase::init();
282 }
283
initPrograms(vk::SourceCollections & programCollection) const284 template<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const
285 {
286 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
287
288 // Create vertex shader
289 std::ostringstream vs;
290
291 vs << "#version 440\n"
292 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
293 << "\n"
294 << "out gl_PerVertex {\n"
295 << " vec4 gl_Position;\n"
296 << "};\n"
297 << "void main (void)\n"
298 << "{\n"
299 << " gl_Position = vs_in_position_ndc;\n"
300 << "}\n";
301
302 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
303
304 // Create fragment shader
305 std::ostringstream fs;
306
307 fs << "#version 440\n"
308 << "\n"
309 << "layout(location = 0) out vec4 fs_out_color;\n"
310 << "\n"
311 << "void main (void)\n"
312 << "{\n"
313 << " fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n"
314 << "}\n";
315
316 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
317 }
318
createInstance(Context & context) const319 template<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const
320 {
321 return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams);
322 }
323
324 class MSInstanceSamplePosDistribution;
325
getVertexDataDescripton(void) const326 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const
327 {
328 return getVertexDataDescriptonNdc();
329 }
330
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const331 template<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
332 {
333 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
334 }
335
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const336 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
337 const vk::VkImageCreateInfo& imageRSInfo,
338 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
339 const tcu::ConstPixelBufferAccess& dataRS) const
340 {
341 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
342
343 // approximate Bates distribution as normal
344 const float variance = (1.0f / (12.0f * (float)numSamples));
345 const float standardDeviation = deFloatSqrt(variance);
346
347 // 95% of means of sample positions are within 2 standard deviations if
348 // they were randomly assigned. Sample patterns are expected to be more
349 // uniform than a random pattern.
350 const float distanceThreshold = 2.0f * standardDeviation;
351
352 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z)
353 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
354 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x)
355 {
356 const deUint32 errorComponent = dataRS.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 if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
362 {
363 const tcu::Vec2 averageSamplePos = tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f);
364 const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
365
366 if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
367 return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
368 }
369 }
370
371 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z)
372 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
373 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x)
374 {
375 std::vector<tcu::Vec2> samplePositions(numSamples);
376
377 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
378 {
379 const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z();
380
381 if (errorComponent > 0)
382 return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]");
383
384 samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f,
385 (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f);
386 }
387
388 for (deUint32 sampleNdxA = 0u; sampleNdxA < numSamples; ++sampleNdxA)
389 for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB)
390 {
391 if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB])
392 return tcu::TestStatus::fail("Two samples have the same position");
393 }
394
395 if (numSamples >= VK_SAMPLE_COUNT_4_BIT)
396 {
397 tcu::Vec2 averageSamplePos(0.0f, 0.0f);
398
399 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
400 {
401 averageSamplePos.x() += samplePositions[sampleNdx].x();
402 averageSamplePos.y() += samplePositions[sampleNdx].y();
403 }
404
405 averageSamplePos.x() /= (float)numSamples;
406 averageSamplePos.y() /= (float)numSamples;
407
408 const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f));
409
410 if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold)
411 return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel");
412 }
413 }
414
415 return tcu::TestStatus::pass("Passed");
416 }
417
418 class MSCaseSamplePosDistribution;
419
checkSupport(Context & context) const420 template<> void MSCase<MSCaseSamplePosDistribution>::checkSupport (Context& context) const
421 {
422 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
423 }
424
init(void)425 template<> void MSCase<MSCaseSamplePosDistribution>::init (void)
426 {
427 m_testCtx.getLog()
428 << tcu::TestLog::Message
429 << "Verifying gl_SamplePosition value with multisample targets:\n"
430 << " a) Expect legal sample position.\n"
431 << " b) Sample position is unique within the set of all sample positions of a pixel.\n"
432 << " c) Sample position distribution is uniform or almost uniform.\n"
433 << tcu::TestLog::EndMessage;
434
435 MultisampleCaseBase::init();
436 }
437
initPrograms(vk::SourceCollections & programCollection) const438 template<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const
439 {
440 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
441
442 // Create vertex shader
443 std::ostringstream vs;
444
445 vs << "#version 440\n"
446 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
447 << "\n"
448 << "out gl_PerVertex {\n"
449 << " vec4 gl_Position;\n"
450 << "};\n"
451 << "void main (void)\n"
452 << "{\n"
453 << " gl_Position = vs_in_position_ndc;\n"
454 << "}\n";
455
456 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
457
458 // Create fragment shader
459 std::ostringstream fs;
460
461 fs << "#version 440\n"
462 << "\n"
463 << "layout(location = 0) out vec4 fs_out_color;\n"
464 << "\n"
465 << "void main (void)\n"
466 << "{\n"
467 << " if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n"
468 " fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
469 " else\n"
470 " fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n"
471 "}\n";
472
473 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
474 }
475
createInstance(Context & context) const476 template<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const
477 {
478 return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams);
479 }
480
481 class MSInstanceSamplePosCorrectness;
482
getVertexDataDescripton(void) const483 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const
484 {
485 return getVertexDataDescriptonNdcScreen();
486 }
487
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const488 template<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
489 {
490 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
491
492 uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y())));
493 }
494
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const495 template<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
496 const vk::VkImageCreateInfo& imageRSInfo,
497 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
498 const tcu::ConstPixelBufferAccess& dataRS) const
499 {
500 if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
501 return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
502
503 if (checkForErrorRS(imageRSInfo, dataRS, 0))
504 return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition");
505
506 return tcu::TestStatus::pass("Passed");
507 }
508
509 class MSCaseSamplePosCorrectness;
510
checkSupport(Context & context) const511 template<> void MSCase<MSCaseSamplePosCorrectness>::checkSupport (Context& context) const
512 {
513 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
514 }
515
init(void)516 template<> void MSCase<MSCaseSamplePosCorrectness>::init (void)
517 {
518 m_testCtx.getLog()
519 << tcu::TestLog::Message
520 << "Verifying gl_SamplePosition correctness:\n"
521 << " 1) Varying values should be sampled at the sample position.\n"
522 << " => fract(position_screen) == gl_SamplePosition\n"
523 << tcu::TestLog::EndMessage;
524
525 MultisampleCaseBase::init();
526 }
527
initPrograms(vk::SourceCollections & programCollection) const528 template<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const
529 {
530 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
531
532 // Create vertex shaders
533 std::ostringstream vs;
534
535 vs << "#version 440\n"
536 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
537 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
538 << "\n"
539 << "layout(location = 0) sample out vec2 vs_out_position_screen;\n"
540 << "\n"
541 << "out gl_PerVertex {\n"
542 << " vec4 gl_Position;\n"
543 << "};\n"
544 << "void main (void)\n"
545 << "{\n"
546 << " gl_Position = vs_in_position_ndc;\n"
547 << " vs_out_position_screen = vs_in_position_screen;\n"
548 << "}\n";
549
550 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
551
552 // Create fragment shader
553 std::ostringstream fs;
554
555 fs << "#version 440\n"
556 << "layout(location = 0) sample in vec2 fs_in_position_screen;\n"
557 << "\n"
558 << "layout(location = 0) out vec4 fs_out_color;\n"
559 << "\n"
560 << "void main (void)\n"
561 << "{\n"
562 << " const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"
563 << " const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n"
564 << " bool ok = false;\n"
565 << "\n"
566 << " // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n"
567 << " // check all neighbors for any match\n"
568 << " for (int dy = -1; dy <= 1; ++dy)\n"
569 << " for (int dx = -1; dx <= 1; ++dx)\n"
570 << " {\n"
571 << " ivec2 current_pixel = nearby_pixel + ivec2(dx, dy);\n"
572 << " vec2 position_inside_pixel = vec2(current_pixel) + gl_SamplePosition;\n"
573 << " vec2 position_diff = abs(position_inside_pixel - fs_in_position_screen);\n"
574 << "\n"
575 << " if (all(lessThan(position_diff, vec2(threshold))))\n"
576 << " ok = true;\n"
577 << " }\n"
578 << "\n"
579 << " if (ok)\n"
580 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
581 << " else\n"
582 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
583 << "}\n";
584
585 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
586 }
587
createInstance(Context & context) const588 template<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const
589 {
590 return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams);
591 }
592
593 class MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch
594 {
595 public:
596 MSInstanceSampleMaskPattern (Context& context,
597 const ImageMSParams& imageMSParams);
598
599 VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const;
600
601 const VkDescriptorSetLayout* createMSPassDescSetLayout (const ImageMSParams& imageMSParams);
602
603 const VkDescriptorSet* createMSPassDescSet (const ImageMSParams& imageMSParams,
604 const VkDescriptorSetLayout* descSetLayout);
605
606 VertexDataDesc getVertexDataDescripton (void) const;
607
608 void uploadVertexData (const Allocation& vertexBufferAllocation,
609 const VertexDataDesc& vertexDataDescripton) const;
610
611 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
612 const vk::VkImageCreateInfo& imageRSInfo,
613 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
614 const tcu::ConstPixelBufferAccess& dataRS) const;
615 protected:
616
617 VkSampleMask m_sampleMask;
618 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
619 Move<VkDescriptorPool> m_descriptorPool;
620 Move<VkDescriptorSet> m_descriptorSet;
621 de::MovePtr<Buffer> m_buffer;
622 };
623
MSInstanceSampleMaskPattern(Context & context,const ImageMSParams & imageMSParams)624 MSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams)
625 {
626 m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u);
627 }
628
getMSStateCreateInfo(const ImageMSParams & imageMSParams) const629 VkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
630 {
631 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
632 {
633 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
634 DE_NULL, // const void* pNext;
635 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags;
636 imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples;
637 VK_FALSE, // VkBool32 sampleShadingEnable;
638 1.0f, // float minSampleShading;
639 &m_sampleMask, // const VkSampleMask* pSampleMask;
640 VK_FALSE, // VkBool32 alphaToCoverageEnable;
641 VK_FALSE, // VkBool32 alphaToOneEnable;
642 };
643
644 return multisampleStateInfo;
645 }
646
createMSPassDescSetLayout(const ImageMSParams & imageMSParams)647 const VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams)
648 {
649 DE_UNREF(imageMSParams);
650
651 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
652 const VkDevice device = m_context.getDevice();
653
654 // Create descriptor set layout
655 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
656 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
657 .build(deviceInterface, device);
658
659 return &m_descriptorSetLayout.get();
660 }
661
createMSPassDescSet(const ImageMSParams & imageMSParams,const VkDescriptorSetLayout * descSetLayout)662 const VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
663 {
664 DE_UNREF(imageMSParams);
665
666 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
667 const VkDevice device = m_context.getDevice();
668 Allocator& allocator = m_context.getDefaultAllocator();
669
670 // Create descriptor pool
671 m_descriptorPool = DescriptorPoolBuilder()
672 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
673 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
674
675 // Create descriptor set
676 m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout);
677
678 const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
679
680 m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible));
681
682 deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask));
683
684 flushAlloc(deviceInterface, device, m_buffer->getAllocation());
685
686 const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask));
687
688 DescriptorSetUpdateBuilder()
689 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo)
690 .update(deviceInterface, device);
691
692 return &m_descriptorSet.get();
693 }
694
getVertexDataDescripton(void) const695 MultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const
696 {
697 return getVertexDataDescriptonNdc();
698 }
699
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const700 void MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
701 {
702 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
703 }
704
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const705 tcu::TestStatus MSInstanceSampleMaskPattern::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
706 const vk::VkImageCreateInfo& imageRSInfo,
707 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
708 const tcu::ConstPixelBufferAccess& dataRS) const
709 {
710 DE_UNREF(imageRSInfo);
711 DE_UNREF(dataRS);
712
713 if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
714 return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state");
715
716 return tcu::TestStatus::pass("Passed");
717 }
718
719 class MSCaseSampleMaskPattern;
720
init(void)721 template<> void MSCase<MSCaseSampleMaskPattern>::init (void)
722 {
723 m_testCtx.getLog()
724 << tcu::TestLog::Message
725 << "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"
726 << "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n"
727 << tcu::TestLog::EndMessage;
728
729 MultisampleCaseBase::init();
730 }
731
initPrograms(vk::SourceCollections & programCollection) const732 template<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const
733 {
734 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
735
736 // Create vertex shader
737 std::ostringstream vs;
738
739 vs << "#version 440\n"
740 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
741 << "\n"
742 << "out gl_PerVertex {\n"
743 << " vec4 gl_Position;\n"
744 << "};\n"
745 << "void main (void)\n"
746 << "{\n"
747 << " gl_Position = vs_in_position_ndc;\n"
748 << "}\n";
749
750 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
751
752 // Create fragment shader
753 std::ostringstream fs;
754
755 fs << "#version 440\n"
756 << "\n"
757 << "layout(location = 0) out vec4 fs_out_color;\n"
758 << "\n"
759 << "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n"
760 << "{\n"
761 << " int sampleMaskPattern;\n"
762 << "};"
763 << "\n"
764 << "void main (void)\n"
765 << "{\n"
766 << " if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n"
767 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
768 << " else\n"
769 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
770 << "}\n";
771
772 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
773 }
774
createInstance(Context & context) const775 template<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const
776 {
777 return new MSInstanceSampleMaskPattern(context, m_imageMSParams);
778 }
779
780 class MSInstanceSampleMaskBitCount;
781
getVertexDataDescripton(void) const782 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const
783 {
784 return getVertexDataDescriptonNdc();
785 }
786
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const787 template<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
788 {
789 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
790 }
791
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const792 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
793 const vk::VkImageCreateInfo& imageRSInfo,
794 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
795 const tcu::ConstPixelBufferAccess& dataRS) const
796 {
797 DE_UNREF(imageRSInfo);
798 DE_UNREF(dataRS);
799
800 if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
801 return tcu::TestStatus::fail("gl_SampleMaskIn has more than one bit set for some shader invocations");
802
803 return tcu::TestStatus::pass("Passed");
804 }
805
806 class MSCaseSampleMaskBitCount;
807
checkSupport(Context & context) const808 template<> void MSCase<MSCaseSampleMaskBitCount>::checkSupport (Context& context) const
809 {
810 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
811 }
812
init(void)813 template<> void MSCase<MSCaseSampleMaskBitCount>::init (void)
814 {
815 m_testCtx.getLog()
816 << tcu::TestLog::Message
817 << "Verifying gl_SampleMaskIn.\n"
818 << " Fragment shader will be invoked numSamples times.\n"
819 << " => gl_SampleMaskIn should have only one bit set for each shader invocation.\n"
820 << tcu::TestLog::EndMessage;
821
822 MultisampleCaseBase::init();
823 }
824
initPrograms(vk::SourceCollections & programCollection) const825 template<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const
826 {
827 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
828
829 // Create vertex shader
830 std::ostringstream vs;
831
832 vs << "#version 440\n"
833 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
834 << "\n"
835 << "out gl_PerVertex {\n"
836 << " vec4 gl_Position;\n"
837 << "};\n"
838 << "void main (void)\n"
839 << "{\n"
840 << " gl_Position = vs_in_position_ndc;\n"
841 << "}\n";
842
843 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
844
845 // Create fragment shader
846 std::ostringstream fs;
847
848 fs << "#version 440\n"
849 << "\n"
850 << "layout(location = 0) out vec4 fs_out_color;\n"
851 << "\n"
852 << "void main (void)\n"
853 << "{\n"
854 << " uint maskBitCount = 0u;\n"
855 << "\n"
856 << " for (int i = 0; i < 32; ++i)\n"
857 << " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n"
858 << " ++maskBitCount;\n"
859 << "\n"
860 << " if (maskBitCount != 1u)\n"
861 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
862 << " else\n"
863 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
864 << "}\n";
865
866 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
867 }
868
createInstance(Context & context) const869 template<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const
870 {
871 return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams);
872 }
873
874 class MSInstanceSampleMaskCorrectBit;
875
getVertexDataDescripton(void) const876 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const
877 {
878 return getVertexDataDescriptonNdc();
879 }
880
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const881 template<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
882 {
883 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
884 }
885
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const886 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
887 const vk::VkImageCreateInfo& imageRSInfo,
888 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
889 const tcu::ConstPixelBufferAccess& dataRS) const
890 {
891 DE_UNREF(imageRSInfo);
892 DE_UNREF(dataRS);
893
894 if (checkForErrorMS(imageMSInfo, dataPerSample, 0))
895 return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn");
896
897 return tcu::TestStatus::pass("Passed");
898 }
899
900 class MSCaseSampleMaskCorrectBit;
901
checkSupport(Context & context) const902 template<> void MSCase<MSCaseSampleMaskCorrectBit>::checkSupport (Context& context) const
903 {
904 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
905 }
906
init(void)907 template<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void)
908 {
909 m_testCtx.getLog()
910 << tcu::TestLog::Message
911 << "Verifying gl_SampleMaskIn.\n"
912 << " Fragment shader will be invoked numSamples times.\n"
913 << " => In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n"
914 << tcu::TestLog::EndMessage;
915
916 MultisampleCaseBase::init();
917 }
918
initPrograms(vk::SourceCollections & programCollection) const919 template<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const
920 {
921 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
922
923 // Create vertex shader
924 std::ostringstream vs;
925
926 vs << "#version 440\n"
927 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
928 << "\n"
929 << "out gl_PerVertex {\n"
930 << " vec4 gl_Position;\n"
931 << "};\n"
932 << "void main (void)\n"
933 << "{\n"
934 << " gl_Position = vs_in_position_ndc;\n"
935 << "}\n";
936
937 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
938
939 // Create fragment shader
940 std::ostringstream fs;
941
942 fs << "#version 440\n"
943 << "\n"
944 << "layout(location = 0) out vec4 fs_out_color;\n"
945 << "\n"
946 << "void main (void)\n"
947 << "{\n"
948 << " if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n"
949 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
950 << " else\n"
951 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
952 << "}\n";
953
954 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
955 }
956
createInstance(Context & context) const957 template<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const
958 {
959 return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams);
960 }
961
962 class MSInstanceSampleMaskWrite;
963
getVertexDataDescripton(void) const964 template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const
965 {
966 return getVertexDataDescriptonNdc();
967 }
968
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const969 template<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
970 {
971 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton);
972 }
973
974 //! Creates VkPipelineMultisampleStateCreateInfo with sample shading disabled.
getMSStateCreateInfo(const ImageMSParams & imageMSParams) const975 template<> VkPipelineMultisampleStateCreateInfo MSInstance<MSInstanceSampleMaskWrite>::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
976 {
977 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
978 {
979 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
980 DE_NULL, // const void* pNext;
981 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags;
982 imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples;
983 VK_FALSE, // VkBool32 sampleShadingEnable;
984 0.0f, // float minSampleShading;
985 DE_NULL, // const VkSampleMask* pSampleMask;
986 VK_FALSE, // VkBool32 alphaToCoverageEnable;
987 VK_FALSE, // VkBool32 alphaToOneEnable;
988 };
989
990 return multisampleStateInfo;
991 }
992
verifyImageData(const vk::VkImageCreateInfo & imageMSInfo,const vk::VkImageCreateInfo & imageRSInfo,const std::vector<tcu::ConstPixelBufferAccess> & dataPerSample,const tcu::ConstPixelBufferAccess & dataRS) const993 template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo,
994 const vk::VkImageCreateInfo& imageRSInfo,
995 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample,
996 const tcu::ConstPixelBufferAccess& dataRS) const
997 {
998 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
999
1000 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z)
1001 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y)
1002 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x)
1003 {
1004 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
1005 {
1006 const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0];
1007
1008 if (firstComponent != 0u && firstComponent != 255u)
1009 return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel");
1010 }
1011 }
1012
1013 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z)
1014 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y)
1015 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x)
1016 {
1017 const float firstComponent = dataRS.getPixel(x, y, z)[0];
1018
1019 if (deFloatAbs(firstComponent - 0.5f) > 0.02f)
1020 return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel");
1021 }
1022
1023 return tcu::TestStatus::pass("Passed");
1024 }
1025
1026 class MSCaseSampleMaskWrite;
1027
init(void)1028 template<> void MSCase<MSCaseSampleMaskWrite>::init (void)
1029 {
1030 m_testCtx.getLog()
1031 << tcu::TestLog::Message
1032 << "Discarding half of the samples using gl_SampleMask."
1033 << "Expecting half intensity on multisample targets (numSamples > 1)\n"
1034 << tcu::TestLog::EndMessage;
1035
1036 MultisampleCaseBase::init();
1037 }
1038
initPrograms(vk::SourceCollections & programCollection) const1039 template<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const
1040 {
1041 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection);
1042
1043 // Create vertex shader
1044 std::ostringstream vs;
1045
1046 vs << "#version 440\n"
1047 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1048 << "\n"
1049 << "out gl_PerVertex {\n"
1050 << " vec4 gl_Position;\n"
1051 << "};\n"
1052 << "void main (void)\n"
1053 << "{\n"
1054 << " gl_Position = vs_in_position_ndc;\n"
1055 << "}\n";
1056
1057 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1058
1059 // Create fragment shader
1060 std::ostringstream fs;
1061
1062 fs << "#version 440\n"
1063 << "\n"
1064 << "layout(location = 0) out vec4 fs_out_color;\n"
1065 << "\n"
1066 << "void main (void)\n"
1067 << "{\n"
1068 << " gl_SampleMask[0] = 0xAAAAAAAA;\n"
1069 << "\n"
1070 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1071 << "}\n";
1072
1073 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1074 }
1075
createInstance(Context & context) const1076 template<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const
1077 {
1078 return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams);
1079 }
1080
1081 const set<deUint32> kValidSquareSampleCounts =
1082 {
1083 vk::VK_SAMPLE_COUNT_1_BIT,
1084 vk::VK_SAMPLE_COUNT_2_BIT,
1085 vk::VK_SAMPLE_COUNT_4_BIT,
1086 vk::VK_SAMPLE_COUNT_8_BIT,
1087 vk::VK_SAMPLE_COUNT_16_BIT,
1088 };
1089
assertSquareSampleCount(deUint32 sampleCount)1090 void assertSquareSampleCount (deUint32 sampleCount)
1091 {
1092 DE_ASSERT(kValidSquareSampleCounts.find(sampleCount) != kValidSquareSampleCounts.end());
1093 DE_UNREF(sampleCount); // for release builds.
1094 }
1095
1096 // When dealing with N samples, each coordinate (x, y) will be used to decide which samples will be written to, using N/2 bits for
1097 // each of the X and Y values. Take into account this returns 0 for 1 sample.
bitsPerCoord(deUint32 numSamples)1098 deUint32 bitsPerCoord (deUint32 numSamples)
1099 {
1100 assertSquareSampleCount(numSamples);
1101 return (numSamples / 2u);
1102 }
1103
1104 // These tests will try to verify all write or mask bit combinations for the given sample count, and will verify one combination per
1105 // image pixel. This means the following image sizes need to be used:
1106 // - 2 samples: 2x2
1107 // - 4 samples: 4x4
1108 // - 8 samples: 16x16
1109 // - 16 samples: 256x256
1110 // In other words, images will be square with 2^(samples-1) pixels on each side.
imageSize(deUint32 sampleCount)1111 vk::VkExtent2D imageSize (deUint32 sampleCount)
1112 {
1113 assertSquareSampleCount(sampleCount);
1114
1115 // Special case: 2x1 image (not actually square).
1116 if (sampleCount == vk::VK_SAMPLE_COUNT_1_BIT)
1117 return vk::VkExtent2D{2u, 1u};
1118
1119 // Other cases: square image as described above.
1120 const auto dim = (1u<<(sampleCount>>1u));
1121 return vk::VkExtent2D{dim, dim};
1122 }
1123
getExtent3D(deUint32 sampleCount)1124 vk::VkExtent3D getExtent3D (deUint32 sampleCount)
1125 {
1126 const auto size = imageSize(sampleCount);
1127 return vk::VkExtent3D{size.width, size.height, 1u};
1128 }
1129
getShaderDecl(const tcu::Vec4 & color)1130 std::string getShaderDecl (const tcu::Vec4& color)
1131 {
1132 std::ostringstream declaration;
1133 declaration << "vec4(" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
1134 return declaration.str();
1135 }
1136
1137 struct WriteSampleParams
1138 {
1139 vk::VkSampleCountFlagBits sampleCount;
1140 };
1141
1142 class WriteSampleTest : public vkt::TestCase
1143 {
1144 public:
WriteSampleTest(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,const WriteSampleParams & params)1145 WriteSampleTest (tcu::TestContext& testCtx, const std::string& name, const std::string& desc, const WriteSampleParams& params)
1146 : vkt::TestCase(testCtx, name, desc), m_params(params)
1147 {}
~WriteSampleTest(void)1148 virtual ~WriteSampleTest (void) {}
1149
1150 virtual void initPrograms (vk::SourceCollections& programCollection) const;
1151 virtual vkt::TestInstance* createInstance (Context& context) const;
1152 virtual void checkSupport (Context& context) const;
1153
1154 static const tcu::Vec4 kClearColor;
1155 static const tcu::Vec4 kBadColor;
1156 static const tcu::Vec4 kGoodColor;
1157 static const tcu::Vec4 kWriteColor;
1158
1159 static constexpr vk::VkFormat kImageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
1160
1161 // Keep these two in sync.
1162 static constexpr vk::VkImageUsageFlags kUsageFlags = (vk::VK_IMAGE_USAGE_STORAGE_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
1163 static constexpr vk::VkFormatFeatureFlags kFeatureFlags = (vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
1164
1165 private:
1166 WriteSampleParams m_params;
1167 };
1168
1169 const tcu::Vec4 WriteSampleTest::kClearColor {0.0f, 0.0f, 0.0f, 1.0f};
1170 const tcu::Vec4 WriteSampleTest::kBadColor {1.0f, 0.0f, 0.0f, 1.0f};
1171 const tcu::Vec4 WriteSampleTest::kGoodColor {0.0f, 1.0f, 0.0f, 1.0f};
1172 const tcu::Vec4 WriteSampleTest::kWriteColor {0.0f, 0.0f, 1.0f, 1.0f};
1173
1174 class WriteSampleTestInstance : public vkt::TestInstance
1175 {
1176 public:
WriteSampleTestInstance(vkt::Context & context,const WriteSampleParams & params)1177 WriteSampleTestInstance (vkt::Context& context, const WriteSampleParams& params)
1178 : vkt::TestInstance(context), m_params(params)
1179 {}
1180
~WriteSampleTestInstance(void)1181 virtual ~WriteSampleTestInstance (void) {}
1182
1183 virtual tcu::TestStatus iterate (void);
1184
1185 private:
1186 WriteSampleParams m_params;
1187 };
1188
checkSupport(Context & context) const1189 void WriteSampleTest::checkSupport (Context& context) const
1190 {
1191 const auto& vki = context.getInstanceInterface();
1192 const auto physicalDevice = context.getPhysicalDevice();
1193
1194 // Check multisample storage images support.
1195 const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
1196 if (!features.shaderStorageImageMultisample)
1197 TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported");
1198
1199 // Check the specific image format.
1200 const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
1201 if (!(properties.optimalTilingFeatures & kFeatureFlags))
1202 TCU_THROW(NotSupportedError, "Format does not support the required features");
1203
1204 // Check the supported sample count.
1205 const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u);
1206 if (!(imgProps.sampleCounts & m_params.sampleCount))
1207 TCU_THROW(NotSupportedError, "Format does not support the required sample count");
1208 }
1209
initPrograms(vk::SourceCollections & programCollection) const1210 void WriteSampleTest::initPrograms (vk::SourceCollections& programCollection) const
1211 {
1212 std::ostringstream writeColorDecl, goodColorDecl, badColorDecl, clearColorDecl, allColorDecl;
1213
1214 writeColorDecl << " vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n";
1215 goodColorDecl << " vec4 bcolor = " << getShaderDecl(kBadColor) << ";\n";
1216 badColorDecl << " vec4 gcolor = " << getShaderDecl(kGoodColor) << ";\n";
1217 clearColorDecl << " vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n";
1218 allColorDecl << writeColorDecl.str() << goodColorDecl.str() << badColorDecl.str() << clearColorDecl.str();
1219
1220 std::ostringstream shaderWrite;
1221
1222 const auto bpc = de::toString(bitsPerCoord(m_params.sampleCount));
1223 const auto count = de::toString(m_params.sampleCount);
1224
1225 shaderWrite
1226 << "#version 450\n"
1227 << "\n"
1228 << "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n"
1229 << "layout (rgba8, set=0, binding=1) uniform image2D verificationImg;\n"
1230 << "\n"
1231 << "void main()\n"
1232 << "{\n"
1233 << writeColorDecl.str()
1234 << " uvec2 ucoords = uvec2(gl_GlobalInvocationID.xy);\n"
1235 << " ivec2 icoords = ivec2(ucoords);\n"
1236 << " uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n"
1237 << " for (uint i = 0; i < " << count << "; ++i)\n"
1238 << " {\n"
1239 << " if ((writeMask & (1 << i)) != 0)\n"
1240 << " imageStore(writeImg, icoords, int(i), wcolor);\n"
1241 << " }\n"
1242 << "}\n"
1243 ;
1244
1245 std::ostringstream shaderVerify;
1246
1247 shaderVerify
1248 << "#version 450\n"
1249 << "\n"
1250 << "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n"
1251 << "layout (rgba8, set=0, binding=1) uniform image2D verificationImg;\n"
1252 << "\n"
1253 << "void main()\n"
1254 << "{\n"
1255 << allColorDecl.str()
1256 << " uvec2 ucoords = uvec2(gl_GlobalInvocationID.xy);\n"
1257 << " ivec2 icoords = ivec2(ucoords);\n"
1258 << " uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n"
1259 << " bool ok = true;\n"
1260 << " for (uint i = 0; i < " << count << "; ++i)\n"
1261 << " {\n"
1262 << " bool expectWrite = ((writeMask & (1 << i)) != 0);\n"
1263 << " vec4 sampleColor = imageLoad(writeImg, icoords, int(i));\n"
1264 << " vec4 wantedColor = (expectWrite ? wcolor : ccolor);\n"
1265 << " ok = ok && (sampleColor == wantedColor);\n"
1266 << " }\n"
1267 << " vec4 resultColor = (ok ? gcolor : bcolor);\n"
1268 << " imageStore(verificationImg, icoords, resultColor);\n"
1269 << "}\n"
1270 ;
1271
1272 programCollection.glslSources.add("write") << glu::ComputeSource(shaderWrite.str());
1273 programCollection.glslSources.add("verify") << glu::ComputeSource(shaderVerify.str());
1274 }
1275
createInstance(Context & context) const1276 vkt::TestInstance* WriteSampleTest::createInstance (Context& context) const
1277 {
1278 return new WriteSampleTestInstance{context, m_params};
1279 }
1280
iterate(void)1281 tcu::TestStatus WriteSampleTestInstance::iterate (void)
1282 {
1283 const auto& vkd = m_context.getDeviceInterface();
1284 const auto device = m_context.getDevice();
1285 auto& allocator = m_context.getDefaultAllocator();
1286 const auto queue = m_context.getUniversalQueue();
1287 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
1288 const auto extent3D = getExtent3D(m_params.sampleCount);
1289
1290 // Create storage image and verification image.
1291 const vk::VkImageCreateInfo storageImageInfo =
1292 {
1293 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1294 nullptr, // const void* pNext;
1295 0u, // VkImageCreateFlags flags;
1296 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1297 WriteSampleTest::kImageFormat, // VkFormat format;
1298 extent3D, // VkExtent3D extent;
1299 1u, // deUint32 mipLevels;
1300 1u, // deUint32 arrayLayers;
1301 m_params.sampleCount, // VkSampleCountFlagBits samples;
1302 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1303 WriteSampleTest::kUsageFlags, // VkImageUsageFlags usage;
1304 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1305 1u, // deUint32 queueFamilyIndexCount;
1306 &queueIndex, // const deUint32* pQueueFamilyIndices;
1307 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1308 };
1309
1310 const vk::VkImageCreateInfo verificationImageInfo =
1311 {
1312 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1313 nullptr, // const void* pNext;
1314 0u, // VkImageCreateFlags flags;
1315 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1316 WriteSampleTest::kImageFormat, // VkFormat format;
1317 extent3D, // VkExtent3D extent;
1318 1u, // deUint32 mipLevels;
1319 1u, // deUint32 arrayLayers;
1320 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1321 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1322 WriteSampleTest::kUsageFlags, // VkImageUsageFlags usage;
1323 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1324 1u, // deUint32 queueFamilyIndexCount;
1325 &queueIndex, // const deUint32* pQueueFamilyIndices;
1326 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1327 };
1328
1329 vk::ImageWithMemory storageImgPrt {vkd, device, allocator, storageImageInfo, vk::MemoryRequirement::Any};
1330 vk::ImageWithMemory verificationImgPtr {vkd, device, allocator, verificationImageInfo, vk::MemoryRequirement::Any};
1331
1332 const vk::VkImageSubresourceRange kSubresourceRange =
1333 {
1334 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1335 0u, // deUint32 baseMipLevel;
1336 1u, // deUint32 levelCount;
1337 0u, // deUint32 baseArrayLayer;
1338 1u, // deUint32 layerCount;
1339 };
1340
1341 auto storageImgViewPtr = vk::makeImageView(vkd, device, storageImgPrt.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange);
1342 auto verificationImgViewPtr = vk::makeImageView(vkd, device, verificationImgPtr.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange);
1343
1344 // Prepare a staging buffer to check verification image.
1345 const auto tcuFormat = vk::mapVkFormat(WriteSampleTest::kImageFormat);
1346 const VkDeviceSize bufferSize = extent3D.width * extent3D.height * extent3D.depth * tcu::getPixelSize(tcuFormat);
1347 const auto stagingBufferInfo = vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1348 vk::BufferWithMemory stagingBuffer {vkd, device, allocator, stagingBufferInfo, MemoryRequirement::HostVisible};
1349
1350 // Descriptor set layout.
1351 vk::DescriptorSetLayoutBuilder layoutBuilder;
1352 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1353 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
1354 auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1355
1356 // Descriptor pool.
1357 vk::DescriptorPoolBuilder poolBuilder;
1358 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);
1359 auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1360
1361 // Descriptor set.
1362 const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1363
1364 // Update descriptor set using the images.
1365 const auto storageImgDescriptorInfo = vk::makeDescriptorImageInfo(DE_NULL, storageImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL);
1366 const auto verificationImgDescriptorInfo = vk::makeDescriptorImageInfo(DE_NULL, verificationImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL);
1367
1368 vk::DescriptorSetUpdateBuilder updateBuilder;
1369 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImgDescriptorInfo);
1370 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verificationImgDescriptorInfo);
1371 updateBuilder.update(vkd, device);
1372
1373 // Create write and verification compute pipelines.
1374 auto shaderWriteModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("write"), 0u);
1375 auto shaderVerifyModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("verify"), 0u);
1376 auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get());
1377
1378 const vk::VkComputePipelineCreateInfo writePipelineCreateInfo =
1379 {
1380 vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1381 nullptr,
1382 0u, // flags
1383 { // compute shader
1384 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1385 nullptr, // const void* pNext;
1386 0u, // VkPipelineShaderStageCreateFlags flags;
1387 vk::VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
1388 shaderWriteModule.get(), // VkShaderModule module;
1389 "main", // const char* pName;
1390 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
1391 },
1392 pipelineLayout.get(), // layout
1393 DE_NULL, // basePipelineHandle
1394 0, // basePipelineIndex
1395 };
1396
1397 auto verificationPipelineCreateInfo = writePipelineCreateInfo;
1398 verificationPipelineCreateInfo.stage.module = shaderVerifyModule.get();
1399
1400 auto writePipeline = vk::createComputePipeline(vkd, device, DE_NULL, &writePipelineCreateInfo);
1401 auto verificationPipeline = vk::createComputePipeline(vkd, device, DE_NULL, &verificationPipelineCreateInfo);
1402
1403 // Transition images to the correct layout and buffers at different stages.
1404 auto storageImgPreClearBarrier = vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, storageImgPrt.get(), kSubresourceRange);
1405 auto storageImgPreShaderBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange);
1406 auto verificationImgPreShaderBarrier = vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, verificationImgPtr.get(), kSubresourceRange);
1407 auto storageImgPreVerificationBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange);
1408 auto verificationImgPostBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationImgPtr.get(), kSubresourceRange);
1409 auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, stagingBuffer.get(), 0ull, bufferSize);
1410
1411 // Command buffer.
1412 auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex);
1413 auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1414 auto cmdBuffer = cmdBufferPtr.get();
1415
1416 // Clear color for the storage image.
1417 const auto clearColor = vk::makeClearValueColor(WriteSampleTest::kClearColor);
1418
1419 const vk::VkBufferImageCopy copyRegion =
1420 {
1421 0ull, // VkDeviceSize bufferOffset;
1422 extent3D.width, // deUint32 bufferRowLength;
1423 extent3D.height, // deUint32 bufferImageHeight;
1424 { // VkImageSubresourceLayers imageSubresource;
1425 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1426 0u, // deUint32 mipLevel;
1427 0u, // deUint32 baseArrayLayer;
1428 1u, // deUint32 layerCount;
1429 },
1430 { 0, 0, 0 }, // VkOffset3D imageOffset;
1431 extent3D, // VkExtent3D imageExtent;
1432 };
1433
1434 // Record and submit commands.
1435 vk::beginCommandBuffer(vkd, cmdBuffer);
1436 // Clear storage image.
1437 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreClearBarrier);
1438 vkd.cmdClearColorImage(cmdBuffer, storageImgPrt.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color, 1u, &kSubresourceRange);
1439
1440 // Bind write pipeline and descriptor set.
1441 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, writePipeline.get());
1442 vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1u, &descriptorSet.get(), 0u, nullptr);
1443
1444 // Transition images to the appropriate layout before running the shader.
1445 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreShaderBarrier);
1446 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPreShaderBarrier);
1447
1448 // Run shader.
1449 vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth);
1450
1451 // Bind verification pipeline.
1452 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, verificationPipeline.get());
1453
1454 // Make sure writes happen before reads in the second dispatch for the storage image.
1455 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreVerificationBarrier);
1456
1457 // Run verification shader.
1458 vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth);
1459
1460 // Change verification image layout to prepare the transfer.
1461 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPostBarrier);
1462
1463 // Copy verification image to staging buffer.
1464 vkd.cmdCopyImageToBuffer(cmdBuffer, verificationImgPtr.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer.get(), 1u, ©Region);
1465 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
1466
1467 vk::endCommandBuffer(vkd, cmdBuffer);
1468
1469 // Run shaders.
1470 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1471
1472 // Read buffer pixels.
1473 const auto& bufferAlloc = stagingBuffer.getAllocation();
1474 vk::invalidateAlloc(vkd, device, bufferAlloc);
1475
1476 // Copy buffer data to texture level and verify all pixels have the proper color.
1477 tcu::TextureLevel texture {tcuFormat, static_cast<int>(extent3D.width), static_cast<int>(extent3D.height), static_cast<int>(extent3D.depth)};
1478 const auto access = texture.getAccess();
1479 deMemcpy(access.getDataPtr(), reinterpret_cast<char*>(bufferAlloc.getHostPtr()) + bufferAlloc.getOffset(), static_cast<size_t>(bufferSize));
1480
1481 for (int i = 0; i < access.getWidth(); ++i)
1482 for (int j = 0; j < access.getHeight(); ++j)
1483 for (int k = 0; k < access.getDepth(); ++k)
1484 {
1485 if (access.getPixel(i, j, k) != WriteSampleTest::kGoodColor)
1486 {
1487 std::ostringstream msg;
1488 msg << "Invalid result at pixel (" << i << ", " << j << ", " << k << "); check error mask for more details";
1489 m_context.getTestContext().getLog() << tcu::TestLog::Image("ErrorMask", "Indicates which pixels have unexpected values", access);
1490 return tcu::TestStatus::fail(msg.str());
1491 }
1492 }
1493
1494 return tcu::TestStatus::pass("Pass");
1495 }
1496
1497 using WriteSampleMaskParams = WriteSampleParams;
1498
1499 class WriteSampleMaskTestCase : public vkt::TestCase
1500 {
1501 public:
1502 WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const WriteSampleMaskParams& params);
~WriteSampleMaskTestCase(void)1503 virtual ~WriteSampleMaskTestCase (void) {}
1504
1505 virtual void checkSupport (Context& context) const;
1506 virtual void initPrograms (vk::SourceCollections& programCollection) const;
1507 virtual TestInstance* createInstance (Context& context) const;
1508 static deUint32 getBufferElems (deUint32 sampleCount);
1509
1510 static const tcu::Vec4 kClearColor;
1511 static const tcu::Vec4 kWriteColor;
1512
1513 static constexpr vk::VkFormat kImageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
1514 static constexpr vk::VkImageUsageFlags kUsageFlags = (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
1515 static constexpr vk::VkFormatFeatureFlags kFeatureFlags = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
1516
1517 private:
1518 WriteSampleMaskParams m_params;
1519 };
1520
1521 const tcu::Vec4 WriteSampleMaskTestCase::kClearColor {0.0f, 0.0f, 0.0f, 1.0f};
1522 const tcu::Vec4 WriteSampleMaskTestCase::kWriteColor {0.0f, 0.0f, 1.0f, 1.0f};
1523
1524 class WriteSampleMaskTestInstance : public vkt::TestInstance
1525 {
1526 public:
1527 WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params);
~WriteSampleMaskTestInstance(void)1528 virtual ~WriteSampleMaskTestInstance (void) {}
1529
1530 virtual tcu::TestStatus iterate (void);
1531
1532 private:
1533 WriteSampleMaskParams m_params;
1534 };
1535
WriteSampleMaskTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const WriteSampleMaskParams & params)1536 WriteSampleMaskTestCase::WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const WriteSampleMaskParams& params)
1537 : vkt::TestCase (testCtx, name, description)
1538 , m_params (params)
1539 {}
1540
checkSupport(Context & context) const1541 void WriteSampleMaskTestCase::checkSupport (Context& context) const
1542 {
1543 const auto& vki = context.getInstanceInterface();
1544 const auto physicalDevice = context.getPhysicalDevice();
1545
1546 // Check if sampleRateShading is supported.
1547 if(!vk::getPhysicalDeviceFeatures(vki, physicalDevice).sampleRateShading)
1548 TCU_THROW(NotSupportedError, "Sample rate shading is not supported");
1549
1550 // Check the specific image format.
1551 const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
1552 if (!(properties.optimalTilingFeatures & kFeatureFlags))
1553 TCU_THROW(NotSupportedError, "Format does not support the required features");
1554
1555 // Check the supported sample count.
1556 const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u);
1557 if (!(imgProps.sampleCounts & m_params.sampleCount))
1558 TCU_THROW(NotSupportedError, "Format does not support the required sample count");
1559 }
1560
initPrograms(vk::SourceCollections & programCollection) const1561 void WriteSampleMaskTestCase::initPrograms (vk::SourceCollections& programCollection) const
1562 {
1563 const auto bpc = de::toString(bitsPerCoord(m_params.sampleCount));
1564 const auto size = imageSize(m_params.sampleCount);
1565 const auto bufferElems = getBufferElems(m_params.sampleCount);
1566
1567 // Passthrough vertex shader.
1568 std::ostringstream vertShader;
1569
1570 vertShader
1571 << "#version 450\n"
1572 << "layout (location=0) in vec2 inPos;\n"
1573 << "void main()\n"
1574 << "{\n"
1575 << " gl_Position = vec4(inPos, 0.0, 1.0);\n"
1576 << "}\n"
1577 ;
1578
1579 // Fragment shader common header.
1580 std::ostringstream fragHeader;
1581
1582 fragHeader
1583 << "#version 450\n"
1584 << "\n"
1585 // The color attachment is useless for the second subpass but avoids having to use an empty subpass and verifying the sample
1586 // count is valid for it.
1587 << "layout (location=0) out vec4 outColor;\n"
1588 << "\n"
1589 << "vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n"
1590 << "vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n"
1591 << "\n"
1592 ;
1593
1594 const auto fragHeaderStr = fragHeader.str();
1595
1596 // Fragment shader setting the sample mask and writing to the output color attachment. The sample mask will guarantee each image
1597 // pixel gets a different combination of sample bits set, allowing the fragment shader to write in that sample or not, from all
1598 // zeros in pixel (0, 0) to all ones in the opposite corner.
1599 std::ostringstream fragShaderWrite;
1600
1601 fragShaderWrite
1602 << fragHeaderStr
1603 << "void main()\n"
1604 << "{\n"
1605 << " uvec2 ucoords = uvec2(gl_FragCoord);\n"
1606 << " ivec2 icoords = ivec2(ucoords);\n"
1607 << " gl_SampleMask[0] = int((ucoords.x << " << bpc << ") | ucoords.y);\n"
1608 << " outColor = wcolor;\n"
1609 << "}\n"
1610 ;
1611
1612 // Fragment shader reading from the previous output color attachment and copying the state to an SSBO for verification.
1613 std::ostringstream fragShaderCheck;
1614
1615 const bool isMultiSample = (m_params.sampleCount != vk::VK_SAMPLE_COUNT_1_BIT);
1616 fragShaderCheck
1617 << fragHeaderStr
1618 << "layout(set=0, binding=0, input_attachment_index=0) uniform subpassInput" << (isMultiSample ? "MS" : "") << " inputAttachment;\n"
1619 << "layout(set=0, binding=1, std430) buffer StorageBuffer {\n"
1620 << " int writeFlags[" << bufferElems << "];\n"
1621 << "} sb;\n"
1622 << "\n"
1623 << "void main()\n"
1624 << "{\n"
1625 << " uvec2 ucoords = uvec2(gl_FragCoord);\n"
1626 << " ivec2 icoords = ivec2(ucoords);\n"
1627 << " uint bufferp = ((ucoords.y * " << size.width << " + ucoords.x) * " << m_params.sampleCount << ") + uint(gl_SampleID);\n"
1628 << " vec4 storedc = subpassLoad(inputAttachment" << (isMultiSample ? ", gl_SampleID" : "") << ");\n"
1629 << " sb.writeFlags[bufferp] = ((storedc == wcolor) ? 1 : ((storedc == ccolor) ? 0 : 2));\n"
1630 << " outColor = storedc;\n"
1631 << "}\n"
1632 ;
1633
1634 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.str());
1635 programCollection.glslSources.add("frag_write") << glu::FragmentSource(fragShaderWrite.str());
1636 programCollection.glslSources.add("frag_check") << glu::FragmentSource(fragShaderCheck.str());
1637 }
1638
createInstance(Context & context) const1639 TestInstance* WriteSampleMaskTestCase::createInstance (Context& context) const
1640 {
1641 return new WriteSampleMaskTestInstance(context, m_params);
1642 }
1643
getBufferElems(deUint32 sampleCount)1644 deUint32 WriteSampleMaskTestCase::getBufferElems (deUint32 sampleCount)
1645 {
1646 const auto imgSize = imageSize(sampleCount);
1647 return (imgSize.width * imgSize.height * sampleCount);
1648 }
1649
WriteSampleMaskTestInstance(Context & context,const WriteSampleMaskParams & params)1650 WriteSampleMaskTestInstance::WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params)
1651 : vkt::TestInstance (context)
1652 , m_params (params)
1653 {}
1654
iterate(void)1655 tcu::TestStatus WriteSampleMaskTestInstance::iterate (void)
1656 {
1657 const auto& vkd = m_context.getDeviceInterface();
1658 const auto device = m_context.getDevice();
1659 auto& alloc = m_context.getDefaultAllocator();
1660 const auto queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1661 const auto queue = m_context.getUniversalQueue();
1662
1663 static constexpr auto kImageFormat = WriteSampleMaskTestCase::kImageFormat;
1664 static constexpr auto kImageUsage = WriteSampleMaskTestCase::kUsageFlags;
1665 const auto kImageExtent = getExtent3D(m_params.sampleCount);
1666 const auto kBufferElems = WriteSampleMaskTestCase::getBufferElems(m_params.sampleCount);
1667 const auto kBufferSize = static_cast<vk::VkDeviceSize>(kBufferElems * sizeof(deInt32));
1668
1669 // Create image.
1670 const vk::VkImageCreateInfo imageCreateInfo =
1671 {
1672 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1673 nullptr, // const void* pNext;
1674 0u, // VkImageCreateFlags flags;
1675 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1676 kImageFormat, // VkFormat format;
1677 kImageExtent, // VkExtent3D extent;
1678 1u, // deUint32 mipLevels;
1679 1u, // deUint32 arrayLayers;
1680 m_params.sampleCount, // VkSampleCountFlagBits samples;
1681 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1682 kImageUsage, // VkImageUsageFlags usage;
1683 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1684 0u, // deUint32 queueFamilyIndexCount;
1685 nullptr, // const deUint32* pQueueFamilyIndices;
1686 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1687 };
1688
1689 const vk::ImageWithMemory colorImage (vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any);
1690 const vk::ImageWithMemory auxiliarImage (vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any); // For the second subpass.
1691
1692 // Image views.
1693 const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1694 const auto colorImageView = vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange);
1695 const auto auxiliarImageView = vk::makeImageView(vkd, device, auxiliarImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange);
1696
1697 // Create storage buffer used to verify results.
1698 const vk::BufferWithMemory storageBuffer(vkd, device, alloc, vk::makeBufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
1699
1700 // Full-screen quad.
1701 const std::vector<tcu::Vec2> quadVertices =
1702 {
1703 tcu::Vec2(-1.0f, 1.0f), // Lower left
1704 tcu::Vec2( 1.0f, 1.0f), // Lower right
1705 tcu::Vec2( 1.0f, -1.0f), // Top right.
1706 tcu::Vec2(-1.0f, 1.0f), // Lower left
1707 tcu::Vec2( 1.0f, -1.0f), // Top right.
1708 tcu::Vec2(-1.0f, -1.0f), // Top left.
1709 };
1710
1711 // Vertex buffer.
1712 const auto vertexBufferSize = static_cast<vk::VkDeviceSize>(quadVertices.size() * sizeof(decltype(quadVertices)::value_type));
1713 const vk::BufferWithMemory vertexBuffer (vkd, device, alloc, vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible);
1714 const auto& vertexBufferAlloc = vertexBuffer.getAllocation();
1715 void* vertexBufferPtr = vertexBufferAlloc.getHostPtr();
1716 const vk::VkDeviceSize vertexBufferOffset = 0;
1717 deMemcpy(vertexBufferPtr, quadVertices.data(), static_cast<size_t>(vertexBufferSize));
1718 vk::flushAlloc(vkd, device, vertexBufferAlloc);
1719
1720 // Descriptor set layout.
1721 vk::DescriptorSetLayoutBuilder setLayoutBuilder;
1722 setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1723 setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1724 const auto descriptorSetLayout = setLayoutBuilder.build(vkd, device);
1725
1726 // Descriptor pool and set.
1727 vk::DescriptorPoolBuilder poolBuilder;
1728 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u);
1729 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
1730 const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1731 const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1732
1733 // Render pass.
1734 const std::vector<vk::VkAttachmentDescription> attachments =
1735 {
1736 // Main color attachment.
1737 {
1738 0u, // VkAttachmentDescriptionFlags flags;
1739 kImageFormat, // VkFormat format;
1740 m_params.sampleCount, // VkSampleCountFlagBits samples;
1741 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1742 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1743 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1744 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1745 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1746 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout finalLayout;
1747 },
1748 // Auxiliar color attachment for the check pass.
1749 {
1750 0u, // VkAttachmentDescriptionFlags flags;
1751 kImageFormat, // VkFormat format;
1752 m_params.sampleCount, // VkSampleCountFlagBits samples;
1753 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
1754 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
1755 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1756 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1757 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1758 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1759 },
1760 };
1761
1762 const vk::VkAttachmentReference colorAttachmentReference =
1763 {
1764 0u, // deUint32 attachment;
1765 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1766 };
1767
1768 const vk::VkAttachmentReference colorAsInputAttachment =
1769 {
1770 0u, // deUint32 attachment;
1771 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout;
1772 };
1773
1774 const vk::VkAttachmentReference auxiliarAttachmentReference =
1775 {
1776 1u, // deUint32 attachment;
1777 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1778 };
1779
1780 const std::vector<vk::VkSubpassDescription> subpasses =
1781 {
1782 // First subpass writing to the main attachment.
1783 {
1784 0u, // VkSubpassDescriptionFlags flags;
1785 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1786 0u, // deUint32 inputAttachmentCount;
1787 nullptr, // const VkAttachmentReference* pInputAttachments;
1788 1u, // deUint32 colorAttachmentCount;
1789 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
1790 nullptr, // const VkAttachmentReference* pResolveAttachments;
1791 nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
1792 0u, // deUint32 preserveAttachmentCount;
1793 nullptr, // const deUint32* pPreserveAttachments;
1794 },
1795 // Second subpass writing to the auxiliar attachment.
1796 {
1797 0u, // VkSubpassDescriptionFlags flags;
1798 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1799 1u, // deUint32 inputAttachmentCount;
1800 &colorAsInputAttachment, // const VkAttachmentReference* pInputAttachments;
1801 1u, // deUint32 colorAttachmentCount;
1802 &auxiliarAttachmentReference, // const VkAttachmentReference* pColorAttachments;
1803 nullptr, // const VkAttachmentReference* pResolveAttachments;
1804 nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
1805 0u, // deUint32 preserveAttachmentCount;
1806 nullptr, // const deUint32* pPreserveAttachments;
1807 },
1808 };
1809
1810 const std::vector<vk::VkSubpassDependency> subpassDependencies =
1811 {
1812 // First subpass writes to the color attachment and second subpass reads it as an input attachment.
1813 {
1814 0u, // deUint32 srcSubpass;
1815 1u, // deUint32 dstSubpass;
1816 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask;
1817 vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask;
1818 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1819 vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
1820 0u, // VkDependencyFlags dependencyFlags;
1821 },
1822 };
1823
1824 const vk::VkRenderPassCreateInfo renderPassInfo =
1825 {
1826 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1827 nullptr, // const void* pNext;
1828 0u, // VkRenderPassCreateFlags flags;
1829 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount;
1830 attachments.data(), // const VkAttachmentDescription* pAttachments;
1831 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
1832 subpasses.data(), // const VkSubpassDescription* pSubpasses;
1833 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount;
1834 subpassDependencies.data(), // const VkSubpassDependency* pDependencies;
1835 };
1836 const auto renderPass = vk::createRenderPass(vkd, device, &renderPassInfo);
1837
1838 // Framebuffer.
1839 const std::vector<vk::VkImageView> imageViews =
1840 {
1841 colorImageView.get(),
1842 auxiliarImageView.get(),
1843 };
1844 const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(imageViews.size()), imageViews.data(), kImageExtent.width, kImageExtent.height);
1845
1846 // Empty pipeline layout for the first subpass.
1847 const auto emptyPipelineLayout = vk::makePipelineLayout(vkd, device);
1848
1849 // Pipeline layout for the second subpass.
1850 const auto checkPipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get());
1851
1852 // Shader modules.
1853 const auto vertModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1854 const auto writeModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag_write"), 0u);
1855 const auto checkModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag_check"), 0u);
1856
1857 const std::vector<vk::VkVertexInputBindingDescription> vertexBindings =
1858 {
1859 {
1860 0u, // deUint32 binding;
1861 static_cast<deUint32>(sizeof(decltype(quadVertices)::value_type)), // deUint32 stride;
1862 vk::VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
1863 },
1864 };
1865
1866 const std::vector<vk::VkVertexInputAttributeDescription> vertexAttributes =
1867 {
1868 {
1869 0u, // deUint32 location;
1870 0u, // deUint32 binding;
1871 vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1872 0u, // deUint32 offset;
1873 },
1874 };
1875
1876 const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
1877 {
1878 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1879 nullptr, // const void* pNext;
1880 0u, // VkPipelineVertexInputStateCreateFlags flags;
1881 static_cast<deUint32>(vertexBindings.size()), // deUint32 vertexBindingDescriptionCount;
1882 vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1883 static_cast<deUint32>(vertexAttributes.size()), // deUint32 vertexAttributeDescriptionCount;
1884 vertexAttributes.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1885 };
1886
1887 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo =
1888 {
1889 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1890 nullptr, // const void* pNext;
1891 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
1892 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
1893 VK_FALSE, // VkBool32 primitiveRestartEnable;
1894 };
1895
1896 const auto viewport = vk::makeViewport(kImageExtent);
1897 const auto scissor = vk::makeRect2D(kImageExtent);
1898
1899 const vk::VkPipelineViewportStateCreateInfo viewportInfo =
1900 {
1901 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1902 nullptr, // const void* pNext;
1903 0u, // VkPipelineViewportStateCreateFlags flags;
1904 1u, // deUint32 viewportCount;
1905 &viewport, // const VkViewport* pViewports;
1906 1u, // deUint32 scissorCount;
1907 &scissor, // const VkRect2D* pScissors;
1908 };
1909
1910 const vk::VkPipelineRasterizationStateCreateInfo rasterizationInfo =
1911 {
1912 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1913 nullptr, // const void* pNext;
1914 0u, // VkPipelineRasterizationStateCreateFlags flags;
1915 VK_FALSE, // VkBool32 depthClampEnable;
1916 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
1917 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
1918 vk::VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
1919 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
1920 VK_FALSE, // VkBool32 depthBiasEnable;
1921 0.0f, // float depthBiasConstantFactor;
1922 0.0f, // float depthBiasClamp;
1923 0.0f, // float depthBiasSlopeFactor;
1924 1.0f, // float lineWidth;
1925 };
1926
1927 const vk::VkPipelineMultisampleStateCreateInfo multisampleInfo =
1928 {
1929 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1930 nullptr, // const void* pNext;
1931 0u, // VkPipelineMultisampleStateCreateFlags flags;
1932 m_params.sampleCount, // VkSampleCountFlagBits rasterizationSamples;
1933 VK_FALSE, // VkBool32 sampleShadingEnable;
1934 1.0f, // float minSampleShading;
1935 nullptr, // const VkSampleMask* pSampleMask;
1936 VK_FALSE, // VkBool32 alphaToCoverageEnable;
1937 VK_FALSE, // VkBool32 alphaToOneEnable;
1938 };
1939
1940 const auto stencilState = vk::makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u);
1941
1942 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilInfo =
1943 {
1944 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1945 nullptr, // const void* pNext;
1946 0u, // VkPipelineDepthStencilStateCreateFlags flags;
1947 VK_FALSE, // VkBool32 depthTestEnable;
1948 VK_FALSE, // VkBool32 depthWriteEnable;
1949 vk::VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
1950 VK_FALSE, // VkBool32 depthBoundsTestEnable;
1951 VK_FALSE, // VkBool32 stencilTestEnable;
1952 stencilState, // VkStencilOpState front;
1953 stencilState, // VkStencilOpState back;
1954 0.0f, // float minDepthBounds;
1955 1.0f, // float maxDepthBounds;
1956 };
1957
1958 const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1959 {
1960 VK_FALSE, // VkBool32 blendEnable;
1961 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
1962 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
1963 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
1964 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
1965 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
1966 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
1967 ( // VkColorComponentFlags colorWriteMask;
1968 vk::VK_COLOR_COMPONENT_R_BIT |
1969 vk::VK_COLOR_COMPONENT_G_BIT |
1970 vk::VK_COLOR_COMPONENT_B_BIT |
1971 vk::VK_COLOR_COMPONENT_A_BIT ),
1972 };
1973
1974 const vk::VkPipelineColorBlendStateCreateInfo colorBlendInfo =
1975 {
1976 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1977 nullptr, // const void* pNext;
1978 0u, // VkPipelineColorBlendStateCreateFlags flags;
1979 VK_FALSE, // VkBool32 logicOpEnable;
1980 vk::VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp;
1981 1u, // deUint32 attachmentCount;
1982 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
1983 { .0f, .0f, .0f, .0f }, // float blendConstants[4];
1984 };
1985
1986 const vk::VkPipelineDynamicStateCreateInfo dynamicStateInfo =
1987 {
1988 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
1989 nullptr, // const void* pNext;
1990 0u, // VkPipelineDynamicStateCreateFlags flags;
1991 0u, // deUint32 dynamicStateCount;
1992 nullptr, // const VkDynamicState* pDynamicStates;
1993 };
1994
1995 // Pipeline for the first subpass.
1996 const auto firstSubpassPipeline = vk::makeGraphicsPipeline(
1997 vkd, device, emptyPipelineLayout.get(),
1998 vertModule.get(), DE_NULL, DE_NULL, DE_NULL, writeModule.get(),
1999 renderPass.get(), 0u,
2000 &vertexInputInfo, &inputAssemblyInfo, nullptr, &viewportInfo, &rasterizationInfo,
2001 &multisampleInfo, &depthStencilInfo, &colorBlendInfo, &dynamicStateInfo
2002 );
2003
2004 // Pipeline for the second subpass.
2005 const auto secondSubpassPipeline = vk::makeGraphicsPipeline(
2006 vkd, device, checkPipelineLayout.get(),
2007 vertModule.get(), DE_NULL, DE_NULL, DE_NULL, checkModule.get(),
2008 renderPass.get(), 1u,
2009 &vertexInputInfo, &inputAssemblyInfo, nullptr, &viewportInfo, &rasterizationInfo,
2010 &multisampleInfo, &depthStencilInfo, &colorBlendInfo, &dynamicStateInfo
2011 );
2012
2013 // Command pool and command buffer.
2014 const auto cmdPool = vk::makeCommandPool(vkd, device, queueFamilyIndex);
2015 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2016 const auto cmdBuffer = cmdBufferPtr.get();
2017
2018 // Update descriptor set.
2019 vk::DescriptorSetUpdateBuilder updateBuilder;
2020 const auto imageInfo = vk::makeDescriptorImageInfo(DE_NULL, colorImageView.get(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2021 const auto bufferInfo = vk::makeDescriptorBufferInfo(storageBuffer.get(), 0u, VK_WHOLE_SIZE);
2022 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo);
2023 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
2024 updateBuilder.update(vkd, device);
2025
2026 // Output buffer pipeline barrier.
2027 const auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, storageBuffer.get(), 0ull, VK_WHOLE_SIZE);
2028
2029 // Run pipelines.
2030 vk::beginCommandBuffer(vkd, cmdBuffer);
2031
2032 vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), vk::makeRect2D(kImageExtent), WriteSampleMaskTestCase::kClearColor);
2033 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2034 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, firstSubpassPipeline.get());
2035 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u);
2036
2037 vkd.cmdNextSubpass(cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE);
2038 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, secondSubpassPipeline.get());
2039 vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, checkPipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2040 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u);
2041
2042 vk::endRenderPass(vkd, cmdBuffer);
2043 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
2044 vk::endCommandBuffer(vkd, cmdBuffer);
2045
2046 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2047
2048 // Check buffer contents.
2049 auto& bufferAlloc = storageBuffer.getAllocation();
2050 const void* bufferPtr = bufferAlloc.getHostPtr();
2051 std::vector<deInt32> bufferContents (kBufferElems, 0);
2052
2053 vk::invalidateAlloc(vkd, device, bufferAlloc);
2054 deMemcpy(bufferContents.data(), bufferPtr, static_cast<size_t>(kBufferSize));
2055
2056 const auto sampleCount = static_cast<deUint32>(m_params.sampleCount);
2057 const auto bpc = bitsPerCoord(sampleCount);
2058
2059 for (deUint32 x = 0; x < kImageExtent.width; ++x)
2060 for (deUint32 y = 0; y < kImageExtent.height; ++y)
2061 {
2062 // Samples on which we expect writes.
2063 const deUint32 sampleMask = ((x << bpc) | y);
2064
2065 // Starting location for the pixel sample values in the buffer.
2066 const deUint32 pixelOffset = (y * kImageExtent.width + x) * sampleCount;
2067
2068 for (deUint32 s = 0; s < sampleCount; ++s)
2069 {
2070 const deUint32 sampleIndex = pixelOffset + s;
2071 const deInt32& value = bufferContents[sampleIndex];
2072
2073 if (value != 0 && value != 1)
2074 {
2075 // Garbage!
2076 std::ostringstream msg;
2077 msg << "Found garbage value " << value << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")";
2078 return tcu::TestStatus::fail(msg.str());
2079 }
2080
2081 const deInt32 expected = (((sampleMask & (1u << s)) != 0u) ? 1 : 0);
2082 if (value != expected)
2083 {
2084 std::ostringstream msg;
2085 msg << "Read " << value << " while expecting " << expected << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")";
2086 return tcu::TestStatus::fail(msg.str());
2087 }
2088 }
2089 }
2090
2091 return tcu::TestStatus::pass("Pass");
2092 }
2093
2094 } // multisample
2095
createMultisampleShaderBuiltInTests(tcu::TestContext & testCtx)2096 tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx)
2097 {
2098 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin", "Multisample Shader BuiltIn Tests"));
2099
2100 const tcu::UVec3 imageSizes[] =
2101 {
2102 tcu::UVec3(128u, 128u, 1u),
2103 tcu::UVec3(137u, 191u, 1u),
2104 };
2105
2106 const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
2107
2108 const vk::VkSampleCountFlagBits samplesSetFull[] =
2109 {
2110 vk::VK_SAMPLE_COUNT_2_BIT,
2111 vk::VK_SAMPLE_COUNT_4_BIT,
2112 vk::VK_SAMPLE_COUNT_8_BIT,
2113 vk::VK_SAMPLE_COUNT_16_BIT,
2114 vk::VK_SAMPLE_COUNT_32_BIT,
2115 vk::VK_SAMPLE_COUNT_64_BIT,
2116 };
2117
2118 const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits));
2119
2120 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2121
2122 de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position", "Sample Position Tests"));
2123
2124 samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2125 samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness", imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount));
2126
2127 testGroup->addChild(samplePositionGroup.release());
2128
2129 const vk::VkSampleCountFlagBits samplesSetReduced[] =
2130 {
2131 vk::VK_SAMPLE_COUNT_2_BIT,
2132 vk::VK_SAMPLE_COUNT_4_BIT,
2133 vk::VK_SAMPLE_COUNT_8_BIT,
2134 vk::VK_SAMPLE_COUNT_16_BIT,
2135 vk::VK_SAMPLE_COUNT_32_BIT,
2136 };
2137
2138 const deUint32 samplesSetReducedCount = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(samplesSetReduced));
2139
2140 de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask", "Sample Mask Tests"));
2141
2142 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> > (testCtx, "pattern", imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2143 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> > (testCtx, "bit_count", imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2144 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit",imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2145 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> > (testCtx, "write", imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount));
2146
2147 testGroup->addChild(sampleMaskGroup.release());
2148
2149 // Write image sample tests using a storage images.
2150 {
2151 de::MovePtr<tcu::TestCaseGroup> imageWriteSampleGroup(new tcu::TestCaseGroup(testCtx, "image_write_sample", "Test OpImageWrite with a sample ID"));
2152
2153 for (auto count : multisample::kValidSquareSampleCounts)
2154 {
2155 if (count == vk::VK_SAMPLE_COUNT_1_BIT)
2156 continue;
2157
2158 multisample::WriteSampleParams params { static_cast<vk::VkSampleCountFlagBits>(count) };
2159 const auto countStr = de::toString(count);
2160 imageWriteSampleGroup->addChild(new multisample::WriteSampleTest(testCtx, countStr + "_samples", "Test image with " + countStr + " samples", params));
2161 }
2162
2163 testGroup->addChild(imageWriteSampleGroup.release());
2164 }
2165
2166 // Write to gl_SampleMask from the fragment shader.
2167 {
2168 de::MovePtr<tcu::TestCaseGroup> writeSampleMaskGroup(new tcu::TestCaseGroup(testCtx, "write_sample_mask", "Test writes to SampleMask variable"));
2169
2170 for (auto count : multisample::kValidSquareSampleCounts)
2171 {
2172 multisample::WriteSampleMaskParams params { static_cast<vk::VkSampleCountFlagBits>(count) };
2173 const auto countStr = de::toString(count);
2174 writeSampleMaskGroup->addChild(new multisample::WriteSampleMaskTestCase(testCtx, countStr + "_samples", "Test image with " + countStr + " samples", params));
2175 }
2176
2177 testGroup->addChild(writeSampleMaskGroup.release());
2178 }
2179
2180 return testGroup.release();
2181 }
2182
2183 } // pipeline
2184 } // vkt
2185