1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 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.
21 * \brief Multisample image Tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktPipelineMultisampleImageTests.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 "tcuTestLog.hpp"
42 #include "deUniquePtr.hpp"
43 #include "deSharedPtr.hpp"
60 typedef SharedPtr<Unique<VkImageView> > ImageViewSp;
61 typedef SharedPtr<Unique<VkPipeline> > PipelineSp;
63 //! Test case parameters
69 VkSampleCountFlagBits numSamples;
73 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
75 return SharedPtr<Unique<T> >(new Unique<T>(move));
79 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
81 return vec.size() * sizeof(vec[0]);
84 //! Create a vector of derived pipelines, each with an increasing subpass index
85 std::vector<PipelineSp> makeGraphicsPipelines (const DeviceInterface& vk,
86 const VkDevice device,
87 const deUint32 numSubpasses,
88 const VkPipelineLayout pipelineLayout,
89 const VkRenderPass renderPass,
90 const VkShaderModule vertexModule,
91 const VkShaderModule fragmentModule,
92 const IVec2 renderSize,
93 const VkSampleCountFlagBits numSamples,
94 const VkPrimitiveTopology topology)
96 const VkVertexInputBindingDescription vertexInputBindingDescription =
98 0u, // uint32_t binding;
99 sizeof(Vertex4RGBA), // uint32_t stride;
100 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
103 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
106 0u, // uint32_t location;
107 0u, // uint32_t binding;
108 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
109 0u, // uint32_t offset;
112 1u, // uint32_t location;
113 0u, // uint32_t binding;
114 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
115 sizeof(Vec4), // uint32_t offset;
119 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
121 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
122 DE_NULL, // const void* pNext;
123 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
124 1u, // uint32_t vertexBindingDescriptionCount;
125 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
126 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
127 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
130 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
132 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
133 DE_NULL, // const void* pNext;
134 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
135 topology, // VkPrimitiveTopology topology;
136 VK_FALSE, // VkBool32 primitiveRestartEnable;
139 const VkViewport viewport = makeViewport(
141 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
144 const VkRect2D scissor = {
146 makeExtent2D(renderSize.x(), renderSize.y()),
149 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
151 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
152 DE_NULL, // const void* pNext;
153 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
154 1u, // uint32_t viewportCount;
155 &viewport, // const VkViewport* pViewports;
156 1u, // uint32_t scissorCount;
157 &scissor, // const VkRect2D* pScissors;
160 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
162 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
163 DE_NULL, // const void* pNext;
164 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
165 VK_FALSE, // VkBool32 depthClampEnable;
166 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
167 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
168 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
169 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
170 VK_FALSE, // VkBool32 depthBiasEnable;
171 0.0f, // float depthBiasConstantFactor;
172 0.0f, // float depthBiasClamp;
173 0.0f, // float depthBiasSlopeFactor;
174 1.0f, // float lineWidth;
177 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
179 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
180 DE_NULL, // const void* pNext;
181 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
182 numSamples, // VkSampleCountFlagBits rasterizationSamples;
183 VK_FALSE, // VkBool32 sampleShadingEnable;
184 0.0f, // float minSampleShading;
185 DE_NULL, // const VkSampleMask* pSampleMask;
186 VK_FALSE, // VkBool32 alphaToCoverageEnable;
187 VK_FALSE // VkBool32 alphaToOneEnable;
190 const VkStencilOpState stencilOpState = makeStencilOpState(
191 VK_STENCIL_OP_KEEP, // stencil fail
192 VK_STENCIL_OP_KEEP, // depth & stencil pass
193 VK_STENCIL_OP_KEEP, // depth only fail
194 VK_COMPARE_OP_ALWAYS, // compare op
199 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
201 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
202 DE_NULL, // const void* pNext;
203 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
204 VK_FALSE, // VkBool32 depthTestEnable;
205 VK_FALSE, // VkBool32 depthWriteEnable;
206 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
207 VK_FALSE, // VkBool32 depthBoundsTestEnable;
208 VK_FALSE, // VkBool32 stencilTestEnable;
209 stencilOpState, // VkStencilOpState front;
210 stencilOpState, // VkStencilOpState back;
211 0.0f, // float minDepthBounds;
212 1.0f, // float maxDepthBounds;
215 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
216 // Number of blend attachments must equal the number of color attachments during any subpass.
217 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
219 VK_FALSE, // VkBool32 blendEnable;
220 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
221 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
222 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
223 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
224 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
225 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
226 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
229 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
231 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
232 DE_NULL, // const void* pNext;
233 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
234 VK_FALSE, // VkBool32 logicOpEnable;
235 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
236 1u, // deUint32 attachmentCount;
237 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
238 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
241 const VkPipelineShaderStageCreateInfo pShaderStages[] =
244 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
245 DE_NULL, // const void* pNext;
246 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
247 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
248 vertexModule, // VkShaderModule module;
249 "main", // const char* pName;
250 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
253 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
254 DE_NULL, // const void* pNext;
255 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
256 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
257 fragmentModule, // VkShaderModule module;
258 "main", // const char* pName;
259 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
263 DE_ASSERT(numSubpasses > 0u);
265 std::vector<VkGraphicsPipelineCreateInfo> graphicsPipelineInfos (0);
266 std::vector<VkPipeline> rawPipelines (numSubpasses, DE_NULL);
269 const VkPipelineCreateFlags firstPipelineFlags = (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
270 : (VkPipelineCreateFlagBits)0);
272 VkGraphicsPipelineCreateInfo createInfo =
274 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
275 DE_NULL, // const void* pNext;
276 firstPipelineFlags, // VkPipelineCreateFlags flags;
277 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
278 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
279 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
280 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
281 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
282 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
283 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
284 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
285 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
286 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
287 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
288 pipelineLayout, // VkPipelineLayout layout;
289 renderPass, // VkRenderPass renderPass;
290 0u, // deUint32 subpass;
291 DE_NULL, // VkPipeline basePipelineHandle;
292 -1, // deInt32 basePipelineIndex;
295 graphicsPipelineInfos.push_back(createInfo);
297 createInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
298 createInfo.basePipelineIndex = 0;
300 for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx)
302 createInfo.subpass = subpassNdx;
303 graphicsPipelineInfos.push_back(createInfo);
307 VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0]));
309 std::vector<PipelineSp> pipelines;
311 for (std::vector<VkPipeline>::const_iterator it = rawPipelines.begin(); it != rawPipelines.end(); ++it)
312 pipelines.push_back(makeSharedPtr(Move<VkPipeline>(check<VkPipeline>(*it), Deleter<VkPipeline>(vk, device, DE_NULL))));
317 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
318 Move<VkRenderPass> makeMultisampleRenderPass (const DeviceInterface& vk,
319 const VkDevice device,
320 const VkFormat colorFormat,
321 const VkSampleCountFlagBits numSamples,
322 const deUint32 numLayers)
324 const VkAttachmentDescription colorAttachmentDescription =
326 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
327 colorFormat, // VkFormat format;
328 numSamples, // VkSampleCountFlagBits samples;
329 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
330 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
331 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
332 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
333 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
334 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
336 const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
338 // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
340 std::vector<VkAttachmentReference> colorAttachmentReferences(numLayers);
341 std::vector<VkSubpassDescription> subpasses;
343 for (deUint32 i = 0; i < numLayers; ++i)
345 const VkAttachmentReference attachmentRef =
347 i, // deUint32 attachment;
348 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
350 colorAttachmentReferences[i] = attachmentRef;
352 const VkSubpassDescription subpassDescription =
354 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
355 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
356 0u, // deUint32 inputAttachmentCount;
357 DE_NULL, // const VkAttachmentReference* pInputAttachments;
358 1u, // deUint32 colorAttachmentCount;
359 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
360 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
361 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
362 0u, // deUint32 preserveAttachmentCount;
363 DE_NULL // const deUint32* pPreserveAttachments;
365 subpasses.push_back(subpassDescription);
368 const VkRenderPassCreateInfo renderPassInfo =
370 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
371 DE_NULL, // const void* pNext;
372 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
373 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
374 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
375 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
376 &subpasses[0], // const VkSubpassDescription* pSubpasses;
377 0u, // deUint32 dependencyCount;
378 DE_NULL // const VkSubpassDependency* pDependencies;
381 return createRenderPass(vk, device, &renderPassInfo);
384 //! A single-attachment, single-subpass render pass.
385 Move<VkRenderPass> makeSimpleRenderPass (const DeviceInterface& vk,
386 const VkDevice device,
387 const VkFormat colorFormat)
389 const VkAttachmentDescription colorAttachmentDescription =
391 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
392 colorFormat, // VkFormat format;
393 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
394 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
395 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
396 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
397 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
398 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
399 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
402 const VkAttachmentReference colorAttachmentRef =
404 0u, // deUint32 attachment;
405 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
408 const VkSubpassDescription subpassDescription =
410 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
411 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
412 0u, // deUint32 inputAttachmentCount;
413 DE_NULL, // const VkAttachmentReference* pInputAttachments;
414 1u, // deUint32 colorAttachmentCount;
415 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
416 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
417 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
418 0u, // deUint32 preserveAttachmentCount;
419 DE_NULL // const deUint32* pPreserveAttachments;
422 const VkRenderPassCreateInfo renderPassInfo =
424 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
425 DE_NULL, // const void* pNext;
426 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
427 1u, // deUint32 attachmentCount;
428 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
429 1u, // deUint32 subpassCount;
430 &subpassDescription, // const VkSubpassDescription* pSubpasses;
431 0u, // deUint32 dependencyCount;
432 DE_NULL // const VkSubpassDependency* pDependencies;
435 return createRenderPass(vk, device, &renderPassInfo);
438 Move<VkImage> makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
440 const VkImageCreateInfo imageParams =
442 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
443 DE_NULL, // const void* pNext;
444 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
445 VK_IMAGE_TYPE_2D, // VkImageType imageType;
446 format, // VkFormat format;
447 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
448 1u, // deUint32 mipLevels;
449 numLayers, // deUint32 arrayLayers;
450 samples, // VkSampleCountFlagBits samples;
451 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
452 usage, // VkImageUsageFlags usage;
453 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
454 0u, // deUint32 queueFamilyIndexCount;
455 DE_NULL, // const deUint32* pQueueFamilyIndices;
456 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
458 return createImage(vk, device, &imageParams);
461 //! Make a simplest sampler.
462 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
464 const VkSamplerCreateInfo samplerParams =
466 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
467 DE_NULL, // const void* pNext;
468 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags;
469 VK_FILTER_NEAREST, // VkFilter magFilter;
470 VK_FILTER_NEAREST, // VkFilter minFilter;
471 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
472 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
473 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
474 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
475 0.0f, // float mipLodBias;
476 VK_FALSE, // VkBool32 anisotropyEnable;
477 1.0f, // float maxAnisotropy;
478 VK_FALSE, // VkBool32 compareEnable;
479 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
480 0.0f, // float minLod;
481 0.0f, // float maxLod;
482 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
483 VK_FALSE, // VkBool32 unnormalizedCoordinates;
485 return createSampler(vk, device, &samplerParams);
488 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
490 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
491 return createBuffer(vk, device, &bufferCreateInfo);
494 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
496 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
499 inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount)
501 return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
504 void checkImageFormatRequirements (const InstanceInterface& vki,
505 const VkPhysicalDevice physDevice,
506 const VkSampleCountFlagBits sampleCount,
507 const VkFormat format,
508 const VkImageUsageFlags usage)
510 VkPhysicalDeviceFeatures features;
511 vki.getPhysicalDeviceFeatures(physDevice, &features);
513 if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample)
514 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
516 VkImageFormatProperties imageFormatProperties;
517 const VkResult imageFormatResult = vki.getPhysicalDeviceImageFormatProperties(
518 physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties);
520 if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
521 TCU_THROW(NotSupportedError, "Image format is not supported");
523 if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount)
524 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
527 void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize bufferSize)
529 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(bufferSize));
530 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
533 //! The default foreground color.
534 inline Vec4 getPrimitiveColor (void)
536 return Vec4(1.0f, 0.0f, 0.0f, 1.0f);
539 //! Get a reference clear value based on color format.
540 VkClearValue getClearValue (const VkFormat format)
542 if (isUintFormat(format) || isIntFormat(format))
543 return makeClearValueColorU32(16, 32, 64, 96);
545 return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f);
548 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
550 std::ostringstream str;
551 if (numComponents == 1)
552 str << (isUint ? "uint" : isSint ? "int" : "float");
554 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
559 std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint)
561 std::ostringstream str;
562 str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : "");
566 //! Generate a gvec4 color literal.
568 std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint)
570 const int maxIndex = 3; // 4 components max
572 std::ostringstream str;
573 str << (isUint ? "u" : isSint ? "i" : "") << "vec4(";
575 for (int i = 0; i < numComponents; ++i)
578 << (i < maxIndex ? ", " : "");
581 for (int i = numComponents; i < maxIndex + 1; ++i)
583 str << (i == maxIndex ? 1 : 0)
584 << (i < maxIndex ? ", " : "");
591 //! Clear color literal value used by the sampling shader.
592 std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint)
594 const VkClearColorValue clearColor = getClearValue(format).color;
596 return getColorStr(clearColor.uint32, numComponents, isUint, isSint);
598 return getColorStr(clearColor.int32, numComponents, isUint, isSint);
600 return getColorStr(clearColor.float32, numComponents, isUint, isSint);
603 //! Primitive color literal value used by the sampling shader.
604 std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint)
606 const Vec4 color = getPrimitiveColor();
607 return getColorStr(color.getPtr(), numComponents, isUint, isSint);
610 inline int getNumSamples (const VkSampleCountFlagBits samples)
612 return static_cast<int>(samples); // enum bitmask actually matches the number of samples
615 //! A flat-colored shape with sharp angles to make antialiasing visible.
616 std::vector<Vertex4RGBA> genTriangleVertices (void)
618 static const Vertex4RGBA data[] =
621 Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
625 Vec4(0.8f, 0.2f, 0.0f, 1.0f),
629 Vec4(0.8f, -0.2f, 0.0f, 1.0f),
633 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
636 //! A full-viewport quad. Use with TRIANGLE_STRIP topology.
637 std::vector<Vertex4RGBA> genFullQuadVertices (void)
639 static const Vertex4RGBA data[] =
642 Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
646 Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
650 Vec4(1.0f, -1.0f, 0.0f, 1.0f),
654 Vec4(1.0f, 1.0f, 0.0f, 1.0f),
658 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
661 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
663 const char* orderPart;
664 const char* typePart;
666 switch (format.order)
668 case tcu::TextureFormat::R: orderPart = "r"; break;
669 case tcu::TextureFormat::RG: orderPart = "rg"; break;
670 case tcu::TextureFormat::RGB: orderPart = "rgb"; break;
671 case tcu::TextureFormat::RGBA: orderPart = "rgba"; break;
680 case tcu::TextureFormat::FLOAT: typePart = "32f"; break;
681 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break;
683 case tcu::TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break;
684 case tcu::TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break;
685 case tcu::TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break;
687 case tcu::TextureFormat::SIGNED_INT32: typePart = "32i"; break;
688 case tcu::TextureFormat::SIGNED_INT16: typePart = "16i"; break;
689 case tcu::TextureFormat::SIGNED_INT8: typePart = "8i"; break;
691 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break;
692 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break;
694 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break;
695 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break;
702 return std::string() + orderPart + typePart;
705 std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers)
707 const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
708 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : "";
710 std::ostringstream str;
711 str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : "");
716 void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
718 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
719 const bool isUint = isUintFormat(caseDef.colorFormat);
720 const bool isSint = isIntFormat(caseDef.colorFormat);
724 std::ostringstream src;
725 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
727 << "layout(location = 0) in vec4 in_position;\n"
728 << "layout(location = 1) in vec4 in_color;\n"
729 << "layout(location = 0) out vec4 o_color;\n"
731 << "out gl_PerVertex {\n"
732 << " vec4 gl_Position;\n"
735 << "void main(void)\n"
737 << " gl_Position = in_position;\n"
738 << " o_color = in_color;\n"
741 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
746 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
748 std::ostringstream src;
749 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
751 << "layout(location = 0) in vec4 in_color;\n"
752 << "layout(location = 0) out " << colorFormat << " o_color;\n"
754 << "void main(void)\n"
756 << " o_color = " << colorFormat << "(" // float color will be converted to int/uint here if needed
757 << (numComponents == 1 ? "in_color.r" :
758 numComponents == 2 ? "in_color.rg" :
759 numComponents == 3 ? "in_color.rgb" : "in_color") << ");\n"
762 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
766 //! Synchronously render to a multisampled color image.
767 void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage)
769 const DeviceInterface& vk = context.getDeviceInterface();
770 const VkDevice device = context.getDevice();
771 const VkQueue queue = context.getUniversalQueue();
772 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
773 Allocator& allocator = context.getDefaultAllocator();
775 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
776 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
778 const VkRect2D renderArea = {
780 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
784 // Create an image view (attachment) for each layer of the image
785 std::vector<ImageViewSp> colorAttachments;
786 std::vector<VkImageView> attachmentHandles;
787 for (int i = 0; i < caseDef.numLayers; ++i)
789 colorAttachments.push_back(makeSharedPtr(makeImageView(
790 vk, device, colorImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.colorFormat, makeColorSubresourceRange(i, 1))));
791 attachmentHandles.push_back(**colorAttachments.back());
795 const std::vector<Vertex4RGBA> vertices = genTriangleVertices();
796 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
797 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
798 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
801 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
802 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
805 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
806 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
807 const Unique<VkRenderPass> renderPass (makeMultisampleRenderPass (vk, device, caseDef.colorFormat, caseDef.numSamples, caseDef.numLayers));
808 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
809 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())));
810 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
811 const std::vector<PipelineSp> pipelines (makeGraphicsPipelines (vk, device, caseDef.numLayers, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
812 caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
814 beginCommandBuffer(vk, *cmdBuffer);
816 const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat));
818 const VkRenderPassBeginInfo renderPassBeginInfo = {
819 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
820 DE_NULL, // const void* pNext;
821 *renderPass, // VkRenderPass renderPass;
822 *framebuffer, // VkFramebuffer framebuffer;
823 renderArea, // VkRect2D renderArea;
824 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
825 &clearValues[0], // const VkClearValue* pClearValues;
827 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
830 const VkDeviceSize vertexBufferOffset = 0ull;
831 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
834 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
837 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
839 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
841 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
844 vk.cmdEndRenderPass(*cmdBuffer);
846 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
847 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
851 namespace SampledImage
854 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
856 // Pass 1: Render to texture
858 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
860 // Pass 2: Sample texture
864 std::ostringstream src;
865 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
867 << "layout(location = 0) in vec4 in_position;\n"
869 << "out gl_PerVertex {\n"
870 << " vec4 gl_Position;\n"
873 << "void main(void)\n"
875 << " gl_Position = in_position;\n"
878 programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
883 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
884 const bool isUint = isUintFormat(caseDef.colorFormat);
885 const bool isSint = isIntFormat(caseDef.colorFormat);
886 const std::string texelFormatStr = (isUint ? "uvec4" : isSint ? "ivec4" : "vec4");
887 const std::string refClearColor = getReferenceClearColorStr(caseDef.colorFormat, numComponents, isUint, isSint);
888 const std::string refPrimitiveColor = getReferencePrimitiveColorStr(numComponents, isUint, isSint);
889 const std::string samplerTypeStr = getSamplerTypeStr(caseDef.numLayers, isUint, isSint);
891 std::ostringstream src;
892 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
894 << "layout(location = 0) out int o_status;\n"
896 << "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n"
898 << "void main(void)\n"
900 << " int checksum = 0;\n"
903 if (caseDef.numLayers == 1)
904 src << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
905 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), sampleNdx);\n"
906 << " if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
910 src << " for (int layerNdx = 0; layerNdx < " << caseDef.numLayers << "; ++layerNdx)\n"
911 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
912 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec3(gl_FragCoord.xy, layerNdx), sampleNdx);\n"
913 << " if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
918 << " o_status = checksum;\n"
921 programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
925 tcu::TestStatus test (Context& context, const CaseDef caseDef)
927 const DeviceInterface& vk = context.getDeviceInterface();
928 const InstanceInterface& vki = context.getInstanceInterface();
929 const VkDevice device = context.getDevice();
930 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
931 const VkQueue queue = context.getUniversalQueue();
932 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
933 Allocator& allocator = context.getDefaultAllocator();
935 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
937 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
940 tcu::TestLog& log = context.getTestContext().getLog();
941 log << tcu::LogSection("Description", "")
942 << tcu::TestLog::Message << "Rendering to a multisampled image. Expecting all samples to be either a clear color or a primitive color." << tcu::TestLog::EndMessage
943 << tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
944 << tcu::TestLog::EndSection;
947 // Multisampled color image
948 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
949 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
951 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
952 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
954 const VkRect2D renderArea = {
956 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
959 // Step 1: Render to texture
961 renderMultisampledImage(context, caseDef, *colorImage);
964 // Step 2: Sample texture
967 const VkImageViewType colorImageViewType = (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
968 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
969 const Unique<VkSampler> colorSampler (makeSampler(vk, device));
972 const VkFormat checksumFormat = VK_FORMAT_R32_SINT;
973 const Unique<VkImage> checksumImage (makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
974 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
975 const UniquePtr<Allocation> checksumImageAlloc (bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
976 const Unique<VkImageView> checksumImageView (makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
978 // Checksum buffer (for host reading)
979 const VkDeviceSize checksumBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
980 const Unique<VkBuffer> checksumBuffer (makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
981 const UniquePtr<Allocation> checksumBufferAlloc (bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
983 zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
986 const std::vector<Vertex4RGBA> vertices = genFullQuadVertices();
987 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
988 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
989 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
992 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
993 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
997 // \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
999 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1000 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1001 .build(vk, device));
1003 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1004 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1005 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1007 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1008 const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1010 DescriptorSetUpdateBuilder()
1011 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1012 .update(vk, device);
1014 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1015 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1016 const Unique<VkRenderPass> renderPass (makeSimpleRenderPass (vk, device, checksumFormat));
1017 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 1u, &checksumImageView.get(),
1018 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())));
1019 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1020 const std::vector<PipelineSp> pipelines (makeGraphicsPipelines (vk, device, 1u, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
1021 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
1023 beginCommandBuffer(vk, *cmdBuffer);
1025 // Prepare for sampling in the fragment shader
1027 const VkImageMemoryBarrier barriers[] =
1030 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1031 DE_NULL, // const void* pNext;
1032 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1033 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags inputMask;
1034 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1035 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
1036 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1037 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1038 *colorImage, // VkImage image;
1039 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1043 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1044 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1047 const VkClearValue clearValue = makeClearValueColorU32(0u, 0u, 0u, 0u);
1049 const VkRenderPassBeginInfo renderPassBeginInfo = {
1050 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1051 DE_NULL, // const void* pNext;
1052 *renderPass, // VkRenderPass renderPass;
1053 *framebuffer, // VkFramebuffer framebuffer;
1054 renderArea, // VkRect2D renderArea;
1055 1u, // uint32_t clearValueCount;
1056 &clearValue, // const VkClearValue* pClearValues;
1058 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1060 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines.back());
1061 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1063 const VkDeviceSize vertexBufferOffset = 0ull;
1064 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1067 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1068 vk.cmdEndRenderPass(*cmdBuffer);
1070 // Prepare checksum image for copy
1072 const VkImageMemoryBarrier barriers[] =
1075 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1076 DE_NULL, // const void* pNext;
1077 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1078 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1079 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1080 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1081 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1082 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1083 *checksumImage, // VkImage image;
1084 makeColorSubresourceRange(0, 1), // VkImageSubresourceRange subresourceRange;
1088 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1089 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1091 // Checksum image -> host buffer
1093 const VkBufferImageCopy region =
1095 0ull, // VkDeviceSize bufferOffset;
1096 0u, // uint32_t bufferRowLength;
1097 0u, // uint32_t bufferImageHeight;
1098 makeColorSubresourceLayers(0, 1), // VkImageSubresourceLayers imageSubresource;
1099 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1100 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D imageExtent;
1103 vk.cmdCopyImageToBuffer(*cmdBuffer, *checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *checksumBuffer, 1u, ®ion);
1105 // Buffer write barrier
1107 const VkBufferMemoryBarrier barriers[] =
1110 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1111 DE_NULL, // const void* pNext;
1112 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1113 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1114 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1115 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1116 *checksumBuffer, // VkBuffer buffer;
1117 0ull, // VkDeviceSize offset;
1118 checksumBufferSize, // VkDeviceSize size;
1122 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1123 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1126 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1127 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1132 invalidateMappedMemoryRange(vk, device, checksumBufferAlloc->getMemory(), 0ull, checksumBufferSize);
1134 const tcu::ConstPixelBufferAccess access(mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1135 const int numExpectedChecksum = getNumSamples(caseDef.numSamples) * caseDef.numLayers;
1137 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1138 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1140 if (access.getPixelInt(x, y).x() != numExpectedChecksum)
1141 return tcu::TestStatus::fail("Some samples have incorrect color");
1146 return tcu::TestStatus::pass("OK");
1149 } // SampledImage ns
1151 namespace StorageImage
1154 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1156 // Vertex & fragment
1158 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1162 const std::string imageTypeStr = getShaderMultisampledImageType(mapVkFormat(caseDef.colorFormat), caseDef.numLayers);
1163 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(caseDef.colorFormat));
1164 const std::string signednessPrefix = isUintFormat(caseDef.colorFormat) ? "u" : isIntFormat(caseDef.colorFormat) ? "i" : "";
1165 const std::string gvec4Expr = signednessPrefix + "vec4";
1166 const std::string texelCoordStr = (caseDef.numLayers == 1 ? "ivec2(gx, gy)" : "ivec3(gx, gy, gz)");
1168 std::ostringstream src;
1169 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1170 << "layout(local_size_x = 1) in;\n"
1171 << "layout(set = 0, binding = 0, " << formatQualifierStr << ") uniform " << imageTypeStr << " u_msImage;\n"
1173 << "void main(void)\n"
1175 << " int gx = int(gl_GlobalInvocationID.x);\n"
1176 << " int gy = int(gl_GlobalInvocationID.y);\n"
1177 << " int gz = int(gl_GlobalInvocationID.z);\n"
1179 << " " << gvec4Expr << " prevColor = imageLoad(u_msImage, " << texelCoordStr << ", 0);\n"
1180 << " for (int sampleNdx = 1; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1181 << " " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n"
1182 << " imageStore(u_msImage, " << texelCoordStr <<", sampleNdx, prevColor);\n"
1183 << " prevColor = color;\n"
1185 << " imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n"
1188 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1192 //! Render a MS image, resolve it, and copy result to resolveBuffer.
1193 void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass)
1195 const DeviceInterface& vk = context.getDeviceInterface();
1196 const VkDevice device = context.getDevice();
1197 const VkQueue queue = context.getUniversalQueue();
1198 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1199 Allocator& allocator = context.getDefaultAllocator();
1201 // Multisampled color image
1202 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples,
1203 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1204 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1206 const Unique<VkImage> resolveImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, VK_SAMPLE_COUNT_1_BIT,
1207 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1208 const UniquePtr<Allocation> resolveImageAlloc (bindImage(vk, device, allocator, *resolveImage, MemoryRequirement::Any));
1210 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1211 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1213 // Working image barrier, we change it based on which rendering stages were executed so far.
1214 VkImageMemoryBarrier colorImageBarrier =
1216 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1217 DE_NULL, // const void* pNext;
1218 (VkAccessFlags)0, // VkAccessFlags outputMask;
1219 (VkAccessFlags)0, // VkAccessFlags inputMask;
1220 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1221 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout newLayout;
1222 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1223 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1224 *colorImage, // VkImage image;
1225 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1228 // Pass 1: Render an image
1230 renderMultisampledImage(context, caseDef, *colorImage);
1232 colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1233 colorImageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1236 // Pass 2: Compute shader
1241 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1242 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1243 .build(vk, device));
1245 Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1246 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1247 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1249 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage,
1250 (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY),
1251 caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1252 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1253 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_GENERAL);
1255 DescriptorSetUpdateBuilder()
1256 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1257 .update(vk, device);
1259 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1260 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp"), 0));
1261 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1263 beginCommandBuffer(vk, *cmdBuffer);
1265 // Image layout for load/stores
1267 colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1268 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1270 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1271 0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
1273 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1274 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1278 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1279 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1280 vk.cmdDispatch(*cmdBuffer, caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers);
1283 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1284 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1287 // Resolve and verify the image
1289 beginCommandBuffer(vk, *cmdBuffer);
1291 // Prepare for resolve
1293 colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1294 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1296 const VkImageMemoryBarrier barriers[] =
1300 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1301 DE_NULL, // const void* pNext;
1302 (VkAccessFlags)0, // VkAccessFlags outputMask;
1303 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags inputMask;
1304 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1305 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1306 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1307 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1308 *resolveImage, // VkImage image;
1309 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1313 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1314 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1316 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1317 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1319 // Resolve the image
1321 const VkImageResolve resolveRegion =
1323 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource;
1324 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
1325 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource;
1326 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
1327 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D extent;
1330 vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion);
1332 // Prepare resolve image for copy
1334 const VkImageMemoryBarrier barriers[] =
1337 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1338 DE_NULL, // const void* pNext;
1339 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags outputMask;
1340 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1341 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1342 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1343 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1344 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1345 *resolveImage, // VkImage image;
1346 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1350 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1351 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1353 // Copy resolved image to host-readable buffer
1355 const VkBufferImageCopy copyRegion =
1357 0ull, // VkDeviceSize bufferOffset;
1358 0u, // uint32_t bufferRowLength;
1359 0u, // uint32_t bufferImageHeight;
1360 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource;
1361 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1362 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D imageExtent;
1365 vk.cmdCopyImageToBuffer(*cmdBuffer, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resolveBuffer, 1u, ©Region);
1368 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1369 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1373 //! Exact image compare, but allow for some error when color format is integer.
1374 bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage)
1376 DE_ASSERT(caseDef.numSamples > 1);
1378 const Vec4 goodColor = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1379 const Vec4 badColor = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1380 const bool isAnyIntFormat = isIntFormat(caseDef.colorFormat) || isUintFormat(caseDef.colorFormat);
1382 // There should be no mismatched pixels for non-integer formats. Otherwise we may get a wrong color in a location where sample coverage isn't exactly 0 or 1.
1383 const int badPixelTolerance = (isAnyIntFormat ? 2 * caseDef.renderSize.x() : 0);
1386 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1388 const tcu::ConstPixelBufferAccess referenceImage = tcu::getSubregion(layeredReferenceImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1389 const tcu::ConstPixelBufferAccess actualImage = tcu::getSubregion(layeredActualImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1390 const std::string imageName = "color layer " + de::toString(layerNdx);
1392 tcu::TextureLevel errorMaskStorage (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), caseDef.renderSize.x(), caseDef.renderSize.y());
1393 tcu::PixelBufferAccess errorMask = errorMaskStorage.getAccess();
1394 int numBadPixels = 0;
1396 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1397 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1399 if (isAnyIntFormat && (referenceImage.getPixelInt(x, y) == actualImage.getPixelInt(x, y)))
1400 errorMask.setPixel(goodColor, x, y);
1401 else if (referenceImage.getPixel(x, y) == actualImage.getPixel(x, y))
1402 errorMask.setPixel(goodColor, x, y);
1406 errorMask.setPixel(badColor, x, y);
1410 if (numBadPixels <= badPixelTolerance)
1414 log << tcu::TestLog::ImageSet(imageName, imageName)
1415 << tcu::TestLog::Image("Result", "Result", actualImage)
1416 << tcu::TestLog::EndImageSet;
1420 log << tcu::TestLog::ImageSet(imageName, imageName)
1421 << tcu::TestLog::Image("Result", "Result", actualImage)
1422 << tcu::TestLog::Image("Reference", "Reference", referenceImage)
1423 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
1424 << tcu::TestLog::EndImageSet;
1428 if (goodLayers == caseDef.numLayers)
1430 log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage;
1435 log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage;
1440 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1442 const DeviceInterface& vk = context.getDeviceInterface();
1443 const InstanceInterface& vki = context.getInstanceInterface();
1444 const VkDevice device = context.getDevice();
1445 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1446 Allocator& allocator = context.getDefaultAllocator();
1448 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
1451 tcu::TestLog& log = context.getTestContext().getLog();
1452 log << tcu::LogSection("Description", "")
1453 << tcu::TestLog::Message << "Rendering to a multisampled image. Image will be processed with a compute shader using OpImageRead and OpImageWrite." << tcu::TestLog::EndMessage
1454 << tcu::TestLog::Message << "Expecting the processed image to be roughly the same as the input image (deviation may occur for integer formats)." << tcu::TestLog::EndMessage
1455 << tcu::TestLog::EndSection;
1458 // Host-readable buffer
1459 const VkDeviceSize resolveBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
1460 const Unique<VkBuffer> resolveImageOneBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1461 const UniquePtr<Allocation> resolveImageOneBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageOneBuffer, MemoryRequirement::HostVisible));
1462 const Unique<VkBuffer> resolveImageTwoBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1463 const UniquePtr<Allocation> resolveImageTwoBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageTwoBuffer, MemoryRequirement::HostVisible));
1465 zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize);
1466 zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize);
1468 // Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy).
1470 renderAndResolve(context, caseDef, *resolveImageOneBuffer, false); // Pass 1: render a basic multisampled image
1471 renderAndResolve(context, caseDef, *resolveImageTwoBuffer, true); // Pass 2: the same but altered with a compute shader
1476 invalidateMappedMemoryRange(vk, device, resolveImageOneBufferAlloc->getMemory(), resolveImageOneBufferAlloc->getOffset(), resolveBufferSize);
1477 invalidateMappedMemoryRange(vk, device, resolveImageTwoBufferAlloc->getMemory(), resolveImageTwoBufferAlloc->getOffset(), resolveBufferSize);
1479 const tcu::PixelBufferAccess layeredImageOne (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageOneBufferAlloc->getHostPtr());
1480 const tcu::ConstPixelBufferAccess layeredImageTwo (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageTwoBufferAlloc->getHostPtr());
1483 if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo))
1484 return tcu::TestStatus::fail("Rendered images are not correct");
1487 return tcu::TestStatus::pass("OK");
1490 } // StorageImage ns
1492 std::string getSizeLayerString (const IVec2& size, const int numLayers)
1494 std::ostringstream str;
1495 str << size.x() << "x" << size.y() << "_" << numLayers;
1499 std::string getFormatString (const VkFormat format)
1501 std::string name(getFormatName(format));
1502 return de::toLower(name.substr(10));
1505 void addTestCasesWithFunctions (tcu::TestCaseGroup* group,
1506 FunctionPrograms1<CaseDef>::Function initPrograms,
1507 FunctionInstance1<CaseDef>::Function testFunc)
1509 const IVec2 size[] =
1514 const int numLayers[] =
1518 const VkSampleCountFlagBits samples[] =
1520 VK_SAMPLE_COUNT_2_BIT,
1521 VK_SAMPLE_COUNT_4_BIT,
1522 VK_SAMPLE_COUNT_8_BIT,
1523 VK_SAMPLE_COUNT_16_BIT,
1524 VK_SAMPLE_COUNT_32_BIT,
1525 VK_SAMPLE_COUNT_64_BIT,
1527 const VkFormat format[] =
1529 VK_FORMAT_R8G8B8A8_UNORM,
1531 VK_FORMAT_R16G16_SINT,
1532 VK_FORMAT_R32G32B32A32_SFLOAT,
1535 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx)
1536 for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx)
1538 MovePtr<tcu::TestCaseGroup> sizeLayerGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeLayerString(size[sizeNdx], numLayers[layerNdx]).c_str(), ""));
1539 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1541 MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str(), ""));
1542 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
1544 std::ostringstream caseName;
1545 caseName << "samples_" << getNumSamples(samples[samplesNdx]);
1547 const CaseDef caseDef =
1549 size[sizeNdx], // IVec2 renderSize;
1550 numLayers[layerNdx], // int numLayers;
1551 format[formatNdx], // VkFormat colorFormat;
1552 samples[samplesNdx], // VkSampleCountFlagBits numSamples;
1555 addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), "", initPrograms, testFunc, caseDef);
1557 sizeLayerGroup->addChild(formatGroup.release());
1559 group->addChild(sizeLayerGroup.release());
1563 void createSampledImageTestsInGroup (tcu::TestCaseGroup* group)
1565 addTestCasesWithFunctions(group, SampledImage::initPrograms, SampledImage::test);
1568 void createStorageImageTestsInGroup (tcu::TestCaseGroup* group)
1570 addTestCasesWithFunctions(group, StorageImage::initPrograms, StorageImage::test);
1575 //! Render to a multisampled image and sample from it in a fragment shader.
1576 tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx)
1578 return createTestGroup(testCtx, "sampled_image", "Multisampled image direct sample access", createSampledImageTestsInGroup);
1581 //! Render to a multisampled image and access it with load/stores in a compute shader.
1582 tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx)
1584 return createTestGroup(testCtx, "storage_image", "Multisampled image draw and read/write in compute shader", createStorageImageTestsInGroup);