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 ¶ms, 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 ¶ms, 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 ¶ms, 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 ¶ms : 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