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 #include "tcuTestLog.hpp"
41
42 #include "deUniquePtr.hpp"
43 #include "deSharedPtr.hpp"
44
45 #include <string>
46
47 namespace vkt
48 {
49 namespace pipeline
50 {
51 namespace
52 {
53 using namespace vk;
54 using de::UniquePtr;
55 using de::MovePtr;
56 using de::SharedPtr;
57 using tcu::IVec2;
58 using tcu::Vec4;
59
60 typedef SharedPtr<Unique<VkImageView> > ImageViewSp;
61 typedef SharedPtr<Unique<VkPipeline> > PipelineSp;
62
63 //! Test case parameters
64 struct CaseDef
65 {
66 IVec2 renderSize;
67 int numLayers;
68 VkFormat colorFormat;
69 VkSampleCountFlagBits numSamples;
70 };
71
72 template<typename T>
makeSharedPtr(Move<T> move)73 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
74 {
75 return SharedPtr<Unique<T> >(new Unique<T>(move));
76 }
77
78 template<typename T>
sizeInBytes(const std::vector<T> & vec)79 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
80 {
81 return vec.size() * sizeof(vec[0]);
82 }
83
84 //! 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)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)
95 {
96 const VkVertexInputBindingDescription vertexInputBindingDescription =
97 {
98 0u, // uint32_t binding;
99 sizeof(Vertex4RGBA), // uint32_t stride;
100 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
101 };
102
103 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
104 {
105 {
106 0u, // uint32_t location;
107 0u, // uint32_t binding;
108 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
109 0u, // uint32_t offset;
110 },
111 {
112 1u, // uint32_t location;
113 0u, // uint32_t binding;
114 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
115 sizeof(Vec4), // uint32_t offset;
116 },
117 };
118
119 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
120 {
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;
128 };
129
130 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
131 {
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;
137 };
138
139 const VkViewport viewport = makeViewport(
140 0.0f, 0.0f,
141 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
142 0.0f, 1.0f);
143
144 const VkRect2D scissor = {
145 makeOffset2D(0, 0),
146 makeExtent2D(renderSize.x(), renderSize.y()),
147 };
148
149 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
150 {
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;
158 };
159
160 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
161 {
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;
175 };
176
177 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
178 {
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;
188 };
189
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
195 0u, // compare mask
196 0u, // write mask
197 0u); // reference
198
199 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
200 {
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;
213 };
214
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 =
218 {
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;
227 };
228
229 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
230 {
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];
239 };
240
241 const VkPipelineShaderStageCreateInfo pShaderStages[] =
242 {
243 {
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;
251 },
252 {
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;
260 }
261 };
262
263 DE_ASSERT(numSubpasses > 0u);
264
265 std::vector<VkGraphicsPipelineCreateInfo> graphicsPipelineInfos (0);
266 std::vector<VkPipeline> rawPipelines (numSubpasses, DE_NULL);
267
268 {
269 const VkPipelineCreateFlags firstPipelineFlags = (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
270 : (VkPipelineCreateFlagBits)0);
271
272 VkGraphicsPipelineCreateInfo createInfo =
273 {
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;
293 };
294
295 graphicsPipelineInfos.push_back(createInfo);
296
297 createInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
298 createInfo.basePipelineIndex = 0;
299
300 for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx)
301 {
302 createInfo.subpass = subpassNdx;
303 graphicsPipelineInfos.push_back(createInfo);
304 }
305 }
306
307 VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0]));
308
309 std::vector<PipelineSp> pipelines;
310
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))));
313
314 return pipelines;
315 }
316
317 //! 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)318 Move<VkRenderPass> makeMultisampleRenderPass (const DeviceInterface& vk,
319 const VkDevice device,
320 const VkFormat colorFormat,
321 const VkSampleCountFlagBits numSamples,
322 const deUint32 numLayers)
323 {
324 const VkAttachmentDescription colorAttachmentDescription =
325 {
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;
335 };
336 const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
337
338 // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
339
340 std::vector<VkAttachmentReference> colorAttachmentReferences(numLayers);
341 std::vector<VkSubpassDescription> subpasses;
342
343 for (deUint32 i = 0; i < numLayers; ++i)
344 {
345 const VkAttachmentReference attachmentRef =
346 {
347 i, // deUint32 attachment;
348 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
349 };
350 colorAttachmentReferences[i] = attachmentRef;
351
352 const VkSubpassDescription subpassDescription =
353 {
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;
364 };
365 subpasses.push_back(subpassDescription);
366 }
367
368 const VkRenderPassCreateInfo renderPassInfo =
369 {
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;
379 };
380
381 return createRenderPass(vk, device, &renderPassInfo);
382 }
383
384 //! A single-attachment, single-subpass render pass.
makeSimpleRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)385 Move<VkRenderPass> makeSimpleRenderPass (const DeviceInterface& vk,
386 const VkDevice device,
387 const VkFormat colorFormat)
388 {
389 const VkAttachmentDescription colorAttachmentDescription =
390 {
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;
400 };
401
402 const VkAttachmentReference colorAttachmentRef =
403 {
404 0u, // deUint32 attachment;
405 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
406 };
407
408 const VkSubpassDescription subpassDescription =
409 {
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;
420 };
421
422 const VkRenderPassCreateInfo renderPassInfo =
423 {
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;
433 };
434
435 return createRenderPass(vk, device, &renderPassInfo);
436 }
437
makeImage(const DeviceInterface & vk,const VkDevice device,const VkFormat format,const IVec2 & size,const deUint32 numLayers,const VkSampleCountFlagBits samples,const VkImageUsageFlags usage)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)
439 {
440 const VkImageCreateInfo imageParams =
441 {
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;
457 };
458 return createImage(vk, device, &imageParams);
459 }
460
461 //! Make a simplest sampler.
makeSampler(const DeviceInterface & vk,const VkDevice device)462 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
463 {
464 const VkSamplerCreateInfo samplerParams =
465 {
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;
484 };
485 return createSampler(vk, device, &samplerParams);
486 }
487
makeBuffer(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)488 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
489 {
490 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
491 return createBuffer(vk, device, &bufferCreateInfo);
492 }
493
makeColorSubresourceRange(const int baseArrayLayer,const int layerCount)494 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
495 {
496 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
497 }
498
makeColorSubresourceLayers(const int baseArrayLayer,const int layerCount)499 inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount)
500 {
501 return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
502 }
503
checkImageFormatRequirements(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const VkSampleCountFlagBits sampleCount,const VkFormat format,const VkImageUsageFlags usage)504 void checkImageFormatRequirements (const InstanceInterface& vki,
505 const VkPhysicalDevice physDevice,
506 const VkSampleCountFlagBits sampleCount,
507 const VkFormat format,
508 const VkImageUsageFlags usage)
509 {
510 VkPhysicalDeviceFeatures features;
511 vki.getPhysicalDeviceFeatures(physDevice, &features);
512
513 if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample)
514 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
515
516 VkImageFormatProperties imageFormatProperties;
517 const VkResult imageFormatResult = vki.getPhysicalDeviceImageFormatProperties(
518 physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties);
519
520 if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
521 TCU_THROW(NotSupportedError, "Image format is not supported");
522
523 if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount)
524 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
525 }
526
zeroBuffer(const DeviceInterface & vk,const VkDevice device,const Allocation & alloc,const VkDeviceSize bufferSize)527 void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize bufferSize)
528 {
529 deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(bufferSize));
530 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
531 }
532
533 //! The default foreground color.
getPrimitiveColor(void)534 inline Vec4 getPrimitiveColor (void)
535 {
536 return Vec4(1.0f, 0.0f, 0.0f, 1.0f);
537 }
538
539 //! Get a reference clear value based on color format.
getClearValue(const VkFormat format)540 VkClearValue getClearValue (const VkFormat format)
541 {
542 if (isUintFormat(format) || isIntFormat(format))
543 return makeClearValueColorU32(16, 32, 64, 96);
544 else
545 return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f);
546 }
547
getColorFormatStr(const int numComponents,const bool isUint,const bool isSint)548 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
549 {
550 std::ostringstream str;
551 if (numComponents == 1)
552 str << (isUint ? "uint" : isSint ? "int" : "float");
553 else
554 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
555
556 return str.str();
557 }
558
getSamplerTypeStr(const int numLayers,const bool isUint,const bool isSint)559 std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint)
560 {
561 std::ostringstream str;
562 str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : "");
563 return str.str();
564 }
565
566 //! Generate a gvec4 color literal.
567 template<typename T>
getColorStr(const T * data,int numComponents,const bool isUint,const bool isSint)568 std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint)
569 {
570 const int maxIndex = 3; // 4 components max
571
572 std::ostringstream str;
573 str << (isUint ? "u" : isSint ? "i" : "") << "vec4(";
574
575 for (int i = 0; i < numComponents; ++i)
576 {
577 str << data[i]
578 << (i < maxIndex ? ", " : "");
579 }
580
581 for (int i = numComponents; i < maxIndex + 1; ++i)
582 {
583 str << (i == maxIndex ? 1 : 0)
584 << (i < maxIndex ? ", " : "");
585 }
586
587 str << ")";
588 return str.str();
589 }
590
591 //! Clear color literal value used by the sampling shader.
getReferenceClearColorStr(const VkFormat format,const int numComponents,const bool isUint,const bool isSint)592 std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint)
593 {
594 const VkClearColorValue clearColor = getClearValue(format).color;
595 if (isUint)
596 return getColorStr(clearColor.uint32, numComponents, isUint, isSint);
597 else if (isSint)
598 return getColorStr(clearColor.int32, numComponents, isUint, isSint);
599 else
600 return getColorStr(clearColor.float32, numComponents, isUint, isSint);
601 }
602
603 //! Primitive color literal value used by the sampling shader.
getReferencePrimitiveColorStr(int numComponents,const bool isUint,const bool isSint)604 std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint)
605 {
606 const Vec4 color = getPrimitiveColor();
607 return getColorStr(color.getPtr(), numComponents, isUint, isSint);
608 }
609
getNumSamples(const VkSampleCountFlagBits samples)610 inline int getNumSamples (const VkSampleCountFlagBits samples)
611 {
612 return static_cast<int>(samples); // enum bitmask actually matches the number of samples
613 }
614
615 //! A flat-colored shape with sharp angles to make antialiasing visible.
genTriangleVertices(void)616 std::vector<Vertex4RGBA> genTriangleVertices (void)
617 {
618 static const Vertex4RGBA data[] =
619 {
620 {
621 Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
622 getPrimitiveColor(),
623 },
624 {
625 Vec4(0.8f, 0.2f, 0.0f, 1.0f),
626 getPrimitiveColor(),
627 },
628 {
629 Vec4(0.8f, -0.2f, 0.0f, 1.0f),
630 getPrimitiveColor(),
631 },
632 };
633 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
634 }
635
636 //! A full-viewport quad. Use with TRIANGLE_STRIP topology.
genFullQuadVertices(void)637 std::vector<Vertex4RGBA> genFullQuadVertices (void)
638 {
639 static const Vertex4RGBA data[] =
640 {
641 {
642 Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
643 Vec4(), // unused
644 },
645 {
646 Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
647 Vec4(), // unused
648 },
649 {
650 Vec4(1.0f, -1.0f, 0.0f, 1.0f),
651 Vec4(), // unused
652 },
653 {
654 Vec4(1.0f, 1.0f, 0.0f, 1.0f),
655 Vec4(), // unused
656 },
657 };
658 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
659 }
660
getShaderImageFormatQualifier(const tcu::TextureFormat & format)661 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
662 {
663 const char* orderPart;
664 const char* typePart;
665
666 switch (format.order)
667 {
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;
672
673 default:
674 DE_ASSERT(false);
675 orderPart = DE_NULL;
676 }
677
678 switch (format.type)
679 {
680 case tcu::TextureFormat::FLOAT: typePart = "32f"; break;
681 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break;
682
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;
686
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;
690
691 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break;
692 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break;
693
694 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break;
695 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break;
696
697 default:
698 DE_ASSERT(false);
699 typePart = DE_NULL;
700 }
701
702 return std::string() + orderPart + typePart;
703 }
704
getShaderMultisampledImageType(const tcu::TextureFormat & format,const int numLayers)705 std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers)
706 {
707 const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
708 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : "";
709
710 std::ostringstream str;
711 str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : "");
712
713 return str.str();
714 }
715
addSimpleVertexAndFragmentPrograms(SourceCollections & programCollection,const CaseDef caseDef)716 void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
717 {
718 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
719 const bool isUint = isUintFormat(caseDef.colorFormat);
720 const bool isSint = isIntFormat(caseDef.colorFormat);
721
722 // Vertex shader
723 {
724 std::ostringstream src;
725 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
726 << "\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"
730 << "\n"
731 << "out gl_PerVertex {\n"
732 << " vec4 gl_Position;\n"
733 << "};\n"
734 << "\n"
735 << "void main(void)\n"
736 << "{\n"
737 << " gl_Position = in_position;\n"
738 << " o_color = in_color;\n"
739 << "}\n";
740
741 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
742 }
743
744 // Fragment shader
745 {
746 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
747
748 std::ostringstream src;
749 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
750 << "\n"
751 << "layout(location = 0) in vec4 in_color;\n"
752 << "layout(location = 0) out " << colorFormat << " o_color;\n"
753 << "\n"
754 << "void main(void)\n"
755 << "{\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"
760 << "}\n";
761
762 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
763 }
764 }
765
766 //! Synchronously render to a multisampled color image.
renderMultisampledImage(Context & context,const CaseDef & caseDef,const VkImage colorImage)767 void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage)
768 {
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();
774
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));
777
778 const VkRect2D renderArea = {
779 makeOffset2D(0, 0),
780 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
781 };
782
783 {
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)
788 {
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());
792 }
793
794 // Vertex buffer
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));
799
800 {
801 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
802 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
803 }
804
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));
813
814 beginCommandBuffer(vk, *cmdBuffer);
815
816 const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat));
817
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;
826 };
827 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
828
829 {
830 const VkDeviceSize vertexBufferOffset = 0ull;
831 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
832 }
833
834 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
835 {
836 if (layerNdx != 0)
837 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
838
839 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
840
841 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
842 }
843
844 vk.cmdEndRenderPass(*cmdBuffer);
845
846 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
847 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
848 }
849 }
850
851 namespace SampledImage
852 {
853
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)854 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
855 {
856 // Pass 1: Render to texture
857
858 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
859
860 // Pass 2: Sample texture
861
862 // Vertex shader
863 {
864 std::ostringstream src;
865 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
866 << "\n"
867 << "layout(location = 0) in vec4 in_position;\n"
868 << "\n"
869 << "out gl_PerVertex {\n"
870 << " vec4 gl_Position;\n"
871 << "};\n"
872 << "\n"
873 << "void main(void)\n"
874 << "{\n"
875 << " gl_Position = in_position;\n"
876 << "}\n";
877
878 programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
879 }
880
881 // Fragment shader
882 {
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);
890
891 std::ostringstream src;
892 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
893 << "\n"
894 << "layout(location = 0) out int o_status;\n"
895 << "\n"
896 << "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n"
897 << "\n"
898 << "void main(void)\n"
899 << "{\n"
900 << " int checksum = 0;\n"
901 << "\n";
902
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"
907 << " ++checksum;\n"
908 << " }\n";
909 else
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"
914 << " ++checksum;\n"
915 << " }\n";
916
917 src << "\n"
918 << " o_status = checksum;\n"
919 << "}\n";
920
921 programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
922 }
923 }
924
test(Context & context,const CaseDef caseDef)925 tcu::TestStatus test (Context& context, const CaseDef caseDef)
926 {
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();
934
935 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
936
937 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
938
939 {
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;
945 }
946
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));
950
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));
953
954 const VkRect2D renderArea = {
955 makeOffset2D(0, 0),
956 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
957 };
958
959 // Step 1: Render to texture
960 {
961 renderMultisampledImage(context, caseDef, *colorImage);
962 }
963
964 // Step 2: Sample texture
965 {
966 // Color image view
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));
970
971 // Checksum image
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)));
977
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));
982
983 zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
984
985 // Vertex buffer
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));
990
991 {
992 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
993 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
994 }
995
996 // Descriptors
997 // \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
998
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));
1002
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));
1006
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);
1009
1010 DescriptorSetUpdateBuilder()
1011 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1012 .update(vk, device);
1013
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));
1022
1023 beginCommandBuffer(vk, *cmdBuffer);
1024
1025 // Prepare for sampling in the fragment shader
1026 {
1027 const VkImageMemoryBarrier barriers[] =
1028 {
1029 {
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;
1040 },
1041 };
1042
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);
1045 }
1046
1047 const VkClearValue clearValue = makeClearValueColorU32(0u, 0u, 0u, 0u);
1048
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;
1057 };
1058 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1059
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);
1062 {
1063 const VkDeviceSize vertexBufferOffset = 0ull;
1064 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1065 }
1066
1067 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1068 vk.cmdEndRenderPass(*cmdBuffer);
1069
1070 // Prepare checksum image for copy
1071 {
1072 const VkImageMemoryBarrier barriers[] =
1073 {
1074 {
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;
1085 },
1086 };
1087
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);
1090 }
1091 // Checksum image -> host buffer
1092 {
1093 const VkBufferImageCopy region =
1094 {
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;
1101 };
1102
1103 vk.cmdCopyImageToBuffer(*cmdBuffer, *checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *checksumBuffer, 1u, ®ion);
1104 }
1105 // Buffer write barrier
1106 {
1107 const VkBufferMemoryBarrier barriers[] =
1108 {
1109 {
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;
1119 },
1120 };
1121
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);
1124 }
1125
1126 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1127 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1128
1129 // Verify result
1130
1131 {
1132 invalidateMappedMemoryRange(vk, device, checksumBufferAlloc->getMemory(), 0ull, checksumBufferSize);
1133
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;
1136
1137 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1138 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1139 {
1140 if (access.getPixelInt(x, y).x() != numExpectedChecksum)
1141 return tcu::TestStatus::fail("Some samples have incorrect color");
1142 }
1143 }
1144 }
1145
1146 return tcu::TestStatus::pass("OK");
1147 }
1148
1149 } // SampledImage ns
1150
1151 namespace StorageImage
1152 {
1153
initPrograms(SourceCollections & programCollection,const CaseDef caseDef)1154 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1155 {
1156 // Vertex & fragment
1157
1158 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1159
1160 // Compute
1161 {
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)");
1167
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"
1172 << "\n"
1173 << "void main(void)\n"
1174 << "{\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"
1178 << "\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"
1184 << " }\n"
1185 << " imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n"
1186 << "}\n";
1187
1188 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1189 }
1190 }
1191
1192 //! Render a MS image, resolve it, and copy result to resolveBuffer.
renderAndResolve(Context & context,const CaseDef & caseDef,const VkBuffer resolveBuffer,const bool useComputePass)1193 void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass)
1194 {
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();
1200
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));
1205
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));
1209
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));
1212
1213 // Working image barrier, we change it based on which rendering stages were executed so far.
1214 VkImageMemoryBarrier colorImageBarrier =
1215 {
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;
1226 };
1227
1228 // Pass 1: Render an image
1229 {
1230 renderMultisampledImage(context, caseDef, *colorImage);
1231
1232 colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1233 colorImageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1234 }
1235
1236 // Pass 2: Compute shader
1237 if (useComputePass)
1238 {
1239 // Descriptors
1240
1241 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1242 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1243 .build(vk, device));
1244
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));
1248
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);
1254
1255 DescriptorSetUpdateBuilder()
1256 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1257 .update(vk, device);
1258
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));
1262
1263 beginCommandBuffer(vk, *cmdBuffer);
1264
1265 // Image layout for load/stores
1266 {
1267 colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1268 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1269
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);
1272
1273 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1274 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1275 }
1276 // Dispatch
1277 {
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);
1281 }
1282
1283 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1284 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1285 }
1286
1287 // Resolve and verify the image
1288 {
1289 beginCommandBuffer(vk, *cmdBuffer);
1290
1291 // Prepare for resolve
1292 {
1293 colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1294 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1295
1296 const VkImageMemoryBarrier barriers[] =
1297 {
1298 colorImageBarrier,
1299 {
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;
1310 },
1311 };
1312
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);
1315
1316 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1317 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1318 }
1319 // Resolve the image
1320 {
1321 const VkImageResolve resolveRegion =
1322 {
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;
1328 };
1329
1330 vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion);
1331 }
1332 // Prepare resolve image for copy
1333 {
1334 const VkImageMemoryBarrier barriers[] =
1335 {
1336 {
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;
1347 },
1348 };
1349
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);
1352 }
1353 // Copy resolved image to host-readable buffer
1354 {
1355 const VkBufferImageCopy copyRegion =
1356 {
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;
1363 };
1364
1365 vk.cmdCopyImageToBuffer(*cmdBuffer, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resolveBuffer, 1u, ©Region);
1366 }
1367
1368 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1369 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1370 }
1371 }
1372
1373 //! 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)1374 bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage)
1375 {
1376 DE_ASSERT(caseDef.numSamples > 1);
1377
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);
1381
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);
1384 int goodLayers = 0;
1385
1386 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1387 {
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);
1391
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;
1395
1396 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1397 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1398 {
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);
1403 else
1404 {
1405 ++numBadPixels;
1406 errorMask.setPixel(badColor, x, y);
1407 }
1408 }
1409
1410 if (numBadPixels <= badPixelTolerance)
1411 {
1412 ++goodLayers;
1413
1414 log << tcu::TestLog::ImageSet(imageName, imageName)
1415 << tcu::TestLog::Image("Result", "Result", actualImage)
1416 << tcu::TestLog::EndImageSet;
1417 }
1418 else
1419 {
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;
1425 }
1426 }
1427
1428 if (goodLayers == caseDef.numLayers)
1429 {
1430 log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage;
1431 return true;
1432 }
1433 else
1434 {
1435 log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage;
1436 return false;
1437 }
1438 }
1439
test(Context & context,const CaseDef caseDef)1440 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1441 {
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();
1447
1448 checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
1449
1450 {
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;
1456 }
1457
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));
1464
1465 zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize);
1466 zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize);
1467
1468 // Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy).
1469 {
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
1472 }
1473
1474 // Verify
1475 {
1476 invalidateMappedMemoryRange(vk, device, resolveImageOneBufferAlloc->getMemory(), resolveImageOneBufferAlloc->getOffset(), resolveBufferSize);
1477 invalidateMappedMemoryRange(vk, device, resolveImageTwoBufferAlloc->getMemory(), resolveImageTwoBufferAlloc->getOffset(), resolveBufferSize);
1478
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());
1481
1482 // Check all layers
1483 if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo))
1484 return tcu::TestStatus::fail("Rendered images are not correct");
1485 }
1486
1487 return tcu::TestStatus::pass("OK");
1488 }
1489
1490 } // StorageImage ns
1491
getSizeLayerString(const IVec2 & size,const int numLayers)1492 std::string getSizeLayerString (const IVec2& size, const int numLayers)
1493 {
1494 std::ostringstream str;
1495 str << size.x() << "x" << size.y() << "_" << numLayers;
1496 return str.str();
1497 }
1498
getFormatString(const VkFormat format)1499 std::string getFormatString (const VkFormat format)
1500 {
1501 std::string name(getFormatName(format));
1502 return de::toLower(name.substr(10));
1503 }
1504
addTestCasesWithFunctions(tcu::TestCaseGroup * group,FunctionPrograms1<CaseDef>::Function initPrograms,FunctionInstance1<CaseDef>::Function testFunc)1505 void addTestCasesWithFunctions (tcu::TestCaseGroup* group,
1506 FunctionPrograms1<CaseDef>::Function initPrograms,
1507 FunctionInstance1<CaseDef>::Function testFunc)
1508 {
1509 const IVec2 size[] =
1510 {
1511 IVec2(64, 64),
1512 IVec2(79, 31),
1513 };
1514 const int numLayers[] =
1515 {
1516 1, 4
1517 };
1518 const VkSampleCountFlagBits samples[] =
1519 {
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,
1526 };
1527 const VkFormat format[] =
1528 {
1529 VK_FORMAT_R8G8B8A8_UNORM,
1530 VK_FORMAT_R32_UINT,
1531 VK_FORMAT_R16G16_SINT,
1532 VK_FORMAT_R32G32B32A32_SFLOAT,
1533 };
1534
1535 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx)
1536 for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx)
1537 {
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)
1540 {
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)
1543 {
1544 std::ostringstream caseName;
1545 caseName << "samples_" << getNumSamples(samples[samplesNdx]);
1546
1547 const CaseDef caseDef =
1548 {
1549 size[sizeNdx], // IVec2 renderSize;
1550 numLayers[layerNdx], // int numLayers;
1551 format[formatNdx], // VkFormat colorFormat;
1552 samples[samplesNdx], // VkSampleCountFlagBits numSamples;
1553 };
1554
1555 addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), "", initPrograms, testFunc, caseDef);
1556 }
1557 sizeLayerGroup->addChild(formatGroup.release());
1558 }
1559 group->addChild(sizeLayerGroup.release());
1560 }
1561 }
1562
createSampledImageTestsInGroup(tcu::TestCaseGroup * group)1563 void createSampledImageTestsInGroup (tcu::TestCaseGroup* group)
1564 {
1565 addTestCasesWithFunctions(group, SampledImage::initPrograms, SampledImage::test);
1566 }
1567
createStorageImageTestsInGroup(tcu::TestCaseGroup * group)1568 void createStorageImageTestsInGroup (tcu::TestCaseGroup* group)
1569 {
1570 addTestCasesWithFunctions(group, StorageImage::initPrograms, StorageImage::test);
1571 }
1572
1573 } // anonymous ns
1574
1575 //! Render to a multisampled image and sample from it in a fragment shader.
createMultisampleSampledImageTests(tcu::TestContext & testCtx)1576 tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx)
1577 {
1578 return createTestGroup(testCtx, "sampled_image", "Multisampled image direct sample access", createSampledImageTestsInGroup);
1579 }
1580
1581 //! Render to a multisampled image and access it with load/stores in a compute shader.
createMultisampleStorageImageTests(tcu::TestContext & testCtx)1582 tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx)
1583 {
1584 return createTestGroup(testCtx, "storage_image", "Multisampled image draw and read/write in compute shader", createStorageImageTestsInGroup);
1585 }
1586
1587 } // pipeline
1588 } // vkt
1589