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
makeBuffer(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)373 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
374 {
375 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
376 return createBuffer(vk, device, &bufferCreateInfo);
377 }
378
makeColorSubresourceRange(const deUint32 baseArrayLayer,const deUint32 layerCount)379 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount)
380 {
381 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
382 }
383
384 // Tests rendering to a a framebuffer with color attachments larger than the
385 // framebuffer dimensions and verifies that rendering does not affect the areas
386 // of the attachment outside the framebuffer dimensions. Tests both single-sample
387 // and multi-sample configurations.
test(Context & context,const CaseDef caseDef)388 tcu::TestStatus test (Context& context, const CaseDef caseDef)
389 {
390 const DeviceInterface& vk = context.getDeviceInterface();
391 const VkDevice device = context.getDevice();
392 const VkQueue queue = context.getUniversalQueue();
393 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
394 Allocator& allocator = context.getDefaultAllocator();
395
396 // Color image for rendering in single-sample tests or resolve target for multi-sample tests
397 Move<VkImage> colorImage;
398 MovePtr<Allocation> colorImageAlloc;
399
400 // For multisampled tests, this is the rendering target
401 Move<VkImage> msColorImage;
402 MovePtr<Allocation> msColorImageAlloc;
403
404 // Host memory buffer where we will copy the rendered image for verification
405 const deUint32 att_size_x = caseDef.attachmentSize.x();
406 const deUint32 att_size_y = caseDef.attachmentSize.y();
407 const deUint32 att_size_z = caseDef.attachmentSize.z();
408 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
409 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
410 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
411
412 Move<VkBuffer> vertexBuffer;
413 MovePtr<Allocation> vertexBufferAlloc;
414
415 vector<SharedPtrVkImageView> colorAttachments;
416 vector<VkImageView> attachmentHandles;
417
418 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device));
419 vector<SharedPtrVkPipeline> pipeline;
420 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample));
421 Move<VkFramebuffer> framebuffer;
422
423 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
424 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
425
426 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
427 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
428
429 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
430 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
431
432 // create vertexBuffer
433 {
434 const vector<tcu::Vec4> vertices = genFullQuadVertices(caseDef.numLayers);
435 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
436
437 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
438 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
439
440 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
441 flushAlloc(vk, device, *vertexBufferAlloc);
442 }
443
444 // create colorImage (and msColorImage) using the configured attachmentsize
445 {
446 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
447
448 colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
449 caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
450 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
451
452 if (caseDef.multisample)
453 {
454 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
455
456 msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
457 caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
458 msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
459 }
460 }
461
462 // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
463 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
464 {
465 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
466 imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
467 attachmentHandles.push_back(**colorAttachments.back());
468
469 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
470 caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u, caseDef.multisample)));
471 }
472
473 // create framebuffer
474 framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
475 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
476
477 // record command buffer
478 beginCommandBuffer(vk, *cmdBuffer);
479 {
480 // Clear the entire image attachment to black
481 {
482 const VkImageMemoryBarrier imageLayoutBarriers[] =
483 {
484 {
485 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
486 DE_NULL, // const void* pNext;
487 0u, // VkAccessFlags srcAccessMask;
488 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
489 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
490 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
491 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
492 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
493 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
494 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
495 },
496 };
497
498 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
499 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
500
501 const VkImageSubresourceRange ranges = makeColorSubresourceRange(0, caseDef.numLayers);
502 const VkClearColorValue clearColor =
503 {
504 {0.0f, 0.0f, 0.0f, 1.0f}
505 };
506 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
507
508 const VkImageMemoryBarrier imageClearBarriers[] =
509 {
510 {
511 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
512 DE_NULL, // const void* pNext;
513 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
514 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
515 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
516 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
517 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
518 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
519 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
520 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
521 },
522 };
523
524 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
525 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
526 }
527
528 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
529 {
530 const VkDeviceSize vertexBufferOffset = 0ull;
531
532 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
533 {
534 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
535 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
536 {
537 if (layerNdx != 0)
538 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
539
540 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
541 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
542 }
543 }
544 endRenderPass(vk, *cmdBuffer);
545 }
546
547 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
548 if (caseDef.multisample)
549 {
550 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
551 const VkImageMemoryBarrier imageBarriers[] =
552 {
553 {
554 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
555 DE_NULL, // const void* pNext;
556 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
557 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
558 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
559 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
560 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
561 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
562 *msColorImage, // VkImage image;
563 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
564 },
565 {
566 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
567 DE_NULL, // const void* pNext;
568 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
569 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
570 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
571 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
572 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
573 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
574 *colorImage, // VkImage image;
575 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
576 }
577 };
578
579 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
580 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
581
582 const VkImageResolve region =
583 {
584 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource;
585 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
586 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource;
587 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
588 makeExtent3D(caseDef.attachmentSize) // VkExtent3D extent;
589 };
590
591 vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
592 }
593
594 // copy colorImage to host visible colorBuffer
595 {
596 const VkImageMemoryBarrier imageBarriers[] =
597 {
598 {
599 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
600 DE_NULL, // const void* pNext;
601 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
602 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
603 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
604 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
605 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
606 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
607 *colorImage, // VkImage image;
608 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
609 }
610 };
611
612 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
613 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
614
615 const VkBufferImageCopy region =
616 {
617 0ull, // VkDeviceSize bufferOffset;
618 0u, // uint32_t bufferRowLength;
619 0u, // uint32_t bufferImageHeight;
620 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource;
621 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
622 makeExtent3D(caseDef.attachmentSize), // VkExtent3D imageExtent;
623 };
624
625 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
626
627 const VkBufferMemoryBarrier bufferBarriers[] =
628 {
629 {
630 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
631 DE_NULL, // const void* pNext;
632 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
633 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
634 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
635 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
636 *colorBuffer, // VkBuffer buffer;
637 0ull, // VkDeviceSize offset;
638 VK_WHOLE_SIZE, // VkDeviceSize size;
639 },
640 };
641
642 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
643 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
644 }
645 } // beginCommandBuffer
646
647 endCommandBuffer(vk, *cmdBuffer);
648 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
649
650 // Verify results
651 {
652 invalidateAlloc(vk, device, *colorBufferAlloc);
653 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
654 const int depth = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
655 tcu::TextureLevel textureLevel (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
656 const tcu::PixelBufferAccess expectedImage = getExpectedData(textureLevel, caseDef);
657 const tcu::ConstPixelBufferAccess resultImage (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
658
659 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
660 return tcu::TestStatus::fail("Fail");
661 }
662
663 return tcu::TestStatus::pass("Pass");
664 }
665
initImagePrograms(SourceCollections & programCollection,const bool multisample)666 void initImagePrograms (SourceCollections& programCollection, const bool multisample)
667 {
668 // Vertex shader
669 {
670 std::ostringstream src;
671 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
672 << "\n"
673 << "layout(location = 0) in vec4 in_position;\n"
674 << "\n"
675 << "out gl_PerVertex {\n"
676 << " vec4 gl_Position;\n"
677 << " float gl_PointSize;\n"
678 << "};\n"
679 << "\n"
680 << "void main(void)\n"
681 << "{\n"
682 << " gl_Position = in_position;\n"
683 << " gl_PointSize = 1.0f;\n"
684 << "}\n";
685
686 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
687 }
688
689 // Fragment shader
690 {
691 std::ostringstream src;
692 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
693 << "\n"
694 << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
695 << "\n"
696 << "void main(void)\n"
697 << "{\n";
698 if (!multisample)
699 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
700 else
701 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
702 src << "}\n";
703
704 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
705 }
706 }
707
708 //! Make a render pass with no attachments
makeRenderPassNoAtt(const DeviceInterface & vk,const VkDevice device)709 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
710 {
711 // Create a single subpass with no attachment references
712 vector<VkSubpassDescription> subpasses;
713
714 const VkSubpassDescription subpassDescription =
715 {
716 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
717 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
718 0u, // deUint32 inputAttachmentCount;
719 DE_NULL, // const VkAttachmentReference* pInputAttachments;
720 0u, // deUint32 colorAttachmentCount;
721 DE_NULL, // const VkAttachmentReference* pColorAttachments;
722 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
723 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
724 0u, // deUint32 preserveAttachmentCount;
725 DE_NULL // const deUint32* pPreserveAttachments;
726 };
727 subpasses.push_back(subpassDescription);
728
729 const VkRenderPassCreateInfo renderPassInfo =
730 {
731 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
732 DE_NULL, // const void* pNext;
733 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
734 0, // deUint32 attachmentCount;
735 DE_NULL, // const VkAttachmentDescription* pAttachments;
736 1, // deUint32 subpassCount;
737 &subpasses[0], // const VkSubpassDescription* pSubpasses;
738 0u, // deUint32 dependencyCount;
739 DE_NULL // const VkSubpassDependency* pDependencies;
740 };
741
742 return createRenderPass(vk, device, &renderPassInfo);
743 }
744
getExpectedDataNoAtt(tcu::TextureLevel & textureLevel)745 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
746 {
747 const tcu::PixelBufferAccess expectedImage (textureLevel);
748 for (int z = 0; z < expectedImage.getDepth(); ++z)
749 {
750 for (int y = 0; y < expectedImage.getHeight(); ++y)
751 {
752 for (int x = 0; x < expectedImage.getWidth(); ++x)
753 {
754 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
755 }
756 }
757 }
758 return expectedImage;
759 }
760
genPointVertices(void)761 vector<tcu::Vec4> genPointVertices (void)
762 {
763 vector<tcu::Vec4> vectorData;
764 vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
765 vectorData.push_back(Vec4(-0.25f, 0.25f, 0, 1));
766 vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
767 vectorData.push_back(Vec4(0.25f, 0.25f, 0, 1));
768 return vectorData;
769 }
770
771 // Tests rendering to a framebuffer without color attachments, checking that
772 // the fragment shader is run even in the absence of color output. In this case
773 // we render 4 point primitives and we make the fragment shader write to a
774 // different pixel of an image via an imageStore command. For the single-sampled
775 // configuration we use a 4x1 image to record the output and for the
776 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
777 // 4-sample multi-sampling
testNoAtt(Context & context,const bool multisample)778 tcu::TestStatus testNoAtt (Context& context, const bool multisample)
779 {
780 const VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
781 if (!features.fragmentStoresAndAtomics)
782 throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported");
783 if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
784 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
785 if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID
786 throw tcu::NotSupportedError("sampleRateShading feature not supported");
787
788 const DeviceInterface& vk = context.getDeviceInterface();
789 const VkDevice device = context.getDevice();
790 const VkQueue queue = context.getUniversalQueue();
791 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
792 Allocator& allocator = context.getDefaultAllocator();
793 const IVec3 renderSize (32, 32, 1);
794
795 Move<VkBuffer> vertexBuffer;
796 MovePtr<Allocation> vertexBufferAlloc;
797
798 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
799 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
800
801 // Create image where we will record the writes. For single-sampled cases this is a 4x1 image
802 // and for multi-sampled cases this is a 4x<num_samples> image.
803 const deUint8 numSamples = multisample ? 4 : 1;
804 const deUint8 imageWidth = 4;
805 const deUint8 imageHeight = numSamples;
806 const deUint8 imageDepth = 1;
807 const deUint8 imageLayers = 1;
808 const IVec3 imageDim = IVec3(imageWidth, imageHeight, imageDepth);
809 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
810 const Move<VkImage> image = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
811 const VkImageSubresourceRange imageSubresourceRange = makeColorSubresourceRange(0u, imageLayers);
812 const MovePtr<Allocation> imageAlloc = bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
813 const Move<VkImageView> imageView = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
814
815 // Create a buffer where we will copy the image for verification
816 const VkDeviceSize colorBufferSize = imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
817 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
818 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
819
820 // Create pipeline descriptor set for the image
821 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
822 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
823 .build(vk, device);
824
825 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
826 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
827 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
828
829 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
830 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
831 DescriptorSetUpdateBuilder()
832 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
833 .update(vk, device);
834
835 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
836 vector<SharedPtrVkPipeline> pipeline;
837 const Unique<VkRenderPass> renderPass (makeRenderPassNoAtt (vk, device));
838 Move<VkFramebuffer> framebuffer;
839
840 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
841 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool));
842
843 // create vertexBuffer
844 {
845 const vector<tcu::Vec4> vertices = genPointVertices();
846 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
847
848 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
849 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
850 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
851 flushAlloc(vk, device, *vertexBufferAlloc);
852 }
853
854 // Create render pass and pipeline
855 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
856 renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, multisample)));
857 framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
858
859 // Record command buffer
860 beginCommandBuffer(vk, *cmdBuffer);
861 {
862 // shader image layout transition undefined -> general
863 {
864 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
865 0u, VK_ACCESS_SHADER_WRITE_BIT,
866 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
867 *image, imageSubresourceRange);
868
869 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
870 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
871 }
872
873 // Render pass
874 {
875 const VkDeviceSize vertexBufferOffset = 0ull;
876
877 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()));
878
879 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]);
880 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
881 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
882 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
883
884 endRenderPass(vk, *cmdBuffer);
885 }
886
887 // copy image to host visible colorBuffer
888 {
889 const VkImageMemoryBarrier imageBarriers[] =
890 {
891 {
892 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
893 DE_NULL, // const void* pNext;
894 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
895 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
896 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout;
897 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
898 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
899 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
900 *image, // VkImage image;
901 makeColorSubresourceRange(0, 1) // VkImageSubresourceRange subresourceRange;
902 }
903 };
904
905 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
906 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
907
908 const VkBufferImageCopy region =
909 {
910 0ull, // VkDeviceSize bufferOffset;
911 0u, // uint32_t bufferRowLength;
912 0u, // uint32_t bufferImageHeight;
913 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1), // VkImageSubresourceLayers imageSubresource;
914 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
915 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)), // VkExtent3D imageExtent;
916 };
917
918 vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
919
920 const VkBufferMemoryBarrier bufferBarriers[] =
921 {
922 {
923 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
924 DE_NULL, // const void* pNext;
925 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
926 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
927 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
928 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
929 *colorBuffer, // VkBuffer buffer;
930 0ull, // VkDeviceSize offset;
931 VK_WHOLE_SIZE, // VkDeviceSize size;
932 },
933 };
934
935 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
936 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
937 }
938 } // beginCommandBuffer
939
940 endCommandBuffer(vk, *cmdBuffer);
941 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
942
943 // Verify results
944 {
945 invalidateAlloc(vk, device, *colorBufferAlloc);
946 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
947 tcu::TextureLevel textureLevel (format, imageWidth, imageHeight, imageDepth);
948 const tcu::PixelBufferAccess expectedImage = getExpectedDataNoAtt(textureLevel);
949 const tcu::ConstPixelBufferAccess resultImage (format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
950
951 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
952 return tcu::TestStatus::fail("Fail");
953 }
954
955 return tcu::TestStatus::pass("Pass");
956 }
957
958 //! Make a render pass with three color attachments
makeRenderPassDifferentAttachmentSizes(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,deUint32 numAttachments,const bool multisample)959 Move<VkRenderPass> makeRenderPassDifferentAttachmentSizes (const DeviceInterface& vk,
960 const VkDevice device,
961 const VkFormat colorFormat,
962 deUint32 numAttachments,
963 const bool multisample)
964 {
965 vector<VkAttachmentDescription> attachmentDescriptions (numAttachments);
966 vector<VkAttachmentReference> colorAttachmentReferences (numAttachments);
967
968 for (deUint32 i = 0; i < numAttachments; i++)
969 {
970 VkAttachmentDescription colorAttachmentDescription =
971 {
972 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags;
973 colorFormat, // VkFormat format;
974 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
975 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
976 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
977 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
978 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
979 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
980 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
981 };
982 attachmentDescriptions[i] = colorAttachmentDescription;
983
984 const VkAttachmentReference attachmentRef =
985 {
986 i, // deUint32 attachment;
987 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
988 };
989 colorAttachmentReferences[i] = attachmentRef;
990 }
991
992 const VkSubpassDescription subpassDescription =
993 {
994 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
995 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
996 0u, // deUint32 inputAttachmentCount;
997 DE_NULL, // const VkAttachmentReference* pInputAttachments;
998 numAttachments, // deUint32 colorAttachmentCount;
999 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
1000 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
1001 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
1002 0u, // deUint32 preserveAttachmentCount;
1003 DE_NULL // const deUint32* pPreserveAttachments;
1004 };
1005
1006 const VkRenderPassCreateInfo renderPassInfo =
1007 {
1008 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1009 DE_NULL, // const void* pNext;
1010 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
1011 numAttachments, // deUint32 attachmentCount;
1012 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
1013 1u, // deUint32 subpassCount;
1014 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1015 0u, // deUint32 dependencyCount;
1016 DE_NULL // const VkSubpassDependency* pDependencies;
1017 };
1018
1019 return createRenderPass(vk, device, &renderPassInfo);
1020 }
1021
1022 // Tests framebuffer with attachments of different sizes
testDifferentAttachmentSizes(Context & context,const CaseDef caseDef)1023 tcu::TestStatus testDifferentAttachmentSizes (Context& context, const CaseDef caseDef)
1024 {
1025 const DeviceInterface& vk = context.getDeviceInterface();
1026 const VkDevice device = context.getDevice();
1027 const VkQueue queue = context.getUniversalQueue();
1028 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1029 Allocator& allocator = context.getDefaultAllocator();
1030 const deUint32 numRenderTargets = 3;
1031
1032 // Color images for rendering in single-sample tests or resolve targets for multi-sample tests
1033 Move<VkImage> colorImages[numRenderTargets];
1034 MovePtr<Allocation> colorImageAllocs[numRenderTargets];
1035
1036 // For multisampled tests, these are the rendering targets
1037 Move<VkImage> msColorImages[numRenderTargets];
1038 MovePtr<Allocation> msColorImageAllocs[numRenderTargets];
1039
1040 Move<VkBuffer> colorBuffers[numRenderTargets];
1041 MovePtr<Allocation> colorBufferAllocs[numRenderTargets];
1042
1043 // Vary attachment sizes by adding an offset to the base size.
1044 const IVec3 attachmentSizes[] =
1045 {
1046 caseDef.attachmentSize,
1047 caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
1048 caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)
1049 };
1050
1051 // Use unique clear color for each render target to verify no leaking happens between render target clears.
1052 const VkClearColorValue clearColors[] =
1053 {
1054 {{1.0f, 0.0f, 0.0f, 1.0f}},
1055 {{0.0f, 1.0f, 0.0f, 1.0f}},
1056 {{0.0f, 0.0f, 1.0f, 1.0f}}
1057 };
1058
1059 Move<VkBuffer> vertexBuffer;
1060 MovePtr<Allocation> vertexBufferAlloc;
1061
1062 vector<SharedPtrVkImageView> colorAttachments;
1063 vector<VkImageView> attachmentHandles;
1064
1065 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device));
1066 Move<VkPipeline> pipeline;
1067 const Unique<VkRenderPass> renderPass (makeRenderPassDifferentAttachmentSizes(vk, device, COLOR_FORMAT, numRenderTargets, caseDef.multisample));
1068 Move<VkFramebuffer> framebuffer;
1069
1070 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1071 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1072
1073 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1074 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1075
1076 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
1077 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
1078
1079 const VkImageSubresourceRange range = makeColorSubresourceRange(0, 1);
1080
1081 // create color buffers
1082 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1083 {
1084 // Host memory buffer where we will copy the rendered image for verification
1085 const deUint32 att_size_x = attachmentSizes[renderTargetIdx].x();
1086 const deUint32 att_size_y = attachmentSizes[renderTargetIdx].y();
1087 const deUint32 att_size_z = attachmentSizes[renderTargetIdx].z();
1088 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1089 colorBuffers[renderTargetIdx] = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1090 colorBufferAllocs[renderTargetIdx] = bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
1091 }
1092
1093 // create vertexBuffer
1094 {
1095 const vector<tcu::Vec4> vertices = genFullQuadVertices(1);
1096 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1097
1098 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1099 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1100
1101 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1102 flushAlloc(vk, device, *vertexBufferAlloc);
1103 }
1104
1105 // create colorImages (and msColorImages) using the configured attachmentsize
1106 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
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 attachmentSizes[renderTargetIdx], 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, attachmentSizes[renderTargetIdx], 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 pipeline = makeGraphicsPipeline(vk, device, *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_GENERAL, // 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);
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 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
1201 const VkImageMemoryBarrier imageBarriers[] =
1202 {
1203 {
1204 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1205 DE_NULL, // const void* pNext;
1206 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1207 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1208 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1209 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1210 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1211 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1212 *msColorImages[renderTargetIdx], // VkImage image;
1213 range // VkImageSubresourceRange subresourceRange;
1214 },
1215 {
1216 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1217 DE_NULL, // const void* pNext;
1218 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1219 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1220 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1221 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1222 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1223 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1224 *colorImages[renderTargetIdx], // VkImage image;
1225 range // VkImageSubresourceRange subresourceRange;
1226 }
1227 };
1228
1229 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1230 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1231
1232 const VkImageResolve region =
1233 {
1234 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers srcSubresource;
1235 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
1236 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers dstSubresource;
1237 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
1238 makeExtent3D(attachmentSizes[renderTargetIdx]) // VkExtent3D extent;
1239 };
1240
1241 vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
1242 }
1243 }
1244
1245 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1246 {
1247 // copy colorImage to host visible colorBuffer
1248 const VkImageMemoryBarrier imageBarrier =
1249 {
1250 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1251 DE_NULL, // const void* pNext;
1252 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1253 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1254 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1255 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1256 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1257 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1258 *colorImages[renderTargetIdx], // VkImage image;
1259 range // VkImageSubresourceRange subresourceRange;
1260 };
1261
1262 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1263 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1264
1265 const VkBufferImageCopy region =
1266 {
1267 0ull, // VkDeviceSize bufferOffset;
1268 0u, // uint32_t bufferRowLength;
1269 0u, // uint32_t bufferImageHeight;
1270 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource;
1271 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1272 makeExtent3D(attachmentSizes[renderTargetIdx]), // VkExtent3D imageExtent;
1273 };
1274
1275 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffers[renderTargetIdx], 1u, ®ion);
1276
1277 const VkBufferMemoryBarrier bufferBarrier =
1278 {
1279 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1280 DE_NULL, // const void* pNext;
1281 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1282 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1283 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1284 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1285 *colorBuffers[renderTargetIdx], // VkBuffer buffer;
1286 0ull, // VkDeviceSize offset;
1287 VK_WHOLE_SIZE, // VkDeviceSize size;
1288 };
1289
1290 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1291 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1292 }
1293
1294 endCommandBuffer(vk, *cmdBuffer);
1295 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1296
1297 // Verify results
1298 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1299 {
1300 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1301 const IVec3 size = attachmentSizes[renderTargetIdx];
1302 tcu::TextureLevel textureLevel (format, size.x(), size.y(), size.z());
1303 const tcu::PixelBufferAccess expectedImage (textureLevel);
1304
1305 const tcu::Vec4 expectedColors[] =
1306 {
1307 tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f),
1308 tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
1309 tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)
1310 };
1311
1312 invalidateAlloc(vk, device, *colorBufferAllocs[renderTargetIdx]);
1313
1314 for (int z = 0; z < expectedImage.getDepth(); ++z)
1315 {
1316 for (int y = 0; y < expectedImage.getHeight(); ++y)
1317 {
1318 for (int x = 0; x < expectedImage.getWidth(); ++x)
1319 {
1320 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1321 expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
1322 else
1323 expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
1324 }
1325 }
1326 }
1327 const tcu::ConstPixelBufferAccess resultImage (format, size.x(), size.y(), size.z(), colorBufferAllocs[renderTargetIdx]->getHostPtr());
1328
1329 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))
1330 return tcu::TestStatus::fail("Fail");
1331 }
1332
1333 return tcu::TestStatus::pass("Pass");
1334 }
1335
testUnusedAtt(Context & context)1336 tcu::TestStatus testUnusedAtt (Context& context)
1337 {
1338 const DeviceInterface& vk = context.getDeviceInterface();
1339 const VkDevice device = context.getDevice();
1340 const Move<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1341 const Move<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1342
1343 const VkAttachmentReference attRef =
1344 {
1345 VK_ATTACHMENT_UNUSED,
1346 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
1347 };
1348
1349 const VkSubpassDescription subpass =
1350 {
1351 0,
1352 VK_PIPELINE_BIND_POINT_GRAPHICS,
1353 0,
1354 DE_NULL,
1355 1,
1356 &attRef,
1357 DE_NULL,
1358 DE_NULL,
1359 0,
1360 DE_NULL
1361 };
1362
1363 const VkRenderPassCreateInfo renderPassCreateInfo =
1364 {
1365 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1366 DE_NULL,
1367 0,
1368 0,
1369 DE_NULL,
1370 1,
1371 &subpass,
1372 0,
1373 DE_NULL
1374 };
1375
1376 const Move<VkRenderPass> renderPass = createRenderPass(vk, device, &renderPassCreateInfo, DE_NULL);
1377
1378 const VkFramebufferCreateInfo framebufferCreateInfo =
1379 {
1380 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
1381 DE_NULL,
1382 0,
1383 *renderPass,
1384 0,
1385 DE_NULL,
1386 32,
1387 32,
1388 1
1389 };
1390
1391 const Move<VkFramebuffer> framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo, DE_NULL);
1392
1393 beginCommandBuffer(vk, *cmdBuffer);
1394 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, 32u, 32u));
1395 endRenderPass(vk, *cmdBuffer);
1396 endCommandBuffer(vk, *cmdBuffer);
1397
1398 return tcu::TestStatus::pass("Pass");
1399 }
1400
initDifferentAttachmentSizesPrograms(SourceCollections & programCollection,const CaseDef caseDef)1401 void initDifferentAttachmentSizesPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1402 {
1403 DE_UNREF(caseDef);
1404
1405 // Vertex shader
1406 {
1407 std::ostringstream src;
1408 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1409 << "\n"
1410 << "layout(location = 0) in vec4 in_position;\n"
1411 << "\n"
1412 << "out gl_PerVertex {\n"
1413 << " vec4 gl_Position;\n"
1414 << "};\n"
1415 << "\n"
1416 << "void main(void)\n"
1417 << "{\n"
1418 << " gl_Position = in_position;\n"
1419 << "}\n";
1420
1421 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1422 }
1423
1424 // Fragment shader
1425 {
1426 std::ostringstream src;
1427 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1428 << "\n"
1429 << "layout(location = 0) out vec4 o_color0;\n"
1430 << "layout(location = 1) out vec4 o_color1;\n"
1431 << "layout(location = 2) out vec4 o_color2;\n"
1432 << "\n"
1433 << "void main(void)\n"
1434 << "{\n"
1435 << " o_color0 = vec4(1.0, 0.5, 0.25, 1.0);\n"
1436 << " o_color1 = vec4(0.5, 1.0, 0.25, 1.0);\n"
1437 << " o_color2 = vec4(0.25, 0.5, 1.0, 1.0);\n"
1438 << "}\n";
1439
1440 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1441 }
1442 }
1443
getShortImageViewTypeName(const VkImageViewType imageViewType)1444 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1445 {
1446 std::string s (getImageViewTypeName(imageViewType));
1447 return de::toLower(s.substr(19));
1448 }
1449
getSizeString(const CaseDef & caseDef)1450 std::string getSizeString (const CaseDef& caseDef)
1451 {
1452 std::ostringstream str;
1453
1454 str << caseDef.renderSize.x();
1455 if (caseDef.renderSize.y() > 1) str << "x" << caseDef.renderSize.y();
1456 if (caseDef.renderSize.z() > 1) str << "x" << caseDef.renderSize.z();
1457
1458 str << "_" << caseDef.attachmentSize.x();
1459
1460 if (caseDef.attachmentSize.y() > 1) str << "x" << caseDef.attachmentSize.y();
1461 if (caseDef.attachmentSize.z() > 1) str << "x" << caseDef.attachmentSize.z();
1462 if (caseDef.numLayers > 1) str << "_" << caseDef.numLayers;
1463
1464 return str.str();
1465 }
1466
getTestCaseString(const CaseDef & caseDef)1467 std::string getTestCaseString (const CaseDef& caseDef)
1468 {
1469 std::ostringstream str;
1470
1471 str << getShortImageViewTypeName (caseDef.imageType).c_str();
1472 str << "_";
1473 str << getSizeString(caseDef);
1474
1475 if (caseDef.multisample)
1476 str << "_ms";
1477
1478 return str.str();
1479 }
1480
addAttachmentTestCasesWithFunctions(tcu::TestCaseGroup * group)1481 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group)
1482 {
1483
1484 // Add test cases for attachment strictly sizes larger than the framebuffer
1485 const CaseDef caseDef[] =
1486 {
1487 // Single-sample test cases
1488 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false },
1489 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false },
1490 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false },
1491 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false },
1492
1493 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(64, 1, 1), 4, false },
1494 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(48, 1, 1), 4, false },
1495 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(39, 1, 1), 4, false },
1496 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(19, 1, 1), IVec3(32, 1, 1), 4, false },
1497
1498 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false },
1499 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false },
1500 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false },
1501 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false },
1502
1503 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, false },
1504 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, false },
1505 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, false },
1506 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, false },
1507
1508 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(64, 64, 1), 6, false },
1509 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(48, 48, 1), 6, false },
1510 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(39, 41, 1), 6, false },
1511 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(19, 27, 1), IVec3(32, 32, 1), 6, false },
1512
1513 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 6*2, false },
1514 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 6*2, false },
1515 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 6*2, false },
1516 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 6*2, false },
1517
1518 // Multi-sample test cases
1519 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true },
1520 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true },
1521 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true },
1522 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true },
1523
1524 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, true },
1525 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, true },
1526 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, true },
1527 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, true },
1528 };
1529
1530 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
1531 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]);
1532
1533 // Add tests for the case where there are no color attachments but the
1534 // fragment shader writes to an image via imageStore().
1535 addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false);
1536 addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true);
1537
1538 // Test render pass with attachment set as unused.
1539 addFunctionCase(group, "unused_attachment", "", testUnusedAtt);
1540
1541 const CaseDef differentAttachmentSizesCaseDef[] =
1542 {
1543 // Single-sample test cases
1544 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false },
1545 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false },
1546 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false },
1547 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false },
1548
1549 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false },
1550 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false },
1551 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false },
1552 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false },
1553
1554 // Multi-sample test cases
1555 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true },
1556 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true },
1557 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true },
1558 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true }
1559 };
1560
1561 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
1562 addFunctionCaseWithPrograms(group, (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(), "", initDifferentAttachmentSizesPrograms, testDifferentAttachmentSizes, differentAttachmentSizesCaseDef[sizeNdx]);
1563 }
1564
1565 } // anonymous ns
1566
createFramebufferAttachmentTests(tcu::TestContext & testCtx)1567 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx)
1568 {
1569 return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions);
1570 }
1571
1572 } // pipeline
1573 } // vkt
1574