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