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