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),
87 static const float REFERENCE_DEPTH_VALUE = 1.0f;
88 static const Vec4 COLOR_TABLE[] =
90 Vec4(0.9f, 0.0f, 0.0f, 1.0f),
91 Vec4(0.6f, 1.0f, 0.0f, 1.0f),
92 Vec4(0.3f, 0.0f, 1.0f, 1.0f),
93 Vec4(0.1f, 1.0f, 1.0f, 1.0f),
94 Vec4(0.8f, 1.0f, 0.0f, 1.0f),
95 Vec4(0.5f, 0.0f, 1.0f, 1.0f),
96 Vec4(0.2f, 0.0f, 0.0f, 1.0f),
97 Vec4(1.0f, 1.0f, 0.0f, 1.0f),
102 VkImageViewType viewType;
103 IVec4 imageSizeHint; //!< (w, h, d, layers), a component may have a symbolic value MAX_SIZE
104 VkFormat colorFormat;
105 VkFormat depthStencilFormat; //! A depth/stencil format, or UNDEFINED if not used
109 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
111 return SharedPtr<Unique<T> >(new Unique<T>(move));
115 inline VkDeviceSize sizeInBytes (const vector<T>& vec)
117 return vec.size() * sizeof(vec[0]);
120 inline bool isCube (const VkImageViewType viewType)
122 return (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
125 inline VkDeviceSize product (const IVec4& v)
127 return ((static_cast<VkDeviceSize>(v.x()) * v.y()) * v.z()) * v.w();
131 inline T sum (const vector<T>& v)
133 T total = static_cast<T>(0);
134 for (typename vector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
139 template <typename T, int Size>
140 int findIndexOfMaxComponent (const tcu::Vector<T, Size>& vec)
145 for (int i = 1; i < Size; ++i)
157 inline int maxLayersOrDepth (const IVec4& size)
159 // This is safe because 3D images must have layers (w) = 1
160 return deMax32(size.z(), size.w());
163 // This is very test specific, so be careful if you want to reuse this code.
164 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
165 const VkDevice device,
166 const VkPipeline basePipeline, // for derivatives
167 const VkPipelineLayout pipelineLayout,
168 const VkRenderPass renderPass,
169 const VkShaderModule vertexModule,
170 const VkShaderModule fragmentModule,
171 const IVec2& renderSize,
172 const VkPrimitiveTopology topology,
173 const deUint32 subpass,
175 const bool useStencil)
177 const VkVertexInputBindingDescription vertexInputBindingDescription =
179 0u, // uint32_t binding;
180 sizeof(Vertex4RGBA), // uint32_t stride;
181 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
184 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
187 0u, // uint32_t location;
188 0u, // uint32_t binding;
189 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
190 0u, // uint32_t offset;
193 1u, // uint32_t location;
194 0u, // uint32_t binding;
195 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
196 sizeof(Vec4), // uint32_t offset;
200 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
202 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
203 DE_NULL, // const void* pNext;
204 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
205 1u, // uint32_t vertexBindingDescriptionCount;
206 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
207 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
208 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
211 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
213 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
214 DE_NULL, // const void* pNext;
215 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
216 topology, // VkPrimitiveTopology topology;
217 VK_FALSE, // VkBool32 primitiveRestartEnable;
220 const VkViewport viewport = makeViewport(
222 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
225 const VkRect2D scissor =
228 makeExtent2D(renderSize.x(), renderSize.y()),
231 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
233 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
234 DE_NULL, // const void* pNext;
235 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
236 1u, // uint32_t viewportCount;
237 &viewport, // const VkViewport* pViewports;
238 1u, // uint32_t scissorCount;
239 &scissor, // const VkRect2D* pScissors;
242 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
244 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
245 DE_NULL, // const void* pNext;
246 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
247 VK_FALSE, // VkBool32 depthClampEnable;
248 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
249 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
250 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
251 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
252 VK_FALSE, // VkBool32 depthBiasEnable;
253 0.0f, // float depthBiasConstantFactor;
254 0.0f, // float depthBiasClamp;
255 0.0f, // float depthBiasSlopeFactor;
256 1.0f, // float lineWidth;
259 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
261 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
262 DE_NULL, // const void* pNext;
263 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
264 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
265 VK_FALSE, // VkBool32 sampleShadingEnable;
266 0.0f, // float minSampleShading;
267 DE_NULL, // const VkSampleMask* pSampleMask;
268 VK_FALSE, // VkBool32 alphaToCoverageEnable;
269 VK_FALSE // VkBool32 alphaToOneEnable;
272 const VkStencilOpState stencilOpState = makeStencilOpState(
273 VK_STENCIL_OP_KEEP, // stencil fail
274 VK_STENCIL_OP_ZERO, // depth & stencil pass
275 VK_STENCIL_OP_KEEP, // depth only fail
276 VK_COMPARE_OP_EQUAL, // compare op
279 static_cast<deUint32>(REFERENCE_STENCIL_VALUE)); // reference
281 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
283 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
284 DE_NULL, // const void* pNext;
285 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
286 useDepth, // VkBool32 depthTestEnable;
287 VK_FALSE, // VkBool32 depthWriteEnable;
288 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
289 VK_FALSE, // VkBool32 depthBoundsTestEnable;
290 useStencil, // VkBool32 stencilTestEnable;
291 stencilOpState, // VkStencilOpState front;
292 stencilOpState, // VkStencilOpState back;
293 0.0f, // float minDepthBounds;
294 1.0f, // float maxDepthBounds;
297 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
298 // Number of blend attachments must equal the number of color attachments during any subpass.
299 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
301 VK_FALSE, // VkBool32 blendEnable;
302 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
303 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
304 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
305 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
306 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
307 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
308 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
311 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
313 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
314 DE_NULL, // const void* pNext;
315 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
316 VK_FALSE, // VkBool32 logicOpEnable;
317 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
318 1u, // deUint32 attachmentCount;
319 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
320 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
323 const VkPipelineShaderStageCreateInfo pShaderStages[] =
326 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
327 DE_NULL, // const void* pNext;
328 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
329 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
330 vertexModule, // VkShaderModule module;
331 "main", // const char* pName;
332 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
335 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
336 DE_NULL, // const void* pNext;
337 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
338 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
339 fragmentModule, // VkShaderModule module;
340 "main", // const char* pName;
341 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
345 const VkPipelineCreateFlags flags = (basePipeline == DE_NULL ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
346 : VK_PIPELINE_CREATE_DERIVATIVE_BIT);
348 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
350 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
351 DE_NULL, // const void* pNext;
352 flags, // VkPipelineCreateFlags flags;
353 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
354 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
355 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
356 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
357 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
358 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
359 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
360 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
361 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
362 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
363 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
364 pipelineLayout, // VkPipelineLayout layout;
365 renderPass, // VkRenderPass renderPass;
366 subpass, // deUint32 subpass;
367 basePipeline, // VkPipeline basePipelineHandle;
368 -1, // deInt32 basePipelineIndex;
371 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
374 //! Make a render pass with one subpass per color attachment and depth/stencil attachment (if used).
375 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
376 const VkDevice device,
377 const VkFormat colorFormat,
378 const VkFormat depthStencilFormat,
379 const deUint32 numLayers,
380 const VkImageLayout initialColorImageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
381 const VkImageLayout initialDepthStencilImageLayout = VK_IMAGE_LAYOUT_UNDEFINED)
383 const VkAttachmentDescription colorAttachmentDescription =
385 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
386 colorFormat, // VkFormat format;
387 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
388 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
389 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
390 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
391 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
392 initialColorImageLayout, // VkImageLayout initialLayout;
393 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
395 vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
397 const VkAttachmentDescription depthStencilAttachmentDescription =
399 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
400 depthStencilFormat, // VkFormat format;
401 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
402 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
403 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
404 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
405 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
406 initialDepthStencilImageLayout, // VkImageLayout initialLayout;
407 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
410 if (depthStencilFormat != VK_FORMAT_UNDEFINED)
411 attachmentDescriptions.insert(attachmentDescriptions.end(), numLayers, depthStencilAttachmentDescription);
413 // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
414 vector<VkAttachmentReference> colorAttachmentReferences (numLayers);
415 vector<VkAttachmentReference> depthStencilAttachmentReferences(numLayers);
416 vector<VkSubpassDescription> subpasses;
418 // Ordering here must match the framebuffer attachments
419 for (deUint32 i = 0; i < numLayers; ++i)
421 const VkAttachmentReference attachmentRef =
423 i, // deUint32 attachment;
424 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
426 const VkAttachmentReference depthStencilAttachmentRef =
428 i + numLayers, // deUint32 attachment;
429 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout;
432 colorAttachmentReferences[i] = attachmentRef;
433 depthStencilAttachmentReferences[i] = depthStencilAttachmentRef;
435 const VkAttachmentReference* pDepthStencilAttachment = (depthStencilFormat != VK_FORMAT_UNDEFINED ? &depthStencilAttachmentReferences[i] : DE_NULL);
436 const VkSubpassDescription subpassDescription =
438 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
439 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
440 0u, // deUint32 inputAttachmentCount;
441 DE_NULL, // const VkAttachmentReference* pInputAttachments;
442 1u, // deUint32 colorAttachmentCount;
443 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
444 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
445 pDepthStencilAttachment, // const VkAttachmentReference* pDepthStencilAttachment;
446 0u, // deUint32 preserveAttachmentCount;
447 DE_NULL // const deUint32* pPreserveAttachments;
449 subpasses.push_back(subpassDescription);
452 const VkRenderPassCreateInfo renderPassInfo =
454 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
455 DE_NULL, // const void* pNext;
456 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
457 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
458 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
459 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
460 &subpasses[0], // const VkSubpassDescription* pSubpasses;
461 0u, // deUint32 dependencyCount;
462 DE_NULL // const VkSubpassDependency* pDependencies;
465 return createRenderPass(vk, device, &renderPassInfo);
468 Move<VkImage> makeImage (const DeviceInterface& vk,
469 const VkDevice device,
470 VkImageCreateFlags flags,
471 VkImageType imageType,
472 const VkFormat format,
474 const deUint32 numMipLevels,
475 const deUint32 numLayers,
476 const VkImageUsageFlags usage)
478 const VkImageCreateInfo imageParams =
480 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
481 DE_NULL, // const void* pNext;
482 flags, // VkImageCreateFlags flags;
483 imageType, // VkImageType imageType;
484 format, // VkFormat format;
485 makeExtent3D(size), // VkExtent3D extent;
486 numMipLevels, // deUint32 mipLevels;
487 numLayers, // deUint32 arrayLayers;
488 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
489 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
490 usage, // VkImageUsageFlags usage;
491 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
492 0u, // deUint32 queueFamilyIndexCount;
493 DE_NULL, // const deUint32* pQueueFamilyIndices;
494 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
496 return createImage(vk, device, &imageParams);
499 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
501 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
502 return createBuffer(vk, device, &bufferCreateInfo);
505 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
507 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
510 //! Get a reference clear value based on color format.
511 VkClearValue getClearValue (const VkFormat format)
513 if (isUintFormat(format) || isIntFormat(format))
514 return makeClearValueColorU32(REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE, REFERENCE_COLOR_VALUE);
516 return makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
519 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
521 std::ostringstream str;
522 if (numComponents == 1)
523 str << (isUint ? "uint" : isSint ? "int" : "float");
525 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
530 //! A half-viewport quad. Use with TRIANGLE_STRIP topology.
531 vector<Vertex4RGBA> genFullQuadVertices (const int subpassCount)
533 vector<Vertex4RGBA> vectorData;
534 for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
538 Vec4(0.0f, -1.0f, 0.0f, 1.0f),
539 COLOR_TABLE[subpassNdx % DE_LENGTH_OF_ARRAY(COLOR_TABLE)],
541 vectorData.push_back(data);
542 data.position = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
543 vectorData.push_back(data);
544 data.position = Vec4(1.0f, -1.0f, 0.0f, 1.0f);
545 vectorData.push_back(data);
546 data.position = Vec4(1.0f, 1.0f, 0.0f, 1.0f);
547 vectorData.push_back(data);
552 VkImageType getImageType (const VkImageViewType viewType)
556 case VK_IMAGE_VIEW_TYPE_1D:
557 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
558 return VK_IMAGE_TYPE_1D;
560 case VK_IMAGE_VIEW_TYPE_2D:
561 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
562 case VK_IMAGE_VIEW_TYPE_CUBE:
563 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
564 return VK_IMAGE_TYPE_2D;
566 case VK_IMAGE_VIEW_TYPE_3D:
567 return VK_IMAGE_TYPE_3D;
571 return VK_IMAGE_TYPE_LAST;
575 //! ImageViewType for accessing a single layer/slice of an image
576 VkImageViewType getImageViewSliceType (const VkImageViewType viewType)
580 case VK_IMAGE_VIEW_TYPE_1D:
581 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
582 return VK_IMAGE_VIEW_TYPE_1D;
584 case VK_IMAGE_VIEW_TYPE_2D:
585 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
586 case VK_IMAGE_VIEW_TYPE_CUBE:
587 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
588 case VK_IMAGE_VIEW_TYPE_3D:
589 return VK_IMAGE_VIEW_TYPE_2D;
593 return VK_IMAGE_VIEW_TYPE_LAST;
597 VkImageCreateFlags getImageCreateFlags (const VkImageViewType viewType)
599 VkImageCreateFlags flags = (VkImageCreateFlags)0;
601 if (viewType == VK_IMAGE_VIEW_TYPE_3D) flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
602 if (isCube(viewType)) flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
607 void generateExpectedImage (const tcu::PixelBufferAccess& outputImage, const IVec2& renderSize, const int colorDepthOffset)
609 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(outputImage.getFormat().type);
610 const bool isInt = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
611 const VkClearValue clearValue = getClearValue(mapTextureFormat(outputImage.getFormat()));
614 tcu::clear(outputImage, IVec4(clearValue.color.int32));
616 tcu::clear(outputImage, Vec4(clearValue.color.float32));
618 for (int z = 0; z < outputImage.getDepth(); ++z)
620 const Vec4& setColor = COLOR_TABLE[(z + colorDepthOffset) % DE_LENGTH_OF_ARRAY(COLOR_TABLE)];
621 const IVec4 setColorInt = (static_cast<float>(REFERENCE_COLOR_VALUE) * setColor).cast<deInt32>();
623 for (int y = 0; y < renderSize.y(); ++y)
624 for (int x = renderSize.x()/2; x < renderSize.x(); ++x)
627 outputImage.setPixel(setColorInt, x, y, z);
629 outputImage.setPixel(setColor, x, y, z);
634 VkDeviceSize getMaxDeviceHeapSize (const InstanceInterface& vki, const VkPhysicalDevice physDevice)
636 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physDevice);
637 VkDeviceSize memorySize = 0;
639 for (deUint32 heapNdx = 0; heapNdx < memoryProperties.memoryHeapCount; ++heapNdx)
641 if ((memoryProperties.memoryHeaps[heapNdx].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
642 memorySize = std::max(memorySize, memoryProperties.memoryHeaps[heapNdx].size);
648 //! Get a smaller image size. Returns a vector of zeroes, if it can't reduce more.
649 IVec4 getReducedImageSize (const CaseDef& caseDef, IVec4 size)
651 const int maxIndex = findIndexOfMaxComponent(size);
652 const int reducedSize = size[maxIndex] >> 1;
654 switch (caseDef.viewType)
656 case VK_IMAGE_VIEW_TYPE_CUBE:
657 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
659 size.x() = size.y() = reducedSize;
660 else if (maxIndex == 3 && reducedSize >= NUM_CUBE_FACES)
661 size.w() = NUM_CUBE_FACES * (reducedSize / NUM_CUBE_FACES); // round down to a multiple of 6
667 size[maxIndex] = reducedSize;
671 if (reducedSize == 0)
677 bool isDepthStencilFormatSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format)
679 const VkFormatProperties properties = getPhysicalDeviceFormatProperties(vki, physDevice, format);
680 return (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
683 IVec4 getMaxImageSize (const VkPhysicalDeviceLimits& limits, const VkImageViewType viewType, const IVec4& sizeHint, const bool useDepthStencil)
685 // If we use a layered D/S together with a 3D image, we have to use the smallest common limit
686 const int maxDepth = (useDepthStencil ? deMin32(static_cast<int>(limits.maxImageArrayLayers), static_cast<int>(limits.maxImageDimension3D))
687 : static_cast<int>(limits.maxImageDimension3D));
689 // Images have to respect framebuffer limits and image limits (the framebuffer is not layered in this case)
691 sizeHint.x() != MAX_SIZE ? sizeHint.x() : static_cast<int>(limits.maxFramebufferWidth),
692 sizeHint.y() != MAX_SIZE ? sizeHint.y() : static_cast<int>(limits.maxFramebufferHeight),
693 sizeHint.z() != MAX_SIZE ? sizeHint.z() : maxDepth,
694 sizeHint.w() != MAX_SIZE ? sizeHint.w() : static_cast<int>(limits.maxImageArrayLayers));
698 case VK_IMAGE_VIEW_TYPE_1D:
699 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
700 size.x() = deMin32(size.x(), limits.maxImageDimension1D);
703 case VK_IMAGE_VIEW_TYPE_2D:
704 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
705 size.x() = deMin32(size.x(), limits.maxImageDimension2D);
706 size.y() = deMin32(size.y(), limits.maxImageDimension2D);
709 case VK_IMAGE_VIEW_TYPE_3D:
710 size.x() = deMin32(size.x(), limits.maxImageDimension3D);
711 size.y() = deMin32(size.y(), limits.maxImageDimension3D);
714 case VK_IMAGE_VIEW_TYPE_CUBE:
715 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
716 size.x() = size.y() = deMin32(size.x(), limits.maxImageDimensionCube);
717 size.w() = NUM_CUBE_FACES * (size.w() / NUM_CUBE_FACES); // round down to 6 faces
728 VkImageAspectFlags getFormatAspectFlags (const VkFormat format)
730 if (format == VK_FORMAT_UNDEFINED)
733 const tcu::TextureFormat::ChannelOrder order = mapVkFormat(format).order;
737 case tcu::TextureFormat::DS: return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
738 case tcu::TextureFormat::D: return VK_IMAGE_ASPECT_DEPTH_BIT;
739 case tcu::TextureFormat::S: return VK_IMAGE_ASPECT_STENCIL_BIT;
740 default: return VK_IMAGE_ASPECT_COLOR_BIT;
744 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
746 const int numComponents = getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
747 const bool isUint = isUintFormat(caseDef.colorFormat);
748 const bool isSint = isIntFormat(caseDef.colorFormat);
752 std::ostringstream src;
753 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
755 << "layout(location = 0) in vec4 in_position;\n"
756 << "layout(location = 1) in vec4 in_color;\n"
757 << "layout(location = 0) out vec4 out_color;\n"
759 << "out gl_PerVertex {\n"
760 << " vec4 gl_Position;\n"
763 << "void main(void)\n"
765 << " gl_Position = in_position;\n"
766 << " out_color = in_color;\n"
769 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
774 std::ostringstream colorValue;
775 colorValue << REFERENCE_COLOR_VALUE;
776 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
777 const std::string colorInteger = (isUint || isSint ? " * "+colorFormat+"("+colorValue.str()+")" :"");
779 std::ostringstream src;
780 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
782 << "layout(location = 0) in vec4 in_color;\n"
783 << "layout(location = 0) out " << colorFormat << " o_color;\n"
785 << "void main(void)\n"
787 << " o_color = " << colorFormat << "("
788 << (numComponents == 1 ? "in_color.r" :
789 numComponents == 2 ? "in_color.rg" :
790 numComponents == 3 ? "in_color.rgb" : "in_color")
795 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
799 //! See testAttachmentSize() description
800 tcu::TestStatus testWithSizeReduction (Context& context, const CaseDef& caseDef, const int sizeReductionIndex)
802 const DeviceInterface& vk = context.getDeviceInterface();
803 const InstanceInterface& vki = context.getInstanceInterface();
804 const VkDevice device = context.getDevice();
805 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
806 const VkQueue queue = context.getUniversalQueue();
807 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
808 Allocator& allocator = context.getDefaultAllocator();
810 // The memory might be too small to allocate a largest possible attachment, so try to account for that.
811 const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
812 const VkDeviceSize deviceMemoryBudget = getMaxDeviceHeapSize(vki, physDevice) >> 2;
813 IVec4 imageSize = getMaxImageSize(context.getDeviceProperties().limits, caseDef.viewType, caseDef.imageSizeHint, useDepthStencil);
815 // Keep reducing the size, if needed
816 for (int i = 0; i < sizeReductionIndex; ++i)
818 imageSize = getReducedImageSize(caseDef, imageSize);
820 if (imageSize == IVec4())
821 return tcu::TestStatus::fail("Couldn't create an image with required size");
824 context.getTestContext().getLog()
825 << tcu::TestLog::Message << "Using an image with size (width, height, depth, layers) = " << imageSize << tcu::TestLog::EndMessage;
827 // "Slices" is either the depth of a 3D image, or the number of layers of an arrayed image
828 const deInt32 numSlices = maxLayersOrDepth(imageSize);
829 const VkDeviceSize colorSize = product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
830 const VkDeviceSize depthStencilSize = (useDepthStencil ? product(imageSize) * tcu::getPixelSize(mapVkFormat(caseDef.depthStencilFormat)) : 0ull);
832 if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat))
833 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
835 if (colorSize + depthStencilSize > deviceMemoryBudget)
836 throw OutOfMemoryError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Image size exceeds test's image memory budget");
838 // Determine the verification bounds. The checked region will be in the center of the rendered image
839 const IVec4 checkSize = tcu::min(imageSize, IVec4(MAX_VERIFICATION_REGION_SIZE,
840 MAX_VERIFICATION_REGION_SIZE,
841 MAX_VERIFICATION_REGION_DEPTH,
842 MAX_VERIFICATION_REGION_DEPTH));
843 const IVec4 checkOffset = (imageSize - checkSize) / 2;
845 // Only make enough space for the check region
846 const VkDeviceSize colorBufferSize = product(checkSize) * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
847 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
848 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
851 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
852 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
855 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
856 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
857 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices)));
858 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
859 vector<SharedPtrVkPipeline> pipelines;
861 Move<VkImage> colorImage;
862 MovePtr<Allocation> colorImageAlloc;
863 vector<SharedPtrVkImageView> colorAttachments;
864 Move<VkImage> depthStencilImage;
865 MovePtr<Allocation> depthStencilImageAlloc;
866 vector<SharedPtrVkImageView> depthStencilAttachments;
867 vector<VkImageView> attachmentHandles; // all attachments (color and d/s)
868 Move<VkBuffer> vertexBuffer;
869 MovePtr<Allocation> vertexBufferAlloc;
870 Move<VkFramebuffer> framebuffer;
872 // Create a color image
874 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
876 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
877 imageSize.swizzle(0, 1, 2), 1u, imageSize.w(), imageUsage);
878 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
881 // Create a depth/stencil image (always a 2D image, optionally layered)
884 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
886 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
887 IVec3(imageSize.x(), imageSize.y(), 1), 1u, numSlices, imageUsage);
888 depthStencilImageAlloc = bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any);
891 // Create a vertex buffer
893 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices);
894 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
896 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
897 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
898 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
899 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
902 // For each image layer or slice (3D), create an attachment and a pipeline
904 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat);
905 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
906 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
907 VkPipeline basePipeline = DE_NULL;
909 // Color attachments are first in the framebuffer
910 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
912 colorAttachments.push_back(makeSharedPtr(
913 makeImageView(vk, device, *colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat, makeColorSubresourceRange(subpassNdx, 1))));
914 attachmentHandles.push_back(**colorAttachments.back());
916 // We also have to create pipelines for each subpass
917 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
918 vk, device, basePipeline, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, imageSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
919 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
921 basePipeline = **pipelines.front();
924 // Then D/S attachments, if any
926 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
928 depthStencilAttachments.push_back(makeSharedPtr(
929 makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat, makeImageSubresourceRange(depthStencilAspect, 0u, 1u, subpassNdx, 1u))));
930 attachmentHandles.push_back(**depthStencilAttachments.back());
934 framebuffer = makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0], static_cast<deUint32>(imageSize.x()), static_cast<deUint32>(imageSize.y()));
937 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
938 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
940 beginCommandBuffer(vk, *cmdBuffer);
942 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat));
945 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
947 const VkRect2D renderArea =
950 makeExtent2D(imageSize.x(), imageSize.y()),
952 const VkRenderPassBeginInfo renderPassBeginInfo =
954 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
955 DE_NULL, // const void* pNext;
956 *renderPass, // VkRenderPass renderPass;
957 *framebuffer, // VkFramebuffer framebuffer;
958 renderArea, // VkRect2D renderArea;
959 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
960 &clearValues[0], // const VkClearValue* pClearValues;
962 const VkDeviceSize vertexBufferOffset = 0ull;
964 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
965 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
969 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
972 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
974 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
975 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
978 vk.cmdEndRenderPass(*cmdBuffer);
980 // Copy colorImage -> host visible colorBuffer
982 const VkImageMemoryBarrier imageBarriers[] =
985 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
986 DE_NULL, // const void* pNext;
987 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
988 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
989 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
990 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
991 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
992 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
993 *colorImage, // VkImage image;
994 makeColorSubresourceRange(0, imageSize.w()) // VkImageSubresourceRange subresourceRange;
998 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
999 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1001 // Copy the checked region rather than the whole image
1002 const VkImageSubresourceLayers subresource =
1004 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1005 0u, // uint32_t mipLevel;
1006 static_cast<deUint32>(checkOffset.w()), // uint32_t baseArrayLayer;
1007 static_cast<deUint32>(checkSize.w()), // uint32_t layerCount;
1010 const VkBufferImageCopy region =
1012 0ull, // VkDeviceSize bufferOffset;
1013 0u, // uint32_t bufferRowLength;
1014 0u, // uint32_t bufferImageHeight;
1015 subresource, // VkImageSubresourceLayers imageSubresource;
1016 makeOffset3D(checkOffset.x(), checkOffset.y(), checkOffset.z()), // VkOffset3D imageOffset;
1017 makeExtent3D(checkSize.swizzle(0, 1, 2)), // VkExtent3D imageExtent;
1020 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ®ion);
1022 const VkBufferMemoryBarrier bufferBarriers[] =
1025 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1026 DE_NULL, // const void* pNext;
1027 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1028 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1029 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1030 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1031 *colorBuffer, // VkBuffer buffer;
1032 0ull, // VkDeviceSize offset;
1033 VK_WHOLE_SIZE, // VkDeviceSize size;
1037 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1038 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1041 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1042 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1047 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1049 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat);
1050 const int checkDepth = maxLayersOrDepth(checkSize);
1051 const int depthOffset = maxLayersOrDepth(checkOffset);
1052 const tcu::ConstPixelBufferAccess resultImage (format, checkSize.x(), checkSize.y(), checkDepth, colorBufferAlloc->getHostPtr());
1053 tcu::TextureLevel textureLevel (format, checkSize.x(), checkSize.y(), checkDepth);
1054 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1057 generateExpectedImage(expectedImage, checkSize.swizzle(0, 1), depthOffset);
1059 if (isFloatFormat(caseDef.colorFormat))
1060 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1062 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1064 return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1068 void checkImageViewTypeRequirements (Context& context, const VkImageViewType viewType)
1070 if (viewType == VK_IMAGE_VIEW_TYPE_3D &&
1071 !de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1"))
1072 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
1074 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY && !context.getDeviceFeatures().imageCubeArray)
1075 TCU_THROW(NotSupportedError, "Missing feature: imageCubeArray");
1078 //! A test that can exercise very big color and depth/stencil attachment sizes.
1079 //! If the total memory consumed by images is too large, or if the implementation returns OUT_OF_MEMORY error somewhere,
1080 //! the test can be retried with a next increment of size reduction index, making the attachments smaller.
1081 tcu::TestStatus testAttachmentSize (Context& context, const CaseDef caseDef)
1083 checkImageViewTypeRequirements(context, caseDef.viewType);
1085 int sizeReductionIndex = 0;
1091 return testWithSizeReduction(context, caseDef, sizeReductionIndex);
1093 catch (OutOfMemoryError& ex)
1095 context.getTestContext().getLog()
1096 << tcu::TestLog::Message << "-- OutOfMemoryError: " << ex.getMessage() << tcu::TestLog::EndMessage;
1098 ++sizeReductionIndex;
1104 vector<IVec4> getMipLevelSizes (IVec4 baseSize)
1106 vector<IVec4> levels;
1107 levels.push_back(baseSize);
1109 while (baseSize.x() != 1 || baseSize.y() != 1 || baseSize.z() != 1)
1111 baseSize.x() = deMax32(baseSize.x() >> 1, 1);
1112 baseSize.y() = deMax32(baseSize.y() >> 1, 1);
1113 baseSize.z() = deMax32(baseSize.z() >> 1, 1);
1114 levels.push_back(baseSize);
1120 //! Compute memory consumed by each mip level, including all layers. Sizes include a padding for alignment.
1121 vector<VkDeviceSize> getPerMipLevelStorageSize (const vector<IVec4>& mipLevelSizes, const VkDeviceSize pixelSize)
1123 const deInt64 levelAlignment = 16;
1124 vector<VkDeviceSize> storageSizes;
1126 for (vector<IVec4>::const_iterator it = mipLevelSizes.begin(); it != mipLevelSizes.end(); ++it)
1127 storageSizes.push_back(deAlign64(pixelSize * product(*it), levelAlignment));
1129 return storageSizes;
1132 void drawToMipLevel (const Context& context,
1133 const CaseDef& caseDef,
1135 const IVec4& mipSize,
1136 const int numSlices,
1137 const VkImage colorImage,
1138 const VkImage depthStencilImage,
1139 const VkBuffer vertexBuffer,
1140 const VkPipelineLayout pipelineLayout,
1141 const VkShaderModule vertexModule,
1142 const VkShaderModule fragmentModule)
1144 const DeviceInterface& vk = context.getDeviceInterface();
1145 const VkDevice device = context.getDevice();
1146 const VkQueue queue = context.getUniversalQueue();
1147 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1148 const VkImageAspectFlags depthStencilAspect = getFormatAspectFlags(caseDef.depthStencilFormat);
1149 const bool useDepth = (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
1150 const bool useStencil = (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
1151 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, caseDef.colorFormat, caseDef.depthStencilFormat, static_cast<deUint32>(numSlices),
1152 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1153 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
1154 vector<SharedPtrVkPipeline> pipelines;
1155 vector<SharedPtrVkImageView> colorAttachments;
1156 vector<SharedPtrVkImageView> depthStencilAttachments;
1157 vector<VkImageView> attachmentHandles; // all attachments (color and d/s)
1159 // For each image layer or slice (3D), create an attachment and a pipeline
1161 VkPipeline basePipeline = DE_NULL;
1163 // Color attachments are first in the framebuffer
1164 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1166 colorAttachments.push_back(makeSharedPtr(makeImageView(
1167 vk, device, colorImage, getImageViewSliceType(caseDef.viewType), caseDef.colorFormat,
1168 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, subpassNdx, 1u))));
1169 attachmentHandles.push_back(**colorAttachments.back());
1171 // We also have to create pipelines for each subpass
1172 pipelines.push_back(makeSharedPtr(makeGraphicsPipeline(
1173 vk, device, basePipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, mipSize.swizzle(0, 1), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1174 static_cast<deUint32>(subpassNdx), useDepth, useStencil)));
1176 basePipeline = **pipelines.front();
1179 // Then D/S attachments, if any
1180 if (useDepth || useStencil)
1181 for (int subpassNdx = 0; subpassNdx < numSlices; ++subpassNdx)
1183 depthStencilAttachments.push_back(makeSharedPtr(makeImageView(
1184 vk, device, depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.depthStencilFormat,
1185 makeImageSubresourceRange(depthStencilAspect, mipLevel, 1u, subpassNdx, 1u))));
1186 attachmentHandles.push_back(**depthStencilAttachments.back());
1190 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, static_cast<deUint32>(attachmentHandles.size()), &attachmentHandles[0],
1191 static_cast<deUint32>(mipSize.x()), static_cast<deUint32>(mipSize.y())));
1194 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1195 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1197 beginCommandBuffer(vk, *cmdBuffer);
1199 vector<VkClearValue> clearValues (numSlices, getClearValue(caseDef.colorFormat));
1201 if (useDepth || useStencil)
1202 clearValues.insert(clearValues.end(), numSlices, makeClearValueDepthStencil(REFERENCE_DEPTH_VALUE, REFERENCE_STENCIL_VALUE));
1204 const VkRect2D renderArea =
1207 makeExtent2D(mipSize.x(), mipSize.y()),
1209 const VkRenderPassBeginInfo renderPassBeginInfo =
1211 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1212 DE_NULL, // const void* pNext;
1213 *renderPass, // VkRenderPass renderPass;
1214 *framebuffer, // VkFramebuffer framebuffer;
1215 renderArea, // VkRect2D renderArea;
1216 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
1217 &clearValues[0], // const VkClearValue* pClearValues;
1219 const VkDeviceSize vertexBufferOffset = 0ull;
1221 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1222 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
1226 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(numSlices); ++subpassNdx)
1228 if (subpassNdx != 0)
1229 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1231 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
1232 vk.cmdDraw(*cmdBuffer, 4u, 1u, subpassNdx*4u, 0u);
1235 vk.cmdEndRenderPass(*cmdBuffer);
1237 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1238 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1242 //! Use image mip levels as attachments
1243 tcu::TestStatus testRenderToMipMaps (Context& context, const CaseDef caseDef)
1245 checkImageViewTypeRequirements(context, caseDef.viewType);
1247 const DeviceInterface& vk = context.getDeviceInterface();
1248 const InstanceInterface& vki = context.getInstanceInterface();
1249 const VkDevice device = context.getDevice();
1250 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1251 const VkQueue queue = context.getUniversalQueue();
1252 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1253 Allocator& allocator = context.getDefaultAllocator();
1255 const IVec4 imageSize = caseDef.imageSizeHint; // MAX_SIZE is not used in this test
1256 const deInt32 numSlices = maxLayersOrDepth(imageSize);
1257 const vector<IVec4> mipLevelSizes = getMipLevelSizes(imageSize);
1258 const vector<VkDeviceSize> mipLevelStorageSizes = getPerMipLevelStorageSize(mipLevelSizes, tcu::getPixelSize(mapVkFormat(caseDef.colorFormat)));
1259 const int numMipLevels = static_cast<int>(mipLevelSizes.size());
1260 const bool useDepthStencil = (caseDef.depthStencilFormat != VK_FORMAT_UNDEFINED);
1262 if (useDepthStencil && !isDepthStencilFormatSupported(vki, physDevice, caseDef.depthStencilFormat))
1263 TCU_THROW(NotSupportedError, "Unsupported depth/stencil format");
1265 // Create a color buffer big enough to hold all layers and mip levels
1266 const VkDeviceSize colorBufferSize = sum(mipLevelStorageSizes);
1267 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1268 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1271 deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
1272 flushMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1275 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
1276 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
1277 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
1279 Move<VkImage> colorImage;
1280 MovePtr<Allocation> colorImageAlloc;
1281 Move<VkImage> depthStencilImage;
1282 MovePtr<Allocation> depthStencilImageAlloc;
1283 Move<VkBuffer> vertexBuffer;
1284 MovePtr<Allocation> vertexBufferAlloc;
1286 // Create a color image
1288 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1290 colorImage = makeImage(vk, device, getImageCreateFlags(caseDef.viewType), getImageType(caseDef.viewType), caseDef.colorFormat,
1291 imageSize.swizzle(0, 1, 2), numMipLevels, imageSize.w(), imageUsage);
1292 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1295 // Create a depth/stencil image (always a 2D image, optionally layered)
1296 if (useDepthStencil)
1298 const VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1300 depthStencilImage = makeImage(vk, device, (VkImageCreateFlags)0, VK_IMAGE_TYPE_2D, caseDef.depthStencilFormat,
1301 IVec3(imageSize.x(), imageSize.y(), 1), numMipLevels, numSlices, imageUsage);
1302 depthStencilImageAlloc = bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any);
1305 // Create a vertex buffer
1307 const vector<Vertex4RGBA> vertices = genFullQuadVertices(numSlices);
1308 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1310 vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1311 vertexBufferAlloc = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1312 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1313 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
1318 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1319 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1321 beginCommandBuffer(vk, *cmdBuffer);
1323 const VkImageMemoryBarrier imageBarriers[] =
1326 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1327 DE_NULL, // const void* pNext;
1328 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1329 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1330 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1331 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1332 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1333 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1334 *colorImage, // VkImage image;
1335 { // VkImageSubresourceRange subresourceRange;
1336 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1337 0u, // uint32_t baseMipLevel;
1338 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1339 0u, // uint32_t baseArrayLayer;
1340 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount;
1344 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1345 DE_NULL, // const void* pNext;
1346 (VkAccessFlags)0, // VkAccessFlags srcAccessMask;
1347 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1348 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1349 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1350 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1351 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1352 *depthStencilImage, // VkImage image;
1353 { // VkImageSubresourceRange subresourceRange;
1354 getFormatAspectFlags(caseDef.depthStencilFormat), // VkImageAspectFlags aspectMask;
1355 0u, // uint32_t baseMipLevel;
1356 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1357 0u, // uint32_t baseArrayLayer;
1358 static_cast<deUint32>(numSlices), // uint32_t layerCount;
1363 const deUint32 numImageBarriers = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(imageBarriers) - (useDepthStencil ? 0 : 1));
1365 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1366 0u, DE_NULL, 0u, DE_NULL, numImageBarriers, imageBarriers);
1368 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1369 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1373 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1375 const IVec4& mipSize = mipLevelSizes[mipLevel];
1376 const int levelSlices = maxLayersOrDepth(mipSize);
1378 drawToMipLevel (context, caseDef, mipLevel, mipSize, levelSlices, *colorImage, *depthStencilImage, *vertexBuffer, *pipelineLayout,
1379 *vertexModule, *fragmentModule);
1382 // Copy results: colorImage -> host visible colorBuffer
1384 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1385 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1387 beginCommandBuffer(vk, *cmdBuffer);
1390 const VkImageMemoryBarrier imageBarriers[] =
1393 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1394 DE_NULL, // const void* pNext;
1395 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
1396 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1397 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1398 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1399 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1400 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1401 *colorImage, // VkImage image;
1402 { // VkImageSubresourceRange subresourceRange;
1403 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1404 0u, // uint32_t baseMipLevel;
1405 static_cast<deUint32>(numMipLevels), // uint32_t levelCount;
1406 0u, // uint32_t baseArrayLayer;
1407 static_cast<deUint32>(imageSize.w()), // uint32_t layerCount;
1412 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1413 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(imageBarriers), imageBarriers);
1416 vector<VkBufferImageCopy> regions;
1417 VkDeviceSize levelOffset = 0ull;
1418 VkBufferImageCopy workRegion =
1420 0ull, // VkDeviceSize bufferOffset;
1421 0u, // uint32_t bufferRowLength;
1422 0u, // uint32_t bufferImageHeight;
1423 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageSize.w()), // VkImageSubresourceLayers imageSubresource;
1424 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1425 makeExtent3D(0, 0, 0), // VkExtent3D imageExtent;
1428 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1430 workRegion.bufferOffset = levelOffset;
1431 workRegion.imageSubresource.mipLevel = static_cast<deUint32>(mipLevel);
1432 workRegion.imageExtent = makeExtent3D(mipLevelSizes[mipLevel].swizzle(0, 1, 2));
1434 regions.push_back(workRegion);
1436 levelOffset += mipLevelStorageSizes[mipLevel];
1439 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, static_cast<deUint32>(regions.size()), ®ions[0]);
1442 const VkBufferMemoryBarrier bufferBarriers[] =
1445 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1446 DE_NULL, // const void* pNext;
1447 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1448 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1449 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1450 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1451 *colorBuffer, // VkBuffer buffer;
1452 0ull, // VkDeviceSize offset;
1453 VK_WHOLE_SIZE, // VkDeviceSize size;
1457 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1458 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1461 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1462 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1465 // Verify results (per mip level)
1467 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1469 const tcu::TextureFormat format = mapVkFormat(caseDef.colorFormat);
1471 VkDeviceSize levelOffset = 0ull;
1474 for (int mipLevel = 0; mipLevel < numMipLevels; ++mipLevel)
1476 const IVec4& mipSize = mipLevelSizes[mipLevel];
1477 const void* const pLevelData = static_cast<const deUint8*>(colorBufferAlloc->getHostPtr()) + levelOffset;
1478 const int levelDepth = maxLayersOrDepth(mipSize);
1479 const tcu::ConstPixelBufferAccess resultImage (format, mipSize.x(), mipSize.y(), levelDepth, pLevelData);
1480 tcu::TextureLevel textureLevel (format, mipSize.x(), mipSize.y(), levelDepth);
1481 const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
1482 const std::string comparisonName = "Mip level " + de::toString(mipLevel);
1485 generateExpectedImage(expectedImage, mipSize.swizzle(0, 1), 0);
1487 if (isFloatFormat(caseDef.colorFormat))
1488 ok = tcu::floatThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
1490 ok = tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", comparisonName.c_str(), expectedImage, resultImage, tcu::UVec4(2), tcu::COMPARE_LOG_RESULT);
1492 allOk = allOk && ok; // keep testing all levels, even if we know it's a fail overall
1493 levelOffset += mipLevelStorageSizes[mipLevel];
1496 return allOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
1500 std::string getSizeDescription (const IVec4& size)
1502 std::ostringstream str;
1504 const char* const description[4] =
1506 "width", "height", "depth", "layers"
1509 int numMaxComponents = 0;
1511 for (int i = 0; i < 4; ++i)
1513 if (size[i] == MAX_SIZE)
1515 if (numMaxComponents > 0)
1518 str << description[i];
1523 if (numMaxComponents == 0)
1529 inline std::string getFormatString (const VkFormat format)
1531 std::string name(getFormatName(format));
1532 return de::toLower(name.substr(10));
1535 std::string getFormatString (const VkFormat colorFormat, const VkFormat depthStencilFormat)
1537 std::ostringstream str;
1538 str << getFormatString(colorFormat);
1539 if (depthStencilFormat != VK_FORMAT_UNDEFINED)
1540 str << "_" << getFormatString(depthStencilFormat);
1544 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1546 std::string s(getImageViewTypeName(imageViewType));
1547 return de::toLower(s.substr(19));
1550 inline BVec4 bvecFromMask (deUint32 mask)
1552 return BVec4((mask >> 0) & 1,
1558 vector<IVec4> genSizeCombinations (const IVec4& baselineSize, const deUint32 sizeMask, const VkImageViewType imageViewType)
1560 vector<IVec4> sizes;
1561 std::set<deUint32> masks;
1563 for (deUint32 i = 0; i < (1u << 4); ++i)
1565 // Cube images have square faces
1566 if (isCube(imageViewType) && ((i & MASK_WH) != 0))
1569 masks.insert(i & sizeMask);
1572 for (std::set<deUint32>::const_iterator it = masks.begin(); it != masks.end(); ++it)
1573 sizes.push_back(tcu::select(IVec4(MAX_SIZE), baselineSize, bvecFromMask(*it)));
1578 void addTestCasesWithFunctions (tcu::TestCaseGroup* group)
1582 VkImageViewType viewType;
1583 IVec4 baselineSize; //!< image size: (dimX, dimY, dimZ, arraySize)
1584 deUint32 sizeMask; //!< if a dimension is masked, generate a huge size case for it
1587 { VK_IMAGE_VIEW_TYPE_1D, IVec4(54, 1, 1, 1), MASK_W },
1588 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, IVec4(54, 1, 1, 4), MASK_W_LAYERS },
1589 { VK_IMAGE_VIEW_TYPE_2D, IVec4(44, 23, 1, 1), MASK_WH },
1590 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, IVec4(44, 23, 1, 4), MASK_WH_LAYERS },
1591 { VK_IMAGE_VIEW_TYPE_3D, IVec4(22, 31, 7, 1), MASK_WHD },
1592 { VK_IMAGE_VIEW_TYPE_CUBE, IVec4(35, 35, 1, 6), MASK_WH },
1593 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, IVec4(35, 35, 1, 2*6), MASK_WH_LAYERS },
1596 const VkFormat format[] =
1598 VK_FORMAT_R8G8B8A8_UNORM,
1600 VK_FORMAT_R16G16_SINT,
1601 VK_FORMAT_R32G32B32A32_SFLOAT,
1604 const VkFormat depthStencilFormat[] =
1606 VK_FORMAT_UNDEFINED, // don't use a depth/stencil attachment
1607 VK_FORMAT_D16_UNORM,
1609 VK_FORMAT_D24_UNORM_S8_UINT, // one of the following mixed formats must be supported
1610 VK_FORMAT_D32_SFLOAT_S8_UINT,
1613 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCase); ++caseNdx)
1615 MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), getShortImageViewTypeName(testCase[caseNdx].viewType).c_str(), ""));
1617 // Generate attachment size cases
1619 const vector<IVec4> sizes = genSizeCombinations(testCase[caseNdx].baselineSize, testCase[caseNdx].sizeMask, testCase[caseNdx].viewType);
1621 MovePtr<tcu::TestCaseGroup> smallGroup(new tcu::TestCaseGroup(group->getTestContext(), "small", ""));
1622 MovePtr<tcu::TestCaseGroup> hugeGroup (new tcu::TestCaseGroup(group->getTestContext(), "huge", ""));
1624 imageGroup->addChild(smallGroup.get());
1625 imageGroup->addChild(hugeGroup.get());
1627 for (vector<IVec4>::const_iterator sizeIter = sizes.begin(); sizeIter != sizes.end(); ++sizeIter)
1629 // The first size is the baseline size, put it in a dedicated group
1630 if (sizeIter == sizes.begin())
1632 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1633 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1635 const CaseDef caseDef =
1637 testCase[caseNdx].viewType, // VkImageViewType imageType;
1638 *sizeIter, // IVec4 imageSizeHint;
1639 format[formatNdx], // VkFormat colorFormat;
1640 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1642 addFunctionCaseWithPrograms(smallGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1645 else // All huge cases go into a separate group
1647 MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(group->getTestContext(), getSizeDescription(*sizeIter).c_str(), ""));
1648 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1650 // Use the same color format for all cases, to reduce the number of permutations
1651 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1653 const CaseDef caseDef =
1655 testCase[caseNdx].viewType, // VkImageViewType viewType;
1656 *sizeIter, // IVec4 imageSizeHint;
1657 colorFormat, // VkFormat colorFormat;
1658 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1660 addFunctionCaseWithPrograms(sizeGroup.get(), getFormatString(colorFormat, depthStencilFormat[dsFormatNdx]), "", initPrograms, testAttachmentSize, caseDef);
1662 hugeGroup->addChild(sizeGroup.release());
1665 smallGroup.release();
1666 hugeGroup.release();
1669 // Generate mip map cases
1671 MovePtr<tcu::TestCaseGroup> mipmapGroup(new tcu::TestCaseGroup(group->getTestContext(), "mipmap", ""));
1673 for (int dsFormatNdx = 0; dsFormatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormat); ++dsFormatNdx)
1674 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1676 const CaseDef caseDef =
1678 testCase[caseNdx].viewType, // VkImageViewType imageType;
1679 testCase[caseNdx].baselineSize, // IVec4 imageSizeHint;
1680 format[formatNdx], // VkFormat colorFormat;
1681 depthStencilFormat[dsFormatNdx], // VkFormat depthStencilFormat;
1683 addFunctionCaseWithPrograms(mipmapGroup.get(), getFormatString(format[formatNdx], depthStencilFormat[dsFormatNdx]), "", initPrograms, testRenderToMipMaps, caseDef);
1685 imageGroup->addChild(mipmapGroup.release());
1688 group->addChild(imageGroup.release());
1694 tcu::TestCaseGroup* createRenderToImageTests (tcu::TestContext& testCtx)
1696 return createTestGroup(testCtx, "render_to_image", "Render to image tests", addTestCasesWithFunctions);