Merge vk-gl-cts/vulkan-cts-1.0.2 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawInvertedDepthRangesTests.cpp
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 Inverted depth ranges tests.
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawInvertedDepthRangesTests.hpp"
26 #include "vktDrawCreateInfoUtil.hpp"
27 #include "vktDrawImageObjectUtil.hpp"
28 #include "vktDrawBufferObjectUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vktTestCaseUtil.hpp"
31
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageUtil.hpp"
35
36 #include "tcuVector.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuTestLog.hpp"
40
41 #include "deSharedPtr.hpp"
42
43 namespace vkt
44 {
45 namespace Draw
46 {
47 namespace
48 {
49 using namespace vk;
50 using tcu::Vec4;
51 using de::SharedPtr;
52 using de::MovePtr;
53
54 struct TestParams
55 {
56         VkBool32        depthClampEnable;
57         float           minDepth;
58         float           maxDepth;
59 };
60
61 class InvertedDepthRangesTestInstance : public TestInstance
62 {
63 public:
64                                                                         InvertedDepthRangesTestInstance (Context& context, const TestParams& params);
65         tcu::TestStatus                                 iterate                                                 (void);
66         tcu::ConstPixelBufferAccess             draw                                                    (const VkViewport viewport);
67         MovePtr<tcu::TextureLevel>              generateReferenceImage                  (void) const;
68
69 private:
70         const TestParams                                m_params;
71         const VkFormat                                  m_colorAttachmentFormat;
72         SharedPtr<Image>                                m_colorTargetImage;
73         Move<VkImageView>                               m_colorTargetView;
74         SharedPtr<Buffer>                               m_vertexBuffer;
75         Move<VkRenderPass>                              m_renderPass;
76         Move<VkFramebuffer>                             m_framebuffer;
77         Move<VkPipelineLayout>                  m_pipelineLayout;
78         Move<VkPipeline>                                m_pipeline;
79 };
80
81 InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& context, const TestParams& params)
82         : TestInstance                          (context)
83         , m_params                                      (params)
84         , m_colorAttachmentFormat       (VK_FORMAT_R8G8B8A8_UNORM)
85 {
86         const DeviceInterface&  vk              = m_context.getDeviceInterface();
87         const VkDevice                  device  = m_context.getDevice();
88
89         // Vertex data
90         {
91                 std::vector<Vec4> vertexData;
92
93                 vertexData.push_back(Vec4(-0.8f, -0.8f, -0.2f, 1.0f));  //  0-----2
94                 vertexData.push_back(Vec4(-0.8f,  0.8f,  0.0f, 1.0f));  //   |  /
95                 vertexData.push_back(Vec4( 0.8f, -0.8f,  1.2f, 1.0f));  //  1|/
96
97                 const VkDeviceSize dataSize = vertexData.size() * sizeof(Vec4);
98                 m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
99                                                                                                 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
100
101                 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &vertexData[0], static_cast<std::size_t>(dataSize));
102                 flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
103         }
104
105         // Render pass
106         {
107                 const VkExtent3D                targetImageExtent               = { 256, 256, 1 };
108                 const VkImageUsageFlags targetImageUsageFlags   = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
109
110                 const ImageCreateInfo   targetImageCreateInfo(
111                         VK_IMAGE_TYPE_2D,                                               // imageType,
112                         m_colorAttachmentFormat,                                // format,
113                         targetImageExtent,                                              // extent,
114                         1u,                                                                             // mipLevels,
115                         1u,                                                                             // arrayLayers,
116                         VK_SAMPLE_COUNT_1_BIT,                                  // samples,
117                         VK_IMAGE_TILING_OPTIMAL,                                // tiling,
118                         targetImageUsageFlags);                                 // usage,
119
120                 m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
121
122                 RenderPassCreateInfo    renderPassCreateInfo;
123                 renderPassCreateInfo.addAttachment(AttachmentDescription(
124                         m_colorAttachmentFormat,                                // format
125                         VK_SAMPLE_COUNT_1_BIT,                                  // samples
126                         VK_ATTACHMENT_LOAD_OP_LOAD,                             // loadOp
127                         VK_ATTACHMENT_STORE_OP_STORE,                   // storeOp
128                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                // stencilLoadOp
129                         VK_ATTACHMENT_STORE_OP_DONT_CARE,               // stencilStoreOp
130                         VK_IMAGE_LAYOUT_GENERAL,                                // initialLayout
131                         VK_IMAGE_LAYOUT_GENERAL));                              // finalLayout
132
133                 const VkAttachmentReference colorAttachmentReference =
134                 {
135                         0u,
136                         VK_IMAGE_LAYOUT_GENERAL
137                 };
138
139                 renderPassCreateInfo.addSubpass(SubpassDescription(
140                         VK_PIPELINE_BIND_POINT_GRAPHICS,                // pipelineBindPoint
141                         (VkSubpassDescriptionFlags)0,                   // flags
142                         0u,                                                                             // inputAttachmentCount
143                         DE_NULL,                                                                // inputAttachments
144                         1u,                                                                             // colorAttachmentCount
145                         &colorAttachmentReference,                              // colorAttachments
146                         DE_NULL,                                                                // resolveAttachments
147                         AttachmentReference(),                                  // depthStencilAttachment
148                         0u,                                                                             // preserveAttachmentCount
149                         DE_NULL));                                                              // preserveAttachments
150
151                 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
152         }
153
154         // Framebuffer
155         {
156                 const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
157                 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
158
159                 std::vector<VkImageView> colorAttachments(1);
160                 colorAttachments[0] = *m_colorTargetView;
161
162                 const FramebufferCreateInfo     framebufferCreateInfo(*m_renderPass, colorAttachments, 256, 256, 1);
163                 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
164         }
165
166         // Vertex input
167
168         const VkVertexInputBindingDescription           vertexInputBindingDescription =
169         {
170                 0u,                                                                             // uint32_t             binding;
171                 sizeof(Vec4),                                                   // uint32_t             stride;
172                 VK_VERTEX_INPUT_RATE_VERTEX,                    // VkVertexInputRate    inputRate;
173         };
174
175         const VkVertexInputAttributeDescription         vertexInputAttributeDescription =
176         {
177                 0u,                                                                             // uint32_t    location;
178                 0u,                                                                             // uint32_t    binding;
179                 VK_FORMAT_R32G32B32A32_SFLOAT,                  // VkFormat    format;
180                 0u                                                                              // uint32_t    offset;
181         };
182
183         const PipelineCreateInfo::VertexInputState      vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
184                                                                                                                                                                                                                 1, &vertexInputAttributeDescription);
185
186         // Graphics pipeline
187
188         const VkRect2D scissor =
189         {
190                 { 0,    0       },      // x, y
191                 { 256,  256     },      // width, height
192         };
193
194         std::vector<VkDynamicState>             dynamicStates;
195         dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
196
197         const Unique<VkShaderModule>    vertexModule    (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
198         const Unique<VkShaderModule>    fragmentModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
199
200         const PipelineLayoutCreateInfo  pipelineLayoutCreateInfo;
201         m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
202
203         const PipelineCreateInfo::ColorBlendState::Attachment colorBlendAttachmentState;
204
205         PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
206         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,   "main", VK_SHADER_STAGE_VERTEX_BIT));
207         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
208         pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState       (vertexInputState));
209         pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
210         pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState        (1, &colorBlendAttachmentState));
211         pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState          (1, std::vector<VkViewport>(), std::vector<VkRect2D>(1, scissor)));
212         pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState      ());
213         pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState        (
214                 m_params.depthClampEnable,      // depthClampEnable
215                 VK_FALSE,                                       // rasterizerDiscardEnable
216                 VK_POLYGON_MODE_FILL,           // polygonMode
217                 VK_CULL_MODE_NONE,                      // cullMode
218                 VK_FRONT_FACE_CLOCKWISE,        // frontFace
219                 VK_FALSE,                                       // depthBiasEnable
220                 0.0f,                                           // depthBiasConstantFactor
221                 0.0f,                                           // depthBiasClamp
222                 0.0f,                                           // depthBiasSlopeFactor
223                 1.0f));                                         // lineWidth
224         pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState       ());
225         pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState           (dynamicStates));
226
227         m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
228 }
229
230 tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewport viewport)
231 {
232         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
233         const VkDevice                  device                          = m_context.getDevice();
234         const VkQueue                   queue                           = m_context.getUniversalQueue();
235         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
236
237         // Command buffer
238
239         const CmdPoolCreateInfo                 cmdPoolCreateInfo       (queueFamilyIndex);
240         const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, &cmdPoolCreateInfo));
241         const Unique<VkCommandBuffer>   cmdBuffer                       (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
242
243         // Draw
244
245         {
246                 const CmdBufferBeginInfo beginInfo;
247                 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
248         }
249
250         vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
251
252         {
253                 const VkClearColorValue         clearColor                      = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
254                 const ImageSubresourceRange subresourceRange    (VK_IMAGE_ASPECT_COLOR_BIT);
255
256                 initialTransitionColor2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
257                 vk.cmdClearColorImage(*cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
258         }
259         {
260                 const VkMemoryBarrier memBarrier =
261                 {
262                         VK_STRUCTURE_TYPE_MEMORY_BARRIER,                                                                                               // VkStructureType    sType;
263                         DE_NULL,                                                                                                                                                // const void*        pNext;
264                         VK_ACCESS_TRANSFER_WRITE_BIT,                                                                                                   // VkAccessFlags      srcAccessMask;
265                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT              // VkAccessFlags      dstAccessMask;
266                 };
267
268                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
269         }
270         {
271                 const VkRect2D                          renderArea              = { { 0, 0 }, { 256, 256 } };
272                 const RenderPassBeginInfo       renderPassBegin (*m_renderPass, *m_framebuffer, renderArea);
273
274                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
275         }
276         {
277                 const VkDeviceSize      offset  = 0;
278                 const VkBuffer          buffer  = m_vertexBuffer->object();
279
280                 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
281         }
282
283         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
284         vk.cmdDraw(*cmdBuffer, 3, 1, 0, 0);
285         vk.cmdEndRenderPass(*cmdBuffer);
286         vk.endCommandBuffer(*cmdBuffer);
287
288         // Submit
289         {
290                 const Unique<VkFence>   fence           (createFence(vk, device));
291                 const VkSubmitInfo              submitInfo      =
292                 {
293                         VK_STRUCTURE_TYPE_SUBMIT_INFO,                          // VkStructureType                sType;
294                         DE_NULL,                                                                        // const void*                    pNext;
295                         0,                                                                                      // uint32_t                       waitSemaphoreCount;
296                         DE_NULL,                                                                        // const VkSemaphore*             pWaitSemaphores;
297                         (const VkPipelineStageFlags*)DE_NULL,           // const VkPipelineStageFlags*    pWaitDstStageMask;
298                         1,                                                                                      // uint32_t                       commandBufferCount;
299                         &cmdBuffer.get(),                                                       // const VkCommandBuffer*         pCommandBuffers;
300                         0,                                                                                      // uint32_t                       signalSemaphoreCount;
301                         DE_NULL                                                                         // const VkSemaphore*             pSignalSemaphores;
302                 };
303
304                 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
305                 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), VK_TRUE, ~0ull));
306         }
307
308         // Get result
309         {
310                 const VkOffset3D zeroOffset = { 0, 0, 0 };
311                 return m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, 256, 256, VK_IMAGE_ASPECT_COLOR_BIT);
312         }
313 }
314
315 MovePtr<tcu::TextureLevel> InvertedDepthRangesTestInstance::generateReferenceImage (void) const
316 {
317         MovePtr<tcu::TextureLevel>              image                   (new tcu::TextureLevel(mapVkFormat(m_colorAttachmentFormat), 256, 256));
318         const tcu::PixelBufferAccess    access                  (image->getAccess());
319         const Vec4                                              black                   (0.0f, 0.0f, 0.0f, 1.0f);
320         const int                                               p1                              = static_cast<int>(256.0f * 0.2f / 2.0f);
321         const int                                               p2                              = static_cast<int>(256.0f * 1.8f / 2.0f);
322         const float                                             delta                   = 256.0f * 1.6f / 2.0f;
323         const float                                             depthValues[]   = { -0.2f, 0.0f, 1.2f };
324
325         tcu::clear(access, black);
326
327         for (int y = p1; y <= p2; ++y)
328                 for (int x = p1; x <  256 - y;  ++x)
329                 {
330                         const float     a = static_cast<float>(p2 - x + p1 - y) / delta;
331                         const float     b = static_cast<float>(y - p1) / delta;
332                         const float     c = 1.0f - a - b;
333                         const float     depth = a * depthValues[0] + b * depthValues[1] + c * depthValues[2];
334                         const float     depthClamped = de::clamp(depth, 0.0f, 1.0f);
335                         const float     depthFinal = depthClamped * m_params.maxDepth + (1.0f - depthClamped) * m_params.minDepth;
336
337                         if (m_params.depthClampEnable || (depth >= 0.0f && depth <= 1.0f))
338                                 access.setPixel(Vec4(depthFinal, 0.5f, 0.5f, 1.0f), x, y);
339                 }
340
341         return image;
342 }
343
344 tcu::TestStatus InvertedDepthRangesTestInstance::iterate (void)
345 {
346         // Check requirements
347
348         if (m_params.depthClampEnable && !m_context.getDeviceFeatures().depthClamp)
349                 TCU_THROW(NotSupportedError, "DepthClamp device feature not supported.");
350
351
352         // Set up the viewport and draw
353
354         const VkViewport viewport =
355         {
356                 0.0f,                           // float    x;
357                 0.0f,                           // float    y;
358                 256.0f,                         // float    width;
359                 256.0f,                         // float    height;
360                 m_params.minDepth,      // float    minDepth;
361                 m_params.maxDepth,      // float    maxDepth;
362         };
363
364         const tcu::ConstPixelBufferAccess       resultImage     = draw(viewport);
365
366         // Verify the results
367
368         tcu::TestLog&                           log                             = m_context.getTestContext().getLog();
369         MovePtr<tcu::TextureLevel>      referenceImage  = generateReferenceImage();
370
371         if (!tcu::fuzzyCompare(log, "Image compare", "Image compare", referenceImage->getAccess(), resultImage, 0.02f, tcu::COMPARE_LOG_RESULT))
372                 return tcu::TestStatus::fail("Rendered image is incorrect");
373         else
374                 return tcu::TestStatus::pass("Pass");
375 }
376
377 class InvertedDepthRangesTest : public TestCase
378 {
379 public:
380         InvertedDepthRangesTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
381                 : TestCase      (testCtx, name, description)
382                 , m_params      (params)
383         {
384         }
385
386         void initPrograms (SourceCollections& programCollection) const
387         {
388                 // Vertex shader
389                 {
390                         std::ostringstream src;
391                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
392                                 << "\n"
393                                 << "layout(location = 0) in vec4 in_position;\n"
394                                 << "\n"
395                                 << "out gl_PerVertex {\n"
396                                 << "    vec4  gl_Position;\n"
397                                 << "};\n"
398                                 << "\n"
399                                 << "void main(void)\n"
400                                 << "{\n"
401                                 << "    gl_Position = in_position;\n"
402                                 << "}\n";
403
404                         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
405                 }
406
407                 // Fragment shader
408                 {
409                         std::ostringstream src;
410                         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
411                                 << "\n"
412                                 << "layout(location = 0) out vec4 out_color;\n"
413                                 << "\n"
414                                 << "void main(void)\n"
415                                 << "{\n"
416                                 << "    out_color = vec4(gl_FragCoord.z, 0.5, 0.5, 1.0);\n"
417                                 << "}\n";
418
419                         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
420                 }
421         }
422
423         virtual TestInstance* createInstance (Context& context) const
424         {
425                 return new InvertedDepthRangesTestInstance(context, m_params);
426         }
427
428 private:
429         const TestParams        m_params;
430 };
431
432 void populateTestGroup (tcu::TestCaseGroup* testGroup)
433 {
434         const struct
435         {
436                 const char* const       name;
437                 VkBool32                        depthClamp;
438         } depthClamp[] =
439         {
440                 { "depthclamp",         VK_TRUE         },
441                 { "nodepthclamp",       VK_FALSE        },
442         };
443
444         const struct
445         {
446                 const char* const       name;
447                 float                           delta;
448         } delta[] =
449         {
450                 { "deltazero",  0.0f    },
451                 { "deltasmall", 0.3f    },
452                 { "deltaone",   1.0f    },
453                 { "deltalarge", 2.7f    },
454         };
455
456         for (int ndxDepthClamp = 0; ndxDepthClamp < DE_LENGTH_OF_ARRAY(depthClamp); ++ndxDepthClamp)
457         for (int ndxDelta = 0; ndxDelta < DE_LENGTH_OF_ARRAY(delta); ++ndxDelta)
458         {
459                 const float minDepth = 0.5f + delta[ndxDelta].delta / 2.0f;
460                 const float maxDepth = minDepth - delta[ndxDelta].delta;
461                 DE_ASSERT(minDepth >= maxDepth);
462
463                 const TestParams params =
464                 {
465                         depthClamp[ndxDepthClamp].depthClamp,
466                         minDepth,
467                         maxDepth
468                 };
469                 std::ostringstream      name;
470                 name << depthClamp[ndxDepthClamp].name << "_" << delta[ndxDelta].name;
471
472                 testGroup->addChild(new InvertedDepthRangesTest(testGroup->getTestContext(), name.str(), "", params));
473         }
474 }
475
476 }       // anonymous
477
478 tcu::TestCaseGroup*     createInvertedDepthRangesTests (tcu::TestContext& testCtx)
479 {
480         return createTestGroup(testCtx, "inverted_depth_ranges", "Inverted depth ranges", populateTestGroup);
481 }
482
483 }       // Draw
484 }       // vkt