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();
91 std::vector<Vec4> vertexData;
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|/
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);
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);
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;
110 const ImageCreateInfo targetImageCreateInfo(
111 VK_IMAGE_TYPE_2D, // imageType,
112 m_colorAttachmentFormat, // format,
113 targetImageExtent, // extent,
116 VK_SAMPLE_COUNT_1_BIT, // samples,
117 VK_IMAGE_TILING_OPTIMAL, // tiling,
118 targetImageUsageFlags); // usage,
120 m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
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
133 const VkAttachmentReference colorAttachmentReference =
136 VK_IMAGE_LAYOUT_GENERAL
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
151 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
156 const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
157 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
159 std::vector<VkImageView> colorAttachments(1);
160 colorAttachments[0] = *m_colorTargetView;
162 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, 256, 256, 1);
163 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
168 const VkVertexInputBindingDescription vertexInputBindingDescription =
170 0u, // uint32_t binding;
171 sizeof(Vec4), // uint32_t stride;
172 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
175 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
177 0u, // uint32_t location;
178 0u, // uint32_t binding;
179 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
180 0u // uint32_t offset;
183 const PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
184 1, &vertexInputAttributeDescription);
188 const VkRect2D scissor =
191 { 256, 256 }, // width, height
194 std::vector<VkDynamicState> dynamicStates;
195 dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
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));
200 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
201 m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
203 const PipelineCreateInfo::ColorBlendState::Attachment colorBlendAttachmentState;
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
224 pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState ());
225 pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState (dynamicStates));
227 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
230 tcu::ConstPixelBufferAccess InvertedDepthRangesTestInstance::draw (const VkViewport viewport)
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();
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));
246 const CmdBufferBeginInfo beginInfo;
247 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
250 vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
253 const VkClearColorValue clearColor = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
254 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
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);
260 const VkMemoryBarrier memBarrier =
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;
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);
271 const VkRect2D renderArea = { { 0, 0 }, { 256, 256 } };
272 const RenderPassBeginInfo renderPassBegin (*m_renderPass, *m_framebuffer, renderArea);
274 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
277 const VkDeviceSize offset = 0;
278 const VkBuffer buffer = m_vertexBuffer->object();
280 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
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);
290 const Unique<VkFence> fence (createFence(vk, device));
291 const VkSubmitInfo submitInfo =
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;
304 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
305 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), VK_TRUE, ~0ull));
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);
315 MovePtr<tcu::TextureLevel> InvertedDepthRangesTestInstance::generateReferenceImage (void) const
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 };
325 tcu::clear(access, black);
327 for (int y = p1; y <= p2; ++y)
328 for (int x = p1; x < 256 - y; ++x)
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;
337 if (m_params.depthClampEnable || (depth >= 0.0f && depth <= 1.0f))
338 access.setPixel(Vec4(depthFinal, 0.5f, 0.5f, 1.0f), x, y);
344 tcu::TestStatus InvertedDepthRangesTestInstance::iterate (void)
346 // Check requirements
348 if (m_params.depthClampEnable && !m_context.getDeviceFeatures().depthClamp)
349 TCU_THROW(NotSupportedError, "DepthClamp device feature not supported.");
352 // Set up the viewport and draw
354 const VkViewport viewport =
358 256.0f, // float width;
359 256.0f, // float height;
360 m_params.minDepth, // float minDepth;
361 m_params.maxDepth, // float maxDepth;
364 const tcu::ConstPixelBufferAccess resultImage = draw(viewport);
366 // Verify the results
368 tcu::TestLog& log = m_context.getTestContext().getLog();
369 MovePtr<tcu::TextureLevel> referenceImage = generateReferenceImage();
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");
374 return tcu::TestStatus::pass("Pass");
377 class InvertedDepthRangesTest : public TestCase
380 InvertedDepthRangesTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
381 : TestCase (testCtx, name, description)
386 void initPrograms (SourceCollections& programCollection) const
390 std::ostringstream src;
391 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
393 << "layout(location = 0) in vec4 in_position;\n"
395 << "out gl_PerVertex {\n"
396 << " vec4 gl_Position;\n"
399 << "void main(void)\n"
401 << " gl_Position = in_position;\n"
404 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
409 std::ostringstream src;
410 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
412 << "layout(location = 0) out vec4 out_color;\n"
414 << "void main(void)\n"
416 << " out_color = vec4(gl_FragCoord.z, 0.5, 0.5, 1.0);\n"
419 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
423 virtual TestInstance* createInstance (Context& context) const
425 return new InvertedDepthRangesTestInstance(context, m_params);
429 const TestParams m_params;
432 void populateTestGroup (tcu::TestCaseGroup* testGroup)
436 const char* const name;
440 { "depthclamp", VK_TRUE },
441 { "nodepthclamp", VK_FALSE },
446 const char* const name;
450 { "deltazero", 0.0f },
451 { "deltasmall", 0.3f },
452 { "deltaone", 1.0f },
453 { "deltalarge", 2.7f },
456 for (int ndxDepthClamp = 0; ndxDepthClamp < DE_LENGTH_OF_ARRAY(depthClamp); ++ndxDepthClamp)
457 for (int ndxDelta = 0; ndxDelta < DE_LENGTH_OF_ARRAY(delta); ++ndxDelta)
459 const float minDepth = 0.5f + delta[ndxDelta].delta / 2.0f;
460 const float maxDepth = minDepth - delta[ndxDelta].delta;
461 DE_ASSERT(minDepth >= maxDepth);
463 const TestParams params =
465 depthClamp[ndxDepthClamp].depthClamp,
469 std::ostringstream name;
470 name << depthClamp[ndxDepthClamp].name << "_" << delta[ndxDelta].name;
472 testGroup->addChild(new InvertedDepthRangesTest(testGroup->getTestContext(), name.str(), "", params));
478 tcu::TestCaseGroup* createInvertedDepthRangesTests (tcu::TestContext& testCtx)
480 return createTestGroup(testCtx, "inverted_depth_ranges", "Inverted depth ranges", populateTestGroup);