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