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