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