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