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