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