1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2019 Valve Corporation.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief VK_EXT_depth_range_unrestricted Tests
25 *//*--------------------------------------------------------------------*/
26
27 #include "vktPipelineDepthRangeUnrestrictedTests.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineClearUtil.hpp"
30 #include "vktPipelineImageUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestCaseUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "tcuTestLog.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuCommandLine.hpp"
47
48 #include <sstream>
49 #include <vector>
50
51 namespace vkt
52 {
53 namespace pipeline
54 {
55
56 using namespace vk;
57
58 namespace
59 {
60
61 enum testDynamicStaticMode
62 {
63 TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC = 0,
64 TEST_MODE_VIEWPORT_DYNAMIC = 1,
65 TEST_MODE_DEPTH_BOUNDS_DYNAMIC = 2,
66 TEST_MODE_VIEWPORT_DEPTH_BOUNDS_DYNAMIC = 3,
67 };
68
69 struct DepthRangeUnrestrictedParam
70 {
71 PipelineConstructionType pipelineConstructionType;
72 VkFormat depthFormat;
73 VkBool32 testClearValueOnly;
74 VkClearValue depthBufferClearValue;
75 VkBool32 depthClampEnable;
76 float wc; // Component W of the vertices
77 uint32_t viewportDepthBoundsMode;
78 float viewportMinDepth;
79 float viewportMaxDepth;
80 VkBool32 depthBoundsTestEnable;
81 float minDepthBounds;
82 float maxDepthBounds;
83 VkCompareOp depthCompareOp;
84 };
85
86 // helper functions
getFormatCaseName(vk::VkFormat format)87 std::string getFormatCaseName(vk::VkFormat format)
88 {
89 return de::toLower(de::toString(getFormatStr(format)).substr(10));
90 }
91
getCompareOpStringName(VkCompareOp compare)92 std::string getCompareOpStringName(VkCompareOp compare)
93 {
94 return de::toLower(de::toString(getCompareOpStr(compare)).substr(3));
95 }
96
generateTestName(struct DepthRangeUnrestrictedParam param)97 const std::string generateTestName(struct DepthRangeUnrestrictedParam param)
98 {
99 std::ostringstream result;
100
101 result << getFormatCaseName(param.depthFormat).c_str();
102 result << "_" << getCompareOpStringName(param.depthCompareOp).c_str();
103 result << "_clear_value_" << (int)param.depthBufferClearValue.depthStencil.depth;
104
105 if (param.depthClampEnable == VK_FALSE)
106 result << "_wc_" << (int)param.wc;
107
108 if (param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC)
109 result << "_dynamic";
110 result << "_viewport_min_" << (int)param.viewportMinDepth << "_max_" << (int)param.viewportMaxDepth;
111
112 if (param.depthBoundsTestEnable)
113 {
114 if (param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC)
115 result << "_dynamic";
116 result << "_boundstest_min" << (int)param.minDepthBounds << "_max_" << (int)param.maxDepthBounds;
117 }
118
119 return result.str();
120 }
121
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)122 bool isSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, VkPhysicalDevice device, VkFormat format)
123 {
124 VkFormatProperties formatProps;
125
126 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
127
128 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0u;
129 }
130
isFloatingPointDepthFormat(VkFormat format)131 bool isFloatingPointDepthFormat(VkFormat format)
132 {
133 switch (format)
134 {
135 case VK_FORMAT_D32_SFLOAT:
136 case VK_FORMAT_D32_SFLOAT_S8_UINT:
137 return true;
138 case VK_FORMAT_D24_UNORM_S8_UINT:
139 case VK_FORMAT_D16_UNORM_S8_UINT:
140 case VK_FORMAT_D16_UNORM:
141 return false;
142 default:
143 DE_FATAL("No depth format");
144 }
145 return false;
146 }
147
depthFormatHasStencilComponent(VkFormat format)148 bool depthFormatHasStencilComponent(VkFormat format)
149 {
150 switch (format)
151 {
152 case VK_FORMAT_D32_SFLOAT_S8_UINT:
153 case VK_FORMAT_D24_UNORM_S8_UINT:
154 case VK_FORMAT_D16_UNORM_S8_UINT:
155 return true;
156 case VK_FORMAT_D32_SFLOAT:
157 case VK_FORMAT_D16_UNORM:
158 return false;
159 default:
160 DE_FATAL("No depth format");
161 }
162 return false;
163 }
164
compareDepthResult(VkCompareOp compare,float depth,float clearValue)165 bool compareDepthResult(VkCompareOp compare, float depth, float clearValue)
166 {
167 bool result = false;
168
169 DE_ASSERT(compare <= VK_COMPARE_OP_ALWAYS && compare >= VK_COMPARE_OP_NEVER);
170
171 switch (compare)
172 {
173 case VK_COMPARE_OP_ALWAYS:
174 result = true;
175 break;
176 case VK_COMPARE_OP_NEVER:
177 result = false;
178 break;
179 case VK_COMPARE_OP_EQUAL:
180 result = depth == clearValue;
181 break;
182 case VK_COMPARE_OP_NOT_EQUAL:
183 result = depth != clearValue;
184 break;
185 case VK_COMPARE_OP_GREATER:
186 result = depth > clearValue;
187 break;
188 case VK_COMPARE_OP_GREATER_OR_EQUAL:
189 result = depth >= clearValue;
190 break;
191 case VK_COMPARE_OP_LESS:
192 result = depth < clearValue;
193 break;
194 case VK_COMPARE_OP_LESS_OR_EQUAL:
195 result = depth <= clearValue;
196 break;
197 default:
198 result = false;
199 break;
200 }
201 return result;
202 }
203
createPoints(float wc)204 static inline std::vector<Vertex4RGBA> createPoints(float wc)
205 {
206 using tcu::Vec2;
207 using tcu::Vec4;
208
209 std::vector<Vertex4RGBA> vertices;
210
211 // Vertices are in the following positions of the image:
212 //
213 // ----------------------------------
214 // | |
215 // | |
216 // | 5 6 |
217 // | |
218 // | 1 2 |
219 // | |
220 // | |
221 // | 3 0 |
222 // | |
223 // | 7 4 |
224 // | |
225 // | |
226 // ----------------------------------
227 //
228 // Vertex Depth Color
229 // 0 0.0 white
230 // 1 0.25 magenta
231 // 2 -2.0 yellow
232 // 3 2.0 red
233 // 4 -5.0 black
234 // 5 5.0 cyan
235 // 6 10.0 blue
236 // 7 -10.0 green
237 // Depth values are constant, they don't depend on wc.
238 const Vertex4RGBA vertex0 = {Vec4(0.25f * wc, 0.25f * wc, 0.0f, wc), Vec4(1.0f, 1.0f, 1.0f, 1.0)};
239 const Vertex4RGBA vertex1 = {Vec4(-0.25f * wc, -0.25f * wc, 0.25f, wc), Vec4(1.0f, 0.0f, 1.0f, 1.0)};
240 const Vertex4RGBA vertex2 = {Vec4(0.25f * wc, -0.25f * wc, -2.0f, wc), Vec4(1.0f, 1.0f, 0.0f, 1.0)};
241 const Vertex4RGBA vertex3 = {Vec4(-0.25f * wc, 0.25f * wc, 2.0f, wc), Vec4(1.0f, 0.0f, 0.0f, 1.0)};
242 const Vertex4RGBA vertex4 = {Vec4(0.5f * wc, 0.5f * wc, -5.0f, wc), Vec4(0.0f, 0.0f, 0.0f, 1.0)};
243 const Vertex4RGBA vertex5 = {Vec4(-0.5f * wc, -0.5f * wc, 5.0f, wc), Vec4(0.0f, 1.0f, 1.0f, 1.0)};
244 const Vertex4RGBA vertex6 = {Vec4(0.5f * wc, -0.5f * wc, 10.0f, wc), Vec4(0.0f, 0.0f, 1.0f, 1.0)};
245
246 const Vertex4RGBA vertex7 = {Vec4(-0.5f * wc, 0.5f * wc, -10.0f, wc), Vec4(0.0f, 1.0f, 0.0f, 1.0)};
247
248 vertices.push_back(vertex0);
249 vertices.push_back(vertex1);
250 vertices.push_back(vertex2);
251 vertices.push_back(vertex3);
252 vertices.push_back(vertex4);
253 vertices.push_back(vertex5);
254 vertices.push_back(vertex6);
255 vertices.push_back(vertex7);
256
257 return vertices;
258 }
259
260 template <class Test>
newTestCase(tcu::TestContext & testContext,const DepthRangeUnrestrictedParam testParam)261 vkt::TestCase *newTestCase(tcu::TestContext &testContext, const DepthRangeUnrestrictedParam testParam)
262 {
263 return new Test(testContext, generateTestName(testParam).c_str(), testParam);
264 }
265
createBufferAndBindMemory(Context & context,VkDeviceSize size,VkBufferUsageFlags usage,de::MovePtr<Allocation> * pAlloc)266 Move<VkBuffer> createBufferAndBindMemory(Context &context, VkDeviceSize size, VkBufferUsageFlags usage,
267 de::MovePtr<Allocation> *pAlloc)
268 {
269 const DeviceInterface &vk = context.getDeviceInterface();
270 const VkDevice vkDevice = context.getDevice();
271 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
272
273 const VkBufferCreateInfo vertexBufferParams = {
274 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
275 DE_NULL, // const void* pNext;
276 0u, // VkBufferCreateFlags flags;
277 size, // VkDeviceSize size;
278 usage, // VkBufferUsageFlags usage;
279 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
280 1u, // uint32_t queueFamilyCount;
281 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
282 };
283
284 Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
285
286 *pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer),
287 MemoryRequirement::HostVisible);
288 VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
289
290 return vertexBuffer;
291 }
292
createImage2DAndBindMemory(Context & context,VkFormat format,uint32_t width,uint32_t height,VkImageUsageFlags usage,VkSampleCountFlagBits sampleCount,de::details::MovePtr<Allocation> * pAlloc)293 Move<VkImage> createImage2DAndBindMemory(Context &context, VkFormat format, uint32_t width, uint32_t height,
294 VkImageUsageFlags usage, VkSampleCountFlagBits sampleCount,
295 de::details::MovePtr<Allocation> *pAlloc)
296 {
297 const DeviceInterface &vk = context.getDeviceInterface();
298 const VkDevice vkDevice = context.getDevice();
299 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
300
301 const VkImageCreateInfo colorImageParams = {
302 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
303 DE_NULL, // const void* pNext;
304 0u, // VkImageCreateFlags flags;
305 VK_IMAGE_TYPE_2D, // VkImageType imageType;
306 format, // VkFormat format;
307 {width, height, 1u}, // VkExtent3D extent;
308 1u, // uint32_t mipLevels;
309 1u, // uint32_t arraySize;
310 sampleCount, // uint32_t samples;
311 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
312 usage, // VkImageUsageFlags usage;
313 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
314 1u, // uint32_t queueFamilyCount;
315 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
316 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
317 };
318
319 Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams);
320
321 *pAlloc = context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image),
322 MemoryRequirement::Any);
323 VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
324
325 return image;
326 }
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const PipelineConstructionType pipelineConstructionType,const VkFormat colorFormat,const VkFormat depthStencilFormat,const VkAttachmentLoadOp loadOperationColor,const VkAttachmentLoadOp loadOperationDepthStencil)327 RenderPassWrapper makeRenderPass(const DeviceInterface &vk, const VkDevice device,
328 const PipelineConstructionType pipelineConstructionType, const VkFormat colorFormat,
329 const VkFormat depthStencilFormat, const VkAttachmentLoadOp loadOperationColor,
330 const VkAttachmentLoadOp loadOperationDepthStencil)
331 {
332 const bool hasColor = colorFormat != VK_FORMAT_UNDEFINED;
333 const bool hasDepthStencil = depthStencilFormat != VK_FORMAT_UNDEFINED;
334 const VkImageLayout initialLayoutColor = loadOperationColor == VK_ATTACHMENT_LOAD_OP_LOAD ?
335 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL :
336 VK_IMAGE_LAYOUT_UNDEFINED;
337 const VkImageLayout initialLayoutDepthStencil = loadOperationDepthStencil == VK_ATTACHMENT_LOAD_OP_LOAD ?
338 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
339 VK_IMAGE_LAYOUT_UNDEFINED;
340
341 const VkAttachmentDescription colorAttachmentDescription = {
342 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
343 colorFormat, // VkFormat format
344 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
345 loadOperationColor, // VkAttachmentLoadOp loadOp
346 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
347 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
348 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
349 initialLayoutColor, // VkImageLayout initialLayout
350 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
351 };
352
353 const VkAttachmentDescription depthStencilAttachmentDescription = {
354 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
355 depthStencilFormat, // VkFormat format
356 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
357 loadOperationDepthStencil, // VkAttachmentLoadOp loadOp
358 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
359 loadOperationDepthStencil, // VkAttachmentLoadOp stencilLoadOp
360 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
361 initialLayoutDepthStencil, // VkImageLayout initialLayout
362 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
363 };
364
365 std::vector<VkAttachmentDescription> attachmentDescriptions;
366
367 if (hasColor)
368 attachmentDescriptions.push_back(colorAttachmentDescription);
369 if (hasDepthStencil)
370 attachmentDescriptions.push_back(depthStencilAttachmentDescription);
371
372 const VkAttachmentReference colorAttachmentRef = {
373 0u, // uint32_t attachment
374 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
375 };
376
377 const VkAttachmentReference depthStencilAttachmentRef = {
378 hasColor ? 1u : 0u, // uint32_t attachment
379 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout
380 };
381
382 const VkSubpassDescription subpassDescription = {
383 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
384 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
385 0u, // uint32_t inputAttachmentCount
386 DE_NULL, // const VkAttachmentReference* pInputAttachments
387 hasColor ? 1u : 0u, // uint32_t colorAttachmentCount
388 hasColor ? &colorAttachmentRef : DE_NULL, // const VkAttachmentReference* pColorAttachments
389 DE_NULL, // const VkAttachmentReference* pResolveAttachments
390 hasDepthStencil ? &depthStencilAttachmentRef :
391 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
392 0u, // uint32_t preserveAttachmentCount
393 DE_NULL // const uint32_t* pPreserveAttachments
394 };
395
396 const VkRenderPassCreateInfo renderPassInfo = {
397 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
398 DE_NULL, // const void* pNext
399 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
400 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount
401 attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] :
402 DE_NULL, // const VkAttachmentDescription* pAttachments
403 1u, // uint32_t subpassCount
404 &subpassDescription, // const VkSubpassDescription* pSubpasses
405 0u, // uint32_t dependencyCount
406 DE_NULL // const VkSubpassDependency* pDependencies
407 };
408
409 return RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo);
410 }
411
412 // Test Classes
413 class DepthRangeUnrestrictedTestInstance : public vkt::TestInstance
414 {
415 public:
416 DepthRangeUnrestrictedTestInstance(Context &context, const DepthRangeUnrestrictedParam param);
417 virtual ~DepthRangeUnrestrictedTestInstance(void);
418 virtual tcu::TestStatus iterate(void);
419
420 protected:
421 void prepareRenderPass(RenderPassWrapper &renderPass, GraphicsPipelineWrapper &pipeline);
422 void prepareCommandBuffer(void);
423 void preparePipelineWrapper(GraphicsPipelineWrapper &gpw, VkRenderPass renderpass);
424 tcu::TestStatus verifyTestResult(void);
425
426 protected:
427 const DepthRangeUnrestrictedParam m_param;
428 bool m_extensions;
429 const tcu::UVec2 m_renderSize;
430 const VkFormat m_colorFormat;
431 PipelineLayoutWrapper m_pipelineLayout;
432
433 Move<VkImage> m_depthImage;
434 de::MovePtr<Allocation> m_depthImageAlloc;
435 de::MovePtr<Allocation> m_colorImageAlloc;
436 Move<VkImageView> m_depthAttachmentView;
437 VkImageMemoryBarrier m_imageLayoutBarriers[2];
438
439 Move<VkBuffer> m_vertexBuffer;
440 de::MovePtr<Allocation> m_vertexBufferMemory;
441 std::vector<Vertex4RGBA> m_vertices;
442
443 RenderPassWrapper m_renderPass;
444 Move<VkCommandPool> m_cmdPool;
445 Move<VkCommandBuffer> m_cmdBuffer;
446 Move<VkImage> m_colorImage;
447 Move<VkImageView> m_colorAttachmentView;
448 GraphicsPipelineWrapper m_pipeline;
449
450 ShaderWrapper m_vertModule;
451 ShaderWrapper m_fragModule;
452 };
453
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,VkRenderPass renderpass)454 void DepthRangeUnrestrictedTestInstance::preparePipelineWrapper(GraphicsPipelineWrapper &gpw, VkRenderPass renderpass)
455 {
456 // Create pipeline
457 const VkVertexInputBindingDescription vertexInputBindingDescription{
458 0u, // uint32_t binding;
459 sizeof(Vertex4RGBA), // uint32_t strideInBytes;
460 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
461 };
462
463 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]{
464 {
465 0u, // uint32_t location;
466 0u, // uint32_t binding;
467 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
468 0u // uint32_t offsetInBytes;
469 },
470 {
471 1u, // uint32_t location;
472 0u, // uint32_t binding;
473 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
474 offsetof(Vertex4RGBA, color), // uint32_t offsetInBytes;
475 }};
476
477 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
478 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
479 DE_NULL, // const void* pNext;
480 0u, // VkPipelineVertexInputStateCreateFlags flags;
481 1u, // uint32_t vertexBindingDescriptionCount;
482 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
483 2u, // uint32_t vertexAttributeDescriptionCount;
484 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
485 };
486
487 const std::vector<VkRect2D> scissor{makeRect2D(m_renderSize)};
488 std::vector<VkViewport> viewport{makeViewport(m_renderSize)};
489
490 if (!(m_param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC))
491 {
492 viewport[0].minDepth = m_param.viewportMinDepth;
493 viewport[0].maxDepth = m_param.viewportMaxDepth;
494 }
495
496 const VkPipelineRasterizationStateCreateInfo rasterStateParams{
497 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
498 DE_NULL, // const void* pNext;
499 0u, // VkPipelineRasterizationStateCreateFlags flags;
500 m_param.depthClampEnable, // VkBool32 depthClampEnable;
501 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
502 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
503 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
504 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
505 VK_FALSE, // VkBool32 depthBiasEnable;
506 0.0f, // float depthBiasConstantFactor;
507 0.0f, // float depthBiasClamp;
508 0.0f, // float depthBiasSlopeFactor;
509 1.0f, // float lineWidth;
510 };
511
512 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
513 VK_FALSE, // VkBool32 blendEnable;
514 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
515 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
516 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
517 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
518 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
519 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
520 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
521 VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask;
522 };
523
524 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
525 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
526 DE_NULL, // const void* pNext;
527 0u, // VkPipelineColorBlendStateCreateFlags flags;
528 VK_FALSE, // VkBool32 logicOpEnable;
529 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
530 1u, // uint32_t attachmentCount;
531 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
532 {0.0f, 0.0f, 0.0f, 0.0f}, // float blendConst[4];
533 };
534
535 float minDepthBounds = m_param.minDepthBounds;
536 float maxDepthBounds = m_param.maxDepthBounds;
537
538 if (m_param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC)
539 {
540 minDepthBounds = 0.0f;
541 maxDepthBounds = 1.0f;
542 }
543
544 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = {
545 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
546 DE_NULL, // const void* pNext;
547 0u, // VkPipelineDepthStencilStateCreateFlags flags;
548 VK_TRUE, // VkBool32 depthTestEnable;
549 VK_TRUE, // VkBool32 depthWriteEnable;
550 m_param.depthCompareOp, // VkCompareOp depthCompareOp;
551 m_param.depthBoundsTestEnable, // VkBool32 depthBoundsTestEnable;
552 VK_FALSE, // VkBool32 stencilTestEnable;
553 // VkStencilOpState front;
554 {
555 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
556 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
557 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
558 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
559 0u, // uint32_t compareMask;
560 0u, // uint32_t writeMask;
561 0u, // uint32_t reference;
562 },
563 // VkStencilOpState back;
564 {
565 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
566 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
567 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
568 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
569 0u, // uint32_t compareMask;
570 0u, // uint32_t writeMask;
571 0u, // uint32_t reference;
572 },
573 minDepthBounds, // float minDepthBounds;
574 maxDepthBounds, // float maxDepthBounds;
575 };
576
577 std::vector<VkDynamicState> dynamicStates;
578 if (m_param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC)
579 dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
580 if (m_param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC)
581 dynamicStates.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
582
583 const VkPipelineDynamicStateCreateInfo dynamicStateParams = {
584 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
585 DE_NULL, // const void* pNext;
586 (VkPipelineDynamicStateCreateFlags)0u, // VkPipelineDynamicStateCreateFlags flags;
587 (uint32_t)dynamicStates.size(), // uint32_t dynamicStateCount;
588 (const VkDynamicState *)dynamicStates.data() // const VkDynamicState* pDynamicStates;
589 };
590
591 gpw.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
592 .setDefaultMultisampleState()
593 .setDynamicState(&dynamicStateParams)
594 .setupVertexInputState(&vertexInputStateParams)
595 .setupPreRasterizationShaderState(viewport, scissor, m_pipelineLayout, renderpass, 0u, m_vertModule,
596 &rasterStateParams)
597 .setupFragmentShaderState(m_pipelineLayout, renderpass, 0u, m_fragModule, &depthStencilStateParams)
598 .setupFragmentOutputState(renderpass, 0u, &colorBlendStateParams)
599 .setMonolithicPipelineLayout(m_pipelineLayout)
600 .buildPipeline();
601 }
602
prepareRenderPass(RenderPassWrapper & renderPass,GraphicsPipelineWrapper & pipeline)603 void DepthRangeUnrestrictedTestInstance::prepareRenderPass(RenderPassWrapper &renderPass,
604 GraphicsPipelineWrapper &pipeline)
605 {
606 const DeviceInterface &vk = m_context.getDeviceInterface();
607
608 const VkClearValue attachmentClearValues[2] = {
609 defaultClearValue(m_colorFormat),
610 m_param.depthBufferClearValue,
611 };
612
613 renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u, attachmentClearValues);
614
615 pipeline.bind(*m_cmdBuffer);
616 VkDeviceSize offsets = 0u;
617 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
618
619 if (m_param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC)
620 {
621 VkViewport viewport = makeViewport(m_renderSize);
622 viewport.minDepth = m_param.viewportMinDepth;
623 viewport.maxDepth = m_param.viewportMaxDepth;
624 if (vk::isConstructionTypeShaderObject(m_param.pipelineConstructionType))
625 {
626 #ifndef CTS_USES_VULKANSC
627 vk.cmdSetViewportWithCount(*m_cmdBuffer, 1u, &viewport);
628 #else
629 vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1u, &viewport);
630 #endif
631 }
632 else
633 {
634 vk.cmdSetViewport(*m_cmdBuffer, 0u, 1u, &viewport);
635 }
636 }
637
638 if (m_param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC)
639 vk.cmdSetDepthBounds(*m_cmdBuffer, m_param.minDepthBounds, m_param.maxDepthBounds);
640
641 if (!m_vertices.empty() && !m_param.testClearValueOnly)
642 vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1u, 0u, 0u);
643
644 renderPass.end(vk, *m_cmdBuffer);
645 }
646
prepareCommandBuffer(void)647 void DepthRangeUnrestrictedTestInstance::prepareCommandBuffer(void)
648 {
649 const DeviceInterface &vk = m_context.getDeviceInterface();
650
651 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
652
653 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
654 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
655 (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers),
656 m_imageLayoutBarriers);
657
658 prepareRenderPass(m_renderPass, m_pipeline);
659
660 endCommandBuffer(vk, *m_cmdBuffer);
661 }
662
DepthRangeUnrestrictedTestInstance(Context & context,const DepthRangeUnrestrictedParam param)663 DepthRangeUnrestrictedTestInstance::DepthRangeUnrestrictedTestInstance(Context &context,
664 const DepthRangeUnrestrictedParam param)
665 : TestInstance(context)
666 , m_param(param)
667 , m_extensions(m_context.requireDeviceFunctionality("VK_EXT_depth_range_unrestricted"))
668 , m_renderSize(tcu::UVec2(32, 32))
669 , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
670 , m_pipeline(m_context.getInstanceInterface(), m_context.getDeviceInterface(), m_context.getPhysicalDevice(),
671 m_context.getDevice(), m_context.getDeviceExtensions(), param.pipelineConstructionType)
672 {
673 const DeviceInterface &vk = m_context.getDeviceInterface();
674 const VkDevice vkDevice = m_context.getDevice();
675 const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
676
677 if (!isSupportedDepthStencilFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(),
678 param.depthFormat))
679 {
680 throw tcu::NotSupportedError("Unsupported depth format");
681 }
682
683 VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
684 if (param.depthClampEnable && features.depthClamp == false)
685 {
686 throw tcu::NotSupportedError("Unsupported feature: depthClamp");
687 }
688
689 if (param.depthBoundsTestEnable && features.depthBounds == false)
690 {
691 throw tcu::NotSupportedError("Unsupported feature: depthBounds");
692 }
693
694 // Create vertex buffer
695 {
696 m_vertexBuffer =
697 createBufferAndBindMemory(m_context, 1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
698 m_vertices = createPoints(m_param.wc);
699 // Load vertices into vertex buffer
700 deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
701 flushAlloc(vk, vkDevice, *m_vertexBufferMemory);
702 }
703
704 // Create render pass
705 m_renderPass = makeRenderPass(vk, vkDevice, m_param.pipelineConstructionType, m_colorFormat, m_param.depthFormat,
706 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR);
707
708 const VkComponentMapping ComponentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
709 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
710 // Create color image
711 {
712 m_colorImage = createImage2DAndBindMemory(m_context, m_colorFormat, m_renderSize.x(), m_renderSize.y(),
713 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
714 VK_SAMPLE_COUNT_1_BIT, &m_colorImageAlloc);
715 }
716
717 // Create depth image
718 {
719 m_depthImage =
720 createImage2DAndBindMemory(m_context, m_param.depthFormat, m_renderSize.x(), m_renderSize.y(),
721 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
722 VK_SAMPLE_COUNT_1_BIT, &m_depthImageAlloc);
723 }
724
725 uint32_t depthAspectBits = VK_IMAGE_ASPECT_DEPTH_BIT;
726 if (depthFormatHasStencilComponent(param.depthFormat))
727 depthAspectBits |= VK_IMAGE_ASPECT_STENCIL_BIT;
728
729 // Set up image layout transition barriers
730 {
731 VkImageMemoryBarrier colorImageBarrier = {
732 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
733 DE_NULL, // const void* pNext;
734 0u, // VkAccessFlags srcAccessMask;
735 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
736 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
737 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
738 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
739 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
740 *m_colorImage, // VkImage image;
741 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
742 };
743
744 m_imageLayoutBarriers[0] = colorImageBarrier;
745
746 VkImageMemoryBarrier depthImageBarrier = {
747 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
748 DE_NULL, // const void* pNext;
749 0u, // VkAccessFlags srcAccessMask;
750 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
751 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
752 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
753 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
754 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex;
755 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex;
756 *m_depthImage, // VkImage image;
757 {depthAspectBits, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
758 };
759
760 m_imageLayoutBarriers[1] = depthImageBarrier;
761 }
762 // Create color attachment view
763 {
764 VkImageViewCreateInfo colorAttachmentViewParams = {
765 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
766 DE_NULL, // const void* pNext;
767 0u, // VkImageViewCreateFlags flags;
768 *m_colorImage, // VkImage image;
769 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
770 m_colorFormat, // VkFormat format;
771 ComponentMappingRGBA, // VkComponentMapping components;
772 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
773 };
774
775 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
776 }
777
778 // Create depth attachment view
779 {
780 const VkImageViewCreateInfo depthAttachmentViewParams = {
781 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
782 DE_NULL, // const void* pNext;
783 0u, // VkImageViewCreateFlags flags;
784 *m_depthImage, // VkImage image;
785 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
786 m_param.depthFormat, // VkFormat format;
787 ComponentMappingRGBA, // VkComponentMapping components;
788 {depthAspectBits, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
789 };
790
791 m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
792 }
793
794 // Create framebuffer
795 {
796 std::vector<VkImage> images = {
797 *m_colorImage,
798 *m_depthImage,
799 };
800 VkImageView attachmentBindInfos[2] = {
801 *m_colorAttachmentView,
802 *m_depthAttachmentView,
803 };
804
805 const VkFramebufferCreateInfo framebufferParams = {
806 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
807 DE_NULL, // const void* pNext;
808 0u, // VkFramebufferCreateFlags flags;
809 *m_renderPass, // VkRenderPass renderPass;
810 2u, // uint32_t attachmentCount;
811 attachmentBindInfos, // const VkImageView* pAttachments;
812 (uint32_t)m_renderSize.x(), // uint32_t width;
813 (uint32_t)m_renderSize.y(), // uint32_t height;
814 1u, // uint32_t layers;
815 };
816
817 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
818 }
819
820 // Create shader modules
821 m_vertModule = ShaderWrapper(vk, vkDevice, context.getBinaryCollection().get("vert"), 0);
822 m_fragModule = ShaderWrapper(vk, vkDevice, context.getBinaryCollection().get("frag"), 0);
823
824 // Create pipeline layout
825 {
826 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
827 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
828 DE_NULL, // const void* pNext;
829 0u, // VkPipelineLayoutCreateFlags flags;
830 0u, // uint32_t setLayoutCount;
831 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
832 0u, // uint32_t pushConstantRangeCount;
833 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
834 };
835
836 m_pipelineLayout = PipelineLayoutWrapper(m_param.pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
837 }
838
839 // Create pipeline
840 preparePipelineWrapper(m_pipeline, *m_renderPass);
841
842 // Create command pool
843 m_cmdPool = createCommandPool(
844 vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
845 queueFamilyIndex);
846
847 // Create command buffer
848 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
849 }
850
~DepthRangeUnrestrictedTestInstance(void)851 DepthRangeUnrestrictedTestInstance::~DepthRangeUnrestrictedTestInstance(void)
852 {
853 }
854
iterate(void)855 tcu::TestStatus DepthRangeUnrestrictedTestInstance::iterate(void)
856 {
857 const DeviceInterface &vk = m_context.getDeviceInterface();
858 const VkDevice vkDevice = m_context.getDevice();
859 const VkQueue queue = m_context.getUniversalQueue();
860
861 prepareCommandBuffer();
862
863 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
864 return verifyTestResult();
865 }
866
verifyTestResult(void)867 tcu::TestStatus DepthRangeUnrestrictedTestInstance::verifyTestResult(void)
868 {
869 bool compareOk = true;
870 const DeviceInterface &vk = m_context.getDeviceInterface();
871 const VkDevice vkDevice = m_context.getDevice();
872 const VkQueue queue = m_context.getUniversalQueue();
873 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
874 tcu::TestLog &log = m_context.getTestContext().getLog();
875 Allocator &allocator = m_context.getDefaultAllocator();
876 tcu::TextureLevel refImage(vk::mapVkFormat(m_colorFormat), 32, 32);
877 float clearValue = m_param.depthBufferClearValue.depthStencil.depth;
878 double epsilon = 1e-5;
879
880 // For non-float depth formats, the value in the depth buffer is already clampled to the range [0, 1], which
881 // includes the clear depth value.
882 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
883 clearValue = de::min(de::max(clearValue, 0.0f), 1.0f);
884
885 // Generate reference image
886 {
887 VkClearValue clearColor = defaultClearValue(m_colorFormat);
888 tcu::Vec4 clearColorVec4(clearColor.color.float32[0], clearColor.color.float32[1], clearColor.color.float32[2],
889 clearColor.color.float32[3]);
890
891 tcu::clear(refImage.getAccess(), clearColorVec4);
892 for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex)
893 {
894 if (m_param.depthClampEnable == VK_FALSE &&
895 (vertex->position.z() < 0.0f || vertex->position.z() > vertex->position.w()))
896 continue;
897
898 if (m_param.testClearValueOnly)
899 continue;
900
901 // Depth Clamp is enabled, then we clamp point depth to viewport's maxDepth and minDepth values, or [0.0f, 1.0f] is depth format is fixed-point.
902 float scaling = ((vertex->position.z() / vertex->position.w()) *
903 (m_param.viewportMaxDepth - m_param.viewportMinDepth)) +
904 m_param.viewportMinDepth;
905 float depth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth);
906
907 // For non-float depth formats, depth value is clampled to the range [0, 1].
908 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
909 depth = de::min(de::max(depth, 0.0f), 1.0f);
910
911 if (compareDepthResult(m_param.depthCompareOp, depth, clearValue))
912 {
913 int32_t x = static_cast<int32_t>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) *
914 static_cast<float>(m_renderSize.x() - 1));
915 int32_t y = static_cast<int32_t>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) *
916 static_cast<float>(m_renderSize.y() - 1));
917 refImage.getAccess().setPixel(vertex->color, x, y);
918 }
919 }
920 }
921
922 // Check the rendered image
923 {
924 de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(
925 vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
926
927 compareOk = tcu::intThresholdPositionDeviationCompare(
928 m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refImage.getAccess(),
929 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
930 #ifdef CTS_USES_VULKANSC
931 if (m_context.getTestContext().getCommandLine().isSubProcess())
932 #endif // CTS_USES_VULKANSC
933 {
934 if (!compareOk)
935 return tcu::TestStatus::fail("Image mismatch");
936 }
937 }
938
939 // Check depth buffer contents
940 {
941 de::MovePtr<tcu::TextureLevel> depthResult = readDepthAttachment(
942 vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_param.depthFormat, m_renderSize);
943
944 if (m_param.testClearValueOnly)
945 {
946 compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "DepthImagecompare",
947 "Depth image comparison", tcu::Vec4(clearValue, 0.0f, 0.0f, 1.0f),
948 depthResult->getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
949 tcu::COMPARE_LOG_RESULT);
950 if (!compareOk)
951 return tcu::TestStatus::fail("Depth buffer mismatch");
952 else
953 return tcu::TestStatus::pass("Result images matches references");
954 }
955
956 log << tcu::TestLog::Message;
957 for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex)
958 {
959 int32_t x = static_cast<int32_t>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) *
960 static_cast<float>(m_renderSize.x() - 1));
961 int32_t y = static_cast<int32_t>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) *
962 static_cast<float>(m_renderSize.y() - 1));
963 tcu::Vec4 depth = depthResult->getAccess().getPixel(x, y);
964
965 // Check depth values are valid
966 if (depth.y() != 0.0f || depth.z() != 0.0f || depth.w() != 1.0f)
967 {
968 log << tcu::TestLog::Message << "Invalid depth buffer values for pixel (" << x << ", " << y << ") = ("
969 << depth.x() << ", " << depth.y() << ", " << depth.z() << ", " << depth.w() << "."
970 << tcu::TestLog::EndMessage;
971 compareOk = false;
972 }
973
974 // Check the case where depth clamping is disabled.
975 if (m_param.depthClampEnable == VK_FALSE)
976 {
977 if ((vertex->position.z() < 0.0f || vertex->position.z() > vertex->position.w()) &&
978 fabs(clearValue - depth.x()) > epsilon)
979 {
980 log << tcu::TestLog::Message << "Error pixel (" << x << ", " << y << "). Depth value = " << depth
981 << ", expected " << clearValue << "." << tcu::TestLog::EndMessage;
982 compareOk = false;
983 }
984
985 float expectedDepth = clearValue;
986
987 if (vertex->position.z() <= vertex->position.w() && vertex->position.z() >= 0.0f)
988 {
989 // Assert we have a symmetric range around zero.
990 DE_ASSERT(m_param.viewportMinDepth == (-m_param.viewportMaxDepth));
991
992 // Calculate the expected depth value: first translate the value to from [0.0f, 1.0f] to [-1.0f, 1.0f].
993 expectedDepth = 2 * (vertex->position.z() / vertex->position.w()) - 1.0f;
994 // Now multiply by m_param.viewportMaxDepth to get the expected value.
995 expectedDepth *= m_param.viewportMaxDepth;
996 }
997
998 // For non-float depth formats, depth value is clampled to the range [0, 1].
999 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
1000 expectedDepth = de::min(de::max(expectedDepth, 0.0f), 1.0f);
1001
1002 expectedDepth =
1003 compareDepthResult(m_param.depthCompareOp, expectedDepth, clearValue) ? expectedDepth : clearValue;
1004
1005 if (fabs(expectedDepth - depth.x()) > epsilon)
1006 {
1007 log << tcu::TestLog::Message << "Error pixel (" << x << ", " << y << "). Depth value " << depth.x()
1008 << ", expected " << expectedDepth << ", error " << fabs(expectedDepth - depth.x())
1009 << tcu::TestLog::EndMessage;
1010 compareOk = false;
1011 }
1012
1013 continue;
1014 }
1015
1016 // Depth Clamp is enabled, then we clamp point depth to viewport's maxDepth and minDepth values, or 0.0f and 1.0f is format is not float.
1017 float scaling =
1018 (vertex->position.z() / vertex->position.w()) * (m_param.viewportMaxDepth - m_param.viewportMinDepth) +
1019 m_param.viewportMinDepth;
1020 float expectedDepth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth);
1021
1022 // For non-float depth formats, depth value is clampled to the range [0, 1].
1023 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
1024 expectedDepth = de::min(de::max(expectedDepth, 0.0f), 1.0f);
1025
1026 expectedDepth =
1027 compareDepthResult(m_param.depthCompareOp, expectedDepth, clearValue) ? expectedDepth : clearValue;
1028
1029 if (fabs(expectedDepth - depth.x()) > epsilon)
1030 {
1031 log << tcu::TestLog::Message << "Error pixel (" << x << ", " << y << "). Depth value " << depth.x()
1032 << ", expected " << expectedDepth << ", error " << fabs(expectedDepth - depth.x())
1033 << tcu::TestLog::EndMessage;
1034 compareOk = false;
1035 }
1036 }
1037 if (!compareOk)
1038 return tcu::TestStatus::fail("Depth buffer mismatch");
1039 }
1040
1041 return tcu::TestStatus::pass("Result images matches references");
1042 }
1043
1044 // Test Classes
1045 class DepthBoundsRangeUnrestrictedTestInstance : public DepthRangeUnrestrictedTestInstance
1046 {
1047 public:
1048 DepthBoundsRangeUnrestrictedTestInstance(Context &context, const DepthRangeUnrestrictedParam param);
1049 virtual ~DepthBoundsRangeUnrestrictedTestInstance(void);
1050 virtual tcu::TestStatus iterate(void);
1051
1052 protected:
1053 tcu::TestStatus verifyTestResult(bool firstDraw);
1054 void prepareCommandBuffer(bool firstDraw);
1055
1056 protected:
1057 RenderPassWrapper m_renderPassSecondDraw;
1058 GraphicsPipelineWrapper m_pipelineSecondDraw;
1059 std::vector<bool> m_vertexWasRendered;
1060 };
1061
DepthBoundsRangeUnrestrictedTestInstance(Context & context,const DepthRangeUnrestrictedParam param)1062 DepthBoundsRangeUnrestrictedTestInstance::DepthBoundsRangeUnrestrictedTestInstance(
1063 Context &context, const DepthRangeUnrestrictedParam param)
1064 : DepthRangeUnrestrictedTestInstance(context, param)
1065 , m_pipelineSecondDraw(m_context.getInstanceInterface(), m_context.getDeviceInterface(),
1066 m_context.getPhysicalDevice(), m_context.getDevice(), m_context.getDeviceExtensions(),
1067 param.pipelineConstructionType)
1068 {
1069 const DeviceInterface &vk = m_context.getDeviceInterface();
1070 const VkDevice vkDevice = m_context.getDevice();
1071
1072 // Create render pass for second draw, we keep the first draw's contents of the depth buffer.
1073 m_renderPassSecondDraw =
1074 makeRenderPass(vk, vkDevice, param.pipelineConstructionType, m_colorFormat, m_param.depthFormat,
1075 VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_LOAD);
1076
1077 // Create framebuffer for second draw.
1078 {
1079 std::vector<VkImage> images = {
1080 *m_colorImage,
1081 *m_depthImage,
1082 };
1083 VkImageView attachmentBindInfos[2] = {
1084 *m_colorAttachmentView,
1085 *m_depthAttachmentView,
1086 };
1087
1088 const VkFramebufferCreateInfo framebufferParams = {
1089 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1090 DE_NULL, // const void* pNext;
1091 0u, // VkFramebufferCreateFlags flags;
1092 *m_renderPassSecondDraw, // VkRenderPass renderPass;
1093 2u, // uint32_t attachmentCount;
1094 attachmentBindInfos, // const VkImageView* pAttachments;
1095 (uint32_t)m_renderSize.x(), // uint32_t width;
1096 (uint32_t)m_renderSize.y(), // uint32_t height;
1097 1u, // uint32_t layers;
1098 };
1099
1100 m_renderPassSecondDraw.createFramebuffer(vk, vkDevice, &framebufferParams, images);
1101 }
1102
1103 // Create pipeline
1104 preparePipelineWrapper(m_pipelineSecondDraw, *m_renderPassSecondDraw);
1105 }
1106
~DepthBoundsRangeUnrestrictedTestInstance(void)1107 DepthBoundsRangeUnrestrictedTestInstance::~DepthBoundsRangeUnrestrictedTestInstance(void)
1108 {
1109 }
1110
iterate(void)1111 tcu::TestStatus DepthBoundsRangeUnrestrictedTestInstance::iterate(void)
1112 {
1113 const DeviceInterface &vk = m_context.getDeviceInterface();
1114 const VkDevice vkDevice = m_context.getDevice();
1115 const VkQueue queue = m_context.getUniversalQueue();
1116
1117 // This test will draw the same scene two times.
1118 // First one will render the points depending on if the pass the depth test and if clear depth value passes the
1119 // depthBounds test.
1120 //
1121 // The second one, will render the same scene but the the point positions will have depth buffer values from
1122 // the first draw. If they pass the depth test, the depthBounds test will check the content of the depth buffer,
1123 // which is most cases, will make that the second result differs from the first one, hence the need to split
1124 // the verification in two steps.
1125 prepareCommandBuffer(true);
1126 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1127 tcu::TestStatus status = verifyTestResult(true);
1128
1129 #ifdef CTS_USES_VULKANSC
1130 if (m_context.getTestContext().getCommandLine().isSubProcess())
1131 #endif // CTS_USES_VULKANSC
1132 {
1133 if (status.getCode() != QP_TEST_RESULT_PASS)
1134 return status;
1135 }
1136
1137 prepareCommandBuffer(false);
1138 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1139 return verifyTestResult(false);
1140 }
1141
prepareCommandBuffer(bool firstDraw)1142 void DepthBoundsRangeUnrestrictedTestInstance::prepareCommandBuffer(bool firstDraw)
1143 {
1144 const DeviceInterface &vk = m_context.getDeviceInterface();
1145
1146 if (!firstDraw)
1147 {
1148 VK_CHECK(vk.resetCommandBuffer(*m_cmdBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT));
1149 // Color image layout changed after verifying the first draw call, restore it.
1150 m_imageLayoutBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1151 m_imageLayoutBarriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1152 // Depth image layout changed after verifying the first draw call, restore it.
1153 m_imageLayoutBarriers[1].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1154 m_imageLayoutBarriers[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1155 }
1156
1157 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1158
1159 vk.cmdPipelineBarrier(*m_cmdBuffer,
1160 (firstDraw ? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT : VK_PIPELINE_STAGE_TRANSFER_BIT),
1161 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1162 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1163 (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers),
1164 m_imageLayoutBarriers);
1165
1166 prepareRenderPass((firstDraw ? m_renderPass : m_renderPassSecondDraw),
1167 (firstDraw ? m_pipeline : m_pipelineSecondDraw));
1168
1169 endCommandBuffer(vk, *m_cmdBuffer);
1170 }
1171
verifyTestResult(bool firstDraw)1172 tcu::TestStatus DepthBoundsRangeUnrestrictedTestInstance::verifyTestResult(bool firstDraw)
1173 {
1174 bool compareOk = true;
1175 const DeviceInterface &vk = m_context.getDeviceInterface();
1176 const VkDevice vkDevice = m_context.getDevice();
1177 const VkQueue queue = m_context.getUniversalQueue();
1178 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1179 tcu::TestLog &log = m_context.getTestContext().getLog();
1180 Allocator &allocator = m_context.getDefaultAllocator();
1181 tcu::TextureLevel refImage(vk::mapVkFormat(m_colorFormat), 32, 32);
1182 float clearValue = m_param.depthBufferClearValue.depthStencil.depth;
1183 double epsilon = 1e-5;
1184
1185 // For non-float depth formats, depth value is clampled to the range [0, 1].
1186 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
1187 clearValue = de::min(de::max(clearValue, 0.0f), 1.0f);
1188
1189 // Generate reference image
1190 {
1191 VkClearValue clearColor = defaultClearValue(m_colorFormat);
1192 tcu::Vec4 clearColorVec4(clearColor.color.float32[0], clearColor.color.float32[1], clearColor.color.float32[2],
1193 clearColor.color.float32[3]);
1194 tcu::clear(refImage.getAccess(), clearColorVec4);
1195 for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex)
1196 {
1197 // Depth Clamp is enabled, then we clamp point depth to viewport's maxDepth and minDepth values and later check if it is inside depthBounds volume.
1198 float scaling = ((vertex->position.z() / vertex->position.w()) *
1199 (m_param.viewportMaxDepth - m_param.viewportMinDepth)) +
1200 m_param.viewportMinDepth;
1201 float depth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth);
1202 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
1203 depth = de::min(de::max(depth, 0.0f), 1.0f);
1204
1205 auto i = vertex - m_vertices.begin();
1206
1207 // Depending if the first draw call succeed, we need to know if the second draw call will render the points because the depth buffer content
1208 // will determine if it passes the depth test and the depth bounds test.
1209 bool firstDrawHasPassedDepthBoundsTest = !firstDraw && m_vertexWasRendered[i];
1210 float depthBufferValue = firstDrawHasPassedDepthBoundsTest ? depth : clearValue;
1211
1212 // For non-float depth formats, depth value is clampled to the range [0, 1].
1213 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
1214 depthBufferValue = de::min(de::max(depthBufferValue, 0.0f), 1.0f);
1215
1216 // Check that the point passes the depth test and the depth bounds test.
1217 if (compareDepthResult(m_param.depthCompareOp, depth, depthBufferValue) &&
1218 depthBufferValue >= m_param.minDepthBounds && depthBufferValue <= m_param.maxDepthBounds)
1219 {
1220 int32_t x = static_cast<int32_t>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) *
1221 static_cast<float>(m_renderSize.x() - 1));
1222 int32_t y = static_cast<int32_t>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) *
1223 static_cast<float>(m_renderSize.y() - 1));
1224 refImage.getAccess().setPixel(vertex->color, x, y);
1225 if (firstDraw)
1226 m_vertexWasRendered.push_back(true);
1227 continue;
1228 }
1229
1230 if (firstDraw)
1231 m_vertexWasRendered.push_back(false);
1232 }
1233 }
1234
1235 // Check the rendered image
1236 {
1237 de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(
1238 vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1239 std::string description = "Image comparison draw ";
1240 description += (firstDraw ? "1" : "2");
1241
1242 compareOk = tcu::intThresholdPositionDeviationCompare(
1243 m_context.getTestContext().getLog(), "IntImageCompare", description.c_str(), refImage.getAccess(),
1244 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
1245 #ifdef CTS_USES_VULKANSC
1246 if (m_context.getTestContext().getCommandLine().isSubProcess())
1247 #endif // CTS_USES_VULKANSC
1248 {
1249 if (!compareOk)
1250 return tcu::TestStatus::fail("Image mismatch");
1251 }
1252 }
1253
1254 // Check depth buffer contents
1255 {
1256 de::MovePtr<tcu::TextureLevel> depthResult = readDepthAttachment(
1257 vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_param.depthFormat, m_renderSize);
1258
1259 log << tcu::TestLog::Message;
1260 for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex)
1261 {
1262 int32_t x = static_cast<int32_t>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) *
1263 static_cast<float>(m_renderSize.x() - 1));
1264 int32_t y = static_cast<int32_t>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) *
1265 static_cast<float>(m_renderSize.y() - 1));
1266 tcu::Vec4 depth = depthResult->getAccess().getPixel(x, y);
1267
1268 // Check depth values are valid
1269 if (depth.y() != 0.0f || depth.z() != 0.0f || depth.w() != 1.0f)
1270 {
1271 log << tcu::TestLog::Message << "Draw " << (firstDraw ? "1" : "2")
1272 << ": Invalid depth buffer values for pixel (" << x << ", " << y << ") = (" << depth.x() << ", "
1273 << depth.y() << ", " << depth.z() << ", " << depth.w() << "." << tcu::TestLog::EndMessage;
1274 compareOk = false;
1275 }
1276
1277 // Depth Clamp is enabled, so we clamp point depth to viewport's maxDepth and minDepth values, or 0.0f and 1.0f is format is not float.
1278 float scaling =
1279 (vertex->position.z() / vertex->position.w()) * (m_param.viewportMaxDepth - m_param.viewportMinDepth) +
1280 m_param.viewportMinDepth;
1281 float expectedDepth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth);
1282
1283 auto i = vertex - m_vertices.begin();
1284
1285 // Depending if the first draw call succeed, we need to know if the second draw call will render the points because the depth buffer content
1286 // will determine if it passes the depth test and the depth bounds test.
1287 bool firstDrawHasPassedDepthBoundsTest = !firstDraw && m_vertexWasRendered[i];
1288
1289 // If we are in the first draw call, the depth buffer content is clearValue. If we are in the second draw call, it is going to be depth.x() if the first
1290 // succeeded.
1291 float depthBufferValue = firstDrawHasPassedDepthBoundsTest ? depth.x() : clearValue;
1292
1293 // For non-float depth formats, depth value is clampled to the range [0, 1].
1294 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
1295 depthBufferValue = de::min(de::max(depthBufferValue, 0.0f), 1.0f);
1296
1297 // Calculate the expectd depth depending on the depth test and the depth bounds test results.
1298 expectedDepth = (compareDepthResult(m_param.depthCompareOp, expectedDepth, depthBufferValue) &&
1299 depthBufferValue <= m_param.maxDepthBounds && depthBufferValue >= m_param.minDepthBounds) ?
1300 expectedDepth :
1301 depthBufferValue;
1302
1303 // For non-float depth formats, depth value is clampled to the range [0, 1].
1304 if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE)
1305 expectedDepth = de::min(de::max(expectedDepth, 0.0f), 1.0f);
1306
1307 if (fabs(expectedDepth - depth.x()) > epsilon)
1308 {
1309 log << tcu::TestLog::Message << "Draw " << (firstDraw ? "1" : "2") << ": Error pixel (" << x << ", "
1310 << y << "). Depth value " << depth.x() << ", expected " << expectedDepth << ", error "
1311 << fabs(expectedDepth - depth.x()) << tcu::TestLog::EndMessage;
1312 compareOk = false;
1313 }
1314 }
1315
1316 if (!compareOk)
1317 return tcu::TestStatus::fail("Depth buffer mismatch");
1318 }
1319
1320 return tcu::TestStatus::pass("Result images matches references");
1321 }
1322
1323 class DepthRangeUnrestrictedTest : public vkt::TestCase
1324 {
1325 public:
DepthRangeUnrestrictedTest(tcu::TestContext & testContext,const std::string & name,const DepthRangeUnrestrictedParam param)1326 DepthRangeUnrestrictedTest(tcu::TestContext &testContext, const std::string &name,
1327 const DepthRangeUnrestrictedParam param)
1328 : vkt::TestCase(testContext, name)
1329 , m_param(param)
1330 {
1331 }
~DepthRangeUnrestrictedTest(void)1332 virtual ~DepthRangeUnrestrictedTest(void)
1333 {
1334 }
1335 virtual void initPrograms(SourceCollections &programCollection) const;
1336 virtual TestInstance *createInstance(Context &context) const;
1337 void checkSupport(Context &context) const;
1338
1339 protected:
1340 const DepthRangeUnrestrictedParam m_param;
1341 };
1342
initPrograms(SourceCollections & programCollection) const1343 void DepthRangeUnrestrictedTest::initPrograms(SourceCollections &programCollection) const
1344 {
1345 programCollection.glslSources.add("vert") << glu::VertexSource("#version 310 es\n"
1346 "layout(location = 0) in vec4 position;\n"
1347 "layout(location = 1) in vec4 color;\n"
1348 "layout(location = 0) out highp vec4 vtxColor;\n"
1349 "void main (void)\n"
1350 "{\n"
1351 " gl_Position = position;\n"
1352 " gl_PointSize = 1.0f;\n"
1353 " vtxColor = color;\n"
1354
1355 "}\n");
1356
1357 programCollection.glslSources.add("frag") << glu::FragmentSource("#version 310 es\n"
1358 "layout(location = 0) in highp vec4 vtxColor;\n"
1359 "layout(location = 0) out highp vec4 fragColor;\n"
1360 "void main (void)\n"
1361 "{\n"
1362 " fragColor = vtxColor;\n"
1363 "}\n");
1364 }
1365
createInstance(Context & context) const1366 TestInstance *DepthRangeUnrestrictedTest::createInstance(Context &context) const
1367 {
1368 if (m_param.depthBoundsTestEnable)
1369 return new DepthBoundsRangeUnrestrictedTestInstance(context, m_param);
1370 return new DepthRangeUnrestrictedTestInstance(context, m_param);
1371 }
1372
checkSupport(Context & context) const1373 void DepthRangeUnrestrictedTest::checkSupport(Context &context) const
1374 {
1375 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1376 m_param.pipelineConstructionType);
1377 }
1378 } // namespace
1379
createDepthRangeUnrestrictedTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1380 tcu::TestCaseGroup *createDepthRangeUnrestrictedTests(tcu::TestContext &testCtx,
1381 PipelineConstructionType pipelineConstructionType)
1382 {
1383 de::MovePtr<tcu::TestCaseGroup> depthTests(new tcu::TestCaseGroup(testCtx, "depth_range_unrestricted"));
1384 const VkFormat depthFormats[] = {
1385 VK_FORMAT_D32_SFLOAT,
1386 VK_FORMAT_D24_UNORM_S8_UINT,
1387 VK_FORMAT_D16_UNORM,
1388 };
1389
1390 const VkCompareOp compareOps[] = {
1391 VK_COMPARE_OP_GREATER,
1392 VK_COMPARE_OP_GREATER_OR_EQUAL,
1393 VK_COMPARE_OP_LESS,
1394 VK_COMPARE_OP_LESS_OR_EQUAL,
1395 };
1396
1397 float viewportValues[] = {2.0f, 6.0f, 12.0f};
1398 float depthBoundsValues[] = {2.0f, 4.0f, 8.0f};
1399 float wcValues[] = {2.0f, 6.0f, 12.0f};
1400 float clearValues[] = {2.0f, -3.0f, 6.0f, -7.0f};
1401
1402 // Depth clear values outside range [0.0f, 1.0f].
1403 {
1404 de::MovePtr<tcu::TestCaseGroup> depthClearValueTests(new tcu::TestCaseGroup(testCtx, "clear_value"));
1405 DepthRangeUnrestrictedParam testParams;
1406 testParams.pipelineConstructionType = pipelineConstructionType;
1407 testParams.testClearValueOnly = VK_TRUE;
1408 testParams.depthClampEnable = VK_FALSE;
1409 testParams.wc = 1.0f;
1410 testParams.viewportMinDepth = 0.0f;
1411 testParams.viewportMaxDepth = 1.0f;
1412 testParams.minDepthBounds = 0.0f;
1413 testParams.maxDepthBounds = 1.0f;
1414 testParams.depthBoundsTestEnable = VK_FALSE;
1415 testParams.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
1416 testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC;
1417
1418 for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format)
1419 {
1420 testParams.depthFormat = depthFormats[format];
1421 testParams.depthBufferClearValue = defaultClearValue(depthFormats[format]);
1422 for (int val = 0; val < DE_LENGTH_OF_ARRAY(clearValues); val++)
1423 {
1424 testParams.depthBufferClearValue.depthStencil.depth = clearValues[val];
1425 depthClearValueTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams));
1426 }
1427 }
1428 depthTests->addChild(depthClearValueTests.release());
1429 }
1430
1431 // Viewport's depth unrestricted range
1432 {
1433 de::MovePtr<tcu::TestCaseGroup> viewportTests(new tcu::TestCaseGroup(testCtx, "viewport"));
1434 DepthRangeUnrestrictedParam testParams;
1435 testParams.pipelineConstructionType = pipelineConstructionType;
1436 testParams.testClearValueOnly = VK_FALSE;
1437 testParams.wc = 1.0f;
1438 testParams.depthClampEnable = VK_TRUE;
1439 testParams.minDepthBounds = 0.0f;
1440 testParams.maxDepthBounds = 1.0f;
1441 testParams.depthBoundsTestEnable = VK_FALSE;
1442
1443 for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format)
1444 {
1445 testParams.depthFormat = depthFormats[format];
1446 testParams.depthBufferClearValue = defaultClearValue(testParams.depthFormat);
1447 for (int compareOp = 0; compareOp < DE_LENGTH_OF_ARRAY(compareOps); compareOp++)
1448 {
1449 testParams.depthCompareOp = compareOps[compareOp];
1450 for (int clearValue = 0; clearValue < DE_LENGTH_OF_ARRAY(clearValues); clearValue++)
1451 {
1452 testParams.depthBufferClearValue.depthStencil.depth = clearValues[clearValue];
1453 for (int viewportValue = 0; viewportValue < DE_LENGTH_OF_ARRAY(viewportValues); viewportValue++)
1454 {
1455 testParams.viewportMinDepth = -viewportValues[viewportValue];
1456 testParams.viewportMaxDepth = viewportValues[viewportValue];
1457 testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC;
1458 viewportTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams));
1459 testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DYNAMIC;
1460 viewportTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams));
1461 }
1462 }
1463 }
1464 }
1465
1466 depthTests->addChild(viewportTests.release());
1467 }
1468
1469 // DepthBounds's depth unrestricted range
1470 {
1471 de::MovePtr<tcu::TestCaseGroup> depthBoundsTests(new tcu::TestCaseGroup(testCtx, "depthbounds"));
1472 DepthRangeUnrestrictedParam testParams;
1473 testParams.pipelineConstructionType = pipelineConstructionType;
1474 testParams.testClearValueOnly = VK_FALSE;
1475 testParams.wc = 1.0f;
1476 testParams.depthClampEnable = VK_TRUE;
1477 testParams.depthBoundsTestEnable = VK_TRUE;
1478
1479 for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format)
1480 {
1481 testParams.depthFormat = depthFormats[format];
1482 testParams.depthBufferClearValue = defaultClearValue(testParams.depthFormat);
1483 for (int compareOp = 0; compareOp < DE_LENGTH_OF_ARRAY(compareOps); compareOp++)
1484 {
1485 testParams.depthCompareOp = compareOps[compareOp];
1486 for (int clearValue = 0; clearValue < DE_LENGTH_OF_ARRAY(clearValues); clearValue++)
1487 {
1488 testParams.depthBufferClearValue.depthStencil.depth = clearValues[clearValue];
1489 for (int viewportValue = 0; viewportValue < DE_LENGTH_OF_ARRAY(viewportValues); viewportValue++)
1490 {
1491 testParams.viewportMinDepth = -viewportValues[viewportValue];
1492 testParams.viewportMaxDepth = viewportValues[viewportValue];
1493 for (int depthValue = 0; depthValue < DE_LENGTH_OF_ARRAY(depthBoundsValues); depthValue++)
1494 {
1495 testParams.minDepthBounds = -depthBoundsValues[depthValue];
1496 testParams.maxDepthBounds = depthBoundsValues[depthValue];
1497
1498 testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC;
1499 depthBoundsTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams));
1500 testParams.viewportDepthBoundsMode = TEST_MODE_DEPTH_BOUNDS_DYNAMIC;
1501 depthBoundsTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams));
1502 testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_DYNAMIC;
1503 depthBoundsTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams));
1504 }
1505 }
1506 }
1507 }
1508 }
1509
1510 depthTests->addChild(depthBoundsTests.release());
1511 }
1512
1513 // Depth clamping disabled
1514 {
1515 de::MovePtr<tcu::TestCaseGroup> noDepthClampingTests(new tcu::TestCaseGroup(testCtx, "depthclampingdisabled"));
1516 DepthRangeUnrestrictedParam testParams;
1517 testParams.pipelineConstructionType = pipelineConstructionType;
1518 testParams.testClearValueOnly = VK_FALSE;
1519 testParams.depthClampEnable = VK_FALSE;
1520 testParams.minDepthBounds = 0.0f;
1521 testParams.maxDepthBounds = 1.0f;
1522 testParams.depthBoundsTestEnable = VK_FALSE;
1523 testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC;
1524
1525 for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format)
1526 {
1527 testParams.depthFormat = depthFormats[format];
1528 testParams.depthBufferClearValue = defaultClearValue(testParams.depthFormat);
1529 for (int compareOp = 0; compareOp < DE_LENGTH_OF_ARRAY(compareOps); compareOp++)
1530 {
1531 testParams.depthCompareOp = compareOps[compareOp];
1532 for (int clearValue = 0; clearValue < DE_LENGTH_OF_ARRAY(clearValues); clearValue++)
1533 {
1534 testParams.depthBufferClearValue.depthStencil.depth = clearValues[clearValue];
1535 for (int viewportValue = 0; viewportValue < DE_LENGTH_OF_ARRAY(viewportValues); viewportValue++)
1536 {
1537 testParams.viewportMinDepth = -viewportValues[viewportValue];
1538 testParams.viewportMaxDepth = viewportValues[viewportValue];
1539 for (int wc = 0; wc < DE_LENGTH_OF_ARRAY(wcValues); wc++)
1540 {
1541 testParams.wc = wcValues[wc];
1542 noDepthClampingTests->addChild(
1543 newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams));
1544 }
1545 }
1546 }
1547 }
1548 }
1549
1550 depthTests->addChild(noDepthClampingTests.release());
1551 }
1552
1553 return depthTests.release();
1554 }
1555
1556 } // namespace pipeline
1557
1558 } // namespace vkt
1559