1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 The Khronos Group Inc.
6 * Copyright (c) 2022 Google Inc.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file vktPipelineMultisampleResolveRenderAreaTests.hpp
24 * \brief Multisample resolve tests where a render area is less than an
25 * attachment size.
26 *//*--------------------------------------------------------------------*/
27
28 #include "vktPipelineMultisampleResolveRenderAreaTests.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktTestGroupUtil.hpp"
31
32 #include "vkCmdUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkTypeUtil.hpp"
38
39 #include "tcuImageCompare.hpp"
40 #include "tcuTestLog.hpp"
41
42 namespace vkt
43 {
44 namespace pipeline
45 {
46 using namespace vk;
47 using de::UniquePtr;
48
49 namespace
50 {
51
52 enum class TestShape
53 {
54 SHAPE_RECTANGLE,
55 SHAPE_DIAMOND,
56 SHAPE_PARALLELOGRAM
57 };
58
59 class MultisampleRenderAreaTestInstance : public TestInstance
60 {
61 public:
MultisampleRenderAreaTestInstance(Context& context, const PipelineConstructionType pipelineConstructionType, const deUint32 sampleCount, const tcu::IVec2 framebufferSize, const TestShape testShape, const VkFormat colorFormat)62 MultisampleRenderAreaTestInstance (Context& context,
63 const PipelineConstructionType pipelineConstructionType,
64 const deUint32 sampleCount,
65 const tcu::IVec2 framebufferSize,
66 const TestShape testShape,
67 const VkFormat colorFormat)
68 : TestInstance (context)
69 , m_pipelineConstructionType (pipelineConstructionType)
70 , m_sampleCount (sampleCount)
71 , m_framebufferSize (framebufferSize)
72 , m_testShape (testShape)
73 , m_colorFormat (colorFormat)
74 {}
75
76 tcu::TestStatus iterate (void);
77
78 private:
79 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& imageSize, const deUint32 sampleCount);
80
81 RenderPassWrapper makeRenderPass (const DeviceInterface& vk,
82 const VkDevice device,
83 const VkFormat colorFormat,
84 const VkImageLayout initialLayout);
85
86 void preparePipelineWrapper (GraphicsPipelineWrapper& gpw,
87 const PipelineLayoutWrapper& pipelineLayout,
88 const VkRenderPass renderPass,
89 const ShaderWrapper vertexModule,
90 const ShaderWrapper fragmentModule,
91 const tcu::IVec2& framebufferSize);
92
93 const PipelineConstructionType m_pipelineConstructionType;
94 const deUint32 m_sampleCount;
95 const tcu::IVec2 m_framebufferSize;
96 const TestShape m_testShape;
97 const VkFormat m_colorFormat;
98 };
99
makeImageCreateInfo(const tcu::IVec2& imageSize, const deUint32 sampleCount)100 VkImageCreateInfo MultisampleRenderAreaTestInstance::makeImageCreateInfo(const tcu::IVec2& imageSize, const deUint32 sampleCount)
101 {
102 const VkImageCreateInfo imageParams =
103 {
104 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
105 DE_NULL, // const void* pNext;
106 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
107 VK_IMAGE_TYPE_2D, // VkImageType imageType;
108 m_colorFormat, // VkFormat format;
109 makeExtent3D(imageSize.x(), imageSize.y(), 1), // VkExtent3D extent;
110 1u, // deUint32 mipLevels;
111 1u, // deUint32 arrayLayers;
112 sampleCount < 2u ? VK_SAMPLE_COUNT_1_BIT : (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
113 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
114 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
115 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
116 0u, // deUint32 queueFamilyIndexCount;
117 DE_NULL, // const deUint32* pQueueFamilyIndices;
118 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
119 };
120
121 return imageParams;
122 }
123
makeRenderPass(const DeviceInterface& vk, const VkDevice device, const VkFormat colorFormat, const VkImageLayout initialLayout)124 RenderPassWrapper MultisampleRenderAreaTestInstance::makeRenderPass (const DeviceInterface& vk,
125 const VkDevice device,
126 const VkFormat colorFormat,
127 const VkImageLayout initialLayout)
128 {
129 const VkAttachmentDescription colorAttachmentDescription =
130 {
131 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
132 colorFormat, // VkFormat format;
133 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
134 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
135 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
136 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
137 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
138 initialLayout, // VkImageLayout initialLayout;
139 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
140 };
141
142 const VkAttachmentDescription resolveAttachmentDescription =
143 {
144 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
145 colorFormat, // VkFormat format;
146 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
147 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
148 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
149 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
150 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
151 initialLayout, // VkImageLayout initialLayout;
152 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
153 };
154
155 std::vector<VkAttachmentDescription> attachmentDescriptions;
156
157 attachmentDescriptions.push_back(colorAttachmentDescription);
158 attachmentDescriptions.push_back(resolveAttachmentDescription);
159
160 const VkAttachmentReference colorAttachmentRef =
161 {
162 0u, // uint32_t attachment;
163 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
164 };
165
166 const VkAttachmentReference resolveAttachmentRef =
167 {
168 1u, // uint32_t attachment;
169 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
170 };
171
172 const VkSubpassDescription subpassDescription =
173 {
174 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
175 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
176 0u, // uint32_t inputAttachmentCount;
177 DE_NULL, // const VkAttachmentReference* pInputAttachments;
178 1u, // uint32_t colorAttachmentCount;
179 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
180 &resolveAttachmentRef, // const VkAttachmentReference* pResolveAttachments;
181 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
182 0u, // uint32_t preserveAttachmentCount;
183 DE_NULL // const uint32_t* pPreserveAttachments;
184 };
185
186 const VkRenderPassCreateInfo renderPassInfo =
187 {
188 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
189 DE_NULL, // const void* pNext;
190 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
191 (deUint32)attachmentDescriptions.size(), // uint32_t attachmentCount;
192 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
193 1u, // uint32_t subpassCount;
194 &subpassDescription, // const VkSubpassDescription* pSubpasses;
195 0u, // uint32_t dependencyCount;
196 DE_NULL, // const VkSubpassDependency* pDependencies;
197 };
198
199 return RenderPassWrapper(m_pipelineConstructionType, vk, device, &renderPassInfo);
200 }
201
preparePipelineWrapper(GraphicsPipelineWrapper& gpw, const PipelineLayoutWrapper& pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const tcu::IVec2& framebufferSize)202 void MultisampleRenderAreaTestInstance::preparePipelineWrapper (GraphicsPipelineWrapper& gpw,
203 const PipelineLayoutWrapper& pipelineLayout,
204 const VkRenderPass renderPass,
205 const ShaderWrapper vertexModule,
206 const ShaderWrapper fragmentModule,
207 const tcu::IVec2& framebufferSize)
208 {
209 const std::vector<VkViewport> viewports { makeViewport(framebufferSize) };
210 const std::vector<VkRect2D> scissors { makeRect2D(framebufferSize) };
211 VkSampleMask sampleMask = 0xffff;
212
213 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
214 {
215 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
216 DE_NULL, // const void* pNext
217 0u, // VkPipelineMultisampleStateCreateFlags flags
218 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits rasterizationSamples
219 DE_FALSE, // VkBool32 sampleShadingEnable
220 0.0f, // float minSampleShading
221 &sampleMask, // const VkSampleMask* pSampleMask
222 DE_FALSE, // VkBool32 alphaToCoverageEnable
223 DE_FALSE, // VkBool32 alphaToOneEnable
224 };
225
226 gpw.setDefaultDepthStencilState()
227 .setDefaultColorBlendState()
228 .setDefaultRasterizationState()
229 .setupVertexInputState()
230 .setupPreRasterizationShaderState(viewports,
231 scissors,
232 pipelineLayout,
233 renderPass,
234 0u,
235 vertexModule)
236 .setupFragmentShaderState(pipelineLayout,
237 renderPass,
238 0u,
239 fragmentModule,
240 DE_NULL,
241 &multisampleStateCreateInfo)
242 .setupFragmentOutputState(renderPass, 0u, DE_NULL, &multisampleStateCreateInfo)
243 .setMonolithicPipelineLayout(pipelineLayout)
244 .buildPipeline();
245 }
246
iterate(void)247 tcu::TestStatus MultisampleRenderAreaTestInstance::iterate (void)
248 {
249 const InstanceInterface& vki = m_context.getInstanceInterface();
250 const DeviceInterface& vk = m_context.getDeviceInterface();
251 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
252 const VkDevice device = m_context.getDevice();
253 Allocator& allocator = m_context.getDefaultAllocator();
254 const VkQueue queue = m_context.getUniversalQueue();
255 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
256 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
257
258 const ShaderWrapper vertexModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
259 const ShaderWrapper fragmentModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
260
261 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(m_framebufferSize, m_sampleCount)));
262 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
263 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, colorSubresourceRange));
264
265 const Unique<VkImage> resolveColorImage (makeImage(vk, device, makeImageCreateInfo(m_framebufferSize, 1u)));
266 const UniquePtr<Allocation> resolveColorImageAlloc (bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
267 const Unique<VkImageView> resolveColorImageView (makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, colorSubresourceRange));
268
269 const VkImage images[] = { *colorImage, *resolveColorImage };
270 const VkImageView attachmentImages[] = { *colorImageView, *resolveColorImageView };
271 const deUint32 numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
272
273 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(m_colorFormat)) * m_framebufferSize.x() * m_framebufferSize.y();
274 const Unique<VkBuffer> colorBufferResults (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
275 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBufferResults, MemoryRequirement::HostVisible));
276
277 RenderPassWrapper renderPassOne (makeRenderPass(vk, device, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED));
278 RenderPassWrapper renderPassTwo (makeRenderPass(vk, device, m_colorFormat, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
279 renderPassOne.createFramebuffer(vk, device, numUsedAttachmentImages, images, attachmentImages, m_framebufferSize.x(), m_framebufferSize.y());
280 renderPassTwo.createFramebuffer(vk, device, numUsedAttachmentImages, images, attachmentImages, m_framebufferSize.x(), m_framebufferSize.y());
281
282 const PipelineLayoutWrapper pipelineLayout (m_pipelineConstructionType, vk, device);
283 GraphicsPipelineWrapper graphicsPipeline {vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_pipelineConstructionType};
284
285 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
286 const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
287
288 // Main vertex buffer
289 const deUint32 numVertices = 6;
290 const VkDeviceSize vertexBufferSizeBytes = 256;
291 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
292 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
293
294 preparePipelineWrapper(graphicsPipeline, pipelineLayout, *renderPassOne, vertexModule, fragmentModule, m_framebufferSize);
295
296 {
297 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
298
299 // The shapes should fit just and just inside the renderArea.
300 if (m_testShape == TestShape::SHAPE_RECTANGLE)
301 {
302 float size = 0.5f;
303
304 pVertices[0] = tcu::Vec4(size, -size, 0.0f, 1.0f);
305 pVertices[1] = tcu::Vec4(-size, -size, 0.0f, 1.0f);
306 pVertices[2] = tcu::Vec4(-size, size, 0.0f, 1.0f);
307
308 pVertices[3] = tcu::Vec4(-size, size, 0.0f, 1.0f);
309 pVertices[4] = tcu::Vec4(size, size, 0.0f, 1.0f);
310 pVertices[5] = tcu::Vec4(size, -size, 0.0f, 1.0f);
311 }
312
313 if (m_testShape == TestShape::SHAPE_DIAMOND)
314 {
315 float size = 0.5f;
316
317 pVertices[0] = tcu::Vec4( size, 0.0f, 0.0f, 1.0f);
318 pVertices[1] = tcu::Vec4(-0.0f, -size, 0.0f, 1.0f);
319 pVertices[2] = tcu::Vec4(-size, 0.0f, 0.0f, 1.0f);
320
321 pVertices[3] = tcu::Vec4( size, 0.0f, 0.0f, 1.0f);
322 pVertices[4] = tcu::Vec4(-size, 0.0f, 0.0f, 1.0f);
323 pVertices[5] = tcu::Vec4(-0.0f, size, 0.0f, 1.0f);
324 }
325
326 if (m_testShape == TestShape::SHAPE_PARALLELOGRAM)
327 {
328 float size = 0.3125f;
329
330 pVertices[0] = tcu::Vec4(size, -size, 0.0f, 1.0f);
331 pVertices[1] = tcu::Vec4(-0.5f, -size, 0.0f, 1.0f);
332 pVertices[2] = tcu::Vec4(-size, size, 0.0f, 1.0f);
333
334 pVertices[3] = tcu::Vec4(-size, size, 0.0f, 1.0f);
335 pVertices[4] = tcu::Vec4(0.5f, size, 0.0f, 1.0f);
336 pVertices[5] = tcu::Vec4(size, -size, 0.0f, 1.0f);
337 }
338
339 flushAlloc(vk, device, *vertexBufferAlloc);
340 }
341
342 const VkDeviceSize vertexBufferOffset = 0ull;
343
344 const VkRect2D testRenderArea =
345 {
346 makeOffset2D(m_framebufferSize.x() / 4u, m_framebufferSize.x() / 4u),
347 makeExtent2D(m_framebufferSize.x() / 2u, m_framebufferSize.y() / 2u),
348 };
349
350 const std::vector<VkClearValue> clearValuesFullArea = { makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)), makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)) };
351 const std::vector<VkClearValue> clearValuesTestArea = { makeClearValueColor(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)), makeClearValueColor(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)) };
352
353 beginCommandBuffer(vk, *commandBuffer);
354
355 const VkRect2D fullRenderArea =
356 {
357 makeOffset2D(0u, 0u),
358 makeExtent2D(m_framebufferSize.x(), m_framebufferSize.y()),
359 };
360
361 // Clear whole render area with red color.
362 renderPassOne.begin(vk, *commandBuffer, fullRenderArea, static_cast<deUint32>(clearValuesFullArea.size()), clearValuesFullArea.data());
363 renderPassTwo.end(vk, *commandBuffer);
364
365 // Draw shape when render area size is halved.
366 renderPassTwo.begin(vk, *commandBuffer, testRenderArea, static_cast<deUint32>(clearValuesTestArea.size()), clearValuesTestArea.data());
367 vk.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
368 graphicsPipeline.bind(*commandBuffer);
369 vk.cmdDraw(*commandBuffer, numVertices, 1u, 0u, 0u);
370 renderPassTwo.end(vk, *commandBuffer);
371
372 copyImageToBuffer(vk, *commandBuffer, *resolveColorImage, *colorBufferResults, m_framebufferSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
373
374 endCommandBuffer(vk, *commandBuffer);
375 submitCommandsAndWait(vk, device, queue, *commandBuffer);
376
377 // Verify color output
378 {
379 invalidateAlloc(vk, device, *colorBufferAlloc);
380
381 tcu::TestLog& log = m_context.getTestContext().getLog();
382 const Unique<VkBuffer> testBufferResults (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
383 tcu::ConstPixelBufferAccess imageAccess (mapVkFormat(m_colorFormat), m_framebufferSize.x(), m_framebufferSize.y(), 1, colorBufferAlloc->getHostPtr());
384
385 // Color check for rendered shape. Shape color is yellow.
386 if (imageAccess.getPixel(m_framebufferSize.x() / 2, m_framebufferSize.y() / 2) != tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f))
387 {
388 log << tcu::TestLog::Image("color0", "Rendered image", imageAccess);
389 return tcu::TestStatus::fail("Pixel check failed: shape color");
390 }
391
392 // Color check for the second render area. Clear color should be green.
393 if (m_testShape != TestShape::SHAPE_RECTANGLE) // In this case the shape has covered the whole render area.
394 {
395 if (imageAccess.getPixel(m_framebufferSize.x() / 4 + 1, m_framebufferSize.y() / 4 + 1) != tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f))
396 {
397 log << tcu::TestLog::Image("color0", "Rendered image", imageAccess);
398 return tcu::TestStatus::fail("Pixel check failed inside the render area");
399 }
400 }
401
402 // Color check for possible overflowed multisample pixels outside of the second render area.
403 // Clear color after the first beginRenderPass should be red.
404 const int minValue = m_framebufferSize.y() / 4 - 1;
405 const int maxValue = m_framebufferSize.y() - m_framebufferSize.y() / 4;
406
407 for (int y = 0; y < m_framebufferSize.y(); y++)
408 {
409 for (int x = 0; x < m_framebufferSize.x(); x++)
410 {
411 if (!(x > minValue && y > minValue && x < maxValue && y < maxValue))
412 {
413 if (imageAccess.getPixel(x, y) != tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f))
414 {
415 log << tcu::TestLog::Message << "Incorrect color value " << imageAccess.getPixel(x, y) << " at location (" << x << ", " << y << ")" << tcu::TestLog::EndMessage;
416 log << tcu::TestLog::Image("color0", "Rendered image", imageAccess);
417 return tcu::TestStatus::fail("Pixel check failed outside the render area");
418 }
419 }
420 }
421 }
422 }
423
424 return tcu::TestStatus::pass("Success");
425 }
426
427 class MultisampleRenderAreaTest : public TestCase
428 {
429 public:
MultisampleRenderAreaTest(tcu::TestContext& testCtx, const std::string name, const PipelineConstructionType pipelineConstructionType, const deUint32 sampleCount, const tcu::IVec2 framebufferSize, const TestShape testShape, const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM)430 MultisampleRenderAreaTest (tcu::TestContext& testCtx,
431 const std::string name,
432 const PipelineConstructionType pipelineConstructionType,
433 const deUint32 sampleCount,
434 const tcu::IVec2 framebufferSize,
435 const TestShape testShape,
436 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM)
437 : TestCase(testCtx, name)
438 , m_pipelineConstructionType (pipelineConstructionType)
439 , m_sampleCount (sampleCount)
440 , m_framebufferSize (framebufferSize)
441 , m_testShape (testShape)
442 , m_colorFormat (colorFormat)
443 {}
444
445 void initPrograms (SourceCollections& programCollection) const;
446 TestInstance* createInstance (Context& context) const;
447 virtual void checkSupport (Context& context) const;
448
449 private:
450
451 const PipelineConstructionType m_pipelineConstructionType;
452 const deUint32 m_sampleCount;
453 const tcu::IVec2 m_framebufferSize;
454 const TestShape m_testShape;
455 const VkFormat m_colorFormat;
456 };
457
initPrograms(SourceCollections& programCollection) const458 void MultisampleRenderAreaTest::initPrograms(SourceCollections& programCollection) const
459 {
460 // Vertex shader
461 {
462 std::ostringstream src;
463 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
464 << "\n"
465 << "layout(location = 0) in vec4 position;\n"
466 << "\n"
467 << "void main (void)\n"
468 << "{\n"
469 << " gl_Position = position;\n"
470 << "}\n";
471
472 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
473 }
474
475 // Fragment shader
476 {
477 std::ostringstream frg;
478 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
479 << "\n"
480 << "layout(location = 0) out vec4 fragColor;\n"
481 << "\n"
482 << "void main (void)\n"
483 << "{\n"
484 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
485 << "}\n";
486
487 programCollection.glslSources.add("frag") << glu::FragmentSource(frg.str());
488 }
489 }
490
createInstance(Context& context) const491 TestInstance* MultisampleRenderAreaTest::createInstance(Context& context) const
492 {
493 return new MultisampleRenderAreaTestInstance(context, m_pipelineConstructionType, m_sampleCount, m_framebufferSize, m_testShape, m_colorFormat);
494 }
495
checkSupport(Context& context) const496 void MultisampleRenderAreaTest::checkSupport(Context& context) const
497 {
498 // Check support for MSAA image format used in the test.
499 const InstanceInterface& vki = context.getInstanceInterface();
500 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
501
502 VkImageFormatProperties formatProperties;
503
504 vki.getPhysicalDeviceImageFormatProperties (physDevice, m_colorFormat,
505 VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
506 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
507 0u, &formatProperties);
508
509 if ((formatProperties.sampleCounts & m_sampleCount) == 0)
510 TCU_THROW(NotSupportedError, "Format does not support this number of samples");
511
512 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
513 }
514
515 } // anonymous
516
createMultisampleResolveRenderpassRenderAreaTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)517 tcu::TestCaseGroup* createMultisampleResolveRenderpassRenderAreaTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
518 {
519 // resolving multisample image tests
520 de::MovePtr<tcu::TestCaseGroup> testGroupResolve(new tcu::TestCaseGroup(testCtx, "resolve"));
521
522 de::MovePtr<tcu::TestCaseGroup> testGroupRenderArea(new tcu::TestCaseGroup(testCtx, "renderpass_renderarea", "renderpass render area tests"));
523
524 static const struct
525 {
526 std::string shapeName;
527 TestShape testShape;
528 } shapes[] =
529 {
530 { "rectangle", TestShape::SHAPE_RECTANGLE },
531 { "diamond", TestShape::SHAPE_DIAMOND },
532 { "parallelogram", TestShape::SHAPE_PARALLELOGRAM }
533 };
534
535 static const struct
536 {
537 std::string caseName;
538 const deUint32 sampleCount;
539 } cases[] =
540 {
541 { "samples_2", 2u, },
542 { "samples_4", 4u, },
543 { "samples_8", 8u, },
544 { "samples_16", 16u },
545 };
546
547 for (const auto& testShape : shapes)
548 {
549 for (const auto& testCase : cases)
550 {
551 testGroupRenderArea->addChild(new MultisampleRenderAreaTest(testCtx, testShape.shapeName + "_" + testCase.caseName, pipelineConstructionType, testCase.sampleCount, tcu::IVec2(32, 32), testShape.testShape));
552 }
553 }
554
555 testGroupResolve->addChild(testGroupRenderArea.release());
556
557 return testGroupResolve.release();
558 }
559
560 } // pipeline
561 } // vkt
562