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
38namespace vkt
39{
40namespace pipeline
41{
42namespace multisample
43{
44
45using namespace vk;
46
47tcu::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