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