1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2017 Google Inc.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Inverted depth ranges tests.
23 *//*--------------------------------------------------------------------*/
25 #include "vktDrawInvertedDepthRangesTests.hpp"
26 #include "vktDrawCreateInfoUtil.hpp"
27 #include "vktDrawImageObjectUtil.hpp"
28 #include "vktDrawBufferObjectUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vktTestCaseUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkImageUtil.hpp"
36 #include "tcuVector.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuTestLog.hpp"
41 #include "deSharedPtr.hpp"
56 VkBool32 depthClampEnable;
61 class InvertedDepthRangesTestInstance : public TestInstance
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;
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;
81 InvertedDepthRangesTestInstance::InvertedDepthRangesTestInstance (Context& context, const TestParams& params)
82 : TestInstance (context)
84 , m_colorAttachmentFormat (VK_FORMAT_R8G8B8A8_UNORM)
86 const DeviceInterface& vk = m_context.getDeviceInterface();
87 const VkDevice device = m_context.getDevice();
89 if (m_params.depthClampEnable && !m_context.getDeviceFeatures().depthClamp)
90 TCU_THROW(NotSupportedError, "DepthClamp device feature not supported.");
92 if (params.minDepth > 1.0f ||
93 params.minDepth < 0.0f ||
94 params.maxDepth > 1.0f ||
95 params.maxDepth < 0.0f)
97 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_EXT_depth_range_unrestricted"))
98 throw tcu::NotSupportedError("Test variant with minDepth/maxDepth outside 0..1 requires the VK_EXT_depth_range_unrestricted extension");
103 std::vector<Vec4> vertexData;
105 vertexData.push_back(Vec4(-0.8f, -0.8f, -0.2f, 1.0f)); // 0-----2
106 vertexData.push_back(Vec4(-0.8f, 0.8f, 0.0f, 1.0f)); // | /
107 vertexData.push_back(Vec4( 0.8f, -0.8f, 1.2f, 1.0f)); // 1|/
109 const VkDeviceSize dataSize = vertexData.size() * sizeof(Vec4);
110 m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
111 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
113 deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &vertexData[0], static_cast<std::size_t>(dataSize));
114 flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
119 const VkExtent3D targetImageExtent = { 256, 256, 1 };
120 const VkImageUsageFlags targetImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
122 const ImageCreateInfo targetImageCreateInfo(
123 VK_IMAGE_TYPE_2D, // imageType,
124 m_colorAttachmentFormat, // format,
125 targetImageExtent, // extent,
128 VK_SAMPLE_COUNT_1_BIT, // samples,
129 VK_IMAGE_TILING_OPTIMAL, // tiling,
130 targetImageUsageFlags); // usage,
132 m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
134 RenderPassCreateInfo renderPassCreateInfo;
135 renderPassCreateInfo.addAttachment(AttachmentDescription(
136 m_colorAttachmentFormat, // format
137 VK_SAMPLE_COUNT_1_BIT, // samples
138 VK_ATTACHMENT_LOAD_OP_LOAD, // loadOp
139 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
140 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
141 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
142 VK_IMAGE_LAYOUT_GENERAL, // initialLayout
143 VK_IMAGE_LAYOUT_GENERAL)); // finalLayout
145 const VkAttachmentReference colorAttachmentReference =
148 VK_IMAGE_LAYOUT_GENERAL
151 renderPassCreateInfo.addSubpass(SubpassDescription(
152 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
153 (VkSubpassDescriptionFlags)0, // flags
154 0u, // inputAttachmentCount
155 DE_NULL, // inputAttachments
156 1u, // colorAttachmentCount
157 &colorAttachmentReference, // colorAttachments
158 DE_NULL, // resolveAttachments
159 AttachmentReference(), // depthStencilAttachment
160 0u, // preserveAttachmentCount
161 DE_NULL)); // preserveAttachments
163 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
168 const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
169 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
171 std::vector<VkImageView> colorAttachments(1);
172 colorAttachments[0] = *m_colorTargetView;
174 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, 256, 256, 1);
175 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
180 const VkVertexInputBindingDescription vertexInputBindingDescription =
182 0u, // uint32_t binding;
183 sizeof(Vec4), // uint32_t stride;
184 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
187 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
189 0u, // uint32_t location;
190 0u, // uint32_t binding;
191 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
192 0u // uint32_t offset;
195 const PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
196 1, &vertexInputAttributeDescription);
200 const VkRect2D scissor =
203 { 256, 256 }, // width, height
206 std::vector<VkDynamicState> dynamicStates;
207 dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
209 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
210 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
212 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
213 m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
215 const PipelineCreateInfo::ColorBlendState::Attachment colorBlendAttachmentState;
217 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
218 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule, "main", VK_SHADER_STAGE_VERTEX_BIT));
219 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
220 pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState (vertexInputState));
221 pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
222 pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState (1, &colorBlendAttachmentState));
223 pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState (1, std::vector<VkViewport>(), std::vector<VkRect2D>(1, scissor)));
224 pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState ());
225 pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState (
226 m_params.depthClampEnable, // depthClampEnable
227 VK_FALSE, // rasterizerDiscardEnable
228 VK_POLYGON_MODE_FILL, // polygonMode
229 VK_CULL_MODE_NONE, // cullMode
230 VK_FRONT_FACE_CLOCKWISE, // frontFace
231 VK_FALSE, // depthBiasEnable
232 0.0f, // depthBiasConstantFactor
233 0.0f, // depthBiasClamp
234 0.0f, // depthBiasSlopeFactor
236 pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState ());
237 pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState (dynamicStates));
239 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
242 tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewport viewport)
244 const DeviceInterface& vk = m_context.getDeviceInterface();
245 const VkDevice device = m_context.getDevice();
246 const VkQueue queue = m_context.getUniversalQueue();
247 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
251 const CmdPoolCreateInfo cmdPoolCreateInfo (queueFamilyIndex);
252 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo));
253 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
258 const CmdBufferBeginInfo beginInfo;
259 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
262 vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
265 const VkClearColorValue clearColor = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
266 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
268 initialTransitionColor2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
269 vk.cmdClearColorImage(*cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
272 const VkMemoryBarrier memBarrier =
274 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
275 DE_NULL, // const void* pNext;
276 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
277 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT // VkAccessFlags dstAccessMask;
280 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
283 const VkRect2D renderArea = { { 0, 0 }, { 256, 256 } };
284 const RenderPassBeginInfo renderPassBegin (*m_renderPass, *m_framebuffer, renderArea);
286 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
289 const VkDeviceSize offset = 0;
290 const VkBuffer buffer = m_vertexBuffer->object();
292 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
295 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
296 vk.cmdDraw(*cmdBuffer, 3, 1, 0, 0);
297 vk.cmdEndRenderPass(*cmdBuffer);
298 vk.endCommandBuffer(*cmdBuffer);
302 const Unique<VkFence> fence (createFence(vk, device));
303 const VkSubmitInfo submitInfo =
305 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
306 DE_NULL, // const void* pNext;
307 0, // uint32_t waitSemaphoreCount;
308 DE_NULL, // const VkSemaphore* pWaitSemaphores;
309 (const VkPipelineStageFlags*)DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask;
310 1, // uint32_t commandBufferCount;
311 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
312 0, // uint32_t signalSemaphoreCount;
313 DE_NULL // const VkSemaphore* pSignalSemaphores;
316 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
317 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), VK_TRUE, ~0ull));
322 const VkOffset3D zeroOffset = { 0, 0, 0 };
323 return m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, 256, 256, VK_IMAGE_ASPECT_COLOR_BIT);
327 MovePtr<tcu::TextureLevel> InvertedDepthRangesTestInstance::generateReferenceImage (void) const
329 MovePtr<tcu::TextureLevel> image (new tcu::TextureLevel(mapVkFormat(m_colorAttachmentFormat), 256, 256));
330 const tcu::PixelBufferAccess access (image->getAccess());
331 const Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
332 const int p1 = static_cast<int>(256.0f * 0.2f / 2.0f);
333 const int p2 = static_cast<int>(256.0f * 1.8f / 2.0f);
334 const float delta = 256.0f * 1.6f / 2.0f;
335 const float depthValues[] = { -0.2f, 0.0f, 1.2f };
337 tcu::clear(access, black);
339 for (int y = p1; y <= p2; ++y)
340 for (int x = p1; x < 256 - y; ++x)
342 const float a = static_cast<float>(p2 - x + p1 - y) / delta;
343 const float b = static_cast<float>(y - p1) / delta;
344 const float c = 1.0f - a - b;
345 const float depth = a * depthValues[0] + b * depthValues[1] + c * depthValues[2];
346 const float depthClamped = de::clamp(depth, 0.0f, 1.0f);
347 const float depthFinal = depthClamped * m_params.maxDepth + (1.0f - depthClamped) * m_params.minDepth;
349 if (m_params.depthClampEnable || (depth >= 0.0f && depth <= 1.0f))
350 access.setPixel(Vec4(depthFinal, 0.5f, 0.5f, 1.0f), x, y);
356 tcu::TestStatus InvertedDepthRangesTestInstance::iterate (void)
358 // Set up the viewport and draw
360 const VkViewport viewport =
364 256.0f, // float width;
365 256.0f, // float height;
366 m_params.minDepth, // float minDepth;
367 m_params.maxDepth, // float maxDepth;
370 const tcu::ConstPixelBufferAccess resultImage = draw(viewport);
372 // Verify the results
374 tcu::TestLog& log = m_context.getTestContext().getLog();
375 MovePtr<tcu::TextureLevel> referenceImage = generateReferenceImage();
377 if (!tcu::fuzzyCompare(log, "Image compare", "Image compare", referenceImage->getAccess(), resultImage, 0.02f, tcu::COMPARE_LOG_RESULT))
378 return tcu::TestStatus::fail("Rendered image is incorrect");
380 return tcu::TestStatus::pass("Pass");
383 class InvertedDepthRangesTest : public TestCase
386 InvertedDepthRangesTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
387 : TestCase (testCtx, name, description)
392 void initPrograms (SourceCollections& programCollection) const
396 std::ostringstream src;
397 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
399 << "layout(location = 0) in vec4 in_position;\n"
401 << "out gl_PerVertex {\n"
402 << " vec4 gl_Position;\n"
405 << "void main(void)\n"
407 << " gl_Position = in_position;\n"
410 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
415 std::ostringstream src;
416 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
418 << "layout(location = 0) out vec4 out_color;\n"
420 << "void main(void)\n"
422 << " out_color = vec4(gl_FragCoord.z, 0.5, 0.5, 1.0);\n"
425 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
429 virtual TestInstance* createInstance (Context& context) const
431 return new InvertedDepthRangesTestInstance(context, m_params);
435 const TestParams m_params;
438 void populateTestGroup (tcu::TestCaseGroup* testGroup)
442 const char* const name;
446 { "depthclamp", VK_TRUE },
447 { "nodepthclamp", VK_FALSE },
452 const char* const name;
456 { "deltazero", 0.0f },
457 { "deltasmall", 0.3f },
458 { "deltaone", 1.0f },
460 // Range > 1.0 requires VK_EXT_depth_range_unrestricted extension
461 { "depth_range_unrestricted", 2.7f },
464 for (int ndxDepthClamp = 0; ndxDepthClamp < DE_LENGTH_OF_ARRAY(depthClamp); ++ndxDepthClamp)
465 for (int ndxDelta = 0; ndxDelta < DE_LENGTH_OF_ARRAY(delta); ++ndxDelta)
467 const float minDepth = 0.5f + delta[ndxDelta].delta / 2.0f;
468 const float maxDepth = minDepth - delta[ndxDelta].delta;
469 DE_ASSERT(minDepth >= maxDepth);
471 const TestParams params =
473 depthClamp[ndxDepthClamp].depthClamp,
477 std::ostringstream name;
478 name << depthClamp[ndxDepthClamp].name << "_" << delta[ndxDelta].name;
480 testGroup->addChild(new InvertedDepthRangesTest(testGroup->getTestContext(), name.str(), "", params));
486 tcu::TestCaseGroup* createInvertedDepthRangesTests (tcu::TestContext& testCtx)
488 return createTestGroup(testCtx, "inverted_depth_ranges", "Inverted depth ranges", populateTestGroup);