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