1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Multisample image Tests
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktPipelineMultisampleImageTests.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32
33 #include "vkMemUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkPrograms.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTestLog.hpp"
45
46 #include "deUniquePtr.hpp"
47 #include "deSharedPtr.hpp"
48
49 #include <string>
50
51 namespace vkt
52 {
53 namespace pipeline
54 {
55 namespace
56 {
57 using namespace vk;
58 using de::UniquePtr;
59 using de::MovePtr;
60 using de::SharedPtr;
61 using tcu::IVec2;
62 using tcu::Vec4;
63
64 typedef SharedPtr<Unique<VkImageView> > ImageViewSp;
65 typedef SharedPtr<Unique<VkPipeline> > PipelineSp;
66
67 //! Test case parameters
68 struct CaseDef
69 {
70 PipelineConstructionType pipelineConstructionType;
71 IVec2 renderSize;
72 int numLayers;
73 VkFormat colorFormat;
74 VkSampleCountFlagBits numSamples;
75 bool colorSamples;
76 };
77
78 template<typename T>
makeSharedPtr(Move<T> move)79 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
80 {
81 return SharedPtr<Unique<T> >(new Unique<T>(move));
82 }
83
84 template<typename T>
sizeInBytes(const std::vector<T>& vec)85 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
86 {
87 return vec.size() * sizeof(vec[0]);
88 }
89
90 //! 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 ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const IVec2 renderSize, const VkSampleCountFlagBits numSamples, const VkPrimitiveTopology topology)91 std::vector<PipelineSp> makeGraphicsPipelines (const DeviceInterface& vk,
92 const VkDevice device,
93 const deUint32 numSubpasses,
94 const VkPipelineLayout pipelineLayout,
95 const VkRenderPass renderPass,
96 const ShaderWrapper vertexModule,
97 const ShaderWrapper fragmentModule,
98 const IVec2 renderSize,
99 const VkSampleCountFlagBits numSamples,
100 const VkPrimitiveTopology topology)
101 {
102 const VkVertexInputBindingDescription vertexInputBindingDescription =
103 {
104 0u, // uint32_t binding;
105 sizeof(Vertex4RGBA), // uint32_t stride;
106 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
107 };
108
109 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
110 {
111 {
112 0u, // uint32_t location;
113 0u, // uint32_t binding;
114 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
115 0u, // uint32_t offset;
116 },
117 {
118 1u, // uint32_t location;
119 0u, // uint32_t binding;
120 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
121 sizeof(Vec4), // uint32_t offset;
122 },
123 };
124
125 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
126 {
127 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
128 DE_NULL, // const void* pNext;
129 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
130 1u, // uint32_t vertexBindingDescriptionCount;
131 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
132 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
133 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
134 };
135
136 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
137 {
138 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
139 DE_NULL, // const void* pNext;
140 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
141 topology, // VkPrimitiveTopology topology;
142 VK_FALSE, // VkBool32 primitiveRestartEnable;
143 };
144
145 const VkViewport viewport = makeViewport(renderSize);
146 const VkRect2D scissor = makeRect2D(renderSize);
147
148 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
149 {
150 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
151 DE_NULL, // const void* pNext;
152 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags;
153 1u, // uint32_t viewportCount;
154 &viewport, // const VkViewport* pViewports;
155 1u, // uint32_t scissorCount;
156 &scissor, // const VkRect2D* pScissors;
157 };
158
159 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
160 {
161 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
162 DE_NULL, // const void* pNext;
163 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
164 VK_FALSE, // VkBool32 depthClampEnable;
165 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
166 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
167 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
168 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
169 VK_FALSE, // VkBool32 depthBiasEnable;
170 0.0f, // float depthBiasConstantFactor;
171 0.0f, // float depthBiasClamp;
172 0.0f, // float depthBiasSlopeFactor;
173 1.0f, // float lineWidth;
174 };
175
176 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
177 {
178 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
179 DE_NULL, // const void* pNext;
180 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
181 numSamples, // VkSampleCountFlagBits rasterizationSamples;
182 VK_FALSE, // VkBool32 sampleShadingEnable;
183 0.0f, // float minSampleShading;
184 DE_NULL, // const VkSampleMask* pSampleMask;
185 VK_FALSE, // VkBool32 alphaToCoverageEnable;
186 VK_FALSE // VkBool32 alphaToOneEnable;
187 };
188
189 const VkStencilOpState stencilOpState = makeStencilOpState(
190 VK_STENCIL_OP_KEEP, // stencil fail
191 VK_STENCIL_OP_KEEP, // depth & stencil pass
192 VK_STENCIL_OP_KEEP, // depth only fail
193 VK_COMPARE_OP_ALWAYS, // compare op
194 0u, // compare mask
195 0u, // write mask
196 0u); // reference
197
198 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
199 {
200 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
201 DE_NULL, // const void* pNext;
202 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags;
203 VK_FALSE, // VkBool32 depthTestEnable;
204 VK_FALSE, // VkBool32 depthWriteEnable;
205 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
206 VK_FALSE, // VkBool32 depthBoundsTestEnable;
207 VK_FALSE, // VkBool32 stencilTestEnable;
208 stencilOpState, // VkStencilOpState front;
209 stencilOpState, // VkStencilOpState back;
210 0.0f, // float minDepthBounds;
211 1.0f, // float maxDepthBounds;
212 };
213
214 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
215 // Number of blend attachments must equal the number of color attachments during any subpass.
216 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
217 {
218 VK_FALSE, // VkBool32 blendEnable;
219 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
220 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
221 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
222 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
223 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
224 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
225 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
226 };
227
228 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
229 {
230 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
231 DE_NULL, // const void* pNext;
232 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
233 VK_FALSE, // VkBool32 logicOpEnable;
234 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
235 1u, // deUint32 attachmentCount;
236 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
237 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
238 };
239
240 const VkPipelineShaderStageCreateInfo pShaderStages[] =
241 {
242 {
243 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
244 DE_NULL, // const void* pNext;
245 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
246 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
247 vertexModule.getModule(), // VkShaderModule module;
248 "main", // const char* pName;
249 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
250 },
251 {
252 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
253 DE_NULL, // const void* pNext;
254 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags;
255 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
256 fragmentModule.getModule(), // VkShaderModule module;
257 "main", // const char* pName;
258 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
259 }
260 };
261
262 DE_ASSERT(numSubpasses > 0u);
263
264 std::vector<VkGraphicsPipelineCreateInfo> graphicsPipelineInfos (0);
265 std::vector<VkPipeline> rawPipelines (numSubpasses, DE_NULL);
266
267 {
268 #ifndef CTS_USES_VULKANSC
269 const VkPipelineCreateFlags firstPipelineFlags = (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
270 : VkPipelineCreateFlagBits(0));
271 #else
272 const VkPipelineCreateFlags firstPipelineFlags = VkPipelineCreateFlagBits(0);
273 #endif // CTS_USES_VULKANSC
274
275 VkGraphicsPipelineCreateInfo createInfo =
276 {
277 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
278 DE_NULL, // const void* pNext;
279 firstPipelineFlags, // VkPipelineCreateFlags flags;
280 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount;
281 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages;
282 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
283 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
284 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
285 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
286 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
287 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
288 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
289 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
290 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
291 pipelineLayout, // VkPipelineLayout layout;
292 renderPass, // VkRenderPass renderPass;
293 0u, // deUint32 subpass;
294 DE_NULL, // VkPipeline basePipelineHandle;
295 0u, // deInt32 basePipelineIndex;
296 };
297
298 graphicsPipelineInfos.push_back (createInfo);
299
300 #ifndef CTS_USES_VULKANSC
301 createInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
302 createInfo.basePipelineIndex = 0;
303 #endif // CTS_USES_VULKANSC
304
305 for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx)
306 {
307 createInfo.subpass = subpassNdx;
308 graphicsPipelineInfos.push_back(createInfo);
309 }
310 }
311
312 VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0]));
313
314 std::vector<PipelineSp> pipelines;
315
316 for (std::vector<VkPipeline>::const_iterator it = rawPipelines.begin(); it != rawPipelines.end(); ++it)
317 pipelines.push_back(makeSharedPtr(Move<VkPipeline>(check<VkPipeline>(*it), Deleter<VkPipeline>(vk, device, DE_NULL))));
318
319 return pipelines;
320 }
321
322 //! Create a vector of pipelines, each with an increasing subpass index
preparePipelineWrapper(GraphicsPipelineWrapper& gpw, const deUint32 subpassNdx, const PipelineLayoutWrapper& pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper vertexModule, const ShaderWrapper fragmentModule, const IVec2 renderSize, const VkSampleCountFlagBits numSamples, const VkPrimitiveTopology topology)323 void preparePipelineWrapper (GraphicsPipelineWrapper& gpw,
324 const deUint32 subpassNdx,
325 const PipelineLayoutWrapper& pipelineLayout,
326 const VkRenderPass renderPass,
327 const ShaderWrapper vertexModule,
328 const ShaderWrapper fragmentModule,
329 const IVec2 renderSize,
330 const VkSampleCountFlagBits numSamples,
331 const VkPrimitiveTopology topology)
332 {
333 const VkVertexInputBindingDescription vertexInputBindingDescription =
334 {
335 0u, // uint32_t binding;
336 sizeof(Vertex4RGBA), // uint32_t stride;
337 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
338 };
339
340 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
341 {
342 {
343 0u, // uint32_t location;
344 0u, // uint32_t binding;
345 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
346 0u, // uint32_t offset;
347 },
348 {
349 1u, // uint32_t location;
350 0u, // uint32_t binding;
351 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
352 sizeof(Vec4), // uint32_t offset;
353 },
354 };
355
356 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
357 {
358 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
359 DE_NULL, // const void* pNext;
360 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
361 1u, // uint32_t vertexBindingDescriptionCount;
362 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
363 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
364 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
365 };
366
367 const std::vector<VkViewport> viewport { makeViewport(renderSize) };
368 const std::vector<VkRect2D> scissor { makeRect2D(renderSize) };
369
370 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
371 {
372 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
373 DE_NULL, // const void* pNext;
374 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
375 numSamples, // VkSampleCountFlagBits rasterizationSamples;
376 VK_FALSE, // VkBool32 sampleShadingEnable;
377 0.0f, // float minSampleShading;
378 DE_NULL, // const VkSampleMask* pSampleMask;
379 VK_FALSE, // VkBool32 alphaToCoverageEnable;
380 VK_FALSE // VkBool32 alphaToOneEnable;
381 };
382
383 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
384 // Number of blend attachments must equal the number of color attachments during any subpass.
385 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
386 {
387 VK_FALSE, // VkBool32 blendEnable;
388 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
389 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
390 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
391 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
392 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
393 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
394 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
395 };
396
397 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
398 {
399 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
400 DE_NULL, // const void* pNext;
401 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
402 VK_FALSE, // VkBool32 logicOpEnable;
403 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
404 1u, // deUint32 attachmentCount;
405 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
406 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
407 };
408
409 gpw.setDefaultTopology(topology)
410 .setDefaultRasterizationState()
411 .setDefaultDepthStencilState()
412 .setupVertexInputState(&vertexInputStateInfo)
413 .setupPreRasterizationShaderState(viewport,
414 scissor,
415 pipelineLayout,
416 renderPass,
417 subpassNdx,
418 vertexModule)
419 .setupFragmentShaderState(pipelineLayout, renderPass, subpassNdx, fragmentModule, DE_NULL, &pipelineMultisampleStateInfo)
420 .setupFragmentOutputState(renderPass, subpassNdx, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
421 .setMonolithicPipelineLayout(pipelineLayout)
422 .buildPipeline();
423 }
424
425 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
makeMultisampleRenderPass(const DeviceInterface& vk, const VkDevice device, const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat, const VkSampleCountFlagBits numSamples, const deUint32 numLayers)426 RenderPassWrapper makeMultisampleRenderPass (const DeviceInterface& vk,
427 const VkDevice device,
428 const PipelineConstructionType pipelineConstructionType,
429 const VkFormat colorFormat,
430 const VkSampleCountFlagBits numSamples,
431 const deUint32 numLayers)
432 {
433 const VkAttachmentDescription colorAttachmentDescription =
434 {
435 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
436 colorFormat, // VkFormat format;
437 numSamples, // VkSampleCountFlagBits samples;
438 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
439 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
440 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
441 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
442 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
443 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
444 };
445 const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
446
447 // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
448
449 std::vector<VkAttachmentReference> colorAttachmentReferences(numLayers);
450 std::vector<VkSubpassDescription> subpasses;
451
452 for (deUint32 i = 0; i < numLayers; ++i)
453 {
454 const VkAttachmentReference attachmentRef =
455 {
456 i, // deUint32 attachment;
457 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
458 };
459 colorAttachmentReferences[i] = attachmentRef;
460
461 const VkSubpassDescription subpassDescription =
462 {
463 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
464 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
465 0u, // deUint32 inputAttachmentCount;
466 DE_NULL, // const VkAttachmentReference* pInputAttachments;
467 1u, // deUint32 colorAttachmentCount;
468 &colorAttachmentReferences[i], // const VkAttachmentReference* pColorAttachments;
469 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
470 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
471 0u, // deUint32 preserveAttachmentCount;
472 DE_NULL // const deUint32* pPreserveAttachments;
473 };
474 subpasses.push_back(subpassDescription);
475 }
476
477 const VkRenderPassCreateInfo renderPassInfo =
478 {
479 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
480 DE_NULL, // const void* pNext;
481 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
482 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
483 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
484 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
485 &subpasses[0], // const VkSubpassDescription* pSubpasses;
486 0u, // deUint32 dependencyCount;
487 DE_NULL // const VkSubpassDependency* pDependencies;
488 };
489
490 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
491 }
492
493 //! A single-attachment, single-subpass render pass.
makeSimpleRenderPass(const DeviceInterface& vk, const VkDevice device, const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat)494 RenderPassWrapper makeSimpleRenderPass (const DeviceInterface& vk,
495 const VkDevice device,
496 const PipelineConstructionType pipelineConstructionType,
497 const VkFormat colorFormat)
498 {
499 const VkAttachmentDescription colorAttachmentDescription =
500 {
501 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags;
502 colorFormat, // VkFormat format;
503 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
504 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
505 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
506 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
507 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
508 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
509 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
510 };
511
512 const VkAttachmentReference colorAttachmentRef =
513 {
514 0u, // deUint32 attachment;
515 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
516 };
517
518 const VkSubpassDescription subpassDescription =
519 {
520 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags;
521 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
522 0u, // deUint32 inputAttachmentCount;
523 DE_NULL, // const VkAttachmentReference* pInputAttachments;
524 1u, // deUint32 colorAttachmentCount;
525 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments;
526 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
527 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
528 0u, // deUint32 preserveAttachmentCount;
529 DE_NULL // const deUint32* pPreserveAttachments;
530 };
531
532 const VkRenderPassCreateInfo renderPassInfo =
533 {
534 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
535 DE_NULL, // const void* pNext;
536 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
537 1u, // deUint32 attachmentCount;
538 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments;
539 1u, // deUint32 subpassCount;
540 &subpassDescription, // const VkSubpassDescription* pSubpasses;
541 0u, // deUint32 dependencyCount;
542 DE_NULL // const VkSubpassDependency* pDependencies;
543 };
544
545 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
546 }
547
makeImage(const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)548 Move<VkImage> makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
549 {
550 const VkImageCreateInfo imageParams =
551 {
552 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
553 DE_NULL, // const void* pNext;
554 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
555 VK_IMAGE_TYPE_2D, // VkImageType imageType;
556 format, // VkFormat format;
557 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
558 1u, // deUint32 mipLevels;
559 numLayers, // deUint32 arrayLayers;
560 samples, // VkSampleCountFlagBits samples;
561 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
562 usage, // VkImageUsageFlags usage;
563 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
564 0u, // deUint32 queueFamilyIndexCount;
565 DE_NULL, // const deUint32* pQueueFamilyIndices;
566 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
567 };
568 return createImage(vk, device, &imageParams);
569 }
570
571 //! Make a simplest sampler.
makeSampler(const DeviceInterface& vk, const VkDevice device)572 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
573 {
574 const VkSamplerCreateInfo samplerParams =
575 {
576 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
577 DE_NULL, // const void* pNext;
578 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags;
579 VK_FILTER_NEAREST, // VkFilter magFilter;
580 VK_FILTER_NEAREST, // VkFilter minFilter;
581 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
582 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
583 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
584 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
585 0.0f, // float mipLodBias;
586 VK_FALSE, // VkBool32 anisotropyEnable;
587 1.0f, // float maxAnisotropy;
588 VK_FALSE, // VkBool32 compareEnable;
589 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp;
590 0.0f, // float minLod;
591 0.0f, // float maxLod;
592 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
593 VK_FALSE, // VkBool32 unnormalizedCoordinates;
594 };
595 return createSampler(vk, device, &samplerParams);
596 }
597
makeColorSubresourceRange(const int baseArrayLayer, const int layerCount)598 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
599 {
600 return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
601 }
602
makeColorSubresourceLayers(const int baseArrayLayer, const int layerCount)603 inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount)
604 {
605 return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
606 }
607
checkImageFormatRequirements(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkSampleCountFlagBits sampleCount, const VkFormat format, const VkImageUsageFlags usage)608 void checkImageFormatRequirements (const InstanceInterface& vki,
609 const VkPhysicalDevice physDevice,
610 const VkSampleCountFlagBits sampleCount,
611 const VkFormat format,
612 const VkImageUsageFlags usage)
613 {
614 VkPhysicalDeviceFeatures features;
615 vki.getPhysicalDeviceFeatures(physDevice, &features);
616
617 if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample)
618 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
619
620 VkImageFormatProperties imageFormatProperties;
621 const VkResult imageFormatResult = vki.getPhysicalDeviceImageFormatProperties(
622 physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties);
623
624 if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
625 TCU_THROW(NotSupportedError, "Image format is not supported");
626
627 if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount)
628 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
629 }
630
631 //! The default foreground color.
getPrimitiveColor(void)632 inline Vec4 getPrimitiveColor (void)
633 {
634 return Vec4(1.0f, 0.0f, 0.0f, 1.0f);
635 }
636
637 //! Get a reference clear value based on color format.
getClearValue(const VkFormat format)638 VkClearValue getClearValue (const VkFormat format)
639 {
640 if (isUintFormat(format) || isIntFormat(format))
641 return makeClearValueColorU32(16, 32, 64, 96);
642 else
643 return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f);
644 }
645
getColorFormatStr(const int numComponents, const bool isUint, const bool isSint)646 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
647 {
648 std::ostringstream str;
649 if (numComponents == 1)
650 str << (isUint ? "uint" : isSint ? "int" : "float");
651 else
652 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
653
654 return str.str();
655 }
656
getSamplerTypeStr(const int numLayers, const bool isUint, const bool isSint)657 std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint)
658 {
659 std::ostringstream str;
660 str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : "");
661 return str.str();
662 }
663
664 //! Generate a gvec4 color literal.
665 template<typename T>
getColorStr(const T* data, int numComponents, const bool isUint, const bool isSint)666 std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint)
667 {
668 const int maxIndex = 3; // 4 components max
669
670 std::ostringstream str;
671 str << (isUint ? "u" : isSint ? "i" : "") << "vec4(";
672
673 for (int i = 0; i < numComponents; ++i)
674 {
675 str << data[i]
676 << (i < maxIndex ? ", " : "");
677 }
678
679 for (int i = numComponents; i < maxIndex + 1; ++i)
680 {
681 str << (i == maxIndex ? 1 : 0)
682 << (i < maxIndex ? ", " : "");
683 }
684
685 str << ")";
686 return str.str();
687 }
688
689 //! Clear color literal value used by the sampling shader.
690 std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint)
691 {
692 const VkClearColorValue clearColor = getClearValue(format).color;
693 if (isUint)
694 return getColorStr(clearColor.uint32, numComponents, isUint, isSint);
695 else if (isSint)
696 return getColorStr(clearColor.int32, numComponents, isUint, isSint);
697 else
698 return getColorStr(clearColor.float32, numComponents, isUint, isSint);
699 }
700
701 //! Primitive color literal value used by the sampling shader.
702 std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint)
703 {
704 const Vec4 color = getPrimitiveColor();
705 return getColorStr(color.getPtr(), numComponents, isUint, isSint);
706 }
707
708 inline int getNumSamples (const VkSampleCountFlagBits samples)
709 {
710 return static_cast<int>(samples); // enum bitmask actually matches the number of samples
711 }
712
713 //! A flat-colored shape with sharp angles to make antialiasing visible.
714 std::vector<Vertex4RGBA> genTriangleVertices (void)
715 {
716 static const Vertex4RGBA data[] =
717 {
718 {
719 Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
720 getPrimitiveColor(),
721 },
722 {
723 Vec4(0.8f, 0.2f, 0.0f, 1.0f),
724 getPrimitiveColor(),
725 },
726 {
727 Vec4(0.8f, -0.2f, 0.0f, 1.0f),
728 getPrimitiveColor(),
729 },
730 };
731 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
732 }
733
734 Vec4 sampleIndexToColor (deUint32 index)
735 {
736 Vec4 res = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
737
738 if (index & 0x01) res += Vec4(0.5f, 0.0f, 0.0f, 0.0f);
739 if (index & 0x02) res += Vec4(0.0f, 0.5f, 0.0f, 0.0f);
740 if (index & 0x04) res += Vec4(0.0f, 0.0f, 0.5f, 0.0f);
741
742 if (index & 0x08) res += Vec4(0.5f, 0.0f, 0.0f, 0.0f);
743 if (index & 0x10) res += Vec4(0.0f, 0.5f, 0.0f, 0.0f);
744 if (index & 0x20) res += Vec4(0.0f, 0.0f, 0.5f, 0.0f);
745
746 return res;
747 }
748
749 float* getStandardSampleLocations (VkSampleCountFlagBits samples)
750 {
751 static float standardSampleLocations_1[1 * 2] = {
752 0.5f, 0.5f,
753 };
754
755 static float standardSampleLocations_2[2 * 2] = {
756 0.75f, 0.75f,
757 0.25f, 0.25f,
758 };
759
760 static float standardSampleLocations_4[4 * 2] = {
761 0.375f, 0.125f,
762 0.875f, 0.375f,
763 0.125f, 0.625f,
764 0.625f, 0.875f,
765 };
766
767 static float standardSampleLocations_8[8 * 2] = {
768 0.5625f, 0.3125f,
769 0.4375f, 0.6875f,
770 0.8125f, 0.5625f,
771 0.3125f, 0.1875f,
772 0.1875f, 0.8125f,
773 0.0625f, 0.4375f,
774 0.6875f, 0.9375f,
775 0.9375f, 0.0625f,
776 };
777
778 static float standardSampleLocations_16[16 * 2] = {
779 0.5625f, 0.5625f,
780 0.4375f, 0.3125f,
781 0.3125f, 0.625f,
782 0.75f, 0.4375f,
783 0.1875f, 0.375f,
784 0.625f, 0.8125f,
785 0.8125f, 0.6875f,
786 0.6875f, 0.1875f,
787 0.375f, 0.875f,
788 0.5f, 0.0625f,
789 0.25f, 0.125f,
790 0.125f, 0.75f,
791 0.0f, 0.5f,
792 0.9375f, 0.25f,
793 0.875f, 0.9375f,
794 0.0625f, 0.0f,
795 };
796
797 switch (samples)
798 {
799 case VK_SAMPLE_COUNT_1_BIT:
800 return standardSampleLocations_1;
801 case VK_SAMPLE_COUNT_2_BIT:
802 return standardSampleLocations_2;
803 case VK_SAMPLE_COUNT_4_BIT:
804 return standardSampleLocations_4;
805 case VK_SAMPLE_COUNT_8_BIT:
806 return standardSampleLocations_8;
807 case VK_SAMPLE_COUNT_16_BIT:
808 return standardSampleLocations_16;
809 default:
810 TCU_THROW(InternalError, "Unknown multisample bit configuration requested");
811 }
812 }
813
814 //! A flat-colored shapes plotted at standard sample points.
815 std::vector<Vertex4RGBA> genPerSampleTriangleVertices (VkSampleCountFlagBits samples)
816 {
817 float* coordinates = getStandardSampleLocations(samples);
818 const float triangleSize = 1.0f / (static_cast<float>(samples) * 2.0f);
819 std::vector<Vertex4RGBA> res;
820
821 for (deUint32 i = 0; i < static_cast<deUint32>(samples); i++)
822 {
823 Vertex4RGBA data[] =
824 {
825 {
826 Vec4(0 + coordinates[i * 2 + 0] * 2 - 1, -triangleSize + coordinates[i * 2 + 1] * 2 - 1, 0.0f, 1.0f),
827 sampleIndexToColor(i),
828 },
829 {
830 Vec4(-triangleSize + coordinates[i * 2 + 0] * 2 - 1, triangleSize + coordinates[i * 2 + 1] * 2 - 1, 0.0f, 1.0f),
831 sampleIndexToColor(i),
832 },
833 {
834 Vec4(triangleSize + coordinates[i * 2 + 0] * 2 - 1, triangleSize + coordinates[i * 2 + 1] * 2 - 1, 0.0f, 1.0f),
835 sampleIndexToColor(i),
836 },
837 };
838 res.push_back(data[0]);
839 res.push_back(data[1]);
840 res.push_back(data[2]);
841 }
842 return res;
843 }
844
845 //! A full-viewport quad. Use with TRIANGLE_STRIP topology.
846 std::vector<Vertex4RGBA> genFullQuadVertices (void)
847 {
848 static const Vertex4RGBA data[] =
849 {
850 {
851 Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
852 Vec4(), // unused
853 },
854 {
855 Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
856 Vec4(), // unused
857 },
858 {
859 Vec4(1.0f, -1.0f, 0.0f, 1.0f),
860 Vec4(), // unused
861 },
862 {
863 Vec4(1.0f, 1.0f, 0.0f, 1.0f),
864 Vec4(), // unused
865 },
866 };
867 return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
868 }
869
870 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
871 {
872 const char* orderPart;
873 const char* typePart;
874
875 switch (format.order)
876 {
877 case tcu::TextureFormat::R: orderPart = "r"; break;
878 case tcu::TextureFormat::RG: orderPart = "rg"; break;
879 case tcu::TextureFormat::RGB: orderPart = "rgb"; break;
880 case tcu::TextureFormat::RGBA: orderPart = "rgba"; break;
881
882 default:
883 DE_ASSERT(false);
884 orderPart = DE_NULL;
885 }
886
887 switch (format.type)
888 {
889 case tcu::TextureFormat::FLOAT: typePart = "32f"; break;
890 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break;
891
892 case tcu::TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break;
893 case tcu::TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break;
894 case tcu::TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break;
895
896 case tcu::TextureFormat::SIGNED_INT32: typePart = "32i"; break;
897 case tcu::TextureFormat::SIGNED_INT16: typePart = "16i"; break;
898 case tcu::TextureFormat::SIGNED_INT8: typePart = "8i"; break;
899
900 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break;
901 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break;
902
903 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break;
904 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break;
905
906 default:
907 DE_ASSERT(false);
908 typePart = DE_NULL;
909 }
910
911 return std::string() + orderPart + typePart;
912 }
913
914 std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers)
915 {
916 const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
917 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : "";
918
919 std::ostringstream str;
920 str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : "");
921
922 return str.str();
923 }
924
925 void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
926 {
927 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
928 const bool isUint = isUintFormat(caseDef.colorFormat);
929 const bool isSint = isIntFormat(caseDef.colorFormat);
930
931 // Vertex shader
932 {
933 std::ostringstream src;
934 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
935 << "\n"
936 << "layout(location = 0) in vec4 in_position;\n"
937 << "layout(location = 1) in vec4 in_color;\n"
938 << "layout(location = 0) out vec4 o_color;\n"
939 << "\n"
940 << "out gl_PerVertex {\n"
941 << " vec4 gl_Position;\n"
942 << "};\n"
943 << "\n"
944 << "void main(void)\n"
945 << "{\n"
946 << " gl_Position = in_position;\n"
947 << " o_color = in_color;\n"
948 << "}\n";
949
950 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
951 }
952
953 // Fragment shader
954 {
955 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
956
957 std::ostringstream src;
958 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
959 << "\n"
960 << "layout(location = 0) in vec4 in_color;\n"
961 << "layout(location = 0) out " << colorFormat << " o_color;\n"
962 << "\n"
963 << "void main(void)\n"
964 << "{\n"
965 << " o_color = " << colorFormat << "(" // float color will be converted to int/uint here if needed
966 << (numComponents == 1 ? "in_color.r" :
967 numComponents == 2 ? "in_color.rg" :
968 numComponents == 3 ? "in_color.rgb" : "in_color") << ");\n"
969 << "}\n";
970
971 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
972 }
973 }
974
975 //! Synchronously render to a multisampled color image.
976 void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage)
977 {
978 const InstanceInterface& vki = context.getInstanceInterface();
979 const DeviceInterface& vk = context.getDeviceInterface();
980 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
981 const VkDevice device = context.getDevice();
982 const VkQueue queue = context.getUniversalQueue();
983 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
984 Allocator& allocator = context.getDefaultAllocator();
985
986 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
987 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
988
989 {
990 // Create an image view (attachment) for each layer of the image
991 std::vector<ImageViewSp> colorAttachments;
992 std::vector<VkImage> images;
993 std::vector<VkImageView> attachmentHandles;
994 for (int i = 0; i < caseDef.numLayers; ++i)
995 {
996 colorAttachments.push_back(makeSharedPtr(makeImageView(
997 vk, device, colorImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.colorFormat, makeColorSubresourceRange(i, 1))));
998 images.push_back(colorImage);
999 attachmentHandles.push_back(**colorAttachments.back());
1000 }
1001
1002 // Vertex buffer
1003 const std::vector<Vertex4RGBA> vertices = caseDef.colorSamples ? genPerSampleTriangleVertices(caseDef.numSamples) : genTriangleVertices();
1004 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1005 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1006 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1007
1008 {
1009 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1010 flushAlloc(vk, device, *vertexBufferAlloc);
1011 }
1012
1013 const ShaderWrapper vertexModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("vert"), 0u));
1014 const ShaderWrapper fragmentModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("frag"), 0u));
1015 RenderPassWrapper renderPass (makeMultisampleRenderPass (vk, device, caseDef.pipelineConstructionType, caseDef.colorFormat, caseDef.numSamples, caseDef.numLayers));
1016 renderPass.createFramebuffer(vk, device, caseDef.numLayers, &images[0], &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1017 const PipelineLayoutWrapper pipelineLayout (caseDef.pipelineConstructionType, vk, device);
1018 const bool isMonolithic (caseDef.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1019 std::vector<PipelineSp> pipelinesSp;
1020 std::vector<GraphicsPipelineWrapper> pipelineWrapper;
1021
1022 if (isMonolithic)
1023 {
1024 pipelinesSp = makeGraphicsPipelines(vk, device, caseDef.numLayers, *pipelineLayout, *renderPass, vertexModule, fragmentModule,
1025 caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1026 }
1027 else
1028 {
1029 // we can't create a vector of derived pipelines with GraphicsPipelineWrapper
1030 pipelineWrapper.reserve(caseDef.numLayers);
1031 for (int subpassNdx = 0; subpassNdx < caseDef.numLayers; ++subpassNdx)
1032 {
1033 pipelineWrapper.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), caseDef.pipelineConstructionType);
1034 preparePipelineWrapper(pipelineWrapper.back(), subpassNdx, pipelineLayout, *renderPass, vertexModule, fragmentModule,
1035 caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1036 }
1037 }
1038
1039 beginCommandBuffer(vk, *cmdBuffer);
1040
1041 const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat));
1042
1043 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()), (deUint32)clearValues.size(), &clearValues[0]);
1044 {
1045 const VkDeviceSize vertexBufferOffset = 0ull;
1046 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1047 }
1048
1049 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1050 {
1051 if (layerNdx != 0)
1052 renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1053
1054 if (isMonolithic)
1055 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelinesSp[layerNdx]);
1056 else
1057 pipelineWrapper[layerNdx].bind(*cmdBuffer);
1058 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1059 }
1060
1061 renderPass.end(vk, *cmdBuffer);
1062
1063 endCommandBuffer(vk, *cmdBuffer);
1064 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1065 }
1066 }
1067
1068 namespace SampledImage
1069 {
1070
1071 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1072 {
1073 // Pass 1: Render to texture
1074
1075 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1076
1077 // Pass 2: Sample texture
1078
1079 // Vertex shader
1080 {
1081 std::ostringstream src;
1082 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1083 << "\n"
1084 << "layout(location = 0) in vec4 in_position;\n"
1085 << "\n"
1086 << "out gl_PerVertex {\n"
1087 << " vec4 gl_Position;\n"
1088 << "};\n"
1089 << "\n"
1090 << "void main(void)\n"
1091 << "{\n"
1092 << " gl_Position = in_position;\n"
1093 << "}\n";
1094
1095 programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
1096 }
1097
1098 // Fragment shader
1099 {
1100 const int numComponents = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
1101 const bool isUint = isUintFormat(caseDef.colorFormat);
1102 const bool isSint = isIntFormat(caseDef.colorFormat);
1103 const std::string texelFormatStr = (isUint ? "uvec4" : isSint ? "ivec4" : "vec4");
1104 const std::string refClearColor = getReferenceClearColorStr(caseDef.colorFormat, numComponents, isUint, isSint);
1105 const std::string refPrimitiveColor = getReferencePrimitiveColorStr(numComponents, isUint, isSint);
1106 const std::string samplerTypeStr = getSamplerTypeStr(caseDef.numLayers, isUint, isSint);
1107
1108 std::ostringstream src;
1109 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1110 << "\n"
1111 << "layout(location = 0) out uvec2 o_status;\n"
1112 << "\n"
1113 << "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n"
1114 << "\n"
1115 << "void main(void)\n"
1116 << "{\n"
1117 << " uint clearColorCount = 0;\n"
1118 << " uint primitiveColorCount = 0;\n"
1119 << "\n";
1120
1121 if (caseDef.numLayers == 1)
1122 src << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1123 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), sampleNdx);\n"
1124 << " if (color == " << refClearColor << ")\n"
1125 << " ++clearColorCount;\n"
1126 << " else if (color == " << refPrimitiveColor << ")\n"
1127 << " ++primitiveColorCount;\n"
1128 << " }\n";
1129 else
1130 src << " for (int layerNdx = 0; layerNdx < " << caseDef.numLayers << "; ++layerNdx)\n"
1131 << " for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1132 << " " << texelFormatStr << " color = texelFetch(colorTexture, ivec3(gl_FragCoord.xy, layerNdx), sampleNdx);\n"
1133 << " if (color == " << refClearColor << ")\n"
1134 << " ++clearColorCount;\n"
1135 << " else if (color == " << refPrimitiveColor << ")\n"
1136 << " ++primitiveColorCount;\n"
1137 << " }\n";
1138
1139 src << "\n"
1140 << " o_status = uvec2(clearColorCount, primitiveColorCount);\n"
1141 << "}\n";
1142
1143 programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
1144 }
1145 }
1146
1147 void checkSupport (Context& context, const CaseDef caseDef)
1148 {
1149 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1150
1151 checkImageFormatRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
1152 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1153
1154 #ifndef CTS_USES_VULKANSC
1155 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1156 !context.getPortabilitySubsetFeatures().multisampleArrayImage &&
1157 (caseDef.numSamples != VK_SAMPLE_COUNT_1_BIT) && (caseDef.numLayers != 1))
1158 {
1159 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
1160 }
1161 #endif // CTS_USES_VULKANSC
1162 }
1163
1164 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1165 {
1166 const InstanceInterface& vki = context.getInstanceInterface();
1167 const DeviceInterface& vk = context.getDeviceInterface();
1168 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1169 const VkDevice device = context.getDevice();
1170 const VkQueue queue = context.getUniversalQueue();
1171 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1172 Allocator& allocator = context.getDefaultAllocator();
1173
1174 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1175
1176 {
1177 tcu::TestLog& log = context.getTestContext().getLog();
1178 log << tcu::LogSection("Description", "")
1179 << tcu::TestLog::Message << "Rendering to a multisampled image. Expecting all samples to be either a clear color or a primitive color." << tcu::TestLog::EndMessage
1180 << tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
1181 << tcu::TestLog::EndSection;
1182 }
1183
1184 // Multisampled color image
1185 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
1186 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1187
1188 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1189 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1190
1191 // Step 1: Render to texture
1192 {
1193 renderMultisampledImage(context, caseDef, *colorImage);
1194 }
1195
1196 // Step 2: Sample texture
1197 {
1198 // Color image view
1199 const VkImageViewType colorImageViewType = (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
1200 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1201 const Unique<VkSampler> colorSampler (makeSampler(vk, device));
1202
1203 // Checksum image
1204 const VkFormat checksumFormat = VK_FORMAT_R8G8_UINT;
1205 const Unique<VkImage> checksumImage (makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
1206 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
1207 const UniquePtr<Allocation> checksumImageAlloc (bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
1208 const Unique<VkImageView> checksumImageView (makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
1209
1210 // Checksum buffer (for host reading)
1211 const VkDeviceSize checksumBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
1212 const Unique<VkBuffer> checksumBuffer (makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1213 const UniquePtr<Allocation> checksumBufferAlloc (bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
1214
1215 zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
1216
1217 // Vertex buffer
1218 const std::vector<Vertex4RGBA> vertices = genFullQuadVertices();
1219 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1220 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1221 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1222
1223 {
1224 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1225 flushAlloc(vk, device, *vertexBufferAlloc);
1226 }
1227
1228 // Descriptors
1229 // \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
1230
1231 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1232 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1233 .build(vk, device));
1234
1235 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1236 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1237 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1238
1239 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1240 const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1241
1242 DescriptorSetUpdateBuilder()
1243 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1244 .update(vk, device);
1245
1246 const ShaderWrapper vertexModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1247 const ShaderWrapper fragmentModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1248 RenderPassWrapper renderPass (caseDef.pipelineConstructionType, vk, device, checksumFormat);
1249 renderPass.createFramebuffer(vk, device, 1u, &checksumImage.get(), &checksumImageView.get(), static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1250 const PipelineLayoutWrapper pipelineLayout (caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
1251
1252 const bool isMonolithic (caseDef.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1253 std::vector<PipelineSp> pipelinesSp;
1254 std::vector<GraphicsPipelineWrapper> pipelineWrapper;
1255
1256 if (isMonolithic)
1257 {
1258 pipelinesSp = makeGraphicsPipelines(vk, device, 1u, *pipelineLayout, *renderPass, vertexModule, fragmentModule,
1259 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1260 }
1261 else
1262 {
1263 pipelineWrapper.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), caseDef.pipelineConstructionType);
1264 preparePipelineWrapper(pipelineWrapper.back(), 0u, pipelineLayout, *renderPass, vertexModule, fragmentModule,
1265 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1266 }
1267
1268 beginCommandBuffer(vk, *cmdBuffer);
1269
1270 // Prepare for sampling in the fragment shader
1271 {
1272 const VkImageMemoryBarrier barriers[] =
1273 {
1274 {
1275 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1276 DE_NULL, // const void* pNext;
1277 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1278 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags inputMask;
1279 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1280 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
1281 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1282 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1283 *colorImage, // VkImage image;
1284 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1285 },
1286 };
1287
1288 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1289 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1290 }
1291
1292 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()), tcu::UVec4(0u));
1293
1294 if (isMonolithic)
1295 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelinesSp.back());
1296 else
1297 pipelineWrapper.back().bind(*cmdBuffer);
1298 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1299 {
1300 const VkDeviceSize vertexBufferOffset = 0ull;
1301 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1302 }
1303
1304 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1305 renderPass.end(vk, *cmdBuffer);
1306
1307 copyImageToBuffer(vk, *cmdBuffer, *checksumImage, *checksumBuffer, caseDef.renderSize);
1308
1309 endCommandBuffer(vk, *cmdBuffer);
1310 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1311
1312 // Verify result
1313
1314 {
1315 invalidateAlloc(vk, device, *checksumBufferAlloc);
1316
1317 const tcu::ConstPixelBufferAccess access (mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1318 const deUint32 numExpectedChecksum = getNumSamples(caseDef.numSamples) * caseDef.numLayers;
1319 bool multipleColorsPerTexelFound = false;
1320
1321 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1322 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1323 {
1324 deUint32 clearColorCount = access.getPixelUint(x, y).x();
1325 deUint32 primitiveColorCount = access.getPixelUint(x, y).y();
1326
1327 if ((clearColorCount + primitiveColorCount) != numExpectedChecksum)
1328 return tcu::TestStatus::fail("Some samples have incorrect color");
1329
1330 if ((clearColorCount > 0) && (primitiveColorCount > 0))
1331 multipleColorsPerTexelFound = true;
1332 }
1333
1334 // For a multisampled image, we are expecting some texels to have samples of both clear color and primitive color
1335 if (!multipleColorsPerTexelFound)
1336 return tcu::TestStatus::fail("Could not find texels with samples of both clear color and primitive color");
1337 }
1338 }
1339
1340 return tcu::TestStatus::pass("OK");
1341 }
1342
1343 } // SampledImage ns
1344
1345 namespace StorageImage
1346 {
1347
1348 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1349 {
1350 // Vertex & fragment
1351
1352 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1353
1354 // Compute
1355 {
1356 const std::string imageTypeStr = getShaderMultisampledImageType(mapVkFormat(caseDef.colorFormat), caseDef.numLayers);
1357 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(caseDef.colorFormat));
1358 const std::string signednessPrefix = isUintFormat(caseDef.colorFormat) ? "u" : isIntFormat(caseDef.colorFormat) ? "i" : "";
1359 const std::string gvec4Expr = signednessPrefix + "vec4";
1360 const std::string texelCoordStr = (caseDef.numLayers == 1 ? "ivec2(gx, gy)" : "ivec3(gx, gy, gz)");
1361
1362 std::ostringstream src;
1363 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1364 << "layout(local_size_x = 1) in;\n"
1365 << "layout(set = 0, binding = 0, " << formatQualifierStr << ") uniform " << imageTypeStr << " u_msImage;\n"
1366 << "\n"
1367 << "void main(void)\n"
1368 << "{\n"
1369 << " int gx = int(gl_GlobalInvocationID.x);\n"
1370 << " int gy = int(gl_GlobalInvocationID.y);\n"
1371 << " int gz = int(gl_GlobalInvocationID.z);\n"
1372 << "\n"
1373 << " " << gvec4Expr << " prevColor = imageLoad(u_msImage, " << texelCoordStr << ", 0);\n"
1374 << " for (int sampleNdx = 1; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1375 << " " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n"
1376 << " imageStore(u_msImage, " << texelCoordStr <<", sampleNdx, prevColor);\n"
1377 << " prevColor = color;\n"
1378 << " }\n"
1379 << " imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n"
1380 << "}\n";
1381
1382 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1383 }
1384 }
1385
1386 //! Render a MS image, resolve it, and copy result to resolveBuffer.
1387 void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass)
1388 {
1389 const DeviceInterface& vk = context.getDeviceInterface();
1390 const VkDevice device = context.getDevice();
1391 const VkQueue queue = context.getUniversalQueue();
1392 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1393 Allocator& allocator = context.getDefaultAllocator();
1394
1395 // Multisampled color image
1396 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples,
1397 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1398 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1399
1400 const Unique<VkImage> resolveImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, VK_SAMPLE_COUNT_1_BIT,
1401 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1402 const UniquePtr<Allocation> resolveImageAlloc (bindImage(vk, device, allocator, *resolveImage, MemoryRequirement::Any));
1403
1404 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1405 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1406
1407 // Working image barrier, we change it based on which rendering stages were executed so far.
1408 VkImageMemoryBarrier colorImageBarrier =
1409 {
1410 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1411 DE_NULL, // const void* pNext;
1412 (VkAccessFlags)0, // VkAccessFlags outputMask;
1413 (VkAccessFlags)0, // VkAccessFlags inputMask;
1414 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1415 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout newLayout;
1416 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1417 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1418 *colorImage, // VkImage image;
1419 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1420 };
1421
1422 // Pass 1: Render an image
1423 {
1424 renderMultisampledImage(context, caseDef, *colorImage);
1425
1426 colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1427 colorImageBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1428 }
1429
1430 // Pass 2: Compute shader
1431 if (useComputePass)
1432 {
1433 // Descriptors
1434
1435 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1436 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1437 .build(vk, device));
1438
1439 Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1440 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1441 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1442
1443 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage,
1444 (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY),
1445 caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1446 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1447 const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_GENERAL);
1448
1449 DescriptorSetUpdateBuilder()
1450 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1451 .update(vk, device);
1452
1453 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device, *descriptorSetLayout));
1454 const Unique<VkShaderModule> shaderModule (createShaderModule (vk, device, context.getBinaryCollection().get("comp"), 0));
1455 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
1456
1457 beginCommandBuffer(vk, *cmdBuffer);
1458
1459 // Image layout for load/stores
1460 {
1461 colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1462 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
1463
1464 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1465 0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
1466
1467 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1468 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1469 }
1470 // Dispatch
1471 {
1472 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1473 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1474 vk.cmdDispatch(*cmdBuffer, caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers);
1475 }
1476
1477 endCommandBuffer(vk, *cmdBuffer);
1478 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1479 }
1480
1481 // Resolve and verify the image
1482 {
1483 beginCommandBuffer(vk, *cmdBuffer);
1484
1485 // Prepare for resolve
1486 {
1487 colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1488 colorImageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1489
1490 const VkImageMemoryBarrier barriers[] =
1491 {
1492 colorImageBarrier,
1493 {
1494 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1495 DE_NULL, // const void* pNext;
1496 (VkAccessFlags)0, // VkAccessFlags outputMask;
1497 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags inputMask;
1498 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1499 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1500 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1501 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1502 *resolveImage, // VkImage image;
1503 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1504 },
1505 };
1506
1507 const VkPipelineStageFlags srcStageMask = (colorImageBarrier.srcAccessMask == VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
1508 ? VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
1509 : VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
1510
1511 vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1512 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1513
1514 colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1515 colorImageBarrier.oldLayout = colorImageBarrier.newLayout;
1516 }
1517 // Resolve the image
1518 {
1519 const VkImageResolve resolveRegion =
1520 {
1521 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers srcSubresource;
1522 makeOffset3D(0, 0, 0), // VkOffset3D srcOffset;
1523 makeColorSubresourceLayers(0, caseDef.numLayers), // VkImageSubresourceLayers dstSubresource;
1524 makeOffset3D(0, 0, 0), // VkOffset3D dstOffset;
1525 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u), // VkExtent3D extent;
1526 };
1527
1528 vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion);
1529 }
1530
1531 copyImageToBuffer(vk, *cmdBuffer, *resolveImage, resolveBuffer, caseDef.renderSize, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, caseDef.numLayers);
1532
1533 endCommandBuffer(vk, *cmdBuffer);
1534 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1535 }
1536 }
1537
1538 //! Exact image compare, but allow for some error when color format is integer.
1539 bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage)
1540 {
1541 DE_ASSERT(caseDef.numSamples > 1);
1542
1543 const Vec4 goodColor = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1544 const Vec4 badColor = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1545 const bool isAnyIntFormat = isIntFormat(caseDef.colorFormat) || isUintFormat(caseDef.colorFormat);
1546
1547 // 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.
1548 const int badPixelTolerance = (isAnyIntFormat ? 2 * caseDef.renderSize.x() : 0);
1549 int goodLayers = 0;
1550
1551 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1552 {
1553 const tcu::ConstPixelBufferAccess referenceImage = tcu::getSubregion(layeredReferenceImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1554 const tcu::ConstPixelBufferAccess actualImage = tcu::getSubregion(layeredActualImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1555 const std::string imageName = "color layer " + de::toString(layerNdx);
1556
1557 tcu::TextureLevel errorMaskStorage (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), caseDef.renderSize.x(), caseDef.renderSize.y());
1558 tcu::PixelBufferAccess errorMask = errorMaskStorage.getAccess();
1559 int numBadPixels = 0;
1560
1561 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1562 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1563 {
1564 if (isAnyIntFormat && (referenceImage.getPixelInt(x, y) == actualImage.getPixelInt(x, y)))
1565 errorMask.setPixel(goodColor, x, y);
1566 else if (referenceImage.getPixel(x, y) == actualImage.getPixel(x, y))
1567 errorMask.setPixel(goodColor, x, y);
1568 else
1569 {
1570 ++numBadPixels;
1571 errorMask.setPixel(badColor, x, y);
1572 }
1573 }
1574
1575 if (numBadPixels <= badPixelTolerance)
1576 {
1577 ++goodLayers;
1578
1579 log << tcu::TestLog::ImageSet(imageName, imageName)
1580 << tcu::TestLog::Image("Result", "Result", actualImage)
1581 << tcu::TestLog::EndImageSet;
1582 }
1583 else
1584 {
1585 log << tcu::TestLog::ImageSet(imageName, imageName)
1586 << tcu::TestLog::Image("Result", "Result", actualImage)
1587 << tcu::TestLog::Image("Reference", "Reference", referenceImage)
1588 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask)
1589 << tcu::TestLog::EndImageSet;
1590 }
1591 }
1592
1593 if (goodLayers == caseDef.numLayers)
1594 {
1595 log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage;
1596 return true;
1597 }
1598 else
1599 {
1600 log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage;
1601 return false;
1602 }
1603 }
1604
1605 void checkSupport (Context& context, const CaseDef caseDef)
1606 {
1607 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
1608
1609 checkImageFormatRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
1610 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1611 }
1612
1613 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1614 {
1615 const DeviceInterface& vk = context.getDeviceInterface();
1616 const VkDevice device = context.getDevice();
1617 Allocator& allocator = context.getDefaultAllocator();
1618
1619 {
1620 tcu::TestLog& log = context.getTestContext().getLog();
1621 log << tcu::LogSection("Description", "")
1622 << tcu::TestLog::Message << "Rendering to a multisampled image. Image will be processed with a compute shader using OpImageRead and OpImageWrite." << tcu::TestLog::EndMessage
1623 << 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
1624 << tcu::TestLog::EndSection;
1625 }
1626
1627 // Host-readable buffer
1628 const VkDeviceSize resolveBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
1629 const Unique<VkBuffer> resolveImageOneBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1630 const UniquePtr<Allocation> resolveImageOneBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageOneBuffer, MemoryRequirement::HostVisible));
1631 const Unique<VkBuffer> resolveImageTwoBuffer (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1632 const UniquePtr<Allocation> resolveImageTwoBufferAlloc (bindBuffer(vk, device, allocator, *resolveImageTwoBuffer, MemoryRequirement::HostVisible));
1633
1634 zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize);
1635 zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize);
1636
1637 // Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy).
1638 {
1639 renderAndResolve(context, caseDef, *resolveImageOneBuffer, false); // Pass 1: render a basic multisampled image
1640 renderAndResolve(context, caseDef, *resolveImageTwoBuffer, true); // Pass 2: the same but altered with a compute shader
1641 }
1642
1643 // Verify
1644 {
1645 invalidateAlloc(vk, device, *resolveImageOneBufferAlloc);
1646 invalidateAlloc(vk, device, *resolveImageTwoBufferAlloc);
1647
1648 const tcu::PixelBufferAccess layeredImageOne (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageOneBufferAlloc->getHostPtr());
1649 const tcu::ConstPixelBufferAccess layeredImageTwo (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageTwoBufferAlloc->getHostPtr());
1650
1651 // Check all layers
1652 if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo))
1653 return tcu::TestStatus::fail("Rendered images are not correct");
1654 }
1655
1656 return tcu::TestStatus::pass("OK");
1657 }
1658
1659 } // StorageImage ns
1660
1661
1662 namespace StandardSamplePosition
1663 {
1664
1665 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1666 {
1667 // Pass 1: Render to texture
1668
1669 addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1670
1671 // Pass 2: Sample texture
1672
1673 // Vertex shader
1674 {
1675 std::ostringstream src;
1676 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1677 << "\n"
1678 << "layout(location = 0) in vec4 in_position;\n"
1679 << "\n"
1680 << "out gl_PerVertex {\n"
1681 << " vec4 gl_Position;\n"
1682 << "};\n"
1683 << "\n"
1684 << "void main(void)\n"
1685 << "{\n"
1686 << " gl_Position = in_position;\n"
1687 << "}\n";
1688
1689 programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
1690 }
1691
1692 // Fragment shader
1693 {
1694 std::ostringstream src;
1695 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1696 << "\n"
1697 << "layout(location = 0) out uint o_status;\n"
1698 << "\n"
1699 << "layout(set = 0, binding = 0) uniform sampler2DMS colorTexture;\n"
1700 << "\n"
1701 << "void main(void)\n"
1702 << "{\n"
1703 << " uint result = 0;\n"
1704 << " vec4 a, b;\n\n"
1705 << "\n";
1706
1707 for (deUint32 sampleNdx = 0; sampleNdx < (deUint32)caseDef.numSamples; sampleNdx++)
1708 {
1709 Vec4 expectedColor = sampleIndexToColor(sampleNdx);
1710
1711 src << " a = texelFetch(colorTexture, ivec2(0,0), " << sampleNdx << ");\n"
1712 " b = vec4(" << expectedColor.x() << ", " << expectedColor.y() << ", " << expectedColor.z() << ", 1.0);\n"
1713 " if (abs(a.x - b.x) > 0.1 || abs(a.y - b.y) > 0.1 || abs(a.z - b.z) > 0.1) result++;\n";
1714 }
1715
1716 src << "\n"
1717 << " o_status = result;\n"
1718 << "}\n";
1719
1720 programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
1721 }
1722 }
1723
1724 void checkSupport (Context& context, const CaseDef caseDef)
1725 {
1726 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1727 const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice());
1728
1729 checkImageFormatRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
1730
1731 if (!props.limits.standardSampleLocations)
1732 TCU_THROW(NotSupportedError, "Device does not support standard sample locations.");
1733
1734 if (caseDef.numSamples == VK_SAMPLE_COUNT_32_BIT ||
1735 caseDef.numSamples == VK_SAMPLE_COUNT_64_BIT)
1736 {
1737 TCU_THROW(InternalError, "Standard does not define sample positions for 32x or 64x multisample modes");
1738 }
1739
1740 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1741 }
1742
1743 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1744 {
1745 const InstanceInterface& vki = context.getInstanceInterface();
1746 const DeviceInterface& vk = context.getDeviceInterface();
1747 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1748 const VkDevice device = context.getDevice();
1749 const VkQueue queue = context.getUniversalQueue();
1750 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1751 Allocator& allocator = context.getDefaultAllocator();
1752
1753 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
1754
1755 {
1756 tcu::TestLog& log = context.getTestContext().getLog();
1757 log << tcu::LogSection("Description", "")
1758 << tcu::TestLog::Message << "Rendering to a multisampled image. Expecting samples to have specified colors." << tcu::TestLog::EndMessage
1759 << tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
1760 << tcu::TestLog::EndSection;
1761 }
1762
1763 // Multisampled color image
1764 const Unique<VkImage> colorImage (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
1765 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1766
1767 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1768 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
1769
1770 // Step 1: Render to texture
1771 {
1772 renderMultisampledImage(context, caseDef, *colorImage);
1773 }
1774
1775 // Step 2: Sample texture
1776 {
1777 // Color image view
1778 const VkImageViewType colorImageViewType = (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
1779 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1780 const Unique<VkSampler> colorSampler (makeSampler(vk, device));
1781
1782 // Checksum image
1783 const VkFormat checksumFormat = VK_FORMAT_R8_UINT;
1784 const Unique<VkImage> checksumImage (makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
1785 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
1786 const UniquePtr<Allocation> checksumImageAlloc (bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
1787 const Unique<VkImageView> checksumImageView (makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
1788
1789 // Checksum buffer (for host reading)
1790 const VkDeviceSize checksumBufferSize = caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
1791 const Unique<VkBuffer> checksumBuffer (makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1792 const UniquePtr<Allocation> checksumBufferAlloc (bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
1793
1794 zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
1795
1796 // Vertex buffer
1797 const std::vector<Vertex4RGBA> vertices = genFullQuadVertices();
1798 const VkDeviceSize vertexBufferSize = sizeInBytes(vertices);
1799 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1800 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1801
1802 {
1803 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1804 flushAlloc(vk, device, *vertexBufferAlloc);
1805 }
1806
1807 // Descriptors
1808 // \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
1809
1810 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1811 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1812 .build(vk, device));
1813
1814 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1815 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1816 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1817
1818 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1819 const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1820
1821 DescriptorSetUpdateBuilder()
1822 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1823 .update(vk, device);
1824
1825 const ShaderWrapper vertexModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1826 const ShaderWrapper fragmentModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1827 RenderPassWrapper renderPass (makeSimpleRenderPass (vk, device, caseDef.pipelineConstructionType, checksumFormat));
1828 renderPass.createFramebuffer(vk, device, 1u, &checksumImage.get(), &checksumImageView.get(), static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1829 const PipelineLayoutWrapper pipelineLayout (caseDef.pipelineConstructionType, vk, device, *descriptorSetLayout);
1830 const bool isMonolithic (caseDef.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1831 std::vector<PipelineSp> pipelinesSp;
1832 std::vector<GraphicsPipelineWrapper> pipelineWrapper;
1833
1834 if (isMonolithic)
1835 {
1836 pipelinesSp = makeGraphicsPipelines(vk, device, 1u, *pipelineLayout, *renderPass, vertexModule, fragmentModule,
1837 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1838 }
1839 else
1840 {
1841 pipelineWrapper.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), caseDef.pipelineConstructionType);
1842 preparePipelineWrapper(pipelineWrapper.back(), 0u, pipelineLayout, *renderPass, vertexModule, fragmentModule,
1843 caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
1844 }
1845
1846 beginCommandBuffer(vk, *cmdBuffer);
1847
1848 // Prepare for sampling in the fragment shader
1849 {
1850 const VkImageMemoryBarrier barriers[] =
1851 {
1852 {
1853 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1854 DE_NULL, // const void* pNext;
1855 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask;
1856 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags inputMask;
1857 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
1858 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout;
1859 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1860 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
1861 *colorImage, // VkImage image;
1862 makeColorSubresourceRange(0, caseDef.numLayers), // VkImageSubresourceRange subresourceRange;
1863 },
1864 };
1865
1866 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1867 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1868 }
1869
1870 renderPass.begin(vk, *cmdBuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()), tcu::UVec4(0u));
1871
1872 if (isMonolithic)
1873 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelinesSp.back());
1874 else
1875 pipelineWrapper.back().bind(*cmdBuffer);
1876 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1877 {
1878 const VkDeviceSize vertexBufferOffset = 0ull;
1879 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1880 }
1881
1882 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1883 renderPass.end(vk, *cmdBuffer);
1884
1885 copyImageToBuffer(vk, *cmdBuffer, *checksumImage, *checksumBuffer, caseDef.renderSize);
1886
1887 endCommandBuffer(vk, *cmdBuffer);
1888 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1889
1890 // Verify result
1891
1892 {
1893 invalidateAlloc(vk, device, *checksumBufferAlloc);
1894
1895 const tcu::ConstPixelBufferAccess access (mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1896
1897 deUint32 result = access.getPixelUint(0, 0).x();
1898
1899 if (result)
1900 return tcu::TestStatus::fail(std::to_string(result) + " multisamples have unexpected color.");
1901 }
1902 }
1903
1904 return tcu::TestStatus::pass("OK");
1905 }
1906
1907 } // StandardSamplePosition ns
1908
1909
1910 std::string getSizeLayerString (const IVec2& size, const int numLayers)
1911 {
1912 std::ostringstream str;
1913 str << size.x() << "x" << size.y() << "_" << numLayers;
1914 return str.str();
1915 }
1916
1917 std::string getFormatString (const VkFormat format)
1918 {
1919 std::string name(getFormatName(format));
1920 return de::toLower(name.substr(10));
1921 }
1922
1923 void addTestCasesWithFunctions (tcu::TestCaseGroup* group,
1924 FunctionSupport1<CaseDef>::Function checkSupport,
1925 FunctionPrograms1<CaseDef>::Function initPrograms,
1926 FunctionInstance1<CaseDef>::Function testFunc,
1927 PipelineConstructionType pipelineConstructionType)
1928 {
1929 const IVec2 size[] =
1930 {
1931 IVec2(64, 64),
1932 IVec2(79, 31),
1933 };
1934 const int numLayers[] =
1935 {
1936 1, 4
1937 };
1938 const VkSampleCountFlagBits samples[] =
1939 {
1940 VK_SAMPLE_COUNT_2_BIT,
1941 VK_SAMPLE_COUNT_4_BIT,
1942 VK_SAMPLE_COUNT_8_BIT,
1943 VK_SAMPLE_COUNT_16_BIT,
1944 VK_SAMPLE_COUNT_32_BIT,
1945 VK_SAMPLE_COUNT_64_BIT,
1946 };
1947 const VkFormat format[] =
1948 {
1949 VK_FORMAT_R8G8B8A8_UNORM,
1950 VK_FORMAT_R32_UINT,
1951 VK_FORMAT_R16G16_SINT,
1952 VK_FORMAT_R32G32B32A32_SFLOAT,
1953 };
1954
1955 for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx)
1956 for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx)
1957 {
1958 MovePtr<tcu::TestCaseGroup> sizeLayerGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeLayerString(size[sizeNdx], numLayers[layerNdx]).c_str()));
1959 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1960 {
1961 MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str()));
1962 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
1963 {
1964 std::ostringstream caseName;
1965 caseName << "samples_" << getNumSamples(samples[samplesNdx]);
1966
1967 const CaseDef caseDef
1968 {
1969 pipelineConstructionType, // PipelineConstructionType pipelineConstructionType;
1970 size[sizeNdx], // IVec2 renderSize;
1971 numLayers[layerNdx], // int numLayers;
1972 format[formatNdx], // VkFormat colorFormat;
1973 samples[samplesNdx], // VkSampleCountFlagBits numSamples;
1974 false, // bool colorQuad;
1975 };
1976
1977 addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), checkSupport, initPrograms, testFunc, caseDef);
1978 }
1979 sizeLayerGroup->addChild(formatGroup.release());
1980 }
1981 group->addChild(sizeLayerGroup.release());
1982 }
1983 }
1984
1985 void addStandardSamplePositionTestCasesWithFunctions (tcu::TestCaseGroup* group,
1986 FunctionSupport1<CaseDef>::Function checkSupport,
1987 FunctionPrograms1<CaseDef>::Function initPrograms,
1988 FunctionInstance1<CaseDef>::Function testFunc,
1989 PipelineConstructionType pipelineConstructionType)
1990 {
1991 const VkSampleCountFlagBits samples[] =
1992 {
1993 VK_SAMPLE_COUNT_2_BIT,
1994 VK_SAMPLE_COUNT_4_BIT,
1995 VK_SAMPLE_COUNT_8_BIT,
1996 VK_SAMPLE_COUNT_16_BIT,
1997 VK_SAMPLE_COUNT_32_BIT,
1998 VK_SAMPLE_COUNT_64_BIT,
1999 };
2000 const VkFormat format[] =
2001 {
2002 VK_FORMAT_R8G8B8A8_UNORM,
2003 VK_FORMAT_R32G32B32A32_SFLOAT,
2004 };
2005
2006 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
2007 {
2008 MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str()));
2009 for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
2010 {
2011 std::ostringstream caseName;
2012 caseName << "samples_" << getNumSamples(samples[samplesNdx]);
2013
2014 const CaseDef caseDef
2015 {
2016 pipelineConstructionType, // PipelineConstructionType pipelineConstructionType;
2017 IVec2(1,1), // IVec2 renderSize;
2018 1, // int numLayers;
2019 format[formatNdx], // VkFormat colorFormat;
2020 samples[samplesNdx], // VkSampleCountFlagBits numSamples;
2021 true, // bool colorQuad;
2022 };
2023
2024 addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), checkSupport, initPrograms, testFunc, caseDef);
2025 }
2026 group->addChild(formatGroup.release());
2027 }
2028 }
2029
2030 void createSampledImageTestsInGroup (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
2031 {
2032 addTestCasesWithFunctions(group, SampledImage::checkSupport, SampledImage::initPrograms, SampledImage::test, pipelineConstructionType);
2033 }
2034
2035 void createStorageImageTestsInGroup (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
2036 {
2037 addTestCasesWithFunctions(group, StorageImage::checkSupport, StorageImage::initPrograms, StorageImage::test, pipelineConstructionType);
2038 }
2039
2040 void createStandardSamplePositionTestsInGroup (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
2041 {
2042 addStandardSamplePositionTestCasesWithFunctions(group, StandardSamplePosition::checkSupport, StandardSamplePosition::initPrograms, StandardSamplePosition::test, pipelineConstructionType);
2043 }
2044
2045 } // anonymous ns
2046
2047 //! Render to a multisampled image and sample from it in a fragment shader.
2048 tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2049 {
2050 return createTestGroup(testCtx, "sampled_image", createSampledImageTestsInGroup, pipelineConstructionType);
2051 }
2052
2053 //! Render to a multisampled image and access it with load/stores in a compute shader.
2054 tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2055 {
2056 return createTestGroup(testCtx, "storage_image", createStorageImageTestsInGroup, pipelineConstructionType);
2057 }
2058
2059 //! Render to a multisampled image and verify standard multisample positions.
2060 tcu::TestCaseGroup* createMultisampleStandardSamplePositionTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2061 {
2062 return createTestGroup(testCtx, "standardsampleposition", createStandardSamplePositionTestsInGroup, pipelineConstructionType);
2063 }
2064
2065 } // pipeline
2066 } // vkt
2067