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 (caseDef.viewType == VK_IMAGE_VIEW_TYPE_3D) ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
922 : VK_IMAGE_LAYOUT_UNDEFINED));
923 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
924 vector<SharedPtrVkPipeline> pipelines;
926 Move<VkImage> colorImage;
927 MovePtr<Allocation> colorImageAlloc;
928 vector<SharedPtrVkImageView> colorAttachments;
929 Move<VkImage> depthStencilImage;
930 MovePtr<Allocation> depthStencilImageAlloc;
931 vector<SharedPtrVkImageView> depthStencilAttachments;
932 vector<VkImageView> attachmentHandles; // all attachments (color and d/s)
933 Move<VkBuffer> vertexBuffer;
934 MovePtr<Allocation> vertexBufferAlloc;
935 Move<VkFramebuffer> framebuffer;
937 // Create a color image
939 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
941 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
942 imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage);
943 colorImageAlloc = bindImage(vki, vk, physDevice, device, *colorImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
946 // Create a depth/stencil image (always a 2D image, optionally layered)
949 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
951 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
952 IVec3(imageSize.x(), imageSize.y(), 1), 1u, numSlices, imageUsage);
953 depthStencilImageAlloc = bindImage(vki, vk, physDevice, device, *depthStencilImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
956 // Create a vertex buffer
958 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices);
959 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
961 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
962 vertexBufferAlloc = bindBuffer(vki, vk, physDevice, device, *vertexBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind);
964 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
965 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
968 // Prepare color image upfront for rendering to individual slices. 3D slices aren't separate subresources, so they shouldn't be transitioned
969 // during each subpass like array layers.
970 if (caseDef.viewType == VK_IMAGE_VIEW_TYPE_3D)
972 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
973 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
975 beginCommandBuffer(vk, *cmdBuffer);
977 const VkImageMemoryBarrier imageBarrier =
979 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
980 DE_NULL, // const void* pNext;
981 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
982 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
983 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
984 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
985 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
986 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
987 *colorImage, // VkImage image;
988 { // VkImageSubresourceRange subresourceRange;
989 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
990 0u, // uint32_t baseMipLevel;
991 1u, // uint32_t levelCount;
992 0u, // uint32_t baseArrayLayer;
993 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount;
997 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
998 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1000 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1001 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1004 // For each image layer or slice (3D), create an attachment and a pipeline
1006 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat);
1007 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
1008 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
1009 VkPipeline basePipeline = DE_NULL;
1011 // Color attachments are first in the framebuffer
1012 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1014 colorAttachments.push_back(makeSharedPtr(
1015 makeImageView(vk, device, *colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat, makeColorSubresourceRange(subpassNdx, 1))));
1016 attachmentHandles.push_back(**colorAttachments.back());
1018 // We also have to create pipelines for each subpass
1019 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
1020 vk, device, basePipeline, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, imageSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1021 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
1023 basePipeline = **pipelines.front();
1026 // Then D/S attachments, if any
1027 if (useDepthStencil)
1028 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1030 depthStencilAttachments.push_back(makeSharedPtr(
1031 makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat, makeImageSubresourceRange(depthStencilAspect, 0u, 1u, subpassNdx, 1u))));
1032 attachmentHandles.push_back(**depthStencilAttachments.back());
1036 framebuffer = makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0], static_cast<deUint32>(imageSize.x()), static_cast<deUint32>(imageSize.y()));
1039 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1040 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1042 beginCommandBuffer(vk, *cmdBuffer);
1044 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat));
1046 if (useDepthStencil)
1047 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
1049 const VkRect2D renderArea =
1052 makeExtent2D(imageSize.x(), imageSize.y()),
1054 const VkRenderPassBeginInfo renderPassBeginInfo =
1056 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1057 DE_NULL, // const void* pNext;
1058 *renderPass, // VkRenderPass renderPass;
1059 *framebuffer, // VkFramebuffer framebuffer;
1060 renderArea, // VkRect2D renderArea;
1061 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
1062 &clearValues[0], // const VkClearValue* pClearValues;
1064 const VkDeviceSize vertexBufferOffset = 0ull;
1066 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1067 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1071 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
1073 if (subpassNdx != 0)
1074 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1076 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
1077 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
1080 vk.cmdEndRenderPass(*cmdBuffer);
1082 // Copy colorImage -> host visible colorBuffer
1084 const VkImageMemoryBarrier imageBarriers[] =
1087 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1088 DE_NULL, // const void* pNext;
1089 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1090 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1091 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1092 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1093 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1094 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1095 *colorImage, // VkImage image;
1096 makeColorSubresourceRange(0, imageSize.w()) // VkImageSubresourceRange subresourceRange;
1100 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1101 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1103 // Copy the checked region rather than the whole image
1104 const VkImageSubresourceLayers subresource =
1106 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1107 0u, // uint32_t mipLevel;
1108 static_cast<deUint32>(checkOffset.w()), // uint32_t baseArrayLayer;
1109 static_cast<deUint32>(checkSize.w()), // uint32_t layerCount;
1112 const VkBufferImageCopy region =
1114 0ull, // VkDeviceSize bufferOffset;
1115 0u, // uint32_t bufferRowLength;
1116 0u, // uint32_t bufferImageHeight;
1117 subresource, // VkImageSubresourceLayers imageSubresource;
1118 makeOffset3D(checkOffset.x(), checkOffset.y(), checkOffset.z()), // VkOffset3D imageOffset;
1119 makeExtent3D(checkSize.swizzle(0, 1, 2)), // VkExtent3D imageExtent;
1122 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1124 const VkBufferMemoryBarrier bufferBarriers[] =
1127 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1128 DE_NULL, // const void* pNext;
1129 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1130 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1131 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1132 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1133 *colorBuffer, // VkBuffer buffer;
1134 0ull, // VkDeviceSize offset;
1135 VK_WHOLE_SIZE, // VkDeviceSize size;
1139 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1140 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1143 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1144 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1149 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1151 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat);
1152 const int checkDepth = maxLayersOrDepth(checkSize);
1153 const int depthOffset = maxLayersOrDepth(checkOffset);
1154 const tcu::ConstPixelBufferAccess resultImage (format, checkSize.x(), checkSize.y(), checkDepth, colorBufferAlloc->getHostPtr());
1155 tcu::TextureLevel textureLevel (format, checkSize.x(), checkSize.y(), checkDepth);
1156 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1159 generateExpectedImage(expectedImage, checkSize.swizzle(0, 1), depthOffset);
1161 if (isFloatFormat(caseDef.colorFormat))
1162 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1164 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1166 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1170 void checkImageViewTypeRequirements (Context& context, const VkImageViewType viewType)
1172 if (viewType == VK_IMAGE_VIEW_TYPE_3D &&
1173 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1"))
1174 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1176 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !context.getDeviceFeatures().imageCubeArray)
1177 TCU_THROW(NotSupportedError, "Missing feature: imageCubeArray");
1180 //! A test that can exercise very big color and depth/stencil attachment sizes.
1181 //! If the total memory consumed by images is too large, or if the implementation returns OUT_OF_MEMORY error somewhere,
1182 //! the test can be retried with a next increment of size reduction index, making the attachments smaller.
1183 tcu::TestStatus testAttachmentSize (Context& context, const CaseDef caseDef)
1185 checkImageViewTypeRequirements(context, caseDef.viewType);
1187 int sizeReductionIndex = 0;
1189 if (caseDef.allocationKind == ALLOCATION_KIND_DEDICATED)
1191 const std::string extensionName("VK_KHR_dedicated_allocation");
1193 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
1194 TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
1201 return testWithSizeReduction(context, caseDef, sizeReductionIndex);
1203 catch (OutOfMemoryError& ex)
1205 context.getTestContext().getLog()
1206 << tcu::TestLog::Message << "-- OutOfMemoryError: " << ex.getMessage() << tcu::TestLog::EndMessage;
1208 ++sizeReductionIndex;
1214 vector<IVec4> getMipLevelSizes (IVec4 baseSize)
1216 vector<IVec4> levels;
1217 levels.push_back(baseSize);
1219 while (baseSize.x() != 1 || baseSize.y() != 1 || baseSize.z() != 1)
1221 baseSize.x() = deMax32(baseSize.x() >> 1, 1);
1222 baseSize.y() = deMax32(baseSize.y() >> 1, 1);
1223 baseSize.z() = deMax32(baseSize.z() >> 1, 1);
1224 levels.push_back(baseSize);
1230 //! Compute memory consumed by each mip level, including all layers. Sizes include a padding for alignment.
1231 vector<VkDeviceSize> getPerMipLevelStorageSize (const vector<IVec4>& mipLevelSizes, const VkDeviceSize pixelSize)
1233 const deInt64 levelAlignment = 16;
1234 vector<VkDeviceSize> storageSizes;
1236 for (vector<IVec4>::const_iterator it = mipLevelSizes.begin(); it != mipLevelSizes.end(); ++it)
1237 storageSizes.push_back(deAlign64(pixelSize * product(*it), levelAlignment));
1239 return storageSizes;
1242 void drawToMipLevel (const Context& context,
1243 const CaseDef& caseDef,
1245 const IVec4& mipSize,
1246 const int numSlices,
1247 const VkImage colorImage,
1248 const VkImage depthStencilImage,
1249 const VkBuffer vertexBuffer,
1250 const VkPipelineLayout pipelineLayout,
1251 const VkShaderModule vertexModule,
1252 const VkShaderModule fragmentModule)
1254 const DeviceInterface& vk = context.getDeviceInterface();
1255 const VkDevice device = context.getDevice();
1256 const VkQueue queue = context.getUniversalQueue();
1257 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1258 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat);
1259 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
1260 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
1261 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices),
1262 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1263 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
1264 vector<SharedPtrVkPipeline> pipelines;
1265 vector<SharedPtrVkImageView> colorAttachments;
1266 vector<SharedPtrVkImageView> depthStencilAttachments;
1267 vector<VkImageView> attachmentHandles; // all attachments (color and d/s)
1269 // For each image layer or slice (3D), create an attachment and a pipeline
1271 VkPipeline basePipeline = DE_NULL;
1273 // Color attachments are first in the framebuffer
1274 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1276 colorAttachments.push_back(makeSharedPtr(makeImageView(
1277 vk, device, colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat,
1278 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, subpassNdx, 1u))));
1279 attachmentHandles.push_back(**colorAttachments.back());
1281 // We also have to create pipelines for each subpass
1282 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
1283 vk, device, basePipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, mipSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1284 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
1286 basePipeline = **pipelines.front();
1289 // Then D/S attachments, if any
1290 if (useDepth || useStencil)
1291 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1293 depthStencilAttachments.push_back(makeSharedPtr(makeImageView(
1294 vk, device, depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat,
1295 makeImageSubresourceRange(depthStencilAspect, mipLevel, 1u, subpassNdx, 1u))));
1296 attachmentHandles.push_back(**depthStencilAttachments.back());
1300 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0],
1301 static_cast<deUint32>(mipSize.x()), static_cast<deUint32>(mipSize.y())));
1304 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1305 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1307 beginCommandBuffer(vk, *cmdBuffer);
1309 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat));
1311 if (useDepth || useStencil)
1312 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
1314 const VkRect2D renderArea =
1317 makeExtent2D(mipSize.x(), mipSize.y()),
1319 const VkRenderPassBeginInfo renderPassBeginInfo =
1321 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1322 DE_NULL, // const void* pNext;
1323 *renderPass, // VkRenderPass renderPass;
1324 *framebuffer, // VkFramebuffer framebuffer;
1325 renderArea, // VkRect2D renderArea;
1326 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
1327 &clearValues[0], // const VkClearValue* pClearValues;
1329 const VkDeviceSize vertexBufferOffset = 0ull;
1331 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1332 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1336 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
1338 if (subpassNdx != 0)
1339 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1341 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
1342 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
1345 vk.cmdEndRenderPass(*cmdBuffer);
1347 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1348 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1352 //! Use image mip levels as attachments
1353 tcu::TestStatus testRenderToMipMaps (Context& context, const CaseDef caseDef)
1355 checkImageViewTypeRequirements(context, caseDef.viewType);
1357 const DeviceInterface& vk = context.getDeviceInterface();
1358 const InstanceInterface& vki = context.getInstanceInterface();
1359 const VkDevice device = context.getDevice();
1360 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1361 const VkQueue queue = context.getUniversalQueue();
1362 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1363 Allocator& allocator = context.getDefaultAllocator();
1365 const IVec4 imageSize = caseDef.imageSizeHint; // MAX_SIZE is not used in this test
1366 const deInt32 numSlices = maxLayersOrDepth(imageSize);
1367 const vector<IVec4> mipLevelSizes = getMipLevelSizes(imageSize);
1368 const vector<VkDeviceSize> mipLevelStorageSizes = getPerMipLevelStorageSize(mipLevelSizes, tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)));
1369 const int numMipLevels = static_cast<int>(mipLevelSizes.size());
1370 const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
1372 if (caseDef.allocationKind == ALLOCATION_KIND_DEDICATED)
1374 const std::string extensionName("VK_KHR_dedicated_allocation");
1376 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), extensionName))
1377 TCU_THROW(NotSupportedError, std::string(extensionName + " is not supported").c_str());
1380 if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat))
1381 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
1383 // Create a color buffer big enough to hold all layers and mip levels
1384 const VkDeviceSize colorBufferSize = sum(mipLevelStorageSizes);
1385 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1386 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vki, vk, physDevice, device, *colorBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind));
1389 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1390 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1393 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1394 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1395 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
1397 Move<VkImage> colorImage;
1398 MovePtr<Allocation> colorImageAlloc;
1399 Move<VkImage> depthStencilImage;
1400 MovePtr<Allocation> depthStencilImageAlloc;
1401 Move<VkBuffer> vertexBuffer;
1402 MovePtr<Allocation> vertexBufferAlloc;
1404 // Create a color image
1406 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1408 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
1409 imageSize.swizzle(0, 1, 2), numMipLevels, imageSize.w(), imageUsage);
1410 colorImageAlloc = bindImage(vki, vk, physDevice, device, *colorImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
1413 // Create a depth/stencil image (always a 2D image, optionally layered)
1414 if (useDepthStencil)
1416 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1418 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
1419 IVec3(imageSize.x(), imageSize.y(), 1), numMipLevels, numSlices, imageUsage);
1420 depthStencilImageAlloc = bindImage(vki, vk, physDevice, device, *depthStencilImage, MemoryRequirement::Any, allocator, caseDef.allocationKind);
1423 // Create a vertex buffer
1425 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices);
1426 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1428 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1429 vertexBufferAlloc = bindBuffer(vki, vk, physDevice, device, *vertexBuffer, MemoryRequirement::HostVisible, allocator, caseDef.allocationKind);
1431 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1432 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
1437 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1438 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1440 beginCommandBuffer(vk, *cmdBuffer);
1442 const VkImageMemoryBarrier imageBarriers[] =
1445 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1446 DE_NULL, // const void* pNext;
1447 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1448 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1449 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1450 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1451 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1452 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1453 *colorImage, // VkImage image;
1454 { // VkImageSubresourceRange subresourceRange;
1455 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1456 0u, // uint32_t baseMipLevel;
1457 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1458 0u, // uint32_t baseArrayLayer;
1459 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount;
1463 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1464 DE_NULL, // const void* pNext;
1465 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1466 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1467 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1468 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1469 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1470 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1471 *depthStencilImage, // VkImage image;
1472 { // VkImageSubresourceRange subresourceRange;
1473 getFormatAspectFlags(caseDef.depthStencilFormat), // VkImageAspectFlags aspectMask;
1474 0u, // uint32_t baseMipLevel;
1475 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1476 0u, // uint32_t baseArrayLayer;
1477 static_cast<deUint32>(numSlices), // uint32_t layerCount;
1482 const deUint32 numImageBarriers = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(imageBarriers) - (useDepthStencil ? 0 : 1));
1484 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1485 0u, DE_NULL, 0u, DE_NULL, numImageBarriers, imageBarriers);
1487 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1488 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1492 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1494 const IVec4& mipSize = mipLevelSizes[mipLevel];
1495 const int levelSlices = maxLayersOrDepth(mipSize);
1497 drawToMipLevel (context, caseDef, mipLevel, mipSize, levelSlices, *colorImage, *depthStencilImage, *vertexBuffer, *pipelineLayout,
1498 *vertexModule, *fragmentModule);
1501 // Copy results: colorImage -> host visible colorBuffer
1503 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1504 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1506 beginCommandBuffer(vk, *cmdBuffer);
1509 const VkImageMemoryBarrier imageBarriers[] =
1512 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1513 DE_NULL, // const void* pNext;
1514 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1515 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1516 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1517 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1518 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1519 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1520 *colorImage, // VkImage image;
1521 { // VkImageSubresourceRange subresourceRange;
1522 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1523 0u, // uint32_t baseMipLevel;
1524 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1525 0u, // uint32_t baseArrayLayer;
1526 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount;
1531 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1532 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1535 vector<VkBufferImageCopy> regions;
1536 VkDeviceSize levelOffset = 0ull;
1537 VkBufferImageCopy workRegion =
1539 0ull, // VkDeviceSize bufferOffset;
1540 0u, // uint32_t bufferRowLength;
1541 0u, // uint32_t bufferImageHeight;
1542 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageSize.w()), // VkImageSubresourceLayers imageSubresource;
1543 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1544 makeExtent3D(0, 0, 0), // VkExtent3D imageExtent;
1547 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1549 workRegion.bufferOffset = levelOffset;
1550 workRegion.imageSubresource.mipLevel = static_cast<deUint32>(mipLevel);
1551 workRegion.imageExtent = makeExtent3D(mipLevelSizes[mipLevel].swizzle(0, 1, 2));
1553 regions.push_back(workRegion);
1555 levelOffset += mipLevelStorageSizes[mipLevel];
1558 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, static_cast<deUint32>(regions.size()), ®ions[0]);
1561 const VkBufferMemoryBarrier bufferBarriers[] =
1564 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1565 DE_NULL, // const void* pNext;
1566 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1567 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1568 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1569 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1570 *colorBuffer, // VkBuffer buffer;
1571 0ull, // VkDeviceSize offset;
1572 VK_WHOLE_SIZE, // VkDeviceSize size;
1576 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1577 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1580 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1581 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1584 // Verify results (per mip level)
1586 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1588 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat);
1590 VkDeviceSize levelOffset = 0ull;
1593 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1595 const IVec4& mipSize = mipLevelSizes[mipLevel];
1596 const void* const pLevelData = static_cast<const deUint8*>(colorBufferAlloc->getHostPtr()) + levelOffset;
1597 const int levelDepth = maxLayersOrDepth(mipSize);
1598 const tcu::ConstPixelBufferAccess resultImage (format, mipSize.x(), mipSize.y(), levelDepth, pLevelData);
1599 tcu::TextureLevel textureLevel (format, mipSize.x(), mipSize.y(), levelDepth);
1600 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1601 const std::string comparisonName = "Mip level " + de::toString(mipLevel);
1604 generateExpectedImage(expectedImage, mipSize.swizzle(0, 1), 0);
1606 if (isFloatFormat(caseDef.colorFormat))
1607 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1609 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1611 allOk = allOk && ok; // keep testing all levels, even if we know it's a fail overall
1612 levelOffset += mipLevelStorageSizes[mipLevel];
1615 return allOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1619 std::string getSizeDescription (const IVec4& size)
1621 std::ostringstream str;
1623 const char* const description[4] =
1625 "width", "height", "depth", "layers"
1628 int numMaxComponents = 0;
1630 for (int i = 0; i < 4; ++i)
1632 if (size[i] == MAX_SIZE)
1634 if (numMaxComponents > 0)
1637 str << description[i];
1642 if (numMaxComponents == 0)
1648 inline std::string getFormatString (const VkFormat format)
1650 std::string name(getFormatName(format));
1651 return de::toLower(name.substr(10));
1654 std::string getFormatString (const VkFormat colorFormat, const VkFormat depthStencilFormat)
1656 std::ostringstream str;
1657 str << getFormatString(colorFormat);
1658 if (depthStencilFormat != VK_FORMAT_UNDEFINED)
1659 str << "_" << getFormatString(depthStencilFormat);
1663 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1665 std::string s(getImageViewTypeName(imageViewType));
1666 return de::toLower(s.substr(19));
1669 inline BVec4 bvecFromMask (deUint32 mask)
1671 return BVec4((mask >> 0) & 1,
1677 vector<IVec4> genSizeCombinations (const IVec4& baselineSize, const deUint32 sizeMask, const VkImageViewType imageViewType)
1679 vector<IVec4> sizes;
1680 std::set<deUint32> masks;
1682 for (deUint32 i = 0; i < (1u << 4); ++i)
1684 // Cube images have square faces
1685 if (isCube(imageViewType) && ((i & MASK_WH) != 0))
1688 masks.insert(i & sizeMask);
1691 for (std::set<deUint32>::const_iterator it = masks.begin(); it != masks.end(); ++it)
1692 sizes.push_back(tcu::select(IVec4(MAX_SIZE), baselineSize, bvecFromMask(*it)));
1697 void addTestCasesWithFunctions (tcu::TestCaseGroup* group, AllocationKind allocationKind)
1701 VkImageViewType viewType;
1702 IVec4 baselineSize; //!< image size: (dimX, dimY, dimZ, arraySize)
1703 deUint32 sizeMask; //!< if a dimension is masked, generate a huge size case for it
1706 { VK_IMAGE_VIEW_TYPE_1D, IVec4(54, 1, 1, 1), MASK_W },
1707 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec4(54, 1, 1, 4), MASK_W_LAYERS },
1708 { VK_IMAGE_VIEW_TYPE_2D, IVec4(44, 23, 1, 1), MASK_WH },
1709 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec4(44, 23, 1, 4), MASK_WH_LAYERS },
1710 { VK_IMAGE_VIEW_TYPE_3D, IVec4(22, 31, 7, 1), MASK_WHD },
1711 { VK_IMAGE_VIEW_TYPE_CUBE, IVec4(35, 35, 1, 6), MASK_WH },
1712 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec4(35, 35, 1, 2*6), MASK_WH_LAYERS },
1715 const VkFormat format[] =
1717 VK_FORMAT_R8G8B8A8_UNORM,
1719 VK_FORMAT_R16G16_SINT,
1720 VK_FORMAT_R32G32B32A32_SFLOAT,
1723 const VkFormat depthStencilFormat[] =
1725 VK_FORMAT_UNDEFINED, // don't use a depth/stencil attachment
1726 VK_FORMAT_D16_UNORM,
1728 VK_FORMAT_D24_UNORM_S8_UINT, // one of the following mixed formats must be supported
1729 VK_FORMAT_D32_SFLOAT_S8_UINT,
1732 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCase); ++caseNdx)
1734 MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(testCase[caseNdx].viewType).c_str(), ""));
1736 // Generate attachment size cases
1738 const vector<IVec4> sizes = genSizeCombinations(testCase[caseNdx].baselineSize, testCase[caseNdx].sizeMask, testCase[caseNdx].viewType);
1740 MovePtr<tcu::TestCaseGroup> smallGroup(new tcu::TestCaseGroup(group->getTestContext(), "small", ""));
1741 MovePtr<tcu::TestCaseGroup> hugeGroup (new tcu::TestCaseGroup(group->getTestContext(), "huge", ""));
1743 imageGroup->addChild(smallGroup.get());
1744 imageGroup->addChild(hugeGroup.get());
1746 for (vector<IVec4>::const_iterator sizeIter = sizes.begin(); sizeIter != sizes.end(); ++sizeIter)
1748 // The first size is the baseline size, put it in a dedicated group
1749 if (sizeIter == sizes.begin())
1751 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1752 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1754 const CaseDef caseDef =
1756 testCase[caseNdx].viewType, // VkImageViewType imageType;
1757 *sizeIter, // IVec4 imageSizeHint;
1758 format[formatNdx], // VkFormat colorFormat;
1759 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1760 allocationKind // AllocationKind allocationKind;
1762 addFunctionCaseWithPrograms(smallGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1765 else // All huge cases go into a separate group
1767 if (allocationKind != ALLOCATION_KIND_DEDICATED)
1769 MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(group->getTestContext(), getSizeDescription(*sizeIter).c_str(), ""));
1770 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1772 // Use the same color format for all cases, to reduce the number of permutations
1773 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1775 const CaseDef caseDef =
1777 testCase[caseNdx].viewType, // VkImageViewType viewType;
1778 *sizeIter, // IVec4 imageSizeHint;
1779 colorFormat, // VkFormat colorFormat;
1780 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1781 allocationKind // AllocationKind allocationKind;
1783 addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(colorFormat, depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1785 hugeGroup->addChild(sizeGroup.release());
1789 smallGroup.release();
1790 hugeGroup.release();
1793 // Generate mip map cases
1795 MovePtr<tcu::TestCaseGroup> mipmapGroup(new tcu::TestCaseGroup(group->getTestContext(), "mipmap", ""));
1797 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1798 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1800 const CaseDef caseDef =
1802 testCase[caseNdx].viewType, // VkImageViewType imageType;
1803 testCase[caseNdx].baselineSize, // IVec4 imageSizeHint;
1804 format[formatNdx], // VkFormat colorFormat;
1805 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1806 allocationKind // AllocationKind allocationKind;
1808 addFunctionCaseWithPrograms(mipmapGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testRenderToMipMaps, caseDef);
1810 imageGroup->addChild(mipmapGroup.release());
1813 group->addChild(imageGroup.release());
1817 void addCoreRenderToImageTests (tcu::TestCaseGroup* group)
1819 addTestCasesWithFunctions(group, ALLOCATION_KIND_SUBALLOCATED);
1822 void addDedicatedAllocationRenderToImageTests (tcu::TestCaseGroup* group)
1824 addTestCasesWithFunctions(group, ALLOCATION_KIND_DEDICATED);
1829 tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx)
1831 de::MovePtr<tcu::TestCaseGroup> renderToImageTests (new tcu::TestCaseGroup(testCtx, "render_to_image", "Render to image tests"));
1833 renderToImageTests->addChild(createTestGroup(testCtx, "core", "Core render to image tests", addCoreRenderToImageTests));
1834 renderToImageTests->addChild(createTestGroup(testCtx, "dedicated_allocation", "Render to image tests for dedicated memory allocation", addDedicatedAllocationRenderToImageTests));
1836 return renderToImageTests.release();