From 2eda7edb5a3193b800ce1f2a0e859548719fec24 Mon Sep 17 00:00:00 2001 From: Maciej Jesionowski Date: Thu, 4 Aug 2016 15:07:25 +0200 Subject: [PATCH] Add scissoring tests Scissoring tests based on GLES 2.0. New test: - dEQP-VK.fragment_operations.scissor.* Fixes #452 Change-Id: I8bd7cb1dfc0889249d1f7bfb159f51defdf55a2d --- .../cts/master/com.drawelements.deqp.vk.xml | 43 + android/cts/master/vk-master.txt | 11 + .../vulkancts/modules/vulkan/CMakeLists.txt | 3 + .../vulkan/fragment_ops/CMakeLists.txt | 19 + .../vktFragmentOperationsMakeUtil.cpp | 303 +++++++ .../vktFragmentOperationsMakeUtil.hpp | 56 ++ .../vktFragmentOperationsScissorTests.cpp | 826 ++++++++++++++++++ .../vktFragmentOperationsScissorTests.hpp | 40 + .../vktFragmentOperationsTests.cpp | 50 ++ .../vktFragmentOperationsTests.hpp | 39 + .../modules/vulkan/vktTestPackage.cpp | 2 + .../vulkancts/mustpass/1.0.1/vk-default.txt | 11 + 12 files changed, 1403 insertions(+) create mode 100644 external/vulkancts/modules/vulkan/fragment_ops/CMakeLists.txt create mode 100644 external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.cpp create mode 100644 external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.hpp create mode 100644 external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.cpp create mode 100644 external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.hpp create mode 100644 external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.cpp create mode 100644 external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.hpp diff --git a/android/cts/master/com.drawelements.deqp.vk.xml b/android/cts/master/com.drawelements.deqp.vk.xml index 2021dda99..5d54ee163 100644 --- a/android/cts/master/com.drawelements.deqp.vk.xml +++ b/android/cts/master/com.drawelements.deqp.vk.xml @@ -368128,5 +368128,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index bf57c2657..434e7b43b 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -114573,3 +114573,14 @@ dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_nearest_mipmap_near dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_nearest_mipmap_linear dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_linear_mipmap_nearest dEQP-VK.texture_filtering.explicit_lod.2d.derivatives.linear_linear_mipmap_linear +dEQP-VK.fragment_operations.scissor.points.inside +dEQP-VK.fragment_operations.scissor.points.partially_inside +dEQP-VK.fragment_operations.scissor.points.outside +dEQP-VK.fragment_operations.scissor.lines.inside +dEQP-VK.fragment_operations.scissor.lines.partially_inside +dEQP-VK.fragment_operations.scissor.lines.outside +dEQP-VK.fragment_operations.scissor.lines.crossing +dEQP-VK.fragment_operations.scissor.triangles.inside +dEQP-VK.fragment_operations.scissor.triangles.partially_inside +dEQP-VK.fragment_operations.scissor.triangles.outside +dEQP-VK.fragment_operations.scissor.triangles.crossing diff --git a/external/vulkancts/modules/vulkan/CMakeLists.txt b/external/vulkancts/modules/vulkan/CMakeLists.txt index fbc11d085..979aadbc2 100644 --- a/external/vulkancts/modules/vulkan/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/CMakeLists.txt @@ -21,6 +21,7 @@ add_subdirectory(tessellation) add_subdirectory(rasterization) add_subdirectory(synchronization) add_subdirectory(clipping) +add_subdirectory(fragment_ops) include_directories( api @@ -44,6 +45,7 @@ include_directories( rasterization synchronization clipping + fragment_ops ) set(DEQP_VK_COMMON_SRCS @@ -88,6 +90,7 @@ set(DEQP_VK_COMMON_LIBS deqp-vk-rasterization deqp-vk-synchronization deqp-vk-clipping + deqp-vk-fragment-ops ) add_library(deqp-vk-common STATIC ${DEQP_VK_COMMON_SRCS}) diff --git a/external/vulkancts/modules/vulkan/fragment_ops/CMakeLists.txt b/external/vulkancts/modules/vulkan/fragment_ops/CMakeLists.txt new file mode 100644 index 000000000..304c5c7ca --- /dev/null +++ b/external/vulkancts/modules/vulkan/fragment_ops/CMakeLists.txt @@ -0,0 +1,19 @@ +include_directories(..) + +set(DEQP_VK_FRAGMENT_OPS_SRCS + vktFragmentOperationsTests.cpp + vktFragmentOperationsTests.hpp + vktFragmentOperationsScissorTests.cpp + vktFragmentOperationsScissorTests.hpp + vktFragmentOperationsMakeUtil.cpp + vktFragmentOperationsMakeUtil.hpp + ) + +set(DEQP_VK_FRAGMENT_OPS_LIBS + deqp-vk-common + tcutil + vkutil + ) + +add_library(deqp-vk-fragment-ops STATIC ${DEQP_VK_FRAGMENT_OPS_SRCS}) +target_link_libraries(deqp-vk-fragment-ops ${DEQP_VK_FRAGMENT_OPS_LIBS}) diff --git a/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.cpp b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.cpp new file mode 100644 index 000000000..27405ebb9 --- /dev/null +++ b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.cpp @@ -0,0 +1,303 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group 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 Object creation utilities + *//*--------------------------------------------------------------------*/ + +#include "vktFragmentOperationsMakeUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkPrograms.hpp" +#include "vkRefUtil.hpp" +#include "vkQueryUtil.hpp" +#include + +namespace vkt +{ +namespace FragmentOperations +{ +using namespace vk; +using de::MovePtr; + +VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize, + const VkBufferUsageFlags usage) +{ + const VkBufferCreateInfo bufferCreateInfo = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkBufferCreateFlags)0, // VkBufferCreateFlags flags; + bufferSize, // VkDeviceSize size; + usage, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + }; + return bufferCreateInfo; +} + +VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask, + const VkAccessFlags dstAccessMask, + const VkBuffer buffer, + const VkDeviceSize offset, + const VkDeviceSize bufferSizeBytes) +{ + const VkBufferMemoryBarrier barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + srcAccessMask, // VkAccessFlags srcAccessMask; + dstAccessMask, // VkAccessFlags dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + buffer, // VkBuffer buffer; + offset, // VkDeviceSize offset; + bufferSizeBytes, // VkDeviceSize size; + }; + return barrier; +} + +VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask, + const VkAccessFlags dstAccessMask, + const VkImageLayout oldLayout, + const VkImageLayout newLayout, + const VkImage image, + const VkImageSubresourceRange subresourceRange) +{ + const VkImageMemoryBarrier barrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + srcAccessMask, // VkAccessFlags outputMask; + dstAccessMask, // VkAccessFlags inputMask; + oldLayout, // VkImageLayout oldLayout; + newLayout, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + image, // VkImage image; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + return barrier; +} + +Move makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex) +{ + const VkCommandPoolCreateInfo info = + { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags; + queueFamilyIndex, // deUint32 queueFamilyIndex; + }; + return createCommandPool(vk, device, &info); +} + +Move makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool) +{ + const VkCommandBufferAllocateInfo info = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + commandPool, // VkCommandPool commandPool; + VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; + 1u, // deUint32 commandBufferCount; + }; + return allocateCommandBuffer(vk, device, &info); +} + +Move makeDescriptorSet (const DeviceInterface& vk, + const VkDevice device, + const VkDescriptorPool descriptorPool, + const VkDescriptorSetLayout setLayout) +{ + const VkDescriptorSetAllocateInfo info = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + descriptorPool, // VkDescriptorPool descriptorPool; + 1u, // deUint32 descriptorSetCount; + &setLayout, // const VkDescriptorSetLayout* pSetLayouts; + }; + return allocateDescriptorSet(vk, device, &info); +} + +Move makePipelineLayout (const DeviceInterface& vk, + const VkDevice device) +{ + const VkPipelineLayoutCreateInfo info = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; + 0u, // deUint32 setLayoutCount; + DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + return createPipelineLayout(vk, device, &info); +} + +Move makePipelineLayout (const DeviceInterface& vk, + const VkDevice device, + const VkDescriptorSetLayout descriptorSetLayout) +{ + const VkPipelineLayoutCreateInfo info = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineLayoutCreateFlags)0, // VkPipelineLayoutCreateFlags flags; + 1u, // deUint32 setLayoutCount; + &descriptorSetLayout, // const VkDescriptorSetLayout* pSetLayouts; + 0u, // deUint32 pushConstantRangeCount; + DE_NULL, // const VkPushConstantRange* pPushConstantRanges; + }; + return createPipelineLayout(vk, device, &info); +} + +Move makeComputePipeline (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const VkShaderModule shaderModule, + const VkSpecializationInfo* specInfo) +{ + const VkPipelineShaderStageCreateInfo shaderStageInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; + shaderModule, // VkShaderModule module; + "main", // const char* pName; + specInfo, // const VkSpecializationInfo* pSpecializationInfo; + }; + const VkComputePipelineCreateInfo pipelineInfo = + { + VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; + shaderStageInfo, // VkPipelineShaderStageCreateInfo stage; + pipelineLayout, // VkPipelineLayout layout; + DE_NULL, // VkPipeline basePipelineHandle; + 0, // deInt32 basePipelineIndex; + }; + return createComputePipeline(vk, device, DE_NULL , &pipelineInfo); +} + +Move makeImageView (const DeviceInterface& vk, + const VkDevice vkDevice, + const VkImage image, + const VkImageViewType viewType, + const VkFormat format, + const VkImageSubresourceRange subresourceRange) +{ + const VkImageViewCreateInfo imageViewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkImageViewCreateFlags)0, // VkImageViewCreateFlags flags; + image, // VkImage image; + viewType, // VkImageViewType viewType; + format, // VkFormat format; + makeComponentMappingRGBA(), // VkComponentMapping components; + subresourceRange, // VkImageSubresourceRange subresourceRange; + }; + return createImageView(vk, vkDevice, &imageViewParams); +} + +void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer) +{ + const VkCommandBufferBeginInfo info = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags; + DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; + }; + VK_CHECK(vk.beginCommandBuffer(commandBuffer, &info)); +} + +void submitCommandsAndWait (const DeviceInterface& vk, + const VkDevice device, + const VkQueue queue, + const VkCommandBuffer commandBuffer) +{ + const VkFenceCreateInfo fenceInfo = + { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFenceCreateFlags)0, // VkFenceCreateFlags flags; + }; + const Unique fence(createFence(vk, device, &fenceInfo)); + + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // uint32_t waitSemaphoreCount; + DE_NULL, // const VkSemaphore* pWaitSemaphores; + DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // uint32_t commandBufferCount; + &commandBuffer, // const VkCommandBuffer* pCommandBuffers; + 0u, // uint32_t signalSemaphoreCount; + DE_NULL, // const VkSemaphore* pSignalSemaphores; + }; + VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence)); + VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); +} + +Move makeFramebuffer (const DeviceInterface& vk, + const VkDevice device, + const VkRenderPass renderPass, + const deUint32 attachmentCount, + const VkImageView* pAttachments, + const deUint32 width, + const deUint32 height, + const deUint32 layers) +{ + const VkFramebufferCreateInfo framebufferInfo = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; + renderPass, // VkRenderPass renderPass; + attachmentCount, // uint32_t attachmentCount; + pAttachments, // const VkImageView* pAttachments; + width, // uint32_t width; + height, // uint32_t height; + layers, // uint32_t layers; + }; + + return createFramebuffer(vk, device, &framebufferInfo); +} + +MovePtr bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement) +{ + MovePtr alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement); + VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset())); + return alloc; +} + +MovePtr bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement) +{ + MovePtr alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement)); + VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset())); + return alloc; +} + +} // FragmentOperations +} // vkt diff --git a/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.hpp b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.hpp new file mode 100644 index 000000000..b907e5b92 --- /dev/null +++ b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsMakeUtil.hpp @@ -0,0 +1,56 @@ +#ifndef _VKTFRAGMENTOPERATIONSMAKEUTIL_HPP +#define _VKTFRAGMENTOPERATIONSMAKEUTIL_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group 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 Object creation utilities + *//*--------------------------------------------------------------------*/ + +#include "vkDefs.hpp" +#include "vkRef.hpp" +#include "vkMemUtil.hpp" +#include "deUniquePtr.hpp" +#include "tcuVector.hpp" + +namespace vkt +{ +namespace FragmentOperations +{ + +vk::VkBufferCreateInfo makeBufferCreateInfo (const vk::VkDeviceSize bufferSize, const vk::VkBufferUsageFlags usage); +vk::Move makeCommandPool (const vk::DeviceInterface& vk, const vk::VkDevice device, const deUint32 queueFamilyIndex); +vk::Move makeCommandBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkCommandPool commandPool); +vk::Move makeDescriptorSet (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorPool descriptorPool, const vk::VkDescriptorSetLayout setLayout); +vk::Move makePipelineLayout (const vk::DeviceInterface& vk, const vk::VkDevice device); +vk::Move makePipelineLayout (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkDescriptorSetLayout descriptorSetLayout); +vk::Move makeComputePipeline (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkPipelineLayout pipelineLayout, const vk::VkShaderModule shaderModule, const vk::VkSpecializationInfo* specInfo); +vk::Move makeFramebuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkRenderPass renderPass, const deUint32 attachmentCount, const vk::VkImageView* pAttachments, const deUint32 width, const deUint32 height, const deUint32 layers = 1u); +vk::Move makeImageView (const vk::DeviceInterface& vk, const vk::VkDevice vkDevice, const vk::VkImage image, const vk::VkImageViewType viewType, const vk::VkFormat format, const vk::VkImageSubresourceRange subresourceRange); +vk::VkBufferMemoryBarrier makeBufferMemoryBarrier (const vk::VkAccessFlags srcAccessMask, const vk::VkAccessFlags dstAccessMask, const vk::VkBuffer buffer, const vk::VkDeviceSize offset, const vk::VkDeviceSize bufferSizeBytes); +vk::VkImageMemoryBarrier makeImageMemoryBarrier (const vk::VkAccessFlags srcAccessMask, const vk::VkAccessFlags dstAccessMask, const vk::VkImageLayout oldLayout, const vk::VkImageLayout newLayout, const vk::VkImage image, const vk::VkImageSubresourceRange subresourceRange); +de::MovePtr bindImage (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::Allocator& allocator, const vk::VkImage image, const vk::MemoryRequirement requirement); +de::MovePtr bindBuffer (const vk::DeviceInterface& vk, const vk::VkDevice device, vk::Allocator& allocator, const vk::VkBuffer buffer, const vk::MemoryRequirement requirement); +void beginCommandBuffer (const vk::DeviceInterface& vk, const vk::VkCommandBuffer commandBuffer); +void submitCommandsAndWait (const vk::DeviceInterface& vk, const vk::VkDevice device, const vk::VkQueue queue, const vk::VkCommandBuffer commandBuffer); + +} // FragmentOperations +} // vkt + +#endif // _VKTFRAGMENTOPERATIONSMAKEUTIL_HPP diff --git a/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.cpp b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.cpp new file mode 100644 index 000000000..cd645c288 --- /dev/null +++ b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.cpp @@ -0,0 +1,826 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2014 The Android Open Source Project + * + * 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 Scissor tests + *//*--------------------------------------------------------------------*/ + +#include "vktFragmentOperationsScissorTests.hpp" +#include "vktTestCaseUtil.hpp" +#include "vktFragmentOperationsMakeUtil.hpp" + +#include "vkDefs.hpp" +#include "vkRefUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkMemUtil.hpp" +#include "vkPrograms.hpp" +#include "vkImageUtil.hpp" + +#include "tcuTestLog.hpp" +#include "tcuVector.hpp" +#include "tcuImageCompare.hpp" + +#include "deUniquePtr.hpp" +#include "deRandom.hpp" + +namespace vkt +{ +namespace FragmentOperations +{ +using namespace vk; +using de::UniquePtr; +using de::MovePtr; +using tcu::Vec4; +using tcu::Vec2; +using tcu::IVec2; +using tcu::IVec4; + +namespace +{ + +//! What primitives will be drawn by the test case. +enum TestPrimitive +{ + TEST_PRIMITIVE_POINTS, //!< Many points. + TEST_PRIMITIVE_LINES, //!< Many short lines. + TEST_PRIMITIVE_TRIANGLES, //!< Many small triangles. + TEST_PRIMITIVE_BIG_LINE, //!< One line crossing the whole render area. + TEST_PRIMITIVE_BIG_TRIANGLE, //!< One triangle covering the whole render area. +}; + +struct VertexData +{ + Vec4 position; + Vec4 color; +}; + +//! Parameters used by the test case. +struct CaseDef +{ + Vec4 renderArea; //!< (ox, oy, w, h), where origin (0,0) is the top-left corner of the viewport. Width and height are in range [0, 1]. + Vec4 scissorArea; //!< scissored area (ox, oy, w, h) + TestPrimitive primitive; +}; + +template +inline VkDeviceSize sizeInBytes(const std::vector& vec) +{ + return vec.size() * sizeof(vec[0]); +} + +Move makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, VkImageUsageFlags usage) +{ + const VkImageCreateInfo imageParams = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkImageCreateFlags)0, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + format, // VkFormat format; + makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; + 1u, // deUint32 mipLevels; + 1u, // deUint32 arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + usage, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // deUint32 queueFamilyIndexCount; + DE_NULL, // const deUint32* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + return createImage(vk, device, &imageParams); +} + +inline Move makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage) +{ + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage); + return createBuffer(vk, device, &bufferCreateInfo); +} + +//! A single-attachment, single-subpass render pass. +Move makeRenderPass (const DeviceInterface& vk, + const VkDevice device, + const VkFormat colorFormat) +{ + const VkAttachmentDescription colorAttachmentDescription = + { + (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; + colorFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // 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; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; + }; + + const VkAttachmentReference colorAttachmentRef = + { + 0u, // deUint32 attachment; + VK_IMAGE_LAYOUT_COLOR_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; + 1u, // deUint32 colorAttachmentCount; + &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments; + DE_NULL, // const VkAttachmentReference* pResolveAttachments; + 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; + 1u, // deUint32 attachmentCount; + &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; + 1u, // deUint32 subpassCount; + &subpassDescription, // const VkSubpassDescription* pSubpasses; + 0u, // deUint32 dependencyCount; + DE_NULL // const VkSubpassDependency* pDependencies; + }; + + return createRenderPass(vk, device, &renderPassInfo); +} + +Move makeGraphicsPipeline (const DeviceInterface& vk, + const VkDevice device, + const VkPipelineLayout pipelineLayout, + const VkRenderPass renderPass, + const VkShaderModule vertexModule, + const VkShaderModule fragmentModule, + const IVec2 renderSize, + const IVec4 scissorArea, //!< (ox, oy, w, h) + const VkPrimitiveTopology topology) +{ + const VkVertexInputBindingDescription vertexInputBindingDescription = + { + 0u, // uint32_t binding; + sizeof(VertexData), // uint32_t stride; + VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; + }; + + const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = + { + { + 0u, // uint32_t location; + 0u, // uint32_t binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + 0u, // uint32_t offset; + }, + { + 1u, // uint32_t location; + 0u, // uint32_t binding; + VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; + sizeof(Vec4), // uint32_t offset; + }, + }; + + const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; + 1u, // uint32_t vertexBindingDescriptionCount; + &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; + DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount; + vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; + }; + + const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; + topology, // VkPrimitiveTopology topology; + VK_FALSE, // VkBool32 primitiveRestartEnable; + }; + + const VkViewport viewport = makeViewport( + 0.0f, 0.0f, + static_cast(renderSize.x()), static_cast(renderSize.y()), + 0.0f, 1.0f); + + const VkRect2D scissor = { + makeOffset2D(scissorArea.x(), scissorArea.y()), + makeExtent2D(static_cast(scissorArea.z()), static_cast(scissorArea.w())), + }; + + const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; + 1u, // uint32_t viewportCount; + &viewport, // const VkViewport* pViewports; + 1u, // uint32_t scissorCount; + &scissor, // const VkRect2D* pScissors; + }; + + const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; + VK_FALSE, // 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 VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineMultisampleStateCreateFlags)0, // 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; + }; + + const VkStencilOpState stencilOpState = makeStencilOpState( + VK_STENCIL_OP_KEEP, // stencil fail + VK_STENCIL_OP_KEEP, // depth & stencil pass + VK_STENCIL_OP_KEEP, // depth only fail + VK_COMPARE_OP_ALWAYS, // compare op + 0u, // compare mask + 0u, // write mask + 0u); // reference + + VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; + VK_FALSE, // VkBool32 depthTestEnable; + VK_FALSE, // VkBool32 depthWriteEnable; + VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; + VK_FALSE, // VkBool32 depthBoundsTestEnable; + VK_FALSE, // VkBool32 stencilTestEnable; + stencilOpState, // VkStencilOpState front; + stencilOpState, // VkStencilOpState back; + 0.0f, // float minDepthBounds; + 1.0f, // float maxDepthBounds; + }; + + const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + // Number of blend attachments must equal the number of color attachments during any subpass. + const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = + { + 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; + colorComponentsAll, // VkColorComponentFlags colorWriteMask; + }; + + const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; + VK_FALSE, // VkBool32 logicOpEnable; + VK_LOGIC_OP_COPY, // VkLogicOp logicOp; + 1u, // deUint32 attachmentCount; + &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; + { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; + }; + + const VkPipelineShaderStageCreateInfo pShaderStages[] = + { + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; + vertexModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; + VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; + fragmentModule, // VkShaderModule module; + "main", // const char* pName; + DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; + } + }; + + const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; + DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; + pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; + &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; + &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; + DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; + &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; + &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; + &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; + &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; + &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; + DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; + pipelineLayout, // VkPipelineLayout layout; + renderPass, // VkRenderPass renderPass; + 0u, // deUint32 subpass; + DE_NULL, // VkPipeline basePipelineHandle; + 0, // deInt32 basePipelineIndex; + }; + + return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); +} + +inline VertexData makeVertex (const float x, const float y, const Vec4& color) +{ + const VertexData data = { Vec4(x, y, 0.0f, 1.0f), color }; + return data; +} + +std::vector genVertices (const TestPrimitive primitive, const Vec4& renderArea, const Vec4& primitiveColor) +{ + std::vector vertices; + de::Random rng (1234); + + const float x0 = 2.0f * renderArea.x() - 1.0f; + const float y0 = 2.0f * renderArea.y() - 1.0f; + const float rx = 2.0f * renderArea.z(); + const float ry = 2.0f * renderArea.w(); + const float size = 0.2f; + + switch (primitive) + { + case TEST_PRIMITIVE_POINTS: + for (int i = 0; i < 50; ++i) + { + const float x = x0 + rng.getFloat(0.0f, rx); + const float y = y0 + rng.getFloat(0.0f, ry); + vertices.push_back(makeVertex(x, y, primitiveColor)); + } + break; + + case TEST_PRIMITIVE_LINES: + for (int i = 0; i < 30; ++i) + { + const float x = x0 + rng.getFloat(0.0f, rx - size); + const float y = y0 + rng.getFloat(0.0f, ry - size); + vertices.push_back(makeVertex(x, y, primitiveColor)); + vertices.push_back(makeVertex(x + size, y + size, primitiveColor)); + } + break; + + case TEST_PRIMITIVE_TRIANGLES: + for (int i = 0; i < 20; ++i) + { + const float x = x0 + rng.getFloat(0.0f, rx - size); + const float y = y0 + rng.getFloat(0.0f, ry - size); + vertices.push_back(makeVertex(x, y, primitiveColor)); + vertices.push_back(makeVertex(x + size/2.0f, y + size, primitiveColor)); + vertices.push_back(makeVertex(x + size, y, primitiveColor)); + } + break; + + case TEST_PRIMITIVE_BIG_LINE: + vertices.push_back(makeVertex(x0, y0, primitiveColor)); + vertices.push_back(makeVertex(x0 + rx, y0 + ry, primitiveColor)); + break; + + case TEST_PRIMITIVE_BIG_TRIANGLE: + vertices.push_back(makeVertex(x0, y0, primitiveColor)); + vertices.push_back(makeVertex(x0 + rx/2.0f, y0 + ry, primitiveColor)); + vertices.push_back(makeVertex(x0 + rx, y0, primitiveColor)); + break; + } + + return vertices; +} + +VkPrimitiveTopology getTopology (const TestPrimitive primitive) +{ + switch (primitive) + { + case TEST_PRIMITIVE_POINTS: return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; + + case TEST_PRIMITIVE_LINES: + case TEST_PRIMITIVE_BIG_LINE: return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; + + case TEST_PRIMITIVE_TRIANGLES: + case TEST_PRIMITIVE_BIG_TRIANGLE: return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + default: + DE_ASSERT(0); + return VK_PRIMITIVE_TOPOLOGY_LAST; + } +} + +void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize size) +{ + deMemset(alloc.getHostPtr(), 0, static_cast(size)); + flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), size); +} + +//! Transform from normalized coords to framebuffer space. +inline IVec4 getAreaRect (const Vec4& area, const int width, const int height) +{ + return IVec4(static_cast(static_cast(width) * area.x()), + static_cast(static_cast(height) * area.y()), + static_cast(static_cast(width) * area.z()), + static_cast(static_cast(height) * area.w())); +} + +void applyScissor (tcu::PixelBufferAccess imageAccess, const Vec4& floatScissorArea, const Vec4& clearColor) +{ + const IVec4 scissorRect (getAreaRect(floatScissorArea, imageAccess.getWidth(), imageAccess.getHeight())); + const int sx0 = scissorRect.x(); + const int sx1 = scissorRect.x() + scissorRect.z(); + const int sy0 = scissorRect.y(); + const int sy1 = scissorRect.y() + scissorRect.w(); + + for (int y = 0; y < imageAccess.getHeight(); ++y) + for (int x = 0; x < imageAccess.getWidth(); ++x) + { + // Fragments outside fail the scissor test. + if (x < sx0 || x >= sx1 || y < sy0 || y >= sy1) + imageAccess.setPixel(clearColor, x, y); + } +} + +void initPrograms (SourceCollections& programCollection, const CaseDef caseDef) +{ + DE_UNREF(caseDef); + + // Vertex shader + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n" + << "layout(location = 0) in vec4 in_position;\n" + << "layout(location = 1) in vec4 in_color;\n" + << "layout(location = 0) out vec4 o_color;\n" + << "\n" + << "out gl_PerVertex {\n" + << " vec4 gl_Position;\n" + << "};\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " gl_Position = in_position;\n" + << " o_color = in_color;\n" + << "}\n"; + + programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); + } + + // Fragment shader + { + std::ostringstream src; + src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" + << "\n" + << "layout(location = 0) in vec4 in_color;\n" + << "layout(location = 0) out vec4 o_color;\n" + << "\n" + << "void main(void)\n" + << "{\n" + << " o_color = in_color;\n" + << "}\n"; + + programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); + } +} + +class ScissorRenderer +{ +public: + ScissorRenderer (Context& context, const CaseDef caseDef, const IVec2& renderSize, const VkFormat colorFormat, const Vec4& primitiveColor, const Vec4& clearColor) + : m_renderSize (renderSize) + , m_colorFormat (colorFormat) + , m_colorSubresourceRange (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)) + , m_primitiveColor (primitiveColor) + , m_clearColor (clearColor) + , m_vertices (genVertices(caseDef.primitive, caseDef.renderArea, m_primitiveColor)) + , m_vertexBufferSize (sizeInBytes(m_vertices)) + , m_topology (getTopology(caseDef.primitive)) + { + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + Allocator& allocator = context.getDefaultAllocator(); + + m_colorImage = makeImage(vk, device, m_colorFormat, m_renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any); + m_colorAttachment = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, m_colorSubresourceRange); + + m_vertexBuffer = makeBuffer(vk, device, m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + m_vertexBufferAlloc = bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible); + + { + deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], static_cast(m_vertexBufferSize)); + flushMappedMemoryRange(vk, device, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), m_vertexBufferSize); + } + + m_vertexModule = createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u); + m_fragmentModule = createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u); + m_renderPass = makeRenderPass (vk, device, m_colorFormat); + m_framebuffer = makeFramebuffer (vk, device, *m_renderPass, 1u, &m_colorAttachment.get(), + static_cast(m_renderSize.x()), static_cast(m_renderSize.y())); + m_pipelineLayout = makePipelineLayout (vk, device); + m_cmdPool = makeCommandPool (vk, device, queueFamilyIndex); + m_cmdBuffer = makeCommandBuffer (vk, device, *m_cmdPool); + + } + + void draw (Context& context, const Vec4& scissorAreaFloat, const VkBuffer colorBuffer) const + { + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const VkQueue queue = context.getUniversalQueue(); + + // New pipeline, because we're modifying scissor (we don't use dynamic state). + const Unique pipeline (makeGraphicsPipeline(vk, device, *m_pipelineLayout, *m_renderPass, *m_vertexModule, *m_fragmentModule, + m_renderSize, getAreaRect(scissorAreaFloat, m_renderSize.x(), m_renderSize.y()), m_topology)); + + beginCommandBuffer(vk, *m_cmdBuffer); + + const VkClearValue clearValue = makeClearValueColor(m_clearColor); + const VkRect2D renderArea = + { + makeOffset2D(0, 0), + makeExtent2D(m_renderSize.x(), m_renderSize.y()), + }; + const VkRenderPassBeginInfo renderPassBeginInfo = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + *m_renderPass, // VkRenderPass renderPass; + *m_framebuffer, // VkFramebuffer framebuffer; + renderArea, // VkRect2D renderArea; + 1u, // uint32_t clearValueCount; + &clearValue, // const VkClearValue* pClearValues; + }; + vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); + { + const VkDeviceSize vertexBufferOffset = 0ull; + vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset); + } + + vk.cmdDraw(*m_cmdBuffer, static_cast(m_vertices.size()), 1u, 0u, 0u); + vk.cmdEndRenderPass(*m_cmdBuffer); + + // Prepare color image for copy + { + const VkImageMemoryBarrier barriers[] = + { + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags outputMask; + VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags inputMask; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout; + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex; + *m_colorImage, // VkImage image; + m_colorSubresourceRange, // VkImageSubresourceRange subresourceRange; + }, + }; + + vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, + 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); + } + // Color image -> host buffer + { + const VkBufferImageCopy region = + { + 0ull, // VkDeviceSize bufferOffset; + 0u, // uint32_t bufferRowLength; + 0u, // uint32_t bufferImageHeight; + makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u), // VkExtent3D imageExtent; + }; + + vk.cmdCopyImageToBuffer(*m_cmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer, 1u, ®ion); + } + // Buffer write barrier + { + const VkBufferMemoryBarrier barriers[] = + { + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + colorBuffer, // VkBuffer buffer; + 0ull, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }, + }; + + vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, + 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u); + } + + VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); + submitCommandsAndWait(vk, device, queue, *m_cmdBuffer); + } + +private: + const IVec2 m_renderSize; + const VkFormat m_colorFormat; + const VkImageSubresourceRange m_colorSubresourceRange; + const Vec4 m_primitiveColor; + const Vec4 m_clearColor; + const std::vector m_vertices; + const VkDeviceSize m_vertexBufferSize; + const VkPrimitiveTopology m_topology; + + Move m_colorImage; + MovePtr m_colorImageAlloc; + Move m_colorAttachment; + Move m_vertexBuffer; + MovePtr m_vertexBufferAlloc; + Move m_vertexModule; + Move m_fragmentModule; + Move m_renderPass; + Move m_framebuffer; + Move m_pipelineLayout; + Move m_cmdPool; + Move m_cmdBuffer; + + // "deleted" + ScissorRenderer (const ScissorRenderer&); + ScissorRenderer& operator= (const ScissorRenderer&); +}; + +tcu::TestStatus test (Context& context, const CaseDef caseDef) +{ + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + Allocator& allocator = context.getDefaultAllocator(); + + const IVec2 renderSize (128, 128); + const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; + const Vec4 scissorFullArea (0.0f, 0.0f, 1.0f, 1.0f); + const Vec4 primitiveColor (1.0f, 1.0f, 1.0f, 1.0f); + const Vec4 clearColor (0.5f, 0.5f, 1.0f, 1.0f); + + const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); + const Unique colorBufferFull (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); + const UniquePtr colorBufferFullAlloc (bindBuffer(vk, device, allocator, *colorBufferFull, MemoryRequirement::HostVisible)); + + const Unique colorBufferScissored (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); + const UniquePtr colorBufferScissoredAlloc (bindBuffer(vk, device, allocator, *colorBufferScissored, MemoryRequirement::HostVisible)); + + zeroBuffer(vk, device, *colorBufferFullAlloc, colorBufferSize); + zeroBuffer(vk, device, *colorBufferScissoredAlloc, colorBufferSize); + + // Draw + { + const ScissorRenderer renderer (context, caseDef, renderSize, colorFormat, primitiveColor, clearColor); + + renderer.draw(context, scissorFullArea, *colorBufferFull); + renderer.draw(context, caseDef.scissorArea, *colorBufferScissored); + } + + // Log image + { + invalidateMappedMemoryRange(vk, device, colorBufferFullAlloc->getMemory(), 0ull, colorBufferSize); + invalidateMappedMemoryRange(vk, device, colorBufferScissoredAlloc->getMemory(), 0ull, colorBufferSize); + + const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferScissoredAlloc->getHostPtr()); + tcu::PixelBufferAccess referenceImage (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferFullAlloc->getHostPtr()); + + // Apply scissor to the full image, so we can compare it with the result image. + applyScissor (referenceImage, caseDef.scissorArea, clearColor); + + // Images should now match. + if (!tcu::floatThresholdCompare(context.getTestContext().getLog(), "color", "Image compare", referenceImage, resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT)) + return tcu::TestStatus::fail("Rendered image is not correct"); + } + + return tcu::TestStatus::pass("OK"); +} + +} // anonymous + +//! \note The ES 2.0 scissoring tests included color/depth/stencil clear cases, but these operations are not affected by scissor test in Vulkan. +//! Scissor is part of the pipeline state and pipeline only affects the drawing commands. +tcu::TestCaseGroup* createScissorTests (tcu::TestContext& testCtx) +{ + MovePtr scissorGroup(new tcu::TestCaseGroup(testCtx, "scissor", "Scissor tests")); + + struct TestSpec + { + const char* name; + const char* description; + CaseDef caseDef; + }; + + const Vec4 areaFull (0.0f, 0.0f, 1.0f, 1.0f); + const Vec4 areaCropped (0.2f, 0.2f, 0.6f, 0.6f); + const Vec4 areaCroppedMore (0.4f, 0.4f, 0.2f, 0.2f); + const Vec4 areaLeftHalf (0.0f, 0.0f, 0.5f, 1.0f); + const Vec4 areaRightHalf (0.5f, 0.0f, 0.5f, 1.0f); + + // Points + { + MovePtr primitiveGroup (new tcu::TestCaseGroup(testCtx, "points", "")); + + const TestSpec cases[] = + { + { "inside", "Points fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_POINTS } }, + { "partially_inside", "Points partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_POINTS } }, + { "outside", "Points fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_POINTS } }, + }; + + for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) + addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef); + + scissorGroup->addChild(primitiveGroup.release()); + } + + // Lines + { + MovePtr primitiveGroup (new tcu::TestCaseGroup(testCtx, "lines", "")); + + const TestSpec cases[] = + { + { "inside", "Lines fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_LINES } }, + { "partially_inside", "Lines partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_LINES } }, + { "outside", "Lines fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_LINES } }, + { "crossing", "A line crossing the scissor area", { areaFull, areaCroppedMore, TEST_PRIMITIVE_BIG_LINE } }, + }; + + for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) + addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef); + + scissorGroup->addChild(primitiveGroup.release()); + } + + // Triangles + { + MovePtr primitiveGroup (new tcu::TestCaseGroup(testCtx, "triangles", "")); + + const TestSpec cases[] = + { + { "inside", "Triangles fully inside the scissor area", { areaFull, areaFull, TEST_PRIMITIVE_TRIANGLES } }, + { "partially_inside", "Triangles partially inside the scissor area", { areaFull, areaCropped, TEST_PRIMITIVE_TRIANGLES } }, + { "outside", "Triangles fully outside the scissor area", { areaLeftHalf, areaRightHalf, TEST_PRIMITIVE_TRIANGLES } }, + { "crossing", "A triangle crossing the scissor area", { areaFull, areaCroppedMore, TEST_PRIMITIVE_BIG_TRIANGLE } }, + }; + + for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) + addFunctionCaseWithPrograms(primitiveGroup.get(), cases[i].name, cases[i].description, initPrograms, test, cases[i].caseDef); + + scissorGroup->addChild(primitiveGroup.release()); + } + + return scissorGroup.release(); +} + +} // FragmentOperations +} // vkt diff --git a/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.hpp b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.hpp new file mode 100644 index 000000000..f7d59b14c --- /dev/null +++ b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsScissorTests.hpp @@ -0,0 +1,40 @@ +#ifndef _VKTFRAGMENTOPERATIONSSCISSORTESTS_HPP +#define _VKTFRAGMENTOPERATIONSSCISSORTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group Inc. + * Copyright (c) 2014 The Android Open Source Project + * + * 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 Scissor tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace vkt +{ +namespace FragmentOperations +{ + +tcu::TestCaseGroup* createScissorTests (tcu::TestContext& testCtx); + +} // FragmentOperations +} // vkt + +#endif // _VKTFRAGMENTOPERATIONSSCISSORTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.cpp b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.cpp new file mode 100644 index 000000000..f14678a86 --- /dev/null +++ b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.cpp @@ -0,0 +1,50 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group 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 Fragment operations tests + *//*--------------------------------------------------------------------*/ + +#include "vktFragmentOperationsTests.hpp" +#include "vktTestGroupUtil.hpp" +#include "vktFragmentOperationsScissorTests.hpp" + +namespace vkt +{ +namespace FragmentOperations +{ +namespace +{ + +void addFragmentOperationsTests (tcu::TestCaseGroup* fragmentOperationsTestsGroup) +{ + tcu::TestContext& testCtx = fragmentOperationsTestsGroup->getTestContext(); + + fragmentOperationsTestsGroup->addChild(createScissorTests(testCtx)); +} + +} // anonymous + +tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx) +{ + return createTestGroup(testCtx, "fragment_operations", "Fragment operations tests", addFragmentOperationsTests); +} + +} // FragmentOperations +} // vkt diff --git a/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.hpp b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.hpp new file mode 100644 index 000000000..1eccb188d --- /dev/null +++ b/external/vulkancts/modules/vulkan/fragment_ops/vktFragmentOperationsTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTFRAGMENTOPERATIONSTESTS_HPP +#define _VKTFRAGMENTOPERATIONSTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2016 The Khronos Group 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 Fragment operations tests + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace vkt +{ +namespace FragmentOperations +{ + +tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx); + +} // FragmentOperations +} // vkt + +#endif // _VKTFRAGMENTOPERATIONSTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/vktTestPackage.cpp b/external/vulkancts/modules/vulkan/vktTestPackage.cpp index 928e017eb..199fdbfd6 100644 --- a/external/vulkancts/modules/vulkan/vktTestPackage.cpp +++ b/external/vulkancts/modules/vulkan/vktTestPackage.cpp @@ -74,6 +74,7 @@ #include "vktTessellationTests.hpp" #include "vktRasterizationTests.hpp" #include "vktClippingTests.hpp" +#include "vktFragmentOperationsTests.hpp" #include #include @@ -394,6 +395,7 @@ void TestPackage::init (void) addChild(rasterization::createTests (m_testCtx)); addChild(clipping::createTests (m_testCtx)); addChild(texture_filtering::createTests (m_testCtx)); + addChild(FragmentOperations::createTests(m_testCtx)); } } // vkt diff --git a/external/vulkancts/mustpass/1.0.1/vk-default.txt b/external/vulkancts/mustpass/1.0.1/vk-default.txt index 34b9ea985..f17697e2f 100644 --- a/external/vulkancts/mustpass/1.0.1/vk-default.txt +++ b/external/vulkancts/mustpass/1.0.1/vk-default.txt @@ -107939,3 +107939,14 @@ dEQP-VK.clipping.user_defined.clip_cull_distance.vert.5_3 dEQP-VK.clipping.user_defined.clip_cull_distance.vert.6_2 dEQP-VK.clipping.user_defined.clip_cull_distance.vert.7_1 dEQP-VK.clipping.user_defined.clip_cull_distance.vert.8 +dEQP-VK.fragment_operations.scissor.points.inside +dEQP-VK.fragment_operations.scissor.points.partially_inside +dEQP-VK.fragment_operations.scissor.points.outside +dEQP-VK.fragment_operations.scissor.lines.inside +dEQP-VK.fragment_operations.scissor.lines.partially_inside +dEQP-VK.fragment_operations.scissor.lines.outside +dEQP-VK.fragment_operations.scissor.lines.crossing +dEQP-VK.fragment_operations.scissor.triangles.inside +dEQP-VK.fragment_operations.scissor.triangles.partially_inside +dEQP-VK.fragment_operations.scissor.triangles.outside +dEQP-VK.fragment_operations.scissor.triangles.crossing -- 2.34.1