From 8e1cce4ba720300676a239cb264795c9ea301cbc Mon Sep 17 00:00:00 2001 From: Pyry Haulos Date: Mon, 11 Apr 2016 16:37:53 -0700 Subject: [PATCH] Add basic WSI rendering test Bug: 27536551 Bug: 27641433 Change-Id: Icc74ea9c6d669ced21e536ee96f0dd04d5e47343 --- android/cts/master/com.drawelements.deqp.vk.xml | 5 + android/cts/master/vk-master.txt | 1 + .../vulkancts/framework/vulkan/vkBasicTypes.inl | 1 + external/vulkancts/framework/vulkan/vkWsiUtil.cpp | 20 + external/vulkancts/framework/vulkan/vkWsiUtil.hpp | 4 + external/vulkancts/gen_framework.py | 1 + .../modules/vulkan/wsi/vktWsiSwapchainTests.cpp | 885 +++++++++++++++++++++ 7 files changed, 917 insertions(+) diff --git a/android/cts/master/com.drawelements.deqp.vk.xml b/android/cts/master/com.drawelements.deqp.vk.xml index 9c4e1d4..ea34bef 100644 --- a/android/cts/master/com.drawelements.deqp.vk.xml +++ b/android/cts/master/com.drawelements.deqp.vk.xml @@ -261362,6 +261362,11 @@ + + + + + diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 94fd6a8..8e09788 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -81128,6 +81128,7 @@ dEQP-VK.wsi.android.swapchain.simulate_oom.pre_transform dEQP-VK.wsi.android.swapchain.simulate_oom.composite_alpha dEQP-VK.wsi.android.swapchain.simulate_oom.present_mode dEQP-VK.wsi.android.swapchain.simulate_oom.clipped +dEQP-VK.wsi.android.swapchain.render.basic dEQP-VK.synchronization.fences dEQP-VK.synchronization.semaphores dEQP-VK.synchronization.events diff --git a/external/vulkancts/framework/vulkan/vkBasicTypes.inl b/external/vulkancts/framework/vulkan/vkBasicTypes.inl index 5e5db01..a00b8e3 100644 --- a/external/vulkancts/framework/vulkan/vkBasicTypes.inl +++ b/external/vulkancts/framework/vulkan/vkBasicTypes.inl @@ -9,6 +9,7 @@ enum { VK_MAX_MEMORY_TYPES = 32 }; enum { VK_MAX_MEMORY_HEAPS = 16 }; enum { VK_MAX_DESCRIPTION_SIZE = 256 }; enum { VK_ATTACHMENT_UNUSED = (~0U) }; +enum { VK_SUBPASS_EXTERNAL = (~0U) }; VK_DEFINE_HANDLE (VkInstance, HANDLE_TYPE_INSTANCE); VK_DEFINE_HANDLE (VkPhysicalDevice, HANDLE_TYPE_PHYSICAL_DEVICE); diff --git a/external/vulkancts/framework/vulkan/vkWsiUtil.cpp b/external/vulkancts/framework/vulkan/vkWsiUtil.cpp index 6f0968d..d94610b 100644 --- a/external/vulkancts/framework/vulkan/vkWsiUtil.cpp +++ b/external/vulkancts/framework/vulkan/vkWsiUtil.cpp @@ -310,5 +310,25 @@ std::vector getPhysicalDeviceSurfacePresentModes (const Instan return std::vector(); } +std::vector getSwapchainImages (const DeviceInterface& vkd, + VkDevice device, + VkSwapchainKHR swapchain) +{ + deUint32 numImages = 0; + + VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, DE_NULL)); + + if (numImages > 0) + { + std::vector images (numImages); + + VK_CHECK(vkd.getSwapchainImagesKHR(device, swapchain, &numImages, &images[0])); + + return images; + } + else + return std::vector(); +} + } // wsi } // vk diff --git a/external/vulkancts/framework/vulkan/vkWsiUtil.hpp b/external/vulkancts/framework/vulkan/vkWsiUtil.hpp index e7da7d7..bee82de 100644 --- a/external/vulkancts/framework/vulkan/vkWsiUtil.hpp +++ b/external/vulkancts/framework/vulkan/vkWsiUtil.hpp @@ -94,6 +94,10 @@ std::vector getPhysicalDeviceSurfacePresentModes (const Instan VkPhysicalDevice physicalDevice, VkSurfaceKHR surface); +std::vector getSwapchainImages (const DeviceInterface& vkd, + VkDevice device, + VkSwapchainKHR swapchain); + } // wsi } // vk diff --git a/external/vulkancts/gen_framework.py b/external/vulkancts/gen_framework.py index 4cf7263..e6d9e55 100644 --- a/external/vulkancts/gen_framework.py +++ b/external/vulkancts/gen_framework.py @@ -113,6 +113,7 @@ DEFINITIONS = [ "VK_MAX_MEMORY_HEAPS", "VK_MAX_DESCRIPTION_SIZE", "VK_ATTACHMENT_UNUSED", + "VK_SUBPASS_EXTERNAL" ] PLATFORM_TYPES = [ diff --git a/external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp b/external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp index 5ddfa64..6935899 100644 --- a/external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp +++ b/external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp @@ -48,6 +48,9 @@ #include "deUniquePtr.hpp" #include "deStringUtil.hpp" #include "deArrayUtil.hpp" +#include "deSharedPtr.hpp" + +#include namespace vkt { @@ -671,12 +674,894 @@ void populateSwapchainGroup (tcu::TestCaseGroup* testGroup, GroupParameters para } } +VkSwapchainCreateInfoKHR getBasicSwapchainParameters (Type wsiType, + const InstanceInterface& vki, + VkPhysicalDevice physicalDevice, + VkSurfaceKHR surface, + const tcu::UVec2& desiredSize, + deUint32 desiredImageCount) +{ + const VkSurfaceCapabilitiesKHR capabilities = getPhysicalDeviceSurfaceCapabilities(vki, + physicalDevice, + surface); + const vector formats = getPhysicalDeviceSurfaceFormats(vki, + physicalDevice, + surface); + const PlatformProperties& platformProperties = getPlatformProperties(wsiType); + const VkSwapchainCreateInfoKHR parameters = + { + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + DE_NULL, + (VkSwapchainCreateFlagsKHR)0, + surface, + de::clamp(desiredImageCount, capabilities.minImageCount, capabilities.maxImageCount), + formats[0].format, + formats[0].colorSpace, + (platformProperties.swapchainExtent == PlatformProperties::SWAPCHAIN_EXTENT_MUST_MATCH_WINDOW_SIZE + ? capabilities.currentExtent : vk::makeExtent2D(desiredSize.x(), desiredSize.y())), + 1u, // imageArrayLayers + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_SHARING_MODE_EXCLUSIVE, + 0u, + (const deUint32*)DE_NULL, + VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + VK_PRESENT_MODE_FIFO_KHR, + VK_FALSE, // clipped + (VkSwapchainKHR)0 // oldSwapchain + }; + + return parameters; +} + +typedef de::SharedPtr > ImageViewSp; +typedef de::SharedPtr > FramebufferSp; + +class TriangleRenderer +{ +public: + TriangleRenderer (const DeviceInterface& vkd, + const VkDevice device, + Allocator& allocator, + const BinaryCollection& binaryRegistry, + const vector swapchainImages, + const VkFormat framebufferFormat, + const UVec2& renderSize); + ~TriangleRenderer (void); + + void recordFrame (VkCommandBuffer cmdBuffer, + deUint32 imageNdx, + deUint32 frameNdx) const; + + static void getPrograms (SourceCollections& dst); + +private: + static Move createRenderPass (const DeviceInterface& vkd, + const VkDevice device, + const VkFormat colorAttachmentFormat); + static Move createPipelineLayout(const DeviceInterface& vkd, + VkDevice device); + static Move createPipeline (const DeviceInterface& vkd, + const VkDevice device, + const VkRenderPass renderPass, + const VkPipelineLayout pipelineLayout, + const BinaryCollection& binaryCollection, + const UVec2& renderSize); + + static Move createAttachmentView(const DeviceInterface& vkd, + const VkDevice device, + const VkImage image, + const VkFormat format); + static Move createFramebuffer (const DeviceInterface& vkd, + const VkDevice device, + const VkRenderPass renderPass, + const VkImageView colorAttachment, + const UVec2& renderSize); + + static Move createBuffer (const DeviceInterface& vkd, + VkDevice device, + VkDeviceSize size, + VkBufferUsageFlags usage); + + const DeviceInterface& m_vkd; + + const vector m_swapchainImages; + const tcu::UVec2 m_renderSize; + + const Unique m_renderPass; + const Unique m_pipelineLayout; + const Unique m_pipeline; + + const Unique m_vertexBuffer; + const UniquePtr m_vertexBufferMemory; + + vector m_attachmentViews; + vector m_framebuffers; +}; + +Move TriangleRenderer::createRenderPass (const DeviceInterface& vkd, + const VkDevice device, + const VkFormat colorAttachmentFormat) +{ + const VkAttachmentDescription colorAttDesc = + { + (VkAttachmentDescriptionFlags)0, + colorAttachmentFormat, + VK_SAMPLE_COUNT_1_BIT, + VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_STORE_OP_STORE, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_DONT_CARE, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + }; + const VkAttachmentReference colorAttRef = + { + 0u, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + }; + const VkSubpassDescription subpassDesc = + { + (VkSubpassDescriptionFlags)0u, + VK_PIPELINE_BIND_POINT_GRAPHICS, + 0u, // inputAttachmentCount + DE_NULL, // pInputAttachments + 1u, // colorAttachmentCount + &colorAttRef, // pColorAttachments + DE_NULL, // pResolveAttachments + DE_NULL, // depthStencilAttachment + 0u, // preserveAttachmentCount + DE_NULL, // pPreserveAttachments + }; + const VkSubpassDependency dependencies[] = + { + { + VK_SUBPASS_EXTERNAL, // srcSubpass + 0u, // dstSubpass + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_MEMORY_READ_BIT, + (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT| + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), + VK_DEPENDENCY_BY_REGION_BIT + }, + { + 0u, // srcSubpass + VK_SUBPASS_EXTERNAL, // dstSubpass + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT| + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), + VK_ACCESS_MEMORY_READ_BIT, + VK_DEPENDENCY_BY_REGION_BIT + }, + }; + const VkRenderPassCreateInfo renderPassParams = + { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + DE_NULL, + (VkRenderPassCreateFlags)0, + 1u, + &colorAttDesc, + 1u, + &subpassDesc, + DE_LENGTH_OF_ARRAY(dependencies), + dependencies, + }; + + return vk::createRenderPass(vkd, device, &renderPassParams); +} + +Move TriangleRenderer::createPipelineLayout (const DeviceInterface& vkd, + const VkDevice device) +{ + const VkPushConstantRange pushConstantRange = + { + VK_SHADER_STAGE_VERTEX_BIT, + 0u, // offset + (deUint32)sizeof(deUint32), // size + }; + const VkPipelineLayoutCreateInfo pipelineLayoutParams = + { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + DE_NULL, + (vk::VkPipelineLayoutCreateFlags)0, + 0u, // setLayoutCount + DE_NULL, // pSetLayouts + 1u, + &pushConstantRange, + }; + + return vk::createPipelineLayout(vkd, device, &pipelineLayoutParams); +} + +Move TriangleRenderer::createPipeline (const DeviceInterface& vkd, + const VkDevice device, + const VkRenderPass renderPass, + const VkPipelineLayout pipelineLayout, + const BinaryCollection& binaryCollection, + const UVec2& renderSize) +{ + // \note VkShaderModules are fully consumed by vkCreateGraphicsPipelines() + // and can be deleted immediately following that call. + const Unique vertShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-vert"), 0)); + const Unique fragShaderModule (createShaderModule(vkd, device, binaryCollection.get("tri-frag"), 0)); + + const VkSpecializationInfo emptyShaderSpecParams = + { + 0u, // mapEntryCount + DE_NULL, // pMap + 0, // dataSize + DE_NULL, // pData + }; + const VkPipelineShaderStageCreateInfo shaderStageParams[] = + { + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + DE_NULL, + (VkPipelineShaderStageCreateFlags)0, + VK_SHADER_STAGE_VERTEX_BIT, + *vertShaderModule, + "main", + &emptyShaderSpecParams, + }, + { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + DE_NULL, + (VkPipelineShaderStageCreateFlags)0, + VK_SHADER_STAGE_FRAGMENT_BIT, + *fragShaderModule, + "main", + &emptyShaderSpecParams, + } + }; + const VkPipelineDepthStencilStateCreateInfo depthStencilParams = + { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineDepthStencilStateCreateFlags)0, + DE_FALSE, // depthTestEnable + DE_FALSE, // depthWriteEnable + VK_COMPARE_OP_ALWAYS, // depthCompareOp + DE_FALSE, // depthBoundsTestEnable + DE_FALSE, // stencilTestEnable + { + VK_STENCIL_OP_KEEP, // failOp + VK_STENCIL_OP_KEEP, // passOp + VK_STENCIL_OP_KEEP, // depthFailOp + VK_COMPARE_OP_ALWAYS, // compareOp + 0u, // compareMask + 0u, // writeMask + 0u, // reference + }, // front + { + VK_STENCIL_OP_KEEP, // failOp + VK_STENCIL_OP_KEEP, // passOp + VK_STENCIL_OP_KEEP, // depthFailOp + VK_COMPARE_OP_ALWAYS, // compareOp + 0u, // compareMask + 0u, // writeMask + 0u, // reference + }, // back + -1.0f, // minDepthBounds + +1.0f, // maxDepthBounds + }; + const VkViewport viewport0 = + { + 0.0f, // x + 0.0f, // y + (float)renderSize.x(), // width + (float)renderSize.y(), // height + 0.0f, // minDepth + 1.0f, // maxDepth + }; + const VkRect2D scissor0 = + { + { 0u, 0u, }, // offset + { renderSize.x(), renderSize.y() }, // extent + }; + const VkPipelineViewportStateCreateInfo viewportParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineViewportStateCreateFlags)0, + 1u, + &viewport0, + 1u, + &scissor0 + }; + const VkPipelineMultisampleStateCreateInfo multisampleParams = + { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineMultisampleStateCreateFlags)0, + VK_SAMPLE_COUNT_1_BIT, // rasterizationSamples + VK_FALSE, // sampleShadingEnable + 0.0f, // minSampleShading + (const VkSampleMask*)DE_NULL, // sampleMask + VK_FALSE, // alphaToCoverageEnable + VK_FALSE, // alphaToOneEnable + }; + const VkPipelineRasterizationStateCreateInfo rasterParams = + { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineRasterizationStateCreateFlags)0, + VK_TRUE, // depthClampEnable + VK_FALSE, // rasterizerDiscardEnable + VK_POLYGON_MODE_FILL, // polygonMode + VK_CULL_MODE_NONE, // cullMode + VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace + VK_FALSE, // depthBiasEnable + 0.0f, // depthBiasConstantFactor + 0.0f, // depthBiasClamp + 0.0f, // depthBiasSlopeFactor + 1.0f, // lineWidth + }; + const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams = + { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineInputAssemblyStateCreateFlags)0, + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + DE_FALSE, // primitiveRestartEnable + }; + const VkVertexInputBindingDescription vertexBinding0 = + { + 0u, // binding + (deUint32)sizeof(tcu::Vec4), // stride + VK_VERTEX_INPUT_RATE_VERTEX, // inputRate + }; + const VkVertexInputAttributeDescription vertexAttrib0 = + { + 0u, // location + 0u, // binding + VK_FORMAT_R32G32B32A32_SFLOAT, // format + 0u, // offset + }; + const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = + { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineVertexInputStateCreateFlags)0, + 1u, + &vertexBinding0, + 1u, + &vertexAttrib0, + }; + const VkPipelineColorBlendAttachmentState attBlendParams0 = + { + VK_FALSE, // blendEnable + VK_BLEND_FACTOR_ONE, // srcColorBlendFactor + VK_BLEND_FACTOR_ZERO, // dstColorBlendFactor + VK_BLEND_OP_ADD, // colorBlendOp + VK_BLEND_FACTOR_ONE, // srcAlphaBlendFactor + VK_BLEND_FACTOR_ZERO, // dstAlphaBlendFactor + VK_BLEND_OP_ADD, // alphaBlendOp + (VK_COLOR_COMPONENT_R_BIT| + VK_COLOR_COMPONENT_G_BIT| + VK_COLOR_COMPONENT_B_BIT| + VK_COLOR_COMPONENT_A_BIT), // colorWriteMask + }; + const VkPipelineColorBlendStateCreateInfo blendParams = + { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + DE_NULL, + (VkPipelineColorBlendStateCreateFlags)0, + VK_FALSE, // logicOpEnable + VK_LOGIC_OP_COPY, + 1u, + &attBlendParams0, + { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConstants[4] + }; + const VkGraphicsPipelineCreateInfo pipelineParams = + { + VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + DE_NULL, + (VkPipelineCreateFlags)0, + (deUint32)DE_LENGTH_OF_ARRAY(shaderStageParams), + shaderStageParams, + &vertexInputStateParams, + &inputAssemblyParams, + (const VkPipelineTessellationStateCreateInfo*)DE_NULL, + &viewportParams, + &rasterParams, + &multisampleParams, + &depthStencilParams, + &blendParams, + (const VkPipelineDynamicStateCreateInfo*)DE_NULL, + pipelineLayout, + renderPass, + 0u, // subpass + DE_NULL, // basePipelineHandle + 0u, // basePipelineIndex + }; + + return vk::createGraphicsPipeline(vkd, device, (VkPipelineCache)0, &pipelineParams); +} + +Move TriangleRenderer::createAttachmentView (const DeviceInterface& vkd, + const VkDevice device, + const VkImage image, + const VkFormat format) +{ + const VkImageViewCreateInfo viewParams = + { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + DE_NULL, + (VkImageViewCreateFlags)0, + image, + VK_IMAGE_VIEW_TYPE_2D, + format, + vk::makeComponentMappingRGBA(), + { + VK_IMAGE_ASPECT_COLOR_BIT, + 0u, // baseMipLevel + 1u, // levelCount + 0u, // baseArrayLayer + 1u, // layerCount + }, + }; + + return vk::createImageView(vkd, device, &viewParams); +} + +Move TriangleRenderer::createFramebuffer (const DeviceInterface& vkd, + const VkDevice device, + const VkRenderPass renderPass, + const VkImageView colorAttachment, + const UVec2& renderSize) +{ + const VkFramebufferCreateInfo framebufferParams = + { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + DE_NULL, + (VkFramebufferCreateFlags)0, + renderPass, + 1u, + &colorAttachment, + renderSize.x(), + renderSize.y(), + 1u, // layers + }; + + return vk::createFramebuffer(vkd, device, &framebufferParams); +} + +Move TriangleRenderer::createBuffer (const DeviceInterface& vkd, + VkDevice device, + VkDeviceSize size, + VkBufferUsageFlags usage) +{ + const VkBufferCreateInfo bufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + DE_NULL, + (VkBufferCreateFlags)0, + size, + usage, + VK_SHARING_MODE_EXCLUSIVE, + 0, + DE_NULL + }; + + return vk::createBuffer(vkd, device, &bufferParams); +} + +TriangleRenderer::TriangleRenderer (const DeviceInterface& vkd, + const VkDevice device, + Allocator& allocator, + const BinaryCollection& binaryRegistry, + const vector swapchainImages, + const VkFormat framebufferFormat, + const UVec2& renderSize) + : m_vkd (vkd) + , m_swapchainImages (swapchainImages) + , m_renderSize (renderSize) + , m_renderPass (createRenderPass(vkd, device, framebufferFormat)) + , m_pipelineLayout (createPipelineLayout(vkd, device)) + , m_pipeline (createPipeline(vkd, device, *m_renderPass, *m_pipelineLayout, binaryRegistry, renderSize)) + , m_vertexBuffer (createBuffer(vkd, device, (VkDeviceSize)(sizeof(float)*4*3), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)) + , m_vertexBufferMemory (allocator.allocate(getBufferMemoryRequirements(vkd, device, *m_vertexBuffer), + MemoryRequirement::HostVisible)) +{ + m_attachmentViews.resize(swapchainImages.size()); + m_framebuffers.resize(swapchainImages.size()); + + for (size_t imageNdx = 0; imageNdx < swapchainImages.size(); ++imageNdx) + { + m_attachmentViews[imageNdx] = ImageViewSp(new Unique(createAttachmentView(vkd, device, swapchainImages[imageNdx], framebufferFormat))); + m_framebuffers[imageNdx] = FramebufferSp(new Unique(createFramebuffer(vkd, device, *m_renderPass, **m_attachmentViews[imageNdx], renderSize))); + } + + VK_CHECK(vkd.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset())); + + { + const VkMappedMemoryRange memRange = + { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + DE_NULL, + m_vertexBufferMemory->getMemory(), + m_vertexBufferMemory->getOffset(), + VK_WHOLE_SIZE + }; + const tcu::Vec4 vertices[] = + { + tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f), + tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f), + tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f) + }; + DE_STATIC_ASSERT(sizeof(vertices) == sizeof(float)*4*3); + + deMemcpy(m_vertexBufferMemory->getHostPtr(), &vertices[0], sizeof(vertices)); + VK_CHECK(vkd.flushMappedMemoryRanges(device, 1u, &memRange)); + } +} + +TriangleRenderer::~TriangleRenderer (void) +{ +} + +void TriangleRenderer::recordFrame (VkCommandBuffer cmdBuffer, + deUint32 imageNdx, + deUint32 frameNdx) const +{ + const VkImage curImage = m_swapchainImages[imageNdx]; + const VkFramebuffer curFramebuffer = **m_framebuffers[imageNdx]; + + { + const VkCommandBufferBeginInfo cmdBufBeginParams = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + DE_NULL, + (VkCommandBufferUsageFlags)0, + (const VkCommandBufferInheritanceInfo*)DE_NULL, + }; + VK_CHECK(m_vkd.beginCommandBuffer(cmdBuffer, &cmdBufBeginParams)); + } + + { + const VkImageMemoryBarrier fromPresentationBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + DE_NULL, + VK_ACCESS_MEMORY_READ_BIT, + (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT| + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + curImage, + { + VK_IMAGE_ASPECT_COLOR_BIT, + 0u, // baseMipLevel + 1u, // levelCount + 0u, // baseArrayLayer + 1u, // layerCount + } + }; + m_vkd.cmdPipelineBarrier(cmdBuffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + (VkDependencyFlags)0, + 0, (const VkMemoryBarrier*)DE_NULL, + 0, (const VkBufferMemoryBarrier*)DE_NULL, + 1, &fromPresentationBarrier); + } + + { + const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f); + const VkRenderPassBeginInfo passBeginParams = + { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + DE_NULL, + *m_renderPass, + curFramebuffer, + { + { 0, 0 }, + { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() } + }, // renderArea + 1u, // clearValueCount + &clearValue, // pClearValues + }; + m_vkd.cmdBeginRenderPass(cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE); + } + + m_vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline); + + { + const VkDeviceSize bindingOffset = 0; + m_vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &bindingOffset); + } + + m_vkd.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(deUint32), &frameNdx); + m_vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u); + m_vkd.cmdEndRenderPass(cmdBuffer); + + { + const VkImageMemoryBarrier toPresentationBarrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + DE_NULL, + (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT| + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), + VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + curImage, + { + VK_IMAGE_ASPECT_COLOR_BIT, + 0u, // baseMipLevel + 1u, // levelCount + 0u, // baseArrayLayer + 1u, // layerCount + } + }; + m_vkd.cmdPipelineBarrier(cmdBuffer, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + (VkDependencyFlags)0, + 0, (const VkMemoryBarrier*)DE_NULL, + 0, (const VkBufferMemoryBarrier*)DE_NULL, + 1, &toPresentationBarrier); + } + + VK_CHECK(m_vkd.endCommandBuffer(cmdBuffer)); +} + +void TriangleRenderer::getPrograms (SourceCollections& dst) +{ + dst.glslSources.add("tri-vert") << glu::VertexSource( + "#version 310 es\n" + "layout(location = 0) in highp vec4 a_position;\n" + "layout(push_constant) uniform FrameData\n" + "{\n" + " highp uint frameNdx;\n" + "} frameData;\n" + "void main (void)\n" + "{\n" + " highp float angle = float(frameData.frameNdx) / 100.0;\n" + " highp float c = cos(angle);\n" + " highp float s = sin(angle);\n" + " highp mat4 t = mat4( c, -s, 0, 0,\n" + " s, c, 0, 0,\n" + " 0, 0, 1, 0,\n" + " 0, 0, 0, 1);\n" + " gl_Position = t * a_position;\n" + "}\n"); + dst.glslSources.add("tri-frag") << glu::FragmentSource( + "#version 310 es\n" + "layout(location = 0) out lowp vec4 o_color;\n" + "void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n"); +} + +typedef de::SharedPtr > CommandBufferSp; +typedef de::SharedPtr > FenceSp; +typedef de::SharedPtr > SemaphoreSp; + +Move createFence (const DeviceInterface& vkd, + const VkDevice device) +{ + const VkFenceCreateInfo fenceParams = + { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + DE_NULL, + (VkFenceCreateFlags)0, + }; + return vk::createFence(vkd, device, &fenceParams); +} + +vector createFences (const DeviceInterface& vkd, + const VkDevice device, + size_t numFences) +{ + vector fences(numFences); + + for (size_t ndx = 0; ndx < numFences; ++ndx) + fences[ndx] = FenceSp(new Unique(createFence(vkd, device))); + + return fences; +} + +Move createSemaphore (const DeviceInterface& vkd, + const VkDevice device) +{ + const VkSemaphoreCreateInfo semaphoreParams = + { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + DE_NULL, + (VkSemaphoreCreateFlags)0, + }; + return vk::createSemaphore(vkd, device, &semaphoreParams); +} + +vector createSemaphores (const DeviceInterface& vkd, + const VkDevice device, + size_t numSemaphores) +{ + vector semaphores(numSemaphores); + + for (size_t ndx = 0; ndx < numSemaphores; ++ndx) + semaphores[ndx] = SemaphoreSp(new Unique(createSemaphore(vkd, device))); + + return semaphores; +} + +Move createCommandPool (const DeviceInterface& vkd, + const VkDevice device, + VkCommandPoolCreateFlags flags, + deUint32 queueFamilyIndex) +{ + const VkCommandPoolCreateInfo commandPoolParams = + { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + DE_NULL, + flags, + queueFamilyIndex + }; + + return createCommandPool(vkd, device, &commandPoolParams); +} + +vector allocateCommandBuffers (const DeviceInterface& vkd, + const VkDevice device, + const VkCommandPool commandPool, + const VkCommandBufferLevel level, + const size_t numCommandBuffers) +{ + const VkCommandBufferAllocateInfo allocInfo = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + DE_NULL, + commandPool, + level, + 1u, + }; + + vector buffers (numCommandBuffers); + + for (size_t ndx = 0; ndx < numCommandBuffers; ++ndx) + buffers[ndx] = CommandBufferSp(new Unique(allocateCommandBuffer(vkd, device, &allocInfo))); + + return buffers; +} + +tcu::TestStatus basicRenderTest (Context& context, Type wsiType) +{ + const tcu::UVec2 desiredSize (256, 256); + const InstanceHelper instHelper (context, wsiType); + const NativeObjects native (context, instHelper.supportedExtensions, wsiType, tcu::just(desiredSize)); + const Unique surface (createSurface(instHelper.vki, *instHelper.instance, wsiType, *native.display, *native.window)); + const DeviceHelper devHelper (context, instHelper.vki, *instHelper.instance, *surface); + const DeviceInterface& vkd = devHelper.vkd; + const VkDevice device = *devHelper.device; + const VkSwapchainCreateInfoKHR swapchainInfo = getBasicSwapchainParameters(wsiType, instHelper.vki, devHelper.physicalDevice, *surface, desiredSize, 2); + const Unique swapchain (createSwapchainKHR(vkd, device, &swapchainInfo)); + const vector swapchainImages = getSwapchainImages(vkd, device, *swapchain); + + const TriangleRenderer renderer (vkd, + device, + context.getDefaultAllocator(), + context.getBinaryCollection(), + swapchainImages, + swapchainInfo.imageFormat, + tcu::UVec2(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height)); + + const Unique commandPool (createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, devHelper.queueFamilyIndex)); + + const size_t maxQueuedFrames = swapchainImages.size()*2; + + // We need to keep hold of fences from vkAcquireNextImageKHR to actually + // limit number of frames we allow to be queued. + const vector imageReadyFences (createFences(vkd, device, maxQueuedFrames)); + + // We need maxQueuedFrames+1 for imageReadySemaphores pool as we need to pass + // the semaphore in same time as the fence we use to meter rendering. + const vector imageReadySemaphores (createSemaphores(vkd, device, maxQueuedFrames+1)); + + // For rest we simply need maxQueuedFrames as we will wait for image + // from frameNdx-maxQueuedFrames to become available to us, guaranteeing that + // previous uses must have completed. + const vector renderingCompleteSemaphores (createSemaphores(vkd, device, maxQueuedFrames)); + const vector commandBuffers (allocateCommandBuffers(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, maxQueuedFrames)); + + try + { + const deUint32 numFramesToRender = 60*10; + + for (deUint32 frameNdx = 0; frameNdx < numFramesToRender; ++frameNdx) + { + const VkFence imageReadyFence = **imageReadyFences[frameNdx%imageReadyFences.size()]; + const VkSemaphore imageReadySemaphore = **imageReadySemaphores[frameNdx%imageReadySemaphores.size()]; + deUint32 imageNdx = ~0u; + + if (frameNdx >= maxQueuedFrames) + VK_CHECK(vkd.waitForFences(device, 1u, &imageReadyFence, VK_TRUE, std::numeric_limits::max())); + + VK_CHECK(vkd.resetFences(device, 1, &imageReadyFence)); + + { + const VkResult acquireResult = vkd.acquireNextImageKHR(device, + *swapchain, + std::numeric_limits::max(), + imageReadySemaphore, + imageReadyFence, + &imageNdx); + + if (acquireResult == VK_SUBOPTIMAL_KHR) + context.getTestContext().getLog() << TestLog::Message << "Got " << acquireResult << " at frame " << frameNdx << TestLog::EndMessage; + else + VK_CHECK(acquireResult); + } + + TCU_CHECK((size_t)imageNdx < swapchainImages.size()); + + { + const VkSemaphore renderingCompleteSemaphore = **renderingCompleteSemaphores[frameNdx%renderingCompleteSemaphores.size()]; + const VkCommandBuffer commandBuffer = **commandBuffers[frameNdx%commandBuffers.size()]; + const VkPipelineStageFlags waitDstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + const VkSubmitInfo submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, + DE_NULL, + 1u, + &imageReadySemaphore, + &waitDstStage, + 1u, + &commandBuffer, + 1u, + &renderingCompleteSemaphore + }; + const VkPresentInfoKHR presentInfo = + { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + DE_NULL, + 1u, + &renderingCompleteSemaphore, + 1u, + &*swapchain, + &imageNdx, + (VkResult*)DE_NULL + }; + + renderer.recordFrame(commandBuffer, imageNdx, frameNdx); + VK_CHECK(vkd.queueSubmit(devHelper.queue, 1u, &submitInfo, (VkFence)0)); + VK_CHECK(vkd.queuePresentKHR(devHelper.queue, &presentInfo)); + } + } + + VK_CHECK(vkd.deviceWaitIdle(device)); + } + catch (...) + { + // Make sure device is idle before destroying resources + vkd.deviceWaitIdle(device); + throw; + } + + return tcu::TestStatus::pass("Rendering tests suceeded"); +} + +void getBasicRenderPrograms (SourceCollections& dst, Type) +{ + TriangleRenderer::getPrograms(dst); +} + +void populateRenderGroup (tcu::TestCaseGroup* testGroup, Type wsiType) +{ + addFunctionCaseWithPrograms(testGroup, "basic", "Basic Rendering Test", getBasicRenderPrograms, basicRenderTest, wsiType); +} + } // anonymous void createSwapchainTests (tcu::TestCaseGroup* testGroup, vk::wsi::Type wsiType) { addTestGroup(testGroup, "create", "Create VkSwapchain with various parameters", populateSwapchainGroup, GroupParameters(wsiType, createSwapchainTest)); addTestGroup(testGroup, "simulate_oom", "Simulate OOM using callbacks during swapchain construction", populateSwapchainGroup, GroupParameters(wsiType, createSwapchainSimulateOOMTest)); + addTestGroup(testGroup, "render", "Rendering Tests", populateRenderGroup, wsiType); } } // wsi -- 2.7.4