• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Fragment Operations Occlusion Query Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktFragmentOperationsOcclusionQueryTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTextureUtil.hpp"
46 
47 #include "deUniquePtr.hpp"
48 #include "deStringUtil.hpp"
49 #include "deMath.h"
50 
51 #include <string>
52 
53 namespace vkt
54 {
55 namespace FragmentOperations
56 {
57 namespace
58 {
59 using namespace vk;
60 using de::UniquePtr;
61 
62 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)63 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
64 {
65 	const VkImageCreateInfo imageParams =
66 	{
67 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
68 		DE_NULL,								// const void*				pNext;
69 		(VkImageCreateFlags)0,					// VkImageCreateFlags		flags;
70 		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
71 		format,									// VkFormat					format;
72 		makeExtent3D(size.x(), size.y(), 1),	// VkExtent3D				extent;
73 		1u,										// deUint32					mipLevels;
74 		1u,										// deUint32					arrayLayers;
75 		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
76 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
77 		usage,									// VkImageUsageFlags		usage;
78 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
79 		0u,										// deUint32					queueFamilyIndexCount;
80 		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
81 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
82 	};
83 
84 	return imageParams;
85 }
86 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)87 Move<VkRenderPass> makeRenderPass	(const DeviceInterface&	vk,
88 									 const VkDevice			device,
89 									 const VkFormat			colorFormat,
90 									 const bool				useDepthStencilAttachment,
91 									 const VkFormat			depthStencilFormat)
92 {
93 	return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
94 }
95 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableScissorTest,const bool enableDepthTest,const bool enableStencilTest,const bool enableStencilWrite)96 Move<VkPipeline> makeGraphicsPipeline	(const DeviceInterface&	vk,
97 										 const VkDevice			device,
98 										 const VkPipelineLayout	pipelineLayout,
99 										 const VkRenderPass		renderPass,
100 										 const VkShaderModule	vertexModule,
101 										 const VkShaderModule	fragmentModule,
102 										 const tcu::IVec2&		renderSize,
103 										 const bool				enableScissorTest,
104 										 const bool				enableDepthTest,
105 										 const bool				enableStencilTest,
106 										 const bool				enableStencilWrite)
107 {
108 	const std::vector<VkViewport>			viewports					(1, makeViewport(renderSize));
109 	const std::vector<VkRect2D>				scissors					(1, enableScissorTest
110 																		? makeRect2D(renderSize.x() / 4, renderSize.y() / 4, renderSize.x() / 4 * 2, renderSize.y() / 4 * 2)
111 																		: makeRect2D(renderSize));
112 
113 	const VkStencilOpState					stencilOpState				= makeStencilOpState(VK_STENCIL_OP_KEEP,												// stencil fail
114 																							 enableStencilWrite ? VK_STENCIL_OP_REPLACE : VK_STENCIL_OP_KEEP,	// depth & stencil pass
115 																							 VK_STENCIL_OP_KEEP,												// depth only fail
116 																							 enableStencilWrite ? VK_COMPARE_OP_ALWAYS : VK_COMPARE_OP_EQUAL,	// compare op
117 																							 0xff,																// compare mask
118 																							 0xff,																// write mask
119 																							 enableStencilWrite ? 0u : 1u);										// reference
120 
121 	VkPipelineDepthStencilStateCreateInfo	depthStencilStateCreateInfo	=
122 	{
123 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,			// VkStructureType							sType
124 		DE_NULL,															// const void*								pNext
125 		0u,																	// VkPipelineDepthStencilStateCreateFlags	flags
126 		enableDepthTest ? VK_TRUE : VK_FALSE,								// VkBool32									depthTestEnable
127 		enableDepthTest ? VK_TRUE : VK_FALSE,								// VkBool32									depthWriteEnable
128 		VK_COMPARE_OP_LESS,													// VkCompareOp								depthCompareOp
129 		VK_FALSE,															// VkBool32									depthBoundsTestEnable
130 		enableStencilTest ? VK_TRUE : VK_FALSE,								// VkBool32									stencilTestEnable
131 		enableStencilTest ? stencilOpState : VkStencilOpState{},			// VkStencilOpState							front
132 		enableStencilTest ? stencilOpState : VkStencilOpState{},			// VkStencilOpState							back
133 		0.0f,																// float									minDepthBounds
134 		1.0f																// float									maxDepthBounds
135 	};
136 
137 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
138 									device,									// const VkDevice									device
139 									pipelineLayout,							// const VkPipelineLayout							pipelineLayout
140 									vertexModule,							// const VkShaderModule								vertexShaderModule
141 									DE_NULL,								// const VkShaderModule								tessellationControlModule
142 									DE_NULL,								// const VkShaderModule								tessellationEvalModule
143 									DE_NULL,								// const VkShaderModule								geometryShaderModule
144 									fragmentModule,							// const VkShaderModule								fragmentShaderModule
145 									renderPass,								// const VkRenderPass								renderPass
146 									viewports,								// const std::vector<VkViewport>&					viewports
147 									scissors,								// const std::vector<VkRect2D>&						scissors
148 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology						topology
149 									0u,										// const deUint32									subpass
150 									0u,										// const deUint32									patchControlPoints
151 									DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
152 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
153 									DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
154 									&depthStencilStateCreateInfo);			// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
155 }
156 
commandClearDepthAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)157 void commandClearDepthAttachment	(const DeviceInterface&	vk,
158 									 const VkCommandBuffer	commandBuffer,
159 									 const VkOffset2D&		offset,
160 									 const VkExtent2D&		extent,
161 									 const deUint32			clearValue)
162 {
163 	const VkClearAttachment	depthAttachment	=
164 	{
165 		VK_IMAGE_ASPECT_DEPTH_BIT,						// VkImageAspectFlags	aspectMask;
166 		0u,												// uint32_t				colorAttachment;
167 		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue			clearValue;
168 	};
169 
170 	const VkClearRect		rect			=
171 	{
172 		{ offset, extent },		// VkRect2D		rect;
173 		0u,						// uint32_t		baseArrayLayer;
174 		1u,						// uint32_t		layerCount;
175 	};
176 
177 	vk.cmdClearAttachments(commandBuffer, 1u, &depthAttachment, 1u, &rect);
178 }
179 
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)180 void commandClearStencilAttachment (const DeviceInterface&	vk,
181 									const VkCommandBuffer	commandBuffer,
182 									const VkOffset2D&		offset,
183 									const VkExtent2D&		extent,
184 									const deUint32			clearValue)
185 {
186 	const VkClearAttachment	stencilAttachment	=
187 	{
188 		VK_IMAGE_ASPECT_STENCIL_BIT,					// VkImageAspectFlags	aspectMask;
189 		0u,												// uint32_t				colorAttachment;
190 		makeClearValueDepthStencil(0.0f, clearValue),	// VkClearValue			clearValue;
191 	};
192 
193 	const VkClearRect		rect				=
194 	{
195 		{ offset, extent },		// VkRect2D		rect;
196 		0u,						// uint32_t		baseArrayLayer;
197 		1u,						// uint32_t		layerCount;
198 	};
199 
200 	vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
201 }
202 
getImageAspectFlags(const VkFormat format)203 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
204 {
205 	const tcu::TextureFormat tcuFormat = mapVkFormat(format);
206 
207 	if		(tcuFormat.order == tcu::TextureFormat::DS)		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
208 	else if	(tcuFormat.order == tcu::TextureFormat::D)		return VK_IMAGE_ASPECT_DEPTH_BIT;
209 	else if	(tcuFormat.order == tcu::TextureFormat::S)		return VK_IMAGE_ASPECT_STENCIL_BIT;
210 
211 	DE_ASSERT(false);
212 	return 0u;
213 }
214 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)215 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
216 {
217 	VkFormatProperties formatProps;
218 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
219 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
220 }
221 
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device)222 VkFormat pickSupportedDepthStencilFormat	(const InstanceInterface&	instanceInterface,
223 											 const VkPhysicalDevice		device)
224 {
225 	static const VkFormat dsFormats[] =
226 	{
227 		VK_FORMAT_D16_UNORM_S8_UINT,
228 		VK_FORMAT_D24_UNORM_S8_UINT,
229 		VK_FORMAT_D32_SFLOAT_S8_UINT,
230 	};
231 
232 	for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(dsFormats); ++i)
233 		if (isSupportedDepthStencilFormat(instanceInterface, device, dsFormats[i]))
234 			return dsFormats[i];
235 
236 	return VK_FORMAT_UNDEFINED;
237 }
238 
239 enum Flags
240 {
241 	TEST_NO_FLAGS		= 0,
242 	TEST_SCISSOR		= 1u << 0,
243 	TEST_DEPTH_WRITE	= 1u << 1,
244 	TEST_DEPTH_CLEAR	= 1u << 2,
245 	TEST_STENCIL_WRITE	= 1u << 3,
246 	TEST_STENCIL_CLEAR	= 1u << 4,
247 	TEST_ALL			= 1u << 5,
248 	TEST_PRECISE_BIT	= 1u << 6
249 };
250 
251 class OcclusionQueryTestInstance : public TestInstance
252 {
253 public:
254 							OcclusionQueryTestInstance	(Context& context,
255 														 const tcu::IVec2 renderSize,
256 														 const bool preciseBitEnabled,
257 														 const bool scissorTestEnabled,
258 														 const bool depthTestEnabled,
259 														 const bool stencilTestEnabled,
260 														 const bool depthWriteEnabled,
261 														 const bool stencilWriteEnabled);
262 
263 	tcu::TestStatus			iterate						(void);
264 
265 private:
266 	const tcu::IVec2		m_renderSize;
267 	const bool				m_preciseBitEnabled;
268 	const bool				m_scissorTestEnabled;
269 	const bool				m_depthClearTestEnabled;
270 	const bool				m_stencilClearTestEnabled;
271 	const bool				m_depthWriteTestEnabled;
272 	const bool				m_stencilWriteTestEnabled;
273 };
274 
OcclusionQueryTestInstance(Context & context,const tcu::IVec2 renderSize,const bool preciseBitEnabled,const bool scissorTestEnabled,const bool depthClearTestEnabled,const bool stencilClearTestEnabled,const bool depthWriteTestEnabled,const bool stencilWriteTestEnabled)275 OcclusionQueryTestInstance::OcclusionQueryTestInstance	(Context& context,
276 														 const tcu::IVec2 renderSize,
277 														 const bool preciseBitEnabled,
278 														 const bool scissorTestEnabled,
279 														 const bool depthClearTestEnabled,
280 														 const bool stencilClearTestEnabled,
281 														 const bool depthWriteTestEnabled,
282 														 const bool stencilWriteTestEnabled)
283 	: TestInstance				(context)
284 	, m_renderSize				(renderSize)
285 	, m_preciseBitEnabled		(preciseBitEnabled)
286 	, m_scissorTestEnabled		(scissorTestEnabled)
287 	, m_depthClearTestEnabled	(depthClearTestEnabled)
288 	, m_stencilClearTestEnabled	(stencilClearTestEnabled)
289 	, m_depthWriteTestEnabled	(depthWriteTestEnabled)
290 	, m_stencilWriteTestEnabled	(stencilWriteTestEnabled)
291 {
292 }
293 
iterate(void)294 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
295 {
296 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
297 	const InstanceInterface&		vki						= m_context.getInstanceInterface();
298 	const VkDevice					device					= m_context.getDevice();
299 	const VkPhysicalDevice			physDevice				= m_context.getPhysicalDevice();
300 	const VkQueue					queue					= m_context.getUniversalQueue();
301 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
302 	Allocator&						allocator				= m_context.getDefaultAllocator();
303 	VkQueryPool						queryPool;
304 	const deUint32					queryCount				= 1u;
305 	std::vector<VkDeviceSize>		sampleCounts			(queryCount);
306 
307 	// Create a query pool for storing the occlusion query result
308 	{
309 		VkQueryPoolCreateInfo queryPoolInfo
310 		{
311 			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType;
312 			DE_NULL,									// const void*						pNext;
313 			(VkQueryPoolCreateFlags)0,					// VkQueryPoolCreateFlags			flags;
314 			VK_QUERY_TYPE_OCCLUSION,					// VkQueryType						queryType;
315 			queryCount,									// uint32_t							queryCount;
316 			0u,											// VkQueryPipelineStatisticFlags	pipelineStatistics;
317 		};
318 		VK_CHECK(vk.createQueryPool(device, &queryPoolInfo, NULL, &queryPool));
319 	}
320 
321 	// Color attachment
322 	const VkFormat					colorFormat				= VK_FORMAT_R8G8B8A8_UNORM;
323 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
324 	const Unique<VkImage>			colorImage				(makeImage(vk, device, makeImageCreateInfo(m_renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
325 	const UniquePtr<Allocation>		colorImageAlloc			(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
326 	const Unique<VkImageView>		colorImageView			(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
327 
328 	std::vector<VkImageView>		attachmentImages		= { *colorImageView };
329 
330 	bool							depthTestsEnabled		= (m_depthClearTestEnabled		|| m_depthWriteTestEnabled);
331 	bool							stencilTestsEnabled		= (m_stencilClearTestEnabled	|| m_stencilWriteTestEnabled);
332 
333 	const VkFormat					testFormat				= (depthTestsEnabled	&& stencilTestsEnabled
334 															? pickSupportedDepthStencilFormat(vki, physDevice)
335 															: !depthTestsEnabled		&& stencilTestsEnabled
336 															? VK_FORMAT_S8_UINT
337 															: VK_FORMAT_D16_UNORM);
338 
339 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
340 
341 	const VkImageSubresourceRange	testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
342 	const Unique<VkImage>			testImage(makeImage(vk, device, makeImageCreateInfo(m_renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
343 	const UniquePtr<Allocation>		testImageAlloc(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
344 	const Unique<VkImageView>		testImageView(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
345 
346 	if (depthTestsEnabled || stencilTestsEnabled)
347 		attachmentImages.push_back(*testImageView);
348 
349 	const deUint32					numUsedAttachmentImages	= deUint32(attachmentImages.size());
350 
351 	// Depth occluder vertex buffer
352 	const deUint32					numDepthOccVertices		= 6;
353 	const VkDeviceSize				dOccVertBuffSizeBytes	= 256;
354 	const Unique<VkBuffer>			dOccluderVertexBuffer	(makeBuffer(vk, device, dOccVertBuffSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
355 	const UniquePtr<Allocation>		dOccVertexBufferAlloc	(bindBuffer(vk, device, allocator, *dOccluderVertexBuffer, MemoryRequirement::HostVisible));
356 
357 	{
358 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(dOccVertexBufferAlloc->getHostPtr());
359 
360 		pVertices[0]	= tcu::Vec4(-0.25f, -0.50f , 0.0f, 1.0f);	// Top Right
361 		pVertices[1]	= tcu::Vec4(-0.50f, -0.50f , 0.0f, 1.0f);	// Top Left
362 		pVertices[2]	= tcu::Vec4(-0.25f, -0.25f, 0.0f, 1.0f);	// Bottom Right
363 		pVertices[3]	= tcu::Vec4(-0.50f, -0.25f, 0.0f, 1.0f);	// Bottom Left
364 		pVertices[4]	= tcu::Vec4(-0.25f, -0.25f, 0.0f, 1.0f);	// Bottom Right
365 		pVertices[5]	= tcu::Vec4(-0.50f, -0.50f, 0.0f, 1.0f);	// Top Left
366 
367 		flushAlloc(vk, device, *dOccVertexBufferAlloc);
368 	}
369 
370 	// Stencil occluder vertex buffer
371 	const deUint32					numStencilOccVertices	= 6;
372 	const VkDeviceSize				sOccVertBuffSizeBytes	= 256;
373 	const Unique<VkBuffer>			sOccluderVertexBuffer	(makeBuffer(vk, device, sOccVertBuffSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
374 	const UniquePtr<Allocation>		sOccVertexBufferAlloc	(bindBuffer(vk, device, allocator, *sOccluderVertexBuffer, MemoryRequirement::HostVisible));
375 
376 	{
377 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(sOccVertexBufferAlloc->getHostPtr());
378 
379 		pVertices[0]	= tcu::Vec4(-0.25f, -0.25f, 0.0f, 1.0f);	// Top Right
380 		pVertices[1]	= tcu::Vec4(-0.50f, -0.25f, 0.0f, 1.0f);	// Top Left
381 		pVertices[2]	= tcu::Vec4(-0.25f,  0.00f, 0.0f, 1.0f);	// Bottom Right
382 		pVertices[3]	= tcu::Vec4(-0.50f,  0.00f, 0.0f, 1.0f);	// Bottom Left
383 		pVertices[4]	= tcu::Vec4(-0.25f,  0.00f, 0.0f, 1.0f);	// Bottom Right
384 		pVertices[5]	= tcu::Vec4(-0.50f, -0.25f, 0.0f, 1.0f);	// Top Left
385 
386 		flushAlloc(vk, device, *sOccVertexBufferAlloc);
387 	}
388 
389 	// Main vertex buffer
390 	const deUint32					numVertices				= 6;
391 	const VkDeviceSize				vertexBufferSizeBytes	= 256;
392 	const Unique<VkBuffer>			vertexBuffer			(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
393 	const UniquePtr<Allocation>		vertexBufferAlloc		(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
394 
395 	{
396 		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
397 
398 		pVertices[0]	= tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
399 		pVertices[1]	= tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
400 		pVertices[2]	= tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f);
401 		pVertices[3]	= tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f);
402 		pVertices[4]	= tcu::Vec4( 1.0f,  1.0f, 1.0f, 1.0f);
403 		pVertices[5]	= tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f);
404 
405 		flushAlloc(vk, device, *vertexBufferAlloc);
406 	}
407 
408 	// Render result buffer (to retrieve color attachment contents)
409 	const VkDeviceSize				colorBufferSizeBytes	= tcu::getPixelSize(mapVkFormat(colorFormat)) * m_renderSize.x() * m_renderSize.y();
410 	const Unique<VkBuffer>			colorBuffer				(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
411 	const UniquePtr<Allocation>		colorBufferAlloc		(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
412 
413 	// Pipeline
414 	const Unique<VkShaderModule>	vertexModule			(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
415 	const Unique<VkShaderModule>	fragmentModule			(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
416 	const Unique<VkRenderPass>		renderPass				(makeRenderPass(vk, device, colorFormat, (depthTestsEnabled || stencilTestsEnabled), testFormat));
417 	const Unique<VkFramebuffer>		framebuffer				(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages.data(), m_renderSize.x(), m_renderSize.y()));
418 	const Unique<VkPipelineLayout>	pipelineLayout			(makePipelineLayout(vk, device, DE_NULL));
419 	const Unique<VkPipeline>		pipeline				(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, m_renderSize,
420 															 m_scissorTestEnabled, depthTestsEnabled, stencilTestsEnabled, false));
421 
422 	const Unique<VkPipeline>		pipelineStencilWrite	(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, m_renderSize,
423 															 m_scissorTestEnabled, false, stencilTestsEnabled, true));
424 
425 	// Command buffer
426 	const Unique<VkCommandPool>		cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
427 	const Unique<VkCommandBuffer>	cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
428 
429 	{
430 		const tcu::Vec4		clearColor			= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
431 		const float			clearDepth			= 0.5f;
432 		const deUint32		clearStencil		= 1u;
433 		const VkDeviceSize	vertexBufferOffset	= 0ull;
434 
435 		const VkRect2D		renderArea			=
436 		{
437 			makeOffset2D(0, 0),
438 			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
439 		};
440 
441 		beginCommandBuffer(vk, *cmdBuffer);
442 
443 		vk.cmdResetQueryPool(*cmdBuffer, queryPool, 0, queryCount);
444 
445 		// Will clear the attachments with specified depth and stencil values.
446 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, clearDepth, clearStencil);
447 
448 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
449 
450 		// Mask half of the attachment image with value that will pass the stencil test.
451 		if (m_depthClearTestEnabled)
452 			commandClearDepthAttachment(vk, *cmdBuffer, makeOffset2D(0, m_renderSize.y() / 2), makeExtent2D(m_renderSize.x(), m_renderSize.y() / 2), 1u);
453 
454 		// Mask half of the attachment image with value that will pass the stencil test.
455 		if (m_stencilClearTestEnabled)
456 			commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(m_renderSize.x() / 2, 0), makeExtent2D(m_renderSize.x() / 2, m_renderSize.y()), 0u);
457 
458 		if (m_depthWriteTestEnabled)
459 		{
460 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &dOccluderVertexBuffer.get(), &vertexBufferOffset);
461 			vk.cmdDraw(*cmdBuffer, numDepthOccVertices, 1u, 0u, 0u);
462 		}
463 
464 		if (m_stencilWriteTestEnabled)
465 		{
466 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineStencilWrite);
467 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &sOccluderVertexBuffer.get(), &vertexBufferOffset);
468 			vk.cmdDraw(*cmdBuffer, numStencilOccVertices, 1u, 0u, 0u);
469 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
470 		}
471 
472 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
473 
474 		if (m_preciseBitEnabled)
475 		{
476 			vk.cmdBeginQuery(cmdBuffer.get(), queryPool, 0, VK_QUERY_CONTROL_PRECISE_BIT);
477 		}
478 		else
479 		{
480 			vk.cmdBeginQuery(cmdBuffer.get(), queryPool, 0, DE_NULL);
481 		}
482 
483 		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
484 		vk.cmdEndQuery(cmdBuffer.get(), queryPool, 0);
485 
486 		endRenderPass(vk, *cmdBuffer);
487 
488 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, m_renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
489 
490 		endCommandBuffer(vk, *cmdBuffer);
491 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
492 	}
493 
494 	// Check results
495 	{
496 		deUint64 expResult = 0;
497 
498 		if (m_preciseBitEnabled)
499 		{
500 			const deUint64	imageSize = m_scissorTestEnabled	? deUint64(m_renderSize.x()) * deUint64(m_renderSize.y()) / 4u
501 																: deUint64(m_renderSize.x()) * deUint64(m_renderSize.y());
502 
503 			const deUint64	renderHeight = m_scissorTestEnabled	? deUint64(m_renderSize.y() / 2u)
504 																: deUint64(m_renderSize.y());
505 
506 			const deUint64	occluderWriteSize = deUint64(m_renderSize.x()) * deUint64(m_renderSize.y()) / 64u;
507 
508 			if (m_depthClearTestEnabled || m_stencilClearTestEnabled)
509 			{
510 				if (m_depthClearTestEnabled && m_stencilClearTestEnabled)
511 				{
512 					expResult = imageSize / 4;
513 				}
514 
515 				if (!m_depthClearTestEnabled && m_stencilClearTestEnabled)
516 				{
517 					expResult = imageSize / 2;
518 				}
519 
520 				if (m_depthClearTestEnabled && !m_stencilClearTestEnabled)
521 				{
522 					expResult = imageSize / 2 - imageSize / 8 - renderHeight / 4;
523 				}
524 			}
525 			else if (m_depthWriteTestEnabled)
526 			{
527 				expResult = imageSize / 2 - renderHeight / 2;
528 			}
529 			else
530 			{
531 				expResult = imageSize;
532 			}
533 
534 			if (m_depthWriteTestEnabled)
535 			{
536 				expResult -= occluderWriteSize;
537 
538 				if (m_stencilClearTestEnabled && !m_depthClearTestEnabled)
539 				{
540 					expResult -= (imageSize / 8 + renderHeight / 4);
541 				}
542 			}
543 
544 			if (m_stencilWriteTestEnabled)
545 			{
546 				expResult -= occluderWriteSize;
547 			}
548 		}
549 
550 		VK_CHECK(vk.getQueryPoolResults(device, queryPool, 0u, queryCount, queryCount * sizeof(VkDeviceSize), sampleCounts.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
551 
552 		// Log test results
553 		{
554 			tcu::TestLog& log = m_context.getTestContext().getLog();
555 			log << tcu::TestLog::Message << "Passed Samples : " << de::toString(sampleCounts[0]) << " / " << expResult << tcu::TestLog::EndMessage;
556 		}
557 
558 #ifndef CTS_USES_VULKANSC
559 		vk.destroyQueryPool(device, queryPool, nullptr);
560 #endif // CTS_USES_VULKANSC
561 
562 		if ((m_preciseBitEnabled && sampleCounts[0] == expResult) || (!m_preciseBitEnabled && sampleCounts[0] > 0))
563 		{
564 			return tcu::TestStatus::pass("Success");
565 		}
566 		else
567 		{
568 
569 			invalidateAlloc(vk, device, *colorBufferAlloc);
570 
571 			const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), m_renderSize.x(), m_renderSize.y(), 1, colorBufferAlloc->getHostPtr());
572 			tcu::TestLog&						log					= m_context.getTestContext().getLog();
573 
574 			log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
575 
576 			return tcu::TestStatus::fail("Failure");
577 		}
578 	}
579 }
580 
581 class OcclusionQueryTest : public TestCase
582 {
583 public:
584 						OcclusionQueryTest	(tcu::TestContext&		testCtx,
585 											 const std::string		name,
586 											 const deUint32			flags,
587 											 const int				renderWidth,
588 											 const int				renderHeight);
589 
590 	void				initPrograms		(SourceCollections&		programCollection) const;
591 	TestInstance*		createInstance		(Context&				context) const;
592 	virtual void		checkSupport		(Context&				context) const;
593 
594 private:
595 	const bool		m_preciseBitEnabled;
596 	const bool		m_scissorTestEnabled;
597 	const bool		m_depthClearTestEnabled;
598 	const bool		m_stencilClearTestEnabled;
599 	const bool		m_depthWriteTestEnabled;
600 	const bool		m_stencilWriteTestEnabled;
601 	const int		m_renderWidth;
602 	const int		m_renderHeight;
603 };
604 
OcclusionQueryTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags,const int renderWidth,const int renderHeight)605 OcclusionQueryTest::OcclusionQueryTest	(tcu::TestContext& testCtx, const std::string name, const deUint32 flags, const int renderWidth, const int renderHeight)
606 	: TestCase							(testCtx, name, "")
607 	, m_preciseBitEnabled				(flags & TEST_PRECISE_BIT)
608 	, m_scissorTestEnabled				(flags & TEST_SCISSOR)
609 	, m_depthClearTestEnabled			(flags & TEST_DEPTH_CLEAR	|| flags & TEST_ALL)
610 	, m_stencilClearTestEnabled			(flags & TEST_STENCIL_CLEAR	|| flags & TEST_ALL)
611 	, m_depthWriteTestEnabled			(flags & TEST_DEPTH_WRITE	|| flags & TEST_ALL)
612 	, m_stencilWriteTestEnabled			(flags & TEST_STENCIL_WRITE	|| flags & TEST_ALL)
613 	, m_renderWidth						(renderWidth)
614 	, m_renderHeight					(renderHeight)
615 {
616 }
617 
initPrograms(SourceCollections & programCollection) const618 void OcclusionQueryTest::initPrograms (SourceCollections& programCollection) const
619 {
620 	// Vertex
621 	{
622 		std::ostringstream src;
623 
624 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
625 			<< "\n"
626 			<< "layout(location = 0) in highp vec4 position;\n"
627 			<< "\n"
628 			<< "out gl_PerVertex\n"
629 			<< "{\n"
630 			<< "   vec4 gl_Position;\n"
631 			<< "};\n"
632 			<< "\n"
633 			<< "void main (void)\n"
634 			<< "{\n"
635 			<< "    gl_Position = position;\n"
636 			<< "}\n";
637 
638 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
639 	}
640 
641 	// Fragment
642 	{
643 		std::ostringstream src;
644 
645 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
646 			<< "\n"
647 			<< "layout(location = 0) out highp vec4 fragColor;\n"
648 			<< "\n"
649 			<< "void main (void)\n"
650 			<< "{\n"
651 			<< "	fragColor = vec4(gl_FragCoord.x / " << m_renderWidth << ", gl_FragCoord.y / " << m_renderHeight << ", 0.0, 1.0); \n"
652 			<< "}\n";
653 
654 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
655 	}
656 }
657 
createInstance(Context & context) const658 TestInstance* OcclusionQueryTest::createInstance (Context& context) const
659 {
660 	return new OcclusionQueryTestInstance	(context, tcu::IVec2(m_renderWidth, m_renderHeight),
661 											 m_preciseBitEnabled, m_scissorTestEnabled,
662 											 m_depthClearTestEnabled, m_stencilClearTestEnabled,
663 											 m_depthWriteTestEnabled, m_stencilWriteTestEnabled);
664 }
665 
checkSupport(Context & context) const666 void OcclusionQueryTest::checkSupport (Context& context) const
667 {
668 	const InstanceInterface&	vki					= context.getInstanceInterface();
669 	const VkPhysicalDevice		physDevice			= context.getPhysicalDevice();
670 	VkImageFormatProperties		formatProperties;
671 
672 	bool						depthTestsEnabled	= (m_depthClearTestEnabled		|| m_depthWriteTestEnabled);
673 	bool						stencilTestsEnabled	= (m_stencilClearTestEnabled	|| m_stencilWriteTestEnabled);
674 
675 	const VkFormat				testFormat			= (stencilTestsEnabled	&& depthTestsEnabled
676 													? pickSupportedDepthStencilFormat(vki, physDevice)
677 													: stencilTestsEnabled
678 													? VK_FORMAT_S8_UINT
679 													: VK_FORMAT_D16_UNORM);
680 
681 	if (m_preciseBitEnabled)
682 	{
683 		vk::VkQueryControlFlags queryControlFlags = { VK_QUERY_CONTROL_PRECISE_BIT };
684 
685 		if (queryControlFlags && vk::VK_QUERY_CONTROL_PRECISE_BIT != context.getDeviceFeatures().occlusionQueryPrecise)
686 			TCU_THROW(NotSupportedError, "Precise occlusion queries are not supported");
687 	}
688 
689 	vki.getPhysicalDeviceImageFormatProperties(physDevice, testFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
690 	if (formatProperties.sampleCounts == 0 || testFormat == VK_FORMAT_UNDEFINED)
691 		TCU_THROW(NotSupportedError, de::toString(testFormat) + " not supported");
692 }
693 
694 } // anonymous ns
695 
createOcclusionQueryTests(tcu::TestContext & testCtx)696 tcu::TestCaseGroup* createOcclusionQueryTests(tcu::TestContext& testCtx)
697 {
698 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "occlusion_query", "occlusion query test cases"));
699 
700 	{
701 		static const struct
702 		{
703 			std::string	caseName;
704 			deUint32	flags;
705 		} cases[] =
706 		{
707 			{ "_test_scissors_clear_color",								TEST_SCISSOR																			},
708 			{ "_test_scissors_depth_clear",								TEST_SCISSOR	|	TEST_DEPTH_CLEAR													},
709 			{ "_test_scissors_depth_write",								TEST_SCISSOR	|	TEST_DEPTH_WRITE													},
710 			{ "_test_scissors_depth_clear_depth_write",					TEST_SCISSOR	|	TEST_DEPTH_CLEAR	|	TEST_DEPTH_WRITE							},
711 			{ "_test_scissors_stencil_clear",							TEST_SCISSOR	|	TEST_STENCIL_CLEAR													},
712 			{ "_test_scissors_stencil_write",							TEST_SCISSOR	|	TEST_STENCIL_WRITE													},
713 			{ "_test_scissors_stencil_clear_stencil_write",				TEST_SCISSOR	|	TEST_STENCIL_CLEAR	|	TEST_STENCIL_WRITE							},
714 			{ "_test_scissors_depth_clear_stencil_clear",				TEST_SCISSOR	|	TEST_DEPTH_CLEAR	|	TEST_STENCIL_CLEAR							},
715 			{ "_test_scissors_depth_write_stencil_clear",				TEST_SCISSOR	|	TEST_DEPTH_WRITE	|	TEST_STENCIL_CLEAR							},
716 			{ "_test_scissors_depth_clear_stencil_write",				TEST_SCISSOR	|	TEST_DEPTH_CLEAR	|	TEST_STENCIL_WRITE							},
717 			{ "_test_scissors_depth_write_stencil_write",				TEST_SCISSOR	|	TEST_DEPTH_WRITE	|	TEST_STENCIL_WRITE							},
718 			{ "_test_scissors_depth_clear_stencil_clear_depth_write",	TEST_SCISSOR	|	TEST_DEPTH_CLEAR	|	TEST_DEPTH_WRITE	|	TEST_STENCIL_CLEAR	},
719 			{ "_test_scissors_depth_clear_stencil_clear_stencil_write",	TEST_SCISSOR	|	TEST_DEPTH_CLEAR	|	TEST_STENCIL_CLEAR	|	TEST_STENCIL_WRITE	},
720 			{ "_test_scissors_depth_clear_depth_write_stencil_write",	TEST_SCISSOR	|	TEST_DEPTH_CLEAR	|	TEST_DEPTH_WRITE	|	TEST_STENCIL_WRITE	},
721 			{ "_test_scissors_depth_write_stencil_clear_stencil_write",	TEST_SCISSOR	|	TEST_DEPTH_WRITE	|	TEST_STENCIL_CLEAR	|	TEST_STENCIL_WRITE	},
722 			{ "_test_scissors_test_all",								TEST_SCISSOR	|	TEST_ALL															},
723 			{ "_test_clear_color",										TEST_NO_FLAGS																			},
724 			{ "_test_depth_clear",															TEST_DEPTH_CLEAR													},
725 			{ "_test_depth_write",															TEST_DEPTH_WRITE													},
726 			{ "_test_depth_clear_depth_write",												TEST_DEPTH_CLEAR	|	TEST_DEPTH_WRITE							},
727 			{ "_test_stencil_clear",														TEST_STENCIL_CLEAR													},
728 			{ "_test_stencil_write",														TEST_STENCIL_WRITE													},
729 			{ "_test_stencil_clear_stencil_write",											TEST_STENCIL_CLEAR	|	TEST_STENCIL_WRITE							},
730 			{ "_test_depth_clear_stencil_clear",											TEST_DEPTH_CLEAR	|	TEST_STENCIL_CLEAR							},
731 			{ "_test_depth_write_stencil_clear",											TEST_DEPTH_WRITE	|	TEST_STENCIL_CLEAR							},
732 			{ "_test_depth_clear_stencil_write",											TEST_DEPTH_CLEAR	|	TEST_STENCIL_WRITE							},
733 			{ "_test_depth_write_stencil_write",											TEST_DEPTH_WRITE	|	TEST_STENCIL_WRITE							},
734 			{ "_test_depth_clear_stencil_clear_depth_write",								TEST_DEPTH_CLEAR	|	TEST_DEPTH_WRITE	|	TEST_STENCIL_CLEAR	},
735 			{ "_test_depth_clear_stencil_clear_stencil_write",								TEST_DEPTH_CLEAR	|	TEST_STENCIL_CLEAR	|	TEST_STENCIL_WRITE	},
736 			{ "_test_depth_clear_depth_write_stencil_write",								TEST_DEPTH_CLEAR	|	TEST_DEPTH_WRITE	|	TEST_STENCIL_WRITE	},
737 			{ "_test_depth_write_stencil_clear_stencil_write",								TEST_DEPTH_WRITE	|	TEST_STENCIL_CLEAR	|	TEST_STENCIL_WRITE	},
738 			{ "_test_test_all",																TEST_ALL															}
739 		};
740 
741 		// Conservative tests
742 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
743 			testGroup->addChild(new OcclusionQueryTest(testCtx, "conservative" + cases[i].caseName, cases[i].flags, 32, 32));
744 
745 		// Precise tests
746 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
747 			testGroup->addChild(new OcclusionQueryTest(testCtx, "precise" + cases[i].caseName, cases[i].flags | TEST_PRECISE_BIT, 32, 32));
748 	}
749 
750 	return testGroup.release();
751 }
752 
753 } // FragmentOperations
754 } // vkt
755