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