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