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