| /*------------------------------------------------------------------------- |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2016 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Tests for incremental present extension |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktWsiIncrementalPresentTests.hpp" |
| |
| #include "vktTestCaseUtil.hpp" |
| #include "vktTestGroupUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkWsiPlatform.hpp" |
| #include "vkWsiUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkDeviceUtil.hpp" |
| #include "vkPlatform.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkPrograms.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| |
| #include "vkWsiUtil.hpp" |
| |
| #include "tcuPlatform.hpp" |
| #include "tcuResultCollector.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include <vector> |
| #include <string> |
| |
| using std::vector; |
| using std::string; |
| |
| using tcu::Maybe; |
| using tcu::UVec2; |
| using tcu::TestLog; |
| |
| namespace vkt |
| { |
| namespace wsi |
| { |
| namespace |
| { |
| enum Scaling |
| { |
| SCALING_NONE, |
| SCALING_UP, |
| SCALING_DOWN |
| }; |
| |
| typedef vector<vk::VkExtensionProperties> Extensions; |
| |
| void checkAllSupported (const Extensions& supportedExtensions, const vector<string>& requiredExtensions) |
| { |
| for (vector<string>::const_iterator requiredExtName = requiredExtensions.begin(); |
| requiredExtName != requiredExtensions.end(); |
| ++requiredExtName) |
| { |
| if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(*requiredExtName))) |
| TCU_THROW(NotSupportedError, (*requiredExtName + " is not supported").c_str()); |
| } |
| } |
| |
| vk::Move<vk::VkInstance> createInstanceWithWsi (const vk::PlatformInterface& vkp, |
| deUint32 version, |
| const Extensions& supportedExtensions, |
| vk::wsi::Type wsiType) |
| { |
| vector<string> extensions; |
| |
| extensions.push_back("VK_KHR_surface"); |
| extensions.push_back(getExtensionName(wsiType)); |
| |
| checkAllSupported(supportedExtensions, extensions); |
| |
| return vk::createDefaultInstance(vkp, version, vector<string>(), extensions); |
| } |
| |
| vk::VkPhysicalDeviceFeatures getDeviceNullFeatures (void) |
| { |
| vk::VkPhysicalDeviceFeatures features; |
| deMemset(&features, 0, sizeof(features)); |
| return features; |
| } |
| |
| deUint32 getNumQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice) |
| { |
| deUint32 numFamilies = 0; |
| |
| vki.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &numFamilies, DE_NULL); |
| |
| return numFamilies; |
| } |
| |
| vector<deUint32> getSupportedQueueFamilyIndices (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface) |
| { |
| const deUint32 numTotalFamilyIndices = getNumQueueFamilyIndices(vki, physicalDevice); |
| vector<deUint32> supportedFamilyIndices; |
| |
| for (deUint32 queueFamilyNdx = 0; queueFamilyNdx < numTotalFamilyIndices; ++queueFamilyNdx) |
| { |
| if (vk::wsi::getPhysicalDeviceSurfaceSupport(vki, physicalDevice, queueFamilyNdx, surface) != VK_FALSE) |
| supportedFamilyIndices.push_back(queueFamilyNdx); |
| } |
| |
| return supportedFamilyIndices; |
| } |
| |
| deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, vk::VkSurfaceKHR surface) |
| { |
| const vector<deUint32> supportedFamilyIndices = getSupportedQueueFamilyIndices(vki, physicalDevice, surface); |
| |
| if (supportedFamilyIndices.empty()) |
| TCU_THROW(NotSupportedError, "Device doesn't support presentation"); |
| |
| return supportedFamilyIndices[0]; |
| } |
| |
| vk::Move<vk::VkDevice> createDeviceWithWsi (const vk::PlatformInterface& vkp, |
| vk::VkInstance instance, |
| const vk::InstanceInterface& vki, |
| vk::VkPhysicalDevice physicalDevice, |
| const Extensions& supportedExtensions, |
| const deUint32 queueFamilyIndex, |
| bool requiresIncrementalPresent, |
| const vk::VkAllocationCallbacks* pAllocator = DE_NULL) |
| { |
| const float queuePriorities[] = { 1.0f }; |
| const vk::VkDeviceQueueCreateInfo queueInfos[] = |
| { |
| { |
| vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| DE_NULL, |
| (vk::VkDeviceQueueCreateFlags)0, |
| queueFamilyIndex, |
| DE_LENGTH_OF_ARRAY(queuePriorities), |
| &queuePriorities[0] |
| } |
| }; |
| const vk::VkPhysicalDeviceFeatures features = getDeviceNullFeatures(); |
| const char* const extensions[] = |
| { |
| "VK_KHR_swapchain", |
| "VK_KHR_incremental_present" |
| }; |
| |
| const vk::VkDeviceCreateInfo deviceParams = |
| { |
| vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, |
| DE_NULL, |
| (vk::VkDeviceCreateFlags)0, |
| DE_LENGTH_OF_ARRAY(queueInfos), |
| &queueInfos[0], |
| 0u, |
| DE_NULL, |
| requiresIncrementalPresent ? 2u : 1u, |
| DE_ARRAY_BEGIN(extensions), |
| &features |
| }; |
| |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(extensions); ++ndx) |
| { |
| if (!isExtensionSupported(supportedExtensions, vk::RequiredExtension(extensions[ndx]))) |
| TCU_THROW(NotSupportedError, (string(extensions[ndx]) + " is not supported").c_str()); |
| } |
| |
| return createDevice(vkp, instance, vki, physicalDevice, &deviceParams, pAllocator); |
| } |
| |
| de::MovePtr<vk::wsi::Display> createDisplay (const vk::Platform& platform, |
| const Extensions& supportedExtensions, |
| vk::wsi::Type wsiType) |
| { |
| try |
| { |
| return de::MovePtr<vk::wsi::Display>(platform.createWsiDisplay(wsiType)); |
| } |
| catch (const tcu::NotSupportedError& e) |
| { |
| if (isExtensionSupported(supportedExtensions, vk::RequiredExtension(getExtensionName(wsiType))) && |
| platform.hasDisplay(wsiType)) |
| { |
| // If VK_KHR_{platform}_surface was supported, vk::Platform implementation |
| // must support creating native display & window for that WSI type. |
| throw tcu::TestError(e.getMessage()); |
| } |
| else |
| throw; |
| } |
| } |
| |
| de::MovePtr<vk::wsi::Window> createWindow (const vk::wsi::Display& display, const Maybe<UVec2>& initialSize) |
| { |
| try |
| { |
| return de::MovePtr<vk::wsi::Window>(display.createWindow(initialSize)); |
| } |
| catch (const tcu::NotSupportedError& e) |
| { |
| // See createDisplay - assuming that wsi::Display was supported platform port |
| // should also support creating a window. |
| throw tcu::TestError(e.getMessage()); |
| } |
| } |
| |
| void initSemaphores (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| std::vector<vk::VkSemaphore>& semaphores) |
| { |
| for (size_t ndx = 0; ndx < semaphores.size(); ndx++) |
| semaphores[ndx] = createSemaphore(vkd, device).disown(); |
| } |
| |
| void deinitSemaphores (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| std::vector<vk::VkSemaphore>& semaphores) |
| { |
| for (size_t ndx = 0; ndx < semaphores.size(); ndx++) |
| { |
| if (semaphores[ndx] != (vk::VkSemaphore)0) |
| vkd.destroySemaphore(device, semaphores[ndx], DE_NULL); |
| |
| semaphores[ndx] = (vk::VkSemaphore)0; |
| } |
| |
| semaphores.clear(); |
| } |
| |
| void initFences (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| std::vector<vk::VkFence>& fences) |
| { |
| for (size_t ndx = 0; ndx < fences.size(); ndx++) |
| fences[ndx] = createFence(vkd, device).disown(); |
| } |
| |
| void deinitFences (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| std::vector<vk::VkFence>& fences) |
| { |
| for (size_t ndx = 0; ndx < fences.size(); ndx++) |
| { |
| if (fences[ndx] != (vk::VkFence)0) |
| vkd.destroyFence(device, fences[ndx], DE_NULL); |
| |
| fences[ndx] = (vk::VkFence)0; |
| } |
| |
| fences.clear(); |
| } |
| |
| vk::VkRect2D getRenderFrameRect (size_t frameNdx, |
| deUint32 imageWidth, |
| deUint32 imageHeight) |
| { |
| const deUint32 x = frameNdx == 0 |
| ? 0 |
| : de::min(((deUint32)frameNdx) % imageWidth, imageWidth - 1u); |
| const deUint32 y = frameNdx == 0 |
| ? 0 |
| : de::min(((deUint32)frameNdx) % imageHeight, imageHeight - 1u); |
| const deUint32 width = frameNdx == 0 |
| ? imageWidth |
| : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageWidth / 3), imageWidth - x); |
| const deUint32 height = frameNdx == 0 |
| ? imageHeight |
| : 1 + de::min((deUint32)(frameNdx) % de::min<deUint32>(100, imageHeight / 3), imageHeight - y); |
| const vk::VkRect2D rect = |
| { |
| { (deInt32)x, (deInt32)y }, |
| { width, height } |
| }; |
| |
| DE_ASSERT(width > 0); |
| DE_ASSERT(height > 0); |
| |
| return rect; |
| } |
| |
| vector<vk::VkRectLayerKHR> getUpdatedRects (size_t firstFrameNdx, |
| size_t lastFrameNdx, |
| deUint32 width, |
| deUint32 height) |
| { |
| vector<vk::VkRectLayerKHR> rects; |
| |
| for (size_t frameNdx = firstFrameNdx; frameNdx <= lastFrameNdx; frameNdx++) |
| { |
| const vk::VkRect2D rect = getRenderFrameRect(frameNdx, width, height); |
| const vk::VkRectLayerKHR rectLayer = |
| { |
| rect.offset, |
| rect.extent, |
| 0 |
| }; |
| |
| rects.push_back(rectLayer); |
| } |
| |
| return rects; |
| } |
| |
| void cmdRenderFrame (const vk::DeviceInterface& vkd, |
| vk::VkCommandBuffer commandBuffer, |
| vk::VkPipelineLayout pipelineLayout, |
| vk::VkPipeline pipeline, |
| size_t frameNdx, |
| deUint32 imageWidth, |
| deUint32 imageHeight) |
| { |
| const deUint32 mask = (deUint32)frameNdx; |
| |
| if (frameNdx == 0) |
| { |
| const vk::VkRect2D scissor = vk::makeRect2D(imageWidth, imageHeight); |
| vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor); |
| const vk::VkClearAttachment attachment = |
| { |
| vk::VK_IMAGE_ASPECT_COLOR_BIT, |
| 0u, |
| vk::makeClearValueColorF32(0.25f, 0.50, 0.75f, 1.00f) |
| }; |
| const vk::VkClearRect rect = |
| { |
| scissor, |
| 0u, |
| 1u |
| }; |
| |
| vkd.cmdClearAttachments(commandBuffer, 1u, &attachment, 1u, &rect); |
| } |
| |
| { |
| const vk::VkRect2D scissor = getRenderFrameRect(frameNdx, imageWidth, imageHeight); |
| vkd.cmdSetScissor(commandBuffer, 0u, 1u, &scissor); |
| |
| vkd.cmdPushConstants(commandBuffer, pipelineLayout, vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u, &mask); |
| vkd.cmdBindPipeline(commandBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); |
| vkd.cmdDraw(commandBuffer, 6u, 1u, 0u, 0u); |
| } |
| } |
| |
| vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkCommandPool commandPool, |
| vk::VkPipelineLayout pipelineLayout, |
| vk::VkRenderPass renderPass, |
| vk::VkFramebuffer framebuffer, |
| vk::VkPipeline pipeline, |
| vk::VkImage image, |
| bool isFirst, |
| size_t imageNextFrame, |
| size_t currentFrame, |
| deUint32 imageWidth, |
| deUint32 imageHeight) |
| { |
| const vk::VkCommandBufferAllocateInfo allocateInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, |
| DE_NULL, |
| |
| commandPool, |
| vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, |
| 1 |
| }; |
| |
| vk::Move<vk::VkCommandBuffer> commandBuffer (vk::allocateCommandBuffer(vkd, device, &allocateInfo)); |
| beginCommandBuffer(vkd, *commandBuffer, 0u); |
| |
| { |
| const vk::VkImageSubresourceRange subRange = |
| { |
| vk::VK_IMAGE_ASPECT_COLOR_BIT, |
| 0, |
| 1, |
| 0, |
| 1 |
| }; |
| const vk::VkImageMemoryBarrier barrier = |
| { |
| vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, |
| DE_NULL, |
| vk::VK_ACCESS_TRANSFER_WRITE_BIT, |
| vk::VK_ACCESS_TRANSFER_READ_BIT | vk::VK_ACCESS_TRANSFER_WRITE_BIT, |
| isFirst ? vk::VK_IMAGE_LAYOUT_UNDEFINED : vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, |
| vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| VK_QUEUE_FAMILY_IGNORED, |
| VK_QUEUE_FAMILY_IGNORED, |
| image, |
| subRange |
| }; |
| vkd.cmdPipelineBarrier(*commandBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1, &barrier); |
| } |
| |
| beginRenderPass(vkd, *commandBuffer, renderPass, framebuffer, vk::makeRect2D(imageWidth, imageHeight), tcu::Vec4(0.25f, 0.5f, 0.75f, 1.0f)); |
| |
| for (size_t frameNdx = imageNextFrame; frameNdx <= currentFrame; frameNdx++) |
| cmdRenderFrame(vkd, *commandBuffer, pipelineLayout, pipeline, frameNdx, imageWidth, imageHeight); |
| |
| endRenderPass(vkd, *commandBuffer); |
| |
| endCommandBuffer(vkd, *commandBuffer); |
| return commandBuffer; |
| } |
| |
| void deinitCommandBuffers (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkCommandPool commandPool, |
| std::vector<vk::VkCommandBuffer>& commandBuffers) |
| { |
| for (size_t ndx = 0; ndx < commandBuffers.size(); ndx++) |
| { |
| if (commandBuffers[ndx] != (vk::VkCommandBuffer)0) |
| vkd.freeCommandBuffers(device, commandPool, 1u, &commandBuffers[ndx]); |
| |
| commandBuffers[ndx] = (vk::VkCommandBuffer)0; |
| } |
| |
| commandBuffers.clear(); |
| } |
| |
| vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| deUint32 queueFamilyIndex) |
| { |
| const vk::VkCommandPoolCreateInfo createInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, |
| DE_NULL, |
| 0u, |
| queueFamilyIndex |
| }; |
| |
| return vk::createCommandPool(vkd, device, &createInfo); |
| } |
| |
| vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkRenderPass renderPass, |
| vk::VkImageView imageView, |
| deUint32 width, |
| deUint32 height) |
| { |
| const vk::VkFramebufferCreateInfo createInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, |
| DE_NULL, |
| |
| 0u, |
| renderPass, |
| 1u, |
| &imageView, |
| width, |
| height, |
| 1u |
| }; |
| |
| return vk::createFramebuffer(vkd, device, &createInfo); |
| } |
| |
| void initFramebuffers (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkRenderPass renderPass, |
| std::vector<vk::VkImageView> imageViews, |
| deUint32 width, |
| deUint32 height, |
| std::vector<vk::VkFramebuffer>& framebuffers) |
| { |
| DE_ASSERT(framebuffers.size() == imageViews.size()); |
| |
| for (size_t ndx = 0; ndx < framebuffers.size(); ndx++) |
| framebuffers[ndx] = createFramebuffer(vkd, device, renderPass, imageViews[ndx], width, height).disown(); |
| } |
| |
| void deinitFramebuffers (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| std::vector<vk::VkFramebuffer>& framebuffers) |
| { |
| for (size_t ndx = 0; ndx < framebuffers.size(); ndx++) |
| { |
| if (framebuffers[ndx] != (vk::VkFramebuffer)0) |
| vkd.destroyFramebuffer(device, framebuffers[ndx], DE_NULL); |
| |
| framebuffers[ndx] = (vk::VkFramebuffer)0; |
| } |
| |
| framebuffers.clear(); |
| } |
| |
| vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkImage image, |
| vk::VkFormat format) |
| { |
| const vk::VkImageViewCreateInfo createInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, |
| DE_NULL, |
| |
| 0u, |
| image, |
| vk::VK_IMAGE_VIEW_TYPE_2D, |
| format, |
| vk::makeComponentMappingRGBA(), |
| { |
| vk::VK_IMAGE_ASPECT_COLOR_BIT, |
| 0u, |
| 1u, |
| 0u, |
| 1u |
| } |
| }; |
| |
| return vk::createImageView(vkd, device, &createInfo, DE_NULL); |
| } |
| |
| void initImageViews (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| const std::vector<vk::VkImage>& images, |
| vk::VkFormat format, |
| std::vector<vk::VkImageView>& imageViews) |
| { |
| DE_ASSERT(images.size() == imageViews.size()); |
| |
| for (size_t ndx = 0; ndx < imageViews.size(); ndx++) |
| imageViews[ndx] = createImageView(vkd, device, images[ndx], format).disown(); |
| } |
| |
| void deinitImageViews (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| std::vector<vk::VkImageView>& imageViews) |
| { |
| for (size_t ndx = 0; ndx < imageViews.size(); ndx++) |
| { |
| if (imageViews[ndx] != (vk::VkImageView)0) |
| vkd.destroyImageView(device, imageViews[ndx], DE_NULL); |
| |
| imageViews[ndx] = (vk::VkImageView)0; |
| } |
| |
| imageViews.clear(); |
| } |
| |
| vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkFormat format) |
| { |
| return vk::makeRenderPass(vkd, device, format, vk::VK_FORMAT_UNDEFINED, vk::VK_ATTACHMENT_LOAD_OP_LOAD, vk::VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); |
| } |
| |
| vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vkd, |
| vk::VkDevice device, |
| vk::VkRenderPass renderPass, |
| vk::VkPipelineLayout layout, |
| vk::VkShaderModule vertexShaderModule, |
| vk::VkShaderModule fragmentShaderModule, |
| deUint32 width, |
| deUint32 height) |
| { |
| const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = |
| { |
| vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, |
| DE_NULL, |
| 0u, |
| 0u, |
| DE_NULL, |
| 0u, |
| DE_NULL |
| }; |
| const std::vector<vk::VkViewport> viewports (1, vk::makeViewport(tcu::UVec2(width, height))); |
| const std::vector<vk::VkRect2D> scissors (1, vk::makeRect2D(tcu::UVec2(width, height))); |
| |
| return vk::makeGraphicsPipeline(vkd, // const DeviceInterface& vk |
| device, // const VkDevice device |
| layout, // const VkPipelineLayout pipelineLayout |
| vertexShaderModule, // const VkShaderModule vertexShaderModule |
| DE_NULL, // const VkShaderModule tessellationControlShaderModule |
| DE_NULL, // const VkShaderModule tessellationEvalShaderModule |
| DE_NULL, // const VkShaderModule geometryShaderModule |
| fragmentShaderModule, // const VkShaderModule fragmentShaderModule |
| renderPass, // const VkRenderPass renderPass |
| viewports, // const std::vector<VkViewport>& viewports |
| scissors, // const std::vector<VkRect2D>& scissors |
| vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology |
| 0u, // const deUint32 subpass |
| 0u, // const deUint32 patchControlPoints |
| &vertexInputState); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo |
| } |
| |
| vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vkd, |
| vk::VkDevice device) |
| { |
| const vk::VkPushConstantRange pushConstants[] = |
| { |
| { |
| vk::VK_SHADER_STAGE_FRAGMENT_BIT, |
| 0u, |
| 4u |
| } |
| }; |
| const vk::VkPipelineLayoutCreateInfo createInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| DE_NULL, |
| 0u, |
| |
| 0u, |
| DE_NULL, |
| |
| DE_LENGTH_OF_ARRAY(pushConstants), |
| pushConstants |
| }; |
| |
| return vk::createPipelineLayout(vkd, device, &createInfo); |
| } |
| |
| struct TestConfig |
| { |
| vk::wsi::Type wsiType; |
| Scaling scaling; |
| bool useIncrementalPresent; |
| vk::VkPresentModeKHR presentMode; |
| vk::VkSurfaceTransformFlagsKHR transform; |
| vk::VkCompositeAlphaFlagsKHR alpha; |
| }; |
| |
| class IncrementalPresentTestInstance : public TestInstance |
| { |
| public: |
| IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig); |
| ~IncrementalPresentTestInstance (void); |
| |
| tcu::TestStatus iterate (void); |
| |
| private: |
| const TestConfig m_testConfig; |
| const bool m_useIncrementalPresent; |
| const vk::PlatformInterface& m_vkp; |
| const Extensions m_instanceExtensions; |
| const vk::Unique<vk::VkInstance> m_instance; |
| const vk::InstanceDriver m_vki; |
| const vk::VkPhysicalDevice m_physicalDevice; |
| const de::UniquePtr<vk::wsi::Display> m_nativeDisplay; |
| const de::UniquePtr<vk::wsi::Window> m_nativeWindow; |
| const vk::Unique<vk::VkSurfaceKHR> m_surface; |
| |
| const deUint32 m_queueFamilyIndex; |
| const Extensions m_deviceExtensions; |
| const vk::Unique<vk::VkDevice> m_device; |
| const vk::DeviceDriver m_vkd; |
| const vk::VkQueue m_queue; |
| |
| const vk::Unique<vk::VkCommandPool> m_commandPool; |
| const vk::Unique<vk::VkShaderModule> m_vertexShaderModule; |
| const vk::Unique<vk::VkShaderModule> m_fragmentShaderModule; |
| const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout; |
| |
| const vk::VkSurfaceCapabilitiesKHR m_surfaceProperties; |
| const vector<vk::VkSurfaceFormatKHR> m_surfaceFormats; |
| const vector<vk::VkPresentModeKHR> m_presentModes; |
| |
| tcu::ResultCollector m_resultCollector; |
| |
| vk::Move<vk::VkSwapchainKHR> m_swapchain; |
| std::vector<vk::VkImage> m_swapchainImages; |
| std::vector<size_t> m_imageNextFrames; |
| std::vector<bool> m_isFirst; |
| |
| vk::Move<vk::VkRenderPass> m_renderPass; |
| vk::Move<vk::VkPipeline> m_pipeline; |
| |
| std::vector<vk::VkImageView> m_swapchainImageViews; |
| std::vector<vk::VkFramebuffer> m_framebuffers; |
| std::vector<vk::VkCommandBuffer> m_commandBuffers; |
| std::vector<vk::VkSemaphore> m_acquireSemaphores; |
| std::vector<vk::VkSemaphore> m_renderSemaphores; |
| std::vector<vk::VkFence> m_fences; |
| |
| vk::VkSemaphore m_freeAcquireSemaphore; |
| vk::VkSemaphore m_freeRenderSemaphore; |
| |
| std::vector<vk::VkSwapchainCreateInfoKHR> m_swapchainConfigs; |
| size_t m_swapchainConfigNdx; |
| |
| const size_t m_frameCount; |
| size_t m_frameNdx; |
| |
| const size_t m_maxOutOfDateCount; |
| size_t m_outOfDateCount; |
| |
| void initSwapchainResources (void); |
| void deinitSwapchainResources (void); |
| void render (void); |
| }; |
| |
| std::vector<vk::VkSwapchainCreateInfoKHR> generateSwapchainConfigs (vk::VkSurfaceKHR surface, |
| const deUint32 *queueFamilyIndex, |
| Scaling scaling, |
| const vk::VkSurfaceCapabilitiesKHR& properties, |
| const vector<vk::VkSurfaceFormatKHR>& formats, |
| const vector<vk::VkPresentModeKHR>& presentModes, |
| vk::VkPresentModeKHR presentMode, |
| const vk::VkSurfaceTransformFlagsKHR transform, |
| const vk::VkCompositeAlphaFlagsKHR alpha) |
| { |
| const deUint32 imageLayers = 1u; |
| const vk::VkImageUsageFlags imageUsage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
| const vk::VkBool32 clipped = VK_FALSE; |
| vector<vk::VkSwapchainCreateInfoKHR> createInfos; |
| |
| const deUint32 currentWidth = properties.currentExtent.width != 0xFFFFFFFFu |
| ? properties.currentExtent.width |
| : de::min(1024u, properties.minImageExtent.width + ((properties.maxImageExtent.width - properties.minImageExtent.width) / 2)); |
| const deUint32 currentHeight = properties.currentExtent.height != 0xFFFFFFFFu |
| ? properties.currentExtent.height |
| : de::min(1024u, properties.minImageExtent.height + ((properties.maxImageExtent.height - properties.minImageExtent.height) / 2)); |
| |
| const deUint32 imageWidth = scaling == SCALING_NONE |
| ? currentWidth |
| : (scaling == SCALING_UP |
| ? de::max(31u, properties.minImageExtent.width) |
| : de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentWidth+1), properties.maxImageExtent.width)); |
| const deUint32 imageHeight = scaling == SCALING_NONE |
| ? currentHeight |
| : (scaling == SCALING_UP |
| ? de::max(31u, properties.minImageExtent.height) |
| : de::min(deSmallestGreaterOrEquallPowerOfTwoU32(currentHeight+1), properties.maxImageExtent.height)); |
| const vk::VkExtent2D imageSize = { imageWidth, imageHeight }; |
| const vk::VkExtent2D dummySize = { de::max(31u, properties.minImageExtent.width), de::max(31u, properties.minImageExtent.height) }; |
| |
| { |
| size_t presentModeNdx; |
| |
| for (presentModeNdx = 0; presentModeNdx < presentModes.size(); presentModeNdx++) |
| { |
| if (presentModes[presentModeNdx] == presentMode) |
| break; |
| } |
| |
| if (presentModeNdx == presentModes.size()) |
| TCU_THROW(NotSupportedError, "Present mode not supported"); |
| |
| if ((properties.supportedTransforms & transform) == 0) |
| TCU_THROW(NotSupportedError, "Transform not supported"); |
| |
| if ((properties.supportedCompositeAlpha & alpha) == 0) |
| TCU_THROW(NotSupportedError, "Composite alpha not supported"); |
| } |
| |
| for (size_t formatNdx = 0; formatNdx < formats.size(); formatNdx++) |
| { |
| |
| const vk::VkSurfaceTransformFlagBitsKHR preTransform = (vk::VkSurfaceTransformFlagBitsKHR)transform; |
| const vk::VkCompositeAlphaFlagBitsKHR compositeAlpha = (vk::VkCompositeAlphaFlagBitsKHR)alpha; |
| const vk::VkFormat imageFormat = formats[formatNdx].format; |
| const vk::VkColorSpaceKHR imageColorSpace = formats[formatNdx].colorSpace; |
| const vk::VkSwapchainCreateInfoKHR createInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, |
| DE_NULL, |
| 0u, |
| surface, |
| properties.minImageCount, |
| imageFormat, |
| imageColorSpace, |
| imageSize, |
| imageLayers, |
| imageUsage, |
| vk::VK_SHARING_MODE_EXCLUSIVE, |
| 1u, |
| queueFamilyIndex, |
| preTransform, |
| compositeAlpha, |
| presentMode, |
| clipped, |
| (vk::VkSwapchainKHR)0 |
| }; |
| |
| createInfos.push_back(createInfo); |
| |
| // add an extra dummy swapchain |
| const vk::VkSwapchainCreateInfoKHR dummyInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, |
| DE_NULL, |
| 0u, |
| surface, |
| properties.minImageCount, |
| imageFormat, |
| imageColorSpace, |
| dummySize, |
| imageLayers, |
| imageUsage, |
| vk::VK_SHARING_MODE_EXCLUSIVE, |
| 1u, |
| queueFamilyIndex, |
| preTransform, |
| compositeAlpha, |
| presentMode, |
| clipped, |
| (vk::VkSwapchainKHR)0 |
| }; |
| |
| createInfos.push_back(dummyInfo); |
| } |
| |
| return createInfos; |
| } |
| |
| IncrementalPresentTestInstance::IncrementalPresentTestInstance (Context& context, const TestConfig& testConfig) |
| : TestInstance (context) |
| , m_testConfig (testConfig) |
| , m_useIncrementalPresent (testConfig.useIncrementalPresent) |
| , m_vkp (context.getPlatformInterface()) |
| , m_instanceExtensions (vk::enumerateInstanceExtensionProperties(m_vkp, DE_NULL)) |
| , m_instance (createInstanceWithWsi(m_vkp, context.getUsedApiVersion(), m_instanceExtensions, testConfig.wsiType)) |
| , m_vki (m_vkp, *m_instance) |
| , m_physicalDevice (vk::chooseDevice(m_vki, *m_instance, context.getTestContext().getCommandLine())) |
| , m_nativeDisplay (createDisplay(context.getTestContext().getPlatform().getVulkanPlatform(), m_instanceExtensions, testConfig.wsiType)) |
| , m_nativeWindow (createWindow(*m_nativeDisplay, tcu::nothing<UVec2>())) |
| , m_surface (vk::wsi::createSurface(m_vki, *m_instance, testConfig.wsiType, *m_nativeDisplay, *m_nativeWindow)) |
| |
| , m_queueFamilyIndex (chooseQueueFamilyIndex(m_vki, m_physicalDevice, *m_surface)) |
| , m_deviceExtensions (vk::enumerateDeviceExtensionProperties(m_vki, m_physicalDevice, DE_NULL)) |
| , m_device (createDeviceWithWsi(m_vkp, *m_instance, m_vki, m_physicalDevice, m_deviceExtensions, m_queueFamilyIndex, testConfig.useIncrementalPresent)) |
| , m_vkd (m_vkp, *m_instance, *m_device) |
| , m_queue (getDeviceQueue(m_vkd, *m_device, m_queueFamilyIndex, 0u)) |
| |
| , m_commandPool (createCommandPool(m_vkd, *m_device, m_queueFamilyIndex)) |
| , m_vertexShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-vert"), 0u)) |
| , m_fragmentShaderModule (vk::createShaderModule(m_vkd, *m_device, context.getBinaryCollection().get("quad-frag"), 0u)) |
| , m_pipelineLayout (createPipelineLayout(m_vkd, *m_device)) |
| |
| , m_surfaceProperties (vk::wsi::getPhysicalDeviceSurfaceCapabilities(m_vki, m_physicalDevice, *m_surface)) |
| , m_surfaceFormats (vk::wsi::getPhysicalDeviceSurfaceFormats(m_vki, m_physicalDevice, *m_surface)) |
| , m_presentModes (vk::wsi::getPhysicalDeviceSurfacePresentModes(m_vki, m_physicalDevice, *m_surface)) |
| |
| , m_freeAcquireSemaphore ((vk::VkSemaphore)0) |
| , m_freeRenderSemaphore ((vk::VkSemaphore)0) |
| |
| , m_swapchainConfigs (generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, testConfig.presentMode, testConfig.transform, testConfig.alpha)) |
| , m_swapchainConfigNdx (0u) |
| |
| , m_frameCount (60u * 5u) |
| , m_frameNdx (0u) |
| |
| , m_maxOutOfDateCount (20u) |
| , m_outOfDateCount (0u) |
| { |
| { |
| const tcu::ScopedLogSection surfaceInfo (m_context.getTestContext().getLog(), "SurfaceCapabilities", "SurfaceCapabilities"); |
| m_context.getTestContext().getLog() << TestLog::Message << m_surfaceProperties << TestLog::EndMessage; |
| } |
| } |
| |
| IncrementalPresentTestInstance::~IncrementalPresentTestInstance (void) |
| { |
| deinitSwapchainResources(); |
| } |
| |
| void IncrementalPresentTestInstance::initSwapchainResources (void) |
| { |
| const size_t fenceCount = 6; |
| const deUint32 imageWidth = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width; |
| const deUint32 imageHeight = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height; |
| const vk::VkFormat imageFormat = m_swapchainConfigs[m_swapchainConfigNdx].imageFormat; |
| |
| m_swapchain = vk::createSwapchainKHR(m_vkd, *m_device, &m_swapchainConfigs[m_swapchainConfigNdx]); |
| m_swapchainImages = vk::wsi::getSwapchainImages(m_vkd, *m_device, *m_swapchain); |
| |
| m_imageNextFrames.resize(m_swapchainImages.size(), 0); |
| m_isFirst.resize(m_swapchainImages.size(), true); |
| |
| m_renderPass = createRenderPass(m_vkd, *m_device, imageFormat); |
| m_pipeline = createPipeline(m_vkd, *m_device, *m_renderPass, *m_pipelineLayout, *m_vertexShaderModule, *m_fragmentShaderModule, imageWidth, imageHeight); |
| |
| m_swapchainImageViews = std::vector<vk::VkImageView>(m_swapchainImages.size(), (vk::VkImageView)0); |
| m_framebuffers = std::vector<vk::VkFramebuffer>(m_swapchainImages.size(), (vk::VkFramebuffer)0); |
| m_acquireSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0); |
| m_renderSemaphores = std::vector<vk::VkSemaphore>(m_swapchainImages.size(), (vk::VkSemaphore)0); |
| |
| m_fences = std::vector<vk::VkFence>(fenceCount, (vk::VkFence)0); |
| m_commandBuffers = std::vector<vk::VkCommandBuffer>(m_fences.size(), (vk::VkCommandBuffer)0); |
| |
| m_freeAcquireSemaphore = (vk::VkSemaphore)0; |
| m_freeRenderSemaphore = (vk::VkSemaphore)0; |
| |
| m_freeAcquireSemaphore = createSemaphore(m_vkd, *m_device).disown(); |
| m_freeRenderSemaphore = createSemaphore(m_vkd, *m_device).disown(); |
| |
| initImageViews(m_vkd, *m_device, m_swapchainImages, imageFormat, m_swapchainImageViews); |
| initFramebuffers(m_vkd, *m_device, *m_renderPass, m_swapchainImageViews, imageWidth, imageHeight, m_framebuffers); |
| initSemaphores(m_vkd, *m_device, m_acquireSemaphores); |
| initSemaphores(m_vkd, *m_device, m_renderSemaphores); |
| |
| initFences(m_vkd, *m_device, m_fences); |
| } |
| |
| void IncrementalPresentTestInstance::deinitSwapchainResources (void) |
| { |
| VK_CHECK(m_vkd.queueWaitIdle(m_queue)); |
| |
| if (m_freeAcquireSemaphore != (vk::VkSemaphore)0) |
| { |
| m_vkd.destroySemaphore(*m_device, m_freeAcquireSemaphore, DE_NULL); |
| m_freeAcquireSemaphore = (vk::VkSemaphore)0; |
| } |
| |
| if (m_freeRenderSemaphore != (vk::VkSemaphore)0) |
| { |
| m_vkd.destroySemaphore(*m_device, m_freeRenderSemaphore, DE_NULL); |
| m_freeRenderSemaphore = (vk::VkSemaphore)0; |
| } |
| |
| deinitSemaphores(m_vkd, *m_device, m_acquireSemaphores); |
| deinitSemaphores(m_vkd, *m_device, m_renderSemaphores); |
| deinitFences(m_vkd, *m_device, m_fences); |
| deinitCommandBuffers(m_vkd, *m_device, *m_commandPool, m_commandBuffers); |
| deinitFramebuffers(m_vkd, *m_device, m_framebuffers); |
| deinitImageViews(m_vkd, *m_device, m_swapchainImageViews); |
| |
| m_swapchainImages.clear(); |
| m_imageNextFrames.clear(); |
| m_isFirst.clear(); |
| |
| m_swapchain = vk::Move<vk::VkSwapchainKHR>(); |
| m_renderPass = vk::Move<vk::VkRenderPass>(); |
| m_pipeline = vk::Move<vk::VkPipeline>(); |
| |
| } |
| |
| void IncrementalPresentTestInstance::render (void) |
| { |
| const deUint64 foreverNs = 0xFFFFFFFFFFFFFFFFul; |
| const vk::VkFence fence = m_fences[m_frameNdx % m_fences.size()]; |
| const deUint32 width = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.width; |
| const deUint32 height = m_swapchainConfigs[m_swapchainConfigNdx].imageExtent.height; |
| size_t imageNextFrame; |
| |
| // Throttle execution |
| if (m_frameNdx >= m_fences.size()) |
| { |
| VK_CHECK(m_vkd.waitForFences(*m_device, 1u, &fence, VK_TRUE, foreverNs)); |
| VK_CHECK(m_vkd.resetFences(*m_device, 1u, &fence)); |
| |
| m_vkd.freeCommandBuffers(*m_device, *m_commandPool, 1u, &m_commandBuffers[m_frameNdx % m_commandBuffers.size()]); |
| m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = (vk::VkCommandBuffer)0; |
| } |
| |
| vk::VkSemaphore currentAcquireSemaphore = m_freeAcquireSemaphore; |
| vk::VkSemaphore currentRenderSemaphore = m_freeRenderSemaphore; |
| deUint32 imageIndex; |
| |
| // Acquire next image |
| VK_CHECK(m_vkd.acquireNextImageKHR(*m_device, *m_swapchain, foreverNs, currentAcquireSemaphore, (vk::VkFence)0, &imageIndex)); |
| |
| // Create command buffer |
| { |
| imageNextFrame = m_imageNextFrames[imageIndex]; |
| m_commandBuffers[m_frameNdx % m_commandBuffers.size()] = createCommandBuffer(m_vkd, *m_device, *m_commandPool, *m_pipelineLayout, *m_renderPass, m_framebuffers[imageIndex], *m_pipeline, m_swapchainImages[imageIndex], m_isFirst[imageIndex], imageNextFrame, m_frameNdx, width, height).disown(); |
| m_imageNextFrames[imageIndex] = m_frameNdx + 1; |
| m_isFirst[imageIndex] = false; |
| } |
| |
| // Submit command buffer |
| { |
| const vk::VkPipelineStageFlags dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; |
| const vk::VkSubmitInfo submitInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, |
| DE_NULL, |
| 1u, |
| ¤tAcquireSemaphore, |
| &dstStageMask, |
| 1u, |
| &m_commandBuffers[m_frameNdx % m_commandBuffers.size()], |
| 1u, |
| ¤tRenderSemaphore |
| }; |
| |
| VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submitInfo, fence)); |
| } |
| |
| // Present frame |
| if (m_useIncrementalPresent) |
| { |
| vk::VkResult result; |
| const vector<vk::VkRectLayerKHR> rects = getUpdatedRects(imageNextFrame, m_frameNdx, width, height); |
| const vk::VkPresentRegionKHR region = |
| { |
| (deUint32)rects.size(), |
| rects.empty() ? DE_NULL : &rects[0] |
| }; |
| const vk::VkPresentRegionsKHR regionInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR, |
| DE_NULL, |
| 1u, |
| ®ion |
| }; |
| const vk::VkPresentInfoKHR presentInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, |
| ®ionInfo, |
| 1u, |
| ¤tRenderSemaphore, |
| 1u, |
| &*m_swapchain, |
| &imageIndex, |
| &result |
| }; |
| |
| VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo)); |
| VK_CHECK_WSI(result); |
| } |
| else |
| { |
| vk::VkResult result; |
| const vk::VkPresentInfoKHR presentInfo = |
| { |
| vk::VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, |
| DE_NULL, |
| 1u, |
| ¤tRenderSemaphore, |
| 1u, |
| &*m_swapchain, |
| &imageIndex, |
| &result |
| }; |
| |
| VK_CHECK_WSI(m_vkd.queuePresentKHR(m_queue, &presentInfo)); |
| VK_CHECK_WSI(result); |
| } |
| |
| { |
| m_freeAcquireSemaphore = m_acquireSemaphores[imageIndex]; |
| m_acquireSemaphores[imageIndex] = currentAcquireSemaphore; |
| |
| m_freeRenderSemaphore = m_renderSemaphores[imageIndex]; |
| m_renderSemaphores[imageIndex] = currentRenderSemaphore; |
| } |
| } |
| |
| tcu::TestStatus IncrementalPresentTestInstance::iterate (void) |
| { |
| // Initialize swapchain specific resources |
| // Render test |
| try |
| { |
| if (m_frameNdx == 0) |
| { |
| if (m_outOfDateCount == 0) |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Swapchain: " << m_swapchainConfigs[m_swapchainConfigNdx] << tcu::TestLog::EndMessage; |
| |
| initSwapchainResources(); |
| } |
| |
| render(); |
| } |
| catch (const vk::Error& error) |
| { |
| if (error.getError() == vk::VK_ERROR_OUT_OF_DATE_KHR) |
| { |
| m_swapchainConfigs = generateSwapchainConfigs(*m_surface, &m_queueFamilyIndex, m_testConfig.scaling, m_surfaceProperties, m_surfaceFormats, m_presentModes, m_testConfig.presentMode, m_testConfig.transform, m_testConfig.alpha); |
| |
| if (m_outOfDateCount < m_maxOutOfDateCount) |
| { |
| m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date. Recreating resources." << TestLog::EndMessage; |
| deinitSwapchainResources(); |
| m_frameNdx = 0; |
| m_outOfDateCount++; |
| |
| return tcu::TestStatus::incomplete(); |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << TestLog::Message << "Frame " << m_frameNdx << ": Swapchain out of date." << TestLog::EndMessage; |
| m_resultCollector.fail("Received too many VK_ERROR_OUT_OF_DATE_KHR errors. Received " + de::toString(m_outOfDateCount) + ", max " + de::toString(m_maxOutOfDateCount)); |
| } |
| } |
| else |
| { |
| m_resultCollector.fail(error.what()); |
| } |
| |
| deinitSwapchainResources(); |
| |
| m_swapchainConfigNdx++; |
| m_frameNdx = 0; |
| m_outOfDateCount = 0; |
| |
| if (m_swapchainConfigNdx >= m_swapchainConfigs.size()) |
| return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage()); |
| else |
| return tcu::TestStatus::incomplete(); |
| } |
| |
| m_frameNdx++; |
| |
| if (m_frameNdx >= m_frameCount) |
| { |
| m_frameNdx = 0; |
| m_outOfDateCount = 0; |
| m_swapchainConfigNdx++; |
| |
| deinitSwapchainResources(); |
| |
| if (m_swapchainConfigNdx >= m_swapchainConfigs.size()) |
| return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage()); |
| else |
| return tcu::TestStatus::incomplete(); |
| } |
| else |
| return tcu::TestStatus::incomplete(); |
| } |
| |
| struct Programs |
| { |
| static void init (vk::SourceCollections& dst, TestConfig) |
| { |
| dst.glslSources.add("quad-vert") << glu::VertexSource( |
| "#version 450\n" |
| "out gl_PerVertex {\n" |
| "\tvec4 gl_Position;\n" |
| "};\n" |
| "highp float;\n" |
| "void main (void) {\n" |
| "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n" |
| "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n" |
| "}\n"); |
| dst.glslSources.add("quad-frag") << glu::FragmentSource( |
| "#version 310 es\n" |
| "layout(location = 0) out highp vec4 o_color;\n" |
| "layout(push_constant) uniform PushConstant {\n" |
| "\thighp uint mask;\n" |
| "} pushConstants;\n" |
| "void main (void)\n" |
| "{\n" |
| "\thighp uint mask = pushConstants.mask;\n" |
| "\thighp uint x = mask ^ uint(gl_FragCoord.x);\n" |
| "\thighp uint y = mask ^ uint(gl_FragCoord.y);\n" |
| "\thighp uint r = 128u * bitfieldExtract(x, 0, 1)\n" |
| "\t + 64u * bitfieldExtract(y, 1, 1)\n" |
| "\t + 32u * bitfieldExtract(x, 3, 1);\n" |
| "\thighp uint g = 128u * bitfieldExtract(y, 0, 1)\n" |
| "\t + 64u * bitfieldExtract(x, 2, 1)\n" |
| "\t + 32u * bitfieldExtract(y, 3, 1);\n" |
| "\thighp uint b = 128u * bitfieldExtract(x, 1, 1)\n" |
| "\t + 64u * bitfieldExtract(y, 2, 1)\n" |
| "\t + 32u * bitfieldExtract(x, 4, 1);\n" |
| "\to_color = vec4(float(r) / 255.0, float(g) / 255.0, float(b) / 255.0, 1.0);\n" |
| "}\n"); |
| } |
| }; |
| |
| } // anonymous |
| |
| void createIncrementalPresentTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType) |
| { |
| const struct |
| { |
| Scaling scaling; |
| const char* name; |
| } scaling [] = |
| { |
| { SCALING_NONE, "scale_none" }, |
| { SCALING_UP, "scale_up" }, |
| { SCALING_DOWN, "scale_down" } |
| }; |
| const struct |
| { |
| vk::VkPresentModeKHR mode; |
| const char* name; |
| } presentModes[] = |
| { |
| { vk::VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" }, |
| { vk::VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" }, |
| { vk::VK_PRESENT_MODE_FIFO_KHR, "fifo" }, |
| { vk::VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" } |
| }; |
| const struct |
| { |
| vk::VkSurfaceTransformFlagsKHR transform; |
| const char* name; |
| } transforms[] = |
| { |
| { vk::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, "identity" }, |
| { vk::VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, "rotate_90" }, |
| { vk::VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, "rotate_180" }, |
| { vk::VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR, "rotate_270" }, |
| { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR, "horizontal_mirror" }, |
| { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR, "horizontal_mirror_rotate_90" }, |
| { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR, "horizontal_mirror_rotate_180" }, |
| { vk::VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR, "horizontal_mirror_rotate_270" }, |
| { vk::VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR, "inherit" } |
| }; |
| const struct |
| { |
| vk::VkCompositeAlphaFlagsKHR alpha; |
| const char* name; |
| } alphas[] = |
| { |
| { vk::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, "opaque" }, |
| { vk::VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, "pre_multiplied" }, |
| { vk::VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, "post_multiplied" }, |
| { vk::VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, "inherit" } |
| }; |
| |
| for (size_t scalingNdx = 0; scalingNdx < DE_LENGTH_OF_ARRAY(scaling); scalingNdx++) |
| { |
| if (scaling[scalingNdx].scaling != SCALING_NONE && wsiType == vk::wsi::TYPE_WAYLAND) |
| continue; |
| |
| if (scaling[scalingNdx].scaling != SCALING_NONE && vk::wsi::getPlatformProperties(wsiType).swapchainExtent != vk::wsi::PlatformProperties::SWAPCHAIN_EXTENT_SCALED_TO_WINDOW_SIZE) |
| continue; |
| |
| { |
| |
| de::MovePtr<tcu::TestCaseGroup> scaleGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), scaling[scalingNdx].name, scaling[scalingNdx].name)); |
| |
| for (size_t presentModeNdx = 0; presentModeNdx < DE_LENGTH_OF_ARRAY(presentModes); presentModeNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> presentModeGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), presentModes[presentModeNdx].name, presentModes[presentModeNdx].name)); |
| |
| for (size_t transformNdx = 0; transformNdx < DE_LENGTH_OF_ARRAY(transforms); transformNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> transformGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), transforms[transformNdx].name, transforms[transformNdx].name)); |
| |
| for (size_t alphaNdx = 0; alphaNdx < DE_LENGTH_OF_ARRAY(alphas); alphaNdx++) |
| { |
| de::MovePtr<tcu::TestCaseGroup> alphaGroup (new tcu::TestCaseGroup(testGroup->getTestContext(), alphas[alphaNdx].name, alphas[alphaNdx].name)); |
| |
| for (size_t ref = 0; ref < 2; ref++) |
| { |
| const bool isReference = (ref == 0); |
| const char* const name = isReference ? "reference" : "incremental_present"; |
| TestConfig config; |
| |
| config.wsiType = wsiType; |
| config.scaling = scaling[scalingNdx].scaling; |
| config.useIncrementalPresent = !isReference; |
| config.presentMode = presentModes[presentModeNdx].mode; |
| config.transform = transforms[transformNdx].transform; |
| config.alpha = alphas[alphaNdx].alpha; |
| |
| alphaGroup->addChild(new vkt::InstanceFactory1<IncrementalPresentTestInstance, TestConfig, Programs>(testGroup->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, name, Programs(), config)); |
| } |
| |
| transformGroup->addChild(alphaGroup.release()); |
| } |
| |
| presentModeGroup->addChild(transformGroup.release()); |
| } |
| |
| scaleGroup->addChild(presentModeGroup.release()); |
| } |
| |
| testGroup->addChild(scaleGroup.release()); |
| } |
| } |
| } |
| |
| } // wsi |
| } // vkt |