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