1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * \file vktPipelineFramebuferAttachmentTests.cpp
21 * \brief Render to a framebuffer with attachments of different sizes and with
22 * no attachments at all
24 *//*--------------------------------------------------------------------*/
26 #include "vktPipelineFramebufferAttachmentTests.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkPrograms.hpp"
39 #include "vkImageUtil.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuImageCompare.hpp"
44 #include "deUniquePtr.hpp"
45 #include "deSharedPtr.hpp"
66 static const VkFormat COLOR_FORMAT = VK_FORMAT_R8G8B8A8_UNORM;
68 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
69 typedef SharedPtr<Unique<VkPipeline> > SharedPtrVkPipeline;
73 VkImageViewType imageType;
81 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
83 return SharedPtr<Unique<T> >(new Unique<T>(move));
87 inline VkDeviceSize sizeInBytes(const vector<T>& vec)
89 return vec.size() * sizeof(vec[0]);
92 VkImageType getImageType(const VkImageViewType viewType)
96 case VK_IMAGE_VIEW_TYPE_1D:
97 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
98 return VK_IMAGE_TYPE_1D;
100 case VK_IMAGE_VIEW_TYPE_2D:
101 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
102 case VK_IMAGE_VIEW_TYPE_CUBE:
103 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
104 return VK_IMAGE_TYPE_2D;
106 case VK_IMAGE_VIEW_TYPE_3D:
107 return VK_IMAGE_TYPE_3D;
111 return VK_IMAGE_TYPE_LAST;
115 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
116 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
117 const VkDevice device,
118 const VkFormat colorFormat,
119 const deUint32 numLayers,
120 const bool multisample)
122 vector<VkAttachmentDescription> attachmentDescriptions (numLayers);
123 deUint32 attachmentIndex = 0;
124 vector<VkAttachmentReference> colorAttachmentReferences (numLayers);
125 vector<VkSubpassDescription> subpasses;
127 for (deUint32 i = 0; i < numLayers; i++)
129 VkAttachmentDescription colorAttachmentDescription =
131 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags;
132 colorFormat, // VkFormat format;
133 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
134 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
135 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
136 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
137 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
138 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
139 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
141 attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription;
144 // Create a subpass for each attachment (each attachment is a layer of an arrayed image).
145 for (deUint32 i = 0; i < numLayers; ++i)
147 const VkAttachmentReference attachmentRef =
149 i, // deUint32 attachment;
150 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
152 colorAttachmentReferences[i] = attachmentRef;
154 const VkSubpassDescription subpassDescription =
156 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
157 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
158 0u, // deUint32 inputAttachmentCount;
159 DE_NULL, // const VkAttachmentReference* pInputAttachments;
160 1u, // deUint32 colorAttachmentCount;
161 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
162 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
163 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
164 0u, // deUint32 preserveAttachmentCount;
165 DE_NULL // const deUint32* pPreserveAttachments;
167 subpasses.push_back(subpassDescription);
170 const VkRenderPassCreateInfo renderPassInfo =
172 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
173 DE_NULL, // const void* pNext;
174 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
175 numLayers, // deUint32 attachmentCount;
176 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
177 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
178 &subpasses[0], // const VkSubpassDescription* pSubpasses;
179 0u, // deUint32 dependencyCount;
180 DE_NULL // const VkSubpassDependency* pDependencies;
183 return createRenderPass(vk, device, &renderPassInfo);
186 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
187 const VkDevice device,
188 const VkPipelineLayout pipelineLayout,
189 const VkRenderPass renderPass,
190 const VkShaderModule vertexModule,
191 const VkShaderModule fragmentModule,
192 const IVec3 renderSize,
193 const VkPrimitiveTopology topology,
194 const deUint32 subpass,
195 const deUint32 numAttachments,
196 const bool multisample)
198 const VkVertexInputBindingDescription vertexInputBindingDescription =
200 0u, // uint32_t binding;
201 sizeof(tcu::Vec4), // uint32_t stride;
202 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
205 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
208 0u, // uint32_t location;
209 0u, // uint32_t binding;
210 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
211 0u, // uint32_t offset;
215 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
217 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
218 DE_NULL, // const void* pNext;
219 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
220 1u, // uint32_t vertexBindingDescriptionCount;
221 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
222 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
223 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
226 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
228 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
229 DE_NULL, // const void* pNext;
230 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
231 topology, // VkPrimitiveTopology topology;
232 VK_FALSE, // VkBool32 primitiveRestartEnable;
235 const VkViewport viewport = makeViewport(
237 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
240 // We must set the scissor rect to the renderSize, since the renderArea specified
241 // during the begin render pass command does not ensure that rendering is strictly
242 // limited to the rect provided there and the spec clearly states that the scissor
243 // must be configured appropriately to ensure this
244 const VkRect2D scissor =
247 makeExtent2D(renderSize.x(), renderSize.y()),
250 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
252 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
253 DE_NULL, // const void* pNext;
254 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
255 1u, // uint32_t viewportCount;
256 &viewport, // const VkViewport* pViewports;
257 1u, // uint32_t scissorCount;
258 &scissor, // const VkRect2D* pScissors;
261 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
263 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
264 DE_NULL, // const void* pNext;
265 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
266 VK_FALSE, // VkBool32 depthClampEnable;
267 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
268 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
269 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
270 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
271 VK_FALSE, // VkBool32 depthBiasEnable;
272 0.0f, // float depthBiasConstantFactor;
273 0.0f, // float depthBiasClamp;
274 0.0f, // float depthBiasSlopeFactor;
275 1.0f, // float lineWidth;
278 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
280 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
281 DE_NULL, // const void* pNext;
282 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
283 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits rasterizationSamples;
284 !multisample ? VK_FALSE : VK_TRUE, // VkBool32 sampleShadingEnable;
285 1.0f, // float minSampleShading;
286 DE_NULL, // const VkSampleMask* pSampleMask;
287 VK_FALSE, // VkBool32 alphaToCoverageEnable;
288 VK_FALSE // VkBool32 alphaToOneEnable;
291 const VkStencilOpState stencilOpState = makeStencilOpState(
292 VK_STENCIL_OP_KEEP, // stencil fail
293 VK_STENCIL_OP_KEEP, // depth & stencil pass
294 VK_STENCIL_OP_KEEP, // depth only fail
295 VK_COMPARE_OP_ALWAYS, // compare op
300 const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
302 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
303 DE_NULL, // const void* pNext;
304 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
305 VK_FALSE, // VkBool32 depthTestEnable;
306 VK_FALSE, // VkBool32 depthWriteEnable;
307 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
308 VK_FALSE, // VkBool32 depthBoundsTestEnable;
309 VK_FALSE, // VkBool32 stencilTestEnable;
310 stencilOpState, // VkStencilOpState front;
311 stencilOpState, // VkStencilOpState back;
312 0.0f, // float minDepthBounds;
313 1.0f, // float maxDepthBounds;
316 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
317 // Number of blend attachments must equal the number of color attachments during any subpass.
318 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
320 VK_FALSE, // VkBool32 blendEnable;
321 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
322 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
323 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
324 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
325 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
326 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
327 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
330 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
331 for (deUint32 attachmentIdx = 0; attachmentIdx < numAttachments; attachmentIdx++)
332 colorBlendAttachmentStates.push_back(pipelineColorBlendAttachmentState);
334 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
336 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
337 DE_NULL, // const void* pNext;
338 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
339 VK_FALSE, // VkBool32 logicOpEnable;
340 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
341 numAttachments, // deUint32 attachmentCount;
342 numAttachments == 0 ? DE_NULL : &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
343 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
346 const VkPipelineShaderStageCreateInfo pShaderStages[] =
349 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
350 DE_NULL, // const void* pNext;
351 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
352 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
353 vertexModule, // VkShaderModule module;
354 "main", // const char* pName;
355 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
358 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
359 DE_NULL, // const void* pNext;
360 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
361 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
362 fragmentModule, // VkShaderModule module;
363 "main", // const char* pName;
364 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
368 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
370 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
371 DE_NULL, // const void* pNext;
372 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
373 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
374 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
375 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
376 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
377 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
378 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
379 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
380 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
381 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
382 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
383 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
384 pipelineLayout, // VkPipelineLayout layout;
385 renderPass, // VkRenderPass renderPass;
386 subpass, // deUint32 subpass;
387 DE_NULL, // VkPipeline basePipelineHandle;
388 0, // deInt32 basePipelineIndex;
391 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
394 Move<VkImage> makeImage (const DeviceInterface& vk,
395 const VkDevice device,
396 const VkImageCreateFlags flags,
397 const VkImageType imageType,
398 const VkFormat format,
400 const deUint32 numLayers,
401 const VkImageUsageFlags usage,
402 const bool multisample)
404 const VkImageCreateInfo imageParams =
406 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
407 DE_NULL, // const void* pNext;
408 flags, // VkImageCreateFlags flags;
409 imageType, // VkImageType imageType;
410 format, // VkFormat format;
411 makeExtent3D(size), // VkExtent3D extent;
412 1u, // deUint32 mipLevels;
413 numLayers, // deUint32 arrayLayers;
414 multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
415 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
416 usage, // VkImageUsageFlags usage;
417 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
418 0u, // deUint32 queueFamilyIndexCount;
419 DE_NULL, // const deUint32* pQueueFamilyIndices;
420 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
423 return createImage(vk, device, &imageParams);
426 vector<tcu::Vec4> genFullQuadVertices (const int subpassCount)
428 vector<tcu::Vec4> vectorData;
429 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
431 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
432 vectorData.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
433 vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
434 vectorData.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
439 void initColorPrograms (SourceCollections& programCollection, const CaseDef caseDef)
445 std::ostringstream src;
446 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
448 << "layout(location = 0) in vec4 in_position;\n"
450 << "out gl_PerVertex {\n"
451 << " vec4 gl_Position;\n"
454 << "void main(void)\n"
456 << " gl_Position = in_position;\n"
459 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
464 std::ostringstream src;
465 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
467 << "layout(location = 0) out vec4 o_color;\n"
469 << "void main(void)\n"
471 << " o_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
474 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
478 tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef)
480 const tcu::PixelBufferAccess expectedImage (textureLevel);
481 const int renderDepth = deMax32(caseDef.renderSize.z(), caseDef.numLayers);
483 for (int z = 0; z < expectedImage.getDepth(); ++z)
485 for (int y = 0; y < expectedImage.getHeight(); ++y)
487 for (int x = 0; x < expectedImage.getWidth(); ++x)
489 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth)
490 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
492 expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z);
496 return expectedImage;
499 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
501 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
502 return createBuffer(vk, device, &bufferCreateInfo);
505 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount)
507 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
510 // Tests rendering to a a framebuffer with color attachments larger than the
511 // framebuffer dimensions and verifies that rendering does not affect the areas
512 // of the attachment outside the framebuffer dimensions. Tests both single-sample
513 // and multi-sample configurations.
514 tcu::TestStatus test (Context& context, const CaseDef caseDef)
516 const DeviceInterface& vk = context.getDeviceInterface();
517 const VkDevice device = context.getDevice();
518 const VkQueue queue = context.getUniversalQueue();
519 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
520 Allocator& allocator = context.getDefaultAllocator();
522 // Color image for rendering in single-sample tests or resolve target for multi-sample tests
523 Move<VkImage> colorImage;
524 MovePtr<Allocation> colorImageAlloc;
526 // For multisampled tests, this is the rendering target
527 Move<VkImage> msColorImage;
528 MovePtr<Allocation> msColorImageAlloc;
530 // Host memory buffer where we will copy the rendered image for verification
531 const deUint32 att_size_x = caseDef.attachmentSize.x();
532 const deUint32 att_size_y = caseDef.attachmentSize.y();
533 const deUint32 att_size_z = caseDef.attachmentSize.z();
534 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
535 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
536 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
538 Move<VkBuffer> vertexBuffer;
539 MovePtr<Allocation> vertexBufferAlloc;
541 vector<SharedPtrVkImageView> colorAttachments;
542 vector<VkImageView> attachmentHandles;
544 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device));
545 vector<SharedPtrVkPipeline> pipeline;
546 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample));
547 Move<VkFramebuffer> framebuffer;
549 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
550 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
552 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
553 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
555 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
556 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
558 // create vertexBuffer
560 const vector<tcu::Vec4> vertices = genFullQuadVertices(caseDef.numLayers);
561 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
563 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
564 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
566 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
567 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
570 // create colorImage (and msColorImage) using the configured attachmentsize
572 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
574 colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
575 caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
576 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
578 if (caseDef.multisample)
580 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
582 msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
583 caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
584 msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
588 // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
589 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
591 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
592 imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
593 attachmentHandles.push_back(**colorAttachments.back());
595 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
596 caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u, caseDef.multisample)));
599 // create framebuffer
600 framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
601 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
603 // record command buffer
604 beginCommandBuffer(vk, *cmdBuffer);
606 // Clear the entire image attachment to black
608 const VkImageMemoryBarrier imageLayoutBarriers[] =
611 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
612 DE_NULL, // const void* pNext;
613 0u, // VkAccessFlags srcAccessMask;
614 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
615 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
616 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
617 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
618 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
619 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
620 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
624 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
625 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
627 const VkImageSubresourceRange ranges = makeColorSubresourceRange(0, caseDef.numLayers);
628 const VkClearColorValue clearColor =
630 {0.0f, 0.0f, 0.0f, 1.0f}
632 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
634 const VkImageMemoryBarrier imageClearBarriers[] =
637 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
638 DE_NULL, // const void* pNext;
639 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
640 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
641 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
642 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
643 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
644 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
645 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
646 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
650 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
651 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
654 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
656 const VkRect2D renderArea =
659 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
661 const VkRenderPassBeginInfo renderPassBeginInfo =
663 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
664 DE_NULL, // const void* pNext;
665 *renderPass, // VkRenderPass renderPass;
666 *framebuffer, // VkFramebuffer framebuffer;
667 renderArea, // VkRect2D renderArea;
668 0, // uint32_t clearValueCount;
669 DE_NULL, // const VkClearValue* pClearValues;
671 const VkDeviceSize vertexBufferOffset = 0ull;
673 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
675 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
676 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
679 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
681 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
682 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
685 vk.cmdEndRenderPass(*cmdBuffer);
688 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
689 if (caseDef.multisample)
691 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
692 const VkImageMemoryBarrier imageBarriers[] =
695 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
696 DE_NULL, // const void* pNext;
697 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
698 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
699 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
700 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
701 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
702 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
703 *msColorImage, // VkImage image;
704 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
707 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
708 DE_NULL, // const void* pNext;
709 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
710 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
711 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
712 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
713 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
714 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
715 *colorImage, // VkImage image;
716 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
720 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
721 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
723 const VkImageResolve region =
725 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource;
726 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
727 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource;
728 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
729 makeExtent3D(caseDef.attachmentSize) // VkExtent3D extent;
732 vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
735 // copy colorImage to host visible colorBuffer
737 const VkImageMemoryBarrier imageBarriers[] =
740 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
741 DE_NULL, // const void* pNext;
742 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
743 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
744 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
745 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
746 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
747 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
748 *colorImage, // VkImage image;
749 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
753 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
754 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
756 const VkBufferImageCopy region =
758 0ull, // VkDeviceSize bufferOffset;
759 0u, // uint32_t bufferRowLength;
760 0u, // uint32_t bufferImageHeight;
761 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource;
762 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
763 makeExtent3D(caseDef.attachmentSize), // VkExtent3D imageExtent;
766 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
768 const VkBufferMemoryBarrier bufferBarriers[] =
771 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
772 DE_NULL, // const void* pNext;
773 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
774 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
775 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
776 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
777 *colorBuffer, // VkBuffer buffer;
778 0ull, // VkDeviceSize offset;
779 VK_WHOLE_SIZE, // VkDeviceSize size;
783 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
784 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
786 } // beginCommandBuffer
788 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
789 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
793 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
794 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
795 const int depth = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
796 tcu::TextureLevel textureLevel (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
797 const tcu::PixelBufferAccess expectedImage = getExpectedData(textureLevel, caseDef);
798 const tcu::ConstPixelBufferAccess resultImage (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
800 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
801 return tcu::TestStatus::fail("Fail");
804 return tcu::TestStatus::pass("Pass");
807 void initImagePrograms (SourceCollections& programCollection, const bool multisample)
811 std::ostringstream src;
812 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
814 << "layout(location = 0) in vec4 in_position;\n"
816 << "out gl_PerVertex {\n"
817 << " vec4 gl_Position;\n"
820 << "void main(void)\n"
822 << " gl_Position = in_position;\n"
825 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
830 std::ostringstream src;
831 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
833 << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
835 << "void main(void)\n"
838 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
840 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
843 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
847 //! Make a render pass with no attachments
848 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
850 // Create a single subpass with no attachment references
851 vector<VkSubpassDescription> subpasses;
853 const VkSubpassDescription subpassDescription =
855 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
856 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
857 0u, // deUint32 inputAttachmentCount;
858 DE_NULL, // const VkAttachmentReference* pInputAttachments;
859 0u, // deUint32 colorAttachmentCount;
860 DE_NULL, // const VkAttachmentReference* pColorAttachments;
861 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
862 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
863 0u, // deUint32 preserveAttachmentCount;
864 DE_NULL // const deUint32* pPreserveAttachments;
866 subpasses.push_back(subpassDescription);
868 const VkRenderPassCreateInfo renderPassInfo =
870 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
871 DE_NULL, // const void* pNext;
872 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
873 0, // deUint32 attachmentCount;
874 DE_NULL, // const VkAttachmentDescription* pAttachments;
875 1, // deUint32 subpassCount;
876 &subpasses[0], // const VkSubpassDescription* pSubpasses;
877 0u, // deUint32 dependencyCount;
878 DE_NULL // const VkSubpassDependency* pDependencies;
881 return createRenderPass(vk, device, &renderPassInfo);
884 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
886 const tcu::PixelBufferAccess expectedImage (textureLevel);
887 for (int z = 0; z < expectedImage.getDepth(); ++z)
889 for (int y = 0; y < expectedImage.getHeight(); ++y)
891 for (int x = 0; x < expectedImage.getWidth(); ++x)
893 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
897 return expectedImage;
900 vector<tcu::Vec4> genPointVertices (void)
902 vector<tcu::Vec4> vectorData;
903 vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
904 vectorData.push_back(Vec4(-0.25f, 0.25f, 0, 1));
905 vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
906 vectorData.push_back(Vec4(0.25f, 0.25f, 0, 1));
910 // Tests rendering to a framebuffer without color attachments, checking that
911 // the fragment shader is run even in the absence of color output. In this case
912 // we render 4 point primitives and we make the fragment shader write to a
913 // different pixel of an image via an imageStore command. For the single-sampled
914 // configuration we use a 4x1 image to record the output and for the
915 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
916 // 4-sample multi-sampling
917 tcu::TestStatus testNoAtt (Context& context, const bool multisample)
919 const VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
920 if (!features.fragmentStoresAndAtomics)
921 throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported");
922 if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
923 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
924 if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID
925 throw tcu::NotSupportedError("sampleRateShading feature not supported");
927 const DeviceInterface& vk = context.getDeviceInterface();
928 const VkDevice device = context.getDevice();
929 const VkQueue queue = context.getUniversalQueue();
930 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
931 Allocator& allocator = context.getDefaultAllocator();
932 const IVec3 renderSize (32, 32, 1);
934 Move<VkBuffer> vertexBuffer;
935 MovePtr<Allocation> vertexBufferAlloc;
937 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
938 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
940 // Create image where we will record the writes. For single-sampled cases this is a 4x1 image
941 // and for multi-sampled cases this is a 4x<num_samples> image.
942 const deUint8 numSamples = multisample ? 4 : 1;
943 const deUint8 imageWidth = 4;
944 const deUint8 imageHeight = numSamples;
945 const deUint8 imageDepth = 1;
946 const deUint8 imageLayers = 1;
947 const IVec3 imageDim = IVec3(imageWidth, imageHeight, imageDepth);
948 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
949 const Move<VkImage> image = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
950 const VkImageSubresourceRange imageSubresourceRange = makeColorSubresourceRange(0u, imageLayers);
951 const MovePtr<Allocation> imageAlloc = bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
952 const Move<VkImageView> imageView = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
954 // Create a buffer where we will copy the image for verification
955 const VkDeviceSize colorBufferSize = imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
956 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
957 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
959 // Create pipeline descriptor set for the image
960 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
961 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
964 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
965 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
966 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
968 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
969 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
970 DescriptorSetUpdateBuilder()
971 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
974 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
975 vector<SharedPtrVkPipeline> pipeline;
976 const Unique<VkRenderPass> renderPass (makeRenderPassNoAtt (vk, device));
977 Move<VkFramebuffer> framebuffer;
979 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
980 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool));
982 // create vertexBuffer
984 const vector<tcu::Vec4> vertices = genPointVertices();
985 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
987 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
988 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
989 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
990 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
993 // Create render pass and pipeline
994 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
995 renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, multisample)));
996 framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
998 // Record command buffer
999 beginCommandBuffer(vk, *cmdBuffer);
1001 // shader image layout transition undefined -> general
1003 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
1004 0u, VK_ACCESS_SHADER_WRITE_BIT,
1005 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1006 *image, imageSubresourceRange);
1008 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
1009 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
1014 const VkRect2D renderArea =
1017 makeExtent2D(renderSize.x(), renderSize.y()),
1019 const VkRenderPassBeginInfo renderPassBeginInfo =
1021 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1022 DE_NULL, // const void* pNext;
1023 *renderPass, // VkRenderPass renderPass;
1024 *framebuffer, // VkFramebuffer framebuffer;
1025 renderArea, // VkRect2D renderArea;
1026 0, // uint32_t clearValueCount;
1027 DE_NULL, // const VkClearValue* pClearValues;
1029 const VkDeviceSize vertexBufferOffset = 0ull;
1031 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1033 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]);
1034 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1035 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1036 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1038 vk.cmdEndRenderPass(*cmdBuffer);
1041 // copy image to host visible colorBuffer
1043 const VkImageMemoryBarrier imageBarriers[] =
1046 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1047 DE_NULL, // const void* pNext;
1048 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1049 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1050 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout;
1051 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1052 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1053 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1054 *image, // VkImage image;
1055 makeColorSubresourceRange(0, 1) // VkImageSubresourceRange subresourceRange;
1059 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1060 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
1062 const VkBufferImageCopy region =
1064 0ull, // VkDeviceSize bufferOffset;
1065 0u, // uint32_t bufferRowLength;
1066 0u, // uint32_t bufferImageHeight;
1067 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1), // VkImageSubresourceLayers imageSubresource;
1068 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1069 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)), // VkExtent3D imageExtent;
1072 vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1074 const VkBufferMemoryBarrier bufferBarriers[] =
1077 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1078 DE_NULL, // const void* pNext;
1079 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1080 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1081 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1082 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1083 *colorBuffer, // VkBuffer buffer;
1084 0ull, // VkDeviceSize offset;
1085 VK_WHOLE_SIZE, // VkDeviceSize size;
1089 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1090 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1092 } // beginCommandBuffer
1094 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1095 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1099 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1100 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1101 tcu::TextureLevel textureLevel (format, imageWidth, imageHeight, imageDepth);
1102 const tcu::PixelBufferAccess expectedImage = getExpectedDataNoAtt(textureLevel);
1103 const tcu::ConstPixelBufferAccess resultImage (format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
1105 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1106 return tcu::TestStatus::fail("Fail");
1109 return tcu::TestStatus::pass("Pass");
1112 //! Make a render pass with three color attachments
1113 Move<VkRenderPass> makeRenderPassDifferentAttachmentSizes (const DeviceInterface& vk,
1114 const VkDevice device,
1115 const VkFormat colorFormat,
1116 deUint32 numAttachments,
1117 const bool multisample)
1119 vector<VkAttachmentDescription> attachmentDescriptions (numAttachments);
1120 vector<VkAttachmentReference> colorAttachmentReferences (numAttachments);
1122 for (deUint32 i = 0; i < numAttachments; i++)
1124 VkAttachmentDescription colorAttachmentDescription =
1126 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFla flags;
1127 colorFormat, // VkFormat format;
1128 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
1129 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
1130 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1131 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
1132 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
1133 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout;
1134 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1136 attachmentDescriptions[i] = colorAttachmentDescription;
1138 const VkAttachmentReference attachmentRef =
1140 i, // deUint32 attachment;
1141 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
1143 colorAttachmentReferences[i] = attachmentRef;
1146 const VkSubpassDescription subpassDescription =
1148 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
1149 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1150 0u, // deUint32 inputAttachmentCount;
1151 DE_NULL, // const VkAttachmentReference* pInputAttachments;
1152 numAttachments, // deUint32 colorAttachmentCount;
1153 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
1154 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
1155 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
1156 0u, // deUint32 preserveAttachmentCount;
1157 DE_NULL // const deUint32* pPreserveAttachments;
1160 const VkRenderPassCreateInfo renderPassInfo =
1162 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1163 DE_NULL, // const void* pNext;
1164 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
1165 numAttachments, // deUint32 attachmentCount;
1166 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
1167 1u, // deUint32 subpassCount;
1168 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1169 0u, // deUint32 dependencyCount;
1170 DE_NULL // const VkSubpassDependency* pDependencies;
1173 return createRenderPass(vk, device, &renderPassInfo);
1176 // Tests framebuffer with attachments of different sizes
1177 tcu::TestStatus testDifferentAttachmentSizes (Context& context, const CaseDef caseDef)
1179 const DeviceInterface& vk = context.getDeviceInterface();
1180 const VkDevice device = context.getDevice();
1181 const VkQueue queue = context.getUniversalQueue();
1182 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1183 Allocator& allocator = context.getDefaultAllocator();
1184 const deUint32 numRenderTargets = 3;
1186 // Color images for rendering in single-sample tests or resolve targets for multi-sample tests
1187 Move<VkImage> colorImages[numRenderTargets];
1188 MovePtr<Allocation> colorImageAllocs[numRenderTargets];
1190 // For multisampled tests, these are the rendering targets
1191 Move<VkImage> msColorImages[numRenderTargets];
1192 MovePtr<Allocation> msColorImageAllocs[numRenderTargets];
1194 Move<VkBuffer> colorBuffers[numRenderTargets];
1195 MovePtr<Allocation> colorBufferAllocs[numRenderTargets];
1197 // Vary attachment sizes by adding an offset to the base size.
1198 const IVec3 attachmentSizes[] =
1200 caseDef.attachmentSize,
1201 caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
1202 caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)
1205 // Use unique clear color for each render target to verify no leaking happens between render target clears.
1206 const VkClearColorValue clearColors[] =
1208 {{1.0f, 0.0f, 0.0f, 1.0f}},
1209 {{0.0f, 1.0f, 0.0f, 1.0f}},
1210 {{0.0f, 0.0f, 1.0f, 1.0f}}
1213 Move<VkBuffer> vertexBuffer;
1214 MovePtr<Allocation> vertexBufferAlloc;
1216 vector<SharedPtrVkImageView> colorAttachments;
1217 vector<VkImageView> attachmentHandles;
1219 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device));
1220 Move<VkPipeline> pipeline;
1221 const Unique<VkRenderPass> renderPass (makeRenderPassDifferentAttachmentSizes(vk, device, COLOR_FORMAT, numRenderTargets, caseDef.multisample));
1222 Move<VkFramebuffer> framebuffer;
1224 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1225 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1227 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1228 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1230 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
1231 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
1233 const VkImageSubresourceRange range = makeColorSubresourceRange(0, 1);
1235 // create color buffers
1236 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1238 // Host memory buffer where we will copy the rendered image for verification
1239 const deUint32 att_size_x = attachmentSizes[renderTargetIdx].x();
1240 const deUint32 att_size_y = attachmentSizes[renderTargetIdx].y();
1241 const deUint32 att_size_z = attachmentSizes[renderTargetIdx].z();
1242 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1243 colorBuffers[renderTargetIdx] = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1244 colorBufferAllocs[renderTargetIdx] = bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
1247 // create vertexBuffer
1249 const vector<tcu::Vec4> vertices = genFullQuadVertices(1);
1250 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1252 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1253 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1255 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1256 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
1259 // create colorImages (and msColorImages) using the configured attachmentsize
1260 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1262 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1263 colorImages[renderTargetIdx] = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
1264 attachmentSizes[renderTargetIdx], 1, colorImageUsage, false);
1265 colorImageAllocs[renderTargetIdx] = bindImage(vk, device, allocator, *colorImages[renderTargetIdx], MemoryRequirement::Any);
1267 if (caseDef.multisample)
1269 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1271 msColorImages[renderTargetIdx] = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, attachmentSizes[renderTargetIdx], 1, msImageUsage, true);
1272 msColorImageAllocs[renderTargetIdx] = bindImage(vk, device, allocator, *msColorImages[renderTargetIdx], MemoryRequirement::Any);
1276 // create attachmentHandles. We use the renderSize for viewport and scissor
1277 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1279 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx], imageViewType, COLOR_FORMAT, range)));
1280 attachmentHandles.push_back(**colorAttachments.back());
1283 pipeline = makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, numRenderTargets, caseDef.multisample);
1285 // create framebuffer
1286 framebuffer = makeFramebuffer(vk, device, *renderPass, numRenderTargets, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1288 // record command buffer
1289 beginCommandBuffer(vk, *cmdBuffer);
1291 // Clear image attachments
1292 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1295 const VkImageMemoryBarrier imageLayoutBarriers[] =
1298 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1299 DE_NULL, // const void* pNext;
1300 0u, // VkAccessFlags srcAccessMask;
1301 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1302 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1303 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1304 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1305 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1306 caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], // VkImage image;
1307 range // VkImageSubresourceRange subresourceRange;
1311 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
1312 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
1314 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColors[renderTargetIdx], 1u, &range);
1316 const VkImageMemoryBarrier imageClearBarriers[] =
1319 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1320 DE_NULL, // const void* pNext;
1321 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1322 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
1323 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1324 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1325 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1326 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1327 caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], // VkImage image;
1328 range // VkImageSubresourceRange subresourceRange;
1332 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
1336 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1338 const VkRect2D renderArea =
1341 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
1343 const VkRenderPassBeginInfo renderPassBeginInfo =
1345 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1346 DE_NULL, // const void* pNext;
1347 *renderPass, // VkRenderPass renderPass;
1348 *framebuffer, // VkFramebuffer framebuffer;
1349 renderArea, // VkRect2D renderArea;
1350 0, // uint32_t clearValueCount;
1351 DE_NULL, // const VkClearValue* pClearValues;
1353 const VkDeviceSize vertexBufferOffset = 0ull;
1355 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1357 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1358 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1359 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1361 vk.cmdEndRenderPass(*cmdBuffer);
1364 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
1365 if (caseDef.multisample)
1367 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1369 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
1370 const VkImageMemoryBarrier imageBarriers[] =
1373 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1374 DE_NULL, // const void* pNext;
1375 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1376 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1377 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1378 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1379 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1380 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1381 *msColorImages[renderTargetIdx], // VkImage image;
1382 range // VkImageSubresourceRange subresourceRange;
1385 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1386 DE_NULL, // const void* pNext;
1387 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1388 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1389 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1390 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
1391 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1392 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1393 *colorImages[renderTargetIdx], // VkImage image;
1394 range // VkImageSubresourceRange subresourceRange;
1398 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1399 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1401 const VkImageResolve region =
1403 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers srcSubresource;
1404 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
1405 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers dstSubresource;
1406 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
1407 makeExtent3D(attachmentSizes[renderTargetIdx]) // VkExtent3D extent;
1410 vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
1414 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1416 // copy colorImage to host visible colorBuffer
1417 const VkImageMemoryBarrier imageBarrier =
1419 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1420 DE_NULL, // const void* pNext;
1421 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1422 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1423 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1424 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1425 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1426 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1427 *colorImages[renderTargetIdx], // VkImage image;
1428 range // VkImageSubresourceRange subresourceRange;
1431 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1432 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1434 const VkBufferImageCopy region =
1436 0ull, // VkDeviceSize bufferOffset;
1437 0u, // uint32_t bufferRowLength;
1438 0u, // uint32_t bufferImageHeight;
1439 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource;
1440 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1441 makeExtent3D(attachmentSizes[renderTargetIdx]), // VkExtent3D imageExtent;
1444 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffers[renderTargetIdx], 1u, ®ion);
1446 const VkBufferMemoryBarrier bufferBarrier =
1448 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1449 DE_NULL, // const void* pNext;
1450 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1451 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1452 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1453 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1454 *colorBuffers[renderTargetIdx], // VkBuffer buffer;
1455 0ull, // VkDeviceSize offset;
1456 VK_WHOLE_SIZE, // VkDeviceSize size;
1459 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1460 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1463 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1464 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1467 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1469 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1470 const IVec3 size = attachmentSizes[renderTargetIdx];
1471 tcu::TextureLevel textureLevel (format, size.x(), size.y(), size.z());
1472 const tcu::PixelBufferAccess expectedImage (textureLevel);
1474 const tcu::Vec4 expectedColors[] =
1476 tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f),
1477 tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
1478 tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)
1481 invalidateMappedMemoryRange(vk, device, colorBufferAllocs[renderTargetIdx]->getMemory(), colorBufferAllocs[renderTargetIdx]->getOffset(), VK_WHOLE_SIZE);
1483 for (int z = 0; z < expectedImage.getDepth(); ++z)
1485 for (int y = 0; y < expectedImage.getHeight(); ++y)
1487 for (int x = 0; x < expectedImage.getWidth(); ++x)
1489 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1490 expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
1492 expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
1496 const tcu::ConstPixelBufferAccess resultImage (format, size.x(), size.y(), size.z(), colorBufferAllocs[renderTargetIdx]->getHostPtr());
1498 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))
1499 return tcu::TestStatus::fail("Fail");
1502 return tcu::TestStatus::pass("Pass");
1505 void initDifferentAttachmentSizesPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1511 std::ostringstream src;
1512 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1514 << "layout(location = 0) in vec4 in_position;\n"
1516 << "out gl_PerVertex {\n"
1517 << " vec4 gl_Position;\n"
1520 << "void main(void)\n"
1522 << " gl_Position = in_position;\n"
1525 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1530 std::ostringstream src;
1531 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1533 << "layout(location = 0) out vec4 o_color0;\n"
1534 << "layout(location = 1) out vec4 o_color1;\n"
1535 << "layout(location = 2) out vec4 o_color2;\n"
1537 << "void main(void)\n"
1539 << " o_color0 = vec4(1.0, 0.5, 0.25, 1.0);\n"
1540 << " o_color1 = vec4(0.5, 1.0, 0.25, 1.0);\n"
1541 << " o_color2 = vec4(0.25, 0.5, 1.0, 1.0);\n"
1544 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1548 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1550 std::string s (getImageViewTypeName(imageViewType));
1551 return de::toLower(s.substr(19));
1554 std::string getSizeString (const CaseDef& caseDef)
1556 std::ostringstream str;
1558 str << caseDef.renderSize.x();
1559 if (caseDef.renderSize.y() > 1) str << "x" << caseDef.renderSize.y();
1560 if (caseDef.renderSize.z() > 1) str << "x" << caseDef.renderSize.z();
1562 str << "_" << caseDef.attachmentSize.x();
1564 if (caseDef.attachmentSize.y() > 1) str << "x" << caseDef.attachmentSize.y();
1565 if (caseDef.attachmentSize.z() > 1) str << "x" << caseDef.attachmentSize.z();
1566 if (caseDef.numLayers > 1) str << "_" << caseDef.numLayers;
1571 std::string getTestCaseString (const CaseDef& caseDef)
1573 std::ostringstream str;
1575 str << getShortImageViewTypeName (caseDef.imageType).c_str();
1577 str << getSizeString(caseDef);
1579 if (caseDef.multisample)
1585 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group)
1588 // Add test cases for attachment strictly sizes larger than the framebuffer
1589 const CaseDef caseDef[] =
1591 // Single-sample test cases
1592 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false },
1593 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false },
1594 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false },
1595 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false },
1597 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(64, 1, 1), 4, false },
1598 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(48, 1, 1), 4, false },
1599 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(39, 1, 1), 4, false },
1600 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(19, 1, 1), IVec3(32, 1, 1), 4, false },
1602 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false },
1603 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false },
1604 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false },
1605 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false },
1607 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, false },
1608 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, false },
1609 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, false },
1610 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, false },
1612 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(64, 64, 1), 6, false },
1613 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(48, 48, 1), 6, false },
1614 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(39, 41, 1), 6, false },
1615 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(19, 27, 1), IVec3(32, 32, 1), 6, false },
1617 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 6*2, false },
1618 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 6*2, false },
1619 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 6*2, false },
1620 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 6*2, false },
1622 // Multi-sample test cases
1623 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true },
1624 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true },
1625 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true },
1626 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true },
1628 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, true },
1629 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, true },
1630 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, true },
1631 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, true },
1634 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
1635 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]);
1637 // Add tests for the case where there are no color attachments but the
1638 // fragment shader writes to an image via imageStore().
1639 addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false);
1640 addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true);
1642 const CaseDef differentAttachmentSizesCaseDef[] =
1644 // Single-sample test cases
1645 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false },
1646 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false },
1647 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false },
1648 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false },
1650 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false },
1651 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false },
1652 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false },
1653 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false },
1655 // Multi-sample test cases
1656 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true },
1657 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true },
1658 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true },
1659 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true }
1662 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
1663 addFunctionCaseWithPrograms(group, (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(), "", initDifferentAttachmentSizesPrograms, testDifferentAttachmentSizes, differentAttachmentSizesCaseDef[sizeNdx]);
1668 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx)
1670 return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions);