1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*
22 * \file vktPipelineMultisampleBaseResolve.cpp
23 * \brief Base class for tests that check results of multisample resolve
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktPipelineMultisampleBaseResolve.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vkBuilderUtil.hpp"
29 #include "vkBarrierUtil.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
iterate(void)47 tcu::TestStatus MSInstanceBaseResolve::iterate(void)
48 {
49 // cases creating this tests are defined using templates and we do not have easy access
50 // to image type - to do this check in checkSupport bigger reffactoring would be needed
51 #ifndef CTS_USES_VULKANSC
52 if (m_context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
53 !m_context.getPortabilitySubsetFeatures().multisampleArrayImage && (m_imageType == IMAGE_TYPE_2D_ARRAY) &&
54 (m_imageMSParams.numSamples != VK_SAMPLE_COUNT_1_BIT) && (m_imageMSParams.imageSize.z() != 1))
55 {
56 TCU_THROW(
57 NotSupportedError,
58 "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
59 }
60 #endif // CTS_USES_VULKANSC
61
62 const InstanceInterface &instance = m_context.getInstanceInterface();
63 const DeviceInterface &deviceInterface = m_context.getDeviceInterface();
64 const VkDevice device = m_context.getDevice();
65 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
66 const VkPhysicalDeviceFeatures &features = m_context.getDeviceFeatures();
67 Allocator &allocator = m_context.getDefaultAllocator();
68 const VkQueue queue = m_context.getUniversalQueue();
69 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
70 const bool usePushConstants = (m_imageMSParams.componentData.source == ComponentSource::PUSH_CONSTANT);
71 const uint32_t pushConstantSize = static_cast<uint32_t>(sizeof(decltype(m_imageMSParams.componentData.index)));
72
73 VkImageCreateInfo imageMSInfo;
74 VkImageCreateInfo imageRSInfo;
75
76 // Check if image size does not exceed device limits
77 validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
78
79 // Check if device supports image format as color attachment
80 validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat),
81 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
82
83 imageMSInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
84 imageMSInfo.pNext = DE_NULL;
85 imageMSInfo.flags = 0u;
86 imageMSInfo.imageType = mapImageType(m_imageType);
87 imageMSInfo.format = mapTextureFormat(m_imageFormat);
88 imageMSInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
89 imageMSInfo.arrayLayers = getNumLayers(m_imageType, m_imageMSParams.imageSize);
90 imageMSInfo.mipLevels = 1u;
91 imageMSInfo.samples = m_imageMSParams.numSamples;
92 imageMSInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
93 imageMSInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
94 imageMSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
95 imageMSInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
96 imageMSInfo.queueFamilyIndexCount = 0u;
97 imageMSInfo.pQueueFamilyIndices = DE_NULL;
98
99 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
100 {
101 imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
102 }
103
104 validateImageInfo(instance, physicalDevice, imageMSInfo);
105
106 const de::UniquePtr<ImageWithMemory> imageMS(
107 new ImageWithMemory(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
108
109 imageRSInfo = imageMSInfo;
110 imageRSInfo.samples = VK_SAMPLE_COUNT_1_BIT;
111
112 validateImageInfo(instance, physicalDevice, imageRSInfo);
113
114 const de::UniquePtr<ImageWithMemory> imageRS(
115 new ImageWithMemory(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
116
117 // Create render pass
118 const VkAttachmentDescription attachmentMSDesc = {
119 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
120 imageMSInfo.format, // VkFormat format;
121 imageMSInfo.samples, // VkSampleCountFlagBits samples;
122 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
123 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
124 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
125 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
126 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
127 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
128 };
129
130 const VkAttachmentDescription attachmentRSDesc = {
131 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
132 imageRSInfo.format, // VkFormat format;
133 imageRSInfo.samples, // VkSampleCountFlagBits samples;
134 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
135 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
136 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
137 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
138 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
139 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
140 };
141
142 const VkAttachmentDescription attachments[] = {attachmentMSDesc, attachmentRSDesc};
143
144 const VkAttachmentReference attachmentMSRef = {
145 0u, // uint32_t attachment;
146 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
147 };
148
149 const VkAttachmentReference attachmentRSRef = {
150 1u, // uint32_t attachment;
151 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
152 };
153
154 const VkAttachmentReference *resolveAttachment =
155 m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef;
156
157 const VkSubpassDescription subpassDescription = {
158 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags;
159 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
160 0u, // uint32_t inputAttachmentCount;
161 DE_NULL, // const VkAttachmentReference* pInputAttachments;
162 1u, // uint32_t colorAttachmentCount;
163 &attachmentMSRef, // const VkAttachmentReference* pColorAttachments;
164 resolveAttachment, // const VkAttachmentReference* pResolveAttachments;
165 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
166 0u, // uint32_t preserveAttachmentCount;
167 DE_NULL // const uint32_t* pPreserveAttachments;
168 };
169
170 const VkRenderPassCreateInfo renderPassInfo = {
171 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
172 DE_NULL, // const void* pNext;
173 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags;
174 2u, // uint32_t attachmentCount;
175 attachments, // const VkAttachmentDescription* pAttachments;
176 1u, // uint32_t subpassCount;
177 &subpassDescription, // const VkSubpassDescription* pSubpasses;
178 0u, // uint32_t dependencyCount;
179 DE_NULL // const VkSubpassDependency* pDependencies;
180 };
181
182 RenderPassWrapper renderPass(m_imageMSParams.pipelineConstructionType, deviceInterface, device, &renderPassInfo);
183
184 const VkImageSubresourceRange fullImageRange =
185 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
186
187 // Create color attachments image views
188 const Unique<VkImageView> imageMSView(makeImageView(
189 deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
190 const Unique<VkImageView> imageRSView(makeImageView(
191 deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
192
193 std::vector<VkImage> images = {**imageMS, **imageRS};
194 const VkImageView attachmentsViews[] = {*imageMSView, *imageRSView};
195
196 // Create framebuffer
197 const VkFramebufferCreateInfo framebufferInfo = {
198 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
199 DE_NULL, // const void* pNext;
200 (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags;
201 *renderPass, // VkRenderPass renderPass;
202 2u, // uint32_t attachmentCount;
203 attachmentsViews, // const VkImageView* pAttachments;
204 imageMSInfo.extent.width, // uint32_t width;
205 imageMSInfo.extent.height, // uint32_t height;
206 imageMSInfo.arrayLayers, // uint32_t layers;
207 };
208
209 renderPass.createFramebuffer(deviceInterface, device, &framebufferInfo, images);
210
211 std::vector<vk::VkPushConstantRange> pushConstantRanges;
212
213 if (usePushConstants)
214 {
215 const vk::VkPushConstantRange pushConstantRange = {
216 vk::VK_SHADER_STAGE_ALL, // VkShaderStageFlags stageFlags;
217 0u, // uint32_t offset;
218 pushConstantSize, // uint32_t size;
219 };
220 pushConstantRanges.push_back(pushConstantRange);
221 }
222
223 // Create pipeline layout
224 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
225 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
226 DE_NULL, // const void* pNext;
227 (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags;
228 0u, // uint32_t setLayoutCount;
229 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
230 static_cast<uint32_t>(pushConstantRanges.size()), // uint32_t pushConstantRangeCount;
231 (pushConstantRanges.empty() ? nullptr :
232 pushConstantRanges.data()), // const VkPushConstantRange* pPushConstantRanges;
233 };
234
235 const PipelineLayoutWrapper pipelineLayout(m_imageMSParams.pipelineConstructionType, deviceInterface, device,
236 &pipelineLayoutParams);
237
238 // Create vertex attributes data
239 const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
240
241 de::SharedPtr<BufferWithMemory> vertexBuffer = de::SharedPtr<BufferWithMemory>(
242 new BufferWithMemory(deviceInterface, device, allocator,
243 makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
244 MemoryRequirement::HostVisible));
245 const Allocation &vertexBufferAllocation = vertexBuffer->getAllocation();
246
247 uploadVertexData(vertexBufferAllocation, vertexDataDesc);
248
249 flushAlloc(deviceInterface, device, vertexBufferAllocation);
250
251 const VkVertexInputBindingDescription vertexBinding = {
252 0u, // uint32_t binding;
253 vertexDataDesc.dataStride, // uint32_t stride;
254 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
255 };
256
257 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
258 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
259 DE_NULL, // const void* pNext;
260 (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags;
261 1u, // uint32_t vertexBindingDescriptionCount;
262 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
263 static_cast<uint32_t>(
264 vertexDataDesc.vertexAttribDescVec
265 .size()), // uint32_t vertexAttributeDescriptionCount;
266 dataPointer(
267 vertexDataDesc
268 .vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
269 };
270
271 const std::vector<VkViewport> viewports{makeViewport(imageMSInfo.extent)};
272 const std::vector<VkRect2D> scissors{makeRect2D(imageMSInfo.extent)};
273
274 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo{
275 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
276 DE_NULL, // const void* pNext;
277 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags;
278 imageMSInfo.samples, // VkSampleCountFlagBits rasterizationSamples;
279 features.sampleRateShading, // VkBool32 sampleShadingEnable;
280 1.0f, // float minSampleShading;
281 DE_NULL, // const VkSampleMask* pSampleMask;
282 VK_FALSE, // VkBool32 alphaToCoverageEnable;
283 VK_FALSE, // VkBool32 alphaToOneEnable;
284 };
285
286 const ShaderWrapper vsModule(ShaderWrapper(
287 deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0));
288 const ShaderWrapper fsModule(ShaderWrapper(
289 deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0));
290
291 // Create graphics pipeline
292 GraphicsPipelineWrapper graphicsPipeline(instance, deviceInterface, physicalDevice, device,
293 m_context.getDeviceExtensions(), m_imageMSParams.pipelineConstructionType);
294 graphicsPipeline.setDefaultRasterizationState()
295 .setDefaultColorBlendState()
296 .setDefaultDepthStencilState()
297 .setDefaultTopology(vertexDataDesc.primitiveTopology)
298 .setupVertexInputState(&vertexInputStateInfo)
299 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vsModule)
300 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fsModule, DE_NULL, &multisampleStateInfo)
301 .setupFragmentOutputState(*renderPass, 0, DE_NULL, &multisampleStateInfo)
302 .setMonolithicPipelineLayout(pipelineLayout)
303 .buildPipeline();
304
305 // Create command buffer for compute and transfer oparations
306 const Unique<VkCommandPool> commandPool(
307 createCommandPool(deviceInterface, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
308 const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
309
310 // Start recording commands
311 beginCommandBuffer(deviceInterface, *commandBuffer);
312
313 {
314 VkImageMemoryBarrier imageOutputAttachmentBarriers[2];
315
316 imageOutputAttachmentBarriers[0] =
317 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
318 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, **imageMS, fullImageRange);
319
320 imageOutputAttachmentBarriers[1] =
321 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
322 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, **imageRS, fullImageRange);
323
324 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
325 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
326 2u, imageOutputAttachmentBarriers);
327 }
328
329 {
330 const VkDeviceSize vertexStartOffset = 0u;
331
332 std::vector<VkClearValue> clearValues;
333 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
334 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
335
336 renderPass.begin(deviceInterface, *commandBuffer,
337 makeRect2D(0, 0, imageMSInfo.extent.width, imageMSInfo.extent.height),
338 (uint32_t)clearValues.size(), &clearValues[0]);
339
340 // Bind graphics pipeline
341 graphicsPipeline.bind(*commandBuffer);
342
343 // Bind vertex buffer
344 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
345
346 // Push constants.
347 if (usePushConstants)
348 deviceInterface.cmdPushConstants(*commandBuffer, *pipelineLayout, vk::VK_SHADER_STAGE_ALL, 0u,
349 pushConstantSize, &m_imageMSParams.componentData.index);
350
351 // Draw full screen quad
352 deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
353
354 // End render pass
355 renderPass.end(deviceInterface, *commandBuffer);
356 }
357
358 const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS;
359
360 {
361 const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier(
362 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
363 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, sourceImage, fullImageRange);
364
365 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
366 VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u,
367 &imageTransferSrcBarrier);
368 }
369
370 // Copy data from resolve image to buffer
371 const uint32_t imageRSSizeInBytes =
372 getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels);
373
374 const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
375 const de::UniquePtr<BufferWithMemory> bufferRS(
376 new BufferWithMemory(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
377
378 {
379 const VkBufferImageCopy bufferImageCopy = {
380 0u, // VkDeviceSize bufferOffset;
381 0u, // uint32_t bufferRowLength;
382 0u, // uint32_t bufferImageHeight;
383 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u,
384 imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
385 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
386 imageRSInfo.extent, // VkExtent3D imageExtent;
387 };
388
389 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
390 bufferRS->get(), 1u, &bufferImageCopy);
391 }
392
393 {
394 const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier(
395 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, bufferRS->get(), 0u, imageRSSizeInBytes);
396
397 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
398 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
399 }
400
401 // End recording commands
402 endCommandBuffer(deviceInterface, *commandBuffer);
403
404 // Submit commands for execution and wait for completion
405 submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
406
407 // Retrieve data from buffer to host memory
408 const Allocation &bufferRSAllocation = bufferRS->getAllocation();
409
410 invalidateAlloc(deviceInterface, device, bufferRSAllocation);
411
412 const tcu::ConstPixelBufferAccess bufferRSData(m_imageFormat, imageRSInfo.extent.width, imageRSInfo.extent.height,
413 imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
414 bufferRSAllocation.getHostPtr());
415
416 std::stringstream imageName;
417 imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight()
418 << "_" << bufferRSData.getDepth() << std::endl;
419
420 m_context.getTestContext().getLog() << tcu::TestLog::Section(imageName.str(), imageName.str())
421 << tcu::LogImage("image", "", bufferRSData) << tcu::TestLog::EndSection;
422
423 return verifyImageData(imageRSInfo, bufferRSData);
424 }
425
426 } // namespace multisample
427 } // namespace pipeline
428 } // namespace vkt
429