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 const VkSubpassDependency subpassDependency =
299 {
300 0u, // uint32_t srcSubpass;
301 1u + sampleNdx, // uint32_t dstSubpass;
302 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask;
303 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask;
304 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
305 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
306 0u, // VkDependencyFlags dependencyFlags;
307 };
308
309 subpassDependencies.push_back(subpassDependency);
310 }
311 // now handle the very last sample pass, which must synchronize with all prior subpasses
312 for (deUint32 sampleNdx = 0u; sampleNdx < (numSamples - 1); ++sampleNdx)
313 {
314 const VkSubpassDependency subpassDependency =
315 {
316 1u + sampleNdx, // uint32_t srcSubpass;
317 numSamples, // uint32_t dstSubpass;
318 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask;
319 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask;
320 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask;
321 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask;
322 0u, // VkDependencyFlags dependencyFlags;
323 };
324
325 subpassDependencies.push_back(subpassDependency);
326 }
327
328 const VkRenderPassCreateInfo renderPassInfo =
329 {
330 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
331 DE_NULL, // const void* pNext;
332 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags;
333 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount;
334 dataPointer(attachments), // const VkAttachmentDescription* pAttachments;
335 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount;
336 dataPointer(subpasses), // const VkSubpassDescription* pSubpasses;
337 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount;
338 dataPointer(subpassDependencies) // const VkSubpassDependency* pDependencies;
339 };
340
341 const Unique<VkRenderPass> renderPass(createRenderPass(deviceInterface, device, &renderPassInfo));
342
343 const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
344
345 // Create color attachments image views
346 typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp;
347 std::vector<VkImageViewSp> imageViewsShPtrs(firstSubpassAttachmentsCount + numSamples);
348 std::vector<VkImageView> imageViews(firstSubpassAttachmentsCount + numSamples);
349
350 imageViewsShPtrs[0] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
351 imageViewsShPtrs[1] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange));
352
353 imageViews[0] = **imageViewsShPtrs[0];
354 imageViews[1] = **imageViewsShPtrs[1];
355
356 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
357 {
358 imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx] = makeVkSharedPtr(makeImageView(deviceInterface, device, **imagesPerSampleVec[sampleNdx], mapImageViewType(m_imageType), imageRSInfo.format, fullImageRange));
359 imageViews[firstSubpassAttachmentsCount + sampleNdx] = **imageViewsShPtrs[firstSubpassAttachmentsCount + sampleNdx];
360 }
361
362 // Create framebuffer
363 const VkFramebufferCreateInfo framebufferInfo =
364 {
365 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
366 DE_NULL, // const void* pNext;
367 (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags;
368 *renderPass, // VkRenderPass renderPass;
369 static_cast<deUint32>(imageViews.size()), // uint32_t attachmentCount;
370 dataPointer(imageViews), // const VkImageView* pAttachments;
371 imageMSInfo.extent.width, // uint32_t width;
372 imageMSInfo.extent.height, // uint32_t height;
373 imageMSInfo.arrayLayers, // uint32_t layers;
374 };
375
376 const Unique<VkFramebuffer> framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo));
377
378 const VkDescriptorSetLayout* descriptorSetLayoutMSPass = createMSPassDescSetLayout(m_imageMSParams);
379
380 // Create pipeline layout
381 const VkPipelineLayoutCreateInfo pipelineLayoutMSPassParams =
382 {
383 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
384 DE_NULL, // const void* pNext;
385 (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags;
386 descriptorSetLayoutMSPass ? 1u : 0u, // deUint32 setLayoutCount;
387 descriptorSetLayoutMSPass, // const VkDescriptorSetLayout* pSetLayouts;
388 0u, // deUint32 pushConstantRangeCount;
389 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
390 };
391
392 const Unique<VkPipelineLayout> pipelineLayoutMSPass(createPipelineLayout(deviceInterface, device, &pipelineLayoutMSPassParams));
393
394 // Create vertex attributes data
395 const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
396
397 de::SharedPtr<BufferWithMemory> vertexBuffer = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
398 const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
399
400 uploadVertexData(vertexBufferAllocation, vertexDataDesc);
401
402 flushAlloc(deviceInterface, device, vertexBufferAllocation);
403
404 const VkVertexInputBindingDescription vertexBinding =
405 {
406 0u, // deUint32 binding;
407 vertexDataDesc.dataStride, // deUint32 stride;
408 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
409 };
410
411 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
412 {
413 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
414 DE_NULL, // const void* pNext;
415 (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags;
416 1u, // uint32_t vertexBindingDescriptionCount;
417 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
418 static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()), // uint32_t vertexAttributeDescriptionCount;
419 dataPointer(vertexDataDesc.vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
420 };
421
422 const std::vector<VkViewport> viewports { makeViewport(imageMSInfo.extent) };
423 const std::vector<VkRect2D> scissors { makeRect2D(imageMSInfo.extent) };
424
425 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = getMSStateCreateInfo(m_imageMSParams);
426
427 // Create graphics pipeline for multisample pass
428 const Unique<VkShaderModule> vsMSPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0u));
429 const Unique<VkShaderModule> fsMSPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0u));
430
431 GraphicsPipelineWrapper graphicsPipelineMSPass(deviceInterface, device, m_imageMSParams.pipelineConstructionType);
432 graphicsPipelineMSPass.setDefaultColorBlendState()
433 .setDefaultDepthStencilState()
434 .setDefaultRasterizationState()
435 .setDefaultTopology(vertexDataDesc.primitiveTopology)
436 .setupVertexInputState(&vertexInputStateInfo)
437 .setupPreRasterizationShaderState(viewports, scissors, *pipelineLayoutMSPass, *renderPass, 0u, *vsMSPassModule)
438 .setupFragmentShaderState(*pipelineLayoutMSPass, *renderPass, 0u, *fsMSPassModule, DE_NULL, &multisampleStateInfo)
439 .setupFragmentOutputState(*renderPass, 0u, DE_NULL, &multisampleStateInfo)
440 .setMonolithicPipelineLayout(*pipelineLayoutMSPass)
441 .buildPipeline();
442
443 std::vector<GraphicsPipelineWrapper> graphicsPipelinesPerSampleFetch;
444 graphicsPipelinesPerSampleFetch.reserve(numSamples);
445
446 // Create descriptor set layout
447 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
448 DescriptorSetLayoutBuilder()
449 .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
450 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, VK_SHADER_STAGE_FRAGMENT_BIT)
451 .build(deviceInterface, device));
452
453 const Unique<VkPipelineLayout> pipelineLayoutPerSampleFetchPass(makePipelineLayout(deviceInterface, device, *descriptorSetLayout));
454
455 const deUint32 bufferPerSampleFetchPassSize = 4u * (deUint32)sizeof(tcu::Vec4);
456
457 de::SharedPtr<BufferWithMemory> vertexBufferPerSampleFetchPass = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, makeBufferCreateInfo(bufferPerSampleFetchPassSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
458
459 // Create graphics pipelines for per sample texel fetch passes
460 {
461 const Unique<VkShaderModule> vsPerSampleFetchPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_vs"), (VkShaderModuleCreateFlags)0u));
462 const Unique<VkShaderModule> fsPerSampleFetchPassModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("per_sample_fetch_fs"), (VkShaderModuleCreateFlags)0u));
463
464 std::vector<tcu::Vec4> vertices;
465
466 vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
467 vertices.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
468 vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
469 vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));
470
471 const Allocation& vertexAllocPerSampleFetchPass = vertexBufferPerSampleFetchPass->getAllocation();
472
473 deMemcpy(vertexAllocPerSampleFetchPass.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(bufferPerSampleFetchPassSize));
474
475 flushAlloc(deviceInterface, device, vertexAllocPerSampleFetchPass);
476
477 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
478 {
479 const deUint32 subpass = 1u + sampleNdx;
480 graphicsPipelinesPerSampleFetch.emplace_back(deviceInterface, device, m_imageMSParams.pipelineConstructionType);
481 graphicsPipelinesPerSampleFetch.back()
482 .setDefaultMultisampleState()
483 .setDefaultColorBlendState()
484 .setDefaultDepthStencilState()
485 .setDefaultRasterizationState()
486 .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
487 .setupVertexInputState()
488 .setupPreRasterizationShaderState(viewports, scissors, *pipelineLayoutPerSampleFetchPass, *renderPass, subpass, *vsPerSampleFetchPassModule)
489 .setupFragmentShaderState(*pipelineLayoutPerSampleFetchPass, *renderPass, subpass, *fsPerSampleFetchPassModule)
490 .setupFragmentOutputState(*renderPass, subpass)
491 .setMonolithicPipelineLayout(*pipelineLayoutPerSampleFetchPass)
492 .buildPipeline();
493 }
494 }
495
496 // Create descriptor pool
497 const Unique<VkDescriptorPool> descriptorPool(
498 DescriptorPoolBuilder()
499 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u)
500 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1u)
501 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
502
503 // Create descriptor set
504 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(deviceInterface, device, *descriptorPool, *descriptorSetLayout));
505
506 const VkPhysicalDeviceLimits deviceLimits = getPhysicalDeviceProperties(instance, physicalDevice).limits;
507
508 VkDeviceSize uboOffsetAlignment = sizeof(deInt32) < deviceLimits.minUniformBufferOffsetAlignment ? deviceLimits.minUniformBufferOffsetAlignment : sizeof(deInt32);
509
510 uboOffsetAlignment += (deviceLimits.minUniformBufferOffsetAlignment - uboOffsetAlignment % deviceLimits.minUniformBufferOffsetAlignment) % deviceLimits.minUniformBufferOffsetAlignment;
511
512 const VkBufferCreateInfo bufferSampleIDInfo = makeBufferCreateInfo(uboOffsetAlignment * numSamples, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
513 const de::UniquePtr<BufferWithMemory> bufferSampleID(new BufferWithMemory(deviceInterface, device, allocator, bufferSampleIDInfo, MemoryRequirement::HostVisible));
514
515 std::vector<deUint32> sampleIDsOffsets(numSamples);
516
517 {
518 deInt8* sampleIDs = new deInt8[static_cast<deUint32>(uboOffsetAlignment) * numSamples];
519
520 for (deInt32 sampleNdx = 0u; sampleNdx < static_cast<deInt32>(numSamples); ++sampleNdx)
521 {
522 sampleIDsOffsets[sampleNdx] = static_cast<deUint32>(sampleNdx * uboOffsetAlignment);
523 deInt8* samplePtr = sampleIDs + sampleIDsOffsets[sampleNdx];
524
525 deMemcpy(samplePtr, &sampleNdx, sizeof(deInt32));
526 }
527
528 deMemcpy(bufferSampleID->getAllocation().getHostPtr(), sampleIDs, static_cast<deUint32>(uboOffsetAlignment * numSamples));
529
530 flushAlloc(deviceInterface, device, bufferSampleID->getAllocation());
531
532 delete[] sampleIDs;
533 }
534
535 {
536 const VkDescriptorImageInfo descImageInfo = makeDescriptorImageInfo(DE_NULL, imageViews[0], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
537 const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**bufferSampleID, 0u, sizeof(deInt32));
538
539 DescriptorSetUpdateBuilder()
540 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descImageInfo)
541 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, &descBufferInfo)
542 .update(deviceInterface, device);
543 }
544
545 // Create command buffer for compute and transfer oparations
546 const Unique<VkCommandPool> commandPool(createCommandPool(deviceInterface, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
547 const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
548
549 // Start recording commands
550 beginCommandBuffer(deviceInterface, *commandBuffer);
551
552 {
553 std::vector<VkImageMemoryBarrier> imageOutputAttachmentBarriers(firstSubpassAttachmentsCount + numSamples);
554
555 imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
556 (
557 0u,
558 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
559 VK_IMAGE_LAYOUT_UNDEFINED,
560 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
561 **imageMS,
562 fullImageRange
563 );
564
565 imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
566 (
567 0u,
568 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
569 VK_IMAGE_LAYOUT_UNDEFINED,
570 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
571 **imageRS,
572 fullImageRange
573 );
574
575 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
576 {
577 imageOutputAttachmentBarriers[firstSubpassAttachmentsCount + sampleNdx] = makeImageMemoryBarrier
578 (
579 0u,
580 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
581 VK_IMAGE_LAYOUT_UNDEFINED,
582 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
583 **imagesPerSampleVec[sampleNdx],
584 fullImageRange
585 );
586 }
587
588 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
589 static_cast<deUint32>(imageOutputAttachmentBarriers.size()), dataPointer(imageOutputAttachmentBarriers));
590 }
591
592 {
593 const VkDeviceSize vertexStartOffset = 0u;
594
595 std::vector<VkClearValue> clearValues(firstSubpassAttachmentsCount + numSamples);
596 for (deUint32 attachmentNdx = 0u; attachmentNdx < firstSubpassAttachmentsCount + numSamples; ++attachmentNdx)
597 {
598 clearValues[attachmentNdx] = makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
599 }
600
601 beginRenderPass(deviceInterface, *commandBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, imageMSInfo.extent.width, imageMSInfo.extent.height), (deUint32)clearValues.size(), dataPointer(clearValues));
602
603 // Bind graphics pipeline
604 deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineMSPass.getPipeline());
605
606 const VkDescriptorSet* descriptorSetMSPass = createMSPassDescSet(m_imageMSParams, descriptorSetLayoutMSPass);
607
608 if (descriptorSetMSPass)
609 {
610 // Bind descriptor set
611 deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutMSPass, 0u, 1u, descriptorSetMSPass, 0u, DE_NULL);
612 }
613
614 // Bind vertex buffer
615 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
616
617 // Perform a draw
618 deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
619
620 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
621 {
622 deviceInterface.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
623
624 // Bind graphics pipeline
625 deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelinesPerSampleFetch[sampleNdx].getPipeline());
626
627 // Bind descriptor set
628 deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutPerSampleFetchPass, 0u, 1u, &descriptorSet.get(), 1u, &sampleIDsOffsets[sampleNdx]);
629
630 // Bind vertex buffer
631 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBufferPerSampleFetchPass->get(), &vertexStartOffset);
632
633 // Perform a draw
634 deviceInterface.cmdDraw(*commandBuffer, 4u, 1u, 0u, 0u);
635 }
636
637 // End render pass
638 endRenderPass(deviceInterface, *commandBuffer);
639 }
640
641 {
642 const VkImageMemoryBarrier imageRSTransferBarrier = makeImageMemoryBarrier
643 (
644 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
645 VK_ACCESS_TRANSFER_READ_BIT,
646 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
647 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
648 **imageRS,
649 fullImageRange
650 );
651
652 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageRSTransferBarrier);
653 }
654
655 // Copy data from imageRS to buffer
656 const deUint32 imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels, 1u);
657
658 const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
659 const de::UniquePtr<BufferWithMemory> bufferRS(new BufferWithMemory(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
660
661 {
662 const VkBufferImageCopy bufferImageCopy =
663 {
664 0u, // VkDeviceSize bufferOffset;
665 0u, // deUint32 bufferRowLength;
666 0u, // deUint32 bufferImageHeight;
667 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
668 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
669 imageRSInfo.extent, // VkExtent3D imageExtent;
670 };
671
672 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imageRS, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
673 }
674
675 {
676 const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
677 (
678 VK_ACCESS_TRANSFER_WRITE_BIT,
679 VK_ACCESS_HOST_READ_BIT,
680 bufferRS->get(),
681 0u,
682 imageRSSizeInBytes
683 );
684
685 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
686 }
687
688 // Copy data from per sample images to buffers
689 std::vector<VkImageMemoryBarrier> imagesPerSampleTransferBarriers(numSamples);
690
691 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
692 {
693 imagesPerSampleTransferBarriers[sampleNdx] = makeImageMemoryBarrier
694 (
695 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
696 VK_ACCESS_TRANSFER_READ_BIT,
697 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
698 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
699 **imagesPerSampleVec[sampleNdx],
700 fullImageRange
701 );
702 }
703
704 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
705 static_cast<deUint32>(imagesPerSampleTransferBarriers.size()), dataPointer(imagesPerSampleTransferBarriers));
706
707 std::vector<de::SharedPtr<BufferWithMemory> > buffersPerSample(numSamples);
708
709 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
710 {
711 buffersPerSample[sampleNdx] = de::SharedPtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
712
713 const VkBufferImageCopy bufferImageCopy =
714 {
715 0u, // VkDeviceSize bufferOffset;
716 0u, // deUint32 bufferRowLength;
717 0u, // deUint32 bufferImageHeight;
718 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
719 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
720 imageRSInfo.extent, // VkExtent3D imageExtent;
721 };
722
723 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, **imagesPerSampleVec[sampleNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **buffersPerSample[sampleNdx], 1u, &bufferImageCopy);
724 }
725
726 std::vector<VkBufferMemoryBarrier> buffersPerSampleHostReadBarriers(numSamples);
727
728 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
729 {
730 buffersPerSampleHostReadBarriers[sampleNdx] = makeBufferMemoryBarrier
731 (
732 VK_ACCESS_TRANSFER_WRITE_BIT,
733 VK_ACCESS_HOST_READ_BIT,
734 **buffersPerSample[sampleNdx],
735 0u,
736 imageRSSizeInBytes
737 );
738 }
739
740 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
741 static_cast<deUint32>(buffersPerSampleHostReadBarriers.size()), dataPointer(buffersPerSampleHostReadBarriers), 0u, DE_NULL);
742
743 // End recording commands
744 endCommandBuffer(deviceInterface, *commandBuffer);
745
746 // Submit commands for execution and wait for completion
747 submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
748
749 // Retrieve data from bufferRS to host memory
750 const Allocation& bufferRSAlloc = bufferRS->getAllocation();
751
752 invalidateAlloc(deviceInterface, device, bufferRSAlloc);
753
754 const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
755 imageRSInfo.extent.width,
756 imageRSInfo.extent.height,
757 imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
758 bufferRSAlloc.getHostPtr());
759
760 std::stringstream resolveName;
761 resolveName << "Resolve image " << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
762
763 m_context.getTestContext().getLog()
764 << tcu::TestLog::Section(resolveName.str(), resolveName.str())
765 << tcu::LogImage("resolve", "", bufferRSData)
766 << tcu::TestLog::EndSection;
767
768 std::vector<tcu::ConstPixelBufferAccess> buffersPerSampleData(numSamples);
769
770 // Retrieve data from per sample buffers to host memory
771 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx)
772 {
773 const Allocation& bufferAlloc = buffersPerSample[sampleNdx]->getAllocation();
774
775 invalidateAlloc(deviceInterface, device, bufferAlloc);
776
777 buffersPerSampleData[sampleNdx] = tcu::ConstPixelBufferAccess
778 (
779 m_imageFormat,
780 imageRSInfo.extent.width,
781 imageRSInfo.extent.height,
782 imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
783 bufferAlloc.getHostPtr()
784 );
785
786 std::stringstream sampleName;
787 sampleName << "Sample " << sampleNdx << " image" << std::endl;
788
789 m_context.getTestContext().getLog()
790 << tcu::TestLog::Section(sampleName.str(), sampleName.str())
791 << tcu::LogImage("sample", "", buffersPerSampleData[sampleNdx])
792 << tcu::TestLog::EndSection;
793 }
794
795 return verifyImageData(imageMSInfo, imageRSInfo, buffersPerSampleData, bufferRSData);
796 }
797
798 } // multisample
799 } // pipeline
800 } // vkt
801