| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2019 The Khronos Group Inc. |
| * Copyright (c) 2019 Valve Corporation. |
| * |
| * 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 VK_EXT_depth_range_unrestricted Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktPipelineDepthRangeUnrestrictedTests.hpp" |
| #include "vktPipelineVertexUtil.hpp" |
| #include "vktPipelineClearUtil.hpp" |
| #include "vktPipelineImageUtil.hpp" |
| #include "vktPipelineReferenceRenderer.hpp" |
| #include "vktTestCase.hpp" |
| #include "vktTestCaseUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "tcuImageCompare.hpp" |
| |
| #include <sstream> |
| #include <vector> |
| |
| namespace vkt |
| { |
| namespace pipeline |
| { |
| |
| using namespace vk; |
| |
| namespace |
| { |
| |
| enum testDynamicStaticMode |
| { |
| TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC = 0, |
| TEST_MODE_VIEWPORT_DYNAMIC = 1, |
| TEST_MODE_DEPTH_BOUNDS_DYNAMIC = 2, |
| TEST_MODE_VIEWPORT_DEPTH_BOUNDS_DYNAMIC = 3, |
| }; |
| |
| struct DepthRangeUnrestrictedParam |
| { |
| VkFormat depthFormat; |
| VkBool32 testClearValueOnly; |
| VkClearValue depthBufferClearValue; |
| VkBool32 depthClampEnable; |
| float wc; // Component W of the vertices |
| deUint32 viewportDepthBoundsMode; |
| float viewportMinDepth; |
| float viewportMaxDepth; |
| VkBool32 depthBoundsTestEnable; |
| float minDepthBounds; |
| float maxDepthBounds; |
| VkCompareOp depthCompareOp; |
| }; |
| |
| // helper functions |
| std::string getFormatCaseName (vk::VkFormat format) |
| { |
| return de::toLower(de::toString(getFormatStr(format)).substr(10)); |
| } |
| |
| std::string getCompareOpStringName (VkCompareOp compare) |
| { |
| return de::toLower(de::toString(getCompareOpStr(compare)).substr(3)); |
| } |
| |
| const std::string generateTestName (struct DepthRangeUnrestrictedParam param) |
| { |
| std::ostringstream result; |
| |
| result << getFormatCaseName(param.depthFormat).c_str(); |
| result << "_" << getCompareOpStringName(param.depthCompareOp).c_str(); |
| result << "_clear_value_" << (int) param.depthBufferClearValue.depthStencil.depth; |
| |
| if (param.depthClampEnable == VK_FALSE) |
| result << "_wc_" << (int) param.wc; |
| |
| if (param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC) |
| result << "_dynamic"; |
| result << "_viewport_min_" << (int)param.viewportMinDepth << "_max_" << (int)param.viewportMaxDepth; |
| |
| if (param.depthBoundsTestEnable) |
| { |
| if (param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC) |
| result << "_dynamic"; |
| result << "_boundstest_min" << (int)param.minDepthBounds << "_max_" << (int)param.maxDepthBounds; |
| } |
| |
| return result.str(); |
| } |
| |
| const std::string generateTestDescription (struct DepthRangeUnrestrictedParam param) |
| { |
| std::string result("Test unrestricted depth ranges on viewport"); |
| if (param.depthBoundsTestEnable) |
| result += " , depth bounds test"; |
| return result; |
| } |
| |
| deBool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format) |
| { |
| VkFormatProperties formatProps; |
| |
| instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps); |
| |
| return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0u; |
| } |
| |
| deBool isFloatingPointDepthFormat (VkFormat format) |
| { |
| switch (format) |
| { |
| case VK_FORMAT_D32_SFLOAT: |
| case VK_FORMAT_D32_SFLOAT_S8_UINT: |
| return DE_TRUE; |
| case VK_FORMAT_D24_UNORM_S8_UINT: |
| case VK_FORMAT_D16_UNORM_S8_UINT: |
| case VK_FORMAT_D16_UNORM: |
| return DE_FALSE; |
| default: |
| DE_FATAL("No depth format"); |
| }; |
| return DE_FALSE; |
| } |
| |
| deBool depthFormatHasStencilComponent (VkFormat format) |
| { |
| switch (format) |
| { |
| case VK_FORMAT_D32_SFLOAT_S8_UINT: |
| case VK_FORMAT_D24_UNORM_S8_UINT: |
| case VK_FORMAT_D16_UNORM_S8_UINT: |
| return DE_TRUE; |
| case VK_FORMAT_D32_SFLOAT: |
| case VK_FORMAT_D16_UNORM: |
| return DE_FALSE; |
| default: |
| DE_FATAL("No depth format"); |
| }; |
| return DE_FALSE; |
| } |
| |
| deBool compareDepthResult (VkCompareOp compare, float depth, float clearValue) |
| { |
| deBool result = DE_FALSE; |
| |
| DE_ASSERT(compare <= VK_COMPARE_OP_ALWAYS && compare >= VK_COMPARE_OP_NEVER); |
| |
| switch (compare) |
| { |
| case VK_COMPARE_OP_ALWAYS: |
| result = DE_TRUE; |
| break; |
| case VK_COMPARE_OP_NEVER: |
| result = DE_FALSE; |
| break; |
| case VK_COMPARE_OP_EQUAL: |
| result = depth == clearValue; |
| break; |
| case VK_COMPARE_OP_NOT_EQUAL: |
| result = depth != clearValue; |
| break; |
| case VK_COMPARE_OP_GREATER: |
| result = depth > clearValue; |
| break; |
| case VK_COMPARE_OP_GREATER_OR_EQUAL: |
| result = depth >= clearValue; |
| break; |
| case VK_COMPARE_OP_LESS: |
| result = depth < clearValue; |
| break; |
| case VK_COMPARE_OP_LESS_OR_EQUAL: |
| result = depth <= clearValue; |
| break; |
| default: |
| result = false; |
| break; |
| }; |
| return result; |
| } |
| |
| static inline std::vector<Vertex4RGBA> createPoints (float wc) |
| { |
| using tcu::Vec2; |
| using tcu::Vec4; |
| |
| std::vector<Vertex4RGBA> vertices; |
| |
| // Vertices are in the following positions of the image: |
| // |
| // ---------------------------------- |
| // | | |
| // | | |
| // | 5 6 | |
| // | | |
| // | 1 2 | |
| // | | |
| // | | |
| // | 3 0 | |
| // | | |
| // | 7 4 | |
| // | | |
| // | | |
| // ---------------------------------- |
| // |
| // Vertex Depth Color |
| // 0 0.0 white |
| // 1 0.25 magenta |
| // 2 -2.0 yellow |
| // 3 2.0 red |
| // 4 -5.0 black |
| // 5 5.0 cyan |
| // 6 10.0 blue |
| // 7 -10.0 green |
| // Depth values are constant, they don't depend on wc. |
| const Vertex4RGBA vertex0 = |
| { |
| Vec4(0.25f * wc, 0.25f * wc, 0.0f, wc), |
| Vec4(1.0f, 1.0f, 1.0f, 1.0) |
| }; |
| const Vertex4RGBA vertex1 = |
| { |
| Vec4(-0.25f * wc, -0.25f * wc, 0.25f, wc), |
| Vec4(1.0f, 0.0f, 1.0f, 1.0) |
| }; |
| const Vertex4RGBA vertex2 = |
| { |
| Vec4(0.25f * wc, -0.25f * wc, -2.0f, wc), |
| Vec4(1.0f, 1.0f, 0.0f, 1.0) |
| }; |
| const Vertex4RGBA vertex3 = |
| { |
| Vec4(-0.25f * wc, 0.25f * wc, 2.0f, wc), |
| Vec4(1.0f, 0.0f, 0.0f, 1.0) |
| }; |
| const Vertex4RGBA vertex4 = |
| { |
| Vec4(0.5f * wc, 0.5f * wc, -5.0f, wc), |
| Vec4(0.0f, 0.0f, 0.0f, 1.0) |
| }; |
| const Vertex4RGBA vertex5 = |
| { |
| Vec4(-0.5f * wc, -0.5f * wc, 5.0f, wc), |
| Vec4(0.0f, 1.0f, 1.0f, 1.0) |
| }; |
| const Vertex4RGBA vertex6 = |
| { |
| Vec4(0.5f * wc, -0.5f * wc, 10.0f, wc), |
| Vec4(0.0f, 0.0f, 1.0f, 1.0) |
| }; |
| |
| const Vertex4RGBA vertex7 = |
| { |
| Vec4(-0.5f * wc, 0.5f * wc, -10.0f, wc), |
| Vec4(0.0f, 1.0f, 0.0f, 1.0) |
| }; |
| |
| vertices.push_back(vertex0); |
| vertices.push_back(vertex1); |
| vertices.push_back(vertex2); |
| vertices.push_back(vertex3); |
| vertices.push_back(vertex4); |
| vertices.push_back(vertex5); |
| vertices.push_back(vertex6); |
| vertices.push_back(vertex7); |
| |
| return vertices; |
| } |
| |
| template <class Test> |
| vkt::TestCase* newTestCase (tcu::TestContext& testContext, |
| const DepthRangeUnrestrictedParam testParam) |
| { |
| return new Test(testContext, |
| generateTestName(testParam).c_str(), |
| generateTestDescription(testParam).c_str(), |
| testParam); |
| } |
| |
| Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc) |
| { |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| |
| const VkBufferCreateInfo vertexBufferParams = |
| { |
| VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkBufferCreateFlags flags; |
| size, // VkDeviceSize size; |
| usage, // VkBufferUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex // const deUint32* pQueueFamilyIndices; |
| }; |
| |
| Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); |
| |
| *pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible); |
| VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset())); |
| |
| return vertexBuffer; |
| } |
| |
| Move<VkImage> createImage2DAndBindMemory (Context& context, |
| VkFormat format, |
| deUint32 width, |
| deUint32 height, |
| VkImageUsageFlags usage, |
| VkSampleCountFlagBits sampleCount, |
| de::details::MovePtr<Allocation>* pAlloc) |
| { |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice vkDevice = context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| |
| const VkImageCreateInfo colorImageParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageCreateFlags flags; |
| VK_IMAGE_TYPE_2D, // VkImageType imageType; |
| format, // VkFormat format; |
| { width, height, 1u }, // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| 1u, // deUint32 arraySize; |
| sampleCount, // deUint32 samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| usage, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams); |
| |
| *pAlloc = context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any); |
| VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset())); |
| |
| return image; |
| } |
| Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, |
| const VkDevice device, |
| const VkFormat colorFormat, |
| const VkFormat depthStencilFormat, |
| const VkAttachmentLoadOp loadOperationColor, |
| const VkAttachmentLoadOp loadOperationDepthStencil) |
| { |
| const bool hasColor = colorFormat != VK_FORMAT_UNDEFINED; |
| const bool hasDepthStencil = depthStencilFormat != VK_FORMAT_UNDEFINED; |
| const VkImageLayout initialLayoutColor = loadOperationColor == VK_ATTACHMENT_LOAD_OP_LOAD ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED; |
| const VkImageLayout initialLayoutDepthStencil = loadOperationDepthStencil == VK_ATTACHMENT_LOAD_OP_LOAD ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED; |
| |
| const VkAttachmentDescription colorAttachmentDescription = |
| { |
| (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags |
| colorFormat, // VkFormat format |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| loadOperationColor, // VkAttachmentLoadOp loadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp |
| VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp |
| initialLayoutColor, // VkImageLayout initialLayout |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout |
| }; |
| |
| const VkAttachmentDescription depthStencilAttachmentDescription = |
| { |
| (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags |
| depthStencilFormat, // VkFormat format |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples |
| loadOperationDepthStencil, // VkAttachmentLoadOp loadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp |
| loadOperationDepthStencil, // VkAttachmentLoadOp stencilLoadOp |
| VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp |
| initialLayoutDepthStencil, // VkImageLayout initialLayout |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout |
| }; |
| |
| std::vector<VkAttachmentDescription> attachmentDescriptions; |
| |
| if (hasColor) |
| attachmentDescriptions.push_back(colorAttachmentDescription); |
| if (hasDepthStencil) |
| attachmentDescriptions.push_back(depthStencilAttachmentDescription); |
| |
| const VkAttachmentReference colorAttachmentRef = |
| { |
| 0u, // deUint32 attachment |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout |
| }; |
| |
| const VkAttachmentReference depthStencilAttachmentRef = |
| { |
| hasColor ? 1u : 0u, // deUint32 attachment |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout |
| }; |
| |
| const VkSubpassDescription subpassDescription = |
| { |
| (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags |
| VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint |
| 0u, // deUint32 inputAttachmentCount |
| DE_NULL, // const VkAttachmentReference* pInputAttachments |
| hasColor ? 1u : 0u, // deUint32 colorAttachmentCount |
| hasColor ? &colorAttachmentRef : DE_NULL, // const VkAttachmentReference* pColorAttachments |
| DE_NULL, // const VkAttachmentReference* pResolveAttachments |
| hasDepthStencil ? &depthStencilAttachmentRef : DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment |
| 0u, // deUint32 preserveAttachmentCount |
| DE_NULL // const deUint32* pPreserveAttachments |
| }; |
| |
| const VkRenderPassCreateInfo renderPassInfo = |
| { |
| VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType |
| DE_NULL, // const void* pNext |
| (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags |
| (deUint32)attachmentDescriptions.size(), // deUint32 attachmentCount |
| attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] : DE_NULL, // const VkAttachmentDescription* pAttachments |
| 1u, // deUint32 subpassCount |
| &subpassDescription, // const VkSubpassDescription* pSubpasses |
| 0u, // deUint32 dependencyCount |
| DE_NULL // const VkSubpassDependency* pDependencies |
| }; |
| |
| return createRenderPass(vk, device, &renderPassInfo, DE_NULL); |
| } |
| |
| // Test Classes |
| class DepthRangeUnrestrictedTestInstance : public vkt::TestInstance |
| { |
| public: |
| DepthRangeUnrestrictedTestInstance (Context& context, |
| const DepthRangeUnrestrictedParam param); |
| virtual ~DepthRangeUnrestrictedTestInstance (void); |
| virtual tcu::TestStatus iterate (void); |
| protected: |
| void prepareRenderPass (VkRenderPass renderPass, VkFramebuffer framebuffer, VkPipeline pipeline); |
| void prepareCommandBuffer (void); |
| Move<VkPipeline> buildPipeline (VkRenderPass renderpass); |
| void bindShaderStage (VkShaderStageFlagBits stage, |
| const char* sourceName, |
| const char* entryName); |
| tcu::TestStatus verifyTestResult (void); |
| protected: |
| const DepthRangeUnrestrictedParam m_param; |
| deBool m_extensions; |
| const tcu::UVec2 m_renderSize; |
| const VkFormat m_colorFormat; |
| Move<VkPipelineLayout> m_pipelineLayout; |
| |
| Move<VkImage> m_depthImage; |
| de::MovePtr<Allocation> m_depthImageAlloc; |
| de::MovePtr<Allocation> m_colorImageAlloc; |
| Move<VkImageView> m_depthAttachmentView; |
| VkImageMemoryBarrier m_imageLayoutBarriers[2]; |
| |
| Move<VkBuffer> m_vertexBuffer; |
| de::MovePtr<Allocation> m_vertexBufferMemory; |
| std::vector<Vertex4RGBA> m_vertices; |
| |
| Move<VkRenderPass> m_renderPass; |
| Move<VkCommandPool> m_cmdPool; |
| Move<VkCommandBuffer> m_cmdBuffer; |
| Move<VkImage> m_colorImage; |
| Move<VkImageView> m_colorAttachmentView; |
| Move<VkFramebuffer> m_framebuffer; |
| Move<VkPipeline> m_pipeline; |
| |
| Move<VkShaderModule> m_shaderModules[2]; |
| deUint32 m_shaderStageCount; |
| VkPipelineShaderStageCreateInfo m_shaderStageInfo[2]; |
| }; |
| |
| void DepthRangeUnrestrictedTestInstance::bindShaderStage (VkShaderStageFlagBits stage, |
| const char* sourceName, |
| const char* entryName) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| |
| // Create shader module |
| deUint32* code = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary(); |
| deUint32 codeSize = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize(); |
| |
| const VkShaderModuleCreateInfo moduleCreateInfo = |
| { |
| VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkShaderModuleCreateFlags flags; |
| codeSize, // deUintptr codeSize; |
| code, // const deUint32* pCode; |
| }; |
| |
| m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo); |
| |
| // Prepare shader stage info |
| m_shaderStageInfo[m_shaderStageCount].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; |
| m_shaderStageInfo[m_shaderStageCount].pNext = DE_NULL; |
| m_shaderStageInfo[m_shaderStageCount].flags = 0u; |
| m_shaderStageInfo[m_shaderStageCount].stage = stage; |
| m_shaderStageInfo[m_shaderStageCount].module = *m_shaderModules[m_shaderStageCount]; |
| m_shaderStageInfo[m_shaderStageCount].pName = entryName; |
| m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL; |
| |
| m_shaderStageCount++; |
| } |
| |
| Move<VkPipeline> DepthRangeUnrestrictedTestInstance::buildPipeline (VkRenderPass renderPass) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| |
| // Create pipeline |
| const VkVertexInputBindingDescription vertexInputBindingDescription = |
| { |
| 0u, // deUint32 binding; |
| sizeof(Vertex4RGBA), // deUint32 strideInBytes; |
| VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; |
| }; |
| |
| const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = |
| { |
| { |
| 0u, // deUint32 location; |
| 0u, // deUint32 binding; |
| VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; |
| 0u // deUint32 offsetInBytes; |
| }, |
| { |
| 1u, // deUint32 location; |
| 0u, // deUint32 binding; |
| VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; |
| DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes; |
| } |
| }; |
| |
| const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineVertexInputStateCreateFlags flags; |
| 1u, // deUint32 vertexBindingDescriptionCount; |
| &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; |
| 2u, // deUint32 vertexAttributeDescriptionCount; |
| vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; |
| }; |
| |
| const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineInputAssemblyStateCreateFlags flags; |
| VK_PRIMITIVE_TOPOLOGY_POINT_LIST, // VkPrimitiveTopology topology; |
| VK_FALSE, // VkBool32 primitiveRestartEnable; |
| }; |
| |
| const VkRect2D scissor = makeRect2D(m_renderSize); |
| VkViewport viewport = makeViewport(m_renderSize); |
| |
| if (!(m_param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC)) |
| { |
| viewport.minDepth = m_param.viewportMinDepth; |
| viewport.maxDepth = m_param.viewportMaxDepth; |
| } |
| |
| const VkPipelineViewportStateCreateInfo viewportStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineViewportStateCreateFlags flags; |
| 1u, // deUint32 viewportCount; |
| &viewport, // const VkViewport* pViewports; |
| 1u, // deUint32 scissorCount; |
| &scissor // const VkRect2D* pScissors; |
| }; |
| |
| const VkPipelineRasterizationStateCreateInfo rasterStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineRasterizationStateCreateFlags flags; |
| m_param.depthClampEnable, // VkBool32 depthClampEnable; |
| VK_FALSE, // VkBool32 rasterizerDiscardEnable; |
| VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; |
| VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; |
| VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; |
| VK_FALSE, // VkBool32 depthBiasEnable; |
| 0.0f, // float depthBiasConstantFactor; |
| 0.0f, // float depthBiasClamp; |
| 0.0f, // float depthBiasSlopeFactor; |
| 1.0f, // float lineWidth; |
| }; |
| |
| const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = |
| { |
| VK_FALSE, // VkBool32 blendEnable; |
| VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; |
| VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; |
| VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; |
| VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; |
| VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; |
| VK_COLOR_COMPONENT_R_BIT | |
| VK_COLOR_COMPONENT_G_BIT | |
| VK_COLOR_COMPONENT_B_BIT | |
| VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask; |
| }; |
| |
| const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineColorBlendStateCreateFlags flags; |
| VK_FALSE, // VkBool32 logicOpEnable; |
| VK_LOGIC_OP_COPY, // VkLogicOp logicOp; |
| 1u, // deUint32 attachmentCount; |
| &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; |
| { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4]; |
| }; |
| |
| const VkPipelineMultisampleStateCreateInfo multisampleStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineMultisampleStateCreateFlags flags; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; |
| VK_FALSE, // VkBool32 sampleShadingEnable; |
| 0.0f, // float minSampleShading; |
| DE_NULL, // const VkSampleMask* pSampleMask; |
| VK_FALSE, // VkBool32 alphaToCoverageEnable; |
| VK_FALSE, // VkBool32 alphaToOneEnable; |
| }; |
| |
| float minDepthBounds = m_param.minDepthBounds; |
| float maxDepthBounds = m_param.maxDepthBounds; |
| |
| if (m_param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC) |
| { |
| minDepthBounds = 0.0f; |
| maxDepthBounds = 1.0f; |
| } |
| |
| VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineDepthStencilStateCreateFlags flags; |
| VK_TRUE, // VkBool32 depthTestEnable; |
| VK_TRUE, // VkBool32 depthWriteEnable; |
| m_param.depthCompareOp, // VkCompareOp depthCompareOp; |
| m_param.depthBoundsTestEnable, // VkBool32 depthBoundsTestEnable; |
| VK_FALSE, // VkBool32 stencilTestEnable; |
| // VkStencilOpState front; |
| { |
| VK_STENCIL_OP_KEEP, // VkStencilOp failOp; |
| VK_STENCIL_OP_KEEP, // VkStencilOp passOp; |
| VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; |
| VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; |
| 0u, // deUint32 compareMask; |
| 0u, // deUint32 writeMask; |
| 0u, // deUint32 reference; |
| }, |
| // VkStencilOpState back; |
| { |
| VK_STENCIL_OP_KEEP, // VkStencilOp failOp; |
| VK_STENCIL_OP_KEEP, // VkStencilOp passOp; |
| VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp; |
| VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; |
| 0u, // deUint32 compareMask; |
| 0u, // deUint32 writeMask; |
| 0u, // deUint32 reference; |
| }, |
| minDepthBounds, // float minDepthBounds; |
| maxDepthBounds, // float maxDepthBounds; |
| }; |
| |
| std::vector<VkDynamicState> dynamicStates; |
| if (m_param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC) |
| dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT); |
| if (m_param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC) |
| dynamicStates.push_back(VK_DYNAMIC_STATE_DEPTH_BOUNDS); |
| |
| const VkPipelineDynamicStateCreateInfo dynamicStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkPipelineDynamicStateCreateFlags)0u, // VkPipelineDynamicStateCreateFlags flags; |
| (deUint32)dynamicStates.size(), // deUint32 dynamicStateCount; |
| (const VkDynamicState*)dynamicStates.data() // const VkDynamicState* pDynamicStates; |
| }; |
| |
| const VkGraphicsPipelineCreateInfo graphicsPipelineParams = |
| { |
| VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineCreateFlags flags; |
| m_shaderStageCount, // deUint32 stageCount; |
| m_shaderStageInfo, // const VkPipelineShaderStageCreateInfo* pStages; |
| &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; |
| &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; |
| DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; |
| &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; |
| &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterState; |
| &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; |
| &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; |
| &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; |
| &dynamicStateParams, // const VkPipelineDynamicStateCreateInfo* pDynamicState; |
| *m_pipelineLayout, // VkPipelineLayout layout; |
| renderPass, // VkRenderPass renderPass; |
| 0u, // deUint32 subpass; |
| DE_NULL, // VkPipeline basePipelineHandle; |
| 0u, // deInt32 basePipelineIndex; |
| }; |
| |
| return createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); |
| } |
| |
| void DepthRangeUnrestrictedTestInstance::prepareRenderPass (VkRenderPass renderPass, VkFramebuffer framebuffer, VkPipeline pipeline) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| |
| const VkClearValue attachmentClearValues[2] = |
| { |
| defaultClearValue(m_colorFormat), |
| m_param.depthBufferClearValue, |
| }; |
| |
| beginRenderPass(vk, *m_cmdBuffer, renderPass, framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u, attachmentClearValues); |
| |
| vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); |
| VkDeviceSize offsets = 0u; |
| vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets); |
| |
| if (m_param.viewportDepthBoundsMode & TEST_MODE_VIEWPORT_DYNAMIC) |
| { |
| VkViewport viewport = makeViewport(m_renderSize); |
| viewport.minDepth = m_param.viewportMinDepth; |
| viewport.maxDepth = m_param.viewportMaxDepth; |
| vk.cmdSetViewport(*m_cmdBuffer, 0u, 1u, &viewport); |
| } |
| |
| if (m_param.viewportDepthBoundsMode & TEST_MODE_DEPTH_BOUNDS_DYNAMIC) |
| vk.cmdSetDepthBounds(*m_cmdBuffer, m_param.minDepthBounds, m_param.maxDepthBounds); |
| |
| if (!m_vertices.empty() && !m_param.testClearValueOnly) |
| vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u); |
| |
| endRenderPass(vk, *m_cmdBuffer); |
| } |
| |
| void DepthRangeUnrestrictedTestInstance::prepareCommandBuffer (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| |
| beginCommandBuffer(vk, *m_cmdBuffer, 0u); |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0, |
| 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers), m_imageLayoutBarriers); |
| |
| prepareRenderPass(*m_renderPass, *m_framebuffer, *m_pipeline); |
| |
| endCommandBuffer(vk, *m_cmdBuffer); |
| } |
| |
| DepthRangeUnrestrictedTestInstance::DepthRangeUnrestrictedTestInstance (Context& context, |
| const DepthRangeUnrestrictedParam param) |
| : TestInstance (context) |
| , m_param (param) |
| , m_extensions (m_context.requireDeviceFunctionality("VK_EXT_depth_range_unrestricted")) |
| , m_renderSize (tcu::UVec2(32,32)) |
| , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) |
| , m_shaderStageCount (0) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| |
| if (!isSupportedDepthStencilFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), param.depthFormat)) |
| { |
| throw tcu::NotSupportedError("Unsupported depth format"); |
| } |
| |
| VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures(); |
| if (param.depthClampEnable && features.depthClamp == DE_FALSE) |
| { |
| throw tcu::NotSupportedError("Unsupported feature: depthClamp"); |
| } |
| |
| if (param.depthBoundsTestEnable && features.depthBounds == DE_FALSE) |
| { |
| throw tcu::NotSupportedError("Unsupported feature: depthBounds"); |
| } |
| |
| // Create vertex buffer |
| { |
| m_vertexBuffer = createBufferAndBindMemory(m_context, 1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory); |
| m_vertices = createPoints(m_param.wc); |
| // Load vertices into vertex buffer |
| deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA)); |
| flushAlloc(vk, vkDevice, *m_vertexBufferMemory); |
| } |
| |
| // Create render pass |
| m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_param.depthFormat, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR); |
| |
| const VkComponentMapping ComponentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; |
| // Create color image |
| { |
| m_colorImage = createImage2DAndBindMemory(m_context, |
| m_colorFormat, |
| m_renderSize.x(), |
| m_renderSize.y(), |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, |
| VK_SAMPLE_COUNT_1_BIT, |
| &m_colorImageAlloc); |
| } |
| |
| // Create depth image |
| { |
| m_depthImage = createImage2DAndBindMemory(m_context, |
| m_param.depthFormat, |
| m_renderSize.x(), |
| m_renderSize.y(), |
| VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, |
| VK_SAMPLE_COUNT_1_BIT, |
| &m_depthImageAlloc); |
| } |
| |
| deUint32 depthAspectBits = VK_IMAGE_ASPECT_DEPTH_BIT; |
| if (depthFormatHasStencilComponent(param.depthFormat)) |
| depthAspectBits |= VK_IMAGE_ASPECT_STENCIL_BIT; |
| |
| // Set up image layout transition barriers |
| { |
| VkImageMemoryBarrier colorImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_colorImage, // VkImage image; |
| { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| m_imageLayoutBarriers[0] = colorImageBarrier; |
| |
| VkImageMemoryBarrier depthImageBarrier = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkAccessFlags srcAccessMask; |
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; |
| VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; |
| *m_depthImage, // VkImage image; |
| { depthAspectBits, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| m_imageLayoutBarriers[1] = depthImageBarrier; |
| } |
| // Create color attachment view |
| { |
| VkImageViewCreateInfo colorAttachmentViewParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageViewCreateFlags flags; |
| *m_colorImage, // VkImage image; |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; |
| m_colorFormat, // VkFormat format; |
| ComponentMappingRGBA, // VkComponentMapping components; |
| { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); |
| } |
| |
| // Create depth attachment view |
| { |
| const VkImageViewCreateInfo depthAttachmentViewParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageViewCreateFlags flags; |
| *m_depthImage, // VkImage image; |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; |
| m_param.depthFormat, // VkFormat format; |
| ComponentMappingRGBA, // VkComponentMapping components; |
| { depthAspectBits, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams); |
| } |
| |
| // Create framebuffer |
| { |
| VkImageView attachmentBindInfos[2] = |
| { |
| *m_colorAttachmentView, |
| *m_depthAttachmentView, |
| }; |
| |
| const VkFramebufferCreateInfo framebufferParams = |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkFramebufferCreateFlags flags; |
| *m_renderPass, // VkRenderPass renderPass; |
| 2u, // deUint32 attachmentCount; |
| attachmentBindInfos, // const VkImageView* pAttachments; |
| (deUint32)m_renderSize.x(), // deUint32 width; |
| (deUint32)m_renderSize.y(), // deUint32 height; |
| 1u, // deUint32 layers; |
| }; |
| |
| m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); |
| } |
| |
| // Bind shader stages |
| { |
| bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "vert", "main"); |
| bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "frag", "main"); |
| } |
| |
| // Create pipeline layout |
| { |
| const VkPipelineLayoutCreateInfo pipelineLayoutParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkPipelineLayoutCreateFlags flags; |
| 0u, // deUint32 setLayoutCount; |
| DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; |
| 0u, // deUint32 pushConstantRangeCount; |
| DE_NULL // const VkPushConstantRange* pPushConstantRanges; |
| }; |
| |
| m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); |
| } |
| |
| // Create pipeline |
| m_pipeline = buildPipeline(*m_renderPass); |
| |
| // Create command pool |
| m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex); |
| |
| // Create command buffer |
| m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| } |
| |
| DepthRangeUnrestrictedTestInstance::~DepthRangeUnrestrictedTestInstance (void) |
| { |
| } |
| |
| tcu::TestStatus DepthRangeUnrestrictedTestInstance::iterate (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| prepareCommandBuffer(); |
| |
| submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); |
| return verifyTestResult(); |
| } |
| |
| tcu::TestStatus DepthRangeUnrestrictedTestInstance::verifyTestResult (void) |
| { |
| deBool compareOk = DE_TRUE; |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| Allocator& allocator = m_context.getDefaultAllocator(); |
| tcu::TextureLevel refImage (vk::mapVkFormat(m_colorFormat), 32, 32); |
| float clearValue = m_param.depthBufferClearValue.depthStencil.depth; |
| double epsilon = 1e-5; |
| |
| // For non-float depth formats, the value in the depth buffer is already clampled to the range [0, 1], which |
| // includes the clear depth value. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| clearValue = de::min(de::max(clearValue, 0.0f), 1.0f); |
| |
| // Generate reference image |
| { |
| VkClearValue clearColor = defaultClearValue(m_colorFormat); |
| tcu::Vec4 clearColorVec4 (clearColor.color.float32[0], clearColor.color.float32[1], |
| clearColor.color.float32[2], clearColor.color.float32[3]); |
| |
| tcu::clear(refImage.getAccess(), clearColorVec4); |
| for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex) |
| { |
| if (m_param.depthClampEnable == VK_FALSE && (vertex->position.z() < 0.0f || vertex->position.z() > vertex->position.w())) |
| continue; |
| |
| if (m_param.testClearValueOnly) |
| continue; |
| |
| // Depth Clamp is enabled, then we clamp point depth to viewport's maxDepth and minDepth values, or [0.0f, 1.0f] is depth format is fixed-point. |
| float scaling = ((vertex->position.z() / vertex->position.w()) * (m_param.viewportMaxDepth - m_param.viewportMinDepth)) + m_param.viewportMinDepth; |
| float depth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth); |
| |
| // For non-float depth formats, depth value is clampled to the range [0, 1]. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| depth = de::min(de::max(depth, 0.0f), 1.0f); |
| |
| if (compareDepthResult(m_param.depthCompareOp, depth, clearValue)) |
| { |
| deInt32 x = static_cast<deInt32>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.x() - 1)); |
| deInt32 y = static_cast<deInt32>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.y() - 1)); |
| refImage.getAccess().setPixel(vertex->color, x, y); |
| } |
| } |
| } |
| |
| // Check the rendered image |
| { |
| de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize); |
| |
| compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(), |
| "IntImageCompare", |
| "Image comparison", |
| refImage.getAccess(), |
| result->getAccess(), |
| tcu::UVec4(2, 2, 2, 2), |
| tcu::IVec3(1, 1, 0), |
| true, |
| tcu::COMPARE_LOG_RESULT); |
| if (!compareOk) |
| return tcu::TestStatus::fail("Image mismatch"); |
| } |
| |
| // Check depth buffer contents |
| { |
| de::MovePtr<tcu::TextureLevel> depthResult = readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_param.depthFormat, m_renderSize); |
| |
| if (m_param.testClearValueOnly) { |
| compareOk = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), |
| "DepthImagecompare", |
| "Depth image comparison", |
| tcu::Vec4(clearValue, 0.0f, 0.0f, 1.0f), |
| depthResult->getAccess(), |
| tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), |
| tcu::COMPARE_LOG_RESULT); |
| if (!compareOk) |
| return tcu::TestStatus::fail("Depth buffer mismatch"); |
| else |
| return tcu::TestStatus::pass("Result images matches references"); |
| } |
| |
| log << tcu::TestLog::Message; |
| for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex) |
| { |
| deInt32 x = static_cast<deInt32>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.x() - 1)); |
| deInt32 y = static_cast<deInt32>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.y() - 1)); |
| tcu::Vec4 depth = depthResult->getAccess().getPixel(x, y); |
| |
| // Check depth values are valid |
| if (depth.y() != 0.0f || depth.z() != 0.0f || depth.w() != 1.0f) |
| { |
| log << tcu::TestLog::Message << "Invalid depth buffer values for pixel (" << x << ", " << y << ") = (" |
| << depth.x() << ", " << depth.y() << ", " << depth.z() << ", " << depth.w() << "." << tcu::TestLog::EndMessage; |
| compareOk = DE_FALSE; |
| } |
| |
| // Check the case where depth clamping is disabled. |
| if (m_param.depthClampEnable == VK_FALSE) |
| { |
| if ((vertex->position.z() < 0.0f || vertex->position.z() > vertex->position.w()) && |
| fabs(clearValue - depth.x()) > epsilon) |
| { |
| log << tcu::TestLog::Message << "Error pixel (" << x << ", " << y << "). Depth value = " << depth |
| << ", expected " << clearValue << "." << tcu::TestLog::EndMessage; |
| compareOk = DE_FALSE; |
| } |
| |
| float expectedDepth = clearValue; |
| |
| if (vertex->position.z() <= vertex->position.w() && vertex->position.z() >= 0.0f) |
| { |
| // Assert we have a symmetric range around zero. |
| DE_ASSERT(m_param.viewportMinDepth == (-m_param.viewportMaxDepth)); |
| |
| // Calculate the expected depth value: first translate the value to from [0.0f, 1.0f] to [-1.0f, 1.0f]. |
| expectedDepth = 2 * (vertex->position.z() / vertex->position.w()) - 1.0f; |
| // Now multiply by m_param.viewportMaxDepth to get the expected value. |
| expectedDepth *= m_param.viewportMaxDepth; |
| } |
| |
| // For non-float depth formats, depth value is clampled to the range [0, 1]. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| expectedDepth = de::min(de::max(expectedDepth, 0.0f), 1.0f); |
| |
| expectedDepth = compareDepthResult(m_param.depthCompareOp, expectedDepth, clearValue) ? expectedDepth : clearValue; |
| |
| if (fabs(expectedDepth - depth.x()) > epsilon) |
| { |
| log << tcu::TestLog::Message << "Error pixel (" << x << ", " << y |
| << "). Depth value " << depth.x() << ", expected " << expectedDepth << ", error " << fabs(expectedDepth - depth.x()) << tcu::TestLog::EndMessage; |
| compareOk = DE_FALSE; |
| } |
| |
| continue; |
| } |
| |
| // Depth Clamp is enabled, then we clamp point depth to viewport's maxDepth and minDepth values, or 0.0f and 1.0f is format is not float. |
| float scaling = (vertex->position.z() / vertex->position.w()) * (m_param.viewportMaxDepth - m_param.viewportMinDepth) + m_param.viewportMinDepth; |
| float expectedDepth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth); |
| |
| // For non-float depth formats, depth value is clampled to the range [0, 1]. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| expectedDepth = de::min(de::max(expectedDepth, 0.0f), 1.0f); |
| |
| expectedDepth = compareDepthResult(m_param.depthCompareOp, expectedDepth, clearValue) ? expectedDepth : clearValue; |
| |
| if (fabs(expectedDepth - depth.x()) > epsilon) |
| { |
| log << tcu::TestLog::Message << "Error pixel (" << x << ", " << y |
| << "). Depth value " << depth.x() << ", expected " << expectedDepth << ", error " << fabs(expectedDepth - depth.x()) << tcu::TestLog::EndMessage; |
| compareOk = DE_FALSE; |
| } |
| } |
| |
| if (!compareOk) |
| return tcu::TestStatus::fail("Depth buffer mismatch"); |
| } |
| |
| return tcu::TestStatus::pass("Result images matches references"); |
| } |
| |
| // Test Classes |
| class DepthBoundsRangeUnrestrictedTestInstance : public DepthRangeUnrestrictedTestInstance |
| { |
| public: |
| DepthBoundsRangeUnrestrictedTestInstance (Context& context, |
| const DepthRangeUnrestrictedParam param); |
| virtual ~DepthBoundsRangeUnrestrictedTestInstance (void); |
| virtual tcu::TestStatus iterate (void); |
| |
| protected: |
| tcu::TestStatus verifyTestResult (bool firstDraw); |
| void prepareCommandBuffer (bool firstDraw); |
| |
| protected: |
| Move<VkRenderPass> m_renderPassSecondDraw; |
| Move<VkFramebuffer> m_framebufferSecondDraw; |
| Move<VkPipeline> m_pipelineSecondDraw; |
| std::vector<bool> m_vertexWasRendered; |
| |
| }; |
| |
| DepthBoundsRangeUnrestrictedTestInstance::DepthBoundsRangeUnrestrictedTestInstance (Context& context, |
| const DepthRangeUnrestrictedParam param) |
| : DepthRangeUnrestrictedTestInstance(context, param) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| |
| // Create render pass for second draw, we keep the first draw's contents of the depth buffer. |
| m_renderPassSecondDraw = makeRenderPass(vk, vkDevice, m_colorFormat, m_param.depthFormat, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_LOAD); |
| |
| // Create framebuffer for second draw. |
| { |
| VkImageView attachmentBindInfos[2] = |
| { |
| *m_colorAttachmentView, |
| *m_depthAttachmentView, |
| }; |
| |
| const VkFramebufferCreateInfo framebufferParams = |
| { |
| VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkFramebufferCreateFlags flags; |
| *m_renderPassSecondDraw, // VkRenderPass renderPass; |
| 2u, // deUint32 attachmentCount; |
| attachmentBindInfos, // const VkImageView* pAttachments; |
| (deUint32)m_renderSize.x(), // deUint32 width; |
| (deUint32)m_renderSize.y(), // deUint32 height; |
| 1u, // deUint32 layers; |
| }; |
| |
| m_framebufferSecondDraw = createFramebuffer(vk, vkDevice, &framebufferParams); |
| } |
| |
| // Create pipeline |
| m_pipelineSecondDraw = buildPipeline(*m_renderPassSecondDraw); |
| } |
| |
| DepthBoundsRangeUnrestrictedTestInstance::~DepthBoundsRangeUnrestrictedTestInstance (void) |
| { |
| } |
| |
| tcu::TestStatus DepthBoundsRangeUnrestrictedTestInstance::iterate (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| // This test will draw the same scene two times. |
| // First one will render the points depending on if the pass the depth test and if clear depth value passes the |
| // depthBounds test. |
| // |
| // The second one, will render the same scene but the the point positions will have depth buffer values from |
| // the first draw. If they pass the depth test, the depthBounds test will check the content of the depth buffer, |
| // which is most cases, will make that the second result differs from the first one, hence the need to split |
| // the verification in two steps. |
| prepareCommandBuffer(true); |
| submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); |
| tcu::TestStatus status = verifyTestResult(true); |
| if (status.getCode() != QP_TEST_RESULT_PASS) |
| return status; |
| |
| prepareCommandBuffer(false); |
| submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); |
| return verifyTestResult(false); |
| } |
| |
| void DepthBoundsRangeUnrestrictedTestInstance::prepareCommandBuffer (bool firstDraw) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| |
| if (!firstDraw) |
| { |
| vk.resetCommandBuffer(*m_cmdBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); |
| // Color image layout changed after verifying the first draw call, restore it. |
| m_imageLayoutBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| m_imageLayoutBarriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| // Depth image layout changed after verifying the first draw call, restore it. |
| m_imageLayoutBarriers[1].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| m_imageLayoutBarriers[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; |
| } |
| |
| beginCommandBuffer(vk, *m_cmdBuffer, 0u); |
| |
| vk.cmdPipelineBarrier(*m_cmdBuffer, (firstDraw ? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT : VK_PIPELINE_STAGE_TRANSFER_BIT), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0, |
| 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers), m_imageLayoutBarriers); |
| |
| prepareRenderPass((firstDraw ? *m_renderPass : *m_renderPassSecondDraw), |
| (firstDraw ? *m_framebuffer : *m_framebufferSecondDraw), |
| (firstDraw ? *m_pipeline : *m_pipelineSecondDraw)); |
| |
| endCommandBuffer(vk, *m_cmdBuffer); |
| } |
| |
| tcu::TestStatus DepthBoundsRangeUnrestrictedTestInstance::verifyTestResult (bool firstDraw) |
| { |
| deBool compareOk = DE_TRUE; |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| tcu::TestLog& log = m_context.getTestContext().getLog(); |
| Allocator& allocator = m_context.getDefaultAllocator(); |
| tcu::TextureLevel refImage (vk::mapVkFormat(m_colorFormat), 32, 32); |
| float clearValue = m_param.depthBufferClearValue.depthStencil.depth; |
| double epsilon = 1e-5; |
| |
| // For non-float depth formats, depth value is clampled to the range [0, 1]. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| clearValue = de::min(de::max(clearValue, 0.0f), 1.0f); |
| |
| // Generate reference image |
| { |
| VkClearValue clearColor = defaultClearValue(m_colorFormat); |
| tcu::Vec4 clearColorVec4 (clearColor.color.float32[0], clearColor.color.float32[1], |
| clearColor.color.float32[2], clearColor.color.float32[3]); |
| tcu::clear(refImage.getAccess(), clearColorVec4); |
| for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex) |
| { |
| // Depth Clamp is enabled, then we clamp point depth to viewport's maxDepth and minDepth values and later check if it is inside depthBounds volume. |
| float scaling = ((vertex->position.z() / vertex->position.w()) * (m_param.viewportMaxDepth - m_param.viewportMinDepth)) + m_param.viewportMinDepth; |
| float depth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth); |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| depth = de::min(de::max(depth, 0.0f), 1.0f); |
| |
| auto i = vertex - m_vertices.begin(); |
| |
| // Depending if the first draw call succeed, we need to know if the second draw call will render the points because the depth buffer content |
| // will determine if it passes the depth test and the depth bounds test. |
| bool firstDrawHasPassedDepthBoundsTest = !firstDraw && m_vertexWasRendered[i]; |
| float depthBufferValue = firstDrawHasPassedDepthBoundsTest ? depth : clearValue; |
| |
| // For non-float depth formats, depth value is clampled to the range [0, 1]. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| depthBufferValue = de::min(de::max(depthBufferValue, 0.0f), 1.0f); |
| |
| // Check that the point passes the depth test and the depth bounds test. |
| if (compareDepthResult(m_param.depthCompareOp, depth, depthBufferValue) && |
| depthBufferValue >= m_param.minDepthBounds && depthBufferValue <= m_param.maxDepthBounds) |
| { |
| deInt32 x = static_cast<deInt32>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.x() - 1)); |
| deInt32 y = static_cast<deInt32>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.y() - 1)); |
| refImage.getAccess().setPixel(vertex->color, x, y); |
| if (firstDraw) |
| m_vertexWasRendered.push_back(true); |
| continue; |
| } |
| |
| if (firstDraw) |
| m_vertexWasRendered.push_back(false); |
| } |
| } |
| |
| // Check the rendered image |
| { |
| de::MovePtr<tcu::TextureLevel> result = vkt::pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize); |
| std::string description = "Image comparison draw "; |
| description += (firstDraw ? "1" : "2"); |
| |
| compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(), |
| "IntImageCompare", |
| description.c_str(), |
| refImage.getAccess(), |
| result->getAccess(), |
| tcu::UVec4(2, 2, 2, 2), |
| tcu::IVec3(1, 1, 0), |
| true, |
| tcu::COMPARE_LOG_RESULT); |
| if (!compareOk) |
| return tcu::TestStatus::fail("Image mismatch"); |
| } |
| |
| // Check depth buffer contents |
| { |
| de::MovePtr<tcu::TextureLevel> depthResult = readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_param.depthFormat, m_renderSize); |
| |
| log << tcu::TestLog::Message; |
| for (std::vector<Vertex4RGBA>::const_iterator vertex = m_vertices.begin(); vertex != m_vertices.end(); ++vertex) |
| { |
| deInt32 x = static_cast<deInt32>((((vertex->position.x() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.x() - 1)); |
| deInt32 y = static_cast<deInt32>((((vertex->position.y() / vertex->position.w()) + 1.0f) / 2.0f) * static_cast<float>(m_renderSize.y() - 1)); |
| tcu::Vec4 depth = depthResult->getAccess().getPixel(x, y); |
| |
| // Check depth values are valid |
| if (depth.y() != 0.0f || depth.z() != 0.0f || depth.w() != 1.0f) |
| { |
| log << tcu::TestLog::Message << "Draw " << (firstDraw ? "1" : "2") << ": Invalid depth buffer values for pixel (" << x << ", " << y << ") = (" |
| << depth.x() << ", " << depth.y() << ", " << depth.z() << ", " << depth.w() << "." << tcu::TestLog::EndMessage; |
| compareOk = DE_FALSE; |
| } |
| |
| // Depth Clamp is enabled, so we clamp point depth to viewport's maxDepth and minDepth values, or 0.0f and 1.0f is format is not float. |
| float scaling = (vertex->position.z() / vertex->position.w()) * (m_param.viewportMaxDepth - m_param.viewportMinDepth) + m_param.viewportMinDepth; |
| float expectedDepth = de::min(de::max(scaling, m_param.viewportMinDepth), m_param.viewportMaxDepth); |
| |
| auto i = vertex - m_vertices.begin(); |
| |
| // Depending if the first draw call succeed, we need to know if the second draw call will render the points because the depth buffer content |
| // will determine if it passes the depth test and the depth bounds test. |
| bool firstDrawHasPassedDepthBoundsTest = !firstDraw && m_vertexWasRendered[i]; |
| |
| // If we are in the first draw call, the depth buffer content is clearValue. If we are in the second draw call, it is going to be depth.x() if the first |
| // succeeded. |
| float depthBufferValue = firstDrawHasPassedDepthBoundsTest ? depth.x() : clearValue; |
| |
| // For non-float depth formats, depth value is clampled to the range [0, 1]. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| depthBufferValue = de::min(de::max(depthBufferValue, 0.0f), 1.0f); |
| |
| // Calculate the expectd depth depending on the depth test and the depth bounds test results. |
| expectedDepth = |
| (compareDepthResult(m_param.depthCompareOp, expectedDepth, depthBufferValue) && depthBufferValue <= m_param.maxDepthBounds && depthBufferValue >= m_param.minDepthBounds) |
| ? expectedDepth : depthBufferValue; |
| |
| // For non-float depth formats, depth value is clampled to the range [0, 1]. |
| if (isFloatingPointDepthFormat(m_param.depthFormat) == VK_FALSE) |
| expectedDepth = de::min(de::max(expectedDepth, 0.0f), 1.0f); |
| |
| if (fabs(expectedDepth - depth.x()) > epsilon) |
| { |
| log << tcu::TestLog::Message << "Draw " << (firstDraw ? "1" : "2") << ": Error pixel (" << x << ", " << y |
| << "). Depth value " << depth.x() << ", expected " << expectedDepth << ", error " << fabs(expectedDepth - depth.x()) << tcu::TestLog::EndMessage; |
| compareOk = DE_FALSE; |
| } |
| } |
| |
| if (!compareOk) |
| return tcu::TestStatus::fail("Depth buffer mismatch"); |
| } |
| |
| return tcu::TestStatus::pass("Result images matches references"); |
| } |
| |
| class DepthRangeUnrestrictedTest : public vkt::TestCase |
| { |
| public: |
| DepthRangeUnrestrictedTest (tcu::TestContext& testContext, |
| const std::string& name, |
| const std::string& description, |
| const DepthRangeUnrestrictedParam param) |
| : vkt::TestCase (testContext, name, description) |
| , m_param (param) |
| { } |
| virtual ~DepthRangeUnrestrictedTest (void) { } |
| virtual void initPrograms (SourceCollections& programCollection) const; |
| virtual TestInstance* createInstance (Context& context) const; |
| |
| protected: |
| const DepthRangeUnrestrictedParam m_param; |
| }; |
| |
| void DepthRangeUnrestrictedTest::initPrograms (SourceCollections& programCollection) const |
| { |
| programCollection.glslSources.add("vert") << glu::VertexSource( |
| "#version 310 es\n" |
| "layout(location = 0) in vec4 position;\n" |
| "layout(location = 1) in vec4 color;\n" |
| "layout(location = 0) out highp vec4 vtxColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " gl_Position = position;\n" |
| " gl_PointSize = 1.0f;\n" |
| " vtxColor = color;\n" |
| |
| "}\n"); |
| |
| |
| programCollection.glslSources.add("frag") << glu::FragmentSource( |
| "#version 310 es\n" |
| "layout(location = 0) in highp vec4 vtxColor;\n" |
| "layout(location = 0) out highp vec4 fragColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = vtxColor;\n" |
| "}\n"); |
| |
| } |
| |
| TestInstance* DepthRangeUnrestrictedTest::createInstance (Context& context) const |
| { |
| if (m_param.depthBoundsTestEnable) |
| return new DepthBoundsRangeUnrestrictedTestInstance(context, m_param); |
| return new DepthRangeUnrestrictedTestInstance(context, m_param); |
| } |
| } // anonymous |
| |
| tcu::TestCaseGroup* createDepthRangeUnrestrictedTests (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> depthTests (new tcu::TestCaseGroup(testCtx, "depth_range_unrestricted", "VK_EXT_depth_range_unrestricted tests")); |
| const VkFormat depthFormats[] = |
| { |
| VK_FORMAT_D32_SFLOAT, |
| VK_FORMAT_D24_UNORM_S8_UINT, |
| VK_FORMAT_D16_UNORM, |
| }; |
| |
| const VkCompareOp compareOps[] = |
| { |
| VK_COMPARE_OP_GREATER, |
| VK_COMPARE_OP_GREATER_OR_EQUAL, |
| VK_COMPARE_OP_LESS, |
| VK_COMPARE_OP_LESS_OR_EQUAL, |
| }; |
| |
| float viewportValues[] = {2.0f, 6.0f, 12.0f}; |
| float depthBoundsValues[] = {2.0f, 4.0f, 8.0f}; |
| float wcValues[] = {2.0f, 6.0f, 12.0f}; |
| float clearValues[] = {2.0f, -3.0f, 6.0f, -7.0f}; |
| |
| // Depth clear values outside range [0.0f, 1.0f]. |
| { |
| de::MovePtr<tcu::TestCaseGroup> depthClearValueTests (new tcu::TestCaseGroup(testCtx, "clear_value", "Depth Clear value unrestricted")); |
| DepthRangeUnrestrictedParam testParams; |
| testParams.testClearValueOnly = VK_TRUE; |
| testParams.depthClampEnable = VK_FALSE; |
| testParams.wc = 1.0f; |
| testParams.viewportMinDepth = 0.0f; |
| testParams.viewportMaxDepth = 1.0f; |
| testParams.minDepthBounds = 0.0f; |
| testParams.maxDepthBounds = 1.0f; |
| testParams.depthBoundsTestEnable = VK_FALSE; |
| testParams.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; |
| testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC; |
| |
| for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format) |
| { |
| testParams.depthFormat = depthFormats[format]; |
| testParams.depthBufferClearValue = defaultClearValue(depthFormats[format]); |
| for (int val = 0; val < DE_LENGTH_OF_ARRAY(clearValues); val++) |
| { |
| testParams.depthBufferClearValue.depthStencil.depth = clearValues[val]; |
| depthClearValueTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams)); |
| } |
| } |
| depthTests->addChild(depthClearValueTests.release()); |
| } |
| |
| // Viewport's depth unrestricted range |
| { |
| de::MovePtr<tcu::TestCaseGroup> viewportTests (new tcu::TestCaseGroup(testCtx, "viewport", "Viewport depth unrestricted range")); |
| DepthRangeUnrestrictedParam testParams; |
| testParams.testClearValueOnly = VK_FALSE; |
| testParams.wc = 1.0f; |
| testParams.depthClampEnable = VK_TRUE; |
| testParams.minDepthBounds = 0.0f; |
| testParams.maxDepthBounds = 1.0f; |
| testParams.depthBoundsTestEnable = VK_FALSE; |
| |
| for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format) |
| { |
| testParams.depthFormat = depthFormats[format]; |
| testParams.depthBufferClearValue = defaultClearValue(testParams.depthFormat); |
| for (int compareOp = 0; compareOp < DE_LENGTH_OF_ARRAY(compareOps); compareOp++) |
| { |
| testParams.depthCompareOp = compareOps[compareOp]; |
| for (int clearValue = 0; clearValue < DE_LENGTH_OF_ARRAY(clearValues); clearValue++) |
| { |
| testParams.depthBufferClearValue.depthStencil.depth = clearValues[clearValue]; |
| for (int viewportValue = 0; viewportValue < DE_LENGTH_OF_ARRAY(viewportValues); viewportValue++) |
| { |
| testParams.viewportMinDepth = -viewportValues[viewportValue]; |
| testParams.viewportMaxDepth = viewportValues[viewportValue]; |
| testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC; |
| viewportTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams)); |
| testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DYNAMIC; |
| viewportTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams)); |
| } |
| } |
| } |
| } |
| |
| depthTests->addChild(viewportTests.release()); |
| } |
| |
| // DepthBounds's depth unrestricted range |
| { |
| de::MovePtr<tcu::TestCaseGroup> depthBoundsTests (new tcu::TestCaseGroup(testCtx, "depthbounds", "Depthbounds unrestricted range")); |
| DepthRangeUnrestrictedParam testParams; |
| testParams.testClearValueOnly = VK_FALSE; |
| testParams.wc = 1.0f; |
| testParams.depthClampEnable = VK_TRUE; |
| testParams.depthBoundsTestEnable = VK_TRUE; |
| |
| for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format) |
| { |
| testParams.depthFormat = depthFormats[format]; |
| testParams.depthBufferClearValue = defaultClearValue(testParams.depthFormat); |
| for (int compareOp = 0; compareOp < DE_LENGTH_OF_ARRAY(compareOps); compareOp++) |
| { |
| testParams.depthCompareOp = compareOps[compareOp]; |
| for (int clearValue = 0; clearValue < DE_LENGTH_OF_ARRAY(clearValues); clearValue++) |
| { |
| testParams.depthBufferClearValue.depthStencil.depth = clearValues[clearValue]; |
| for (int viewportValue = 0; viewportValue < DE_LENGTH_OF_ARRAY(viewportValues); viewportValue++) |
| { |
| testParams.viewportMinDepth = -viewportValues[viewportValue]; |
| testParams.viewportMaxDepth = viewportValues[viewportValue]; |
| for (int depthValue = 0; depthValue < DE_LENGTH_OF_ARRAY(depthBoundsValues); depthValue++) |
| { |
| testParams.minDepthBounds = -depthBoundsValues[depthValue]; |
| testParams.maxDepthBounds = depthBoundsValues[depthValue]; |
| |
| testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC; |
| depthBoundsTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams)); |
| testParams.viewportDepthBoundsMode = TEST_MODE_DEPTH_BOUNDS_DYNAMIC; |
| depthBoundsTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams)); |
| testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_DYNAMIC; |
| depthBoundsTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams)); |
| } |
| } |
| } |
| } |
| } |
| |
| depthTests->addChild(depthBoundsTests.release()); |
| } |
| |
| // Depth clamping disabled |
| { |
| de::MovePtr<tcu::TestCaseGroup> noDepthClampingTests (new tcu::TestCaseGroup(testCtx, "depthclampingdisabled", "Depth clamping disabled tests")); |
| DepthRangeUnrestrictedParam testParams; |
| testParams.testClearValueOnly = VK_FALSE; |
| testParams.depthClampEnable = VK_FALSE; |
| testParams.minDepthBounds = 0.0f; |
| testParams.maxDepthBounds = 1.0f; |
| testParams.depthBoundsTestEnable = VK_FALSE; |
| testParams.viewportDepthBoundsMode = TEST_MODE_VIEWPORT_DEPTH_BOUNDS_STATIC; |
| |
| for (int format = 0; format < DE_LENGTH_OF_ARRAY(depthFormats); ++format) |
| { |
| testParams.depthFormat = depthFormats[format]; |
| testParams.depthBufferClearValue = defaultClearValue(testParams.depthFormat); |
| for (int compareOp = 0; compareOp < DE_LENGTH_OF_ARRAY(compareOps); compareOp++) |
| { |
| testParams.depthCompareOp = compareOps[compareOp]; |
| for (int clearValue = 0; clearValue < DE_LENGTH_OF_ARRAY(clearValues); clearValue++) |
| { |
| testParams.depthBufferClearValue.depthStencil.depth = clearValues[clearValue]; |
| for (int viewportValue = 0; viewportValue < DE_LENGTH_OF_ARRAY(viewportValues); viewportValue++) |
| { |
| testParams.viewportMinDepth = -viewportValues[viewportValue]; |
| testParams.viewportMaxDepth = viewportValues[viewportValue]; |
| for (int wc = 0; wc < DE_LENGTH_OF_ARRAY(wcValues); wc++) |
| { |
| testParams.wc = wcValues[wc]; |
| noDepthClampingTests->addChild(newTestCase<DepthRangeUnrestrictedTest>(testCtx, testParams)); |
| } |
| } |
| } |
| } |
| } |
| |
| depthTests->addChild(noDepthClampingTests.release()); |
| } |
| |
| return depthTests.release(); |
| } |
| |
| } // pipeline |
| |
| } // vkt |