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 
41 #include <cmath>
42 
43 namespace vkt
44 {
45 namespace Draw
46 {
47 namespace {
48 using namespace vk;
49 using namespace de;
50 using std::string;
51 using tcu::Vec4;
52 
53 static const int					WIDTH				= 256;
54 static const int					HEIGHT				= 256;
55 
56 struct TestParams
57 {
58 	string							testNameSuffix;
59 	float							depthValue;
60 	float							expectedValue;
61 	bool							enableDepthBias;
62 	float							depthBiasConstantFactor;
63 	bool							skipUNorm;
64 	bool							skipSNorm;
65 	std::vector<const char*>		requiredExtensions;
66 };
67 
68 const VkFormat		depthStencilImageFormatsToTest[]	=
69 {
70 	VK_FORMAT_D16_UNORM,
71 	VK_FORMAT_X8_D24_UNORM_PACK32,
72 	VK_FORMAT_D32_SFLOAT,
73 	VK_FORMAT_D16_UNORM_S8_UINT,
74 	VK_FORMAT_D24_UNORM_S8_UINT,
75 	VK_FORMAT_D32_SFLOAT_S8_UINT
76 };
77 const float			depthEpsilonValuesByFormat[]		=
78 {
79     1e-5f,
80 	std::numeric_limits<float>::epsilon(),
81 	std::numeric_limits<float>::epsilon(),
82 	1e-5f,
83 	std::numeric_limits<float>::epsilon(),
84 	std::numeric_limits<float>::epsilon()
85 };
86 
87 const float			initialClearDepth				    = 0.5f;
88 const TestParams	depthClearValuesToTest[]			=
89 {
90 	{
91 		"",											// testNameSuffix
92 		0.3f,										// depthValue
93 		0.3f,										// expectedValue
94 		false,										// enableDepthBias
95 		0.0f,										// depthBiasConstantFactor
96 		false,										// skipUNorm
97 		false,										// skipSNorm
98 		{},											// requiredExtensions
99 	},
100 	{
101 		"_clamp_input_negative",					// testNameSuffix
102 		-1e6f,										// depthValue
103 		0.0f,										// expectedValue
104 		false,										// enableDepthBias
105 		0.0f,										// depthBiasConstantFactor
106 		false,										// skipUNorm
107 		false,										// skipSNorm
108 		{},											// requiredExtensions
109 	},
110 	{
111 		"_clamp_input_positive",					// testNameSuffix
112 		1.e6f,										// depthValue
113 		1.0f,										// expectedValue
114 		false,										// enableDepthBias
115 		0.0f,										// depthBiasConstantFactor
116 		false,										// skipUNorm
117 		false,										// skipSNorm
118 		{},											// requiredExtensions
119 	},
120 	{
121 		"_depth_bias_clamp_input_negative",			// testNameSuffix
122 		0.3f,										// depthValue
123 		0.0f,										// expectedValue
124 		true,										// enableDepthBias
125 		-2e11f,										// depthBiasConstantFactor
126 		false,										// skipUNorm
127 		false,										// skipSNorm
128 		{},											// requiredExtensions
129 	},
130 	{
131 		"_depth_bias_clamp_input_positive",			// testNameSuffix
132 		0.7f,										// depthValue
133 		1.0f,										// expectedValue
134 		true,										// enableDepthBias
135 		2e11f,										// depthBiasConstantFactor
136 		false,										// skipUNorm
137 		false,										// skipSNorm
138 		{},											// requiredExtensions
139 	},
140 	{
141 		"_depth_range_unrestricted_negative",		// testNameSuffix
142 		-1.5f,										// depthValue
143 		-1.5f,										// expectedValue
144 		false,										// enableDepthBias
145 		0.0f,										// depthBiasConstantFactor
146 		true,										// skipUNorm
147 		true,										// skipSNorm
148 		{
149 			"VK_EXT_depth_range_unrestricted"		// requiredExtensions[0]
150 		},
151 	},
152 	{
153 		"_depth_range_unrestricted_positive",		// testNameSuffix
154 		1.5f,										// depthValue
155 		1.5f,										// expectedValue
156 		false,										// enableDepthBias
157 		0.0f,										// depthBiasConstantFactor
158 		true,										// skipUNorm
159 		true,										// skipSNorm
160 		{
161 			"VK_EXT_depth_range_unrestricted"		// requiredExtensions[0]
162 		},
163 	}
164 };
165 
isUnormDepthFormat(VkFormat format)166 bool isUnormDepthFormat(VkFormat format)
167 {
168 	switch (format)
169 	{
170 		case VK_FORMAT_D24_UNORM_S8_UINT:
171 		case VK_FORMAT_X8_D24_UNORM_PACK32:
172 		case VK_FORMAT_D16_UNORM_S8_UINT:
173 			/* Special case for combined depth-stencil-unorm modes for which tcu::getTextureChannelClass()
174 			   returns TEXTURECHANNELCLASS_LAST */
175 			return true;
176 		default:
177 			return vk::isUnormFormat(format);
178 	}
179 }
180 
181 class DepthClampTestInstance : public TestInstance {
182 public:
183 								DepthClampTestInstance	(Context& context, const TestParams& params, const VkFormat format, const float epsilon);
184 	tcu::TestStatus				iterate					();
185 
186 private:
187 	tcu::ConstPixelBufferAccess draw					(const VkViewport viewport);
188 
189 	const TestParams									m_params;
190 	const VkFormat										m_format;
191 	const float											m_epsilon;
192 	SharedPtr<Image>									m_depthTargetImage;
193     Move<VkImageView>									m_depthTargetView;
194 	SharedPtr<Buffer>									m_vertexBuffer;
195 	Move<VkRenderPass>									m_renderPass;
196 	Move<VkFramebuffer>									m_framebuffer;
197 	Move<VkPipelineLayout>								m_pipelineLayout;
198 	Move<VkPipeline>									m_pipeline;
199 };
200 
201 static const Vec4					vertices[]			= {
202 	Vec4(-1.0f, -1.0f,  0.5f, 1.0f),	// 0 -- 2
203 	Vec4(-1.0f,  1.0f,  0.5f, 1.0f),	// |  / |
204 	Vec4( 1.0f, -1.0f,  0.5f, 1.0f),	// | /  |
205 	Vec4( 1.0f,  1.0f,  0.5f, 1.0f)		// 1 -- 3
206 };
207 static const VkPrimitiveTopology    verticesTopology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
208 
DepthClampTestInstance(Context & context,const TestParams & params,const VkFormat format,const float epsilon)209 DepthClampTestInstance::DepthClampTestInstance (Context& context, const TestParams& params, const VkFormat format, const float epsilon)
210 	: TestInstance(context)
211 	, m_params(params)
212 	, m_format(format)
213 	, m_epsilon(epsilon)
214 {
215 	const DeviceInterface&		vk								= m_context.getDeviceInterface();
216 	const VkDevice				device							= m_context.getDevice();
217 	const deUint32			    queueFamilyIndex				= m_context.getUniversalQueueFamilyIndex();
218 
219 	DescriptorPoolBuilder		descriptorPoolBuilder;
220 	DescriptorSetLayoutBuilder	descriptorSetLayoutBuilder;
221 	// Vertex data
222 	{
223 		const size_t			verticesCount					= DE_LENGTH_OF_ARRAY(vertices);
224 		const VkDeviceSize		dataSize					    = verticesCount * sizeof(Vec4);
225 		m_vertexBuffer											= Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
226 																m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
227 
228 		Vec4 testVertices[verticesCount];
229 		deMemcpy(testVertices, vertices, dataSize);
230 		for(size_t i = 0; i < verticesCount; ++i)
231 			testVertices[i][2] = params.depthValue;
232 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), testVertices, static_cast<std::size_t>(dataSize));
233 		flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
234 	}
235 	// Render pass
236 	{
237 		const VkImageUsageFlags		targetImageUsageFlags						= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
238 		const ImageCreateInfo		targetImageCreateInfo						(VK_IMAGE_TYPE_2D, m_format, { WIDTH, HEIGHT, 1u }, 1u,	1u,	VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, targetImageUsageFlags);
239 		m_depthTargetImage														= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
240 
241 		RenderPassCreateInfo		renderPassCreateInfo;
242 		renderPassCreateInfo.addAttachment(AttachmentDescription(
243 			m_format,												// format
244 			VK_SAMPLE_COUNT_1_BIT,									// samples
245 			VK_ATTACHMENT_LOAD_OP_LOAD,								// loadOp
246 			VK_ATTACHMENT_STORE_OP_STORE,							// storeOp
247 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// stencilLoadOp
248 			VK_ATTACHMENT_STORE_OP_DONT_CARE,						// stencilStoreOp
249 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// initialLayout
250 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));		// finalLayout
251 		const VkAttachmentReference depthAttachmentReference					= makeAttachmentReference(0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
252 		renderPassCreateInfo.addSubpass(SubpassDescription(
253 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// pipelineBindPoint
254 			(VkSubpassDescriptionFlags)0,		// flags
255 			0u,									// inputAttachmentCount
256 			DE_NULL,							// inputAttachments
257 			0u,									// colorAttachmentCount
258 			DE_NULL,							// colorAttachments
259 			DE_NULL,							// resolveAttachments
260 			depthAttachmentReference,			// depthStencilAttachment
261 			0u,									// preserveAttachmentCount
262 			DE_NULL));							// preserveAttachments
263 		m_renderPass														    = createRenderPass(vk, device, &renderPassCreateInfo);
264 	}
265 
266 	const ImageViewCreateInfo					depthTargetViewInfo				(m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_format);
267 	m_depthTargetView															= createImageView(vk, device, &depthTargetViewInfo);
268 
269 	const std::vector<VkImageView>				depthAttachments				{ *m_depthTargetView };
270 	FramebufferCreateInfo						framebufferCreateInfo			(*m_renderPass, depthAttachments, WIDTH, HEIGHT, 1);
271 
272 	m_framebuffer																= createFramebuffer(vk, device, &framebufferCreateInfo);
273 
274 	// Vertex input
275 	const VkVertexInputBindingDescription		vertexInputBindingDescription	=
276 	{
277 		0u,										// uint32_t             binding;
278 		sizeof(Vec4),							// uint32_t             stride;
279 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate    inputRate;
280 	};
281 
282 	const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
283 	{
284 		0u,										// uint32_t    location;
285 		0u,										// uint32_t    binding;
286 		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat    format;
287 		0u										// uint32_t    offset;
288 	};
289 
290 	const PipelineCreateInfo::VertexInputState	vertexInputState				= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
291 																													   1, &vertexInputAttributeDescription);
292 
293 	// Graphics pipeline
294 	const Unique<VkShaderModule>	vertexModule								(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
295 	const Unique<VkShaderModule>	fragmentModule								(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
296 
297 	const PipelineLayoutCreateInfo	pipelineLayoutCreateInfo					(0u, DE_NULL, 0u, DE_NULL);
298 	m_pipelineLayout															= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
299 
300 	const VkRect2D					scissor										= makeRect2D(WIDTH, HEIGHT);
301 	const VkViewport				viewport									= makeViewport(WIDTH, HEIGHT);
302 	std::vector<VkDynamicState>		dynamicStates								(1, VK_DYNAMIC_STATE_VIEWPORT);
303 
304 	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
305 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,   "main", VK_SHADER_STAGE_VERTEX_BIT));
306 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
307 	pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState	(vertexInputState));
308 	pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(verticesTopology));
309 	pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState		(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
310 	pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState	(VK_TRUE, VK_TRUE, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE));
311 	pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState	(
312 		VK_TRUE,										// depthClampEnable
313 		VK_FALSE,										// rasterizerDiscardEnable
314 		VK_POLYGON_MODE_FILL,							// polygonMode
315 		VK_CULL_MODE_NONE,								// cullMode
316 		VK_FRONT_FACE_CLOCKWISE,						// frontFace
317 		m_params.enableDepthBias ? VK_TRUE : VK_FALSE,	// depthBiasEnable
318 		m_params.depthBiasConstantFactor,				// depthBiasConstantFactor
319 		0.0f,											// depthBiasClamp
320 		0.0f,											// depthBiasSlopeFactor
321 		1.0f));											// lineWidth
322 	pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState	());
323 	pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState		(dynamicStates));
324 	m_pipeline																	= createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
325 }
326 
draw(const VkViewport viewport)327 tcu::ConstPixelBufferAccess DepthClampTestInstance::draw (const VkViewport viewport)
328 {
329 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
330 	const VkDevice						device				= m_context.getDevice();
331 	const VkQueue						queue				= m_context.getUniversalQueue();
332 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
333 
334 	const CmdPoolCreateInfo				cmdPoolCreateInfo	(queueFamilyIndex);
335 	const Unique<VkCommandPool>			cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo));
336 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
337 
338 	const bool							isCombinedType		= tcu::isCombinedDepthStencilType(mapVkFormat(m_format).type) && m_format != VK_FORMAT_X8_D24_UNORM_PACK32;
339 
340 	beginCommandBuffer(vk, *cmdBuffer);
341 	vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
342 	if (isCombinedType)
343 		initialTransitionDepthStencil2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
344 	else
345 		initialTransitionDepth2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
346 
347 	const VkImageAspectFlagBits			aspectBits			= (VkImageAspectFlagBits)(isCombinedType ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT);
348 	const ImageSubresourceRange			subresourceRange	(aspectBits);
349 	const VkClearDepthStencilValue		clearDepth		    = makeClearDepthStencilValue(initialClearDepth, 0u);
350 
351 	vk.cmdClearDepthStencilImage(*cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearDepth, 1, &subresourceRange);
352 
353 	transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), aspectBits,
354 					  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
355 					  VK_ACCESS_TRANSFER_WRITE_BIT		  , VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
356 					  VK_PIPELINE_STAGE_TRANSFER_BIT	  , VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
357 
358 	{
359 		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 };
360 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
361 	}
362 
363 	beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT));
364 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
365 	const VkDeviceSize		offset							= 0;
366 	const VkBuffer			buffer							= m_vertexBuffer->object();
367 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
368 	vk.cmdDraw(*cmdBuffer, DE_LENGTH_OF_ARRAY(vertices), 1, 0, 0);
369 	endRenderPass(vk, *cmdBuffer);
370 
371 	transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), aspectBits,
372 					  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
373 					  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT	  , VK_ACCESS_MEMORY_READ_BIT,
374 					  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT		  , VK_PIPELINE_STAGE_HOST_BIT);
375 
376 	endCommandBuffer(vk, *cmdBuffer);
377 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
378 
379 	VK_CHECK(vk.queueWaitIdle(queue));
380 
381 	return m_depthTargetImage->readDepth(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { 0, 0, 0 }, WIDTH, HEIGHT, VK_IMAGE_ASPECT_DEPTH_BIT);
382 }
383 
iterate(void)384 tcu::TestStatus DepthClampTestInstance::iterate (void)
385 {
386 	// Set up the viewport and draw
387 	const VkViewport viewport						=
388 	{
389 		0.0f,															// float    x;
390 		0.0f,															// float    y;
391 		WIDTH,															// float    width;
392 		HEIGHT,															// float    height;
393 		m_params.expectedValue < 0.0f ? m_params.expectedValue : 0.0f,	// float    minDepth;
394 		m_params.expectedValue > 1.0f ? m_params.expectedValue : 1.0f,	// float    maxDepth;
395 	};
396 	const tcu::ConstPixelBufferAccess	resultImage	= draw(viewport);
397 
398 	DE_ASSERT((isUnormDepthFormat(m_format) == false) ||
399 		(m_params.expectedValue >= 0.0f && m_params.expectedValue <= 1.0f));
400 
401 	for(int z = 0; z < resultImage.getDepth(); ++z)
402 	for(int y = 0; y < resultImage.getHeight(); ++y)
403 	for(int x = 0; x < resultImage.getWidth(); ++x)
404 	{
405 		if (std::abs(m_params.expectedValue - resultImage.getPixDepth(x,y,z)) >= m_epsilon)
406 		{
407 			std::ostringstream msg;
408 			msg << "Depth value mismatch, expected: " << m_params.expectedValue << ", got: " << resultImage.getPixDepth(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")";
409 			return tcu::TestStatus::fail(msg.str());
410 		}
411 	}
412 	return tcu::TestStatus::pass("Pass");
413 }
414 
415 class DepthClampTest : public TestCase
416 {
417 public:
DepthClampTest(tcu::TestContext & testCtx,const string & name,const string & description,const TestParams & params,const VkFormat format,const float epsilon)418     DepthClampTest (tcu::TestContext &testCtx, const string& name, const string& description, const TestParams &params, const VkFormat format, const float epsilon)
419 		: TestCase	(testCtx, name, description)
420 		, m_params(params)
421 		, m_format(format)
422 		, m_epsilon(epsilon)
423 	{
424 	}
425 
initPrograms(SourceCollections & programCollection) const426 	virtual void initPrograms (SourceCollections& programCollection) const
427 	{
428 		{
429 			std::ostringstream src;
430 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
431 				<< "\n"
432 				<< "layout(location = 0) in vec4 in_position;\n"
433 				<< "\n"
434 				<< "out gl_PerVertex {\n"
435 				<< "    vec4  gl_Position;\n"
436 				<< "};\n"
437 				<< "\n"
438 				<< "void main(void)\n"
439 				<< "{\n"
440 				<< "    gl_Position = in_position;\n"
441 				<< "}\n";
442 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
443 		}
444 		{
445 			std::ostringstream src;
446 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
447 				<< "\n"
448 				<< "void main(void)\n"
449 				<< "{\n"
450 				<< "}\n";
451 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
452 		}
453 	}
454 
checkSupport(Context & context) const455 	virtual void checkSupport (Context& context) const
456 	{
457 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_CLAMP);
458 		for(const auto& extensionName : m_params.requiredExtensions)
459 		{
460 			context.requireDeviceFunctionality(extensionName);
461 		}
462 		VkImageFormatProperties imageFormatProperties;
463 		const auto&	vki		= context.getInstanceInterface();
464 		const auto&	vkd		= context.getPhysicalDevice();
465 		const auto	usage	= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
466 		if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0u, &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
467 		{
468 			TCU_THROW(NotSupportedError, "Format not supported");
469 		}
470 	}
471 
createInstance(Context & context) const472 	virtual TestInstance* createInstance (Context& context) const
473 	{
474 		return new DepthClampTestInstance(context, m_params, m_format, m_epsilon);
475 	}
476 
477 private:
478 	const TestParams	m_params;
479 	const VkFormat		m_format;
480 	const float			m_epsilon;
481 };
482 
getFormatCaseName(VkFormat format)483 std::string getFormatCaseName (VkFormat format)
484 {
485 	return de::toLower(de::toString(getFormatStr(format)).substr(10));
486 }
487 
createTests(tcu::TestCaseGroup * testGroup)488 void createTests (tcu::TestCaseGroup* testGroup)
489 {
490 	for(int i = 0; i < DE_LENGTH_OF_ARRAY(depthStencilImageFormatsToTest); ++i)
491 	{
492 		const auto		format			= depthStencilImageFormatsToTest[i];
493 		const float		epsilon			= depthEpsilonValuesByFormat[i];
494 		const auto		formatCaseName	= getFormatCaseName(format);
495 		for(const auto& params : depthClearValuesToTest)
496 		{
497 			if ((params.skipSNorm && vk::isSnormFormat(format)) || (params.skipUNorm && isUnormDepthFormat(format)))
498 				continue;
499 			const auto	testCaseName	= formatCaseName + params.testNameSuffix;
500 			testGroup->addChild(new DepthClampTest(testGroup->getTestContext(), testCaseName, "Depth clamp", params, format, epsilon));
501 		}
502 	}
503 }
504 }	// anonymous
505 
createDepthClampTests(tcu::TestContext & testCtx)506 tcu::TestCaseGroup*	createDepthClampTests (tcu::TestContext& testCtx)
507 {
508 	return createTestGroup(testCtx, "depth_clamp", "Depth Clamp Tests", createTests);
509 }
510 }	// Draw
511 }	// vkt
512