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 vktPipelineRenderToImageTests.cpp
21 * \brief Render to image tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktPipelineRenderToImageTests.hpp"
25 #include "vktPipelineMakeUtil.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkImageUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuTestLog.hpp"
43 #include "deUniquePtr.hpp"
44 #include "deSharedPtr.hpp"
68 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
69 typedef SharedPtr<Unique<VkPipeline> > SharedPtrVkPipeline;
74 REFERENCE_COLOR_VALUE = 125,
75 REFERENCE_STENCIL_VALUE = 42,
76 MAX_SIZE = -1, //!< Should be queried at runtime and replaced with max possible value
77 MAX_VERIFICATION_REGION_SIZE = 32, //!< Limit the checked area to a small size, especially for huge images
78 MAX_VERIFICATION_REGION_DEPTH = 8,
80 MASK_W = (1 | 0 | 0 | 0),
81 MASK_W_LAYERS = (1 | 0 | 0 | 8),
82 MASK_WH = (1 | 2 | 0 | 0),
83 MASK_WH_LAYERS = (1 | 2 | 0 | 8),
84 MASK_WHD = (1 | 2 | 4 | 0),
89 ALLOCATION_KIND_SUBALLOCATED = 0,
90 ALLOCATION_KIND_DEDICATED,
93 static const float REFERENCE_DEPTH_VALUE = 1.0f;
94 static const Vec4 COLOR_TABLE[] =
96 Vec4(0.9f, 0.0f, 0.0f, 1.0f),
97 Vec4(0.6f, 1.0f, 0.0f, 1.0f),
98 Vec4(0.3f, 0.0f, 1.0f, 1.0f),
99 Vec4(0.1f, 1.0f, 1.0f, 1.0f),
100 Vec4(0.8f, 1.0f, 0.0f, 1.0f),
101 Vec4(0.5f, 0.0f, 1.0f, 1.0f),
102 Vec4(0.2f, 0.0f, 0.0f, 1.0f),
103 Vec4(1.0f, 1.0f, 0.0f, 1.0f),
108 VkImageViewType viewType;
109 IVec4 imageSizeHint; //!< (w, h, d, layers), a component may have a symbolic value MAX_SIZE
110 VkFormat colorFormat;
111 VkFormat depthStencilFormat; //! A depth/stencil format, or UNDEFINED if not used
112 AllocationKind allocationKind;
116 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
118 return SharedPtr<Unique<T> >(new Unique<T>(move));
122 inline VkDeviceSize sizeInBytes (const vector<T>& vec)
124 return vec.size() * sizeof(vec[0]);
127 inline bool isCube (const VkImageViewType viewType)
129 return (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
132 inline VkDeviceSize product (const IVec4& v)
134 return ((static_cast<VkDeviceSize>(v.x()) * v.y()) * v.z()) * v.w();
138 inline T sum (const vector<T>& v)
140 T total = static_cast<T>(0);
141 for (typename vector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
146 template <typename T, int Size>
147 int findIndexOfMaxComponent (const tcu::Vector<T, Size>& vec)
152 for (int i = 1; i < Size; ++i)
164 inline int maxLayersOrDepth (const IVec4& size)
166 // This is safe because 3D images must have layers (w) = 1
167 return deMax32(size.z(), size.w());
170 de::MovePtr<Allocation> bindBuffer (const InstanceInterface& vki,
171 const DeviceInterface& vkd,
172 const VkPhysicalDevice& physDevice,
173 const VkDevice device,
174 const VkBuffer& buffer,
175 const MemoryRequirement requirement,
176 Allocator& allocator,
177 AllocationKind allocationKind)
179 switch (allocationKind)
181 case ALLOCATION_KIND_SUBALLOCATED:
183 return ::vkt::pipeline::bindBuffer(vkd, device, allocator, buffer, requirement);
186 case ALLOCATION_KIND_DEDICATED:
188 return bindBufferDedicated(vki, vkd, physDevice, device, buffer, requirement);
193 TCU_THROW(InternalError, "Invalid allocation kind");
198 de::MovePtr<Allocation> bindImage (const InstanceInterface& vki,
199 const DeviceInterface& vkd,
200 const VkPhysicalDevice& physDevice,
201 const VkDevice device,
202 const VkImage& image,
203 const MemoryRequirement requirement,
204 Allocator& allocator,
205 AllocationKind allocationKind)
207 switch (allocationKind)
209 case ALLOCATION_KIND_SUBALLOCATED:
211 return ::vkt::pipeline::bindImage(vkd, device, allocator, image, requirement);
214 case ALLOCATION_KIND_DEDICATED:
216 return bindImageDedicated(vki, vkd, physDevice, device, image, requirement);
221 TCU_THROW(InternalError, "Invalid allocation kind");
226 // This is very test specific, so be careful if you want to reuse this code.
227 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
228 const VkDevice device,
229 const VkPipeline basePipeline, // for derivatives
230 const VkPipelineLayout pipelineLayout,
231 const VkRenderPass renderPass,
232 const VkShaderModule vertexModule,
233 const VkShaderModule fragmentModule,
234 const IVec2& renderSize,
235 const VkPrimitiveTopology topology,
236 const deUint32 subpass,
238 const bool useStencil)
240 const VkVertexInputBindingDescription vertexInputBindingDescription =
242 0u, // uint32_t binding;
243 sizeof(Vertex4RGBA), // uint32_t stride;
244 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
247 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
250 0u, // uint32_t location;
251 0u, // uint32_t binding;
252 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
253 0u, // uint32_t offset;
256 1u, // uint32_t location;
257 0u, // uint32_t binding;
258 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
259 sizeof(Vec4), // uint32_t offset;
263 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
265 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
266 DE_NULL, // const void* pNext;
267 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
268 1u, // uint32_t vertexBindingDescriptionCount;
269 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
270 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
271 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
274 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
276 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
277 DE_NULL, // const void* pNext;
278 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
279 topology, // VkPrimitiveTopology topology;
280 VK_FALSE, // VkBool32 primitiveRestartEnable;
283 const VkViewport viewport = makeViewport(
285 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
288 const VkRect2D scissor =
291 makeExtent2D(renderSize.x(), renderSize.y()),
294 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
296 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
297 DE_NULL, // const void* pNext;
298 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
299 1u, // uint32_t viewportCount;
300 &viewport, // const VkViewport* pViewports;
301 1u, // uint32_t scissorCount;
302 &scissor, // const VkRect2D* pScissors;
305 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
307 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
308 DE_NULL, // const void* pNext;
309 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
310 VK_FALSE, // VkBool32 depthClampEnable;
311 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
312 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
313 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
314 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
315 VK_FALSE, // VkBool32 depthBiasEnable;
316 0.0f, // float depthBiasConstantFactor;
317 0.0f, // float depthBiasClamp;
318 0.0f, // float depthBiasSlopeFactor;
319 1.0f, // float lineWidth;
322 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
324 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
325 DE_NULL, // const void* pNext;
326 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
327 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
328 VK_FALSE, // VkBool32 sampleShadingEnable;
329 0.0f, // float minSampleShading;
330 DE_NULL, // const VkSampleMask* pSampleMask;
331 VK_FALSE, // VkBool32 alphaToCoverageEnable;
332 VK_FALSE // VkBool32 alphaToOneEnable;
335 const VkStencilOpState stencilOpState = makeStencilOpState(
336 VK_STENCIL_OP_KEEP, // stencil fail
337 VK_STENCIL_OP_ZERO, // depth & stencil pass
338 VK_STENCIL_OP_KEEP, // depth only fail
339 VK_COMPARE_OP_EQUAL, // compare op
342 static_cast<deUint32>(REFERENCE_STENCIL_VALUE)); // reference
344 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
346 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
347 DE_NULL, // const void* pNext;
348 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
349 useDepth, // VkBool32 depthTestEnable;
350 VK_FALSE, // VkBool32 depthWriteEnable;
351 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
352 VK_FALSE, // VkBool32 depthBoundsTestEnable;
353 useStencil, // VkBool32 stencilTestEnable;
354 stencilOpState, // VkStencilOpState front;
355 stencilOpState, // VkStencilOpState back;
356 0.0f, // float minDepthBounds;
357 1.0f, // float maxDepthBounds;
360 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
361 // Number of blend attachments must equal the number of color attachments during any subpass.
362 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
364 VK_FALSE, // VkBool32 blendEnable;
365 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
366 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
367 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
368 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
369 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
370 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
371 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
374 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
376 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
377 DE_NULL, // const void* pNext;
378 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
379 VK_FALSE, // VkBool32 logicOpEnable;
380 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
381 1u, // deUint32 attachmentCount;
382 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
383 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
386 const VkPipelineShaderStageCreateInfo pShaderStages[] =
389 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
390 DE_NULL, // const void* pNext;
391 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
392 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
393 vertexModule, // VkShaderModule module;
394 "main", // const char* pName;
395 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
398 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
399 DE_NULL, // const void* pNext;
400 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
401 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
402 fragmentModule, // VkShaderModule module;
403 "main", // const char* pName;
404 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
408 const VkPipelineCreateFlags flags = (basePipeline == DE_NULL ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
409 : VK_PIPELINE_CREATE_DERIVATIVE_BIT);
411 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
413 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
414 DE_NULL, // const void* pNext;
415 flags, // VkPipelineCreateFlags flags;
416 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
417 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
418 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
419 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
420 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
421 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
422 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
423 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
424 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
425 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
426 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
427 pipelineLayout, // VkPipelineLayout layout;
428 renderPass, // VkRenderPass renderPass;
429 subpass, // deUint32 subpass;
430 basePipeline, // VkPipeline basePipelineHandle;
431 -1, // deInt32 basePipelineIndex;
434 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
437 //! Make a render pass with one subpass per color attachment and depth/stencil attachment (if used).
438 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
439 const VkDevice device,
440 const VkFormat colorFormat,
441 const VkFormat depthStencilFormat,
442 const deUint32 numLayers,
443 const VkImageLayout initialColorImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
444 const VkImageLayout initialDepthStencilImageLayout = VK_IMAGE_LAYOUT_UNDEFINED)
446 const VkAttachmentDescription colorAttachmentDescription =
448 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
449 colorFormat, // VkFormat format;
450 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
451 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
452 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
453 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
454 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
455 initialColorImageLayout, // VkImageLayout initialLayout;
456 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
458 vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
460 const VkAttachmentDescription depthStencilAttachmentDescription =
462 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
463 depthStencilFormat, // VkFormat format;
464 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
465 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
466 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
467 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
468 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
469 initialDepthStencilImageLayout, // VkImageLayout initialLayout;
470 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
473 if (depthStencilFormat != VK_FORMAT_UNDEFINED)
474 attachmentDescriptions.insert(attachmentDescriptions.end(), numLayers, depthStencilAttachmentDescription);
476 // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
477 vector<VkAttachmentReference> colorAttachmentReferences (numLayers);
478 vector<VkAttachmentReference> depthStencilAttachmentReferences(numLayers);
479 vector<VkSubpassDescription> subpasses;
481 // Ordering here must match the framebuffer attachments
482 for (deUint32 i = 0; i < numLayers; ++i)
484 const VkAttachmentReference attachmentRef =
486 i, // deUint32 attachment;
487 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
489 const VkAttachmentReference depthStencilAttachmentRef =
491 i + numLayers, // deUint32 attachment;
492 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout;
495 colorAttachmentReferences[i] = attachmentRef;
496 depthStencilAttachmentReferences[i] = depthStencilAttachmentRef;
498 const VkAttachmentReference* pDepthStencilAttachment = (depthStencilFormat != VK_FORMAT_UNDEFINED ? &depthStencilAttachmentReferences[i] : DE_NULL);
499 const VkSubpassDescription subpassDescription =
501 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
502 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
503 0u, // deUint32 inputAttachmentCount;
504 DE_NULL, // const VkAttachmentReference* pInputAttachments;
505 1u, // deUint32 colorAttachmentCount;
506 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
507 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
508 pDepthStencilAttachment, // const VkAttachmentReference* pDepthStencilAttachment;
509 0u, // deUint32 preserveAttachmentCount;
510 DE_NULL // const deUint32* pPreserveAttachments;
512 subpasses.push_back(subpassDescription);
515 const VkRenderPassCreateInfo renderPassInfo =
517 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
518 DE_NULL, // const void* pNext;
519 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
520 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
521 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
522 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
523 &subpasses[0], // const VkSubpassDescription* pSubpasses;
524 0u, // deUint32 dependencyCount;
525 DE_NULL // const VkSubpassDependency* pDependencies;
528 return createRenderPass(vk, device, &renderPassInfo);
531 Move<VkImage> makeImage (const DeviceInterface& vk,
532 const VkDevice device,
533 VkImageCreateFlags flags,
534 VkImageType imageType,
535 const VkFormat format,
537 const deUint32 numMipLevels,
538 const deUint32 numLayers,
539 const VkImageUsageFlags usage)
541 const VkImageCreateInfo imageParams =
543 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
544 DE_NULL, // const void* pNext;
545 flags, // VkImageCreateFlags flags;
546 imageType, // VkImageType imageType;
547 format, // VkFormat format;
548 makeExtent3D(size), // VkExtent3D extent;
549 numMipLevels, // deUint32 mipLevels;
550 numLayers, // deUint32 arrayLayers;
551 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
552 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
553 usage, // VkImageUsageFlags usage;
554 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
555 0u, // deUint32 queueFamilyIndexCount;
556 DE_NULL, // const deUint32* pQueueFamilyIndices;
557 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
559 return createImage(vk, device, &imageParams);
562 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
564 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
565 return createBuffer(vk, device, &bufferCreateInfo);
568 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
570 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
573 //! Get a reference clear value based on color format.
574 VkClearValue getClearValue (const VkFormat format)
576 if (isUintFormat(format) || isIntFormat(format))
577 return makeClearValueColorU32(REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE);
579 return makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
582 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
584 std::ostringstream str;
585 if (numComponents == 1)
586 str << (isUint ? "uint" : isSint ? "int" : "float");
588 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
593 //! A half-viewport quad. Use with TRIANGLE_STRIP topology.
594 vector<Vertex4RGBA> genFullQuadVertices (const int subpassCount)
596 vector<Vertex4RGBA> vectorData;
597 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
601 Vec4(0.0f, -1.0f, 0.0f, 1.0f),
602 COLOR_TABLE[subpassNdx % DE_LENGTH_OF_ARRAY(COLOR_TABLE)],
604 vectorData.push_back(data);
605 data.position = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
606 vectorData.push_back(data);
607 data.position = Vec4(1.0f, -1.0f, 0.0f, 1.0f);
608 vectorData.push_back(data);
609 data.position = Vec4(1.0f, 1.0f, 0.0f, 1.0f);
610 vectorData.push_back(data);
615 VkImageType getImageType (const VkImageViewType viewType)
619 case VK_IMAGE_VIEW_TYPE_1D:
620 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
621 return VK_IMAGE_TYPE_1D;
623 case VK_IMAGE_VIEW_TYPE_2D:
624 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
625 case VK_IMAGE_VIEW_TYPE_CUBE:
626 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
627 return VK_IMAGE_TYPE_2D;
629 case VK_IMAGE_VIEW_TYPE_3D:
630 return VK_IMAGE_TYPE_3D;
634 return VK_IMAGE_TYPE_LAST;
638 //! ImageViewType for accessing a single layer/slice of an image
639 VkImageViewType getImageViewSliceType (const VkImageViewType viewType)
643 case VK_IMAGE_VIEW_TYPE_1D:
644 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
645 return VK_IMAGE_VIEW_TYPE_1D;
647 case VK_IMAGE_VIEW_TYPE_2D:
648 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
649 case VK_IMAGE_VIEW_TYPE_CUBE:
650 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
651 case VK_IMAGE_VIEW_TYPE_3D:
652 return VK_IMAGE_VIEW_TYPE_2D;
656 return VK_IMAGE_VIEW_TYPE_LAST;
660 VkImageCreateFlags getImageCreateFlags (const VkImageViewType viewType)
662 VkImageCreateFlags flags = (VkImageCreateFlags)0;
664 if (viewType == VK_IMAGE_VIEW_TYPE_3D) flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
665 if (isCube(viewType)) flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
670 void generateExpectedImage (const tcu::PixelBufferAccess& outputImage, const IVec2& renderSize, const int colorDepthOffset)
672 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(outputImage.getFormat().type);
673 const bool isInt = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
674 const VkClearValue clearValue = getClearValue(mapTextureFormat(outputImage.getFormat()));
677 tcu::clear(outputImage, IVec4(clearValue.color.int32));
679 tcu::clear(outputImage, Vec4(clearValue.color.float32));
681 for (int z = 0; z < outputImage.getDepth(); ++z)
683 const Vec4& setColor = COLOR_TABLE[(z + colorDepthOffset) % DE_LENGTH_OF_ARRAY(COLOR_TABLE)];
684 const IVec4 setColorInt = (static_cast<float>(REFERENCE_COLOR_VALUE) * setColor).cast<deInt32>();
686 for (int y = 0; y < renderSize.y(); ++y)
687 for (int x = renderSize.x()/2; x < renderSize.x(); ++x)
690 outputImage.setPixel(setColorInt, x, y, z);
692 outputImage.setPixel(setColor, x, y, z);
697 VkDeviceSize getMaxDeviceHeapSize (const InstanceInterface& vki, const VkPhysicalDevice physDevice)
699 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physDevice);
700 VkDeviceSize memorySize = 0;
702 for (deUint32 heapNdx = 0; heapNdx < memoryProperties.memoryHeapCount; ++heapNdx)
704 if ((memoryProperties.memoryHeaps[heapNdx].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
705 memorySize = std::max(memorySize, memoryProperties.memoryHeaps[heapNdx].size);
711 //! Get a smaller image size. Returns a vector of zeroes, if it can't reduce more.
712 IVec4 getReducedImageSize (const CaseDef& caseDef, IVec4 size)
714 const int maxIndex = findIndexOfMaxComponent(size);
715 const int reducedSize = size[maxIndex] >> 1;
717 switch (caseDef.viewType)
719 case VK_IMAGE_VIEW_TYPE_CUBE:
720 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
722 size.x() = size.y() = reducedSize;
723 else if (maxIndex == 3 && reducedSize >= NUM_CUBE_FACES)
724 size.w() = NUM_CUBE_FACES * (reducedSize / NUM_CUBE_FACES); // round down to a multiple of 6
730 size[maxIndex] = reducedSize;
734 if (reducedSize == 0)
740 bool isDepthStencilFormatSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format)
742 const VkFormatProperties properties = getPhysicalDeviceFormatProperties(vki, physDevice, format);
743 return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
746 IVec4 getMaxImageSize (const VkPhysicalDeviceLimits& limits, const VkImageViewType viewType, const IVec4& sizeHint, const bool useDepthStencil)
748 // If we use a layered D/S together with a 3D image, we have to use the smallest common limit
749 const int maxDepth = (useDepthStencil ? deMin32(static_cast<int>(limits.maxImageArrayLayers), static_cast<int>(limits.maxImageDimension3D))
750 : static_cast<int>(limits.maxImageDimension3D));
752 // Images have to respect framebuffer limits and image limits (the framebuffer is not layered in this case)
754 sizeHint.x() != MAX_SIZE ? sizeHint.x() : static_cast<int>(limits.maxFramebufferWidth),
755 sizeHint.y() != MAX_SIZE ? sizeHint.y() : static_cast<int>(limits.maxFramebufferHeight),
756 sizeHint.z() != MAX_SIZE ? sizeHint.z() : maxDepth,
757 sizeHint.w() != MAX_SIZE ? sizeHint.w() : static_cast<int>(limits.maxImageArrayLayers));
761 case VK_IMAGE_VIEW_TYPE_1D:
762 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
763 size.x() = deMin32(size.x(), limits.maxImageDimension1D);
766 case VK_IMAGE_VIEW_TYPE_2D:
767 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
768 size.x() = deMin32(size.x(), limits.maxImageDimension2D);
769 size.y() = deMin32(size.y(), limits.maxImageDimension2D);
772 case VK_IMAGE_VIEW_TYPE_3D:
773 size.x() = deMin32(size.x(), limits.maxImageDimension3D);
774 size.y() = deMin32(size.y(), limits.maxImageDimension3D);
777 case VK_IMAGE_VIEW_TYPE_CUBE:
778 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
779 size.x() = size.y() = deMin32(size.x(), limits.maxImageDimensionCube);
780 size.w() = NUM_CUBE_FACES * (size.w() / NUM_CUBE_FACES); // round down to 6 faces
791 VkImageAspectFlags getFormatAspectFlags (const VkFormat format)
793 if (format == VK_FORMAT_UNDEFINED)
796 const tcu::TextureFormat::ChannelOrder order = mapVkFormat(format).order;
800 case tcu::TextureFormat::DS: return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
801 case tcu::TextureFormat::D: return VK_IMAGE_ASPECT_DEPTH_BIT;
802 case tcu::TextureFormat::S: return VK_IMAGE_ASPECT_STENCIL_BIT;
803 default: return VK_IMAGE_ASPECT_COLOR_BIT;
807 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
809 const int numComponents = getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
810 const bool isUint = isUintFormat(caseDef.colorFormat);
811 const bool isSint = isIntFormat(caseDef.colorFormat);
815 std::ostringstream src;
816 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
818 << "layout(location = 0) in vec4 in_position;\n"
819 << "layout(location = 1) in vec4 in_color;\n"
820 << "layout(location = 0) out vec4 out_color;\n"
822 << "out gl_PerVertex {\n"
823 << " vec4 gl_Position;\n"
826 << "void main(void)\n"
828 << " gl_Position = in_position;\n"
829 << " out_color = in_color;\n"
832 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
837 std::ostringstream colorValue;
838 colorValue << REFERENCE_COLOR_VALUE;
839 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
840 const std::string colorInteger = (isUint || isSint ? " * "+colorFormat+"("+colorValue.str()+")" :"");
842 std::ostringstream src;
843 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
845 << "layout(location = 0) in vec4 in_color;\n"
846 << "layout(location = 0) out " << colorFormat << " o_color;\n"
848 << "void main(void)\n"
850 << " o_color = " << colorFormat << "("
851 << (numComponents == 1 ? "in_color.r" :
852 numComponents == 2 ? "in_color.rg" :
853 numComponents == 3 ? "in_color.rgb" : "in_color")
858 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
862 //! See testAttachmentSize() description
863 tcu::TestStatus testWithSizeReduction (Context& context, const CaseDef& caseDef, const int sizeReductionIndex)
865 const DeviceInterface& vk = context.getDeviceInterface();
866 const InstanceInterface& vki = context.getInstanceInterface();
867 const VkDevice device = context.getDevice();
868 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
869 const VkQueue queue = context.getUniversalQueue();
870 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
871 Allocator& allocator = context.getDefaultAllocator();
873 // The memory might be too small to allocate a largest possible attachment, so try to account for that.
874 const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
875 const VkDeviceSize deviceMemoryBudget = getMaxDeviceHeapSize(vki, physDevice) >> 2;
876 IVec4 imageSize = getMaxImageSize(context.getDeviceProperties().limits, caseDef.viewType, caseDef.imageSizeHint, useDepthStencil);
878 // Keep reducing the size, if needed
879 for (int i = 0; i < sizeReductionIndex; ++i)
881 imageSize = getReducedImageSize(caseDef, imageSize);
883 if (imageSize == IVec4())
884 return tcu::TestStatus::fail("Couldn't create an image with required size");
887 context.getTestContext().getLog()
888 << tcu::TestLog::Message << "Using an image with size (width, height, depth, layers) = " << imageSize << tcu::TestLog::EndMessage;
890 // "Slices" is either the depth of a 3D image, or the number of layers of an arrayed image
891 const deInt32 numSlices = maxLayersOrDepth(imageSize);
892 const VkDeviceSize colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
893 const VkDeviceSize depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull);
895 if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat))
896 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
898 if (colorSize + depthStencilSize > deviceMemoryBudget)
899 throw OutOfMemoryError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Image size exceeds test's image memory budget");
901 // Determine the verification bounds. The checked region will be in the center of the rendered image
902 const IVec4 checkSize = tcu::min(imageSize, IVec4(MAX_VERIFICATION_REGION_SIZE,
903 MAX_VERIFICATION_REGION_SIZE,
904 MAX_VERIFICATION_REGION_DEPTH,
905 MAX_VERIFICATION_REGION_DEPTH));
906 const IVec4 checkOffset = (imageSize - checkSize) / 2;
908 // Only make enough space for the check region
909 const VkDeviceSize colorBufferSize = product(checkSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
910 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
911 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vki, vk, physDevice, device, *colorBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind));
914 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
915 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
918 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
919 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
920 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices)));
921 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
922 vector<SharedPtrVkPipeline> pipelines;
924 Move<VkImage> colorImage;
925 MovePtr<Allocation> colorImageAlloc;
926 vector<SharedPtrVkImageView> colorAttachments;
927 Move<VkImage> depthStencilImage;
928 MovePtr<Allocation> depthStencilImageAlloc;
929 vector<SharedPtrVkImageView> depthStencilAttachments;
930 vector<VkImageView> attachmentHandles; // all attachments (color and d/s)
931 Move<VkBuffer> vertexBuffer;
932 MovePtr<Allocation> vertexBufferAlloc;
933 Move<VkFramebuffer> framebuffer;
935 // Create a color image
937 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
939 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
940 imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage);
941 colorImageAlloc = bindImage(vki, vk, physDevice, device, *colorImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
944 // Create a depth/stencil image (always a 2D image, optionally layered)
947 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
949 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
950 IVec3(imageSize.x(), imageSize.y(), 1), 1u, numSlices, imageUsage);
951 depthStencilImageAlloc = bindImage(vki, vk, physDevice, device, *depthStencilImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
954 // Create a vertex buffer
956 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices);
957 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
959 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
960 vertexBufferAlloc = bindBuffer(vki, vk, physDevice, device, *vertexBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind);
962 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
963 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
966 // For each image layer or slice (3D), create an attachment and a pipeline
968 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat);
969 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
970 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
971 VkPipeline basePipeline = DE_NULL;
973 // Color attachments are first in the framebuffer
974 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
976 colorAttachments.push_back(makeSharedPtr(
977 makeImageView(vk, device, *colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat, makeColorSubresourceRange(subpassNdx, 1))));
978 attachmentHandles.push_back(**colorAttachments.back());
980 // We also have to create pipelines for each subpass
981 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
982 vk, device, basePipeline, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, imageSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
983 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
985 basePipeline = **pipelines.front();
988 // Then D/S attachments, if any
990 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
992 depthStencilAttachments.push_back(makeSharedPtr(
993 makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat, makeImageSubresourceRange(depthStencilAspect, 0u, 1u, subpassNdx, 1u))));
994 attachmentHandles.push_back(**depthStencilAttachments.back());
998 framebuffer = makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0], static_cast<deUint32>(imageSize.x()), static_cast<deUint32>(imageSize.y()));
1001 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1002 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1004 beginCommandBuffer(vk, *cmdBuffer);
1006 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat));
1008 if (useDepthStencil)
1009 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
1011 const VkRect2D renderArea =
1014 makeExtent2D(imageSize.x(), imageSize.y()),
1016 const VkRenderPassBeginInfo renderPassBeginInfo =
1018 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1019 DE_NULL, // const void* pNext;
1020 *renderPass, // VkRenderPass renderPass;
1021 *framebuffer, // VkFramebuffer framebuffer;
1022 renderArea, // VkRect2D renderArea;
1023 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
1024 &clearValues[0], // const VkClearValue* pClearValues;
1026 const VkDeviceSize vertexBufferOffset = 0ull;
1028 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1029 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1033 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
1035 if (subpassNdx != 0)
1036 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1038 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
1039 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
1042 vk.cmdEndRenderPass(*cmdBuffer);
1044 // Copy colorImage -> host visible colorBuffer
1046 const VkImageMemoryBarrier imageBarriers[] =
1049 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1050 DE_NULL, // const void* pNext;
1051 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1052 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1053 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1054 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1055 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1056 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1057 *colorImage, // VkImage image;
1058 makeColorSubresourceRange(0, imageSize.w()) // VkImageSubresourceRange subresourceRange;
1062 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1063 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1065 // Copy the checked region rather than the whole image
1066 const VkImageSubresourceLayers subresource =
1068 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1069 0u, // uint32_t mipLevel;
1070 static_cast<deUint32>(checkOffset.w()), // uint32_t baseArrayLayer;
1071 static_cast<deUint32>(checkSize.w()), // uint32_t layerCount;
1074 const VkBufferImageCopy region =
1076 0ull, // VkDeviceSize bufferOffset;
1077 0u, // uint32_t bufferRowLength;
1078 0u, // uint32_t bufferImageHeight;
1079 subresource, // VkImageSubresourceLayers imageSubresource;
1080 makeOffset3D(checkOffset.x(), checkOffset.y(), checkOffset.z()), // VkOffset3D imageOffset;
1081 makeExtent3D(checkSize.swizzle(0, 1, 2)), // VkExtent3D imageExtent;
1084 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1086 const VkBufferMemoryBarrier bufferBarriers[] =
1089 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1090 DE_NULL, // const void* pNext;
1091 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1092 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1093 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1094 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1095 *colorBuffer, // VkBuffer buffer;
1096 0ull, // VkDeviceSize offset;
1097 VK_WHOLE_SIZE, // VkDeviceSize size;
1101 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1102 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1105 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1106 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1111 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1113 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat);
1114 const int checkDepth = maxLayersOrDepth(checkSize);
1115 const int depthOffset = maxLayersOrDepth(checkOffset);
1116 const tcu::ConstPixelBufferAccess resultImage (format, checkSize.x(), checkSize.y(), checkDepth, colorBufferAlloc->getHostPtr());
1117 tcu::TextureLevel textureLevel (format, checkSize.x(), checkSize.y(), checkDepth);
1118 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1121 generateExpectedImage(expectedImage, checkSize.swizzle(0, 1), depthOffset);
1123 if (isFloatFormat(caseDef.colorFormat))
1124 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1126 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1128 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1132 void checkImageViewTypeRequirements (Context& context, const VkImageViewType viewType)
1134 if (viewType == VK_IMAGE_VIEW_TYPE_3D &&
1135 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1"))
1136 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1138 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !context.getDeviceFeatures().imageCubeArray)
1139 TCU_THROW(NotSupportedError, "Missing feature: imageCubeArray");
1142 //! A test that can exercise very big color and depth/stencil attachment sizes.
1143 //! If the total memory consumed by images is too large, or if the implementation returns OUT_OF_MEMORY error somewhere,
1144 //! the test can be retried with a next increment of size reduction index, making the attachments smaller.
1145 tcu::TestStatus testAttachmentSize (Context& context, const CaseDef caseDef)
1147 checkImageViewTypeRequirements(context, caseDef.viewType);
1149 int sizeReductionIndex = 0;
1151 if (caseDef.allocationKind == ALLOCATION_KIND_DEDICATED)
1153 const std::string extensionName("VK_KHR_dedicated_allocation");
1155 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
1156 TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
1163 return testWithSizeReduction(context, caseDef, sizeReductionIndex);
1165 catch (OutOfMemoryError& ex)
1167 context.getTestContext().getLog()
1168 << tcu::TestLog::Message << "-- OutOfMemoryError: " << ex.getMessage() << tcu::TestLog::EndMessage;
1170 ++sizeReductionIndex;
1176 vector<IVec4> getMipLevelSizes (IVec4 baseSize)
1178 vector<IVec4> levels;
1179 levels.push_back(baseSize);
1181 while (baseSize.x() != 1 || baseSize.y() != 1 || baseSize.z() != 1)
1183 baseSize.x() = deMax32(baseSize.x() >> 1, 1);
1184 baseSize.y() = deMax32(baseSize.y() >> 1, 1);
1185 baseSize.z() = deMax32(baseSize.z() >> 1, 1);
1186 levels.push_back(baseSize);
1192 //! Compute memory consumed by each mip level, including all layers. Sizes include a padding for alignment.
1193 vector<VkDeviceSize> getPerMipLevelStorageSize (const vector<IVec4>& mipLevelSizes, const VkDeviceSize pixelSize)
1195 const deInt64 levelAlignment = 16;
1196 vector<VkDeviceSize> storageSizes;
1198 for (vector<IVec4>::const_iterator it = mipLevelSizes.begin(); it != mipLevelSizes.end(); ++it)
1199 storageSizes.push_back(deAlign64(pixelSize * product(*it), levelAlignment));
1201 return storageSizes;
1204 void drawToMipLevel (const Context& context,
1205 const CaseDef& caseDef,
1207 const IVec4& mipSize,
1208 const int numSlices,
1209 const VkImage colorImage,
1210 const VkImage depthStencilImage,
1211 const VkBuffer vertexBuffer,
1212 const VkPipelineLayout pipelineLayout,
1213 const VkShaderModule vertexModule,
1214 const VkShaderModule fragmentModule)
1216 const DeviceInterface& vk = context.getDeviceInterface();
1217 const VkDevice device = context.getDevice();
1218 const VkQueue queue = context.getUniversalQueue();
1219 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1220 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat);
1221 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
1222 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
1223 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices),
1224 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1225 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
1226 vector<SharedPtrVkPipeline> pipelines;
1227 vector<SharedPtrVkImageView> colorAttachments;
1228 vector<SharedPtrVkImageView> depthStencilAttachments;
1229 vector<VkImageView> attachmentHandles; // all attachments (color and d/s)
1231 // For each image layer or slice (3D), create an attachment and a pipeline
1233 VkPipeline basePipeline = DE_NULL;
1235 // Color attachments are first in the framebuffer
1236 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1238 colorAttachments.push_back(makeSharedPtr(makeImageView(
1239 vk, device, colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat,
1240 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, subpassNdx, 1u))));
1241 attachmentHandles.push_back(**colorAttachments.back());
1243 // We also have to create pipelines for each subpass
1244 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
1245 vk, device, basePipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, mipSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1246 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
1248 basePipeline = **pipelines.front();
1251 // Then D/S attachments, if any
1252 if (useDepth || useStencil)
1253 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1255 depthStencilAttachments.push_back(makeSharedPtr(makeImageView(
1256 vk, device, depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat,
1257 makeImageSubresourceRange(depthStencilAspect, mipLevel, 1u, subpassNdx, 1u))));
1258 attachmentHandles.push_back(**depthStencilAttachments.back());
1262 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0],
1263 static_cast<deUint32>(mipSize.x()), static_cast<deUint32>(mipSize.y())));
1266 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1267 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1269 beginCommandBuffer(vk, *cmdBuffer);
1271 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat));
1273 if (useDepth || useStencil)
1274 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
1276 const VkRect2D renderArea =
1279 makeExtent2D(mipSize.x(), mipSize.y()),
1281 const VkRenderPassBeginInfo renderPassBeginInfo =
1283 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1284 DE_NULL, // const void* pNext;
1285 *renderPass, // VkRenderPass renderPass;
1286 *framebuffer, // VkFramebuffer framebuffer;
1287 renderArea, // VkRect2D renderArea;
1288 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
1289 &clearValues[0], // const VkClearValue* pClearValues;
1291 const VkDeviceSize vertexBufferOffset = 0ull;
1293 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1294 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1298 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
1300 if (subpassNdx != 0)
1301 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1303 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
1304 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
1307 vk.cmdEndRenderPass(*cmdBuffer);
1309 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1310 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1314 //! Use image mip levels as attachments
1315 tcu::TestStatus testRenderToMipMaps (Context& context, const CaseDef caseDef)
1317 checkImageViewTypeRequirements(context, caseDef.viewType);
1319 const DeviceInterface& vk = context.getDeviceInterface();
1320 const InstanceInterface& vki = context.getInstanceInterface();
1321 const VkDevice device = context.getDevice();
1322 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1323 const VkQueue queue = context.getUniversalQueue();
1324 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1325 Allocator& allocator = context.getDefaultAllocator();
1327 const IVec4 imageSize = caseDef.imageSizeHint; // MAX_SIZE is not used in this test
1328 const deInt32 numSlices = maxLayersOrDepth(imageSize);
1329 const vector<IVec4> mipLevelSizes = getMipLevelSizes(imageSize);
1330 const vector<VkDeviceSize> mipLevelStorageSizes = getPerMipLevelStorageSize(mipLevelSizes, tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)));
1331 const int numMipLevels = static_cast<int>(mipLevelSizes.size());
1332 const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
1334 if (caseDef.allocationKind == ALLOCATION_KIND_DEDICATED)
1336 const std::string extensionName("VK_KHR_dedicated_allocation");
1338 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
1339 TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
1342 if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat))
1343 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
1345 // Create a color buffer big enough to hold all layers and mip levels
1346 const VkDeviceSize colorBufferSize = sum(mipLevelStorageSizes);
1347 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1348 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vki, vk, physDevice, device, *colorBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind));
1351 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1352 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1355 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1356 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1357 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
1359 Move<VkImage> colorImage;
1360 MovePtr<Allocation> colorImageAlloc;
1361 Move<VkImage> depthStencilImage;
1362 MovePtr<Allocation> depthStencilImageAlloc;
1363 Move<VkBuffer> vertexBuffer;
1364 MovePtr<Allocation> vertexBufferAlloc;
1366 // Create a color image
1368 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1370 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
1371 imageSize.swizzle(0, 1, 2), numMipLevels, imageSize.w(), imageUsage);
1372 colorImageAlloc = bindImage(vki, vk, physDevice, device, *colorImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
1375 // Create a depth/stencil image (always a 2D image, optionally layered)
1376 if (useDepthStencil)
1378 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1380 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
1381 IVec3(imageSize.x(), imageSize.y(), 1), numMipLevels, numSlices, imageUsage);
1382 depthStencilImageAlloc = bindImage(vki, vk, physDevice, device, *depthStencilImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
1385 // Create a vertex buffer
1387 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices);
1388 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1390 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1391 vertexBufferAlloc = bindBuffer(vki, vk, physDevice, device, *vertexBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind);
1393 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1394 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
1399 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1400 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1402 beginCommandBuffer(vk, *cmdBuffer);
1404 const VkImageMemoryBarrier imageBarriers[] =
1407 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1408 DE_NULL, // const void* pNext;
1409 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1410 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1411 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1412 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1413 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1414 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1415 *colorImage, // VkImage image;
1416 { // VkImageSubresourceRange subresourceRange;
1417 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1418 0u, // uint32_t baseMipLevel;
1419 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1420 0u, // uint32_t baseArrayLayer;
1421 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount;
1425 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1426 DE_NULL, // const void* pNext;
1427 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1428 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1429 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1430 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1431 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1432 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1433 *depthStencilImage, // VkImage image;
1434 { // VkImageSubresourceRange subresourceRange;
1435 getFormatAspectFlags(caseDef.depthStencilFormat), // VkImageAspectFlags aspectMask;
1436 0u, // uint32_t baseMipLevel;
1437 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1438 0u, // uint32_t baseArrayLayer;
1439 static_cast<deUint32>(numSlices), // uint32_t layerCount;
1444 const deUint32 numImageBarriers = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(imageBarriers) - (useDepthStencil ? 0 : 1));
1446 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1447 0u, DE_NULL, 0u, DE_NULL, numImageBarriers, imageBarriers);
1449 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1450 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1454 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1456 const IVec4& mipSize = mipLevelSizes[mipLevel];
1457 const int levelSlices = maxLayersOrDepth(mipSize);
1459 drawToMipLevel (context, caseDef, mipLevel, mipSize, levelSlices, *colorImage, *depthStencilImage, *vertexBuffer, *pipelineLayout,
1460 *vertexModule, *fragmentModule);
1463 // Copy results: colorImage -> host visible colorBuffer
1465 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1466 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1468 beginCommandBuffer(vk, *cmdBuffer);
1471 const VkImageMemoryBarrier imageBarriers[] =
1474 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1475 DE_NULL, // const void* pNext;
1476 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1477 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1478 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1479 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1480 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1481 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1482 *colorImage, // VkImage image;
1483 { // VkImageSubresourceRange subresourceRange;
1484 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1485 0u, // uint32_t baseMipLevel;
1486 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1487 0u, // uint32_t baseArrayLayer;
1488 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount;
1493 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1494 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1497 vector<VkBufferImageCopy> regions;
1498 VkDeviceSize levelOffset = 0ull;
1499 VkBufferImageCopy workRegion =
1501 0ull, // VkDeviceSize bufferOffset;
1502 0u, // uint32_t bufferRowLength;
1503 0u, // uint32_t bufferImageHeight;
1504 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageSize.w()), // VkImageSubresourceLayers imageSubresource;
1505 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1506 makeExtent3D(0, 0, 0), // VkExtent3D imageExtent;
1509 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1511 workRegion.bufferOffset = levelOffset;
1512 workRegion.imageSubresource.mipLevel = static_cast<deUint32>(mipLevel);
1513 workRegion.imageExtent = makeExtent3D(mipLevelSizes[mipLevel].swizzle(0, 1, 2));
1515 regions.push_back(workRegion);
1517 levelOffset += mipLevelStorageSizes[mipLevel];
1520 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, static_cast<deUint32>(regions.size()), ®ions[0]);
1523 const VkBufferMemoryBarrier bufferBarriers[] =
1526 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1527 DE_NULL, // const void* pNext;
1528 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1529 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1530 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1531 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1532 *colorBuffer, // VkBuffer buffer;
1533 0ull, // VkDeviceSize offset;
1534 VK_WHOLE_SIZE, // VkDeviceSize size;
1538 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1539 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1542 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1543 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1546 // Verify results (per mip level)
1548 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1550 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat);
1552 VkDeviceSize levelOffset = 0ull;
1555 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1557 const IVec4& mipSize = mipLevelSizes[mipLevel];
1558 const void* const pLevelData = static_cast<const deUint8*>(colorBufferAlloc->getHostPtr()) + levelOffset;
1559 const int levelDepth = maxLayersOrDepth(mipSize);
1560 const tcu::ConstPixelBufferAccess resultImage (format, mipSize.x(), mipSize.y(), levelDepth, pLevelData);
1561 tcu::TextureLevel textureLevel (format, mipSize.x(), mipSize.y(), levelDepth);
1562 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1563 const std::string comparisonName = "Mip level " + de::toString(mipLevel);
1566 generateExpectedImage(expectedImage, mipSize.swizzle(0, 1), 0);
1568 if (isFloatFormat(caseDef.colorFormat))
1569 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1571 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1573 allOk = allOk && ok; // keep testing all levels, even if we know it's a fail overall
1574 levelOffset += mipLevelStorageSizes[mipLevel];
1577 return allOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1581 std::string getSizeDescription (const IVec4& size)
1583 std::ostringstream str;
1585 const char* const description[4] =
1587 "width", "height", "depth", "layers"
1590 int numMaxComponents = 0;
1592 for (int i = 0; i < 4; ++i)
1594 if (size[i] == MAX_SIZE)
1596 if (numMaxComponents > 0)
1599 str << description[i];
1604 if (numMaxComponents == 0)
1610 inline std::string getFormatString (const VkFormat format)
1612 std::string name(getFormatName(format));
1613 return de::toLower(name.substr(10));
1616 std::string getFormatString (const VkFormat colorFormat, const VkFormat depthStencilFormat)
1618 std::ostringstream str;
1619 str << getFormatString(colorFormat);
1620 if (depthStencilFormat != VK_FORMAT_UNDEFINED)
1621 str << "_" << getFormatString(depthStencilFormat);
1625 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1627 std::string s(getImageViewTypeName(imageViewType));
1628 return de::toLower(s.substr(19));
1631 inline BVec4 bvecFromMask (deUint32 mask)
1633 return BVec4((mask >> 0) & 1,
1639 vector<IVec4> genSizeCombinations (const IVec4& baselineSize, const deUint32 sizeMask, const VkImageViewType imageViewType)
1641 vector<IVec4> sizes;
1642 std::set<deUint32> masks;
1644 for (deUint32 i = 0; i < (1u << 4); ++i)
1646 // Cube images have square faces
1647 if (isCube(imageViewType) && ((i & MASK_WH) != 0))
1650 masks.insert(i & sizeMask);
1653 for (std::set<deUint32>::const_iterator it = masks.begin(); it != masks.end(); ++it)
1654 sizes.push_back(tcu::select(IVec4(MAX_SIZE), baselineSize, bvecFromMask(*it)));
1659 void addTestCasesWithFunctions (tcu::TestCaseGroup* group, AllocationKind allocationKind)
1663 VkImageViewType viewType;
1664 IVec4 baselineSize; //!< image size: (dimX, dimY, dimZ, arraySize)
1665 deUint32 sizeMask; //!< if a dimension is masked, generate a huge size case for it
1668 { VK_IMAGE_VIEW_TYPE_1D, IVec4(54, 1, 1, 1), MASK_W },
1669 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec4(54, 1, 1, 4), MASK_W_LAYERS },
1670 { VK_IMAGE_VIEW_TYPE_2D, IVec4(44, 23, 1, 1), MASK_WH },
1671 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec4(44, 23, 1, 4), MASK_WH_LAYERS },
1672 { VK_IMAGE_VIEW_TYPE_3D, IVec4(22, 31, 7, 1), MASK_WHD },
1673 { VK_IMAGE_VIEW_TYPE_CUBE, IVec4(35, 35, 1, 6), MASK_WH },
1674 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec4(35, 35, 1, 2*6), MASK_WH_LAYERS },
1677 const VkFormat format[] =
1679 VK_FORMAT_R8G8B8A8_UNORM,
1681 VK_FORMAT_R16G16_SINT,
1682 VK_FORMAT_R32G32B32A32_SFLOAT,
1685 const VkFormat depthStencilFormat[] =
1687 VK_FORMAT_UNDEFINED, // don't use a depth/stencil attachment
1688 VK_FORMAT_D16_UNORM,
1690 VK_FORMAT_D24_UNORM_S8_UINT, // one of the following mixed formats must be supported
1691 VK_FORMAT_D32_SFLOAT_S8_UINT,
1694 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCase); ++caseNdx)
1696 MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(testCase[caseNdx].viewType).c_str(), ""));
1698 // Generate attachment size cases
1700 const vector<IVec4> sizes = genSizeCombinations(testCase[caseNdx].baselineSize, testCase[caseNdx].sizeMask, testCase[caseNdx].viewType);
1702 MovePtr<tcu::TestCaseGroup> smallGroup(new tcu::TestCaseGroup(group->getTestContext(), "small", ""));
1703 MovePtr<tcu::TestCaseGroup> hugeGroup (new tcu::TestCaseGroup(group->getTestContext(), "huge", ""));
1705 imageGroup->addChild(smallGroup.get());
1706 imageGroup->addChild(hugeGroup.get());
1708 for (vector<IVec4>::const_iterator sizeIter = sizes.begin(); sizeIter != sizes.end(); ++sizeIter)
1710 // The first size is the baseline size, put it in a dedicated group
1711 if (sizeIter == sizes.begin())
1713 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1714 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1716 const CaseDef caseDef =
1718 testCase[caseNdx].viewType, // VkImageViewType imageType;
1719 *sizeIter, // IVec4 imageSizeHint;
1720 format[formatNdx], // VkFormat colorFormat;
1721 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1722 allocationKind // AllocationKind allocationKind;
1724 addFunctionCaseWithPrograms(smallGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1727 else // All huge cases go into a separate group
1729 if (allocationKind != ALLOCATION_KIND_DEDICATED)
1731 MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(group->getTestContext(), getSizeDescription(*sizeIter).c_str(), ""));
1732 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1734 // Use the same color format for all cases, to reduce the number of permutations
1735 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1737 const CaseDef caseDef =
1739 testCase[caseNdx].viewType, // VkImageViewType viewType;
1740 *sizeIter, // IVec4 imageSizeHint;
1741 colorFormat, // VkFormat colorFormat;
1742 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1743 allocationKind // AllocationKind allocationKind;
1745 addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(colorFormat, depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1747 hugeGroup->addChild(sizeGroup.release());
1751 smallGroup.release();
1752 hugeGroup.release();
1755 // Generate mip map cases
1757 MovePtr<tcu::TestCaseGroup> mipmapGroup(new tcu::TestCaseGroup(group->getTestContext(), "mipmap", ""));
1759 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1760 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1762 const CaseDef caseDef =
1764 testCase[caseNdx].viewType, // VkImageViewType imageType;
1765 testCase[caseNdx].baselineSize, // IVec4 imageSizeHint;
1766 format[formatNdx], // VkFormat colorFormat;
1767 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1768 allocationKind // AllocationKind allocationKind;
1770 addFunctionCaseWithPrograms(mipmapGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testRenderToMipMaps, caseDef);
1772 imageGroup->addChild(mipmapGroup.release());
1775 group->addChild(imageGroup.release());
1779 void addCoreRenderToImageTests (tcu::TestCaseGroup* group)
1781 addTestCasesWithFunctions(group, ALLOCATION_KIND_SUBALLOCATED);
1784 void addDedicatedAllocationRenderToImageTests (tcu::TestCaseGroup* group)
1786 addTestCasesWithFunctions(group, ALLOCATION_KIND_DEDICATED);
1791 tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx)
1793 de::MovePtr<tcu::TestCaseGroup> renderToImageTests (new tcu::TestCaseGroup(testCtx, "render_to_image", "Render to image tests"));
1795 renderToImageTests->addChild(createTestGroup(testCtx, "core", "Core render to image tests", addCoreRenderToImageTests));
1796 renderToImageTests->addChild(createTestGroup(testCtx, "dedicated_allocation", "Render to image tests for dedicated memory allocation", addDedicatedAllocationRenderToImageTests));
1798 return renderToImageTests.release();