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