| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2020 The Khronos Group Inc. |
| * Copyright (c) 2020 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 Logic Operators Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktPipelineLogicOpTests.hpp" |
| #include "vktPipelineImageUtil.hpp" |
| |
| #include "vkQueryUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkImageWithMemory.hpp" |
| |
| #include "tcuVectorUtil.hpp" |
| #include "tcuImageCompare.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include <string> |
| #include <limits> |
| |
| namespace vkt |
| { |
| namespace pipeline |
| { |
| |
| using namespace vk; |
| |
| namespace |
| { |
| |
| bool isSupportedColorAttachmentFormat (const InstanceInterface& instanceInterface, |
| VkPhysicalDevice device, |
| VkFormat format) |
| { |
| VkFormatProperties formatProps; |
| instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps); |
| |
| // Format also needs to be INT, UINT, or SINT but as we are the ones setting the |
| // color attachment format we only need to check that it is a valid color attachment |
| // format here. |
| return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); |
| } |
| |
| struct TestParams |
| { |
| VkLogicOp logicOp; // Operation. |
| tcu::UVec4 fbColor; // Framebuffer color. |
| tcu::UVec4 quadColor; // Geometry color. |
| VkFormat format; // Framebuffer format. |
| std::string name; // Logic operator test name. |
| }; |
| |
| deUint32 calcOpResult(VkLogicOp op, deUint32 src, deUint32 dst) |
| { |
| // See section 29.2 "Logical Operations" in the spec. |
| // |
| // AND: SRC & DST = 1010 & 1100 = 1000 = 0x8 |
| // AND_REVERSE: SRC & ~DST = 0011 & 1010 = 0010 = 0x2 |
| // COPY: SRC = 1010 = 1010 = 0xa |
| // AND_INVERTED: ~SRC & DST = 0101 & 1100 = 0100 = 0x4 |
| // NO_OP: DST = 1010 = 1010 = 0xa |
| // XOR: SRC ^ DST = 1010 ^ 1100 = 0110 = 0x6 |
| // OR: SRC | DST = 1010 | 1100 = 1110 = 0xe |
| // NOR: ~(SRC | DST) = ~(1010 | 1100) = 0001 = 0x1 |
| // EQUIVALENT: ~(SRC ^ DST) = ~(1010 ^ 1100) = 1001 = 0x9 |
| // INVERT: ~DST = ~1100 = 0011 = 0x3 |
| // OR_REVERSE: SRC | ~DST = 1010 | 0011 = 1011 = 0xb |
| // COPY_INVERTED: ~SRC = 0101 = 0101 = 0x5 |
| // OR_INVERTED: ~SRC | DST = 0101 | 1100 = 1101 = 0xd |
| // NAND: ~(SRC & DST) = ~(1010 &1100) = 0111 = 0x7 |
| // SET: = 1111 = 1111 = 0xf (sets all bits) |
| |
| switch (op) |
| { |
| case VK_LOGIC_OP_CLEAR: return (0u); |
| case VK_LOGIC_OP_AND: return (src & dst); |
| case VK_LOGIC_OP_AND_REVERSE: return (src & ~dst); |
| case VK_LOGIC_OP_COPY: return (src); |
| case VK_LOGIC_OP_AND_INVERTED: return (~src & dst); |
| case VK_LOGIC_OP_NO_OP: return (dst); |
| case VK_LOGIC_OP_XOR: return (src ^ dst); |
| case VK_LOGIC_OP_OR: return (src | dst); |
| case VK_LOGIC_OP_NOR: return (~(src | dst)); |
| case VK_LOGIC_OP_EQUIVALENT: return (~(src ^ dst)); |
| case VK_LOGIC_OP_INVERT: return (~dst); |
| case VK_LOGIC_OP_OR_REVERSE: return (src | ~dst); |
| case VK_LOGIC_OP_COPY_INVERTED: return (~src); |
| case VK_LOGIC_OP_OR_INVERTED: return (~src | dst); |
| case VK_LOGIC_OP_NAND: return (~(src & dst)); |
| case VK_LOGIC_OP_SET: return (std::numeric_limits<deUint32>::max()); |
| default: DE_ASSERT(false); break; |
| } |
| |
| DE_ASSERT(false); |
| return 0u; |
| } |
| |
| // Gets a bitmask to filter out unused bits according to the channel size (e.g. 0xFFu for 8-bit channels). |
| // channelSize in bytes. |
| deUint32 getChannelMask (int channelSize) |
| { |
| DE_ASSERT(channelSize >= 1 && channelSize <= 4); |
| |
| deUint64 mask = 1u; |
| mask <<= (channelSize * 8); |
| --mask; |
| |
| return static_cast<deUint32>(mask); |
| } |
| |
| class LogicOpTest : public vkt::TestCase |
| { |
| public: |
| LogicOpTest (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams &testParams); |
| virtual ~LogicOpTest (void); |
| virtual void initPrograms (SourceCollections& sourceCollections) const; |
| virtual void checkSupport (Context& context) const; |
| virtual TestInstance* createInstance (Context& context) const; |
| |
| private: |
| TestParams m_params; |
| }; |
| |
| LogicOpTest::LogicOpTest (tcu::TestContext& testCtx, |
| const std::string& name, |
| const std::string& description, |
| const TestParams& testParams) |
| : vkt::TestCase (testCtx, name, description) |
| , m_params (testParams) |
| { |
| DE_ASSERT(m_params.format != VK_FORMAT_UNDEFINED); |
| } |
| |
| LogicOpTest::~LogicOpTest (void) |
| { |
| } |
| |
| void LogicOpTest::checkSupport (Context &ctx) const |
| { |
| const auto& features = ctx.getDeviceFeatures(); |
| |
| if (!features.logicOp) |
| TCU_THROW(NotSupportedError, "Logic operations not supported"); |
| |
| if (!isSupportedColorAttachmentFormat(ctx.getInstanceInterface(), ctx.getPhysicalDevice(), m_params.format)) |
| TCU_THROW(NotSupportedError, "Unsupported color attachment format: " + std::string(getFormatName(m_params.format))); |
| } |
| |
| void LogicOpTest::initPrograms (SourceCollections& sourceCollections) const |
| { |
| sourceCollections.glslSources.add("color_vert") << glu::VertexSource( |
| "#version 430\n" |
| "vec2 vdata[] = vec2[] (\n" |
| "vec2(-1.0, -1.0),\n" |
| "vec2(1.0, -1.0),\n" |
| "vec2(-1.0, 1.0),\n" |
| "vec2(1.0, 1.0));\n" |
| "void main (void)\n" |
| "{\n" |
| " gl_Position = vec4(vdata[gl_VertexIndex], 0.0, 1.0);\n" |
| "}\n"); |
| |
| sourceCollections.glslSources.add("color_frag") << glu::FragmentSource( |
| "#version 430\n" |
| "layout(push_constant) uniform quadColor {\n" |
| " uvec4 val;\n" |
| "} QUAD_COLOR;\n" |
| "layout(location = 0) out uvec4 fragColor;\n" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = QUAD_COLOR.val;\n" |
| "}\n"); |
| } |
| |
| class LogicOpTestInstance : public vkt::TestInstance |
| { |
| public: |
| LogicOpTestInstance(Context& context, |
| const TestParams& params); |
| ~LogicOpTestInstance(void); |
| virtual tcu::TestStatus iterate(void); |
| |
| private: |
| tcu::TestStatus verifyImage(void); |
| |
| TestParams m_params; |
| |
| // Derived from m_params. |
| const tcu::TextureFormat m_tcuFormat; |
| const int m_numChannels; |
| const int m_channelSize; |
| const deUint32 m_channelMask; |
| |
| const tcu::UVec2 m_renderSize; |
| |
| VkImageCreateInfo m_colorImageCreateInfo; |
| de::MovePtr<ImageWithMemory> m_colorImage; |
| Move<VkImageView> m_colorAttachmentView; |
| |
| Move<VkRenderPass> m_renderPass; |
| Move<VkFramebuffer> m_framebuffer; |
| |
| Move<VkShaderModule> m_vertexShaderModule; |
| Move<VkShaderModule> m_fragmentShaderModule; |
| |
| Move<VkPipelineLayout> m_pipelineLayout; |
| Move<VkPipeline> m_graphicsPipeline; |
| |
| Move<VkCommandPool> m_cmdPool; |
| Move<VkCommandBuffer> m_cmdBuffer; |
| }; |
| |
| LogicOpTestInstance::LogicOpTestInstance (Context &ctx, const TestParams &testParams) |
| : vkt::TestInstance (ctx) |
| , m_params (testParams) |
| , m_tcuFormat (mapVkFormat(m_params.format)) |
| , m_numChannels (tcu::getNumUsedChannels(m_tcuFormat.order)) |
| , m_channelSize (tcu::getChannelSize(m_tcuFormat.type)) |
| , m_channelMask (getChannelMask(m_channelSize)) |
| , m_renderSize (32u, 32u) |
| { |
| DE_ASSERT(isUintFormat(m_params.format)); |
| |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| Allocator& memAlloc = m_context.getDefaultAllocator(); |
| constexpr auto kPushConstantSize = static_cast<deUint32>(sizeof(m_params.quadColor)); |
| |
| // create color image |
| { |
| 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; |
| m_params.format, // VkFormat format; |
| { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| 1u, // deUint32 arrayLayers; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 1u, // deUint32 queueFamilyIndexCount; |
| &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; |
| }; |
| |
| m_colorImageCreateInfo = colorImageParams; |
| m_colorImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, vkDevice, memAlloc, m_colorImageCreateInfo, MemoryRequirement::Any)); |
| |
| // create color attachment view |
| const VkImageViewCreateInfo colorAttachmentViewParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageViewCreateFlags flags; |
| m_colorImage->get(), // VkImage image; |
| VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; |
| m_params.format, // VkFormat format; |
| { VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY, |
| VK_COMPONENT_SWIZZLE_IDENTITY }, |
| { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); |
| } |
| |
| m_renderPass = makeRenderPass(vk, vkDevice, m_params.format); |
| m_framebuffer = makeFramebuffer(vk, vkDevice, *m_renderPass, m_colorAttachmentView.get(), m_renderSize.x(), m_renderSize.y()); |
| |
| // create pipeline layout |
| { |
| const VkPushConstantRange pcRange = |
| { |
| VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags; |
| 0u, // deUint32 offset; |
| kPushConstantSize, // deUint32 size; |
| }; |
| |
| 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; |
| 1u, // deUint32 pushConstantRangeCount; |
| &pcRange, // const VkPushConstantRange* pPushConstantRanges; |
| }; |
| |
| m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); |
| } |
| |
| m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0); |
| m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0); |
| |
| // create pipeline |
| { |
| const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = initVulkanStructure(); |
| |
| const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize)); |
| const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize)); |
| |
| VkColorComponentFlags colorWriteMask = VK_COLOR_COMPONENT_R_BIT | |
| VK_COLOR_COMPONENT_G_BIT | |
| VK_COLOR_COMPONENT_B_BIT | |
| VK_COLOR_COMPONENT_A_BIT; |
| |
| const VkPipelineColorBlendAttachmentState blendAttachmentState = |
| { |
| VK_FALSE, // VkBool32 blendEnable; |
| (VkBlendFactor) 0, // VkBlendFactor srcColorBlendFactor; |
| (VkBlendFactor) 0, // VkBlendFactor dstColorBlendFactor; |
| (VkBlendOp) 0, // VkBlendOp colorBlendOp; |
| (VkBlendFactor) 0, // VkBlendFactor srcAlphaBlendFactor; |
| (VkBlendFactor) 0, // VkBlendFactor dstAlphaBlendFactor; |
| (VkBlendOp) 0, // VkBlendOp alphaBlendOp; |
| colorWriteMask, // VkColorComponentFlags colorWriteMask; |
| }; |
| |
| const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = |
| { |
| VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| DE_NULL, // VkPipelineColorBlendStateCreateFlags flags; |
| VK_TRUE, // VkBool32 logicOpEnable; |
| m_params.logicOp, // VkLogicOp logicOp; |
| 1u, // uint32_t attachmentCount; |
| &blendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; |
| { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; |
| }; |
| |
| m_graphicsPipeline = makeGraphicsPipeline(vk, |
| vkDevice, // const VkDevice device |
| *m_pipelineLayout, // const VkPipelineLayout pipelineLayout |
| *m_vertexShaderModule, // const VkShaderModule vertexShaderModule |
| DE_NULL, // const VkShaderModule tessellationControlModule |
| DE_NULL, // const VkShaderModule tessellationEvalModule |
| DE_NULL, // const VkShaderModule geometryShaderModule |
| *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule |
| *m_renderPass, // const VkRenderPass renderPass |
| viewports, // const std::vector<VkViewport>& viewports |
| scissors, // const std::vector<VkRect2D>& scissors |
| VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // const VkPrimitiveTopology topology |
| 0u, // const deUint32 subpass |
| 0u, // const deUint32 patchControlPoints |
| &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo |
| DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo |
| DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo |
| &colorBlendStateParams); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo |
| } |
| |
| // create command pool |
| m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); |
| |
| // allocate and record command buffer |
| { |
| // Prepare clear color value and quad color taking into account the channel mask. |
| VkClearValue attachmentClearValue; |
| tcu::UVec4 quadColor(0u, 0u, 0u, 0u); |
| |
| deMemset(&attachmentClearValue.color, 0, sizeof(attachmentClearValue.color)); |
| for (int c = 0; c < m_numChannels; ++c) |
| attachmentClearValue.color.uint32[c] = (m_params.fbColor[c] & m_channelMask); |
| |
| for (int c = 0; c < m_numChannels; ++c) |
| quadColor[c] = (m_params.quadColor[c] & m_channelMask); |
| |
| m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| |
| beginCommandBuffer(vk, *m_cmdBuffer, 0u); |
| beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue); |
| |
| // Update push constant values |
| vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, kPushConstantSize, &quadColor); |
| |
| vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline); |
| vk.cmdDraw(*m_cmdBuffer, 4u, 1u, 0u, 0u); |
| endRenderPass(vk, *m_cmdBuffer); |
| endCommandBuffer(vk, *m_cmdBuffer); |
| } |
| } |
| |
| LogicOpTestInstance::~LogicOpTestInstance (void) |
| { |
| } |
| |
| tcu::TestStatus LogicOpTestInstance::iterate (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| |
| submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); |
| return verifyImage(); |
| } |
| |
| tcu::TestStatus LogicOpTestInstance::verifyImage (void) |
| { |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice vkDevice = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| Allocator& allocator = m_context.getDefaultAllocator(); |
| auto& log = m_context.getTestContext().getLog(); |
| |
| const auto result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, m_colorImage->get(), m_params.format, m_renderSize).release(); |
| const auto resultAccess = result->getAccess(); |
| const int iWidth = static_cast<int>(m_renderSize.x()); |
| const int iHeight = static_cast<int>(m_renderSize.y()); |
| tcu::UVec4 expectedColor (0u, 0u, 0u, 0u); // Overwritten below. |
| tcu::TextureLevel referenceTexture (m_tcuFormat, iWidth, iHeight); |
| auto referenceAccess = referenceTexture.getAccess(); |
| tcu::UVec4 threshold (0u, 0u, 0u, 0u); // Exact results. |
| |
| // Calculate proper expected color values. |
| for (int c = 0; c < m_numChannels; ++c) |
| { |
| expectedColor[c] = calcOpResult(m_params.logicOp, m_params.quadColor[c], m_params.fbColor[c]); |
| expectedColor[c] &= m_channelMask; |
| } |
| |
| for (int y = 0; y < iHeight; ++y) |
| for (int x = 0; x < iWidth; ++x) |
| referenceAccess.setPixel(expectedColor, x, y); |
| |
| // Check result. |
| bool resultOk = tcu::intThresholdCompare(log, "TestResults", "Test Result Images", referenceAccess, resultAccess, threshold, tcu::COMPARE_LOG_ON_ERROR); |
| |
| if (!resultOk) |
| TCU_FAIL("Result does not match expected values; check log for details"); |
| |
| return tcu::TestStatus::pass("Pass"); |
| } |
| |
| TestInstance *LogicOpTest::createInstance (Context& context) const |
| { |
| return new LogicOpTestInstance(context, m_params); |
| } |
| |
| std::string getSimpleFormatName (VkFormat format) |
| { |
| return de::toLower(std::string(getFormatName(format)).substr(std::string("VK_FORMAT_").size())); |
| } |
| |
| } // anonymous namespace |
| |
| tcu::TestCaseGroup* createLogicOpTests (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> logicOpTests (new tcu::TestCaseGroup(testCtx, "logic_op", "Logical Operations tests")); |
| |
| // 4 bits are enough to check all possible combinations of logical operation inputs at once, for example s AND d: |
| // |
| // 1 0 1 0 |
| // AND 1 1 0 0 |
| // ------------ |
| // 1 0 0 0 |
| // |
| // However, we will choose color values such that both higher bits and lower bits are used, and the implementation will not be |
| // able to mix channels by mistake. |
| // |
| // 0011 0101 1010 1100 |
| // 3 5 a c |
| // 0101 0011 1100 1010 |
| // 5 3 c a |
| |
| const tcu::UVec4 kQuadColor = { 0x35acU, 0x5ac3U, 0xac35U, 0xc35aU }; |
| const tcu::UVec4 kFbColor = { 0x53caU, 0x3ca5U, 0xca53U, 0xa53cU }; |
| |
| // Note: the format will be chosen and changed later. |
| std::vector<TestParams> logicOpTestParams = |
| { |
| { VK_LOGIC_OP_CLEAR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "clear" }, |
| { VK_LOGIC_OP_AND, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "and" }, |
| { VK_LOGIC_OP_AND_REVERSE, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "and_reverse" }, |
| { VK_LOGIC_OP_COPY, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "copy" }, |
| { VK_LOGIC_OP_AND_INVERTED, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "and_inverted" }, |
| { VK_LOGIC_OP_NO_OP, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "no_op" }, |
| { VK_LOGIC_OP_XOR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "xor" }, |
| { VK_LOGIC_OP_OR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "or" }, |
| { VK_LOGIC_OP_NOR, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "nor" }, |
| { VK_LOGIC_OP_EQUIVALENT, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "equivalent" }, |
| { VK_LOGIC_OP_INVERT, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "invert" }, |
| { VK_LOGIC_OP_OR_REVERSE, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "or_reverse" }, |
| { VK_LOGIC_OP_COPY_INVERTED, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "copy_inverted" }, |
| { VK_LOGIC_OP_OR_INVERTED, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "or_inverted" }, |
| { VK_LOGIC_OP_NAND, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "nand" }, |
| { VK_LOGIC_OP_SET, kFbColor, kQuadColor, VK_FORMAT_UNDEFINED, "set" }, |
| }; |
| |
| const VkFormat formatList[] = |
| { |
| VK_FORMAT_R8_UINT, |
| VK_FORMAT_R8G8_UINT, |
| VK_FORMAT_R8G8B8_UINT, |
| VK_FORMAT_B8G8R8_UINT, |
| VK_FORMAT_R8G8B8A8_UINT, |
| VK_FORMAT_B8G8R8A8_UINT, |
| VK_FORMAT_R16_UINT, |
| VK_FORMAT_R16G16_UINT, |
| VK_FORMAT_R16G16B16_UINT, |
| VK_FORMAT_R16G16B16A16_UINT, |
| VK_FORMAT_R32_UINT, |
| VK_FORMAT_R32G32_UINT, |
| VK_FORMAT_R32G32B32_UINT, |
| VK_FORMAT_R32G32B32A32_UINT, |
| }; |
| |
| for (int formatIdx = 0; formatIdx < DE_LENGTH_OF_ARRAY(formatList); ++formatIdx) |
| { |
| const auto& format = formatList[formatIdx]; |
| const auto formatName = getSimpleFormatName(format); |
| const auto formatDesc = "Logical operator tests with format " + formatName; |
| |
| de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatDesc.c_str())); |
| |
| for (auto& params : logicOpTestParams) |
| { |
| params.format = format; |
| formatGroup->addChild(new LogicOpTest(testCtx, params.name, "Tests the " + params.name + " logical operator", params)); |
| } |
| |
| logicOpTests->addChild(formatGroup.release()); |
| } |
| |
| return logicOpTests.release(); |
| } |
| |
| } // pipeline namespace |
| } // vkt namespace |