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