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