1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file vktPipelineFramebuferAttachmentTests.cpp
23 * \brief Render to a framebuffer with attachments of different sizes and with
24 * no attachments at all
25 *
26 *//*--------------------------------------------------------------------*/
27
28 #include "vktPipelineFramebufferAttachmentTests.hpp"
29 #include "vktPipelineMakeUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktTestCaseUtil.hpp"
32 #include "vktPipelineVertexUtil.hpp"
33 #include "vktTestGroupUtil.hpp"
34
35 #include "vkMemUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkBuilderUtil.hpp"
41 #include "vkPrograms.hpp"
42 #include "vkImageUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45
46 #include "tcuTextureUtil.hpp"
47 #include "tcuImageCompare.hpp"
48
49 #include "deUniquePtr.hpp"
50 #include "deSharedPtr.hpp"
51
52 #include <string>
53 #include <vector>
54
55 namespace vkt
56 {
57 namespace pipeline
58 {
59 namespace
60 {
61 using namespace vk;
62 using de::MovePtr;
63 using de::SharedPtr;
64 using de::UniquePtr;
65 using std::vector;
66 using tcu::IVec3;
67 using tcu::IVec4;
68 using tcu::UVec4;
69 using tcu::Vec4;
70
71 static const VkFormat COLOR_FORMAT = VK_FORMAT_R8G8B8A8_UNORM;
72
73 typedef SharedPtr<Unique<VkImageView>> SharedPtrVkImageView;
74
75 enum MultiAttachmentsTestType
76 {
77 MULTI_ATTACHMENTS_NONE,
78 MULTI_ATTACHMENTS_DIFFERENT_SIZES,
79 MULTI_ATTACHMENTS_NOT_EXPORTED,
80 };
81
82 struct CaseDef
83 {
84 PipelineConstructionType pipelineConstructionType;
85 VkImageViewType imageType;
86 IVec3 renderSize;
87 IVec3 attachmentSize;
88 uint32_t numLayers;
89 bool multisample;
90 MultiAttachmentsTestType multiAttachmentsTestType;
91 };
92
93 template <typename T>
makeSharedPtr(Move<T> move)94 inline SharedPtr<Unique<T>> makeSharedPtr(Move<T> move)
95 {
96 return SharedPtr<Unique<T>>(new Unique<T>(move));
97 }
98
99 template <typename T>
sizeInBytes(const vector<T> & vec)100 inline VkDeviceSize sizeInBytes(const vector<T> &vec)
101 {
102 return vec.size() * sizeof(vec[0]);
103 }
104
getImageType(const VkImageViewType viewType)105 VkImageType getImageType(const VkImageViewType viewType)
106 {
107 switch (viewType)
108 {
109 case VK_IMAGE_VIEW_TYPE_1D:
110 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
111 return VK_IMAGE_TYPE_1D;
112
113 case VK_IMAGE_VIEW_TYPE_2D:
114 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
115 case VK_IMAGE_VIEW_TYPE_CUBE:
116 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
117 return VK_IMAGE_TYPE_2D;
118
119 case VK_IMAGE_VIEW_TYPE_3D:
120 return VK_IMAGE_TYPE_3D;
121
122 default:
123 DE_ASSERT(0);
124 return VK_IMAGE_TYPE_LAST;
125 }
126 }
127
128 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,const uint32_t numLayers,const bool multisample)129 RenderPassWrapper makeRenderPass(const DeviceInterface &vk, const VkDevice device,
130 const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat,
131 const uint32_t numLayers, const bool multisample)
132 {
133 vector<VkAttachmentDescription> attachmentDescriptions(numLayers);
134 uint32_t attachmentIndex = 0;
135 vector<VkAttachmentReference> colorAttachmentReferences(numLayers);
136 vector<VkSubpassDescription> subpasses;
137
138 for (uint32_t i = 0; i < numLayers; i++)
139 {
140 VkAttachmentDescription colorAttachmentDescription = {
141 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags;
142 colorFormat, // VkFormat format;
143 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
144 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
145 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
146 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
147 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
148 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
149 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
150 };
151 attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription;
152 }
153
154 // Create a subpass for each attachment (each attachment is a layer of an arrayed image).
155 for (uint32_t i = 0; i < numLayers; ++i)
156 {
157 const VkAttachmentReference attachmentRef = {
158 i, // uint32_t attachment;
159 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
160 };
161 colorAttachmentReferences[i] = attachmentRef;
162
163 const VkSubpassDescription subpassDescription = {
164 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
165 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
166 0u, // uint32_t inputAttachmentCount;
167 DE_NULL, // const VkAttachmentReference* pInputAttachments;
168 1u, // uint32_t colorAttachmentCount;
169 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
170 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
171 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
172 0u, // uint32_t preserveAttachmentCount;
173 DE_NULL // const uint32_t* pPreserveAttachments;
174 };
175 subpasses.push_back(subpassDescription);
176 }
177
178 const VkRenderPassCreateInfo renderPassInfo = {
179 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
180 DE_NULL, // const void* pNext;
181 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
182 numLayers, // uint32_t attachmentCount;
183 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
184 static_cast<uint32_t>(subpasses.size()), // uint32_t subpassCount;
185 &subpasses[0], // const VkSubpassDescription* pSubpasses;
186 0u, // uint32_t dependencyCount;
187 DE_NULL // const VkSubpassDependency* pDependencies;
188 };
189
190 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
191 }
192
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertexModule,const ShaderWrapper fragmentModule,const IVec3 renderSize,const VkPrimitiveTopology topology,const uint32_t subpass,const uint32_t numAttachments,const bool multisample)193 void preparePipelineWrapper(GraphicsPipelineWrapper &gpw, const PipelineLayoutWrapper &pipelineLayout,
194 const VkRenderPass renderPass, const ShaderWrapper vertexModule,
195 const ShaderWrapper fragmentModule, const IVec3 renderSize,
196 const VkPrimitiveTopology topology, const uint32_t subpass, const uint32_t numAttachments,
197 const bool multisample)
198 {
199 const std::vector<VkViewport> viewports{makeViewport(renderSize)};
200 const std::vector<VkRect2D> scissors{makeRect2D(renderSize)};
201
202 const VkColorComponentFlags colorComponentsAll =
203 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
204
205 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo{
206 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
207 DE_NULL, // const void* pNext;
208 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
209 multisample ? VK_SAMPLE_COUNT_4_BIT :
210 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
211 VK_FALSE, // VkBool32 sampleShadingEnable;
212 1.0f, // float minSampleShading;
213 DE_NULL, // const VkSampleMask* pSampleMask;
214 VK_FALSE, // VkBool32 alphaToCoverageEnable;
215 VK_FALSE // VkBool32 alphaToOneEnable;
216 };
217
218 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState{
219 VK_FALSE, // VkBool32 blendEnable;
220 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
221 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
222 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
223 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
224 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
225 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
226 colorComponentsAll // VkColorComponentFlags colorWriteMask;
227 };
228
229 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
230 for (uint32_t attachmentIdx = 0; attachmentIdx < numAttachments; attachmentIdx++)
231 colorBlendAttachmentStates.push_back(pipelineColorBlendAttachmentState);
232
233 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo{
234 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
235 DE_NULL, // const void* pNext;
236 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
237 VK_FALSE, // VkBool32 logicOpEnable;
238 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
239 numAttachments, // uint32_t attachmentCount;
240 numAttachments == 0 ?
241 DE_NULL :
242 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
243 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
244 };
245
246 gpw.setDefaultTopology(topology)
247 .setDefaultRasterizationState()
248 .setDefaultDepthStencilState()
249 .setupVertexInputState()
250 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, subpass, vertexModule)
251 .setupFragmentShaderState(pipelineLayout, renderPass, subpass, fragmentModule, DE_NULL,
252 &pipelineMultisampleStateInfo)
253 .setupFragmentOutputState(renderPass, subpass, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
254 .setMonolithicPipelineLayout(pipelineLayout)
255 .buildPipeline();
256 }
257
makeImage(const DeviceInterface & vk,const VkDevice device,const VkImageCreateFlags flags,const VkImageType imageType,const VkFormat format,const IVec3 & size,const uint32_t numLayers,const VkImageUsageFlags usage,const bool multisample)258 Move<VkImage> makeImage(const DeviceInterface &vk, const VkDevice device, const VkImageCreateFlags flags,
259 const VkImageType imageType, const VkFormat format, const IVec3 &size, const uint32_t numLayers,
260 const VkImageUsageFlags usage, const bool multisample)
261 {
262 const VkImageCreateInfo imageParams = {
263 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
264 DE_NULL, // const void* pNext;
265 flags, // VkImageCreateFlags flags;
266 imageType, // VkImageType imageType;
267 format, // VkFormat format;
268 makeExtent3D(size), // VkExtent3D extent;
269 1u, // uint32_t mipLevels;
270 numLayers, // uint32_t arrayLayers;
271 multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
272 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
273 usage, // VkImageUsageFlags usage;
274 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
275 0u, // uint32_t queueFamilyIndexCount;
276 DE_NULL, // const uint32_t* pQueueFamilyIndices;
277 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
278 };
279
280 return createImage(vk, device, &imageParams);
281 }
282
genFullQuadVertices(const int subpassCount)283 vector<tcu::Vec4> genFullQuadVertices(const int subpassCount)
284 {
285 vector<tcu::Vec4> vectorData;
286 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
287 {
288 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
289 vectorData.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
290 vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
291 vectorData.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
292 }
293 return vectorData;
294 }
295
initColorPrograms(SourceCollections & programCollection,const CaseDef)296 void initColorPrograms(SourceCollections &programCollection, const CaseDef)
297 {
298 // Vertex shader
299 {
300 std::ostringstream src;
301 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
302 << "\n"
303 << "layout(location = 0) in vec4 in_position;\n"
304 << "\n"
305 << "out gl_PerVertex {\n"
306 << " vec4 gl_Position;\n"
307 << "};\n"
308 << "\n"
309 << "void main(void)\n"
310 << "{\n"
311 << " gl_Position = in_position;\n"
312 << "}\n";
313
314 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
315 }
316
317 // Fragment shader
318 {
319 std::ostringstream src;
320 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
321 << "\n"
322 << "layout(location = 0) out vec4 o_color;\n"
323 << "\n"
324 << "void main(void)\n"
325 << "{\n"
326 << " o_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
327 << "}\n";
328
329 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
330 }
331 }
332
getExpectedData(tcu::TextureLevel & textureLevel,const CaseDef & caseDef)333 tcu::PixelBufferAccess getExpectedData(tcu::TextureLevel &textureLevel, const CaseDef &caseDef)
334 {
335 const tcu::PixelBufferAccess expectedImage(textureLevel);
336 const int renderDepth = deMax32(caseDef.renderSize.z(), caseDef.numLayers);
337
338 for (int z = 0; z < expectedImage.getDepth(); ++z)
339 {
340 for (int y = 0; y < expectedImage.getHeight(); ++y)
341 {
342 for (int x = 0; x < expectedImage.getWidth(); ++x)
343 {
344 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth)
345 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
346 else
347 expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z);
348 }
349 }
350 }
351 return expectedImage;
352 }
353
makeColorSubresourceRange(const uint32_t baseArrayLayer,const uint32_t layerCount)354 inline VkImageSubresourceRange makeColorSubresourceRange(const uint32_t baseArrayLayer, const uint32_t layerCount)
355 {
356 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
357 }
358
359 // Tests rendering to a a framebuffer with color attachments larger than the
360 // framebuffer dimensions and verifies that rendering does not affect the areas
361 // of the attachment outside the framebuffer dimensions. Tests both single-sample
362 // and multi-sample configurations.
test(Context & context,const CaseDef caseDef)363 tcu::TestStatus test(Context &context, const CaseDef caseDef)
364 {
365 const InstanceInterface &vki = context.getInstanceInterface();
366 const DeviceInterface &vk = context.getDeviceInterface();
367 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
368 const VkDevice device = context.getDevice();
369 const VkQueue queue = context.getUniversalQueue();
370 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
371 Allocator &allocator = context.getDefaultAllocator();
372
373 // Color image for rendering in single-sample tests or resolve target for multi-sample tests
374 Move<VkImage> colorImage;
375 MovePtr<Allocation> colorImageAlloc;
376
377 // For multisampled tests, this is the rendering target
378 Move<VkImage> msColorImage;
379 MovePtr<Allocation> msColorImageAlloc;
380
381 // Host memory buffer where we will copy the rendered image for verification
382 const uint32_t att_size_x = caseDef.attachmentSize.x();
383 const uint32_t att_size_y = caseDef.attachmentSize.y();
384 const uint32_t att_size_z = caseDef.attachmentSize.z();
385 const VkDeviceSize colorBufferSize =
386 att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
387 const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
388 const UniquePtr<Allocation> colorBufferAlloc(
389 bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
390
391 Move<VkBuffer> vertexBuffer;
392 MovePtr<Allocation> vertexBufferAlloc;
393
394 vector<SharedPtrVkImageView> colorAttachments;
395 vector<VkImage> images;
396 vector<VkImageView> attachmentHandles;
397
398 const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device);
399 vector<GraphicsPipelineWrapper> pipeline;
400 RenderPassWrapper renderPass(makeRenderPass(vk, device, caseDef.pipelineConstructionType, COLOR_FORMAT,
401 caseDef.numLayers, caseDef.multisample));
402
403 const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
404 const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
405
406 const Unique<VkCommandPool> cmdPool(
407 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
408 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
409
410 const VkImageViewType imageViewType =
411 caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ?
412 VK_IMAGE_VIEW_TYPE_2D :
413 caseDef.imageType;
414
415 // create vertexBuffer
416 {
417 const vector<tcu::Vec4> vertices = genFullQuadVertices(caseDef.numLayers);
418 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
419
420 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
421 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
422
423 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
424 flushAlloc(vk, device, *vertexBufferAlloc);
425 }
426
427 // create colorImage (and msColorImage) using the configured attachmentsize
428 {
429 const VkImageUsageFlags colorImageUsage =
430 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
431
432 colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
433 caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
434 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
435
436 if (caseDef.multisample)
437 {
438 const VkImageUsageFlags msImageUsage =
439 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
440
441 msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
442 COLOR_FORMAT, caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
443 msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
444 }
445 }
446
447 // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
448 pipeline.reserve(caseDef.numLayers);
449 for (uint32_t layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
450 {
451 colorAttachments.push_back(
452 makeSharedPtr(makeImageView(vk, device, !caseDef.multisample ? *colorImage : *msColorImage, imageViewType,
453 COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
454 images.push_back(!caseDef.multisample ? *colorImage : *msColorImage);
455 attachmentHandles.push_back(**colorAttachments.back());
456
457 pipeline.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
458 caseDef.pipelineConstructionType);
459 preparePipelineWrapper(pipeline.back(), pipelineLayout, *renderPass, vertexModule, fragmentModule,
460 caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u,
461 caseDef.multisample);
462 }
463
464 // create framebuffer
465 renderPass.createFramebuffer(vk, device, caseDef.numLayers, &images[0], &attachmentHandles[0],
466 static_cast<uint32_t>(caseDef.renderSize.x()),
467 static_cast<uint32_t>(caseDef.renderSize.y()));
468
469 // record command buffer
470 beginCommandBuffer(vk, *cmdBuffer);
471 {
472 // Clear the entire image attachment to black
473 {
474 const VkImageMemoryBarrier imageLayoutBarriers[] = {
475 {
476 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
477 DE_NULL, // const void* pNext;
478 0u, // VkAccessFlags srcAccessMask;
479 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
480 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
481 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
482 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
483 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
484 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
485 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
486 },
487 };
488
489 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
490 DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
491
492 const VkImageSubresourceRange ranges = makeColorSubresourceRange(0, caseDef.numLayers);
493 const VkClearColorValue clearColor = {{0.0f, 0.0f, 0.0f, 1.0f}};
494 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage,
495 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
496
497 const VkImageMemoryBarrier imageClearBarriers[] = {
498 {
499 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
500 DE_NULL, // const void* pNext;
501 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
502 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
503 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
504 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
505 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
506 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
507 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
508 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
509 },
510 };
511
512 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
513 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
514 imageClearBarriers);
515 }
516
517 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
518 {
519 const VkDeviceSize vertexBufferOffset = 0ull;
520
521 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
522 {
523 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
524 for (uint32_t layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
525 {
526 if (layerNdx != 0)
527 renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
528
529 pipeline[layerNdx].bind(*cmdBuffer);
530 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx * 4u, 0u);
531 }
532 }
533 renderPass.end(vk, *cmdBuffer);
534 }
535
536 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
537 if (caseDef.multisample)
538 {
539 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
540 const VkImageMemoryBarrier imageBarriers[] = {
541 {
542 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
543 DE_NULL, // const void* pNext;
544 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
545 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
546 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
547 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
548 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
549 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
550 *msColorImage, // VkImage image;
551 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
552 },
553 {
554 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
555 DE_NULL, // const void* pNext;
556 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
557 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
558 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
559 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
560 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
561 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
562 *colorImage, // VkImage image;
563 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
564 }};
565
566 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
567 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
568
569 const VkImageResolve region = {
570 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
571 caseDef.numLayers), // VkImageSubresourceLayers srcSubresource;
572 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
573 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
574 caseDef.numLayers), // VkImageSubresourceLayers dstSubresource;
575 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
576 makeExtent3D(caseDef.attachmentSize) // VkExtent3D extent;
577 };
578
579 vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL,
580 1, ®ion);
581 }
582
583 // copy colorImage to host visible colorBuffer
584 {
585 const VkImageMemoryBarrier imageBarriers[] = {{
586 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
587 DE_NULL, // const void* pNext;
588 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT :
589 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
590 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
591 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL :
592 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
593 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
594 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
595 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
596 *colorImage, // VkImage image;
597 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
598 }};
599
600 vk.cmdPipelineBarrier(*cmdBuffer,
601 caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT :
602 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
603 VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
604
605 const VkBufferImageCopy region = {
606 0ull, // VkDeviceSize bufferOffset;
607 0u, // uint32_t bufferRowLength;
608 0u, // uint32_t bufferImageHeight;
609 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
610 caseDef.numLayers), // VkImageSubresourceLayers imageSubresource;
611 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
612 makeExtent3D(caseDef.attachmentSize), // VkExtent3D imageExtent;
613 };
614
615 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u,
616 ®ion);
617
618 const VkBufferMemoryBarrier bufferBarriers[] = {
619 {
620 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
621 DE_NULL, // const void* pNext;
622 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
623 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
624 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
625 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
626 *colorBuffer, // VkBuffer buffer;
627 0ull, // VkDeviceSize offset;
628 VK_WHOLE_SIZE, // VkDeviceSize size;
629 },
630 };
631
632 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
633 DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
634 }
635 } // beginCommandBuffer
636
637 endCommandBuffer(vk, *cmdBuffer);
638 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
639
640 // Verify results
641 {
642 invalidateAlloc(vk, device, *colorBufferAlloc);
643 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
644 const int depth = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
645 tcu::TextureLevel textureLevel(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
646 const tcu::PixelBufferAccess expectedImage = getExpectedData(textureLevel, caseDef);
647 const tcu::ConstPixelBufferAccess resultImage(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(),
648 depth, colorBufferAlloc->getHostPtr());
649
650 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage,
651 resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
652 return tcu::TestStatus::fail("Fail");
653 }
654
655 return tcu::TestStatus::pass("Pass");
656 }
657
658 struct NoAttCaseDef
659 {
660 PipelineConstructionType pipelineConstructionType;
661 bool multisample;
662 };
663
initImagePrograms(SourceCollections & programCollection,const NoAttCaseDef caseDef)664 void initImagePrograms(SourceCollections &programCollection, const NoAttCaseDef caseDef)
665 {
666 // Vertex shader
667 {
668 std::ostringstream src;
669 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
670 << "\n"
671 << "layout(location = 0) in vec4 in_position;\n"
672 << "\n"
673 << "out gl_PerVertex {\n"
674 << " vec4 gl_Position;\n"
675 << " float gl_PointSize;\n"
676 << "};\n"
677 << "\n"
678 << "void main(void)\n"
679 << "{\n"
680 << " gl_Position = in_position;\n"
681 << " gl_PointSize = 1.0f;\n"
682 << "}\n";
683
684 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
685 }
686
687 // Fragment shader
688 {
689 std::ostringstream src;
690 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
691 << "\n"
692 << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
693 << "\n"
694 << "void main(void)\n"
695 << "{\n";
696 if (!caseDef.multisample)
697 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
698 else
699 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
700 src << "}\n";
701
702 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
703 }
704 }
705
706 //! Make a render pass with no attachments
makeRenderPassNoAtt(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType)707 RenderPassWrapper makeRenderPassNoAtt(const DeviceInterface &vk, const VkDevice device,
708 const PipelineConstructionType pipelineConstructionType)
709 {
710 // Create a single subpass with no attachment references
711 vector<VkSubpassDescription> subpasses;
712
713 const VkSubpassDescription subpassDescription = {
714 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
715 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
716 0u, // uint32_t inputAttachmentCount;
717 DE_NULL, // const VkAttachmentReference* pInputAttachments;
718 0u, // uint32_t colorAttachmentCount;
719 DE_NULL, // const VkAttachmentReference* pColorAttachments;
720 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
721 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
722 0u, // uint32_t preserveAttachmentCount;
723 DE_NULL // const uint32_t* pPreserveAttachments;
724 };
725 subpasses.push_back(subpassDescription);
726
727 const VkRenderPassCreateInfo renderPassInfo = {
728 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
729 DE_NULL, // const void* pNext;
730 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
731 0, // uint32_t attachmentCount;
732 DE_NULL, // const VkAttachmentDescription* pAttachments;
733 1, // uint32_t subpassCount;
734 &subpasses[0], // const VkSubpassDescription* pSubpasses;
735 0u, // uint32_t dependencyCount;
736 DE_NULL // const VkSubpassDependency* pDependencies;
737 };
738
739 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
740 }
741
getExpectedDataNoAtt(tcu::TextureLevel & textureLevel)742 tcu::PixelBufferAccess getExpectedDataNoAtt(tcu::TextureLevel &textureLevel)
743 {
744 const tcu::PixelBufferAccess expectedImage(textureLevel);
745 for (int z = 0; z < expectedImage.getDepth(); ++z)
746 {
747 for (int y = 0; y < expectedImage.getHeight(); ++y)
748 {
749 for (int x = 0; x < expectedImage.getWidth(); ++x)
750 {
751 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
752 }
753 }
754 }
755 return expectedImage;
756 }
757
genPointVertices(void)758 vector<tcu::Vec4> genPointVertices(void)
759 {
760 vector<tcu::Vec4> vectorData;
761 vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
762 vectorData.push_back(Vec4(-0.25f, 0.25f, 0, 1));
763 vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
764 vectorData.push_back(Vec4(0.25f, 0.25f, 0, 1));
765 return vectorData;
766 }
767
768 // Tests rendering to a framebuffer without color attachments, checking that
769 // the fragment shader is run even in the absence of color output. In this case
770 // we render 4 point primitives and we make the fragment shader write to a
771 // different pixel of an image via an imageStore command. For the single-sampled
772 // configuration we use a 4x1 image to record the output and for the
773 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
774 // 4-sample multi-sampling
testNoAtt(Context & context,const NoAttCaseDef caseDef)775 tcu::TestStatus testNoAtt(Context &context, const NoAttCaseDef caseDef)
776 {
777 const InstanceInterface &vki = context.getInstanceInterface();
778 const DeviceInterface &vk = context.getDeviceInterface();
779 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
780 const VkDevice device = context.getDevice();
781 const VkQueue queue = context.getUniversalQueue();
782 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
783 Allocator &allocator = context.getDefaultAllocator();
784 const IVec3 renderSize(32, 32, 1);
785
786 Move<VkBuffer> vertexBuffer;
787 MovePtr<Allocation> vertexBufferAlloc;
788
789 const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
790 const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
791
792 // Create image where we will record the writes. For single-sampled cases this is a 4x1 image
793 // and for multi-sampled cases this is a 4x<num_samples> image.
794 const uint8_t numSamples = caseDef.multisample ? 4 : 1;
795 const uint8_t imageWidth = 4;
796 const uint8_t imageHeight = numSamples;
797 const uint8_t imageDepth = 1;
798 const uint8_t imageLayers = 1;
799 const IVec3 imageDim = IVec3(imageWidth, imageHeight, imageDepth);
800 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
801 const Move<VkImage> image = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT,
802 imageDim, imageLayers, imageUsage, false);
803 const VkImageSubresourceRange imageSubresourceRange = makeColorSubresourceRange(0u, imageLayers);
804 const MovePtr<Allocation> imageAlloc = bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
805 const Move<VkImageView> imageView =
806 makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
807
808 // Create a buffer where we will copy the image for verification
809 const VkDeviceSize colorBufferSize =
810 imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
811 const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
812 const UniquePtr<Allocation> colorBufferAlloc(
813 bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
814
815 // Create pipeline descriptor set for the image
816 const Move<VkDescriptorSetLayout> descriptorSetLayout =
817 DescriptorSetLayoutBuilder()
818 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
819 .build(vk, device);
820
821 const Move<VkDescriptorPool> descriptorPool =
822 DescriptorPoolBuilder()
823 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
824 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
825
826 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
827 const VkDescriptorImageInfo descriptorImageInfo =
828 makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
829 DescriptorSetUpdateBuilder()
830 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
831 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
832 .update(vk, device);
833
834 const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
835 GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
836 caseDef.pipelineConstructionType);
837 RenderPassWrapper renderPass = makeRenderPassNoAtt(vk, device, caseDef.pipelineConstructionType);
838
839 const Unique<VkCommandPool> cmdPool(
840 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
841 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
842
843 // create vertexBuffer
844 {
845 const vector<tcu::Vec4> vertices = genPointVertices();
846 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
847
848 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
849 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
850 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
851 flushAlloc(vk, device, *vertexBufferAlloc);
852 }
853
854 // Create pipeline
855 preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, renderSize,
856 VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, caseDef.multisample);
857 renderPass.createFramebuffer(vk, device, 0, DE_NULL, renderSize.x(), renderSize.y());
858
859 // Record command buffer
860 beginCommandBuffer(vk, *cmdBuffer);
861 {
862 // shader image layout transition undefined -> general
863 {
864 const VkImageMemoryBarrier setImageLayoutBarrier =
865 makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
866 VK_IMAGE_LAYOUT_GENERAL, *image, imageSubresourceRange);
867
868 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
869 0, 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
870 }
871
872 // Render pass
873 {
874 const VkDeviceSize vertexBufferOffset = 0ull;
875
876 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()));
877
878 pipeline.bind(*cmdBuffer);
879 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
880 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
881 &descriptorSet.get(), 0u, DE_NULL);
882 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
883
884 renderPass.end(vk, *cmdBuffer);
885 }
886
887 // copy image to host visible colorBuffer
888 {
889 const VkImageMemoryBarrier imageBarriers[] = {{
890 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
891 DE_NULL, // const void* pNext;
892 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
893 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
894 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout;
895 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
896 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
897 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
898 *image, // VkImage image;
899 makeColorSubresourceRange(0, 1) // VkImageSubresourceRange subresourceRange;
900 }};
901
902 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
903 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
904
905 const VkBufferImageCopy region = {
906 0ull, // VkDeviceSize bufferOffset;
907 0u, // uint32_t bufferRowLength;
908 0u, // uint32_t bufferImageHeight;
909 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
910 1), // VkImageSubresourceLayers imageSubresource;
911 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
912 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)), // VkExtent3D imageExtent;
913 };
914
915 vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u,
916 ®ion);
917
918 const VkBufferMemoryBarrier bufferBarriers[] = {
919 {
920 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
921 DE_NULL, // const void* pNext;
922 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
923 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
924 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
925 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
926 *colorBuffer, // VkBuffer buffer;
927 0ull, // VkDeviceSize offset;
928 VK_WHOLE_SIZE, // VkDeviceSize size;
929 },
930 };
931
932 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
933 DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
934 }
935 } // beginCommandBuffer
936
937 endCommandBuffer(vk, *cmdBuffer);
938 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
939
940 // Verify results
941 {
942 invalidateAlloc(vk, device, *colorBufferAlloc);
943 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
944 tcu::TextureLevel textureLevel(format, imageWidth, imageHeight, imageDepth);
945 const tcu::PixelBufferAccess expectedImage = getExpectedDataNoAtt(textureLevel);
946 const tcu::ConstPixelBufferAccess resultImage(format, imageWidth, imageHeight, imageDepth,
947 colorBufferAlloc->getHostPtr());
948
949 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage,
950 resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
951 return tcu::TestStatus::fail("Fail");
952 }
953
954 return tcu::TestStatus::pass("Pass");
955 }
956
957 //! Make a render pass with three color attachments
makeRenderPassMultiAttachments(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,uint32_t numAttachments,const bool multisample)958 RenderPassWrapper makeRenderPassMultiAttachments(const DeviceInterface &vk, const VkDevice device,
959 const PipelineConstructionType pipelineConstructionType,
960 const VkFormat colorFormat, uint32_t numAttachments,
961 const bool multisample)
962 {
963 vector<VkAttachmentDescription> attachmentDescriptions(numAttachments);
964 vector<VkAttachmentReference> colorAttachmentReferences(numAttachments);
965
966 for (uint32_t i = 0; i < numAttachments; i++)
967 {
968 VkAttachmentDescription colorAttachmentDescription = {
969 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags;
970 colorFormat, // VkFormat format;
971 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
972 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
973 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
974 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
975 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
976 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
977 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
978 };
979 attachmentDescriptions[i] = colorAttachmentDescription;
980
981 const VkAttachmentReference attachmentRef = {
982 i, // uint32_t attachment;
983 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
984 };
985 colorAttachmentReferences[i] = attachmentRef;
986 }
987
988 const VkSubpassDescription subpassDescription = {
989 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
990 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
991 0u, // uint32_t inputAttachmentCount;
992 DE_NULL, // const VkAttachmentReference* pInputAttachments;
993 numAttachments, // uint32_t colorAttachmentCount;
994 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
995 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
996 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
997 0u, // uint32_t preserveAttachmentCount;
998 DE_NULL // const uint32_t* pPreserveAttachments;
999 };
1000
1001 const VkRenderPassCreateInfo renderPassInfo = {
1002 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1003 DE_NULL, // const void* pNext;
1004 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
1005 numAttachments, // uint32_t attachmentCount;
1006 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
1007 1u, // uint32_t subpassCount;
1008 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1009 0u, // uint32_t dependencyCount;
1010 DE_NULL // const VkSubpassDependency* pDependencies;
1011 };
1012
1013 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
1014 }
1015
1016 // Tests framebuffer with attachments of different sizes
testMultiAttachments(Context & context,const CaseDef caseDef)1017 tcu::TestStatus testMultiAttachments(Context &context, const CaseDef caseDef)
1018 {
1019 const InstanceInterface &vki = context.getInstanceInterface();
1020 const DeviceInterface &vk = context.getDeviceInterface();
1021 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1022 const VkDevice device = context.getDevice();
1023 const VkQueue queue = context.getUniversalQueue();
1024 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1025 Allocator &allocator = context.getDefaultAllocator();
1026 const uint32_t numRenderTargets = 3;
1027 const bool differentSizeTest = caseDef.multiAttachmentsTestType == MULTI_ATTACHMENTS_DIFFERENT_SIZES;
1028 const bool notExportTest = caseDef.multiAttachmentsTestType == MULTI_ATTACHMENTS_NOT_EXPORTED;
1029
1030 // Color images for rendering in single-sample tests or resolve targets for multi-sample tests
1031 Move<VkImage> colorImages[numRenderTargets];
1032 MovePtr<Allocation> colorImageAllocs[numRenderTargets];
1033
1034 // For multisampled tests, these are the rendering targets
1035 Move<VkImage> msColorImages[numRenderTargets];
1036 MovePtr<Allocation> msColorImageAllocs[numRenderTargets];
1037
1038 Move<VkBuffer> colorBuffers[numRenderTargets];
1039 MovePtr<Allocation> colorBufferAllocs[numRenderTargets];
1040
1041 // Vary attachment sizes by adding an offset to the base size.
1042 const IVec3 attachmentSizes[] = {caseDef.attachmentSize,
1043 caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
1044 caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)};
1045
1046 // Use unique clear color for each render target to verify no leaking happens between render target clears.
1047 const VkClearColorValue clearColors[] = {
1048 {{1.0f, 0.0f, 0.0f, 1.0f}}, {{0.0f, 1.0f, 0.0f, 1.0f}}, {{0.0f, 0.0f, 1.0f, 1.0f}}};
1049
1050 Move<VkBuffer> vertexBuffer;
1051 MovePtr<Allocation> vertexBufferAlloc;
1052
1053 vector<SharedPtrVkImageView> colorAttachments;
1054 vector<VkImage> images;
1055 vector<VkImageView> attachmentHandles;
1056
1057 const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device);
1058 GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1059 caseDef.pipelineConstructionType);
1060 RenderPassWrapper renderPass(makeRenderPassMultiAttachments(vk, device, caseDef.pipelineConstructionType,
1061 COLOR_FORMAT, numRenderTargets, caseDef.multisample));
1062
1063 const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1064 const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1065
1066 const Unique<VkCommandPool> cmdPool(
1067 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1068 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1069
1070 const VkImageViewType imageViewType =
1071 caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ?
1072 VK_IMAGE_VIEW_TYPE_2D :
1073 caseDef.imageType;
1074
1075 const VkImageSubresourceRange range = makeColorSubresourceRange(0, 1);
1076
1077 // create color buffers
1078 for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1079 {
1080 const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1081
1082 // Host memory buffer where we will copy the rendered image for verification
1083 const uint32_t att_size_x = attachmentSize.x();
1084 const uint32_t att_size_y = attachmentSize.y();
1085 const uint32_t att_size_z = attachmentSize.z();
1086 const VkDeviceSize colorBufferSize =
1087 att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1088 colorBuffers[renderTargetIdx] = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1089 colorBufferAllocs[renderTargetIdx] =
1090 bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
1091 }
1092
1093 // create vertexBuffer
1094 {
1095 const vector<tcu::Vec4> vertices = genFullQuadVertices(1);
1096 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1097
1098 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1099 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1100
1101 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1102 flushAlloc(vk, device, *vertexBufferAlloc);
1103 }
1104
1105 // create colorImages (and msColorImages) using the configured attachmentsize
1106 for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1107 {
1108 const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1109
1110 const VkImageUsageFlags colorImageUsage =
1111 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1112 colorImages[renderTargetIdx] = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
1113 COLOR_FORMAT, attachmentSize, 1, colorImageUsage, false);
1114 colorImageAllocs[renderTargetIdx] =
1115 bindImage(vk, device, allocator, *colorImages[renderTargetIdx], MemoryRequirement::Any);
1116
1117 if (caseDef.multisample)
1118 {
1119 const VkImageUsageFlags msImageUsage =
1120 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1121
1122 msColorImages[renderTargetIdx] =
1123 makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
1124 attachmentSize, 1, msImageUsage, true);
1125 msColorImageAllocs[renderTargetIdx] =
1126 bindImage(vk, device, allocator, *msColorImages[renderTargetIdx], MemoryRequirement::Any);
1127 }
1128 }
1129
1130 // create attachmentHandles. We use the renderSize for viewport and scissor
1131 for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1132 {
1133 colorAttachments.push_back(makeSharedPtr(makeImageView(
1134 vk, device, !caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx],
1135 imageViewType, COLOR_FORMAT, range)));
1136 images.push_back(!caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx]);
1137 attachmentHandles.push_back(**colorAttachments.back());
1138 }
1139
1140 preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, caseDef.renderSize,
1141 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, numRenderTargets, caseDef.multisample);
1142
1143 // create framebuffer
1144 renderPass.createFramebuffer(vk, device, numRenderTargets, &images[0], &attachmentHandles[0],
1145 static_cast<uint32_t>(caseDef.renderSize.x()),
1146 static_cast<uint32_t>(caseDef.renderSize.y()));
1147
1148 // record command buffer
1149 beginCommandBuffer(vk, *cmdBuffer);
1150
1151 // Clear image attachments
1152 for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1153 {
1154 {
1155 const VkImageMemoryBarrier imageLayoutBarriers[] = {
1156 {
1157 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1158 DE_NULL, // const void* pNext;
1159 0u, // VkAccessFlags srcAccessMask;
1160 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1161 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1162 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1163 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1164 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1165 caseDef.multisample ? *msColorImages[renderTargetIdx] :
1166 *colorImages[renderTargetIdx], // VkImage image;
1167 range // VkImageSubresourceRange subresourceRange;
1168 },
1169 };
1170
1171 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1172 DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
1173
1174 vk.cmdClearColorImage(*cmdBuffer,
1175 caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],
1176 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColors[renderTargetIdx], 1u, &range);
1177
1178 const VkImageMemoryBarrier imageClearBarriers[] = {
1179 {
1180 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1181 DE_NULL, // const void* pNext;
1182 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1183 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
1184 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1185 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1186 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1187 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1188 caseDef.multisample ? *msColorImages[renderTargetIdx] :
1189 *colorImages[renderTargetIdx], // VkImage image;
1190 range // VkImageSubresourceRange subresourceRange;
1191 },
1192 };
1193
1194 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1195 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
1196 imageClearBarriers);
1197 }
1198 }
1199
1200 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1201 {
1202 const VkDeviceSize vertexBufferOffset = 0ull;
1203
1204 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
1205 {
1206 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1207 pipeline.bind(*cmdBuffer);
1208 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1209 }
1210 renderPass.end(vk, *cmdBuffer);
1211 }
1212
1213 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
1214 if (caseDef.multisample)
1215 {
1216 for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1217 {
1218 const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1219
1220 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
1221 const VkImageMemoryBarrier imageBarriers[] = {
1222 {
1223 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1224 DE_NULL, // const void* pNext;
1225 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1226 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1227 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1228 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1229 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1230 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1231 *msColorImages[renderTargetIdx], // VkImage image;
1232 range // VkImageSubresourceRange subresourceRange;
1233 },
1234 {
1235 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1236 DE_NULL, // const void* pNext;
1237 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1238 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1239 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1240 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1241 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1242 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1243 *colorImages[renderTargetIdx], // VkImage image;
1244 range // VkImageSubresourceRange subresourceRange;
1245 }};
1246
1247 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1248 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1249
1250 const VkImageResolve region = {
1251 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
1252 1), // VkImageSubresourceLayers srcSubresource;
1253 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
1254 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0,
1255 1), // VkImageSubresourceLayers dstSubresource;
1256 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
1257 makeExtent3D(attachmentSize) // VkExtent3D extent;
1258 };
1259
1260 vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL,
1261 *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
1262 }
1263 }
1264
1265 for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1266 {
1267 const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1268
1269 // copy colorImage to host visible colorBuffer
1270 const VkImageMemoryBarrier imageBarrier = {
1271 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1272 DE_NULL, // const void* pNext;
1273 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT :
1274 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1275 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1276 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL :
1277 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1278 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1279 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1280 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1281 *colorImages[renderTargetIdx], // VkImage image;
1282 range // VkImageSubresourceRange subresourceRange;
1283 };
1284
1285 vk.cmdPipelineBarrier(*cmdBuffer,
1286 caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT :
1287 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1288 VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1289
1290 const VkBufferImageCopy region = {
1291 0ull, // VkDeviceSize bufferOffset;
1292 0u, // uint32_t bufferRowLength;
1293 0u, // uint32_t bufferImageHeight;
1294 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
1295 1u), // VkImageSubresourceLayers imageSubresource;
1296 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1297 makeExtent3D(attachmentSize), // VkExtent3D imageExtent;
1298 };
1299
1300 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1301 *colorBuffers[renderTargetIdx], 1u, ®ion);
1302
1303 const VkBufferMemoryBarrier bufferBarrier = {
1304 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1305 DE_NULL, // const void* pNext;
1306 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1307 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1308 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1309 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1310 *colorBuffers[renderTargetIdx], // VkBuffer buffer;
1311 0ull, // VkDeviceSize offset;
1312 VK_WHOLE_SIZE, // VkDeviceSize size;
1313 };
1314
1315 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
1316 1u, &bufferBarrier, 0u, DE_NULL);
1317 }
1318
1319 endCommandBuffer(vk, *cmdBuffer);
1320 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1321
1322 // Verify results
1323 const uint32_t skippedRenderTarget = notExportTest ? 1 : numRenderTargets;
1324 const tcu::Vec4 expectedColors[] = {tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f), tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
1325 tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)};
1326
1327 for (uint32_t renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1328 {
1329 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1330 const IVec3 size = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1331 tcu::TextureLevel textureLevel(format, size.x(), size.y(), size.z());
1332 const tcu::PixelBufferAccess expectedImage(textureLevel);
1333
1334 // Doesn't need to check the output of unused MRT, that may be undefined.
1335 if (notExportTest && (renderTargetIdx == skippedRenderTarget))
1336 continue;
1337
1338 invalidateAlloc(vk, device, *colorBufferAllocs[renderTargetIdx]);
1339
1340 for (int z = 0; z < expectedImage.getDepth(); ++z)
1341 {
1342 for (int y = 0; y < expectedImage.getHeight(); ++y)
1343 {
1344 for (int x = 0; x < expectedImage.getWidth(); ++x)
1345 {
1346 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1347 expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
1348 else
1349 expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
1350 }
1351 }
1352 }
1353 const tcu::ConstPixelBufferAccess resultImage(format, size.x(), size.y(), size.z(),
1354 colorBufferAllocs[renderTargetIdx]->getHostPtr());
1355
1356 if (!tcu::intThresholdCompare(
1357 context.getTestContext().getLog(),
1358 (std::string("Image Comparison of render target ") + de::toString(renderTargetIdx)).c_str(), "",
1359 expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1360 return tcu::TestStatus::fail("Fail");
1361 }
1362
1363 return tcu::TestStatus::pass("Pass");
1364 }
1365
initInputResolveSameAttachmentPrograms(SourceCollections & programCollection,const CaseDef caseDef)1366 void initInputResolveSameAttachmentPrograms(SourceCollections &programCollection, const CaseDef caseDef)
1367 {
1368 DE_UNREF(caseDef);
1369
1370 // Vertex shader
1371 {
1372 std::ostringstream src;
1373 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1374 << "\n"
1375 << "layout(location = 0) in vec4 in_position;\n"
1376 << "\n"
1377 << "out gl_PerVertex {\n"
1378 << " vec4 gl_Position;\n"
1379 << "};\n"
1380 << "\n"
1381 << "void main(void)\n"
1382 << "{\n"
1383 << " gl_Position = in_position;\n"
1384 << "}\n";
1385
1386 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1387 }
1388
1389 // Fragment shader
1390 {
1391 std::ostringstream src;
1392 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1393 << "\n"
1394 << "layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;\n"
1395 << "layout(location = 0) out vec4 o_color0;\n"
1396 << "\n"
1397 << "void main(void)\n"
1398 << "{\n"
1399 << " vec4 in_color = subpassLoad(inputColor);\n"
1400 << " o_color0 = vec4(1.0, in_color.y, 0.25, 1.0);\n"
1401 << "}\n";
1402
1403 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1404 }
1405 }
1406
makeRenderPassInputResolveSameAttachment(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat)1407 RenderPassWrapper makeRenderPassInputResolveSameAttachment(const DeviceInterface &vk, const VkDevice device,
1408 const PipelineConstructionType pipelineConstructionType,
1409 const VkFormat colorFormat)
1410 {
1411 std::vector<VkAttachmentDescription> attachmentDescriptions;
1412 VkAttachmentDescription colorAttachmentDescription = {
1413 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags;
1414 colorFormat, // VkFormat format;
1415 VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
1416 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
1417 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1418 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1419 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1420 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
1421 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1422 };
1423
1424 attachmentDescriptions.push_back(colorAttachmentDescription);
1425
1426 VkAttachmentDescription inputAttachmentDescription = {
1427 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags;
1428 colorFormat, // VkFormat format;
1429 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1430 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
1431 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1432 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1433 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1434 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
1435 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout finalLayout;
1436 };
1437
1438 attachmentDescriptions.push_back(inputAttachmentDescription);
1439
1440 const VkAttachmentReference colorAttachmentRef = {
1441 0u, // uint32_t attachment;
1442 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
1443 };
1444
1445 const VkAttachmentReference inputAttachmentRef = {
1446 1u, // uint32_t attachment;
1447 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout layout;
1448 };
1449
1450 const VkSubpassDescription subpassDescription = {
1451 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
1452 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1453 1u, // uint32_t inputAttachmentCount;
1454 &inputAttachmentRef, // const VkAttachmentReference* pInputAttachments;
1455 1u, // uint32_t colorAttachmentCount;
1456 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
1457 &inputAttachmentRef, // const VkAttachmentReference* pResolveAttachments;
1458 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
1459 0u, // uint32_t preserveAttachmentCount;
1460 DE_NULL // const uint32_t* pPreserveAttachments;
1461 };
1462
1463 const VkRenderPassCreateInfo renderPassInfo = {
1464 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1465 DE_NULL, // const void* pNext;
1466 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
1467 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount;
1468 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
1469 1u, // uint32_t subpassCount;
1470 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1471 0u, // uint32_t dependencyCount;
1472 DE_NULL // const VkSubpassDependency* pDependencies;
1473 };
1474
1475 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
1476 }
1477
testInputResolveSameAttachment(Context & context,const CaseDef caseDef)1478 tcu::TestStatus testInputResolveSameAttachment(Context &context, const CaseDef caseDef)
1479 {
1480 const InstanceInterface &vki = context.getInstanceInterface();
1481 const DeviceInterface &vk = context.getDeviceInterface();
1482 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1483 const VkDevice device = context.getDevice();
1484 const VkQueue queue = context.getUniversalQueue();
1485 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1486 Allocator &allocator = context.getDefaultAllocator();
1487
1488 // Use unique clear color for each render target to verify no leaking happens between render target clears.
1489 const VkClearColorValue clearColor[] = {{{1.0f, 0.0f, 0.0f, 1.0f}}, {{0.0f, 0.5f, 0.0f, 1.0f}}};
1490
1491 Move<VkBuffer> vertexBuffer;
1492 MovePtr<Allocation> vertexBufferAlloc;
1493
1494 vector<SharedPtrVkImageView> colorAttachments;
1495 vector<VkImage> images;
1496 vector<VkImageView> attachmentHandles;
1497
1498 // Create pipeline descriptor set for the image
1499 const Move<VkDescriptorSetLayout> descriptorSetLayout =
1500 DescriptorSetLayoutBuilder()
1501 .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
1502 .build(vk, device);
1503
1504 const Move<VkDescriptorPool> descriptorPool =
1505 DescriptorPoolBuilder()
1506 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1)
1507 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1508
1509 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1510
1511 const PipelineLayoutWrapper pipelineLayout(caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
1512 GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1513 caseDef.pipelineConstructionType);
1514 RenderPassWrapper renderPass(
1515 makeRenderPassInputResolveSameAttachment(vk, device, caseDef.pipelineConstructionType, COLOR_FORMAT));
1516
1517 const ShaderWrapper vertexModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u));
1518 const ShaderWrapper fragmentModule(ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u));
1519
1520 const Unique<VkCommandPool> cmdPool(
1521 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1522 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1523
1524 const VkImageViewType imageViewType = caseDef.imageType;
1525
1526 const VkImageSubresourceRange range = makeColorSubresourceRange(0, 1);
1527
1528 // create color buffer
1529 const IVec3 attachmentSize = caseDef.attachmentSize;
1530 const VkDeviceSize colorBufferSize =
1531 attachmentSize.x() * attachmentSize.y() * attachmentSize.z() * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1532 auto colorBuffer = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1533 MovePtr<Allocation> colorBufferAlloc =
1534 bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible);
1535
1536 // create vertexBuffer
1537 {
1538 const vector<tcu::Vec4> vertices = genFullQuadVertices(1);
1539 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1540
1541 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1542 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1543
1544 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1545 flushAlloc(vk, device, *vertexBufferAlloc);
1546 }
1547
1548 // create colorImages (and msColorImages)
1549 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1550 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1551 Move<VkImage> colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
1552 COLOR_FORMAT, attachmentSize, 1, colorImageUsage, false);
1553 MovePtr<Allocation> colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1554
1555 const VkImageUsageFlags msImageUsage =
1556 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1557 Move<VkImage> msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType),
1558 COLOR_FORMAT, attachmentSize, 1, msImageUsage, true);
1559 MovePtr<Allocation> msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
1560
1561 // create attachmentHandles. We use the renderSize for viewport and scissor
1562 colorAttachments.push_back(
1563 makeSharedPtr(makeImageView(vk, device, *msColorImage, imageViewType, COLOR_FORMAT, range)));
1564 images.push_back(*msColorImage);
1565 attachmentHandles.push_back(**colorAttachments.back());
1566
1567 colorAttachments.push_back(
1568 makeSharedPtr(makeImageView(vk, device, *colorImage, imageViewType, COLOR_FORMAT, range)));
1569 images.push_back(*colorImage);
1570 attachmentHandles.push_back(**colorAttachments.back());
1571
1572 const VkDescriptorImageInfo descriptorImageInfo =
1573 makeDescriptorImageInfo(DE_NULL, attachmentHandles[1], VK_IMAGE_LAYOUT_GENERAL);
1574 DescriptorSetUpdateBuilder()
1575 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1576 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfo)
1577 .update(vk, device);
1578
1579 preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, caseDef.renderSize,
1580 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 1u, true);
1581
1582 // create framebuffer
1583 renderPass.createFramebuffer(vk, device, 2u, &images[0], &attachmentHandles[0],
1584 static_cast<uint32_t>(caseDef.renderSize.x()),
1585 static_cast<uint32_t>(caseDef.renderSize.y()));
1586
1587 // record command buffer
1588 beginCommandBuffer(vk, *cmdBuffer);
1589
1590 // Clear image attachments
1591 {
1592 const VkImageMemoryBarrier imageLayoutBarriers[] = {
1593 {
1594 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1595 DE_NULL, // const void* pNext;
1596 0u, // VkAccessFlags srcAccessMask;
1597 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1598 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1599 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1600 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1601 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1602 *msColorImage, // VkImage image;
1603 range // VkImageSubresourceRange subresourceRange;
1604 },
1605 {
1606 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1607 DE_NULL, // const void* pNext;
1608 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1609 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1610 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1611 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1612 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1613 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1614 *colorImage, // VkImage image;
1615 range // VkImageSubresourceRange subresourceRange;
1616 }};
1617
1618 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1619 DE_NULL, 0u, DE_NULL, 2u, imageLayoutBarriers);
1620
1621 vk.cmdClearColorImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[0], 1u,
1622 &range);
1623 vk.cmdClearColorImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[1], 1u,
1624 &range);
1625
1626 const VkImageMemoryBarrier imageClearBarriers[] = {
1627 {
1628 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1629 DE_NULL, // const void* pNext;
1630 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1631 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
1632 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1633 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1634 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1635 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1636 *msColorImage, // VkImage image;
1637 range // VkImageSubresourceRange subresourceRange;
1638 },
1639 {
1640 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1641 DE_NULL, // const void* pNext;
1642 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1643 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
1644 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1645 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1646 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1647 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1648 *colorImage, // VkImage image;
1649 range // VkImageSubresourceRange subresourceRange;
1650 }};
1651
1652 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1653 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageClearBarriers[0]);
1654
1655 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u,
1656 DE_NULL, 0u, DE_NULL, 1u, &imageClearBarriers[1]);
1657 }
1658
1659 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1660 {
1661 const VkDeviceSize vertexBufferOffset = 0ull;
1662
1663 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
1664 {
1665 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1666 pipeline.bind(*cmdBuffer);
1667 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
1668 &descriptorSet.get(), 0u, DE_NULL);
1669 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1670 }
1671 renderPass.end(vk, *cmdBuffer);
1672 }
1673
1674 // copy colorImage to host visible colorBuffer
1675 const VkImageMemoryBarrier imageBarrier = {
1676 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1677 DE_NULL, // const void* pNext;
1678 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1679 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1680 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout;
1681 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1682 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1683 VK_QUEUE_FAMILY_IGNORED, // uint32_t destQueueFamilyIndex;
1684 *colorImage, // VkImage image;
1685 range // VkImageSubresourceRange subresourceRange;
1686 };
1687
1688 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1689 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1690
1691 const VkBufferImageCopy regionBufferImageCopy = {
1692 0ull, // VkDeviceSize bufferOffset;
1693 0u, // uint32_t bufferRowLength;
1694 0u, // uint32_t bufferImageHeight;
1695 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
1696 1u), // VkImageSubresourceLayers imageSubresource;
1697 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1698 makeExtent3D(attachmentSize), // VkExtent3D imageExtent;
1699 };
1700
1701 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u,
1702 ®ionBufferImageCopy);
1703
1704 const VkBufferMemoryBarrier bufferBarrier = {
1705 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1706 DE_NULL, // const void* pNext;
1707 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1708 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1709 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1710 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1711 *colorBuffer, // VkBuffer buffer;
1712 0ull, // VkDeviceSize offset;
1713 VK_WHOLE_SIZE, // VkDeviceSize size;
1714 };
1715
1716 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u,
1717 &bufferBarrier, 0u, DE_NULL);
1718
1719 endCommandBuffer(vk, *cmdBuffer);
1720 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1721
1722 // Verify results
1723 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1724 tcu::TextureLevel textureLevel(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z());
1725 const tcu::PixelBufferAccess expectedImage(textureLevel);
1726
1727 const tcu::Vec4 expectedColor = tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f);
1728
1729 invalidateAlloc(vk, device, *colorBufferAlloc);
1730
1731 for (int z = 0; z < expectedImage.getDepth(); ++z)
1732 {
1733 for (int y = 0; y < expectedImage.getHeight(); ++y)
1734 {
1735 for (int x = 0; x < expectedImage.getWidth(); ++x)
1736 {
1737 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1738 expectedImage.setPixel(expectedColor, x, y, z);
1739 else
1740 expectedImage.setPixel(tcu::Vec4(clearColor[0].float32), x, y, z);
1741 }
1742 }
1743 }
1744 const tcu::ConstPixelBufferAccess resultImage(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z(),
1745 colorBufferAlloc->getHostPtr());
1746
1747 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage,
1748 tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1749 return tcu::TestStatus::fail("Fail");
1750
1751 return tcu::TestStatus::pass("Pass");
1752 }
1753
testUnusedAtt(Context & context,PipelineConstructionType pipelineConstructionType)1754 tcu::TestStatus testUnusedAtt(Context &context, PipelineConstructionType pipelineConstructionType)
1755 {
1756 const DeviceInterface &vk = context.getDeviceInterface();
1757 const VkDevice device = context.getDevice();
1758 const Move<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1759 context.getUniversalQueueFamilyIndex()));
1760 const Move<VkCommandBuffer> cmdBuffer(makeCommandBuffer(vk, device, *cmdPool));
1761
1762 const VkAttachmentReference attRef = {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
1763
1764 const VkSubpassDescription subpass = {
1765 0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, DE_NULL, 1, &attRef, DE_NULL, DE_NULL, 0, DE_NULL};
1766
1767 const VkRenderPassCreateInfo renderPassCreateInfo = {
1768 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, DE_NULL, 0, 0, DE_NULL, 1, &subpass, 0, DE_NULL};
1769
1770 RenderPassWrapper renderPass(pipelineConstructionType, vk, device, &renderPassCreateInfo);
1771
1772 const VkFramebufferCreateInfo framebufferCreateInfo = {
1773 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, DE_NULL, 0, *renderPass, 0, DE_NULL, 32, 32, 1};
1774
1775 renderPass.createFramebuffer(vk, device, &framebufferCreateInfo, VK_NULL_HANDLE);
1776
1777 beginCommandBuffer(vk, *cmdBuffer);
1778 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, 32u, 32u));
1779 renderPass.end(vk, *cmdBuffer);
1780 endCommandBuffer(vk, *cmdBuffer);
1781
1782 return tcu::TestStatus::pass("Pass");
1783 }
1784
initDifferentAttachmentSizesPrograms(SourceCollections & programCollection,const CaseDef caseDef)1785 void initDifferentAttachmentSizesPrograms(SourceCollections &programCollection, const CaseDef caseDef)
1786 {
1787 DE_UNREF(caseDef);
1788
1789 // Vertex shader
1790 {
1791 std::ostringstream src;
1792 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1793 << "\n"
1794 << "layout(location = 0) in vec4 in_position;\n"
1795 << "\n"
1796 << "out gl_PerVertex {\n"
1797 << " vec4 gl_Position;\n"
1798 << "};\n"
1799 << "\n"
1800 << "void main(void)\n"
1801 << "{\n"
1802 << " gl_Position = in_position;\n"
1803 << "}\n";
1804
1805 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1806 }
1807
1808 // Fragment shader
1809 {
1810 std::ostringstream src;
1811 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1812 << "\n"
1813 << "layout(location = 0) out vec4 o_color0;\n"
1814 << "layout(location = 1) out vec4 o_color1;\n"
1815 << "layout(location = 2) out vec4 o_color2;\n"
1816 << "\n"
1817 << "void main(void)\n"
1818 << "{\n"
1819 << " o_color0 = vec4(1.0, 0.5, 0.25, 1.0);\n"
1820 << " o_color1 = vec4(0.5, 1.0, 0.25, 1.0);\n"
1821 << " o_color2 = vec4(0.25, 0.5, 1.0, 1.0);\n"
1822 << "}\n";
1823
1824 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1825 }
1826 }
1827
initMultiAttachmentsNotExportPrograms(SourceCollections & programCollection,const CaseDef caseDef)1828 void initMultiAttachmentsNotExportPrograms(SourceCollections &programCollection, const CaseDef caseDef)
1829 {
1830 DE_UNREF(caseDef);
1831
1832 // Vertex shader
1833 {
1834 std::ostringstream src;
1835 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1836 << "\n"
1837 << "layout(location = 0) in vec4 in_position;\n"
1838 << "\n"
1839 << "out gl_PerVertex {\n"
1840 << " vec4 gl_Position;\n"
1841 << "};\n"
1842 << "\n"
1843 << "void main(void)\n"
1844 << "{\n"
1845 << " gl_Position = in_position;\n"
1846 << "}\n";
1847
1848 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1849 }
1850
1851 // Fragment shader
1852 {
1853 std::ostringstream src;
1854 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1855 << "\n"
1856 << "layout(location = 0) out vec4 o_color0;\n"
1857 << "layout(location = 1) out vec4 o_color1;\n"
1858 << "layout(location = 2) out vec4 o_color2;\n"
1859 << "\n"
1860 << "void main(void)\n"
1861 << "{\n"
1862 << " o_color0 = vec4(1.0, 0.5, 0.25, 1.0);\n"
1863 << " o_color2 = vec4(0.25, 0.5, 1.0, 1.0);\n"
1864 << "}\n";
1865
1866 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1867 }
1868 }
1869
getShortImageViewTypeName(const VkImageViewType imageViewType)1870 std::string getShortImageViewTypeName(const VkImageViewType imageViewType)
1871 {
1872 std::string s(getImageViewTypeName(imageViewType));
1873 return de::toLower(s.substr(19));
1874 }
1875
getSizeString(const CaseDef & caseDef)1876 std::string getSizeString(const CaseDef &caseDef)
1877 {
1878 std::ostringstream str;
1879
1880 str << caseDef.renderSize.x();
1881 if (caseDef.renderSize.y() > 1)
1882 str << "x" << caseDef.renderSize.y();
1883 if (caseDef.renderSize.z() > 1)
1884 str << "x" << caseDef.renderSize.z();
1885
1886 str << "_" << caseDef.attachmentSize.x();
1887
1888 if (caseDef.attachmentSize.y() > 1)
1889 str << "x" << caseDef.attachmentSize.y();
1890 if (caseDef.attachmentSize.z() > 1)
1891 str << "x" << caseDef.attachmentSize.z();
1892 if (caseDef.numLayers > 1)
1893 str << "_" << caseDef.numLayers;
1894
1895 return str.str();
1896 }
1897
getTestCaseString(const CaseDef & caseDef)1898 std::string getTestCaseString(const CaseDef &caseDef)
1899 {
1900 std::ostringstream str;
1901
1902 str << getShortImageViewTypeName(caseDef.imageType).c_str();
1903 str << "_";
1904 str << getSizeString(caseDef);
1905
1906 if (caseDef.multisample)
1907 str << "_ms";
1908
1909 return str.str();
1910 }
1911
checkConstructionTypeSupport(Context & context,PipelineConstructionType pipelineConstructionType)1912 void checkConstructionTypeSupport(Context &context, PipelineConstructionType pipelineConstructionType)
1913 {
1914 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1915 pipelineConstructionType);
1916 }
1917
checkSupport(Context & context,const CaseDef caseDef)1918 void checkSupport(Context &context, const CaseDef caseDef)
1919 {
1920 checkConstructionTypeSupport(context, caseDef.pipelineConstructionType);
1921 }
1922
checkSupportNoAtt(Context & context,const NoAttCaseDef caseDef)1923 void checkSupportNoAtt(Context &context, const NoAttCaseDef caseDef)
1924 {
1925 const auto &features = context.getDeviceFeatures();
1926
1927 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1928
1929 if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
1930 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
1931
1932 if (caseDef.multisample)
1933 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); // MS shader uses gl_SampleID
1934
1935 checkConstructionTypeSupport(context, caseDef.pipelineConstructionType);
1936 }
1937
addAttachmentTestCasesWithFunctions(tcu::TestCaseGroup * group,PipelineConstructionType pipelineConstructionType)1938 void addAttachmentTestCasesWithFunctions(tcu::TestCaseGroup *group, PipelineConstructionType pipelineConstructionType)
1939 {
1940 // Add test cases for attachment strictly sizes larger than the framebuffer
1941 const CaseDef caseDef[] = {
1942 // Single-sample test cases
1943 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false,
1944 MULTI_ATTACHMENTS_NONE},
1945 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false,
1946 MULTI_ATTACHMENTS_NONE},
1947 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false,
1948 MULTI_ATTACHMENTS_NONE},
1949 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false,
1950 MULTI_ATTACHMENTS_NONE},
1951
1952 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(64, 1, 1), 4, false,
1953 MULTI_ATTACHMENTS_NONE},
1954 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(48, 1, 1), 4, false,
1955 MULTI_ATTACHMENTS_NONE},
1956 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(39, 1, 1), 4, false,
1957 MULTI_ATTACHMENTS_NONE},
1958 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(19, 1, 1), IVec3(32, 1, 1), 4, false,
1959 MULTI_ATTACHMENTS_NONE},
1960
1961 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false,
1962 MULTI_ATTACHMENTS_NONE},
1963 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false,
1964 MULTI_ATTACHMENTS_NONE},
1965 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false,
1966 MULTI_ATTACHMENTS_NONE},
1967 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false,
1968 MULTI_ATTACHMENTS_NONE},
1969
1970 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, false,
1971 MULTI_ATTACHMENTS_NONE},
1972 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, false,
1973 MULTI_ATTACHMENTS_NONE},
1974 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, false,
1975 MULTI_ATTACHMENTS_NONE},
1976 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, false,
1977 MULTI_ATTACHMENTS_NONE},
1978
1979 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(64, 64, 1), 6, false,
1980 MULTI_ATTACHMENTS_NONE},
1981 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(48, 48, 1), 6, false,
1982 MULTI_ATTACHMENTS_NONE},
1983 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(39, 41, 1), 6, false,
1984 MULTI_ATTACHMENTS_NONE},
1985 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE, IVec3(19, 27, 1), IVec3(32, 32, 1), 6, false,
1986 MULTI_ATTACHMENTS_NONE},
1987
1988 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 6 * 2, false,
1989 MULTI_ATTACHMENTS_NONE},
1990 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 6 * 2, false,
1991 MULTI_ATTACHMENTS_NONE},
1992 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 6 * 2, false,
1993 MULTI_ATTACHMENTS_NONE},
1994 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 6 * 2, false,
1995 MULTI_ATTACHMENTS_NONE},
1996
1997 // Multi-sample test cases
1998 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true,
1999 MULTI_ATTACHMENTS_NONE},
2000 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true,
2001 MULTI_ATTACHMENTS_NONE},
2002 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true,
2003 MULTI_ATTACHMENTS_NONE},
2004 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true,
2005 MULTI_ATTACHMENTS_NONE},
2006
2007 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, true,
2008 MULTI_ATTACHMENTS_NONE},
2009 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, true,
2010 MULTI_ATTACHMENTS_NONE},
2011 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, true,
2012 MULTI_ATTACHMENTS_NONE},
2013 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, true,
2014 MULTI_ATTACHMENTS_NONE},
2015 };
2016
2017 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
2018 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), checkSupport, initColorPrograms,
2019 test, caseDef[sizeNdx]);
2020
2021 // Add tests for the case where there are no color attachments but the
2022 // fragment shader writes to an image via imageStore().
2023 NoAttCaseDef noAttCaseDef{pipelineConstructionType, false};
2024 addFunctionCaseWithPrograms(group, "no_attachments", checkSupportNoAtt, initImagePrograms, testNoAtt, noAttCaseDef);
2025 noAttCaseDef.multisample = true;
2026 addFunctionCaseWithPrograms(group, "no_attachments_ms", checkSupportNoAtt, initImagePrograms, testNoAtt,
2027 noAttCaseDef);
2028
2029 // Test render pass with attachment set as unused.
2030 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ||
2031 pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV)
2032 addFunctionCase(group, "unused_attachment", checkConstructionTypeSupport, testUnusedAtt,
2033 pipelineConstructionType);
2034
2035 // Tests with multiple attachments that have different sizes.
2036 const CaseDef differentAttachmentSizesCaseDef[] = {
2037 // Single-sample test cases
2038 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false,
2039 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2040 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false,
2041 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2042 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false,
2043 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2044 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false,
2045 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2046
2047 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false,
2048 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2049 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false,
2050 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2051 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false,
2052 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2053 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false,
2054 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2055
2056 // Multi-sample test cases
2057 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true,
2058 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2059 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true,
2060 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2061 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true,
2062 MULTI_ATTACHMENTS_DIFFERENT_SIZES},
2063 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true,
2064 MULTI_ATTACHMENTS_DIFFERENT_SIZES}};
2065
2066 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
2067 addFunctionCaseWithPrograms(
2068 group,
2069 (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(),
2070 checkSupport, initDifferentAttachmentSizesPrograms, testMultiAttachments,
2071 differentAttachmentSizesCaseDef[sizeNdx]);
2072
2073 // Tests with same attachment for input and resolving.
2074 const CaseDef resolveInputSameAttachmentCaseDef = {
2075 pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(64, 64, 1), IVec3(64, 64, 1), 1, true,
2076 MULTI_ATTACHMENTS_NONE};
2077 // Input attachments are not supported with dynamic rendering
2078 if (!vk::isConstructionTypeShaderObject(pipelineConstructionType))
2079 {
2080 addFunctionCaseWithPrograms(group, "resolve_input_same_attachment", checkSupport,
2081 initInputResolveSameAttachmentPrograms, testInputResolveSameAttachment,
2082 resolveInputSameAttachmentCaseDef);
2083 }
2084
2085 // Tests with multiple attachments, which some of them are not used in FS.
2086 const CaseDef AttachmentCaseDef[] = {// Single-sample test case
2087 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(64, 64, 1),
2088 IVec3(64, 64, 1), 1, false, MULTI_ATTACHMENTS_NOT_EXPORTED},
2089 // Multi-sample test case
2090 {pipelineConstructionType, VK_IMAGE_VIEW_TYPE_2D, IVec3(64, 64, 1),
2091 IVec3(64, 64, 1), 1, true, MULTI_ATTACHMENTS_NOT_EXPORTED}};
2092
2093 for (int Ndx = 0; Ndx < DE_LENGTH_OF_ARRAY(AttachmentCaseDef); ++Ndx)
2094 addFunctionCaseWithPrograms(
2095 group, (std::string("multi_attachments_not_exported_") + getTestCaseString(AttachmentCaseDef[Ndx])).c_str(),
2096 checkSupport, initMultiAttachmentsNotExportPrograms, testMultiAttachments, AttachmentCaseDef[Ndx]);
2097 }
2098
2099 } // namespace
2100
createFramebufferAttachmentTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2101 tcu::TestCaseGroup *createFramebufferAttachmentTests(tcu::TestContext &testCtx,
2102 PipelineConstructionType pipelineConstructionType)
2103 {
2104 return createTestGroup(testCtx, "framebuffer_attachment", addAttachmentTestCasesWithFunctions,
2105 pipelineConstructionType);
2106 }
2107
2108 } // namespace pipeline
2109 } // namespace vkt
2110