• 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 "vkQueryUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 
38 #include "tcuVector.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuTestLog.hpp"
42 
43 #include "deSharedPtr.hpp"
44 
45 #include <utility>
46 #include <array>
47 #include <vector>
48 #include <iterator>
49 
50 namespace vkt
51 {
52 namespace Draw
53 {
54 namespace
55 {
56 using namespace vk;
57 using tcu::Vec4;
58 using de::SharedPtr;
59 using de::MovePtr;
60 
61 struct TestParams
62 {
63 	float					minDepth;
64 	float					maxDepth;
65 	VkBool32				depthClampEnable;
66 	VkBool32				depthBiasEnable;
67 	float					depthBiasClamp;
68 	const SharedGroupParams	groupParams;
69 };
70 
71 constexpr deUint32			kImageDim		= 256u;
72 const VkExtent3D			kImageExtent	= makeExtent3D(kImageDim, kImageDim, 1u);
73 const Vec4					kClearColor		(0.0f, 0.0f, 0.0f, 1.0f);
74 constexpr float				kClearDepth		= 1.0f;
75 constexpr int				kClearStencil	= 0;
76 constexpr int				kMaskedStencil	= 1;
77 constexpr float				kDepthEpsilon	= 0.00025f;	// Used to decide if a calculated depth passes the depth test.
78 constexpr float				kDepthThreshold	= 0.0025f;	// Used when checking depth buffer values. Less than depth delta in each pixel (~= 1.4/205).
79 constexpr float				kMargin			= 0.2f;		// Space between triangle and image border. See kVertices.
80 constexpr float				kDiagonalMargin	= 0.00125f; // Makes sure the image diagonal falls inside the triangle. See kVertices.
81 const Vec4					kVertexColor	(0.0f, 0.5f, 0.5f, 1.0f); // Note: the first component will vary.
82 
83 // Maximum depth slope is constant for triangle and the value here is true only for triangle used it this tests.
84 constexpr float				kMaxDepthSlope = 1.4f / 205;
85 
86 const std::array<Vec4, 3u>	kVertices		=
87 {{
88 	Vec4(-1.0f + kMargin,                   -1.0f + kMargin,                    -0.2f, 1.0f),	//  0-----2
89 	Vec4(-1.0f + kMargin,                    1.0f - kMargin + kDiagonalMargin,   0.0f, 1.0f),	//   |  /
90 	Vec4( 1.0f - kMargin + kDiagonalMargin, -1.0f + kMargin,                     1.2f, 1.0f),	//  1|/
91 }};
92 
93 
94 class InvertedDepthRangesTestInstance : public TestInstance
95 {
96 public:
97 	enum class ReferenceImageType
98 	{
99 		COLOR = 0,
100 		DEPTH,
101 	};
102 
103 	using ColorAndDepth = std::pair<tcu::ConstPixelBufferAccess, tcu::ConstPixelBufferAccess>;
104 
105 												InvertedDepthRangesTestInstance	(Context& context, const TestParams& params);
106 	tcu::TestStatus								iterate							(void);
107 
108 	void										preRenderCommands				(VkCommandBuffer cmdBuffer,
109 																				 const VkClearValue& clearColor, const VkClearValue& clearDepth);
110 	void										draw							(VkCommandBuffer cmdBuffer, const VkViewport& viewport);
111 
112 	MovePtr<tcu::TextureLevel>					generateReferenceImage			(ReferenceImageType refType) const;
113 
114 #ifndef CTS_USES_VULKANSC
115 	void										beginSecondaryCmdBuffer			(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u);
116 	void										beginRender						(VkCommandBuffer cmdBuffer, const VkClearValue& clearColor,
117 																				 const VkClearValue& clearDepth, VkRenderingFlagsKHR renderingFlags = 0);
118 #endif // CTS_USES_VULKANSC
119 
120 private:
121 	const TestParams				m_params;
122 	const VkFormat					m_colorAttachmentFormat;
123 	const VkFormat					m_depthAttachmentFormat;
124 	SharedPtr<Image>				m_colorTargetImage;
125 	Move<VkImageView>				m_colorTargetView;
126 	SharedPtr<Image>				m_depthTargetImage;
127 	Move<VkImageView>				m_depthTargetView;
128 	SharedPtr<Buffer>				m_vertexBuffer;
129 	Move<VkRenderPass>				m_renderPass;
130 	Move<VkFramebuffer>				m_framebuffer;
131 	Move<VkPipelineLayout>			m_pipelineLayout;
132 	Move<VkPipeline>				m_pipeline;
133 };
134 
InvertedDepthRangesTestInstance(Context & context,const TestParams & params)135 InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& context, const TestParams& params)
136 	: TestInstance				(context)
137 	, m_params					(params)
138 	, m_colorAttachmentFormat	(VK_FORMAT_R8G8B8A8_UNORM)
139 	, m_depthAttachmentFormat	(VK_FORMAT_D16_UNORM)
140 {
141 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
142 	const VkDevice			device	= m_context.getDevice();
143 	auto&					alloc	= m_context.getDefaultAllocator();
144 	auto					qIndex	= m_context.getUniversalQueueFamilyIndex();
145 
146 	// Vertex data
147 	{
148 		const auto dataSize = static_cast<VkDeviceSize>(kVertices.size() * sizeof(decltype(kVertices)::value_type));
149 		m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
150 												alloc, MemoryRequirement::HostVisible);
151 
152 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), kVertices.data(), static_cast<size_t>(dataSize));
153 		flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
154 	}
155 
156 	const VkImageUsageFlags	targetImageUsageFlags	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
157 	const VkImageUsageFlags depthTargeUsageFlags	= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
158 
159 	const ImageCreateInfo	targetImageCreateInfo(
160 		VK_IMAGE_TYPE_2D,						// imageType,
161 		m_colorAttachmentFormat,				// format,
162 		kImageExtent,							// extent,
163 		1u,										// mipLevels,
164 		1u,										// arrayLayers,
165 		VK_SAMPLE_COUNT_1_BIT,					// samples,
166 		VK_IMAGE_TILING_OPTIMAL,				// tiling,
167 		targetImageUsageFlags);					// usage,
168 
169 	m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, alloc, qIndex);
170 
171 	const ImageCreateInfo	depthTargetImageCreateInfo(
172 		VK_IMAGE_TYPE_2D,						// imageType,
173 		m_depthAttachmentFormat,				// format,
174 		kImageExtent,							// extent,
175 		1u,										// mipLevels,
176 		1u,										// arrayLayers,
177 		VK_SAMPLE_COUNT_1_BIT,					// samples,
178 		VK_IMAGE_TILING_OPTIMAL,				// tiling,
179 		depthTargeUsageFlags);					// usage,
180 
181 	m_depthTargetImage = Image::createAndAlloc(vk, device, depthTargetImageCreateInfo, alloc, qIndex);
182 
183 	const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
184 	m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
185 
186 	const ImageViewCreateInfo depthTargetViewInfo(m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_depthAttachmentFormat);
187 	m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo);
188 
189 	// Render pass and framebuffer
190 	if (!m_params.groupParams->useDynamicRendering)
191 	{
192 		RenderPassCreateInfo	renderPassCreateInfo;
193 		renderPassCreateInfo.addAttachment(AttachmentDescription(
194 			m_colorAttachmentFormat,				// format
195 			VK_SAMPLE_COUNT_1_BIT,					// samples
196 			VK_ATTACHMENT_LOAD_OP_LOAD,				// loadOp
197 			VK_ATTACHMENT_STORE_OP_STORE,			// storeOp
198 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,		// stencilLoadOp
199 			VK_ATTACHMENT_STORE_OP_DONT_CARE,		// stencilStoreOp
200 			VK_IMAGE_LAYOUT_GENERAL,				// initialLayout
201 			VK_IMAGE_LAYOUT_GENERAL));				// finalLayout
202 
203 		renderPassCreateInfo.addAttachment(AttachmentDescription(
204 			m_depthAttachmentFormat,				// format
205 			VK_SAMPLE_COUNT_1_BIT,					// samples
206 			VK_ATTACHMENT_LOAD_OP_LOAD,				// loadOp
207 			VK_ATTACHMENT_STORE_OP_STORE,			// storeOp
208 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,		// stencilLoadOp
209 			VK_ATTACHMENT_STORE_OP_DONT_CARE,		// stencilStoreOp
210 			VK_IMAGE_LAYOUT_GENERAL,				// initialLayout
211 			VK_IMAGE_LAYOUT_GENERAL));				// finalLayout
212 
213 		const VkAttachmentReference colorAttachmentReference =
214 		{
215 			0u,
216 			VK_IMAGE_LAYOUT_GENERAL
217 		};
218 
219 		const VkAttachmentReference depthAttachmentReference =
220 		{
221 			1u,
222 			VK_IMAGE_LAYOUT_GENERAL
223 		};
224 
225 		renderPassCreateInfo.addSubpass(SubpassDescription(
226 			VK_PIPELINE_BIND_POINT_GRAPHICS,		// pipelineBindPoint
227 			(VkSubpassDescriptionFlags)0,			// flags
228 			0u,										// inputAttachmentCount
229 			DE_NULL,								// inputAttachments
230 			1u,										// colorAttachmentCount
231 			&colorAttachmentReference,				// colorAttachments
232 			DE_NULL,								// resolveAttachments
233 			depthAttachmentReference,				// depthStencilAttachment
234 			0u,										// preserveAttachmentCount
235 			DE_NULL));								// preserveAttachments
236 
237 		m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
238 
239 		std::vector<VkImageView> fbAttachments
240 		{
241 			*m_colorTargetView,
242 			*m_depthTargetView
243 		};
244 
245 		const FramebufferCreateInfo	framebufferCreateInfo(*m_renderPass, fbAttachments, kImageExtent.width, kImageExtent.height, 1u);
246 		m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
247 	}
248 
249 	// Vertex input
250 
251 	const VkVertexInputBindingDescription		vertexInputBindingDescription =
252 	{
253 		0u,										// uint32_t             binding;
254 		sizeof(Vec4),							// uint32_t             stride;
255 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate    inputRate;
256 	};
257 
258 	const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
259 	{
260 		0u,										// uint32_t    location;
261 		0u,										// uint32_t    binding;
262 		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat    format;
263 		0u										// uint32_t    offset;
264 	};
265 
266 	const PipelineCreateInfo::VertexInputState	vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
267 																										1, &vertexInputAttributeDescription);
268 
269 	// Graphics pipeline
270 
271 	const auto scissor = makeRect2D(kImageExtent);
272 
273 	std::vector<VkDynamicState>		dynamicStates;
274 	dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
275 
276 	const Unique<VkShaderModule>	vertexModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
277 	const Unique<VkShaderModule>	fragmentModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
278 
279 	const PipelineLayoutCreateInfo	pipelineLayoutCreateInfo;
280 	m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
281 
282 	const PipelineCreateInfo::ColorBlendState::Attachment colorBlendAttachmentState;
283 
284 	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
285 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,   "main", VK_SHADER_STAGE_VERTEX_BIT));
286 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
287 	pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState	(vertexInputState));
288 	pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
289 	pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState	(1, &colorBlendAttachmentState));
290 	pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState		(1, std::vector<VkViewport>(), std::vector<VkRect2D>(1, scissor)));
291 	pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState	(true, true));
292 	pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState	(
293 		m_params.depthClampEnable,										// depthClampEnable
294 		VK_FALSE,														// rasterizerDiscardEnable
295 		VK_POLYGON_MODE_FILL,											// polygonMode
296 		VK_CULL_MODE_NONE,												// cullMode
297 		VK_FRONT_FACE_CLOCKWISE,										// frontFace
298 		m_params.depthBiasEnable,										// depthBiasEnable
299 		0.0f,															// depthBiasConstantFactor
300 		m_params.depthBiasEnable ? m_params.depthBiasClamp : 0.0f,		// depthBiasClamp
301 		m_params.depthBiasEnable ? 1.0f : 0.0f,							// depthBiasSlopeFactor
302 		1.0f));															// lineWidth
303 	pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState	());
304 	pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState		(dynamicStates));
305 
306 #ifndef CTS_USES_VULKANSC
307 	VkPipelineRenderingCreateInfoKHR renderingCreateInfo
308 	{
309 		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
310 		DE_NULL,
311 		0u,
312 		1u,
313 		&m_colorAttachmentFormat,
314 		m_depthAttachmentFormat,
315 		VK_FORMAT_UNDEFINED
316 	};
317 
318 	if (m_params.groupParams->useDynamicRendering)
319 		pipelineCreateInfo.pNext = &renderingCreateInfo;
320 #endif // CTS_USES_VULKANSC
321 
322 	m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
323 }
324 
preRenderCommands(VkCommandBuffer cmdBuffer,const VkClearValue & clearColor,const VkClearValue & clearDepth)325 void InvertedDepthRangesTestInstance::preRenderCommands (VkCommandBuffer cmdBuffer, const VkClearValue& clearColor, const VkClearValue& clearDepth)
326 {
327 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
328 	const ImageSubresourceRange		subresourceRange		(VK_IMAGE_ASPECT_COLOR_BIT);
329 	const ImageSubresourceRange		depthSubresourceRange	(VK_IMAGE_ASPECT_DEPTH_BIT);
330 
331 	initialTransitionColor2DImage(vk, cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
332 	initialTransitionDepth2DImage(vk, cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
333 	vk.cmdClearColorImage(cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &subresourceRange);
334 	vk.cmdClearDepthStencilImage(cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearDepth.depthStencil, 1u, &depthSubresourceRange);
335 
336 	const VkMemoryBarrier memBarrier
337 	{
338 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,																// VkStructureType		sType;
339 		DE_NULL,																						// const void*			pNext;
340 		VK_ACCESS_TRANSFER_WRITE_BIT,																	// VkAccessFlags		srcAccessMask;
341 		VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT						// VkAccessFlags		dstAccessMask;
342 	};
343 
344 	const VkMemoryBarrier depthBarrier
345 	{
346 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,																// VkStructureType		sType;
347 		DE_NULL,																						// const void*			pNext;
348 		VK_ACCESS_TRANSFER_WRITE_BIT,																	// VkAccessFlags		srcAccessMask;
349 		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT		// VkAccessFlags		dstAccessMask;
350 	};
351 
352 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
353 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), 0, 1, &depthBarrier, 0, DE_NULL, 0, DE_NULL);
354 }
355 
draw(VkCommandBuffer cmdBuffer,const VkViewport & viewport)356 void InvertedDepthRangesTestInstance::draw (VkCommandBuffer cmdBuffer, const VkViewport& viewport)
357 {
358 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
359 	const VkBuffer			buffer	= m_vertexBuffer->object();
360 	const VkDeviceSize		offset	= 0;
361 
362 	vk.cmdSetViewport(cmdBuffer, 0u, 1u, &viewport);
363 	vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &buffer, &offset);
364 	vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
365 	vk.cmdDraw(cmdBuffer, 3, 1, 0, 0);
366 }
367 
generateReferenceImage(ReferenceImageType refType) const368 MovePtr<tcu::TextureLevel> InvertedDepthRangesTestInstance::generateReferenceImage (ReferenceImageType refType) const
369 {
370 	const auto						iWidth			= static_cast<int>(kImageExtent.width);
371 	const auto						iHeight			= static_cast<int>(kImageExtent.height);
372 	const bool						color			= (refType == ReferenceImageType::COLOR);
373 	const auto						tcuFormat		= mapVkFormat(color ? m_colorAttachmentFormat : VK_FORMAT_D16_UNORM_S8_UINT);
374 	MovePtr<tcu::TextureLevel>		image			(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
375 	const tcu::PixelBufferAccess	access			(image->getAccess());
376 	const float						fImageDim		= static_cast<float>(kImageDim);
377 	const float						p1f				= fImageDim * kMargin / 2.0f;
378 	const float						p2f				= fImageDim * (2.0f - kMargin + kDiagonalMargin) / 2.0f;
379 	const float						triangleSide	= fImageDim * (2.0f - (2.0f*kMargin - kDiagonalMargin)) / 2.0f;
380 	const float						clampMin		= de::min(m_params.minDepth, m_params.maxDepth);
381 	const float						clampMax		= de::max(m_params.minDepth, m_params.maxDepth);
382 	std::array<float, 3>			depthValues;
383 	float							depthBias		= 0.0f;
384 
385 	// Depth value of each vertex in kVertices.
386 	DE_ASSERT(depthValues.size() == kVertices.size());
387 	std::transform(begin(kVertices), end(kVertices), begin(depthValues), [](const Vec4& coord) { return coord.z(); });
388 
389 	if (color)
390 		tcu::clear(access, kClearColor);
391 	else
392 	{
393 		tcu::clearDepth(access, kClearDepth);
394 		tcu::clearStencil(access, kClearStencil);
395 
396 		if (m_params.depthBiasEnable)
397 		{
398 			const float	depthBiasSlopeFactor	= 1.0f;
399 			const float	r						= 0.000030518f;		// minimum resolvable difference is an implementation-dependent parameter
400 			const float	depthBiasConstantFactor	= 0.0f;				// so we use factor 0.0 to not include it; same as in PipelineCreateInfo
401 
402 			// Equations taken from vkCmdSetDepthBias manual page
403 			depthBias = kMaxDepthSlope * depthBiasSlopeFactor + r * depthBiasConstantFactor;
404 
405 			// dbclamp(x) function depends on the sign of the depthBiasClamp
406 			if (m_params.depthBiasClamp < 0.0f)
407 				depthBias = de::max(depthBias, m_params.depthBiasClamp);
408 			else if (m_params.depthBiasClamp > 0.0f)
409 				depthBias = de::min(depthBias, m_params.depthBiasClamp);
410 
411 			if (m_params.maxDepth < m_params.minDepth)
412 				depthBias *= -1.0f;
413 		}
414 	}
415 
416 	for (int y = 0; y < iHeight; ++y)
417 	for (int x = 0; x < iWidth; ++x)
418 	{
419 		const float xcoord = static_cast<float>(x) + 0.5f;
420 		const float ycoord = static_cast<float>(y) + 0.5f;
421 
422 		if (xcoord < p1f || xcoord > p2f)
423 			continue;
424 
425 		if (ycoord < p1f || ycoord > p2f)
426 			continue;
427 
428 		if (ycoord > -xcoord + fImageDim)
429 			continue;
430 
431 		// Interpolate depth value taking the 3 triangle corners into account.
432 		const float b				= (ycoord - p1f) / triangleSide;
433 		const float c				= (xcoord - p1f) / triangleSide;
434 		const float a				= 1.0f - b - c;
435 		const float depth			= a * depthValues[0] + b * depthValues[1] + c * depthValues[2];
436 
437 		// Depth values are always limited to the range [0,1] by clamping after depth bias addition is performed
438 		const float depthClamped	= de::clamp(depth + depthBias, 0.0f, 1.0f);
439 		const float depthFinal		= depthClamped * m_params.maxDepth + (1.0f - depthClamped) * m_params.minDepth;
440 		const float storedDepth		= (m_params.depthClampEnable ? de::clamp(depthFinal, clampMin, clampMax) : depthFinal);
441 
442 		if (m_params.depthClampEnable || de::inRange(depth, -kDepthEpsilon, 1.0f + kDepthEpsilon))
443 		{
444 			if (color)
445 				access.setPixel(Vec4(depthFinal, kVertexColor.y(), kVertexColor.z(), kVertexColor.w()), x, y);
446 			else
447 			{
448 				if (!m_params.depthClampEnable &&
449 					(de::inRange(depth, -kDepthEpsilon, kDepthEpsilon) ||
450 					 de::inRange(depth, 1.0f - kDepthEpsilon, 1.0f + kDepthEpsilon)))
451 				{
452 					// We should avoid comparing this pixel due to possible rounding problems.
453 					// Pixels that should not be compared will be marked in the stencil aspect.
454 					access.setPixStencil(kMaskedStencil, x, y);
455 				}
456 				access.setPixDepth(storedDepth, x, y);
457 			}
458 		}
459 	}
460 
461 	return image;
462 }
463 
464 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags)465 void InvertedDepthRangesTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags)
466 {
467 	VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
468 	{
469 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
470 		DE_NULL,																// const void*						pNext;
471 		renderingFlags,															// VkRenderingFlagsKHR				flags;
472 		0u,																		// uint32_t							viewMask;
473 		1u,																		// uint32_t							colorAttachmentCount;
474 		&m_colorAttachmentFormat,												// const VkFormat*					pColorAttachmentFormats;
475 		m_depthAttachmentFormat,												// VkFormat							depthAttachmentFormat;
476 		VK_FORMAT_UNDEFINED,													// VkFormat							stencilAttachmentFormat;
477 		VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits			rasterizationSamples;
478 	};
479 	const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
480 
481 	VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
482 	if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
483 		usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
484 
485 	const VkCommandBufferBeginInfo commandBufBeginParams
486 	{
487 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
488 		DE_NULL,																// const void*						pNext;
489 		usageFlags,																// VkCommandBufferUsageFlags		flags;
490 		&bufferInheritanceInfo
491 	};
492 
493 	const DeviceInterface& vk = m_context.getDeviceInterface();
494 	VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
495 }
496 
beginRender(VkCommandBuffer cmdBuffer,const VkClearValue & clearColor,const VkClearValue & clearDepth,VkRenderingFlagsKHR renderingFlags)497 void InvertedDepthRangesTestInstance::beginRender(VkCommandBuffer cmdBuffer, const VkClearValue& clearColor, const VkClearValue& clearDepth, VkRenderingFlagsKHR renderingFlags)
498 {
499 	const DeviceInterface& vk = m_context.getDeviceInterface();
500 
501 	beginRendering(vk, cmdBuffer, *m_colorTargetView, *m_depthTargetView, false, makeRect2D(kImageExtent), clearColor, clearDepth,
502 				   VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ATTACHMENT_LOAD_OP_LOAD, renderingFlags);
503 }
504 #endif // CTS_USES_VULKANSC
505 
506 
iterate(void)507 tcu::TestStatus InvertedDepthRangesTestInstance::iterate (void)
508 {
509 	// Set up the viewport and draw
510 
511 	const VkViewport viewport
512 	{
513 		0.0f,										// float    x;
514 		0.0f,										// float    y;
515 		static_cast<float>(kImageExtent.width),		// float    width;
516 		static_cast<float>(kImageExtent.height),	// float    height;
517 		m_params.minDepth,							// float    minDepth;
518 		m_params.maxDepth,							// float    maxDepth;
519 	};
520 
521 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
522 	const VkDevice					device				= m_context.getDevice();
523 	const VkQueue					queue				= m_context.getUniversalQueue();
524 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
525 	auto&							alloc				= m_context.getDefaultAllocator();
526 	const VkClearValue				clearColor			= makeClearValueColor(kClearColor);
527 	const VkClearValue				clearDepth			= makeClearValueDepthStencil(kClearDepth, 0u);
528 
529 	// Command buffer
530 
531 	const CmdPoolCreateInfo			cmdPoolCreateInfo	(queueFamilyIndex);
532 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo));
533 	const Unique<VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
534 	Move<VkCommandBuffer>			secCmdBuffer;
535 
536 #ifndef CTS_USES_VULKANSC
537 	if (m_params.groupParams->useSecondaryCmdBuffer)
538 	{
539 		secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
540 
541 		// record secondary command buffer
542 		if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
543 		{
544 			beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
545 			beginRender(*secCmdBuffer, clearColor, clearDepth);
546 		}
547 		else
548 			beginSecondaryCmdBuffer(*secCmdBuffer);
549 
550 		draw(*secCmdBuffer, viewport);
551 
552 		if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
553 			endRendering(vk, *secCmdBuffer);
554 
555 		endCommandBuffer(vk, *secCmdBuffer);
556 
557 		// record primary command buffer
558 		beginCommandBuffer(vk, *cmdBuffer, 0u);
559 
560 		preRenderCommands(*cmdBuffer, clearColor, clearDepth);
561 
562 		if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
563 			beginRender(*cmdBuffer, clearColor, clearDepth, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
564 
565 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
566 
567 		if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
568 			endRendering(vk, *cmdBuffer);
569 
570 		endCommandBuffer(vk, *cmdBuffer);
571 	}
572 	else if (m_params.groupParams->useDynamicRendering)
573 	{
574 		beginCommandBuffer(vk, *cmdBuffer);
575 
576 		preRenderCommands(*cmdBuffer, clearColor, clearDepth);
577 		beginRender(*cmdBuffer, clearColor, clearDepth);
578 		draw(*cmdBuffer, viewport);
579 		endRendering(vk, *cmdBuffer);
580 
581 		endCommandBuffer(vk, *cmdBuffer);
582 	}
583 #endif // CTS_USES_VULKANSC
584 
585 	if (!m_params.groupParams->useDynamicRendering)
586 	{
587 		beginCommandBuffer(vk, *cmdBuffer);
588 
589 		preRenderCommands(*cmdBuffer, clearColor, clearDepth);
590 		beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(kImageExtent));
591 		draw(*cmdBuffer, viewport);
592 		endRenderPass(vk, *cmdBuffer);
593 
594 		endCommandBuffer(vk, *cmdBuffer);
595 	}
596 
597 	// Submit
598 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
599 
600 	// Get result
601 	const auto		zeroOffset	= makeOffset3D(0, 0, 0);
602 	const auto		iWidth		= static_cast<int>(kImageExtent.width);
603 	const auto		iHeight		= static_cast<int>(kImageExtent.height);
604 	const auto		colorPixels	= m_colorTargetImage->readSurface(queue, alloc, VK_IMAGE_LAYOUT_GENERAL, zeroOffset, iWidth, iHeight, VK_IMAGE_ASPECT_COLOR_BIT);
605 	const auto		depthPixels	= m_depthTargetImage->readSurface(queue, alloc, VK_IMAGE_LAYOUT_GENERAL, zeroOffset, iWidth, iHeight, VK_IMAGE_ASPECT_DEPTH_BIT);
606 	ColorAndDepth	results		(colorPixels, depthPixels);
607 
608 	auto&			resultImage	= results.first;
609 	auto&			resultDepth	= results.second;
610 
611 	// Verify results
612 	auto&	log				= m_context.getTestContext().getLog();
613 	auto	referenceImage	= generateReferenceImage(ReferenceImageType::COLOR);
614 	auto	referenceDepth	= generateReferenceImage(ReferenceImageType::DEPTH);
615 
616 	bool fail = false;
617 	// Color aspect.
618 	if (!tcu::fuzzyCompare(log, "Image compare", "Image compare", referenceImage->getAccess(), resultImage, 0.02f, tcu::COMPARE_LOG_RESULT))
619 		fail = true;
620 
621 	// Depth aspect.
622 	bool depthFail = false;
623 
624 	const auto refWidth			= referenceDepth->getWidth();
625 	const auto refHeight		= referenceDepth->getHeight();
626 	const auto refAccess		= referenceDepth->getAccess();
627 
628 	tcu::TextureLevel errorMask	(mapVkFormat(VK_FORMAT_R8G8B8_UNORM), refWidth, refHeight);
629 	auto errorAccess			= errorMask.getAccess();
630 	const tcu::Vec4 kGreen		(0.0f, 1.0f, 0.0f, 1.0f);
631 	const tcu::Vec4 kRed		(1.0f, 0.0f, 0.0f, 1.0f);
632 
633 	tcu::clear(errorAccess, kGreen);
634 
635 	for (int y = 0; y < refHeight; ++y)
636 	for (int x = 0; x < refWidth; ++x)
637 	{
638 		// Ignore pixels that could be too close to having or not having coverage.
639 		const auto stencil = refAccess.getPixStencil(x, y);
640 		if (stencil == kMaskedStencil)
641 			continue;
642 
643 		// Compare the rest using a known threshold.
644 		const auto refValue = refAccess.getPixDepth(x, y);
645 		const auto resValue = resultDepth.getPixDepth(x, y);
646 		if (!de::inRange(resValue, refValue - kDepthThreshold, refValue + kDepthThreshold))
647 		{
648 			depthFail = true;
649 			errorAccess.setPixel(kRed, x, y);
650 		}
651 	}
652 
653 	if (depthFail)
654 	{
655 		log << tcu::TestLog::Message << "Depth Image comparison failed" << tcu::TestLog::EndMessage;
656 		log	<< tcu::TestLog::Image("Result", "Result", resultDepth)
657 			<< tcu::TestLog::Image("Reference",	"Reference", refAccess)
658 			<< tcu::TestLog::Image("ErrorMask",	"Error mask", errorAccess);
659 	}
660 
661 	if (fail || depthFail)
662 		return tcu::TestStatus::fail("Result images are incorrect");
663 
664 	return tcu::TestStatus::pass("Pass");
665 }
666 
667 class InvertedDepthRangesTest : public TestCase
668 {
669 public:
InvertedDepthRangesTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)670 	InvertedDepthRangesTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
671 		: TestCase	(testCtx, name, description)
672 		, m_params	(params)
673 	{
674 	}
675 
initPrograms(SourceCollections & programCollection) const676 	void initPrograms (SourceCollections& programCollection) const
677 	{
678 		// Vertex shader
679 		{
680 			std::ostringstream src;
681 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
682 				<< "\n"
683 				<< "layout(location = 0) in highp vec4 in_position;\n"
684 				<< "\n"
685 				<< "out gl_PerVertex {\n"
686 				<< "    highp vec4 gl_Position;\n"
687 				<< "};\n"
688 				<< "\n"
689 				<< "void main(void)\n"
690 				<< "{\n"
691 				<< "    gl_Position = in_position;\n"
692 				<< "}\n";
693 
694 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
695 		}
696 
697 		// Fragment shader
698 		{
699 			std::ostringstream src;
700 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
701 				<< "\n"
702 				<< "layout(location = 0) out highp vec4 out_color;\n"
703 				<< "\n"
704 				<< "void main(void)\n"
705 				<< "{\n"
706 				<< "    out_color = vec4(gl_FragCoord.z, " << kVertexColor.y() << ", " << kVertexColor.z() << ", " << kVertexColor.w() << ");\n"
707 				<< "}\n";
708 
709 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
710 		}
711 	}
712 
checkSupport(Context & context) const713 	virtual void checkSupport (Context& context) const
714 	{
715 		if (m_params.depthClampEnable)
716 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_CLAMP);
717 
718 		if (m_params.depthBiasEnable && m_params.depthBiasClamp != 0.0f)
719 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_BIAS_CLAMP);
720 
721 		if (m_params.minDepth > 1.0f || m_params.minDepth < 0.0f || m_params.maxDepth > 1.0f || m_params.maxDepth < 0.0f)
722 			context.requireDeviceFunctionality("VK_EXT_depth_range_unrestricted");
723 
724 		if (m_params.groupParams->useDynamicRendering)
725 			context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
726 	}
727 
createInstance(Context & context) const728 	virtual TestInstance* createInstance (Context& context) const
729 	{
730 		return new InvertedDepthRangesTestInstance(context, m_params);
731 	}
732 
733 private:
734 	const TestParams	m_params;
735 };
736 
populateTestGroup(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)737 void populateTestGroup (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
738 {
739 	const struct
740 	{
741 		std::string		name;
742 		VkBool32		depthClamp;
743 	} depthClamp[] =
744 	{
745 		{ "depthclamp",		VK_TRUE		},
746 		{ "nodepthclamp",	VK_FALSE	},
747 	};
748 
749 	const struct
750 	{
751 		std::string		name;
752 		float			delta;
753 		VkBool32		depthBiasEnable;
754 		float			depthBiasClamp;
755 	} depthParams[] =
756 	{
757 		{ "deltazero",					0.0f,		DE_FALSE,	 0.0f },
758 		{ "deltasmall",					0.3f,		DE_FALSE,	 0.0f },
759 		{ "deltaone",					1.0f,		DE_FALSE,	 0.0f },
760 
761 		// depthBiasClamp must be smaller then maximum depth slope to make a difference
762 		{ "deltaone_bias_clamp_neg",	1.0f,		DE_TRUE,	-0.003f },
763 		{ "deltasmall_bias_clamp_pos",	0.3f,		DE_TRUE,	 0.003f },
764 
765 		// Range > 1.0 requires VK_EXT_depth_range_unrestricted extension
766 		{ "depth_range_unrestricted",	2.7f,		DE_FALSE,	 0.0f },
767 	};
768 
769 	for (int ndxDepthClamp = 0; ndxDepthClamp < DE_LENGTH_OF_ARRAY(depthClamp); ++ndxDepthClamp)
770 	for (int ndxParams = 0; ndxParams < DE_LENGTH_OF_ARRAY(depthParams); ++ndxParams)
771 	{
772 		const auto& cDepthClamp		= depthClamp[ndxDepthClamp];
773 		const auto& cDepthParams	= depthParams[ndxParams];
774 		const float minDepth		= 0.5f + cDepthParams.delta / 2.0f;
775 		const float maxDepth		 = minDepth - cDepthParams.delta;
776 		DE_ASSERT(minDepth >= maxDepth);
777 
778 		const TestParams params
779 		{
780 			minDepth,
781 			maxDepth,
782 			cDepthClamp.depthClamp,
783 			cDepthParams.depthBiasEnable,
784 			cDepthParams.depthBiasClamp,
785 			groupParams
786 		};
787 
788 		std::string name = cDepthClamp.name + "_" + cDepthParams.name;
789 		testGroup->addChild(new InvertedDepthRangesTest(testGroup->getTestContext(), name, "", params));
790 	}
791 }
792 
793 }	// anonymous
794 
createInvertedDepthRangesTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)795 tcu::TestCaseGroup*	createInvertedDepthRangesTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
796 {
797 	return createTestGroup(testCtx, "inverted_depth_ranges", "Inverted depth ranges", populateTestGroup, groupParams);
798 }
799 
800 }	// Draw
801 }	// vkt
802