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