1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \file
21 * \brief Multisample image Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineMultisampleImageTests.hpp"
25 #include "vktPipelineMakeUtil.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30
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"
38
39 #include "tcuTextureUtil.hpp"
40
41 #include "deUniquePtr.hpp"
42 #include "deSharedPtr.hpp"
43
44 #include <string>
45
46 namespace vkt
47 {
48 namespace pipeline
49 {
50 namespace
51 {
52 using namespace vk;
53 using de::UniquePtr;
54 using de::MovePtr;
55 using de::SharedPtr;
56 using tcu::IVec2;
57 using tcu::Vec4;
58
59 typedef SharedPtr<Unique<VkImageView> > ImageViewSp;
60 typedef SharedPtr<Unique<VkPipeline> > PipelineSp;
61
62 //! Test case parameters
63 struct CaseDef
64 {
65 IVec2 renderSize;
66 int numLayers;
67 VkFormat colorFormat;
68 VkSampleCountFlagBits numSamples;
69 };
70
71 template<typename T>
makeSharedPtr(Move<T> move)72 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
73 {
74 return SharedPtr<Unique<T> >(new Unique<T>(move));
75 }
76
77 template<typename T>
sizeInBytes(const std::vector<T> & vec)78 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
79 {
80 return vec.size() * sizeof(vec[0]);
81 }
82
83 //! Create a vector of derived pipelines, each with an increasing subpass index
makeGraphicsPipelines(const DeviceInterface & vk,const VkDevice device,const deUint32 numSubpasses,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const IVec2 renderSize,const VkSampleCountFlagBits numSamples,const VkPrimitiveTopology topology)84 std::vector<PipelineSp> makeGraphicsPipelines (const DeviceInterface& vk,
85 const VkDevice device,
86 const deUint32 numSubpasses,
87 const VkPipelineLayout pipelineLayout,
88 const VkRenderPass renderPass,
89 const VkShaderModule vertexModule,
90 const VkShaderModule fragmentModule,
91 const IVec2 renderSize,
92 const VkSampleCountFlagBits numSamples,
93 const VkPrimitiveTopology topology)
94 {
95 const VkVertexInputBindingDescription vertexInputBindingDescription =
96 {
97 0u, // uint32_t binding;
98 sizeof(Vertex4RGBA), // uint32_t stride;
99 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
100 };
101
102 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
103 {
104 {
105 0u, // uint32_t location;
106 0u, // uint32_t binding;
107 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
108 0u, // uint32_t offset;
109 },
110 {
111 1u, // uint32_t location;
112 0u, // uint32_t binding;
113 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
114 sizeof(Vec4), // uint32_t offset;
115 },
116 };
117
118 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
119 {
120 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
121 DE_NULL, // const void* pNext;
122 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
123 1u, // uint32_t vertexBindingDescriptionCount;
124 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
125 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
126 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
127 };
128
129 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
130 {
131 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
132 DE_NULL, // const void* pNext;
133 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
134 topology, // VkPrimitiveTopology topology;
135 VK_FALSE, // VkBool32 primitiveRestartEnable;
136 };
137
138 const VkViewport viewport = makeViewport(
139 0.0f, 0.0f,
140 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
141 0.0f, 1.0f);
142
143 const VkRect2D scissor = {
144 makeOffset2D(0, 0),
145 makeExtent2D(renderSize.x(), renderSize.y()),
146 };
147
148 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
149 {
150 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
151 DE_NULL, // const void* pNext;
152 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
153 1u, // uint32_t viewportCount;
154 &viewport, // const VkViewport* pViewports;
155 1u, // uint32_t scissorCount;
156 &scissor, // const VkRect2D* pScissors;
157 };
158
159 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
160 {
161 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
162 DE_NULL, // const void* pNext;
163 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
164 VK_FALSE, // VkBool32 depthClampEnable;
165 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
166 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
167 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
168 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
169 VK_FALSE, // VkBool32 depthBiasEnable;
170 0.0f, // float depthBiasConstantFactor;
171 0.0f, // float depthBiasClamp;
172 0.0f, // float depthBiasSlopeFactor;
173 1.0f, // float lineWidth;
174 };
175
176 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
177 {
178 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
179 DE_NULL, // const void* pNext;
180 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
181 numSamples, // VkSampleCountFlagBits rasterizationSamples;
182 VK_FALSE, // VkBool32 sampleShadingEnable;
183 0.0f, // float minSampleShading;
184 DE_NULL, // const VkSampleMask* pSampleMask;
185 VK_FALSE, // VkBool32 alphaToCoverageEnable;
186 VK_FALSE // VkBool32 alphaToOneEnable;
187 };
188
189 const VkStencilOpState stencilOpState = makeStencilOpState(
190 VK_STENCIL_OP_KEEP, // stencil fail
191 VK_STENCIL_OP_KEEP, // depth & stencil pass
192 VK_STENCIL_OP_KEEP, // depth only fail
193 VK_COMPARE_OP_ALWAYS, // compare op
194 0u, // compare mask
195 0u, // write mask
196 0u); // reference
197
198 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
199 {
200 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
201 DE_NULL, // const void* pNext;
202 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
203 VK_FALSE, // VkBool32 depthTestEnable;
204 VK_FALSE, // VkBool32 depthWriteEnable;
205 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
206 VK_FALSE, // VkBool32 depthBoundsTestEnable;
207 VK_FALSE, // VkBool32 stencilTestEnable;
208 stencilOpState, // VkStencilOpState front;
209 stencilOpState, // VkStencilOpState back;
210 0.0f, // float minDepthBounds;
211 1.0f, // float maxDepthBounds;
212 };
213
214 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
215 // Number of blend attachments must equal the number of color attachments during any subpass.
216 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
217 {
218 VK_FALSE, // VkBool32 blendEnable;
219 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
220 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
221 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
222 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
223 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
224 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
225 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
226 };
227
228 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
229 {
230 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
231 DE_NULL, // const void* pNext;
232 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
233 VK_FALSE, // VkBool32 logicOpEnable;
234 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
235 1u, // deUint32 attachmentCount;
236 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
237 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
238 };
239
240 const VkPipelineShaderStageCreateInfo pShaderStages[] =
241 {
242 {
243 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
244 DE_NULL, // const void* pNext;
245 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
246 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
247 vertexModule, // VkShaderModule module;
248 "main", // const char* pName;
249 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
250 },
251 {
252 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
253 DE_NULL, // const void* pNext;
254 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
255 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
256 fragmentModule, // VkShaderModule module;
257 "main", // const char* pName;
258 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
259 }
260 };
261
262 DE_ASSERT(numSubpasses > 0u);
263
264 std::vector<VkGraphicsPipelineCreateInfo> graphicsPipelineInfos (0);
265 std::vector<VkPipeline> rawPipelines (numSubpasses, DE_NULL);
266
267 {
268 const VkPipelineCreateFlags firstPipelineFlags = (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
269 : (VkPipelineCreateFlagBits)0);
270
271 VkGraphicsPipelineCreateInfo createInfo =
272 {
273 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
274 DE_NULL, // const void* pNext;
275 firstPipelineFlags, // VkPipelineCreateFlags flags;
276 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
277 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
278 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
279 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
280 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
281 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
282 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
283 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
284 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
285 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
286 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
287 pipelineLayout, // VkPipelineLayout layout;
288 renderPass, // VkRenderPass renderPass;
289 0u, // deUint32 subpass;
290 DE_NULL, // VkPipeline basePipelineHandle;
291 -1, // deInt32 basePipelineIndex;
292 };
293
294 graphicsPipelineInfos.push_back(createInfo);
295
296 createInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
297 createInfo.basePipelineIndex = 0;
298
299 for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx)
300 {
301 createInfo.subpass = subpassNdx;
302 graphicsPipelineInfos.push_back(createInfo);
303 }
304 }
305
306 VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0]));
307
308 std::vector<PipelineSp> pipelines;
309
310 for (std::vector<VkPipeline>::const_iterator it = rawPipelines.begin(); it != rawPipelines.end(); ++it)
311 pipelines.push_back(makeSharedPtr(Move<VkPipeline>(check<VkPipeline>(*it), Deleter<VkPipeline>(vk, device, DE_NULL))));
312
313 return pipelines;
314 }
315
316 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
makeMultisampleRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkSampleCountFlagBits numSamples,const deUint32 numLayers)317 Move<VkRenderPass> makeMultisampleRenderPass (const DeviceInterface& vk,
318 const VkDevice device,
319 const VkFormat colorFormat,
320 const VkSampleCountFlagBits numSamples,
321 const deUint32 numLayers)
322 {
323 const VkAttachmentDescription colorAttachmentDescription =
324 {
325 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
326 colorFormat, // VkFormat format;
327 numSamples, // VkSampleCountFlagBits samples;
328 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
329 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
330 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
331 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
332 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
333 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
334 };
335 const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
336
337 // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
338
339 std::vector<VkAttachmentReference> colorAttachmentReferences(numLayers);
340 std::vector<VkSubpassDescription> subpasses;
341
342 for (deUint32 i = 0; i < numLayers; ++i)
343 {
344 const VkAttachmentReference attachmentRef =
345 {
346 i, // deUint32 attachment;
347 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
348 };
349 colorAttachmentReferences[i] = attachmentRef;
350
351 const VkSubpassDescription subpassDescription =
352 {
353 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
354 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
355 0u, // deUint32 inputAttachmentCount;
356 DE_NULL, // const VkAttachmentReference* pInputAttachments;
357 1u, // deUint32 colorAttachmentCount;
358 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
359 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
360 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
361 0u, // deUint32 preserveAttachmentCount;
362 DE_NULL // const deUint32* pPreserveAttachments;
363 };
364 subpasses.push_back(subpassDescription);
365 }
366
367 const VkRenderPassCreateInfo renderPassInfo =
368 {
369 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
370 DE_NULL, // const void* pNext;
371 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
372 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
373 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
374 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
375 &subpasses[0], // const VkSubpassDescription* pSubpasses;
376 0u, // deUint32 dependencyCount;
377 DE_NULL // const VkSubpassDependency* pDependencies;
378 };
379
380 return createRenderPass(vk, device, &renderPassInfo);
381 }
382
383 //! A single-attachment, single-subpass render pass.
makeSimpleRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)384 Move<VkRenderPass> makeSimpleRenderPass (const DeviceInterface& vk,
385 const VkDevice device,
386 const VkFormat colorFormat)
387 {
388 const VkAttachmentDescription colorAttachmentDescription =
389 {
390 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
391 colorFormat, // VkFormat format;
392 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
393 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
394 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
395 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
396 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
397 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
398 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
399 };
400
401 const VkAttachmentReference colorAttachmentRef =
402 {
403 0u, // deUint32 attachment;
404 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
405 };
406
407 const VkSubpassDescription subpassDescription =
408 {
409 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
410 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
411 0u, // deUint32 inputAttachmentCount;
412 DE_NULL, // const VkAttachmentReference* pInputAttachments;
413 1u, // deUint32 colorAttachmentCount;
414 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
415 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
416 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
417 0u, // deUint32 preserveAttachmentCount;
418 DE_NULL // const deUint32* pPreserveAttachments;
419 };
420
421 const VkRenderPassCreateInfo renderPassInfo =
422 {
423 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
424 DE_NULL, // const void* pNext;
425 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
426 1u, // deUint32 attachmentCount;
427 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
428 1u, // deUint32 subpassCount;
429 &subpassDescription, // const VkSubpassDescription* pSubpasses;
430 0u, // deUint32 dependencyCount;
431 DE_NULL // const VkSubpassDependency* pDependencies;
432 };
433
434 return createRenderPass(vk, device, &renderPassInfo);
435 }
436
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const IVec2 & size,const deUint32 numLayers,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)437 Move<VkImage> makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
438 {
439 const VkImageCreateInfo imageParams =
440 {
441 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
442 DE_NULL, // const void* pNext;
443 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
444 VK_IMAGE_TYPE_2D, // VkImageType imageType;
445 format, // VkFormat format;
446 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
447 1u, // deUint32 mipLevels;
448 numLayers, // deUint32 arrayLayers;
449 samples, // VkSampleCountFlagBits samples;
450 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
451 usage, // VkImageUsageFlags usage;
452 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
453 0u, // deUint32 queueFamilyIndexCount;
454 DE_NULL, // const deUint32* pQueueFamilyIndices;
455 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
456 };
457 return createImage(vk, device, &imageParams);
458 }
459
460 //! Make a simplest sampler.
makeSampler(const DeviceInterface & vk,const VkDevice device)461 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
462 {
463 const VkSamplerCreateInfo samplerParams =
464 {
465 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
466 DE_NULL, // const void* pNext;
467 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags;
468 VK_FILTER_NEAREST, // VkFilter magFilter;
469 VK_FILTER_NEAREST, // VkFilter minFilter;
470 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
471 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
472 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
473 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
474 0.0f, // float mipLodBias;
475 VK_FALSE, // VkBool32 anisotropyEnable;
476 1.0f, // float maxAnisotropy;
477 VK_FALSE, // VkBool32 compareEnable;
478 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
479 0.0f, // float minLod;
480 0.0f, // float maxLod;
481 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
482 VK_FALSE, // VkBool32 unnormalizedCoordinates;
483 };
484 return createSampler(vk, device, &samplerParams);
485 }
486
makeBuffer(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)487 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
488 {
489 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
490 return createBuffer(vk, device, &bufferCreateInfo);
491 }
492
makeColorSubresourceRange(const int baseArrayLayer,const int layerCount)493 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
494 {
495 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
496 }
497
makeColorSubresourceLayers(const int baseArrayLayer,const int layerCount)498 inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount)
499 {
500 return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
501 }
502
checkImageFormatRequirements(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkSampleCountFlagBits sampleCount,const VkFormat format,const VkImageUsageFlags usage)503 void checkImageFormatRequirements (const InstanceInterface& vki,
504 const VkPhysicalDevice physDevice,
505 const VkSampleCountFlagBits sampleCount,
506 const VkFormat format,
507 const VkImageUsageFlags usage)
508 {
509 VkPhysicalDeviceFeatures features;
510 vki.getPhysicalDeviceFeatures(physDevice, &features);
511
512 if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample)
513 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
514
515 VkImageFormatProperties imageFormatProperties;
516 const VkResult imageFormatResult = vki.getPhysicalDeviceImageFormatProperties(
517 physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties);
518
519 if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
520 TCU_THROW(NotSupportedError, "Image format is not supported");
521
522 if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount)
523 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
524 }
525
zeroBuffer(const DeviceInterface & vk,const VkDevice device,const Allocation & alloc,const VkDeviceSize bufferSize)526 void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize bufferSize)
527 {
528 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(bufferSize));
529 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
530 }
531
532 //! The default foreground color.
getPrimitiveColor(void)533 inline Vec4 getPrimitiveColor (void)
534 {
535 return Vec4(1.0f, 0.0f, 0.0f, 1.0f);
536 }
537
538 //! Get a reference clear value based on color format.
getClearValue(const VkFormat format)539 VkClearValue getClearValue (const VkFormat format)
540 {
541 if (isUintFormat(format) || isIntFormat(format))
542 return makeClearValueColorU32(16, 32, 64, 96);
543 else
544 return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f);
545 }
546
getColorFormatStr(const int numComponents,const bool isUint,const bool isSint)547 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
548 {
549 std::ostringstream str;
550 if (numComponents == 1)
551 str << (isUint ? "uint" : isSint ? "int" : "float");
552 else
553 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
554
555 return str.str();
556 }
557
getSamplerTypeStr(const int numLayers,const bool isUint,const bool isSint)558 std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint)
559 {
560 std::ostringstream str;
561 str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : "");
562 return str.str();
563 }
564
565 //! Generate a gvec4 color literal.
566 template<typename T>
getColorStr(const T * data,int numComponents,const bool isUint,const bool isSint)567 std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint)
568 {
569 const int maxIndex = 3; // 4 components max
570
571 std::ostringstream str;
572 str << (isUint ? "u" : isSint ? "i" : "") << "vec4(";
573
574 for (int i = 0; i < numComponents; ++i)
575 {
576 str << data[i]
577 << (i < maxIndex ? ", " : "");
578 }
579
580 for (int i = numComponents; i < maxIndex + 1; ++i)
581 {
582 str << (i == maxIndex ? 1 : 0)
583 << (i < maxIndex ? ", " : "");
584 }
585
586 str << ")";
587 return str.str();
588 }
589
590 //! Clear color literal value used by the sampling shader.
getReferenceClearColorStr(const VkFormat format,const int numComponents,const bool isUint,const bool isSint)591 std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint)
592 {
593 const VkClearColorValue clearColor = getClearValue(format).color;
594 if (isUint)
595 return getColorStr(clearColor.uint32, numComponents, isUint, isSint);
596 else if (isSint)
597 return getColorStr(clearColor.int32, numComponents, isUint, isSint);
598 else
599 return getColorStr(clearColor.float32, numComponents, isUint, isSint);
600 }
601
602 //! Primitive color literal value used by the sampling shader.
getReferencePrimitiveColorStr(int numComponents,const bool isUint,const bool isSint)603 std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint)
604 {
605 const Vec4 color = getPrimitiveColor();
606 return getColorStr(color.getPtr(), numComponents, isUint, isSint);
607 }
608
getNumSamples(const VkSampleCountFlagBits samples)609 inline int getNumSamples (const VkSampleCountFlagBits samples)
610 {
611 return static_cast<int>(samples); // enum bitmask actually matches the number of samples
612 }
613
614 //! A flat-colored shape with sharp angles to make antialiasing visible.
genTriangleVertices(void)615 std::vector<Vertex4RGBA> genTriangleVertices (void)
616 {
617 static const Vertex4RGBA data[] =
618 {
619 {
620 Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
621 getPrimitiveColor(),
622 },
623 {
624 Vec4(0.8f, 0.2f, 0.0f, 1.0f),
625 getPrimitiveColor(),
626 },
627 {
628 Vec4(0.8f, -0.2f, 0.0f, 1.0f),
629 getPrimitiveColor(),
630 },
631 };
632 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
633 }
634
635 //! A full-viewport quad. Use with TRIANGLE_STRIP topology.
genFullQuadVertices(void)636 std::vector<Vertex4RGBA> genFullQuadVertices (void)
637 {
638 static const Vertex4RGBA data[] =
639 {
640 {
641 Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
642 Vec4(), // unused
643 },
644 {
645 Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
646 Vec4(), // unused
647 },
648 {
649 Vec4(1.0f, -1.0f, 0.0f, 1.0f),
650 Vec4(), // unused
651 },
652 {
653 Vec4(1.0f, 1.0f, 0.0f, 1.0f),
654 Vec4(), // unused
655 },
656 };
657 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
658 }
659
getShaderImageFormatQualifier(const tcu::TextureFormat & format)660 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
661 {
662 const char* orderPart;
663 const char* typePart;
664
665 switch (format.order)
666 {
667 case tcu::TextureFormat::R: orderPart = "r"; break;
668 case tcu::TextureFormat::RG: orderPart = "rg"; break;
669 case tcu::TextureFormat::RGB: orderPart = "rgb"; break;
670 case tcu::TextureFormat::RGBA: orderPart = "rgba"; break;
671
672 default:
673 DE_ASSERT(false);
674 orderPart = DE_NULL;
675 }
676
677 switch (format.type)
678 {
679 case tcu::TextureFormat::FLOAT: typePart = "32f"; break;
680 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break;
681
682 case tcu::TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break;
683 case tcu::TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break;
684 case tcu::TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break;
685
686 case tcu::TextureFormat::SIGNED_INT32: typePart = "32i"; break;
687 case tcu::TextureFormat::SIGNED_INT16: typePart = "16i"; break;
688 case tcu::TextureFormat::SIGNED_INT8: typePart = "8i"; break;
689
690 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break;
691 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break;
692
693 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break;
694 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break;
695
696 default:
697 DE_ASSERT(false);
698 typePart = DE_NULL;
699 }
700
701 return std::string() + orderPart + typePart;
702 }
703
getShaderMultisampledImageType(const tcu::TextureFormat & format,const int numLayers)704 std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers)
705 {
706 const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
707 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : "";
708
709 std::ostringstream str;
710 str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : "");
711
712 return str.str();
713 }
714
addSimpleVertexAndFragmentPrograms(SourceCollections & programCollection,const CaseDef caseDef)715 void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
716 {
717 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
718 const bool isUint = isUintFormat(caseDef.colorFormat);
719 const bool isSint = isIntFormat(caseDef.colorFormat);
720
721 // Vertex shader
722 {
723 std::ostringstream src;
724 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
725 << "\n"
726 << "layout(location = 0) in vec4 in_position;\n"
727 << "layout(location = 1) in vec4 in_color;\n"
728 << "layout(location = 0) out vec4 o_color;\n"
729 << "\n"
730 << "out gl_PerVertex {\n"
731 << " vec4 gl_Position;\n"
732 << "};\n"
733 << "\n"
734 << "void main(void)\n"
735 << "{\n"
736 << " gl_Position = in_position;\n"
737 << " o_color = in_color;\n"
738 << "}\n";
739
740 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
741 }
742
743 // Fragment shader
744 {
745 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
746
747 std::ostringstream src;
748 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
749 << "\n"
750 << "layout(location = 0) in vec4 in_color;\n"
751 << "layout(location = 0) out " << colorFormat << " o_color;\n"
752 << "\n"
753 << "void main(void)\n"
754 << "{\n"
755 << " o_color = " << colorFormat << "(" // float color will be converted to int/uint here if needed
756 << (numComponents == 1 ? "in_color.r" :
757 numComponents == 2 ? "in_color.rg" :
758 numComponents == 3 ? "in_color.rgb" : "in_color") << ");\n"
759 << "}\n";
760
761 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
762 }
763 }
764
765 //! Synchronously render to a multisampled color image.
renderMultisampledImage(Context & context,const CaseDef & caseDef,const VkImage colorImage)766 void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage)
767 {
768 const DeviceInterface& vk = context.getDeviceInterface();
769 const VkDevice device = context.getDevice();
770 const VkQueue queue = context.getUniversalQueue();
771 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
772 Allocator& allocator = context.getDefaultAllocator();
773
774 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex));
775 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
776
777 const VkRect2D renderArea = {
778 makeOffset2D(0, 0),
779 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
780 };
781
782 {
783 // Create an image view (attachment) for each layer of the image
784 std::vector<ImageViewSp> colorAttachments;
785 std::vector<VkImageView> attachmentHandles;
786 for (int i = 0; i < caseDef.numLayers; ++i)
787 {
788 colorAttachments.push_back(makeSharedPtr(makeImageView(
789 vk, device, colorImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.colorFormat, makeColorSubresourceRange(i, 1))));
790 attachmentHandles.push_back(**colorAttachments.back());
791 }
792
793 // Vertex buffer
794 const std::vector<Vertex4RGBA> vertices = genTriangleVertices();
795 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
796 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
797 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
798
799 {
800 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
801 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
802 }
803
804 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
805 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
806 const Unique<VkRenderPass> renderPass (makeMultisampleRenderPass (vk, device, caseDef.colorFormat, caseDef.numSamples, caseDef.numLayers));
807 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
808 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())));
809 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
810 const std::vector<PipelineSp> pipelines (makeGraphicsPipelines (vk, device, caseDef.numLayers, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
811 caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
812
813 beginCommandBuffer(vk, *cmdBuffer);
814
815 const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat));
816
817 const VkRenderPassBeginInfo renderPassBeginInfo = {
818 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
819 DE_NULL, // const void* pNext;
820 *renderPass, // VkRenderPass renderPass;
821 *framebuffer, // VkFramebuffer framebuffer;
822 renderArea, // VkRect2D renderArea;
823 static_cast<deUint32>(clearValues.size()), // uint32_t clearValueCount;
824 &clearValues[0], // const VkClearValue* pClearValues;
825 };
826 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
827
828 {
829 const VkDeviceSize vertexBufferOffset = 0ull;
830 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
831 }
832
833 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
834 {
835 if (layerNdx != 0)
836 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
837
838 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
839
840 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
841 }
842
843 vk.cmdEndRenderPass(*cmdBuffer);
844
845 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
846 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
847 }
848 }
849
850 namespace SampledImage
851 {
852
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)853 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
854 {
855 // Pass 1: Render to texture
856
857 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
858
859 // Pass 2: Sample texture
860
861 // Vertex shader
862 {
863 std::ostringstream src;
864 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
865 << "\n"
866 << "layout(location = 0) in vec4 in_position;\n"
867 << "\n"
868 << "out gl_PerVertex {\n"
869 << " vec4 gl_Position;\n"
870 << "};\n"
871 << "\n"
872 << "void main(void)\n"
873 << "{\n"
874 << " gl_Position = in_position;\n"
875 << "}\n";
876
877 programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
878 }
879
880 // Fragment shader
881 {
882 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
883 const bool isUint = isUintFormat(caseDef.colorFormat);
884 const bool isSint = isIntFormat(caseDef.colorFormat);
885 const std::string texelFormatStr = (isUint ? "uvec4" : isSint ? "ivec4" : "vec4");
886 const std::string refClearColor = getReferenceClearColorStr(caseDef.colorFormat, numComponents, isUint, isSint);
887 const std::string refPrimitiveColor = getReferencePrimitiveColorStr(numComponents, isUint, isSint);
888 const std::string samplerTypeStr = getSamplerTypeStr(caseDef.numLayers, isUint, isSint);
889
890 std::ostringstream src;
891 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
892 << "\n"
893 << "layout(location = 0) out int o_status;\n"
894 << "\n"
895 << "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n"
896 << "\n"
897 << "void main(void)\n"
898 << "{\n"
899 << " int checksum = 0;\n"
900 << "\n";
901
902 if (caseDef.numLayers == 1)
903 src << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
904 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), sampleNdx);\n"
905 << " if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
906 << " ++checksum;\n"
907 << " }\n";
908 else
909 src << " for (int layerNdx = 0; layerNdx < " << caseDef.numLayers << "; ++layerNdx)\n"
910 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
911 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec3(gl_FragCoord.xy, layerNdx), sampleNdx);\n"
912 << " if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
913 << " ++checksum;\n"
914 << " }\n";
915
916 src << "\n"
917 << " o_status = checksum;\n"
918 << "}\n";
919
920 programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
921 }
922 }
923
test(Context & context,const CaseDef caseDef)924 tcu::TestStatus test (Context& context, const CaseDef caseDef)
925 {
926 const DeviceInterface& vk = context.getDeviceInterface();
927 const InstanceInterface& vki = context.getInstanceInterface();
928 const VkDevice device = context.getDevice();
929 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
930 const VkQueue queue = context.getUniversalQueue();
931 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
932 Allocator& allocator = context.getDefaultAllocator();
933
934 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
935
936 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
937
938 {
939 tcu::TestLog& log = context.getTestContext().getLog();
940 log << tcu::LogSection("Description", "")
941 << tcu::TestLog::Message << "Rendering to a multisampled image. Expecting all samples to be either a clear color or a primitive color." << tcu::TestLog::EndMessage
942 << tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
943 << tcu::TestLog::EndSection;
944 }
945
946 // Multisampled color image
947 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
948 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
949
950 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex));
951 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
952
953 const VkRect2D renderArea = {
954 makeOffset2D(0, 0),
955 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
956 };
957
958 // Step 1: Render to texture
959 {
960 renderMultisampledImage(context, caseDef, *colorImage);
961 }
962
963 // Step 2: Sample texture
964 {
965 // Color image view
966 const VkImageViewType colorImageViewType = (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
967 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
968 const Unique<VkSampler> colorSampler (makeSampler(vk, device));
969
970 // Checksum image
971 const VkFormat checksumFormat = VK_FORMAT_R32_SINT;
972 const Unique<VkImage> checksumImage (makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
973 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
974 const UniquePtr<Allocation> checksumImageAlloc (bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
975 const Unique<VkImageView> checksumImageView (makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
976
977 // Checksum buffer (for host reading)
978 const VkDeviceSize checksumBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
979 const Unique<VkBuffer> checksumBuffer (makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
980 const UniquePtr<Allocation> checksumBufferAlloc (bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
981
982 zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
983
984 // Vertex buffer
985 const std::vector<Vertex4RGBA> vertices = genFullQuadVertices();
986 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
987 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
988 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
989
990 {
991 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
992 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
993 }
994
995 // Descriptors
996 // \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
997
998 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
999 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1000 .build(vk, device));
1001
1002 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1003 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1004 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1005
1006 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1007 const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1008
1009 DescriptorSetUpdateBuilder()
1010 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1011 .update(vk, device);
1012
1013 const Unique<VkShaderModule> vertexModule (createShaderModule (vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1014 const Unique<VkShaderModule> fragmentModule (createShaderModule (vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1015 const Unique<VkRenderPass> renderPass (makeSimpleRenderPass (vk, device, checksumFormat));
1016 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 1u, &checksumImageView.get(),
1017 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y())));
1018 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1019 const std::vector<PipelineSp> pipelines (makeGraphicsPipelines (vk, device, 1u, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
1020 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
1021
1022 beginCommandBuffer(vk, *cmdBuffer);
1023
1024 // Prepare for sampling in the fragment shader
1025 {
1026 const VkImageMemoryBarrier barriers[] =
1027 {
1028 {
1029 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1030 DE_NULL, // const void* pNext;
1031 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1032 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags inputMask;
1033 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1034 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
1035 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1036 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1037 *colorImage, // VkImage image;
1038 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1039 },
1040 };
1041
1042 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1043 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1044 }
1045
1046 const VkClearValue clearValue = makeClearValueColorU32(0u, 0u, 0u, 0u);
1047
1048 const VkRenderPassBeginInfo renderPassBeginInfo = {
1049 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1050 DE_NULL, // const void* pNext;
1051 *renderPass, // VkRenderPass renderPass;
1052 *framebuffer, // VkFramebuffer framebuffer;
1053 renderArea, // VkRect2D renderArea;
1054 1u, // uint32_t clearValueCount;
1055 &clearValue, // const VkClearValue* pClearValues;
1056 };
1057 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1058
1059 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines.back());
1060 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1061 {
1062 const VkDeviceSize vertexBufferOffset = 0ull;
1063 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1064 }
1065
1066 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1067 vk.cmdEndRenderPass(*cmdBuffer);
1068
1069 // Prepare checksum image for copy
1070 {
1071 const VkImageMemoryBarrier barriers[] =
1072 {
1073 {
1074 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1075 DE_NULL, // const void* pNext;
1076 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1077 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1078 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1079 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1080 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1081 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1082 *checksumImage, // VkImage image;
1083 makeColorSubresourceRange(0, 1), // VkImageSubresourceRange subresourceRange;
1084 },
1085 };
1086
1087 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1088 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1089 }
1090 // Checksum image -> host buffer
1091 {
1092 const VkBufferImageCopy region =
1093 {
1094 0ull, // VkDeviceSize bufferOffset;
1095 0u, // uint32_t bufferRowLength;
1096 0u, // uint32_t bufferImageHeight;
1097 makeColorSubresourceLayers(0, 1), // VkImageSubresourceLayers imageSubresource;
1098 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1099 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D imageExtent;
1100 };
1101
1102 vk.cmdCopyImageToBuffer(*cmdBuffer, *checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *checksumBuffer, 1u, ®ion);
1103 }
1104 // Buffer write barrier
1105 {
1106 const VkBufferMemoryBarrier barriers[] =
1107 {
1108 {
1109 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1110 DE_NULL, // const void* pNext;
1111 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1112 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
1113 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
1114 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
1115 *checksumBuffer, // VkBuffer buffer;
1116 0ull, // VkDeviceSize offset;
1117 checksumBufferSize, // VkDeviceSize size;
1118 },
1119 };
1120
1121 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1122 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1123 }
1124
1125 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1126 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1127
1128 // Verify result
1129
1130 {
1131 invalidateMappedMemoryRange(vk, device, checksumBufferAlloc->getMemory(), 0ull, checksumBufferSize);
1132
1133 const tcu::ConstPixelBufferAccess access(mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1134 const int numExpectedChecksum = getNumSamples(caseDef.numSamples) * caseDef.numLayers;
1135
1136 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1137 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1138 {
1139 if (access.getPixelInt(x, y).x() != numExpectedChecksum)
1140 return tcu::TestStatus::fail("Some samples have incorrect color");
1141 }
1142 }
1143 }
1144
1145 return tcu::TestStatus::pass("OK");
1146 }
1147
1148 } // SampledImage ns
1149
1150 namespace StorageImage
1151 {
1152
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)1153 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1154 {
1155 // Vertex & fragment
1156
1157 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1158
1159 // Compute
1160 {
1161 const std::string imageTypeStr = getShaderMultisampledImageType(mapVkFormat(caseDef.colorFormat), caseDef.numLayers);
1162 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(caseDef.colorFormat));
1163 const std::string signednessPrefix = isUintFormat(caseDef.colorFormat) ? "u" : isIntFormat(caseDef.colorFormat) ? "i" : "";
1164 const std::string gvec4Expr = signednessPrefix + "vec4";
1165 const std::string texelCoordStr = (caseDef.numLayers == 1 ? "ivec2(gx, gy)" : "ivec3(gx, gy, gz)");
1166
1167 std::ostringstream src;
1168 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1169 << "layout(local_size_x = 1) in;\n"
1170 << "layout(set = 0, binding = 0, " << formatQualifierStr << ") uniform " << imageTypeStr << " u_msImage;\n"
1171 << "\n"
1172 << "void main(void)\n"
1173 << "{\n"
1174 << " int gx = int(gl_GlobalInvocationID.x);\n"
1175 << " int gy = int(gl_GlobalInvocationID.y);\n"
1176 << " int gz = int(gl_GlobalInvocationID.z);\n"
1177 << "\n"
1178 << " " << gvec4Expr << " prevColor = imageLoad(u_msImage, " << texelCoordStr << ", 0);\n"
1179 << " for (int sampleNdx = 1; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1180 << " " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n"
1181 << " imageStore(u_msImage, " << texelCoordStr <<", sampleNdx, prevColor);\n"
1182 << " prevColor = color;\n"
1183 << " }\n"
1184 << " imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n"
1185 << "}\n";
1186
1187 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1188 }
1189 }
1190
1191 //! Render a MS image, resolve it, and copy result to resolveBuffer.
renderAndResolve(Context & context,const CaseDef & caseDef,const VkBuffer resolveBuffer,const bool useComputePass)1192 void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass)
1193 {
1194 const DeviceInterface& vk = context.getDeviceInterface();
1195 const VkDevice device = context.getDevice();
1196 const VkQueue queue = context.getUniversalQueue();
1197 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1198 Allocator& allocator = context.getDefaultAllocator();
1199
1200 // Multisampled color image
1201 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples,
1202 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1203 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1204
1205 const Unique<VkImage> resolveImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, VK_SAMPLE_COUNT_1_BIT,
1206 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1207 const UniquePtr<Allocation> resolveImageAlloc (bindImage(vk, device, allocator, *resolveImage, MemoryRequirement::Any));
1208
1209 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex));
1210 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1211
1212 // Working image barrier, we change it based on which rendering stages were executed so far.
1213 VkImageMemoryBarrier colorImageBarrier =
1214 {
1215 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1216 DE_NULL, // const void* pNext;
1217 (VkAccessFlags)0, // VkAccessFlags outputMask;
1218 (VkAccessFlags)0, // VkAccessFlags inputMask;
1219 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1220 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout newLayout;
1221 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1222 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1223 *colorImage, // VkImage image;
1224 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1225 };
1226
1227 // Pass 1: Render an image
1228 {
1229 renderMultisampledImage(context, caseDef, *colorImage);
1230
1231 colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1232 colorImageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1233 }
1234
1235 // Pass 2: Compute shader
1236 if (useComputePass)
1237 {
1238 // Descriptors
1239
1240 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1241 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1242 .build(vk, device));
1243
1244 Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1245 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1246 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1247
1248 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage,
1249 (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY),
1250 caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1251 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1252 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_GENERAL);
1253
1254 DescriptorSetUpdateBuilder()
1255 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1256 .update(vk, device);
1257
1258 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1259 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp"), 0));
1260 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1261
1262 beginCommandBuffer(vk, *cmdBuffer);
1263
1264 // Image layout for load/stores
1265 {
1266 colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1267 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1268
1269 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1270 0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
1271
1272 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1273 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1274 }
1275 // Dispatch
1276 {
1277 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1278 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1279 vk.cmdDispatch(*cmdBuffer, caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers);
1280 }
1281
1282 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1283 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1284 }
1285
1286 // Resolve and verify the image
1287 {
1288 beginCommandBuffer(vk, *cmdBuffer);
1289
1290 // Prepare for resolve
1291 {
1292 colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1293 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1294
1295 const VkImageMemoryBarrier barriers[] =
1296 {
1297 colorImageBarrier,
1298 {
1299 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1300 DE_NULL, // const void* pNext;
1301 (VkAccessFlags)0, // VkAccessFlags outputMask;
1302 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags inputMask;
1303 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1304 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1305 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1306 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1307 *resolveImage, // VkImage image;
1308 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1309 },
1310 };
1311
1312 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1313 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1314
1315 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1316 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1317 }
1318 // Resolve the image
1319 {
1320 const VkImageResolve resolveRegion =
1321 {
1322 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource;
1323 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
1324 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource;
1325 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
1326 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D extent;
1327 };
1328
1329 vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion);
1330 }
1331 // Prepare resolve image for copy
1332 {
1333 const VkImageMemoryBarrier barriers[] =
1334 {
1335 {
1336 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1337 DE_NULL, // const void* pNext;
1338 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags outputMask;
1339 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask;
1340 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1341 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1342 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1343 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1344 *resolveImage, // VkImage image;
1345 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1346 },
1347 };
1348
1349 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1350 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1351 }
1352 // Copy resolved image to host-readable buffer
1353 {
1354 const VkBufferImageCopy copyRegion =
1355 {
1356 0ull, // VkDeviceSize bufferOffset;
1357 0u, // uint32_t bufferRowLength;
1358 0u, // uint32_t bufferImageHeight;
1359 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers imageSubresource;
1360 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
1361 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D imageExtent;
1362 };
1363
1364 vk.cmdCopyImageToBuffer(*cmdBuffer, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resolveBuffer, 1u, ©Region);
1365 }
1366
1367 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1368 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1369 }
1370 }
1371
1372 //! Exact image compare, but allow for some error when color format is integer.
compareImages(tcu::TestLog & log,const CaseDef & caseDef,const tcu::ConstPixelBufferAccess layeredReferenceImage,const tcu::ConstPixelBufferAccess layeredActualImage)1373 bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage)
1374 {
1375 DE_ASSERT(caseDef.numSamples > 1);
1376
1377 const Vec4 goodColor = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1378 const Vec4 badColor = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1379 const bool isAnyIntFormat = isIntFormat(caseDef.colorFormat) || isUintFormat(caseDef.colorFormat);
1380
1381 // 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.
1382 const int badPixelTolerance = (isAnyIntFormat ? 2 * caseDef.renderSize.x() : 0);
1383 int goodLayers = 0;
1384
1385 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1386 {
1387 const tcu::ConstPixelBufferAccess referenceImage = tcu::getSubregion(layeredReferenceImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1388 const tcu::ConstPixelBufferAccess actualImage = tcu::getSubregion(layeredActualImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1389 const std::string imageName = "color layer " + de::toString(layerNdx);
1390
1391 tcu::TextureLevel errorMaskStorage (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), caseDef.renderSize.x(), caseDef.renderSize.y());
1392 tcu::PixelBufferAccess errorMask = errorMaskStorage.getAccess();
1393 int numBadPixels = 0;
1394
1395 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1396 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1397 {
1398 if (isAnyIntFormat && (referenceImage.getPixelInt(x, y) == actualImage.getPixelInt(x, y)))
1399 errorMask.setPixel(goodColor, x, y);
1400 else if (referenceImage.getPixel(x, y) == actualImage.getPixel(x, y))
1401 errorMask.setPixel(goodColor, x, y);
1402 else
1403 {
1404 ++numBadPixels;
1405 errorMask.setPixel(badColor, x, y);
1406 }
1407 }
1408
1409 if (numBadPixels <= badPixelTolerance)
1410 {
1411 ++goodLayers;
1412
1413 log << tcu::TestLog::ImageSet(imageName, imageName)
1414 << tcu::TestLog::Image("Result", "Result", actualImage)
1415 << tcu::TestLog::EndImageSet;
1416 }
1417 else
1418 {
1419 log << tcu::TestLog::ImageSet(imageName, imageName)
1420 << tcu::TestLog::Image("Result", "Result", actualImage)
1421 << tcu::TestLog::Image("Reference", "Reference", referenceImage)
1422 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
1423 << tcu::TestLog::EndImageSet;
1424 }
1425 }
1426
1427 if (goodLayers == caseDef.numLayers)
1428 {
1429 log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage;
1430 return true;
1431 }
1432 else
1433 {
1434 log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage;
1435 return false;
1436 }
1437 }
1438
test(Context & context,const CaseDef caseDef)1439 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1440 {
1441 const DeviceInterface& vk = context.getDeviceInterface();
1442 const InstanceInterface& vki = context.getInstanceInterface();
1443 const VkDevice device = context.getDevice();
1444 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
1445 Allocator& allocator = context.getDefaultAllocator();
1446
1447 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
1448
1449 {
1450 tcu::TestLog& log = context.getTestContext().getLog();
1451 log << tcu::LogSection("Description", "")
1452 << tcu::TestLog::Message << "Rendering to a multisampled image. Image will be processed with a compute shader using OpImageRead and OpImageWrite." << tcu::TestLog::EndMessage
1453 << 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
1454 << tcu::TestLog::EndSection;
1455 }
1456
1457 // Host-readable buffer
1458 const VkDeviceSize resolveBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
1459 const Unique<VkBuffer> resolveImageOneBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1460 const UniquePtr<Allocation> resolveImageOneBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageOneBuffer, MemoryRequirement::HostVisible));
1461 const Unique<VkBuffer> resolveImageTwoBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1462 const UniquePtr<Allocation> resolveImageTwoBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageTwoBuffer, MemoryRequirement::HostVisible));
1463
1464 zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize);
1465 zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize);
1466
1467 // Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy).
1468 {
1469 renderAndResolve(context, caseDef, *resolveImageOneBuffer, false); // Pass 1: render a basic multisampled image
1470 renderAndResolve(context, caseDef, *resolveImageTwoBuffer, true); // Pass 2: the same but altered with a compute shader
1471 }
1472
1473 // Verify
1474 {
1475 invalidateMappedMemoryRange(vk, device, resolveImageOneBufferAlloc->getMemory(), resolveImageOneBufferAlloc->getOffset(), resolveBufferSize);
1476 invalidateMappedMemoryRange(vk, device, resolveImageTwoBufferAlloc->getMemory(), resolveImageTwoBufferAlloc->getOffset(), resolveBufferSize);
1477
1478 const tcu::PixelBufferAccess layeredImageOne (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageOneBufferAlloc->getHostPtr());
1479 const tcu::ConstPixelBufferAccess layeredImageTwo (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageTwoBufferAlloc->getHostPtr());
1480
1481 // Check all layers
1482 if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo))
1483 return tcu::TestStatus::fail("Rendered images are not correct");
1484 }
1485
1486 return tcu::TestStatus::pass("OK");
1487 }
1488
1489 } // StorageImage ns
1490
getSizeLayerString(const IVec2 & size,const int numLayers)1491 std::string getSizeLayerString (const IVec2& size, const int numLayers)
1492 {
1493 std::ostringstream str;
1494 str << size.x() << "x" << size.y() << "_" << numLayers;
1495 return str.str();
1496 }
1497
getFormatString(const VkFormat format)1498 std::string getFormatString (const VkFormat format)
1499 {
1500 std::string name(getFormatName(format));
1501 return de::toLower(name.substr(10));
1502 }
1503
addTestCasesWithFunctions(tcu::TestCaseGroup * group,FunctionPrograms1<CaseDef>::Function initPrograms,FunctionInstance1<CaseDef>::Function testFunc)1504 void addTestCasesWithFunctions (tcu::TestCaseGroup* group,
1505 FunctionPrograms1<CaseDef>::Function initPrograms,
1506 FunctionInstance1<CaseDef>::Function testFunc)
1507 {
1508 const IVec2 size[] =
1509 {
1510 IVec2(64, 64),
1511 IVec2(79, 31),
1512 };
1513 const int numLayers[] =
1514 {
1515 1, 4
1516 };
1517 const VkSampleCountFlagBits samples[] =
1518 {
1519 VK_SAMPLE_COUNT_2_BIT,
1520 VK_SAMPLE_COUNT_4_BIT,
1521 VK_SAMPLE_COUNT_8_BIT,
1522 VK_SAMPLE_COUNT_16_BIT,
1523 VK_SAMPLE_COUNT_32_BIT,
1524 VK_SAMPLE_COUNT_64_BIT,
1525 };
1526 const VkFormat format[] =
1527 {
1528 VK_FORMAT_R8G8B8A8_UNORM,
1529 VK_FORMAT_R32_UINT,
1530 VK_FORMAT_R16G16_SINT,
1531 VK_FORMAT_R32G32B32A32_SFLOAT,
1532 };
1533
1534 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx)
1535 for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx)
1536 {
1537 MovePtr<tcu::TestCaseGroup> sizeLayerGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeLayerString(size[sizeNdx], numLayers[layerNdx]).c_str(), ""));
1538 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1539 {
1540 MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str(), ""));
1541 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
1542 {
1543 std::ostringstream caseName;
1544 caseName << "samples_" << getNumSamples(samples[samplesNdx]);
1545
1546 const CaseDef caseDef =
1547 {
1548 size[sizeNdx], // IVec2 renderSize;
1549 numLayers[layerNdx], // int numLayers;
1550 format[formatNdx], // VkFormat colorFormat;
1551 samples[samplesNdx], // VkSampleCountFlagBits numSamples;
1552 };
1553
1554 addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), "", initPrograms, testFunc, caseDef);
1555 }
1556 sizeLayerGroup->addChild(formatGroup.release());
1557 }
1558 group->addChild(sizeLayerGroup.release());
1559 }
1560 }
1561
createSampledImageTestsInGroup(tcu::TestCaseGroup * group)1562 void createSampledImageTestsInGroup (tcu::TestCaseGroup* group)
1563 {
1564 addTestCasesWithFunctions(group, SampledImage::initPrograms, SampledImage::test);
1565 }
1566
createStorageImageTestsInGroup(tcu::TestCaseGroup * group)1567 void createStorageImageTestsInGroup (tcu::TestCaseGroup* group)
1568 {
1569 addTestCasesWithFunctions(group, StorageImage::initPrograms, StorageImage::test);
1570 }
1571
1572 } // anonymous ns
1573
1574 //! Render to a multisampled image and sample from it in a fragment shader.
createMultisampleSampledImageTests(tcu::TestContext & testCtx)1575 tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx)
1576 {
1577 return createTestGroup(testCtx, "sampled_image", "Multisampled image direct sample access", createSampledImageTestsInGroup);
1578 }
1579
1580 //! Render to a multisampled image and access it with load/stores in a compute shader.
createMultisampleStorageImageTests(tcu::TestContext & testCtx)1581 tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx)
1582 {
1583 return createTestGroup(testCtx, "storage_image", "Multisampled image draw and read/write in compute shader", createStorageImageTestsInGroup);
1584 }
1585
1586 } // pipeline
1587 } // vkt
1588