1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*
22 * \file vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp
23 * \brief Base class for tests that check results of multisample resolve
24 * and/or values of individual samples
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp"
28 #include "vktPipelineMakeUtil.hpp"
29 #include "vkBarrierUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkBufferWithMemory.hpp"
36 #include "vkImageWithMemory.hpp"
37 #include "tcuTestLog.hpp"
38 #include <vector>
39
40 namespace vkt
41 {
42 namespace pipeline
43 {
44 namespace multisample
45 {
46
47 using namespace vk;
48
initPrograms(vk::SourceCollections& programCollection) const49 void MSCaseBaseResolveAndPerSampleFetch::initPrograms (vk::SourceCollections& programCollection) const
50 {
51 // Create vertex shader
52 std::ostringstream vs;
53
54 vs << "#version 440\n"
55 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
56 << "\n"
57 << "out gl_PerVertex {\n"
58 << " vec4 gl_Position;\n"
59 << "};\n"
60 << "void main (void)\n"
61 << "{\n"
62 << " gl_Position = vs_in_position_ndc;\n"
63 << "}\n";
64
65 programCollection.glslSources.add("per_sample_fetch_vs") << glu::VertexSource(vs.str());
66
67 // Create fragment shader
68 std::ostringstream fs;
69
70 fs << "#version 440\n"
71 << "\n"
72 << "layout(location = 0) out vec4 fs_out_color;\n"
73 << "\n"
74 << "layout(set = 0, binding = 0, input_attachment_index = 0) uniform subpassInputMS imageMS;\n"
75 << "\n"
76 << "layout(set = 0, binding = 1, std140) uniform SampleBlock {\n"
77 << " int sampleNdx;\n"
78 << "};\n"
79 << "void main (void)\n"
80 << "{\n"
81 << " fs_out_color = subpassLoad(imageMS, sampleNdx);\n"
82 << "}\n";
83
84 programCollection.glslSources.add("per_sample_fetch_fs") << glu::FragmentSource(fs.str());
85 }
86
MSInstanceBaseResolveAndPerSampleFetch(Context& context, const ImageMSParams& imageMSParams)87 MSInstanceBaseResolveAndPerSampleFetch::MSInstanceBaseResolveAndPerSampleFetch (Context& context, const ImageMSParams& imageMSParams)
88 : MultisampleInstanceBase(context, imageMSParams) {}
89
getMSStateCreateInfo(const ImageMSParams& imageMSParams) const90 VkPipelineMultisampleStateCreateInfo MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const
91 {
92 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
93 {
94 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
95 DE_NULL, // const void* pNext;
96 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags;
97 imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples;
98 VK_TRUE, // VkBool32 sampleShadingEnable;
99 imageMSParams.shadingRate, // float minSampleShading;
100 DE_NULL, // const VkSampleMask* pSampleMask;
101 VK_FALSE, // VkBool32 alphaToCoverageEnable;
102 VK_FALSE, // VkBool32 alphaToOneEnable;
103 };
104
105 return multisampleStateInfo;
106 }
107
createMSPassDescSetLayout(const ImageMSParams& imageMSParams)108 const VkDescriptorSetLayout* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSetLayout(const ImageMSParams& imageMSParams)
109 {
110 DE_UNREF(imageMSParams);
111
112 return DE_NULL;
113 }
114
createMSPassDescSet(const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)115 const VkDescriptorSet* MSInstanceBaseResolveAndPerSampleFetch::createMSPassDescSet(const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout)
116 {
117 DE_UNREF(imageMSParams);
118 DE_UNREF(descSetLayout);
119
120 return DE_NULL;
121 }
122
iterate(void)123 tcu::TestStatus MSInstanceBaseResolveAndPerSampleFetch::iterate (void)
124 {
125 const InstanceInterface& instance = m_context.getInstanceInterface();
126 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
127 const VkDevice device = m_context.getDevice();
128 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
129 Allocator& allocator = m_context.getDefaultAllocator();
130 const VkQueue queue = m_context.getUniversalQueue();
131 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
132
133 VkImageCreateInfo imageMSInfo;
134 VkImageCreateInfo imageRSInfo;
135 const deUint32 firstSubpassAttachmentsCount = 2u;
136
137 // Check if image size does not exceed device limits
138 validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
139
140 // Check if device supports image format as color attachment
141 validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
142
143 imageMSInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
144 imageMSInfo.pNext = DE_NULL;
145 imageMSInfo.flags = 0u;
146 imageMSInfo.imageType = mapImageType(m_imageType);
147 imageMSInfo.format = mapTextureFormat(m_imageFormat);
148 imageMSInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
149 imageMSInfo.arrayLayers = getNumLayers(m_imageType, m_imageMSParams.imageSize);
150 imageMSInfo.mipLevels = 1u;
151 imageMSInfo.samples = m_imageMSParams.numSamples;
152 imageMSInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
153 imageMSInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
154 imageMSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
155 imageMSInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
156 imageMSInfo.queueFamilyIndexCount = 0u;
157 imageMSInfo.pQueueFamilyIndices = DE_NULL;
158
159 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
160 {
161 imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
162 }
163
164 validateImageInfo(instance, physicalDevice, imageMSInfo);
165
166 const de::UniquePtr<ImageWithMemory> imageMS(new ImageWithMemory(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
167
168 imageRSInfo = imageMSInfo;
169 imageRSInfo.samples = VK_SAMPLE_COUNT_1_BIT;
170 imageRSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
171
172 validateImageInfo(instance, physicalDevice, imageRSInfo);
173
174 const de::UniquePtr<ImageWithMemory> imageRS(new ImageWithMemory(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
175
176 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples);
177
178 std::vector<de::SharedPtr<ImageWithMemory> > imagesPerSampleVec(numSamples);
179
180 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
181 {
182 imagesPerSampleVec[sampleNdx] = de::SharedPtr<ImageWithMemory>(new ImageWithMemory(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
183 }
184
185 // Create render pass
186 std::vector<VkAttachmentDescription> attachments(firstSubpassAttachmentsCount + numSamples);
187
188 {
189 const VkAttachmentDescription attachmentMSDesc =
190 {
191 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
192 imageMSInfo.format, // VkFormat format;
193 imageMSInfo.samples, // VkSampleCountFlagBits samples;
194 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
195 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
196 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
197 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
198 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
199 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout;
200 };
201
202 attachments[0] = attachmentMSDesc;
203
204 const VkAttachmentDescription attachmentRSDesc =
205 {
206 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
207 imageRSInfo.format, // VkFormat format;
208 imageRSInfo.samples, // VkSampleCountFlagBits samples;
209 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
210 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
211 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
212 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
213 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
214 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
215 };
216
217 attachments[1] = attachmentRSDesc;
218
219 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
220 {
221 attachments[firstSubpassAttachmentsCount + sampleNdx] = attachmentRSDesc;
222 }
223 }
224
225 const VkAttachmentReference attachmentMSColorRef =
226 {
227 0u, // deUint32 attachment;
228 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
229 };
230
231 const VkAttachmentReference attachmentMSInputRef =
232 {
233 0u, // deUint32 attachment;
234 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout layout;
235 };
236
237 const VkAttachmentReference attachmentRSColorRef =
238 {
239 1u, // deUint32 attachment;
240 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
241 };
242
243 std::vector<VkAttachmentReference> perSampleAttachmentRef(numSamples);
244
245 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
246 {
247 const VkAttachmentReference attachmentRef =
248 {
249 firstSubpassAttachmentsCount + sampleNdx, // deUint32 attachment;
250 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
251 };
252
253 perSampleAttachmentRef[sampleNdx] = attachmentRef;
254 }
255
256 std::vector<deUint32> preserveAttachments(1u + numSamples);
257
258 for (deUint32 attachNdx = 0u; attachNdx < 1u + numSamples; ++attachNdx)
259 {
260 preserveAttachments[attachNdx] = 1u + attachNdx;
261 }
262
263 std::vector<VkSubpassDescription> subpasses(1u + numSamples);
264 std::vector<VkSubpassDependency> subpassDependencies;
265
266 const VkSubpassDescription firstSubpassDesc =
267 {
268 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags;
269 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
270 0u, // deUint32 inputAttachmentCount;
271 DE_NULL, // const VkAttachmentReference* pInputAttachments;
272 1u, // deUint32 colorAttachmentCount;
273 &attachmentMSColorRef, // const VkAttachmentReference* pColorAttachments;
274 &attachmentRSColorRef, // const VkAttachmentReference* pResolveAttachments;
275 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
276 0u, // deUint32 preserveAttachmentCount;
277 DE_NULL // const deUint32* pPreserveAttachments;
278 };
279
280 subpasses[0] = firstSubpassDesc;
281
282 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
283 {
284 const VkSubpassDescription subpassDesc =
285 {
286 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags;
287 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
288 1u, // deUint32 inputAttachmentCount;
289 &attachmentMSInputRef, // const VkAttachmentReference* pInputAttachments;
290 1u, // deUint32 colorAttachmentCount;
291 &perSampleAttachmentRef[sampleNdx], // const VkAttachmentReference* pColorAttachments;
292 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
293 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
294 1u + sampleNdx, // deUint32 preserveAttachmentCount;
295 dataPointer(preserveAttachments) // const deUint32* pPreserveAttachments;
296 };
297
298 subpasses[1u + sampleNdx] = subpassDesc;
299
300 if (sampleNdx == 0u)
301 {
302 // The second subpass will be in charge of transitioning the multisample attachment from
303 // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.
304 const VkSubpassDependency subpassDependency =
305 {
306 0u, // uint32_t srcSubpass;
307 1u + sampleNdx, // uint32_t dstSubpass;
308 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask;
309 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask;
310 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
311 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
312 0u, // VkDependencyFlags dependencyFlags;
313 };
314
315 subpassDependencies.push_back(subpassDependency);
316 }
317 else
318 {
319 // Make sure subpass reads are in order. This serializes subpasses to make sure there are no layout transition hazards
320 // in the multisample image, from VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
321 // caused by parallel execution of several subpasses.
322 const VkSubpassDependency readDependency =
323 {
324 sampleNdx, // uint32_t srcSubpass;
325 1u + sampleNdx, // uint32_t dstSubpass;
326 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags srcStageMask;
327 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask;
328 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags srcAccessMask;
329 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
330 0u, // VkDependencyFlags dependencyFlags;
331 };
332
333 subpassDependencies.push_back(readDependency);
334 }
335 }
336
337 const VkRenderPassCreateInfo renderPassInfo =
338 {
339 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
340 DE_NULL, // const void* pNext;
341 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags;
342 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount;
343 dataPointer(attachments), // const VkAttachmentDescription* pAttachments;
344 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
345 dataPointer(subpasses), // const VkSubpassDescription* pSubpasses;
346 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount;
347 dataPointer(subpassDependencies) // const VkSubpassDependency* pDependencies;
348 };
349
350 RenderPassWrapper renderPass (m_imageMSParams.pipelineConstructionType, deviceInterface, device, &renderPassInfo);
351
352 const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
353
354 // Create color attachments image views
355 typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp;
356 std::vector<VkImageViewSp> imageViewsShPtrs(firstSubpassAttachmentsCount + numSamples);
357 std::vector<VkImage> images(firstSubpassAttachmentsCount + numSamples);
358 std::vector<VkImageView> imageViews(firstSubpassAttachmentsCount + numSamples);
359
360 images[0] = **imageMS;
361 images[1] = **imageRS;
362
363 imageViewsShPtrs[0] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
364 imageViewsShPtrs[1] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange));
365
366 imageViews[0] = **imageViewsShPtrs[0];
367 imageViews[1] = **imageViewsShPtrs[1];
368
369 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
370 {
371 images[firstSubpassAttachmentsCount + sampleNdx] = **imagesPerSampleVec[sampleNdx];
372 imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imagesPerSampleVec[sampleNdx], mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange));
373 imageViews[firstSubpassAttachmentsCount + sampleNdx] = **imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx];
374 }
375
376 // Create framebuffer
377 const VkFramebufferCreateInfo framebufferInfo =
378 {
379 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
380 DE_NULL, // const void* pNext;
381 (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags;
382 *renderPass, // VkRenderPass renderPass;
383 static_cast<deUint32>(imageViews.size()), // uint32_t attachmentCount;
384 dataPointer(imageViews), // const VkImageView* pAttachments;
385 imageMSInfo.extent.width, // uint32_t width;
386 imageMSInfo.extent.height, // uint32_t height;
387 imageMSInfo.arrayLayers, // uint32_t layers;
388 };
389
390 renderPass.createFramebuffer(deviceInterface, device, &framebufferInfo, images);
391
392 const VkDescriptorSetLayout* descriptorSetLayoutMSPass = createMSPassDescSetLayout(m_imageMSParams);
393
394 // Create pipeline layout
395 const VkPipelineLayoutCreateInfo pipelineLayoutMSPassParams =
396 {
397 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
398 DE_NULL, // const void* pNext;
399 (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags;
400 descriptorSetLayoutMSPass ? 1u : 0u, // deUint32 setLayoutCount;
401 descriptorSetLayoutMSPass, // const VkDescriptorSetLayout* pSetLayouts;
402 0u, // deUint32 pushConstantRangeCount;
403 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
404 };
405
406 const PipelineLayoutWrapper pipelineLayoutMSPass(m_imageMSParams.pipelineConstructionType, deviceInterface, device, &pipelineLayoutMSPassParams);
407
408 // Create vertex attributes data
409 const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
410
411 de::SharedPtr<BufferWithMemory> vertexBuffer = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
412 const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
413
414 uploadVertexData(vertexBufferAllocation, vertexDataDesc);
415
416 flushAlloc(deviceInterface, device, vertexBufferAllocation);
417
418 const VkVertexInputBindingDescription vertexBinding =
419 {
420 0u, // deUint32 binding;
421 vertexDataDesc.dataStride, // deUint32 stride;
422 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
423 };
424
425 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
426 {
427 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
428 DE_NULL, // const void* pNext;
429 (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags;
430 1u, // uint32_t vertexBindingDescriptionCount;
431 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
432 static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()), // uint32_t vertexAttributeDescriptionCount;
433 dataPointer(vertexDataDesc.vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
434 };
435
436 const std::vector<VkViewport> viewports { makeViewport(imageMSInfo.extent) };
437 const std::vector<VkRect2D> scissors { makeRect2D(imageMSInfo.extent) };
438
439 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = getMSStateCreateInfo(m_imageMSParams);
440
441 // Create graphics pipeline for multisample pass
442 const ShaderWrapper vsMSPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0u));
443 const ShaderWrapper fsMSPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0u));
444
445 GraphicsPipelineWrapper graphicsPipelineMSPass(instance, deviceInterface, physicalDevice, device, m_context.getDeviceExtensions(), m_imageMSParams.pipelineConstructionType);
446 graphicsPipelineMSPass.setDefaultColorBlendState()
447 .setDefaultDepthStencilState()
448 .setDefaultRasterizationState()
449 .setDefaultTopology(vertexDataDesc.primitiveTopology)
450 .setupVertexInputState(&vertexInputStateInfo)
451 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayoutMSPass, *renderPass, 0u, vsMSPassModule)
452 .setupFragmentShaderState(pipelineLayoutMSPass, *renderPass, 0u, fsMSPassModule, DE_NULL, &multisampleStateInfo)
453 .setupFragmentOutputState(*renderPass, 0u, DE_NULL, &multisampleStateInfo)
454 .setMonolithicPipelineLayout(pipelineLayoutMSPass)
455 .buildPipeline();
456
457 std::vector<GraphicsPipelineWrapper> graphicsPipelinesPerSampleFetch;
458 graphicsPipelinesPerSampleFetch.reserve(numSamples);
459
460 // Create descriptor set layout
461 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
462 DescriptorSetLayoutBuilder()
463 .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
464 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT)
465 .build(deviceInterface, device));
466
467 const PipelineLayoutWrapper pipelineLayoutPerSampleFetchPass(m_imageMSParams.pipelineConstructionType, deviceInterface, device, *descriptorSetLayout);
468
469 const deUint32 bufferPerSampleFetchPassSize = 4u * (deUint32)sizeof(tcu::Vec4);
470
471 de::SharedPtr<BufferWithMemory> vertexBufferPerSampleFetchPass = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, makeBufferCreateInfo(bufferPerSampleFetchPassSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
472
473 // Create graphics pipelines for per sample texel fetch passes
474 {
475 const ShaderWrapper vsPerSampleFetchPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_vs"), (VkShaderModuleCreateFlags)0u));
476 const ShaderWrapper fsPerSampleFetchPassModule(ShaderWrapper(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_fs"), (VkShaderModuleCreateFlags)0u));
477
478 std::vector<tcu::Vec4> vertices;
479
480 vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
481 vertices.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
482 vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
483 vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));
484
485 const Allocation& vertexAllocPerSampleFetchPass = vertexBufferPerSampleFetchPass->getAllocation();
486
487 deMemcpy(vertexAllocPerSampleFetchPass.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(bufferPerSampleFetchPassSize));
488
489 flushAlloc(deviceInterface, device, vertexAllocPerSampleFetchPass);
490
491 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
492 {
493 const deUint32 subpass = 1u + sampleNdx;
494 graphicsPipelinesPerSampleFetch.emplace_back(instance, deviceInterface, physicalDevice, device, m_context.getDeviceExtensions(), m_imageMSParams.pipelineConstructionType);
495 graphicsPipelinesPerSampleFetch.back()
496 .setDefaultMultisampleState()
497 .setDefaultColorBlendState()
498 .setDefaultDepthStencilState()
499 .setDefaultRasterizationState()
500 .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
501 .setupVertexInputState()
502 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayoutPerSampleFetchPass, *renderPass, subpass, vsPerSampleFetchPassModule)
503 .setupFragmentShaderState(pipelineLayoutPerSampleFetchPass, *renderPass, subpass, fsPerSampleFetchPassModule)
504 .setupFragmentOutputState(*renderPass, subpass)
505 .setMonolithicPipelineLayout(pipelineLayoutPerSampleFetchPass)
506 .buildPipeline();
507 }
508 }
509
510 // Create descriptor pool
511 const Unique<VkDescriptorPool> descriptorPool(
512 DescriptorPoolBuilder()
513 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
514 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1u)
515 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
516
517 // Create descriptor set
518 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(deviceInterface, device, *descriptorPool, *descriptorSetLayout));
519
520 const VkPhysicalDeviceLimits deviceLimits = getPhysicalDeviceProperties(instance, physicalDevice).limits;
521
522 VkDeviceSize uboOffsetAlignment = sizeof(deInt32) < deviceLimits.minUniformBufferOffsetAlignment ? deviceLimits.minUniformBufferOffsetAlignment : sizeof(deInt32);
523
524 uboOffsetAlignment += (deviceLimits.minUniformBufferOffsetAlignment - uboOffsetAlignment % deviceLimits.minUniformBufferOffsetAlignment) % deviceLimits.minUniformBufferOffsetAlignment;
525
526 const VkBufferCreateInfo bufferSampleIDInfo = makeBufferCreateInfo(uboOffsetAlignment * numSamples, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
527 const de::UniquePtr<BufferWithMemory> bufferSampleID(new BufferWithMemory(deviceInterface, device, allocator, bufferSampleIDInfo, MemoryRequirement::HostVisible));
528
529 std::vector<deUint32> sampleIDsOffsets(numSamples);
530
531 {
532 deInt8* sampleIDs = new deInt8[static_cast<deUint32>(uboOffsetAlignment) * numSamples];
533
534 for (deInt32 sampleNdx = 0u; sampleNdx < static_cast<deInt32>(numSamples); ++sampleNdx)
535 {
536 sampleIDsOffsets[sampleNdx] = static_cast<deUint32>(sampleNdx * uboOffsetAlignment);
537 deInt8* samplePtr = sampleIDs + sampleIDsOffsets[sampleNdx];
538
539 deMemcpy(samplePtr, &sampleNdx, sizeof(deInt32));
540 }
541
542 deMemcpy(bufferSampleID->getAllocation().getHostPtr(), sampleIDs, static_cast<deUint32>(uboOffsetAlignment * numSamples));
543
544 flushAlloc(deviceInterface, device, bufferSampleID->getAllocation());
545
546 delete[] sampleIDs;
547 }
548
549 {
550 const VkDescriptorImageInfo descImageInfo = makeDescriptorImageInfo(DE_NULL, imageViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
551 const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**bufferSampleID, 0u, sizeof(deInt32));
552
553 DescriptorSetUpdateBuilder()
554 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descImageInfo)
555 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &descBufferInfo)
556 .update(deviceInterface, device);
557 }
558
559 // Create command buffer for compute and transfer oparations
560 const Unique<VkCommandPool> commandPool(createCommandPool(deviceInterface, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
561 const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
562
563 // Start recording commands
564 beginCommandBuffer(deviceInterface, *commandBuffer);
565
566 {
567 std::vector<VkImageMemoryBarrier> imageOutputAttachmentBarriers(firstSubpassAttachmentsCount + numSamples);
568
569 imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
570 (
571 0u,
572 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
573 VK_IMAGE_LAYOUT_UNDEFINED,
574 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
575 **imageMS,
576 fullImageRange
577 );
578
579 imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
580 (
581 0u,
582 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
583 VK_IMAGE_LAYOUT_UNDEFINED,
584 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
585 **imageRS,
586 fullImageRange
587 );
588
589 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
590 {
591 imageOutputAttachmentBarriers[firstSubpassAttachmentsCount + sampleNdx] = makeImageMemoryBarrier
592 (
593 0u,
594 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
595 VK_IMAGE_LAYOUT_UNDEFINED,
596 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
597 **imagesPerSampleVec[sampleNdx],
598 fullImageRange
599 );
600 }
601
602 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
603 static_cast<deUint32>(imageOutputAttachmentBarriers.size()), dataPointer(imageOutputAttachmentBarriers));
604 }
605
606 {
607 const VkDeviceSize vertexStartOffset = 0u;
608
609 std::vector<VkClearValue> clearValues(firstSubpassAttachmentsCount + numSamples);
610 for (deUint32 attachmentNdx = 0u; attachmentNdx < firstSubpassAttachmentsCount + numSamples; ++attachmentNdx)
611 {
612 clearValues[attachmentNdx] = makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
613 }
614
615 renderPass.begin(deviceInterface, *commandBuffer, makeRect2D(0, 0, imageMSInfo.extent.width, imageMSInfo.extent.height), (deUint32)clearValues.size(), dataPointer(clearValues));
616
617 // Bind graphics pipeline
618 graphicsPipelineMSPass.bind(*commandBuffer);
619
620 const VkDescriptorSet* descriptorSetMSPass = createMSPassDescSet(m_imageMSParams, descriptorSetLayoutMSPass);
621
622 if (descriptorSetMSPass)
623 {
624 // Bind descriptor set
625 deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutMSPass, 0u, 1u, descriptorSetMSPass, 0u, DE_NULL);
626 }
627
628 // Bind vertex buffer
629 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
630
631 // Perform a draw
632 deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
633
634 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
635 {
636 renderPass.nextSubpass(deviceInterface, *commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
637
638 // Bind graphics pipeline
639 graphicsPipelinesPerSampleFetch[sampleNdx].bind(*commandBuffer);
640
641 // Bind descriptor set
642 deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPerSampleFetchPass, 0u, 1u, &descriptorSet.get(), 1u, &sampleIDsOffsets[sampleNdx]);
643
644 // Bind vertex buffer
645 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBufferPerSampleFetchPass->get(), &vertexStartOffset);
646
647 // Perform a draw
648 deviceInterface.cmdDraw(*commandBuffer, 4u, 1u, 0u, 0u);
649 }
650
651 // End render pass
652 renderPass.end(deviceInterface, *commandBuffer);
653 }
654
655 {
656 const VkImageMemoryBarrier imageRSTransferBarrier = makeImageMemoryBarrier
657 (
658 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
659 VK_ACCESS_TRANSFER_READ_BIT,
660 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
661 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
662 **imageRS,
663 fullImageRange
664 );
665
666 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageRSTransferBarrier);
667 }
668
669 // Copy data from imageRS to buffer
670 const deUint32 imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels, 1u);
671
672 const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
673 const de::UniquePtr<BufferWithMemory> bufferRS(new BufferWithMemory(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
674
675 {
676 const VkBufferImageCopy bufferImageCopy =
677 {
678 0u, // VkDeviceSize bufferOffset;
679 0u, // deUint32 bufferRowLength;
680 0u, // deUint32 bufferImageHeight;
681 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
682 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
683 imageRSInfo.extent, // VkExtent3D imageExtent;
684 };
685
686 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imageRS, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
687 }
688
689 {
690 const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
691 (
692 VK_ACCESS_TRANSFER_WRITE_BIT,
693 VK_ACCESS_HOST_READ_BIT,
694 bufferRS->get(),
695 0u,
696 imageRSSizeInBytes
697 );
698
699 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
700 }
701
702 // Copy data from per sample images to buffers
703 std::vector<VkImageMemoryBarrier> imagesPerSampleTransferBarriers(numSamples);
704
705 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
706 {
707 imagesPerSampleTransferBarriers[sampleNdx] = makeImageMemoryBarrier
708 (
709 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
710 VK_ACCESS_TRANSFER_READ_BIT,
711 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
712 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
713 **imagesPerSampleVec[sampleNdx],
714 fullImageRange
715 );
716 }
717
718 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
719 static_cast<deUint32>(imagesPerSampleTransferBarriers.size()), dataPointer(imagesPerSampleTransferBarriers));
720
721 std::vector<de::SharedPtr<BufferWithMemory> > buffersPerSample(numSamples);
722
723 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
724 {
725 buffersPerSample[sampleNdx] = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
726
727 const VkBufferImageCopy bufferImageCopy =
728 {
729 0u, // VkDeviceSize bufferOffset;
730 0u, // deUint32 bufferRowLength;
731 0u, // deUint32 bufferImageHeight;
732 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
733 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
734 imageRSInfo.extent, // VkExtent3D imageExtent;
735 };
736
737 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imagesPerSampleVec[sampleNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffersPerSample[sampleNdx], 1u, &bufferImageCopy);
738 }
739
740 std::vector<VkBufferMemoryBarrier> buffersPerSampleHostReadBarriers(numSamples);
741
742 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
743 {
744 buffersPerSampleHostReadBarriers[sampleNdx] = makeBufferMemoryBarrier
745 (
746 VK_ACCESS_TRANSFER_WRITE_BIT,
747 VK_ACCESS_HOST_READ_BIT,
748 **buffersPerSample[sampleNdx],
749 0u,
750 imageRSSizeInBytes
751 );
752 }
753
754 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
755 static_cast<deUint32>(buffersPerSampleHostReadBarriers.size()), dataPointer(buffersPerSampleHostReadBarriers), 0u, DE_NULL);
756
757 // End recording commands
758 endCommandBuffer(deviceInterface, *commandBuffer);
759
760 // Submit commands for execution and wait for completion
761 submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
762
763 // Retrieve data from bufferRS to host memory
764 const Allocation& bufferRSAlloc = bufferRS->getAllocation();
765
766 invalidateAlloc(deviceInterface, device, bufferRSAlloc);
767
768 const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
769 imageRSInfo.extent.width,
770 imageRSInfo.extent.height,
771 imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
772 bufferRSAlloc.getHostPtr());
773
774 std::stringstream resolveName;
775 resolveName << "Resolve image " << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
776
777 m_context.getTestContext().getLog()
778 << tcu::TestLog::Section(resolveName.str(), resolveName.str())
779 << tcu::LogImage("resolve", "", bufferRSData)
780 << tcu::TestLog::EndSection;
781
782 std::vector<tcu::ConstPixelBufferAccess> buffersPerSampleData(numSamples);
783
784 // Retrieve data from per sample buffers to host memory
785 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
786 {
787 const Allocation& bufferAlloc = buffersPerSample[sampleNdx]->getAllocation();
788
789 invalidateAlloc(deviceInterface, device, bufferAlloc);
790
791 buffersPerSampleData[sampleNdx] = tcu::ConstPixelBufferAccess
792 (
793 m_imageFormat,
794 imageRSInfo.extent.width,
795 imageRSInfo.extent.height,
796 imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
797 bufferAlloc.getHostPtr()
798 );
799
800 std::stringstream sampleName;
801 sampleName << "Sample " << sampleNdx << " image" << std::endl;
802
803 m_context.getTestContext().getLog()
804 << tcu::TestLog::Section(sampleName.str(), sampleName.str())
805 << tcu::LogImage("sample", "", buffersPerSampleData[sampleNdx])
806 << tcu::TestLog::EndSection;
807 }
808
809 return verifyImageData(imageMSInfo, imageRSInfo, buffersPerSampleData, bufferRSData);
810 }
811
812 } // multisample
813 } // pipeline
814 } // vkt
815