| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2016 The Khronos Group Inc. |
| * Copyright (c) 2017 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Depth clamp tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vkDefs.hpp" |
| #include "vktDrawDepthClampTests.hpp" |
| #include "vktTestGroupUtil.hpp" |
| #include "vktTestCaseUtil.hpp" |
| #include "vktDrawCreateInfoUtil.hpp" |
| #include "vktDrawBufferObjectUtil.hpp" |
| #include "vktDrawImageObjectUtil.hpp" |
| #include "vkPrograms.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "tcuTextureUtil.hpp" |
| |
| #include <cmath> |
| #include <limits> |
| |
| namespace vkt |
| { |
| namespace Draw |
| { |
| namespace { |
| using namespace vk; |
| using namespace de; |
| using std::string; |
| using tcu::Vec4; |
| |
| static const int WIDTH = 256; |
| static const int HEIGHT = 256; |
| |
| struct TestParams |
| { |
| string testNameSuffix; |
| float depthValue; |
| float expectedValue; |
| bool enableDepthBias; |
| float depthBiasConstantFactor; |
| bool skipUNorm; |
| bool skipSNorm; |
| std::vector<const char*> requiredExtensions; |
| }; |
| |
| const VkFormat depthStencilImageFormatsToTest[] = |
| { |
| VK_FORMAT_D16_UNORM, |
| VK_FORMAT_X8_D24_UNORM_PACK32, |
| VK_FORMAT_D32_SFLOAT, |
| VK_FORMAT_D16_UNORM_S8_UINT, |
| VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_FORMAT_D32_SFLOAT_S8_UINT |
| }; |
| const float depthEpsilonValuesByFormat[] = |
| { |
| 1e-5f, |
| std::numeric_limits<float>::epsilon(), |
| std::numeric_limits<float>::epsilon(), |
| 1e-5f, |
| std::numeric_limits<float>::epsilon(), |
| std::numeric_limits<float>::epsilon() |
| }; |
| |
| const float initialClearDepth = 0.5f; |
| const TestParams depthClearValuesToTest[] = |
| { |
| { |
| "", // testNameSuffix |
| 0.3f, // depthValue |
| 0.3f, // expectedValue |
| false, // enableDepthBias |
| 0.0f, // depthBiasConstantFactor |
| false, // skipUNorm |
| false, // skipSNorm |
| {}, // requiredExtensions |
| }, |
| { |
| "_clamp_input_negative", // testNameSuffix |
| -1e6f, // depthValue |
| 0.0f, // expectedValue |
| false, // enableDepthBias |
| 0.0f, // depthBiasConstantFactor |
| false, // skipUNorm |
| false, // skipSNorm |
| {}, // requiredExtensions |
| }, |
| { |
| "_clamp_input_positive", // testNameSuffix |
| 1.e6f, // depthValue |
| 1.0f, // expectedValue |
| false, // enableDepthBias |
| 0.0f, // depthBiasConstantFactor |
| false, // skipUNorm |
| false, // skipSNorm |
| {}, // requiredExtensions |
| }, |
| { |
| "_depth_bias_clamp_input_negative", // testNameSuffix |
| 0.3f, // depthValue |
| 0.0f, // expectedValue |
| true, // enableDepthBias |
| -2e11f, // depthBiasConstantFactor |
| false, // skipUNorm |
| false, // skipSNorm |
| {}, // requiredExtensions |
| }, |
| { |
| "_depth_bias_clamp_input_positive", // testNameSuffix |
| 0.7f, // depthValue |
| 1.0f, // expectedValue |
| true, // enableDepthBias |
| 2e11f, // depthBiasConstantFactor |
| false, // skipUNorm |
| false, // skipSNorm |
| {}, // requiredExtensions |
| }, |
| { |
| "_depth_range_unrestricted_negative", // testNameSuffix |
| -1.5f, // depthValue |
| -1.5f, // expectedValue |
| false, // enableDepthBias |
| 0.0f, // depthBiasConstantFactor |
| true, // skipUNorm |
| true, // skipSNorm |
| { |
| "VK_EXT_depth_range_unrestricted" // requiredExtensions[0] |
| }, |
| }, |
| { |
| "_depth_range_unrestricted_positive", // testNameSuffix |
| 1.5f, // depthValue |
| 1.5f, // expectedValue |
| false, // enableDepthBias |
| 0.0f, // depthBiasConstantFactor |
| true, // skipUNorm |
| true, // skipSNorm |
| { |
| "VK_EXT_depth_range_unrestricted" // requiredExtensions[0] |
| }, |
| } |
| }; |
| |
| bool isUnormDepthFormat(VkFormat format) |
| { |
| switch (format) |
| { |
| case VK_FORMAT_D24_UNORM_S8_UINT: |
| case VK_FORMAT_X8_D24_UNORM_PACK32: |
| case VK_FORMAT_D16_UNORM_S8_UINT: |
| /* Special case for combined depth-stencil-unorm modes for which tcu::getTextureChannelClass() |
| returns TEXTURECHANNELCLASS_LAST */ |
| return true; |
| default: |
| return vk::isUnormFormat(format); |
| } |
| } |
| |
| class DepthClampTestInstance : public TestInstance { |
| public: |
| DepthClampTestInstance (Context& context, const TestParams& params, const VkFormat format, const float epsilon); |
| tcu::TestStatus iterate (); |
| |
| private: |
| tcu::ConstPixelBufferAccess draw (const VkViewport viewport); |
| |
| const TestParams m_params; |
| const VkFormat m_format; |
| const float m_epsilon; |
| SharedPtr<Image> m_depthTargetImage; |
| Move<VkImageView> m_depthTargetView; |
| SharedPtr<Buffer> m_vertexBuffer; |
| Move<VkRenderPass> m_renderPass; |
| Move<VkFramebuffer> m_framebuffer; |
| Move<VkPipelineLayout> m_pipelineLayout; |
| Move<VkPipeline> m_pipeline; |
| }; |
| |
| static const Vec4 vertices[] = { |
| Vec4(-1.0f, -1.0f, 0.5f, 1.0f), // 0 -- 2 |
| Vec4(-1.0f, 1.0f, 0.5f, 1.0f), // | / | |
| Vec4( 1.0f, -1.0f, 0.5f, 1.0f), // | / | |
| Vec4( 1.0f, 1.0f, 0.5f, 1.0f) // 1 -- 3 |
| }; |
| static const VkPrimitiveTopology verticesTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; |
| |
| DepthClampTestInstance::DepthClampTestInstance (Context& context, const TestParams& params, const VkFormat format, const float epsilon) |
| : TestInstance(context) |
| , m_params(params) |
| , m_format(format) |
| , m_epsilon(epsilon) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice device = m_context.getDevice(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| |
| DescriptorPoolBuilder descriptorPoolBuilder; |
| DescriptorSetLayoutBuilder descriptorSetLayoutBuilder; |
| // Vertex data |
| { |
| const size_t verticesCount = DE_LENGTH_OF_ARRAY(vertices); |
| const VkDeviceSize dataSize = verticesCount * sizeof(Vec4); |
| m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), |
| m_context.getDefaultAllocator(), MemoryRequirement::HostVisible); |
| |
| Vec4 testVertices[verticesCount]; |
| deMemcpy(testVertices, vertices, dataSize); |
| for(size_t i = 0; i < verticesCount; ++i) |
| testVertices[i][2] = params.depthValue; |
| deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), testVertices, static_cast<std::size_t>(dataSize)); |
| flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE); |
| } |
| // Render pass |
| { |
| const VkImageUsageFlags targetImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, m_format, { WIDTH, HEIGHT, 1u }, 1u, 1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, targetImageUsageFlags); |
| m_depthTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex); |
| |
| RenderPassCreateInfo renderPassCreateInfo; |
| renderPassCreateInfo.addAttachment(AttachmentDescription( |
| m_format, // format |
| VK_SAMPLE_COUNT_1_BIT, // samples |
| VK_ATTACHMENT_LOAD_OP_LOAD, // loadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // storeOp |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // initialLayout |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout |
| const VkAttachmentReference depthAttachmentReference = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); |
| renderPassCreateInfo.addSubpass(SubpassDescription( |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint |
| (VkSubpassDescriptionFlags)0, // flags |
| 0u, // inputAttachmentCount |
| DE_NULL, // inputAttachments |
| 0u, // colorAttachmentCount |
| DE_NULL, // colorAttachments |
| DE_NULL, // resolveAttachments |
| depthAttachmentReference, // depthStencilAttachment |
| 0u, // preserveAttachmentCount |
| DE_NULL)); // preserveAttachments |
| m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo); |
| } |
| |
| const ImageViewCreateInfo depthTargetViewInfo (m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_format); |
| m_depthTargetView = createImageView(vk, device, &depthTargetViewInfo); |
| |
| const std::vector<VkImageView> depthAttachments { *m_depthTargetView }; |
| FramebufferCreateInfo framebufferCreateInfo (*m_renderPass, depthAttachments, WIDTH, HEIGHT, 1); |
| |
| m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo); |
| |
| // Vertex input |
| const VkVertexInputBindingDescription vertexInputBindingDescription = |
| { |
| 0u, // uint32_t binding; |
| sizeof(Vec4), // uint32_t stride; |
| VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; |
| }; |
| |
| const VkVertexInputAttributeDescription vertexInputAttributeDescription = |
| { |
| 0u, // uint32_t location; |
| 0u, // uint32_t binding; |
| VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; |
| 0u // uint32_t offset; |
| }; |
| |
| const PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, |
| 1, &vertexInputAttributeDescription); |
| |
| // Graphics pipeline |
| const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); |
| const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0)); |
| |
| const PipelineLayoutCreateInfo pipelineLayoutCreateInfo (0u, DE_NULL, 0u, DE_NULL); |
| m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo); |
| |
| const VkRect2D scissor = makeRect2D(WIDTH, HEIGHT); |
| const VkViewport viewport = makeViewport(WIDTH, HEIGHT); |
| std::vector<VkDynamicState> dynamicStates (1, VK_DYNAMIC_STATE_VIEWPORT); |
| |
| PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0); |
| pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule, "main", VK_SHADER_STAGE_VERTEX_BIT)); |
| pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT)); |
| pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState (vertexInputState)); |
| pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(verticesTopology)); |
| pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState (1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor))); |
| pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState (VK_TRUE, VK_TRUE, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE)); |
| pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState ( |
| VK_TRUE, // depthClampEnable |
| VK_FALSE, // rasterizerDiscardEnable |
| VK_POLYGON_MODE_FILL, // polygonMode |
| VK_CULL_MODE_NONE, // cullMode |
| VK_FRONT_FACE_CLOCKWISE, // frontFace |
| m_params.enableDepthBias ? VK_TRUE : VK_FALSE, // depthBiasEnable |
| m_params.depthBiasConstantFactor, // depthBiasConstantFactor |
| 0.0f, // depthBiasClamp |
| 0.0f, // depthBiasSlopeFactor |
| 1.0f)); // lineWidth |
| pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState ()); |
| pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState (dynamicStates)); |
| m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo); |
| } |
| |
| tcu::ConstPixelBufferAccess DepthClampTestInstance::draw (const VkViewport viewport) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice device = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| |
| const CmdPoolCreateInfo cmdPoolCreateInfo (queueFamilyIndex); |
| const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo)); |
| const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| |
| const bool isCombinedType = tcu::isCombinedDepthStencilType(mapVkFormat(m_format).type) && m_format != VK_FORMAT_X8_D24_UNORM_PACK32; |
| |
| beginCommandBuffer(vk, *cmdBuffer); |
| vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport); |
| if (isCombinedType) |
| initialTransitionDepthStencil2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); |
| else |
| initialTransitionDepth2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); |
| |
| const VkImageAspectFlagBits aspectBits = (VkImageAspectFlagBits)(isCombinedType ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT); |
| const ImageSubresourceRange subresourceRange (aspectBits); |
| const VkClearDepthStencilValue clearDepth = makeClearDepthStencilValue(initialClearDepth, 0u); |
| |
| vk.cmdClearDepthStencilImage(*cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearDepth, 1, &subresourceRange); |
| |
| transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), aspectBits, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, |
| VK_ACCESS_TRANSFER_WRITE_BIT , VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, |
| VK_PIPELINE_STAGE_TRANSFER_BIT , VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT); |
| |
| { |
| 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 }; |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL); |
| } |
| |
| beginRenderPass(vk, *cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT)); |
| vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); |
| const VkDeviceSize offset = 0; |
| const VkBuffer buffer = m_vertexBuffer->object(); |
| vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset); |
| vk.cmdDraw(*cmdBuffer, DE_LENGTH_OF_ARRAY(vertices), 1, 0, 0); |
| endRenderPass(vk, *cmdBuffer); |
| |
| transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), aspectBits, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT , VK_ACCESS_MEMORY_READ_BIT, |
| VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT , VK_PIPELINE_STAGE_HOST_BIT); |
| |
| endCommandBuffer(vk, *cmdBuffer); |
| submitCommandsAndWait(vk, device, queue, *cmdBuffer); |
| |
| VK_CHECK(vk.queueWaitIdle(queue)); |
| |
| return m_depthTargetImage->readDepth(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { 0, 0, 0 }, WIDTH, HEIGHT, VK_IMAGE_ASPECT_DEPTH_BIT); |
| } |
| |
| tcu::TestStatus DepthClampTestInstance::iterate (void) |
| { |
| // Set up the viewport and draw |
| const VkViewport viewport = |
| { |
| 0.0f, // float x; |
| 0.0f, // float y; |
| WIDTH, // float width; |
| HEIGHT, // float height; |
| m_params.expectedValue < 0.0f ? m_params.expectedValue : 0.0f, // float minDepth; |
| m_params.expectedValue > 1.0f ? m_params.expectedValue : 1.0f, // float maxDepth; |
| }; |
| const tcu::ConstPixelBufferAccess resultImage = draw(viewport); |
| |
| DE_ASSERT((isUnormDepthFormat(m_format) == false) || |
| (m_params.expectedValue >= 0.0f && m_params.expectedValue <= 1.0f)); |
| |
| for(int z = 0; z < resultImage.getDepth(); ++z) |
| for(int y = 0; y < resultImage.getHeight(); ++y) |
| for(int x = 0; x < resultImage.getWidth(); ++x) |
| { |
| if (std::abs(m_params.expectedValue - resultImage.getPixDepth(x,y,z)) >= m_epsilon) |
| { |
| std::ostringstream msg; |
| msg << "Depth value mismatch, expected: " << m_params.expectedValue << ", got: " << resultImage.getPixDepth(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")"; |
| return tcu::TestStatus::fail(msg.str()); |
| } |
| } |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| class DepthClampTest : public TestCase |
| { |
| public: |
| DepthClampTest (tcu::TestContext &testCtx, const string& name, const string& description, const TestParams ¶ms, const VkFormat format, const float epsilon) |
| : TestCase (testCtx, name, description) |
| , m_params(params) |
| , m_format(format) |
| , m_epsilon(epsilon) |
| { |
| } |
| |
| virtual void initPrograms (SourceCollections& programCollection) const |
| { |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" |
| << "\n" |
| << "layout(location = 0) in vec4 in_position;\n" |
| << "\n" |
| << "out gl_PerVertex {\n" |
| << " vec4 gl_Position;\n" |
| << "};\n" |
| << "\n" |
| << "void main(void)\n" |
| << "{\n" |
| << " gl_Position = in_position;\n" |
| << "}\n"; |
| programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); |
| } |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" |
| << "\n" |
| << "void main(void)\n" |
| << "{\n" |
| << "}\n"; |
| programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); |
| } |
| } |
| |
| virtual void checkSupport (Context& context) const |
| { |
| context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_DEPTH_CLAMP); |
| for(const auto& extensionName : m_params.requiredExtensions) |
| { |
| context.requireDeviceFunctionality(extensionName); |
| } |
| VkImageFormatProperties imageFormatProperties; |
| const auto& vki = context.getInstanceInterface(); |
| const auto& vkd = context.getPhysicalDevice(); |
| const auto usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0u, &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED) |
| { |
| TCU_THROW(NotSupportedError, "Format not supported"); |
| } |
| } |
| |
| virtual TestInstance* createInstance (Context& context) const |
| { |
| return new DepthClampTestInstance(context, m_params, m_format, m_epsilon); |
| } |
| |
| private: |
| const TestParams m_params; |
| const VkFormat m_format; |
| const float m_epsilon; |
| }; |
| |
| std::string getFormatCaseName (VkFormat format) |
| { |
| return de::toLower(de::toString(getFormatStr(format)).substr(10)); |
| } |
| |
| void createTests (tcu::TestCaseGroup* testGroup) |
| { |
| for(int i = 0; i < DE_LENGTH_OF_ARRAY(depthStencilImageFormatsToTest); ++i) |
| { |
| const auto format = depthStencilImageFormatsToTest[i]; |
| const float epsilon = depthEpsilonValuesByFormat[i]; |
| const auto formatCaseName = getFormatCaseName(format); |
| for(const auto& params : depthClearValuesToTest) |
| { |
| if ((params.skipSNorm && vk::isSnormFormat(format)) || (params.skipUNorm && isUnormDepthFormat(format))) |
| continue; |
| const auto testCaseName = formatCaseName + params.testNameSuffix; |
| testGroup->addChild(new DepthClampTest(testGroup->getTestContext(), testCaseName, "Depth clamp", params, format, epsilon)); |
| } |
| } |
| } |
| } // anonymous |
| |
| tcu::TestCaseGroup* createDepthClampTests (tcu::TestContext& testCtx) |
| { |
| return createTestGroup(testCtx, "depth_clamp", "Depth Clamp Tests", createTests); |
| } |
| } // Draw |
| } // vkt |