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