xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/draw/vktDrawDepthClampTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2017 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Depth clamp tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vkDefs.hpp"
26 #include "vktDrawDepthClampTests.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawCreateInfoUtil.hpp"
30 #include "vktDrawBufferObjectUtil.hpp"
31 #include "vktDrawImageObjectUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuTestLog.hpp"
41 
42 #include <cmath>
43 #include <limits>
44 #include "deMath.h"
45 
46 namespace vkt
47 {
48 namespace Draw
49 {
50 namespace
51 {
52 using namespace vk;
53 using namespace de;
54 using std::string;
55 using tcu::Vec4;
56 
57 static const int WIDTH  = 256;
58 static const int HEIGHT = 256;
59 
60 struct ViewportData
61 {
62     float minDepth;
63     float maxDepth;
64     float depthValue;
65     float expectedValue;
66 };
67 
68 struct TestParams
69 {
70     string testNameSuffix;
71     std::vector<ViewportData> viewportData;
72     bool enableDepthBias;
73     float depthBiasConstantFactor;
74     bool skipUNorm;
75     bool skipSNorm;
76     std::vector<const char *> requiredExtensions;
77 };
78 
79 const VkFormat depthStencilImageFormatsToTest[] = {VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32,
80                                                    VK_FORMAT_D32_SFLOAT,        VK_FORMAT_D16_UNORM_S8_UINT,
81                                                    VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
82 const float depthEpsilonValuesByFormat[]        = {
83     1e-5f, std::numeric_limits<float>::epsilon(), std::numeric_limits<float>::epsilon(),
84     1e-5f, std::numeric_limits<float>::epsilon(), std::numeric_limits<float>::epsilon()};
85 
86 const float initialClearDepth             = 0.5f;
87 const TestParams depthClearValuesToTest[] = {
88     {
89         "", // testNameSuffix
90         {{
91             // viewportData
92             0.0f, //   minDepth
93             1.0f, //   maxDepth
94             0.3f, //   depthValue
95             0.3f, //   expectedValue
96         }},
97         false, // enableDepthBias
98         0.0f,  // depthBiasConstantFactor
99         false, // skipUNorm
100         false, // skipSNorm
101         {},    // requiredExtensions
102     },
103     {
104         "_clamp_input_negative", // testNameSuffix
105         {{
106             // viewportData
107             0.0f,  //   minDepth
108             1.0f,  //   maxDepth
109             -1e6f, //   depthValue
110             0.0f,  //   expectedValue
111         }},
112         false, // enableDepthBias
113         0.0f,  // depthBiasConstantFactor
114         false, // skipUNorm
115         false, // skipSNorm
116         {},    // requiredExtensions
117     },
118     {
119         "_clamp_input_positive", // testNameSuffix
120         {{
121             // viewportData
122             0.0f,  //   minDepth
123             1.0f,  //   maxDepth
124             1.e6f, //   depthValue
125             1.0f,  //   expectedValue
126         }},
127         false, // enableDepthBias
128         0.0f,  // depthBiasConstantFactor
129         false, // skipUNorm
130         false, // skipSNorm
131         {},    // requiredExtensions
132     },
133     {
134         "_depth_bias_clamp_input_negative", // testNameSuffix
135         {{
136             // viewportData
137             0.0f, //   minDepth
138             1.0f, //   maxDepth
139             0.3f, //   depthValue
140             0.0f, //   expectedValue
141         }},
142         true,   // enableDepthBias
143         -2e11f, // depthBiasConstantFactor
144         false,  // skipUNorm
145         false,  // skipSNorm
146         {},     // requiredExtensions
147     },
148     {
149         "_depth_bias_clamp_input_positive", // testNameSuffix
150         {{
151             // viewportData
152             0.0f, //   minDepth
153             1.0f, //   maxDepth
154             0.7f, //   depthValue
155             1.0f, //   expectedValue
156         }},
157         true,  // enableDepthBias
158         2e11f, // depthBiasConstantFactor
159         false, // skipUNorm
160         false, // skipSNorm
161         {},    // requiredExtensions
162     },
163     {
164         "_depth_range_unrestricted_negative", // testNameSuffix
165         {{
166             // viewportData
167             -1.5f, //   minDepth
168             1.0f,  //   maxDepth
169             -1.5f, //   depthValue
170             -1.5f, //   expectedValue
171         }},
172         false, // enableDepthBias
173         0.0f,  // depthBiasConstantFactor
174         true,  // skipUNorm
175         true,  // skipSNorm
176         {
177             "VK_EXT_depth_range_unrestricted" // requiredExtensions[0]
178         },
179     },
180     {
181         "_depth_range_unrestricted_positive", // testNameSuffix
182         {{
183             // viewportData
184             0.0f, //   minDepth
185             1.5f, //   maxDepth
186             1.5f, //   depthValue
187             1.5f, //   expectedValue
188         }},
189         false, // enableDepthBias
190         0.0f,  // depthBiasConstantFactor
191         true,  // skipUNorm
192         true,  // skipSNorm
193         {
194             "VK_EXT_depth_range_unrestricted" // requiredExtensions[0]
195         },
196     },
197     {
198         "_clamp_four_viewports", // testNameSuffix
199         {
200             // viewportData
201             {
202                 0.0f,  //   minDepth
203                 0.5f,  //   maxDepth
204                 0.7f,  //   depthValue
205                 0.35f, //   expectedValue: 0.7 * 0.5 + (1.0 - 0.7) * 0.0) = 0.35
206             },
207             {
208                 0.9f, //   minDepth
209                 1.0f, //   maxDepth
210                 1.0f, //   depthValue
211                 1.0f, //   expectedValue: 1.0 * 1.0 + (1.0 - 1.0) * 0.9 = 1.0
212             },
213             {
214                 0.5f,  //   minDepth
215                 1.0f,  //   maxDepth
216                 0.9f,  //   depthValue
217                 0.95f, //   expectedValue: 0.9 * 1.0 + (1.0 - 0.9) * 0.5 = 0.95
218             },
219             {
220                 0.5f,  //   minDepth
221                 0.9f,  //   maxDepth
222                 0.4f,  //   depthValue
223                 0.66f, //   expectedValue: 0.4 * 0.9 + (1.0 - 0.4) * 0.5 = 0.66
224             },
225         },
226         false, // enableDepthBias
227         0.0f,  // depthBiasConstantFactor
228         true,  // skipUNorm
229         true,  // skipSNorm
230         {},
231     }};
232 
isUnormDepthFormat(VkFormat format)233 bool isUnormDepthFormat(VkFormat format)
234 {
235     switch (format)
236     {
237     case VK_FORMAT_D24_UNORM_S8_UINT:
238     case VK_FORMAT_X8_D24_UNORM_PACK32:
239     case VK_FORMAT_D16_UNORM_S8_UINT:
240         /* Special case for combined depth-stencil-unorm modes for which tcu::getTextureChannelClass()
241            returns TEXTURECHANNELCLASS_LAST */
242         return true;
243     default:
244         return vk::isUnormFormat(format);
245     }
246 }
247 
248 class DepthClampTestInstance : public TestInstance
249 {
250 public:
251     DepthClampTestInstance(Context &context, const TestParams &params, const VkFormat format, const float epsilon,
252                            const SharedGroupParams groupParams);
253     tcu::TestStatus iterate();
254 
255 private:
256     tcu::ConstPixelBufferAccess draw();
257 
258     void preRenderCommands(VkCommandBuffer cmdBuffer, const VkImageAspectFlagBits aspectBits,
259                            const VkClearValue &clearValue) const;
260     void drawCommands(VkCommandBuffer cmdBuffer) const;
261 
262 #ifndef CTS_USES_VULKANSC
263     void beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
264     void beginDynamicRender(VkCommandBuffer cmdBuffer, VkClearValue clearValue,
265                             VkRenderingFlagsKHR renderingFlags = 0u) const;
266 #endif // CTS_USES_VULKANSC
267 
268     const TestParams m_params;
269     const VkFormat m_format;
270     const float m_epsilon;
271     std::vector<VkViewport> m_viewportVect;
272     std::vector<VkRect2D> m_scissorVect;
273     const SharedGroupParams m_groupParams;
274     SharedPtr<Image> m_depthTargetImage;
275     Move<VkImageView> m_depthTargetView;
276     SharedPtr<Buffer> m_vertexBuffer;
277     Move<VkRenderPass> m_renderPass;
278     Move<VkFramebuffer> m_framebuffer;
279     Move<VkPipelineLayout> m_pipelineLayout;
280     Move<VkPipeline> m_pipeline;
281 };
282 
283 static const Vec4 vertices[] = {
284     Vec4(-1.0f, -1.0f, 0.5f, 1.0f), // 0 -- 2
285     Vec4(-1.0f, 1.0f, 0.5f, 1.0f),  // |  / |
286     Vec4(1.0f, -1.0f, 0.5f, 1.0f),  // | /  |
287     Vec4(1.0f, 1.0f, 0.5f, 1.0f)    // 1 -- 3
288 };
289 static const VkPrimitiveTopology verticesTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
290 
DepthClampTestInstance(Context & context,const TestParams & params,const VkFormat format,const float epsilon,const SharedGroupParams groupParams)291 DepthClampTestInstance::DepthClampTestInstance(Context &context, const TestParams &params, const VkFormat format,
292                                                const float epsilon, const SharedGroupParams groupParams)
293     : TestInstance(context)
294     , m_params(params)
295     , m_format(format)
296     , m_epsilon(epsilon)
297     , m_viewportVect(params.viewportData.size(), VkViewport())
298     , m_scissorVect(params.viewportData.size(), VkRect2D())
299     , m_groupParams(groupParams)
300 {
301     const DeviceInterface &vk       = m_context.getDeviceInterface();
302     const VkDevice device           = m_context.getDevice();
303     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
304     const uint32_t viewportCount    = static_cast<uint32_t>(m_params.viewportData.size());
305 
306     // create viewport grid
307     {
308         const uint32_t columnCount = deCeilFloatToInt32(deFloatSqrt(static_cast<float>(viewportCount)));
309         const uint32_t rowCount =
310             deCeilFloatToInt32(static_cast<float>(viewportCount) / static_cast<float>(columnCount));
311         const uint32_t rectWidth  = WIDTH / columnCount;
312         const uint32_t rectHeight = HEIGHT / rowCount;
313 
314         VkOffset2D pos{0, 0};
315 
316         for (uint32_t viewportIndex = 0; viewportIndex < viewportCount; ++viewportIndex)
317         {
318             // move to next row
319             if ((viewportIndex != 0) && (viewportIndex % columnCount == 0))
320             {
321                 pos.x = 0;
322                 pos.y += rectHeight;
323             }
324 
325             m_viewportVect[viewportIndex] = {
326                 static_cast<float>(pos.x),                     // float x;
327                 static_cast<float>(pos.y),                     // float y;
328                 static_cast<float>(rectWidth),                 // float width;
329                 static_cast<float>(rectHeight),                // float height;
330                 m_params.viewportData[viewportIndex].minDepth, // float minDepth;
331                 m_params.viewportData[viewportIndex].maxDepth, // float maxDepth;
332             };
333 
334             m_scissorVect[viewportIndex] = {pos, {rectWidth, rectHeight}};
335 
336             pos.x += rectWidth;
337         }
338     }
339 
340     DescriptorPoolBuilder descriptorPoolBuilder;
341     DescriptorSetLayoutBuilder descriptorSetLayoutBuilder;
342     // Vertex data
343     {
344         const size_t verticesCount  = DE_LENGTH_OF_ARRAY(vertices);
345         const VkDeviceSize dataSize = verticesCount * sizeof(Vec4);
346         m_vertexBuffer =
347             Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
348                                    m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
349 
350         Vec4 testVertices[verticesCount];
351         deMemcpy(testVertices, vertices, dataSize);
352         for (size_t i = 0; i < verticesCount; ++i)
353             testVertices[i][2] = params.viewportData[0].depthValue;
354         deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), testVertices, static_cast<std::size_t>(dataSize));
355         flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(),
356                                m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
357     }
358 
359     const VkImageUsageFlags targetImageUsageFlags =
360         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
361     const ImageCreateInfo targetImageCreateInfo(VK_IMAGE_TYPE_2D, m_format, {WIDTH, HEIGHT, 1u}, 1u, 1u,
362                                                 VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, targetImageUsageFlags);
363     m_depthTargetImage =
364         Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
365 
366     const ImageViewCreateInfo depthTargetViewInfo(m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_format);
367     m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo);
368 
369     // Render pass and framebuffer
370     if (!m_groupParams->useDynamicRendering)
371     {
372         RenderPassCreateInfo renderPassCreateInfo;
373         renderPassCreateInfo.addAttachment(
374             AttachmentDescription(m_format,                                           // format
375                                   VK_SAMPLE_COUNT_1_BIT,                              // samples
376                                   VK_ATTACHMENT_LOAD_OP_LOAD,                         // loadOp
377                                   VK_ATTACHMENT_STORE_OP_STORE,                       // storeOp
378                                   VK_ATTACHMENT_LOAD_OP_DONT_CARE,                    // stencilLoadOp
379                                   VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // stencilStoreOp
380                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,   // initialLayout
381                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout
382         const VkAttachmentReference depthAttachmentReference =
383             makeAttachmentReference(0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
384         renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
385                                                            (VkSubpassDescriptionFlags)0,    // flags
386                                                            0u,                              // inputAttachmentCount
387                                                            DE_NULL,                         // inputAttachments
388                                                            0u,                              // colorAttachmentCount
389                                                            DE_NULL,                         // colorAttachments
390                                                            DE_NULL,                         // resolveAttachments
391                                                            depthAttachmentReference,        // depthStencilAttachment
392                                                            0u,                              // preserveAttachmentCount
393                                                            DE_NULL));                       // preserveAttachments
394         m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
395 
396         const std::vector<VkImageView> depthAttachments{*m_depthTargetView};
397         FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, depthAttachments, WIDTH, HEIGHT, 1);
398         m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
399     }
400 
401     // Vertex input
402     const VkVertexInputBindingDescription vertexInputBindingDescription = {
403         0u,                          // uint32_t             binding;
404         sizeof(Vec4),                // uint32_t             stride;
405         VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate    inputRate;
406     };
407 
408     const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
409         0u,                            // uint32_t    location;
410         0u,                            // uint32_t    binding;
411         VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat    format;
412         0u                             // uint32_t    offset;
413     };
414 
415     const PipelineCreateInfo::VertexInputState vertexInputState =
416         PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 1, &vertexInputAttributeDescription);
417 
418     // Graphics pipeline
419     const Unique<VkShaderModule> vertexModule(
420         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
421     Move<VkShaderModule> geometryModule;
422     const Unique<VkShaderModule> fragmentModule(
423         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
424 
425     if (viewportCount > 1)
426         geometryModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0);
427 
428     const PipelineLayoutCreateInfo pipelineLayoutCreateInfo(0u, DE_NULL, 0u, DE_NULL);
429     m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
430     std::vector<VkDynamicState> dynamicStates{VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
431 
432     PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
433     pipelineCreateInfo.addShader(
434         PipelineCreateInfo::PipelineShaderStage(*vertexModule, "main", VK_SHADER_STAGE_VERTEX_BIT));
435     if (*geometryModule != 0)
436         pipelineCreateInfo.addShader(
437             PipelineCreateInfo::PipelineShaderStage(*geometryModule, "main", VK_SHADER_STAGE_GEOMETRY_BIT));
438     pipelineCreateInfo.addShader(
439         PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
440     pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
441     pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(verticesTopology));
442     pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(viewportCount, m_viewportVect, m_scissorVect));
443     pipelineCreateInfo.addState(
444         PipelineCreateInfo::DepthStencilState(VK_TRUE, VK_TRUE, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE));
445     pipelineCreateInfo.addState(
446         PipelineCreateInfo::RasterizerState(VK_TRUE,                                       // depthClampEnable
447                                             VK_FALSE,                                      // rasterizerDiscardEnable
448                                             VK_POLYGON_MODE_FILL,                          // polygonMode
449                                             VK_CULL_MODE_NONE,                             // cullMode
450                                             VK_FRONT_FACE_CLOCKWISE,                       // frontFace
451                                             m_params.enableDepthBias ? VK_TRUE : VK_FALSE, // depthBiasEnable
452                                             m_params.depthBiasConstantFactor,              // depthBiasConstantFactor
453                                             0.0f,                                          // depthBiasClamp
454                                             0.0f,                                          // depthBiasSlopeFactor
455                                             1.0f));                                        // lineWidth
456     pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
457     pipelineCreateInfo.addState(PipelineCreateInfo::DynamicState(dynamicStates));
458 
459 #ifndef CTS_USES_VULKANSC
460     VkPipelineRenderingCreateInfoKHR renderingCreateInfo{
461         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, DE_NULL, 0u, 0u, DE_NULL, m_format, VK_FORMAT_UNDEFINED};
462 
463     if (m_groupParams->useDynamicRendering)
464         pipelineCreateInfo.pNext = &renderingCreateInfo;
465 #endif // CTS_USES_VULKANSC
466 
467     m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
468 }
469 
draw()470 tcu::ConstPixelBufferAccess DepthClampTestInstance::draw()
471 {
472     const DeviceInterface &vk       = m_context.getDeviceInterface();
473     const VkDevice device           = m_context.getDevice();
474     const VkQueue queue             = m_context.getUniversalQueue();
475     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
476 
477     const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
478     const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, &cmdPoolCreateInfo));
479     const Unique<VkCommandBuffer> cmdBuffer(
480         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
481     Move<VkCommandBuffer> secCmdBuffer;
482     const VkClearValue clearDepth = makeClearValueDepthStencil(initialClearDepth, 0u);
483     const bool isCombinedType =
484         tcu::isCombinedDepthStencilType(mapVkFormat(m_format).type) && m_format != VK_FORMAT_X8_D24_UNORM_PACK32;
485     const VkImageAspectFlagBits aspectBits =
486         (VkImageAspectFlagBits)(isCombinedType ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT :
487                                                  VK_IMAGE_ASPECT_DEPTH_BIT);
488 
489 #ifndef CTS_USES_VULKANSC
490     if (m_groupParams->useSecondaryCmdBuffer)
491     {
492         secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
493 
494         // record secondary command buffer
495         if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
496         {
497             beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
498             beginDynamicRender(*secCmdBuffer, clearDepth);
499         }
500         else
501             beginSecondaryCmdBuffer(*secCmdBuffer);
502 
503         drawCommands(*secCmdBuffer);
504 
505         if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
506             endRendering(vk, *secCmdBuffer);
507 
508         endCommandBuffer(vk, *secCmdBuffer);
509 
510         // record primary command buffer
511         beginCommandBuffer(vk, *cmdBuffer, 0u);
512         preRenderCommands(*cmdBuffer, aspectBits, clearDepth);
513 
514         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
515             beginDynamicRender(*cmdBuffer, clearDepth, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
516 
517         vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
518 
519         if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
520             endRendering(vk, *cmdBuffer);
521     }
522     else if (m_groupParams->useDynamicRendering)
523     {
524         beginCommandBuffer(vk, *cmdBuffer);
525         preRenderCommands(*cmdBuffer, aspectBits, clearDepth);
526         beginDynamicRender(*cmdBuffer, clearDepth);
527         drawCommands(*cmdBuffer);
528         endRendering(vk, *cmdBuffer);
529     }
530 #endif // CTS_USES_VULKANSC
531 
532     if (!m_groupParams->useDynamicRendering)
533     {
534         const VkRect2D renderArea = makeRect2D(0, 0, WIDTH, HEIGHT);
535 
536         beginCommandBuffer(vk, *cmdBuffer);
537         preRenderCommands(*cmdBuffer, aspectBits, clearDepth);
538         beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
539         drawCommands(*cmdBuffer);
540         endRenderPass(vk, *cmdBuffer);
541     }
542 
543     transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), aspectBits,
544                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
545                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
546                       VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
547 
548     endCommandBuffer(vk, *cmdBuffer);
549 
550     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
551 
552     VK_CHECK(vk.queueWaitIdle(queue));
553 
554     return m_depthTargetImage->readDepth(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
555                                          {0, 0, 0}, WIDTH, HEIGHT, VK_IMAGE_ASPECT_DEPTH_BIT);
556 }
557 
preRenderCommands(VkCommandBuffer cmdBuffer,const VkImageAspectFlagBits aspectBits,const VkClearValue & clearValue) const558 void DepthClampTestInstance::preRenderCommands(VkCommandBuffer cmdBuffer, const VkImageAspectFlagBits aspectBits,
559                                                const VkClearValue &clearValue) const
560 {
561     const DeviceInterface &vk = m_context.getDeviceInterface();
562     const bool isCombinedType =
563         tcu::isCombinedDepthStencilType(mapVkFormat(m_format).type) && m_format != VK_FORMAT_X8_D24_UNORM_PACK32;
564 
565     if (isCombinedType)
566         initialTransitionDepthStencil2DImage(vk, cmdBuffer, m_depthTargetImage->object(),
567                                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT,
568                                              VK_PIPELINE_STAGE_TRANSFER_BIT);
569     else
570         initialTransitionDepth2DImage(vk, cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
571                                       VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
572 
573     const ImageSubresourceRange subresourceRange(aspectBits);
574 
575     vk.cmdClearDepthStencilImage(cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
576                                  &clearValue.depthStencil, 1, &subresourceRange);
577 
578     transition2DImage(vk, cmdBuffer, m_depthTargetImage->object(), aspectBits, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
579                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT,
580                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
581                       VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
582 
583     {
584         const VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT,
585                                             VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT};
586         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
587                               0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
588     }
589 }
590 
drawCommands(VkCommandBuffer cmdBuffer) const591 void DepthClampTestInstance::drawCommands(VkCommandBuffer cmdBuffer) const
592 {
593     const DeviceInterface &vk = m_context.getDeviceInterface();
594     const VkDeviceSize offset = 0;
595     const VkBuffer buffer     = m_vertexBuffer->object();
596 
597     // if there is more then one viewport we are also checking
598     // proper behaviour of cmdSetViewport/Scissor - there was
599     // a driver bug that caused invalid behaviour of those
600     // functions when firstViewport/Scissor had a non 0 value
601     uint32_t indexCount = static_cast<uint32_t>(m_viewportVect.size());
602     for (uint32_t index = 0; index < indexCount; ++index)
603     {
604         vk.cmdSetViewport(cmdBuffer, index, 1u, &m_viewportVect[index]);
605         vk.cmdSetScissor(cmdBuffer, index, 1u, &m_scissorVect[index]);
606     }
607 
608     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
609     vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &buffer, &offset);
610     vk.cmdDraw(cmdBuffer, DE_LENGTH_OF_ARRAY(vertices), 1, 0, 0);
611 }
612 
613 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags) const614 void DepthClampTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,
615                                                      VkRenderingFlagsKHR renderingFlags) const
616 {
617     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
618         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
619         DE_NULL,                                                         // const void* pNext;
620         renderingFlags,                                                  // VkRenderingFlagsKHR flags;
621         0u,                                                              // uint32_t viewMask;
622         0u,                                                              // uint32_t colorAttachmentCount;
623         DE_NULL,                                                         // const VkFormat* pColorAttachmentFormats;
624         m_format,                                                        // VkFormat depthAttachmentFormat;
625         VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
626         VK_SAMPLE_COUNT_1_BIT,                                           // VkSampleCountFlagBits rasterizationSamples;
627     };
628 
629     const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
630 
631     VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
632     if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
633         usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
634 
635     const VkCommandBufferBeginInfo commandBufBeginParams{
636         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
637         DE_NULL,                                     // const void* pNext;
638         usageFlags,                                  // VkCommandBufferUsageFlags flags;
639         &bufferInheritanceInfo};
640 
641     const DeviceInterface &vk = m_context.getDeviceInterface();
642     VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
643 }
644 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkClearValue clearValue,VkRenderingFlagsKHR renderingFlags) const645 void DepthClampTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkClearValue clearValue,
646                                                 VkRenderingFlagsKHR renderingFlags) const
647 {
648     const DeviceInterface &vk = m_context.getDeviceInterface();
649     const VkRect2D renderArea = makeRect2D(0, 0, WIDTH, HEIGHT);
650 
651     VkRenderingAttachmentInfoKHR depthAttachment{
652         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,  // VkStructureType sType;
653         DE_NULL,                                          // const void* pNext;
654         *m_depthTargetView,                               // VkImageView imageView;
655         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
656         VK_RESOLVE_MODE_NONE,                             // VkResolveModeFlagBits resolveMode;
657         DE_NULL,                                          // VkImageView resolveImageView;
658         VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout resolveImageLayout;
659         VK_ATTACHMENT_LOAD_OP_LOAD,                       // VkAttachmentLoadOp loadOp;
660         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp storeOp;
661         clearValue                                        // VkClearValue clearValue;
662     };
663 
664     VkRenderingInfoKHR renderingInfo{
665         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
666         DE_NULL,
667         renderingFlags,   // VkRenderingFlagsKHR flags;
668         renderArea,       // VkRect2D renderArea;
669         1u,               // uint32_t layerCount;
670         0u,               // uint32_t viewMask;
671         0u,               // uint32_t colorAttachmentCount;
672         DE_NULL,          // const VkRenderingAttachmentInfoKHR* pColorAttachments;
673         &depthAttachment, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
674         DE_NULL,          // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
675     };
676 
677     vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
678 }
679 #endif // CTS_USES_VULKANSC
680 
iterate(void)681 tcu::TestStatus DepthClampTestInstance::iterate(void)
682 {
683     const tcu::ConstPixelBufferAccess resultImage = draw();
684 
685     DE_ASSERT((isUnormDepthFormat(m_format) == false) ||
686               (m_params.viewportData[0].expectedValue >= 0.0f && m_params.viewportData[0].expectedValue <= 1.0f));
687 
688     for (uint32_t viewportIndex = 0; viewportIndex < m_scissorVect.size(); ++viewportIndex)
689     {
690         const float expectedValue = m_params.viewportData[viewportIndex].expectedValue;
691         const VkRect2D &viewRect  = m_scissorVect[viewportIndex];
692 
693         int32_t xStart = viewRect.offset.x;
694         int32_t xEnd   = xStart + viewRect.extent.width;
695         int32_t yStart = viewRect.offset.y;
696         int32_t yEnd   = yStart + viewRect.extent.height;
697 
698         for (int y = yStart; y < yEnd; ++y)
699             for (int x = xStart; x < xEnd; ++x)
700             {
701                 if (std::abs(expectedValue - resultImage.getPixDepth(x, y, 0)) >= m_epsilon)
702                 {
703                     tcu::TestLog &log = m_context.getTestContext().getLog();
704                     log << tcu::TestLog::ImageSet("Result of rendering", "")
705                         << tcu::TestLog::Image("Result", "", resultImage) << tcu::TestLog::EndImageSet;
706 
707                     std::ostringstream msg;
708                     msg << "Depth value mismatch, expected: " << expectedValue
709                         << ", got: " << resultImage.getPixDepth(x, y, 0) << " at (" << x << ", " << y << ", 0)";
710 
711                     return tcu::TestStatus::fail(msg.str());
712                 }
713             }
714     }
715     return tcu::TestStatus::pass("Pass");
716 }
717 
718 class DepthClampTest : public TestCase
719 {
720 public:
DepthClampTest(tcu::TestContext & testCtx,const string & name,const TestParams & params,const VkFormat format,const float epsilon,const SharedGroupParams groupParams)721     DepthClampTest(tcu::TestContext &testCtx, const string &name, const TestParams &params, const VkFormat format,
722                    const float epsilon, const SharedGroupParams groupParams)
723         : TestCase(testCtx, name)
724         , m_params(params)
725         , m_format(format)
726         , m_epsilon(epsilon)
727         , m_groupParams(groupParams)
728     {
729     }
730 
initPrograms(SourceCollections & programCollection) const731     virtual void initPrograms(SourceCollections &programCollection) const
732     {
733         programCollection.glslSources.add("vert") << glu::VertexSource("#version 450\n"
734                                                                        "\n"
735                                                                        "layout(location = 0) in vec4 in_position;\n"
736                                                                        "void main(void)\n"
737                                                                        "{\n"
738                                                                        "    gl_Position = in_position;\n"
739                                                                        "}\n");
740 
741         if (m_params.viewportData.size() > 1)
742         {
743             // gl_ViewportIndex built-in variable is available only to the geometry shader
744 
745             std::string depthValues = "";
746             for (const auto &vd : m_params.viewportData)
747                 depthValues += std::to_string(vd.depthValue) + ", ";
748 
749             // this geometry shader draws the same quad but with diferent depth to all viewports
750             programCollection.glslSources.add("geom")
751                 << glu::GeometrySource(std::string("#version 450\n") +
752                                        "#extension GL_EXT_geometry_shader : require\n"
753                                        "layout(invocations = " +
754                                        std::to_string(m_params.viewportData.size()) +
755                                        ") in;\n"
756                                        "layout(triangles) in;\n"
757                                        "layout(triangle_strip, max_vertices = 4) out;\n"
758                                        "void main()\n"
759                                        "{\n"
760                                        "  const float depthValues[] = { " +
761                                        depthValues +
762                                        " 0.0 };\n"
763                                        "  for (int i = 0; i < gl_in.length(); i++)\n"
764                                        "  {\n"
765                                        "    gl_ViewportIndex = gl_InvocationID;\n"
766                                        "    gl_Position      = gl_in[i].gl_Position;\n"
767                                        "    gl_Position.z    = depthValues[gl_InvocationID];\n"
768                                        "    EmitVertex();\n"
769                                        "  }\n"
770                                        "  EndPrimitive();\n"
771                                        "}");
772         }
773 
774         programCollection.glslSources.add("frag") << glu::FragmentSource("#version 450\n"
775                                                                          "void main(void)\n"
776                                                                          "{\n"
777                                                                          "}\n");
778     }
779 
checkSupport(Context & context) const780     virtual void checkSupport(Context &context) const
781     {
782         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_CLAMP);
783         for (const auto &extensionName : m_params.requiredExtensions)
784             context.requireDeviceFunctionality(extensionName);
785 
786         if (m_params.viewportData.size() > 1)
787         {
788             context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
789             if (!context.getDeviceFeatures().geometryShader)
790                 throw tcu::NotSupportedError("Geometry shader is not supported");
791         }
792 
793         VkImageFormatProperties imageFormatProperties;
794         const auto &vki  = context.getInstanceInterface();
795         const auto &vkd  = context.getPhysicalDevice();
796         const auto usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
797                            VK_IMAGE_USAGE_TRANSFER_DST_BIT;
798         if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage,
799                                                        0u, &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
800         {
801             TCU_THROW(NotSupportedError, "Format not supported");
802         }
803 
804         if (m_groupParams->useDynamicRendering)
805             context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
806     }
807 
createInstance(Context & context) const808     virtual TestInstance *createInstance(Context &context) const
809     {
810         return new DepthClampTestInstance(context, m_params, m_format, m_epsilon, m_groupParams);
811     }
812 
813 private:
814     const TestParams m_params;
815     const VkFormat m_format;
816     const float m_epsilon;
817     const SharedGroupParams m_groupParams;
818 };
819 
getFormatCaseName(VkFormat format)820 std::string getFormatCaseName(VkFormat format)
821 {
822     return de::toLower(de::toString(getFormatStr(format)).substr(10));
823 }
824 
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)825 void createTests(tcu::TestCaseGroup *testGroup, const SharedGroupParams groupParams)
826 {
827     for (int i = 0; i < DE_LENGTH_OF_ARRAY(depthStencilImageFormatsToTest); ++i)
828     {
829         const auto format = depthStencilImageFormatsToTest[i];
830 
831         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
832         if (groupParams->useSecondaryCmdBuffer && (format != VK_FORMAT_D16_UNORM))
833             continue;
834 
835         const float epsilon       = depthEpsilonValuesByFormat[i];
836         const auto formatCaseName = getFormatCaseName(format);
837         for (const auto &params : depthClearValuesToTest)
838         {
839             if ((params.skipSNorm && vk::isSnormFormat(format)) || (params.skipUNorm && isUnormDepthFormat(format)))
840                 continue;
841             const auto testCaseName = formatCaseName + params.testNameSuffix;
842             testGroup->addChild(
843                 new DepthClampTest(testGroup->getTestContext(), testCaseName, params, format, epsilon, groupParams));
844         }
845     }
846 }
847 } // namespace
848 
createDepthClampTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)849 tcu::TestCaseGroup *createDepthClampTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
850 {
851     return createTestGroup(testCtx, "depth_clamp", createTests, groupParams);
852 }
853 } // namespace Draw
854 } // namespace vkt
855