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