• 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 Inverted depth ranges tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawInvertedDepthRangesTests.hpp"
26 #include "vktDrawCreateInfoUtil.hpp"
27 #include "vktDrawImageObjectUtil.hpp"
28 #include "vktDrawBufferObjectUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vktTestCaseUtil.hpp"
31 
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 
37 #include "tcuVector.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuImageCompare.hpp"
40 #include "tcuTestLog.hpp"
41 
42 #include "deSharedPtr.hpp"
43 
44 namespace vkt
45 {
46 namespace Draw
47 {
48 namespace
49 {
50 using namespace vk;
51 using tcu::Vec4;
52 using de::SharedPtr;
53 using de::MovePtr;
54 
55 struct TestParams
56 {
57 	VkBool32	depthClampEnable;
58 	float		minDepth;
59 	float		maxDepth;
60 };
61 
62 class InvertedDepthRangesTestInstance : public TestInstance
63 {
64 public:
65 									InvertedDepthRangesTestInstance	(Context& context, const TestParams& params);
66 	tcu::TestStatus					iterate							(void);
67 	tcu::ConstPixelBufferAccess		draw							(const VkViewport viewport);
68 	MovePtr<tcu::TextureLevel>		generateReferenceImage			(void) const;
69 
70 private:
71 	const TestParams				m_params;
72 	const VkFormat					m_colorAttachmentFormat;
73 	SharedPtr<Image>				m_colorTargetImage;
74 	Move<VkImageView>				m_colorTargetView;
75 	SharedPtr<Buffer>				m_vertexBuffer;
76 	Move<VkRenderPass>				m_renderPass;
77 	Move<VkFramebuffer>				m_framebuffer;
78 	Move<VkPipelineLayout>			m_pipelineLayout;
79 	Move<VkPipeline>				m_pipeline;
80 };
81 
InvertedDepthRangesTestInstance(Context & context,const TestParams & params)82 InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& context, const TestParams& params)
83 	: TestInstance				(context)
84 	, m_params					(params)
85 	, m_colorAttachmentFormat	(VK_FORMAT_R8G8B8A8_UNORM)
86 {
87 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
88 	const VkDevice			device	= m_context.getDevice();
89 
90 	if (m_params.depthClampEnable && !m_context.getDeviceFeatures().depthClamp)
91 		TCU_THROW(NotSupportedError, "DepthClamp device feature not supported.");
92 
93 	if (params.minDepth > 1.0f	||
94 		params.minDepth < 0.0f	||
95 		params.maxDepth > 1.0f	||
96 		params.maxDepth < 0.0f)
97 	{
98 		if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_EXT_depth_range_unrestricted"))
99 			throw tcu::NotSupportedError("Test variant with minDepth/maxDepth outside 0..1 requires the VK_EXT_depth_range_unrestricted extension");
100 	}
101 
102 	// Vertex data
103 	{
104 		std::vector<Vec4> vertexData;
105 
106 		vertexData.push_back(Vec4(-0.8f, -0.8f, -0.2f, 1.0f));	//  0-----2
107 		vertexData.push_back(Vec4(-0.8f,  0.8f,  0.0f, 1.0f));	//   |  /
108 		vertexData.push_back(Vec4( 0.8f, -0.8f,  1.2f, 1.0f));	//  1|/
109 
110 		const VkDeviceSize dataSize = vertexData.size() * sizeof(Vec4);
111 		m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
112 												m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
113 
114 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &vertexData[0], static_cast<std::size_t>(dataSize));
115 		flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
116 	}
117 
118 	// Render pass
119 	{
120 		const VkExtent3D		targetImageExtent		= { 256, 256, 1 };
121 		const VkImageUsageFlags	targetImageUsageFlags	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
122 
123 		const ImageCreateInfo	targetImageCreateInfo(
124 			VK_IMAGE_TYPE_2D,						// imageType,
125 			m_colorAttachmentFormat,				// format,
126 			targetImageExtent,						// extent,
127 			1u,										// mipLevels,
128 			1u,										// arrayLayers,
129 			VK_SAMPLE_COUNT_1_BIT,					// samples,
130 			VK_IMAGE_TILING_OPTIMAL,				// tiling,
131 			targetImageUsageFlags);					// usage,
132 
133 		m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
134 
135 		RenderPassCreateInfo	renderPassCreateInfo;
136 		renderPassCreateInfo.addAttachment(AttachmentDescription(
137 			m_colorAttachmentFormat,				// format
138 			VK_SAMPLE_COUNT_1_BIT,					// samples
139 			VK_ATTACHMENT_LOAD_OP_LOAD,				// loadOp
140 			VK_ATTACHMENT_STORE_OP_STORE,			// storeOp
141 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,		// stencilLoadOp
142 			VK_ATTACHMENT_STORE_OP_DONT_CARE,		// stencilStoreOp
143 			VK_IMAGE_LAYOUT_GENERAL,				// initialLayout
144 			VK_IMAGE_LAYOUT_GENERAL));				// finalLayout
145 
146 		const VkAttachmentReference colorAttachmentReference =
147 		{
148 			0u,
149 			VK_IMAGE_LAYOUT_GENERAL
150 		};
151 
152 		renderPassCreateInfo.addSubpass(SubpassDescription(
153 			VK_PIPELINE_BIND_POINT_GRAPHICS,		// pipelineBindPoint
154 			(VkSubpassDescriptionFlags)0,			// flags
155 			0u,										// inputAttachmentCount
156 			DE_NULL,								// inputAttachments
157 			1u,										// colorAttachmentCount
158 			&colorAttachmentReference,				// colorAttachments
159 			DE_NULL,								// resolveAttachments
160 			AttachmentReference(),					// depthStencilAttachment
161 			0u,										// preserveAttachmentCount
162 			DE_NULL));								// preserveAttachments
163 
164 		m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
165 	}
166 
167 	// Framebuffer
168 	{
169 		const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
170 		m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
171 
172 		std::vector<VkImageView> colorAttachments(1);
173 		colorAttachments[0] = *m_colorTargetView;
174 
175 		const FramebufferCreateInfo	framebufferCreateInfo(*m_renderPass, colorAttachments, 256, 256, 1);
176 		m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
177 	}
178 
179 	// Vertex input
180 
181 	const VkVertexInputBindingDescription		vertexInputBindingDescription =
182 	{
183 		0u,										// uint32_t             binding;
184 		sizeof(Vec4),							// uint32_t             stride;
185 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate    inputRate;
186 	};
187 
188 	const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
189 	{
190 		0u,										// uint32_t    location;
191 		0u,										// uint32_t    binding;
192 		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat    format;
193 		0u										// uint32_t    offset;
194 	};
195 
196 	const PipelineCreateInfo::VertexInputState	vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
197 																										1, &vertexInputAttributeDescription);
198 
199 	// Graphics pipeline
200 
201 	const VkRect2D scissor = makeRect2D(256u, 256u);
202 
203 	std::vector<VkDynamicState>		dynamicStates;
204 	dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
205 
206 	const Unique<VkShaderModule>	vertexModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
207 	const Unique<VkShaderModule>	fragmentModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
208 
209 	const PipelineLayoutCreateInfo	pipelineLayoutCreateInfo;
210 	m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
211 
212 	const PipelineCreateInfo::ColorBlendState::Attachment colorBlendAttachmentState;
213 
214 	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
215 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,   "main", VK_SHADER_STAGE_VERTEX_BIT));
216 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
217 	pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState	(vertexInputState));
218 	pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
219 	pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState	(1, &colorBlendAttachmentState));
220 	pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState		(1, std::vector<VkViewport>(), std::vector<VkRect2D>(1, scissor)));
221 	pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState	());
222 	pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState	(
223 		m_params.depthClampEnable,	// depthClampEnable
224 		VK_FALSE,					// rasterizerDiscardEnable
225 		VK_POLYGON_MODE_FILL,		// polygonMode
226 		VK_CULL_MODE_NONE,			// cullMode
227 		VK_FRONT_FACE_CLOCKWISE,	// frontFace
228 		VK_FALSE,					// depthBiasEnable
229 		0.0f,						// depthBiasConstantFactor
230 		0.0f,						// depthBiasClamp
231 		0.0f,						// depthBiasSlopeFactor
232 		1.0f));						// lineWidth
233 	pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState	());
234 	pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState		(dynamicStates));
235 
236 	m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
237 }
238 
draw(const VkViewport viewport)239 tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewport viewport)
240 {
241 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
242 	const VkDevice			device				= m_context.getDevice();
243 	const VkQueue			queue				= m_context.getUniversalQueue();
244 	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
245 
246 	// Command buffer
247 
248 	const CmdPoolCreateInfo			cmdPoolCreateInfo	(queueFamilyIndex);
249 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo));
250 	const Unique<VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
251 
252 	// Draw
253 
254 	beginCommandBuffer(vk, *cmdBuffer);
255 
256 	vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
257 
258 	{
259 		const VkClearColorValue		clearColor			= makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
260 		const ImageSubresourceRange subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
261 
262 		initialTransitionColor2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
263 		vk.cmdClearColorImage(*cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
264 	}
265 	{
266 		const VkMemoryBarrier memBarrier =
267 		{
268 			VK_STRUCTURE_TYPE_MEMORY_BARRIER,												// VkStructureType    sType;
269 			DE_NULL,																		// const void*        pNext;
270 			VK_ACCESS_TRANSFER_WRITE_BIT,													// VkAccessFlags      srcAccessMask;
271 			VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT		// VkAccessFlags      dstAccessMask;
272 		};
273 
274 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
275 	}
276 
277 	beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, 256u, 256u));
278 
279 	{
280 		const VkDeviceSize	offset	= 0;
281 		const VkBuffer		buffer	= m_vertexBuffer->object();
282 
283 		vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
284 	}
285 
286 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
287 	vk.cmdDraw(*cmdBuffer, 3, 1, 0, 0);
288 	endRenderPass(vk, *cmdBuffer);
289 	endCommandBuffer(vk, *cmdBuffer);
290 
291 	// Submit
292 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
293 
294 	// Get result
295 	{
296 		const VkOffset3D zeroOffset = { 0, 0, 0 };
297 		return m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, 256, 256, VK_IMAGE_ASPECT_COLOR_BIT);
298 	}
299 }
300 
generateReferenceImage(void) const301 MovePtr<tcu::TextureLevel> InvertedDepthRangesTestInstance::generateReferenceImage (void) const
302 {
303 	MovePtr<tcu::TextureLevel>		image			(new tcu::TextureLevel(mapVkFormat(m_colorAttachmentFormat), 256, 256));
304 	const tcu::PixelBufferAccess	access			(image->getAccess());
305 	const Vec4						black			(0.0f, 0.0f, 0.0f, 1.0f);
306 	const int						p1				= static_cast<int>(256.0f * 0.2f / 2.0f);
307 	const int						p2				= static_cast<int>(256.0f * 1.8f / 2.0f);
308 	const float						delta			= 256.0f * 1.6f / 2.0f;
309 	const float						depthValues[]	= { -0.2f, 0.0f, 1.2f };
310 
311 	tcu::clear(access, black);
312 
313 	for (int y = p1; y <= p2; ++y)
314 		for (int x = p1; x <  256 - y;  ++x)
315 		{
316 			const float	a = static_cast<float>(p2 - x + p1 - y) / delta;
317 			const float	b = static_cast<float>(y - p1) / delta;
318 			const float	c = 1.0f - a - b;
319 			const float	depth = a * depthValues[0] + b * depthValues[1] + c * depthValues[2];
320 			const float	depthClamped = de::clamp(depth, 0.0f, 1.0f);
321 			const float	depthFinal = depthClamped * m_params.maxDepth + (1.0f - depthClamped) * m_params.minDepth;
322 
323 			if (m_params.depthClampEnable || (depth >= 0.0f && depth <= 1.0f))
324 				access.setPixel(Vec4(depthFinal, 0.5f, 0.5f, 1.0f), x, y);
325 		}
326 
327 	return image;
328 }
329 
iterate(void)330 tcu::TestStatus InvertedDepthRangesTestInstance::iterate (void)
331 {
332 	// Set up the viewport and draw
333 
334 	const VkViewport viewport =
335 	{
336 		0.0f,				// float    x;
337 		0.0f,				// float    y;
338 		256.0f,				// float    width;
339 		256.0f,				// float    height;
340 		m_params.minDepth,	// float    minDepth;
341 		m_params.maxDepth,	// float    maxDepth;
342 	};
343 
344 	const tcu::ConstPixelBufferAccess	resultImage	= draw(viewport);
345 
346 	// Verify the results
347 
348 	tcu::TestLog&				log				= m_context.getTestContext().getLog();
349 	MovePtr<tcu::TextureLevel>	referenceImage	= generateReferenceImage();
350 
351 	if (!tcu::fuzzyCompare(log, "Image compare", "Image compare", referenceImage->getAccess(), resultImage, 0.02f, tcu::COMPARE_LOG_RESULT))
352 		return tcu::TestStatus::fail("Rendered image is incorrect");
353 	else
354 		return tcu::TestStatus::pass("Pass");
355 }
356 
357 class InvertedDepthRangesTest : public TestCase
358 {
359 public:
InvertedDepthRangesTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)360 	InvertedDepthRangesTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
361 		: TestCase	(testCtx, name, description)
362 		, m_params	(params)
363 	{
364 	}
365 
initPrograms(SourceCollections & programCollection) const366 	void initPrograms (SourceCollections& programCollection) const
367 	{
368 		// Vertex shader
369 		{
370 			std::ostringstream src;
371 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
372 				<< "\n"
373 				<< "layout(location = 0) in vec4 in_position;\n"
374 				<< "\n"
375 				<< "out gl_PerVertex {\n"
376 				<< "    vec4  gl_Position;\n"
377 				<< "};\n"
378 				<< "\n"
379 				<< "void main(void)\n"
380 				<< "{\n"
381 				<< "    gl_Position = in_position;\n"
382 				<< "}\n";
383 
384 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
385 		}
386 
387 		// Fragment shader
388 		{
389 			std::ostringstream src;
390 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
391 				<< "\n"
392 				<< "layout(location = 0) out vec4 out_color;\n"
393 				<< "\n"
394 				<< "void main(void)\n"
395 				<< "{\n"
396 				<< "    out_color = vec4(gl_FragCoord.z, 0.5, 0.5, 1.0);\n"
397 				<< "}\n";
398 
399 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
400 		}
401 	}
402 
createInstance(Context & context) const403 	virtual TestInstance* createInstance (Context& context) const
404 	{
405 		return new InvertedDepthRangesTestInstance(context, m_params);
406 	}
407 
408 private:
409 	const TestParams	m_params;
410 };
411 
populateTestGroup(tcu::TestCaseGroup * testGroup)412 void populateTestGroup (tcu::TestCaseGroup* testGroup)
413 {
414 	const struct
415 	{
416 		const char* const	name;
417 		VkBool32			depthClamp;
418 	} depthClamp[] =
419 	{
420 		{ "depthclamp",		VK_TRUE		},
421 		{ "nodepthclamp",	VK_FALSE	},
422 	};
423 
424 	const struct
425 	{
426 		const char* const	name;
427 		float				delta;
428 	} delta[] =
429 	{
430 		{ "deltazero",					0.0f	},
431 		{ "deltasmall",					0.3f	},
432 		{ "deltaone",					1.0f	},
433 
434 		// Range > 1.0 requires VK_EXT_depth_range_unrestricted extension
435 		{ "depth_range_unrestricted",	2.7f	},
436 	};
437 
438 	for (int ndxDepthClamp = 0; ndxDepthClamp < DE_LENGTH_OF_ARRAY(depthClamp); ++ndxDepthClamp)
439 	for (int ndxDelta = 0; ndxDelta < DE_LENGTH_OF_ARRAY(delta); ++ndxDelta)
440 	{
441 		const float minDepth = 0.5f + delta[ndxDelta].delta / 2.0f;
442 		const float maxDepth = minDepth - delta[ndxDelta].delta;
443 		DE_ASSERT(minDepth >= maxDepth);
444 
445 		const TestParams params =
446 		{
447 			depthClamp[ndxDepthClamp].depthClamp,
448 			minDepth,
449 			maxDepth
450 		};
451 		std::ostringstream	name;
452 		name << depthClamp[ndxDepthClamp].name << "_" << delta[ndxDelta].name;
453 
454 		testGroup->addChild(new InvertedDepthRangesTest(testGroup->getTestContext(), name.str(), "", params));
455 	}
456 }
457 
458 }	// anonymous
459 
createInvertedDepthRangesTests(tcu::TestContext & testCtx)460 tcu::TestCaseGroup*	createInvertedDepthRangesTests (tcu::TestContext& testCtx)
461 {
462 	return createTestGroup(testCtx, "inverted_depth_ranges", "Inverted depth ranges", populateTestGroup);
463 }
464 
465 }	// Draw
466 }	// vkt
467