• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2017 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 Depth clamp tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vkDefs.hpp"
26 #include "vktDrawDepthClampTests.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawCreateInfoUtil.hpp"
30 #include "vktDrawBufferObjectUtil.hpp"
31 #include "vktDrawImageObjectUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuTestLog.hpp"
41 
42 #include <cmath>
43 #include <limits>
44 #include "deMath.h"
45 
46 namespace vkt
47 {
48 namespace Draw
49 {
50 namespace {
51 using namespace vk;
52 using namespace de;
53 using std::string;
54 using tcu::Vec4;
55 
56 static const int					WIDTH				= 256;
57 static const int					HEIGHT				= 256;
58 
59 struct ViewportData
60 {
61 	float minDepth;
62 	float maxDepth;
63 	float depthValue;
64 	float expectedValue;
65 };
66 
67 struct TestParams
68 {
69 	string							testNameSuffix;
70 	std::vector<ViewportData>		viewportData;
71 	bool							enableDepthBias;
72 	float							depthBiasConstantFactor;
73 	bool							skipUNorm;
74 	bool							skipSNorm;
75 	std::vector<const char*>		requiredExtensions;
76 };
77 
78 const VkFormat		depthStencilImageFormatsToTest[]	=
79 {
80 	VK_FORMAT_D16_UNORM,
81 	VK_FORMAT_X8_D24_UNORM_PACK32,
82 	VK_FORMAT_D32_SFLOAT,
83 	VK_FORMAT_D16_UNORM_S8_UINT,
84 	VK_FORMAT_D24_UNORM_S8_UINT,
85 	VK_FORMAT_D32_SFLOAT_S8_UINT
86 };
87 const float			depthEpsilonValuesByFormat[]		=
88 {
89 	1e-5f,
90 	std::numeric_limits<float>::epsilon(),
91 	std::numeric_limits<float>::epsilon(),
92 	1e-5f,
93 	std::numeric_limits<float>::epsilon(),
94 	std::numeric_limits<float>::epsilon()
95 };
96 
97 const float			initialClearDepth					= 0.5f;
98 const TestParams	depthClearValuesToTest[]			=
99 {
100 	{
101 		"",											// testNameSuffix
102 		{ {											// viewportData
103 			0.0f,									//   minDepth
104 			1.0f,									//   maxDepth
105 			0.3f,									//   depthValue
106 			0.3f,									//   expectedValue
107 		} },
108 		false,										// enableDepthBias
109 		0.0f,										// depthBiasConstantFactor
110 		false,										// skipUNorm
111 		false,										// skipSNorm
112 		{},											// requiredExtensions
113 	},
114 	{
115 		"_clamp_input_negative",					// testNameSuffix
116 		{ {											// viewportData
117 			0.0f,									//   minDepth
118 			1.0f,									//   maxDepth
119 		   -1e6f,									//   depthValue
120 			0.0f,									//   expectedValue
121 		} },
122 		false,										// enableDepthBias
123 		0.0f,										// depthBiasConstantFactor
124 		false,										// skipUNorm
125 		false,										// skipSNorm
126 		{},											// requiredExtensions
127 	},
128 	{
129 		"_clamp_input_positive",					// testNameSuffix
130 		{ {											// viewportData
131 			0.0f,									//   minDepth
132 			1.0f,									//   maxDepth
133 			1.e6f,									//   depthValue
134 			1.0f,									//   expectedValue
135 		} },
136 		false,										// enableDepthBias
137 		0.0f,										// depthBiasConstantFactor
138 		false,										// skipUNorm
139 		false,										// skipSNorm
140 		{},											// requiredExtensions
141 	},
142 	{
143 		"_depth_bias_clamp_input_negative",			// testNameSuffix
144 		{ {											// viewportData
145 			0.0f,									//   minDepth
146 			1.0f,									//   maxDepth
147 			0.3f,									//   depthValue
148 			0.0f,									//   expectedValue
149 		} },
150 		true,										// enableDepthBias
151 		-2e11f,										// depthBiasConstantFactor
152 		false,										// skipUNorm
153 		false,										// skipSNorm
154 		{},											// requiredExtensions
155 	},
156 	{
157 		"_depth_bias_clamp_input_positive",			// testNameSuffix
158 		{ {											// viewportData
159 			0.0f,									//   minDepth
160 			1.0f,									//   maxDepth
161 			0.7f,									//   depthValue
162 			1.0f,									//   expectedValue
163 		} },
164 		true,										// enableDepthBias
165 		2e11f,										// depthBiasConstantFactor
166 		false,										// skipUNorm
167 		false,										// skipSNorm
168 		{},											// requiredExtensions
169 	},
170 	{
171 		"_depth_range_unrestricted_negative",		// testNameSuffix
172 		{ {											// viewportData
173 		   -1.5f,									//   minDepth
174 			1.0f,									//   maxDepth
175 		   -1.5f,									//   depthValue
176 		   -1.5f,									//   expectedValue
177 		} },
178 		false,										// enableDepthBias
179 		0.0f,										// depthBiasConstantFactor
180 		true,										// skipUNorm
181 		true,										// skipSNorm
182 		{
183 			"VK_EXT_depth_range_unrestricted"		// requiredExtensions[0]
184 		},
185 	},
186 	{
187 		"_depth_range_unrestricted_positive",		// testNameSuffix
188 		{ {											// viewportData
189 			0.0f,									//   minDepth
190 			1.5f,									//   maxDepth
191 			1.5f,									//   depthValue
192 			1.5f,									//   expectedValue
193 		} },
194 		false,										// enableDepthBias
195 		0.0f,										// depthBiasConstantFactor
196 		true,										// skipUNorm
197 		true,										// skipSNorm
198 		{
199 			"VK_EXT_depth_range_unrestricted"		// requiredExtensions[0]
200 		},
201 	},
202 	{
203 		"_clamp_four_viewports",					// testNameSuffix
204 		{											// viewportData
205 			{
206 				0.0f,								//   minDepth
207 				0.5f,								//   maxDepth
208 				0.7f,								//   depthValue
209 				0.35f,								//   expectedValue: 0.7 * 0.5 + (1.0 - 0.7) * 0.0) = 0.35
210 			},
211 			{
212 				0.9f,								//   minDepth
213 				1.0f,								//   maxDepth
214 				1.0f,								//   depthValue
215 				1.0f,								//   expectedValue: 1.0 * 1.0 + (1.0 - 1.0) * 0.9 = 1.0
216 			},
217 			{
218 				0.5f,								//   minDepth
219 				1.0f,								//   maxDepth
220 				0.9f,								//   depthValue
221 				0.95f,								//   expectedValue: 0.9 * 1.0 + (1.0 - 0.9) * 0.5 = 0.95
222 			},
223 			{
224 				0.5f,								//   minDepth
225 				0.9f,								//   maxDepth
226 				0.4f,								//   depthValue
227 				0.66f,								//   expectedValue: 0.4 * 0.9 + (1.0 - 0.4) * 0.5 = 0.66
228 			},
229 		},
230 		false,										// enableDepthBias
231 		0.0f,										// depthBiasConstantFactor
232 		true,										// skipUNorm
233 		true,										// skipSNorm
234 		{},
235 	}
236 };
237 
isUnormDepthFormat(VkFormat format)238 bool isUnormDepthFormat(VkFormat format)
239 {
240 	switch (format)
241 	{
242 		case VK_FORMAT_D24_UNORM_S8_UINT:
243 		case VK_FORMAT_X8_D24_UNORM_PACK32:
244 		case VK_FORMAT_D16_UNORM_S8_UINT:
245 			/* Special case for combined depth-stencil-unorm modes for which tcu::getTextureChannelClass()
246 			   returns TEXTURECHANNELCLASS_LAST */
247 			return true;
248 		default:
249 			return vk::isUnormFormat(format);
250 	}
251 }
252 
253 class DepthClampTestInstance : public TestInstance {
254 public:
255 								DepthClampTestInstance	(Context& context, const TestParams& params, const VkFormat format, const float epsilon, const SharedGroupParams groupParams);
256 	tcu::TestStatus				iterate					();
257 
258 private:
259 	tcu::ConstPixelBufferAccess draw					();
260 
261 	void						preRenderCommands		(VkCommandBuffer cmdBuffer, const VkImageAspectFlagBits aspectBits, const VkClearValue& clearValue) const;
262 	void						drawCommands			(VkCommandBuffer cmdBuffer) const;
263 
264 #ifndef CTS_USES_VULKANSC
265 	void						beginSecondaryCmdBuffer	(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
266 	void						beginDynamicRender		(VkCommandBuffer cmdBuffer, VkClearValue clearValue, VkRenderingFlagsKHR renderingFlags = 0u) const;
267 #endif // CTS_USES_VULKANSC
268 
269 	const TestParams									m_params;
270 	const VkFormat										m_format;
271 	const float											m_epsilon;
272 	std::vector<VkViewport>								m_viewportVect;
273 	std::vector<VkRect2D>								m_scissorVect;
274 	const SharedGroupParams								m_groupParams;
275 	SharedPtr<Image>									m_depthTargetImage;
276 	Move<VkImageView>									m_depthTargetView;
277 	SharedPtr<Buffer>									m_vertexBuffer;
278 	Move<VkRenderPass>									m_renderPass;
279 	Move<VkFramebuffer>									m_framebuffer;
280 	Move<VkPipelineLayout>								m_pipelineLayout;
281 	Move<VkPipeline>									m_pipeline;
282 };
283 
284 static const Vec4					vertices[]			= {
285 	Vec4(-1.0f, -1.0f,  0.5f, 1.0f),	// 0 -- 2
286 	Vec4(-1.0f,  1.0f,  0.5f, 1.0f),	// |  / |
287 	Vec4( 1.0f, -1.0f,  0.5f, 1.0f),	// | /  |
288 	Vec4( 1.0f,  1.0f,  0.5f, 1.0f)		// 1 -- 3
289 };
290 static const VkPrimitiveTopology	verticesTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
291 
DepthClampTestInstance(Context & context,const TestParams & params,const VkFormat format,const float epsilon,const SharedGroupParams groupParams)292 DepthClampTestInstance::DepthClampTestInstance (Context& context, const TestParams& params, const VkFormat format, const float epsilon, const SharedGroupParams groupParams)
293 	: TestInstance		(context)
294 	, m_params			(params)
295 	, m_format			(format)
296 	, m_epsilon			(epsilon)
297 	, m_viewportVect	(params.viewportData.size(), VkViewport())
298 	, m_scissorVect		(params.viewportData.size(), VkRect2D())
299 	, m_groupParams		(groupParams)
300 {
301 	const DeviceInterface&		vk								= m_context.getDeviceInterface();
302 	const VkDevice				device							= m_context.getDevice();
303 	const deUint32				queueFamilyIndex				= m_context.getUniversalQueueFamilyIndex();
304 	const deUint32				viewportCount					= static_cast<deUint32>(m_params.viewportData.size());
305 
306 	// create viewport grid
307 	{
308 		const deUint32	columnCount		= deCeilFloatToInt32(deFloatSqrt(static_cast<float>(viewportCount)));
309 		const deUint32	rowCount		= deCeilFloatToInt32(static_cast<float>(viewportCount) / static_cast<float>(columnCount));
310 		const deUint32	rectWidth		= WIDTH / columnCount;
311 		const deUint32	rectHeight		= HEIGHT / rowCount;
312 
313 		VkOffset2D		pos				{ 0, 0 };
314 
315 		for (deUint32 viewportIndex = 0; viewportIndex < viewportCount; ++viewportIndex)
316 		{
317 			// move to next row
318 			if ((viewportIndex != 0) && (viewportIndex % columnCount == 0))
319 			{
320 				pos.x = 0;
321 				pos.y += rectHeight;
322 			}
323 
324 			m_viewportVect[viewportIndex] =
325 			{
326 				static_cast<float>(pos.x),							// float	x;
327 				static_cast<float>(pos.y),							// float	y;
328 				static_cast<float>(rectWidth),						// float	width;
329 				static_cast<float>(rectHeight),						// float	height;
330 				m_params.viewportData[viewportIndex].minDepth,		// float	minDepth;
331 				m_params.viewportData[viewportIndex].maxDepth,		// float	maxDepth;
332 			};
333 
334 			m_scissorVect[viewportIndex] =
335 			{
336 				pos,
337 				{rectWidth, rectHeight}
338 			};
339 
340 			pos.x += rectWidth;
341 		}
342 	}
343 
344 	DescriptorPoolBuilder		descriptorPoolBuilder;
345 	DescriptorSetLayoutBuilder	descriptorSetLayoutBuilder;
346 	// Vertex data
347 	{
348 		const size_t			verticesCount					= DE_LENGTH_OF_ARRAY(vertices);
349 		const VkDeviceSize		dataSize						= verticesCount * sizeof(Vec4);
350 		m_vertexBuffer											= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
351 																m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
352 
353 		Vec4 testVertices[verticesCount];
354 		deMemcpy(testVertices, vertices, dataSize);
355 		for(size_t i = 0; i < verticesCount; ++i)
356 			testVertices[i][2] = params.viewportData[0].depthValue;
357 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), testVertices, static_cast<std::size_t>(dataSize));
358 		flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
359 	}
360 
361 	const VkImageUsageFlags		targetImageUsageFlags						= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
362 	const ImageCreateInfo		targetImageCreateInfo						(VK_IMAGE_TYPE_2D, m_format, { WIDTH, HEIGHT, 1u }, 1u,	1u,	VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, targetImageUsageFlags);
363 	m_depthTargetImage														= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
364 
365 	const ImageViewCreateInfo	depthTargetViewInfo							(m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_format);
366 	m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo);
367 
368 	// Render pass and framebuffer
369 	if (!m_groupParams->useDynamicRendering)
370 	{
371 		RenderPassCreateInfo		renderPassCreateInfo;
372 		renderPassCreateInfo.addAttachment(AttachmentDescription(
373 			m_format,												// format
374 			VK_SAMPLE_COUNT_1_BIT,									// samples
375 			VK_ATTACHMENT_LOAD_OP_LOAD,								// loadOp
376 			VK_ATTACHMENT_STORE_OP_STORE,							// storeOp
377 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// stencilLoadOp
378 			VK_ATTACHMENT_STORE_OP_DONT_CARE,						// stencilStoreOp
379 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// initialLayout
380 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));		// finalLayout
381 		const VkAttachmentReference depthAttachmentReference					= makeAttachmentReference(0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
382 		renderPassCreateInfo.addSubpass(SubpassDescription(
383 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// pipelineBindPoint
384 			(VkSubpassDescriptionFlags)0,		// flags
385 			0u,									// inputAttachmentCount
386 			DE_NULL,							// inputAttachments
387 			0u,									// colorAttachmentCount
388 			DE_NULL,							// colorAttachments
389 			DE_NULL,							// resolveAttachments
390 			depthAttachmentReference,			// depthStencilAttachment
391 			0u,									// preserveAttachmentCount
392 			DE_NULL));							// preserveAttachments
393 		m_renderPass															= createRenderPass(vk, device, &renderPassCreateInfo);
394 
395 		const std::vector<VkImageView>				depthAttachments			{ *m_depthTargetView };
396 		FramebufferCreateInfo						framebufferCreateInfo		(*m_renderPass, depthAttachments, WIDTH, HEIGHT, 1);
397 		m_framebuffer															= createFramebuffer(vk, device, &framebufferCreateInfo);
398 	}
399 
400 	// Vertex input
401 	const VkVertexInputBindingDescription		vertexInputBindingDescription	=
402 	{
403 		0u,										// uint32_t             binding;
404 		sizeof(Vec4),							// uint32_t             stride;
405 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate    inputRate;
406 	};
407 
408 	const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
409 	{
410 		0u,										// uint32_t    location;
411 		0u,										// uint32_t    binding;
412 		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat    format;
413 		0u										// uint32_t    offset;
414 	};
415 
416 	const PipelineCreateInfo::VertexInputState	vertexInputState				= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
417 																													   1, &vertexInputAttributeDescription);
418 
419 	// Graphics pipeline
420 	const Unique<VkShaderModule>	vertexModule								(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
421 	Move<VkShaderModule>			geometryModule;
422 	const Unique<VkShaderModule>	fragmentModule								(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
423 
424 	if (viewportCount > 1)
425 		geometryModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0);
426 
427 	const PipelineLayoutCreateInfo	pipelineLayoutCreateInfo					(0u, DE_NULL, 0u, DE_NULL);
428 	m_pipelineLayout															= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
429 	std::vector<VkDynamicState>		dynamicStates								{ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
430 
431 	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
432 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,   "main", VK_SHADER_STAGE_VERTEX_BIT));
433 	if (*geometryModule != 0)
434 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*geometryModule, "main", VK_SHADER_STAGE_GEOMETRY_BIT));
435 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
436 	pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState	(vertexInputState));
437 	pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(verticesTopology));
438 	pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState		(viewportCount, m_viewportVect, m_scissorVect));
439 	pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState	(VK_TRUE, VK_TRUE, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE));
440 	pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState	(
441 		VK_TRUE,										// depthClampEnable
442 		VK_FALSE,										// rasterizerDiscardEnable
443 		VK_POLYGON_MODE_FILL,							// polygonMode
444 		VK_CULL_MODE_NONE,								// cullMode
445 		VK_FRONT_FACE_CLOCKWISE,						// frontFace
446 		m_params.enableDepthBias ? VK_TRUE : VK_FALSE,	// depthBiasEnable
447 		m_params.depthBiasConstantFactor,				// depthBiasConstantFactor
448 		0.0f,											// depthBiasClamp
449 		0.0f,											// depthBiasSlopeFactor
450 		1.0f));											// lineWidth
451 	pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState	());
452 	pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState		(dynamicStates));
453 
454 #ifndef CTS_USES_VULKANSC
455 	VkPipelineRenderingCreateInfoKHR renderingCreateInfo
456 	{
457 		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
458 		DE_NULL,
459 		0u,
460 		0u,
461 		DE_NULL,
462 		m_format,
463 		m_format
464 	};
465 
466 	if (m_groupParams->useDynamicRendering)
467 		pipelineCreateInfo.pNext = &renderingCreateInfo;
468 #endif // CTS_USES_VULKANSC
469 
470 	m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
471 }
472 
draw()473 tcu::ConstPixelBufferAccess DepthClampTestInstance::draw ()
474 {
475 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
476 	const VkDevice						device				= m_context.getDevice();
477 	const VkQueue						queue				= m_context.getUniversalQueue();
478 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
479 
480 	const CmdPoolCreateInfo				cmdPoolCreateInfo	(queueFamilyIndex);
481 	const Unique<VkCommandPool>			cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo));
482 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
483 	Move<VkCommandBuffer>				secCmdBuffer;
484 	const VkClearValue					clearDepth			= makeClearValueDepthStencil(initialClearDepth, 0u);
485 	const bool							isCombinedType		= tcu::isCombinedDepthStencilType(mapVkFormat(m_format).type) && m_format != VK_FORMAT_X8_D24_UNORM_PACK32;
486 	const VkImageAspectFlagBits			aspectBits			= (VkImageAspectFlagBits)(isCombinedType ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT);
487 
488 #ifndef CTS_USES_VULKANSC
489 	if (m_groupParams->useSecondaryCmdBuffer)
490 	{
491 		secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
492 
493 		// record secondary command buffer
494 		if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
495 		{
496 			beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
497 			beginDynamicRender(*secCmdBuffer, clearDepth);
498 		}
499 		else
500 			beginSecondaryCmdBuffer(*secCmdBuffer);
501 
502 		drawCommands(*secCmdBuffer);
503 
504 		if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
505 			endRendering(vk, *secCmdBuffer);
506 
507 		endCommandBuffer(vk, *secCmdBuffer);
508 
509 		// record primary command buffer
510 		beginCommandBuffer(vk, *cmdBuffer, 0u);
511 		preRenderCommands(*cmdBuffer, aspectBits, clearDepth);
512 
513 		if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
514 			beginDynamicRender(*cmdBuffer, clearDepth, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
515 
516 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
517 
518 		if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
519 			endRendering(vk, *cmdBuffer);
520 	}
521 	else if (m_groupParams->useDynamicRendering)
522 	{
523 		beginCommandBuffer(vk, *cmdBuffer);
524 		preRenderCommands(*cmdBuffer, aspectBits, clearDepth);
525 		beginDynamicRender(*cmdBuffer, clearDepth);
526 		drawCommands(*cmdBuffer);
527 		endRendering(vk, *cmdBuffer);
528 	}
529 #endif // CTS_USES_VULKANSC
530 
531 	if (!m_groupParams->useDynamicRendering)
532 	{
533 		const VkRect2D renderArea = makeRect2D(0, 0, WIDTH, HEIGHT);
534 
535 		beginCommandBuffer(vk, *cmdBuffer);
536 		preRenderCommands(*cmdBuffer, aspectBits, clearDepth);
537 		beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
538 		drawCommands(*cmdBuffer);
539 		endRenderPass(vk, *cmdBuffer);
540 	}
541 
542 	transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), aspectBits,
543 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
544 		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
545 		VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
546 
547 	endCommandBuffer(vk, *cmdBuffer);
548 
549 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
550 
551 	VK_CHECK(vk.queueWaitIdle(queue));
552 
553 	return m_depthTargetImage->readDepth(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { 0, 0, 0 }, WIDTH, HEIGHT, VK_IMAGE_ASPECT_DEPTH_BIT);
554 }
555 
preRenderCommands(VkCommandBuffer cmdBuffer,const VkImageAspectFlagBits aspectBits,const VkClearValue & clearValue) const556 void DepthClampTestInstance::preRenderCommands(VkCommandBuffer cmdBuffer, const VkImageAspectFlagBits aspectBits, const VkClearValue& clearValue) const
557 {
558 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
559 	const bool				isCombinedType	= tcu::isCombinedDepthStencilType(mapVkFormat(m_format).type) && m_format != VK_FORMAT_X8_D24_UNORM_PACK32;
560 
561 	if (isCombinedType)
562 		initialTransitionDepthStencil2DImage(vk, cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
563 	else
564 		initialTransitionDepth2DImage(vk, cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
565 
566 	const ImageSubresourceRange subresourceRange (aspectBits);
567 
568 	vk.cmdClearDepthStencilImage(cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.depthStencil, 1, &subresourceRange);
569 
570 	transition2DImage(vk, cmdBuffer, m_depthTargetImage->object(), aspectBits,
571 					  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
572 					  VK_ACCESS_TRANSFER_WRITE_BIT		  , VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
573 					  VK_PIPELINE_STAGE_TRANSFER_BIT	  , VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
574 
575 	{
576 		const VkMemoryBarrier memBarrier					= { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT };
577 		vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
578 	}
579 }
580 
drawCommands(VkCommandBuffer cmdBuffer) const581 void DepthClampTestInstance::drawCommands(VkCommandBuffer cmdBuffer) const
582 {
583 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
584 	const VkDeviceSize		offset	= 0;
585 	const VkBuffer			buffer	= m_vertexBuffer->object();
586 
587 	// if there is more then one viewport we are also checking
588 	// proper behaviour of cmdSetViewport/Scissor - there was
589 	// a driver bug that caused invalid behaviour of those
590 	// functions when firstViewport/Scissor had a non 0 value
591 	deUint32 indexCount = static_cast<deUint32>(m_viewportVect.size());
592 	for (deUint32 index = 0; index < indexCount; ++index)
593 	{
594 		vk.cmdSetViewport(cmdBuffer, index, 1u, &m_viewportVect[index]);
595 		vk.cmdSetScissor(cmdBuffer, index, 1u, &m_scissorVect[index]);
596 	}
597 
598 	vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
599 	vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &buffer, &offset);
600 	vk.cmdDraw(cmdBuffer, DE_LENGTH_OF_ARRAY(vertices), 1, 0, 0);
601 }
602 
603 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags) const604 void DepthClampTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
605 {
606 	VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
607 	{
608 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
609 		DE_NULL,																// const void*						pNext;
610 		renderingFlags,															// VkRenderingFlagsKHR				flags;
611 		0u,																		// uint32_t							viewMask;
612 		0u,																		// uint32_t							colorAttachmentCount;
613 		DE_NULL,																// const VkFormat*					pColorAttachmentFormats;
614 		m_format,																// VkFormat							depthAttachmentFormat;
615 		VK_FORMAT_UNDEFINED,													// VkFormat							stencilAttachmentFormat;
616 		VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits			rasterizationSamples;
617 	};
618 
619 	const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
620 
621 	VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
622 	if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
623 		usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
624 
625 	const VkCommandBufferBeginInfo commandBufBeginParams
626 	{
627 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
628 		DE_NULL,																// const void*						pNext;
629 		usageFlags,																// VkCommandBufferUsageFlags		flags;
630 		&bufferInheritanceInfo
631 	};
632 
633 	const DeviceInterface& vk = m_context.getDeviceInterface();
634 	VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
635 }
636 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkClearValue clearValue,VkRenderingFlagsKHR renderingFlags) const637 void DepthClampTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkClearValue clearValue, VkRenderingFlagsKHR renderingFlags) const
638 {
639 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
640 	const VkRect2D			renderArea	= makeRect2D(0, 0, WIDTH, HEIGHT);
641 
642 	VkRenderingAttachmentInfoKHR depthAttachment
643 	{
644 		VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,		// VkStructureType						sType;
645 		DE_NULL,												// const void*							pNext;
646 		*m_depthTargetView,										// VkImageView							imageView;
647 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// VkImageLayout						imageLayout;
648 		VK_RESOLVE_MODE_NONE,									// VkResolveModeFlagBits				resolveMode;
649 		DE_NULL,												// VkImageView							resolveImageView;
650 		VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout						resolveImageLayout;
651 		VK_ATTACHMENT_LOAD_OP_LOAD,								// VkAttachmentLoadOp					loadOp;
652 		VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp					storeOp;
653 		clearValue												// VkClearValue							clearValue;
654 	};
655 
656 	VkRenderingInfoKHR renderingInfo
657 	{
658 		VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
659 		DE_NULL,
660 		renderingFlags,											// VkRenderingFlagsKHR					flags;
661 		renderArea,												// VkRect2D								renderArea;
662 		1u,														// deUint32								layerCount;
663 		0u,														// deUint32								viewMask;
664 		0u,														// deUint32								colorAttachmentCount;
665 		DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
666 		&depthAttachment,										// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
667 		DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
668 	};
669 
670 	vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
671 }
672 #endif // CTS_USES_VULKANSC
673 
iterate(void)674 tcu::TestStatus DepthClampTestInstance::iterate (void)
675 {
676 	const tcu::ConstPixelBufferAccess resultImage = draw();
677 
678 	DE_ASSERT((isUnormDepthFormat(m_format) == false) ||
679 		(m_params.viewportData[0].expectedValue >= 0.0f && m_params.viewportData[0].expectedValue <= 1.0f));
680 
681 	for(deUint32 viewportIndex = 0 ; viewportIndex < m_scissorVect.size() ; ++viewportIndex)
682 	{
683 		const float		expectedValue	= m_params.viewportData[viewportIndex].expectedValue;
684 		const VkRect2D&	viewRect		= m_scissorVect[viewportIndex];
685 
686 		deInt32 xStart	= viewRect.offset.x;
687 		deInt32 xEnd	= xStart + viewRect.extent.width;
688 		deInt32 yStart	= viewRect.offset.y;
689 		deInt32 yEnd	= yStart + viewRect.extent.height;
690 
691 		for (int y = yStart; y < yEnd; ++y)
692 		for (int x = xStart; x < xEnd; ++x)
693 		{
694 			if (std::abs(expectedValue - resultImage.getPixDepth(x, y, 0)) >= m_epsilon)
695 			{
696 				tcu::TestLog& log = m_context.getTestContext().getLog();
697 				log << tcu::TestLog::ImageSet("Result of rendering", "")
698 					<< tcu::TestLog::Image("Result", "", resultImage)
699 					<< tcu::TestLog::EndImageSet;
700 
701 				std::ostringstream msg;
702 				msg << "Depth value mismatch, expected: " << expectedValue
703 					<< ", got: " << resultImage.getPixDepth(x, y, 0) << " at (" << x << ", " << y << ", 0)";
704 
705 				return tcu::TestStatus::fail(msg.str());
706 			}
707 		}
708 	}
709 	return tcu::TestStatus::pass("Pass");
710 }
711 
712 class DepthClampTest : public TestCase
713 {
714 public:
DepthClampTest(tcu::TestContext & testCtx,const string & name,const string & description,const TestParams & params,const VkFormat format,const float epsilon,const SharedGroupParams groupParams)715 	DepthClampTest (tcu::TestContext &testCtx, const string& name, const string& description, const TestParams &params, const VkFormat format, const float epsilon, const SharedGroupParams groupParams)
716 		: TestCase		(testCtx, name, description)
717 		, m_params		(params)
718 		, m_format		(format)
719 		, m_epsilon		(epsilon)
720 		, m_groupParams	(groupParams)
721 	{
722 	}
723 
initPrograms(SourceCollections & programCollection) const724 	virtual void initPrograms (SourceCollections& programCollection) const
725 	{
726 		programCollection.glslSources.add("vert") << glu::VertexSource(
727 			"#version 450\n"
728 			"\n"
729 			"layout(location = 0) in vec4 in_position;\n"
730 			"void main(void)\n"
731 			"{\n"
732 			"    gl_Position = in_position;\n"
733 			"}\n");
734 
735 		if (m_params.viewportData.size() > 1)
736 		{
737 			// gl_ViewportIndex built-in variable is available only to the geometry shader
738 
739 			std::string depthValues = "";
740 			for (const auto& vd : m_params.viewportData)
741 				depthValues += std::to_string(vd.depthValue) + ", ";
742 
743 			// this geometry shader draws the same quad but with diferent depth to all viewports
744 			programCollection.glslSources.add("geom") << glu::GeometrySource(
745 				std::string("#version 450\n") +
746 				"#extension GL_EXT_geometry_shader : require\n"
747 				"layout(invocations = " + std::to_string(m_params.viewportData.size()) + ") in;\n"
748 				"layout(triangles) in;\n"
749 				"layout(triangle_strip, max_vertices = 4) out;\n"
750 				"void main()\n"
751 				"{\n"
752 				"  const float depthValues[] = { " + depthValues + " 0.0 };\n"
753 				"  for (int i = 0; i < gl_in.length(); i++)\n"
754 				"  {\n"
755 				"    gl_ViewportIndex = gl_InvocationID;\n"
756 				"    gl_Position      = gl_in[i].gl_Position;\n"
757 				"    gl_Position.z    = depthValues[gl_InvocationID];\n"
758 				"    EmitVertex();\n"
759 				"  }\n"
760 				"  EndPrimitive();\n"
761 				"}");
762 		}
763 
764 		programCollection.glslSources.add("frag") << glu::FragmentSource(
765 			"#version 450\n"
766 			"void main(void)\n"
767 			"{\n"
768 			"}\n");
769 	}
770 
checkSupport(Context & context) const771 	virtual void checkSupport (Context& context) const
772 	{
773 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_CLAMP);
774 		for(const auto& extensionName : m_params.requiredExtensions)
775 			context.requireDeviceFunctionality(extensionName);
776 
777 		if (m_params.viewportData.size() > 1)
778 		{
779 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
780 			if (!context.getDeviceFeatures().geometryShader)
781 				throw tcu::NotSupportedError("Geometry shader is not supported");
782 		}
783 
784 		VkImageFormatProperties imageFormatProperties;
785 		const auto&	vki		= context.getInstanceInterface();
786 		const auto&	vkd		= context.getPhysicalDevice();
787 		const auto	usage	= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
788 		if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0u, &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
789 		{
790 			TCU_THROW(NotSupportedError, "Format not supported");
791 		}
792 
793 		if (m_groupParams->useDynamicRendering)
794 			context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
795 	}
796 
createInstance(Context & context) const797 	virtual TestInstance* createInstance (Context& context) const
798 	{
799 		return new DepthClampTestInstance(context, m_params, m_format, m_epsilon, m_groupParams);
800 	}
801 
802 private:
803 	const TestParams			m_params;
804 	const VkFormat				m_format;
805 	const float					m_epsilon;
806 	const SharedGroupParams		m_groupParams;
807 };
808 
getFormatCaseName(VkFormat format)809 std::string getFormatCaseName (VkFormat format)
810 {
811 	return de::toLower(de::toString(getFormatStr(format)).substr(10));
812 }
813 
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)814 void createTests (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
815 {
816 	for(int i = 0; i < DE_LENGTH_OF_ARRAY(depthStencilImageFormatsToTest); ++i)
817 	{
818 		const auto format = depthStencilImageFormatsToTest[i];
819 
820 		// reduce number of tests for dynamic rendering cases where secondary command buffer is used
821 		if (groupParams->useSecondaryCmdBuffer && (format != VK_FORMAT_D16_UNORM))
822 			continue;
823 
824 		const float		epsilon			= depthEpsilonValuesByFormat[i];
825 		const auto		formatCaseName	= getFormatCaseName(format);
826 		for(const auto& params : depthClearValuesToTest)
827 		{
828 			if ((params.skipSNorm && vk::isSnormFormat(format)) || (params.skipUNorm && isUnormDepthFormat(format)))
829 				continue;
830 			const auto	testCaseName	= formatCaseName + params.testNameSuffix;
831 			testGroup->addChild(new DepthClampTest(testGroup->getTestContext(), testCaseName, "Depth clamp", params, format, epsilon, groupParams));
832 		}
833 	}
834 }
835 }	// anonymous
836 
createDepthClampTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)837 tcu::TestCaseGroup*	createDepthClampTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
838 {
839 	return createTestGroup(testCtx, "depth_clamp", "Depth Clamp Tests", createTests, groupParams);
840 }
841 }	// Draw
842 }	// vkt
843