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 bool hasAttachments,
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 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
332 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
333 DE_NULL, // const void* pNext;
334 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
335 VK_FALSE, // VkBool32 logicOpEnable;
336 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
337 hasAttachments ? 1u : 0u, // deUint32 attachmentCount;
338 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
339 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
342 const VkPipelineShaderStageCreateInfo pShaderStages[] =
345 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
346 DE_NULL, // const void* pNext;
347 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
348 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
349 vertexModule, // VkShaderModule module;
350 "main", // const char* pName;
351 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
354 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
355 DE_NULL, // const void* pNext;
356 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
357 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
358 fragmentModule, // VkShaderModule module;
359 "main", // const char* pName;
360 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
364 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
366 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
367 DE_NULL, // const void* pNext;
368 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
369 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
370 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
371 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
372 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
373 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
374 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
375 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
376 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
377 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
378 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
379 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
380 pipelineLayout, // VkPipelineLayout layout;
381 renderPass, // VkRenderPass renderPass;
382 subpass, // deUint32 subpass;
383 DE_NULL, // VkPipeline basePipelineHandle;
384 0, // deInt32 basePipelineIndex;
387 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
390 Move<VkImage> makeImage (const DeviceInterface& vk,
391 const VkDevice device,
392 const VkImageCreateFlags flags,
393 const VkImageType imageType,
394 const VkFormat format,
396 const deUint32 numLayers,
397 const VkImageUsageFlags usage,
398 const bool multisample)
400 const VkImageCreateInfo imageParams =
402 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
403 DE_NULL, // const void* pNext;
404 flags, // VkImageCreateFlags flags;
405 imageType, // VkImageType imageType;
406 format, // VkFormat format;
407 makeExtent3D(size), // VkExtent3D extent;
408 1u, // deUint32 mipLevels;
409 numLayers, // deUint32 arrayLayers;
410 multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
411 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
412 usage, // VkImageUsageFlags usage;
413 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
414 0u, // deUint32 queueFamilyIndexCount;
415 DE_NULL, // const deUint32* pQueueFamilyIndices;
416 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
419 return createImage(vk, device, &imageParams);
422 vector<tcu::Vec4> genFullQuadVertices (const int subpassCount)
424 vector<tcu::Vec4> vectorData;
425 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
427 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
428 vectorData.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
429 vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
430 vectorData.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
435 void initColorPrograms (SourceCollections& programCollection, const CaseDef caseDef)
441 std::ostringstream src;
442 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
444 << "layout(location = 0) in vec4 in_position;\n"
446 << "out gl_PerVertex {\n"
447 << " vec4 gl_Position;\n"
450 << "void main(void)\n"
452 << " gl_Position = in_position;\n"
455 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
460 std::ostringstream src;
461 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
463 << "layout(location = 0) out vec4 o_color;\n"
465 << "void main(void)\n"
467 << " o_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
470 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
474 tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef)
476 const tcu::PixelBufferAccess expectedImage (textureLevel);
477 const int renderDepth = deMax32(caseDef.renderSize.z(), caseDef.numLayers);
479 for (int z = 0; z < expectedImage.getDepth(); ++z)
481 for (int y = 0; y < expectedImage.getHeight(); ++y)
483 for (int x = 0; x < expectedImage.getWidth(); ++x)
485 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth)
486 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
488 expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z);
492 return expectedImage;
495 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
497 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
498 return createBuffer(vk, device, &bufferCreateInfo);
501 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount)
503 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
506 // Tests rendering to a a framebuffer with color attachments larger than the
507 // framebuffer dimensions and verifies that rendering does not affect the areas
508 // of the attachment outside the framebuffer dimensions. Tests both single-sample
509 // and multi-sample configurations.
510 tcu::TestStatus test (Context& context, const CaseDef caseDef)
512 const DeviceInterface& vk = context.getDeviceInterface();
513 const VkDevice device = context.getDevice();
514 const VkQueue queue = context.getUniversalQueue();
515 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
516 Allocator& allocator = context.getDefaultAllocator();
518 // Color image for rendering in single-sample tests or resolve target for multi-sample tests
519 Move<VkImage> colorImage;
520 MovePtr<Allocation> colorImageAlloc;
522 // For multisampled tests, this is the rendering target
523 Move<VkImage> msColorImage;
524 MovePtr<Allocation> msColorImageAlloc;
526 // Host memory buffer where we will copy the rendered image for verification
527 const deUint32 att_size_x = caseDef.attachmentSize.x();
528 const deUint32 att_size_y = caseDef.attachmentSize.y();
529 const deUint32 att_size_z = caseDef.attachmentSize.z();
530 const VkDeviceSize colorBufferSize = att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
531 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
532 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
534 Move<VkBuffer> vertexBuffer;
535 MovePtr<Allocation> vertexBufferAlloc;
537 vector<SharedPtrVkImageView> colorAttachments;
538 vector<VkImageView> attachmentHandles;
540 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device));
541 vector<SharedPtrVkPipeline> pipeline;
542 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample));
543 Move<VkFramebuffer> framebuffer;
545 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
546 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
548 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
549 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
551 const VkImageViewType imageViewType = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
552 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
554 // create vertexBuffer
556 const vector<tcu::Vec4> vertices = genFullQuadVertices(caseDef.numLayers);
557 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
559 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
560 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
562 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
563 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
566 // create colorImage (and msColorImage) using the configured attachmentsize
568 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
570 colorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
571 caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
572 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
574 if (caseDef.multisample)
576 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
578 msColorImage = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
579 caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
580 msColorImageAlloc = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
584 // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
585 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
587 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
588 imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
589 attachmentHandles.push_back(**colorAttachments.back());
591 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
592 caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, true, caseDef.multisample)));
595 // create framebuffer
596 framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
597 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
599 // record command buffer
600 beginCommandBuffer(vk, *cmdBuffer);
602 // Clear the entire image attachment to black
604 const VkImageMemoryBarrier imageLayoutBarriers[] =
607 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
608 DE_NULL, // const void* pNext;
609 0u, // VkAccessFlags srcAccessMask;
610 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
611 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
612 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
613 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
614 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
615 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
616 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
620 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
621 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
623 const VkImageSubresourceRange ranges = makeColorSubresourceRange(0, caseDef.numLayers);
624 const VkClearColorValue clearColor =
626 {0.0f, 0.0f, 0.0f, 1.0f}
628 vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
630 const VkImageMemoryBarrier imageClearBarriers[] =
633 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
634 DE_NULL, // const void* pNext;
635 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
636 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
637 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
638 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
639 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
640 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
641 caseDef.multisample ? *msColorImage : *colorImage, // VkImage image;
642 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
646 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
647 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
650 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
652 const VkRect2D renderArea =
655 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
657 const VkRenderPassBeginInfo renderPassBeginInfo =
659 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
660 DE_NULL, // const void* pNext;
661 *renderPass, // VkRenderPass renderPass;
662 *framebuffer, // VkFramebuffer framebuffer;
663 renderArea, // VkRect2D renderArea;
664 0, // uint32_t clearValueCount;
665 DE_NULL, // const VkClearValue* pClearValues;
667 const VkDeviceSize vertexBufferOffset = 0ull;
669 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
671 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
672 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
675 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
677 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
678 vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
681 vk.cmdEndRenderPass(*cmdBuffer);
684 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
685 if (caseDef.multisample)
687 // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
688 const VkImageMemoryBarrier imageBarriers[] =
691 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
692 DE_NULL, // const void* pNext;
693 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
694 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
695 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
696 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
697 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
698 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
699 *msColorImage, // VkImage image;
700 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
703 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
704 DE_NULL, // const void* pNext;
705 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
706 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
707 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
708 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
709 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
710 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
711 *colorImage, // VkImage image;
712 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
716 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
717 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
719 const VkImageResolve region =
721 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource;
722 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
723 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource;
724 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
725 makeExtent3D(caseDef.attachmentSize) // VkExtent3D extent;
728 vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, ®ion);
731 // copy colorImage to host visible colorBuffer
733 const VkImageMemoryBarrier imageBarriers[] =
736 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
737 DE_NULL, // const void* pNext;
738 (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
739 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
740 caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
741 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
742 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
743 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
744 *colorImage, // VkImage image;
745 makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange subresourceRange;
749 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
750 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
752 const VkBufferImageCopy region =
754 0ull, // VkDeviceSize bufferOffset;
755 0u, // uint32_t bufferRowLength;
756 0u, // uint32_t bufferImageHeight;
757 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource;
758 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
759 makeExtent3D(caseDef.attachmentSize), // VkExtent3D imageExtent;
762 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
764 const VkBufferMemoryBarrier bufferBarriers[] =
767 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
768 DE_NULL, // const void* pNext;
769 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
770 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
771 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
772 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
773 *colorBuffer, // VkBuffer buffer;
774 0ull, // VkDeviceSize offset;
775 VK_WHOLE_SIZE, // VkDeviceSize size;
779 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
780 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
782 } // beginCommandBuffer
784 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
785 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
789 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
790 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
791 const int depth = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
792 tcu::TextureLevel textureLevel (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
793 const tcu::PixelBufferAccess expectedImage = getExpectedData(textureLevel, caseDef);
794 const tcu::ConstPixelBufferAccess resultImage (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
796 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
797 return tcu::TestStatus::fail("Fail");
800 return tcu::TestStatus::pass("Pass");
803 void initImagePrograms (SourceCollections& programCollection, const bool multisample)
807 std::ostringstream src;
808 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
810 << "layout(location = 0) in vec4 in_position;\n"
812 << "out gl_PerVertex {\n"
813 << " vec4 gl_Position;\n"
816 << "void main(void)\n"
818 << " gl_Position = in_position;\n"
821 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
826 std::ostringstream src;
827 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
829 << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
831 << "void main(void)\n"
834 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
836 src << " imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
839 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
843 //! Make a render pass with no attachments
844 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
846 // Create a single subpass with no attachment references
847 vector<VkSubpassDescription> subpasses;
849 const VkSubpassDescription subpassDescription =
851 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
852 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
853 0u, // deUint32 inputAttachmentCount;
854 DE_NULL, // const VkAttachmentReference* pInputAttachments;
855 0u, // deUint32 colorAttachmentCount;
856 DE_NULL, // const VkAttachmentReference* pColorAttachments;
857 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
858 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
859 0u, // deUint32 preserveAttachmentCount;
860 DE_NULL // const deUint32* pPreserveAttachments;
862 subpasses.push_back(subpassDescription);
864 const VkRenderPassCreateInfo renderPassInfo =
866 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
867 DE_NULL, // const void* pNext;
868 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
869 0, // deUint32 attachmentCount;
870 DE_NULL, // const VkAttachmentDescription* pAttachments;
871 1, // deUint32 subpassCount;
872 &subpasses[0], // const VkSubpassDescription* pSubpasses;
873 0u, // deUint32 dependencyCount;
874 DE_NULL // const VkSubpassDependency* pDependencies;
877 return createRenderPass(vk, device, &renderPassInfo);
880 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
882 const tcu::PixelBufferAccess expectedImage (textureLevel);
883 for (int z = 0; z < expectedImage.getDepth(); ++z)
885 for (int y = 0; y < expectedImage.getHeight(); ++y)
887 for (int x = 0; x < expectedImage.getWidth(); ++x)
889 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
893 return expectedImage;
896 vector<tcu::Vec4> genPointVertices (void)
898 vector<tcu::Vec4> vectorData;
899 vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
900 vectorData.push_back(Vec4(-0.25f, 0.25f, 0, 1));
901 vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
902 vectorData.push_back(Vec4(0.25f, 0.25f, 0, 1));
906 // Tests rendering to a framebuffer without color attachments, checking that
907 // the fragment shader is run even in the absence of color output. In this case
908 // we render 4 point primitives and we make the fragment shader write to a
909 // different pixel of an image via an imageStore command. For the single-sampled
910 // configuration we use a 4x1 image to record the output and for the
911 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
912 // 4-sample multi-sampling
913 tcu::TestStatus testNoAtt (Context& context, const bool multisample)
915 const VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
916 if (!features.fragmentStoresAndAtomics)
917 throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported");
918 if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
919 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
920 if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID
921 throw tcu::NotSupportedError("sampleRateShading feature not supported");
923 const DeviceInterface& vk = context.getDeviceInterface();
924 const VkDevice device = context.getDevice();
925 const VkQueue queue = context.getUniversalQueue();
926 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
927 Allocator& allocator = context.getDefaultAllocator();
928 const IVec3 renderSize (32, 32, 1);
930 Move<VkBuffer> vertexBuffer;
931 MovePtr<Allocation> vertexBufferAlloc;
933 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
934 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
936 // Create image where we will record the writes. For single-sampled cases this is a 4x1 image
937 // and for multi-sampled cases this is a 4x<num_samples> image.
938 const deUint8 numSamples = multisample ? 4 : 1;
939 const deUint8 imageWidth = 4;
940 const deUint8 imageHeight = numSamples;
941 const deUint8 imageDepth = 1;
942 const deUint8 imageLayers = 1;
943 const IVec3 imageDim = IVec3(imageWidth, imageHeight, imageDepth);
944 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
945 const Move<VkImage> image = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
946 const VkImageSubresourceRange imageSubresourceRange = makeColorSubresourceRange(0u, imageLayers);
947 const MovePtr<Allocation> imageAlloc = bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
948 const Move<VkImageView> imageView = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
950 // Create a buffer where we will copy the image for verification
951 const VkDeviceSize colorBufferSize = imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
952 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
953 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
955 // Create pipeline descriptor set for the image
956 const Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder()
957 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
960 const Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder()
961 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
962 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
964 const Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
965 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
966 DescriptorSetUpdateBuilder()
967 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
970 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
971 vector<SharedPtrVkPipeline> pipeline;
972 const Unique<VkRenderPass> renderPass (makeRenderPassNoAtt (vk, device));
973 Move<VkFramebuffer> framebuffer;
975 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
976 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool));
978 // create vertexBuffer
980 const vector<tcu::Vec4> vertices = genPointVertices();
981 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
983 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
984 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
985 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
986 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
989 // Create render pass and pipeline
990 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
991 renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, false, multisample)));
992 framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
994 // Record command buffer
995 beginCommandBuffer(vk, *cmdBuffer);
997 // shader image layout transition undefined -> general
999 const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
1000 0u, VK_ACCESS_SHADER_WRITE_BIT,
1001 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1002 *image, imageSubresourceRange);
1004 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
1005 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
1010 const VkRect2D renderArea =
1013 makeExtent2D(renderSize.x(), renderSize.y()),
1015 const VkRenderPassBeginInfo renderPassBeginInfo =
1017 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1018 DE_NULL, // const void* pNext;
1019 *renderPass, // VkRenderPass renderPass;
1020 *framebuffer, // VkFramebuffer framebuffer;
1021 renderArea, // VkRect2D renderArea;
1022 0, // uint32_t clearValueCount;
1023 DE_NULL, // const VkClearValue* pClearValues;
1025 const VkDeviceSize vertexBufferOffset = 0ull;
1027 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1029 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]);
1030 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1031 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1032 vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1034 vk.cmdEndRenderPass(*cmdBuffer);
1037 // copy image to host visible colorBuffer
1039 const VkImageMemoryBarrier imageBarriers[] =
1042 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1043 DE_NULL, // const void* pNext;
1044 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1045 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1046 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout;
1047 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1048 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1049 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1050 *image, // VkImage image;
1051 makeColorSubresourceRange(0, 1) // VkImageSubresourceRange subresourceRange;
1055 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1056 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
1058 const VkBufferImageCopy region =
1060 0ull, // VkDeviceSize bufferOffset;
1061 0u, // uint32_t bufferRowLength;
1062 0u, // uint32_t bufferImageHeight;
1063 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1), // VkImageSubresourceLayers imageSubresource;
1064 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1065 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)), // VkExtent3D imageExtent;
1068 vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1070 const VkBufferMemoryBarrier bufferBarriers[] =
1073 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1074 DE_NULL, // const void* pNext;
1075 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1076 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1077 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1078 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1079 *colorBuffer, // VkBuffer buffer;
1080 0ull, // VkDeviceSize offset;
1081 VK_WHOLE_SIZE, // VkDeviceSize size;
1085 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1086 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1088 } // beginCommandBuffer
1090 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1091 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1095 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1096 const tcu::TextureFormat format = mapVkFormat(COLOR_FORMAT);
1097 tcu::TextureLevel textureLevel (format, imageWidth, imageHeight, imageDepth);
1098 const tcu::PixelBufferAccess expectedImage = getExpectedDataNoAtt(textureLevel);
1099 const tcu::ConstPixelBufferAccess resultImage (format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
1101 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1102 return tcu::TestStatus::fail("Fail");
1105 return tcu::TestStatus::pass("Pass");
1108 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1110 std::string s (getImageViewTypeName(imageViewType));
1111 return de::toLower(s.substr(19));
1114 std::string getSizeString (const CaseDef& caseDef)
1116 std::ostringstream str;
1118 str << caseDef.renderSize.x();
1119 if (caseDef.renderSize.y() > 1) str << "x" << caseDef.renderSize.y();
1120 if (caseDef.renderSize.z() > 1) str << "x" << caseDef.renderSize.z();
1122 str << "_" << caseDef.attachmentSize.x();
1124 if (caseDef.attachmentSize.y() > 1) str << "x" << caseDef.attachmentSize.y();
1125 if (caseDef.attachmentSize.z() > 1) str << "x" << caseDef.attachmentSize.z();
1126 if (caseDef.numLayers > 1) str << "_" << caseDef.numLayers;
1131 std::string getTestCaseString (const CaseDef& caseDef)
1133 std::ostringstream str;
1135 str << getShortImageViewTypeName (caseDef.imageType).c_str();
1137 str << getSizeString(caseDef);
1139 if (caseDef.multisample)
1145 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group)
1148 // Add test cases for attachment strictly sizes larger than the framebuffer
1149 const CaseDef caseDef[] =
1151 // Single-sample test cases
1152 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(64, 1, 1), 1, false },
1153 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(48, 1, 1), 1, false },
1154 { VK_IMAGE_VIEW_TYPE_1D, IVec3(32, 1, 1), IVec3(39, 1, 1), 1, false },
1155 { VK_IMAGE_VIEW_TYPE_1D, IVec3(19, 1, 1), IVec3(32, 1, 1), 1, false },
1157 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(64, 1, 1), 4, false },
1158 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(48, 1, 1), 4, false },
1159 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(32, 1, 1), IVec3(39, 1, 1), 4, false },
1160 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec3(19, 1, 1), IVec3(32, 1, 1), 4, false },
1162 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, false },
1163 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, false },
1164 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, false },
1165 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, false },
1167 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, false },
1168 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, false },
1169 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, false },
1170 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, false },
1172 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(64, 64, 1), 6, false },
1173 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(48, 48, 1), 6, false },
1174 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(32, 32, 1), IVec3(39, 41, 1), 6, false },
1175 { VK_IMAGE_VIEW_TYPE_CUBE, IVec3(19, 27, 1), IVec3(32, 32, 1), 6, false },
1177 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 6*2, false },
1178 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 6*2, false },
1179 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 6*2, false },
1180 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 6*2, false },
1182 // Multi-sample test cases
1183 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(64, 64, 1), 1, true },
1184 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(48, 48, 1), 1, true },
1185 { VK_IMAGE_VIEW_TYPE_2D, IVec3(32, 32, 1), IVec3(39, 41, 1), 1, true },
1186 { VK_IMAGE_VIEW_TYPE_2D, IVec3(19, 27, 1), IVec3(32, 32, 1), 1, true },
1188 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(64, 64, 1), 4, true },
1189 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(48, 48, 1), 4, true },
1190 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(32, 32, 1), IVec3(39, 41, 1), 4, true },
1191 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec3(19, 27, 1), IVec3(32, 32, 1), 4, true },
1194 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
1195 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]);
1197 // Add tests for the case where there are no color attachments but the
1198 // fragment shader writes to an image via imageStore().
1199 addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false);
1200 addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true);
1205 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx)
1207 return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions);