From cf06b4a9471beeca6bfbb9ca7ae6574b94bb3a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Aug 2019 23:07:42 +0200 Subject: [PATCH 1/5] Vulkan: Image views: The driver is probably smart enough to recognize a no-swizzle, but let's use the proper method. --- Common/Vulkan/VulkanImage.cpp | 5 +---- GPU/Vulkan/DepalettizeShaderVulkan.cpp | 4 ++-- ext/native/thin3d/VulkanRenderManager.cpp | 20 ++++++++++---------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 5c5e513948..8ad99b774d 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -142,10 +142,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, VulkanDeviceAllocator *all if (mapping) { view_info.components = *mapping; } else { - view_info.components.r = VK_COMPONENT_SWIZZLE_R; - view_info.components.g = VK_COMPONENT_SWIZZLE_G; - view_info.components.b = VK_COMPONENT_SWIZZLE_B; - view_info.components.a = VK_COMPONENT_SWIZZLE_A; + view_info.components = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; } view_info.subresourceRange.aspectMask = aspect; view_info.subresourceRange.baseMipLevel = 0; diff --git a/GPU/Vulkan/DepalettizeShaderVulkan.cpp b/GPU/Vulkan/DepalettizeShaderVulkan.cpp index b759882ad7..a55352b31c 100644 --- a/GPU/Vulkan/DepalettizeShaderVulkan.cpp +++ b/GPU/Vulkan/DepalettizeShaderVulkan.cpp @@ -37,8 +37,8 @@ void main() { static const VkComponentMapping VULKAN_4444_SWIZZLE = { VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B }; static const VkComponentMapping VULKAN_1555_SWIZZLE = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A }; -static const VkComponentMapping VULKAN_565_SWIZZLE = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; -static const VkComponentMapping VULKAN_8888_SWIZZLE = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; +static const VkComponentMapping VULKAN_565_SWIZZLE = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; +static const VkComponentMapping VULKAN_8888_SWIZZLE = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; static VkFormat GetClutDestFormat(GEPaletteFormat format, VkComponentMapping *componentMapping) { switch (format) { diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 1f8795a34e..81093108ad 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -64,7 +64,7 @@ void CreateImage(VulkanContext *vulkan, VkCommandBuffer cmd, VKRImage &img, int VkImageAspectFlags aspects = color ? VK_IMAGE_ASPECT_COLOR_BIT : (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); VkImageViewCreateInfo ivci{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - ivci.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; + ivci.components = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; ivci.format = ici.format; ivci.image = img.image; ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; @@ -161,10 +161,10 @@ void VulkanRenderManager::CreateBackbuffers() { VkImageViewCreateInfo color_image_view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; color_image_view.format = vulkan_->GetSwapchainFormat(); - color_image_view.components.r = VK_COMPONENT_SWIZZLE_R; - color_image_view.components.g = VK_COMPONENT_SWIZZLE_G; - color_image_view.components.b = VK_COMPONENT_SWIZZLE_B; - color_image_view.components.a = VK_COMPONENT_SWIZZLE_A; + color_image_view.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + color_image_view.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + color_image_view.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + color_image_view.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; color_image_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; color_image_view.subresourceRange.baseMipLevel = 0; color_image_view.subresourceRange.levelCount = 1; @@ -394,6 +394,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR if (steps_.size() && steps_.back()->render.framebuffer == fb && steps_.back()->stepType == VKRStepType::RENDER) { if (color != VKRRenderPassAction::CLEAR && depth != VKRRenderPassAction::CLEAR && stencil != VKRRenderPassAction::CLEAR) { // We don't move to a new step, this bind was unnecessary and we can safely skip it. + // Not sure how much this is still happening but probably worth checking for nevertheless. return; } } @@ -558,7 +559,6 @@ bool VulkanRenderManager::InitDepthStencilBuffer(VkCommandBuffer cmd) { image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; image_info.flags = 0; - depth_.format = depth_format; VkDevice device = vulkan_->GetDevice(); @@ -608,10 +608,10 @@ bool VulkanRenderManager::InitDepthStencilBuffer(VkCommandBuffer cmd) { VkImageViewCreateInfo depth_view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; depth_view_info.image = depth_.image; depth_view_info.format = depth_format; - depth_view_info.components.r = VK_COMPONENT_SWIZZLE_R; - depth_view_info.components.g = VK_COMPONENT_SWIZZLE_G; - depth_view_info.components.b = VK_COMPONENT_SWIZZLE_B; - depth_view_info.components.a = VK_COMPONENT_SWIZZLE_A; + depth_view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + depth_view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + depth_view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + depth_view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; depth_view_info.subresourceRange.aspectMask = aspectMask; depth_view_info.subresourceRange.baseMipLevel = 0; depth_view_info.subresourceRange.levelCount = 1; From ddb5208130921c83b53552b7c3cd09ab8d61aec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Aug 2019 23:19:07 +0200 Subject: [PATCH 2/5] Vulkan: Reduce the amount of redundant stencil parameter sets --- ext/native/thin3d/VulkanQueueRunner.cpp | 28 +++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index fdbdf3ebe9..be7b62cf67 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -869,9 +869,11 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c auto &commands = step.commands; - // TODO: Dynamic state commands (SetViewport, SetScissor, SetBlendConstants, SetStencil*) are only - // valid when a pipeline is bound with those as dynamic state. So we need to add some state tracking here - // for this to be correct. This is a bit of a pain but also will let us eliminate redundant calls. + // We can do a little bit of state tracking here to eliminate some calls into the driver. + // The stencil ones are very commonly mostly redundant so let's eliminate them where possible. + int lastStencilWriteMask = -1; + int lastStencilCompareMask = -1; + int lastStencilReference = -1; for (const auto &c : commands) { switch (c.cmd) { @@ -882,6 +884,10 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c if (c.pipeline.pipeline != lastPipeline) { vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, c.pipeline.pipeline); lastPipeline = c.pipeline.pipeline; + // Reset dynamic state so it gets refreshed with the new pipeline. + lastStencilWriteMask = -1; + lastStencilCompareMask = -1; + lastStencilReference = -1; } break; @@ -902,9 +908,18 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c break; case VKRRenderCommand::STENCIL: - vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilWriteMask); - vkCmdSetStencilCompareMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilCompareMask); - vkCmdSetStencilReference(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilRef); + if (lastStencilReference != c.stencil.stencilWriteMask) { + lastStencilReference = (int)c.stencil.stencilWriteMask; + vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilWriteMask); + } + if (lastStencilCompareMask != c.stencil.stencilCompareMask) { + lastStencilCompareMask = c.stencil.stencilCompareMask; + vkCmdSetStencilCompareMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilCompareMask); + } + if (lastStencilReference != c.stencil.stencilRef) { + lastStencilReference = c.stencil.stencilRef; + vkCmdSetStencilReference(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilRef); + } break; case VKRRenderCommand::DRAW_INDEXED: @@ -924,6 +939,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c case VKRRenderCommand::CLEAR: { + // If we get here, we failed to merge a clear into a render pass load op. This is bad for perf. int numAttachments = 0; VkClearRect rc{}; rc.baseArrayLayer = 0; From f4d348ca0c5e1388aa5ec0702a81c6f888edbb8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Aug 2019 23:24:40 +0200 Subject: [PATCH 3/5] Micro-optimize the Vulkan loader: Load more device-specific function pointers to avoid a bounce in the device loader, reorder things a little. --- Common/Vulkan/VulkanLoader.cpp | 255 ++++++++++++++++----------------- 1 file changed, 126 insertions(+), 129 deletions(-) diff --git a/Common/Vulkan/VulkanLoader.cpp b/Common/Vulkan/VulkanLoader.cpp index aedcfd639b..0a3dc04f57 100644 --- a/Common/Vulkan/VulkanLoader.cpp +++ b/Common/Vulkan/VulkanLoader.cpp @@ -61,9 +61,7 @@ PFN_vkGetPhysicalDeviceSparseImageFormatProperties vkGetPhysicalDeviceSparseImag PFN_vkQueueBindSparse vkQueueBindSparse; PFN_vkCreateFence vkCreateFence; PFN_vkDestroyFence vkDestroyFence; -PFN_vkResetFences vkResetFences; PFN_vkGetFenceStatus vkGetFenceStatus; -PFN_vkWaitForFences vkWaitForFences; PFN_vkCreateSemaphore vkCreateSemaphore; PFN_vkDestroySemaphore vkDestroySemaphore; PFN_vkCreateEvent vkCreateEvent; @@ -115,7 +113,7 @@ PFN_vkResetCommandPool vkResetCommandPool; PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers; PFN_vkFreeCommandBuffers vkFreeCommandBuffers; -// Used frequently +// Used frequently together PFN_vkCmdBindPipeline vkCmdBindPipeline; PFN_vkCmdSetViewport vkCmdSetViewport; PFN_vkCmdSetScissor vkCmdSetScissor; @@ -128,14 +126,16 @@ PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer; PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers; PFN_vkCmdDraw vkCmdDraw; PFN_vkCmdDrawIndexed vkCmdDrawIndexed; -PFN_vkCmdClearAttachments vkCmdClearAttachments; PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier; PFN_vkCmdPushConstants vkCmdPushConstants; // Every frame to a few times per frame +PFN_vkWaitForFences vkWaitForFences; +PFN_vkResetFences vkResetFences; PFN_vkBeginCommandBuffer vkBeginCommandBuffer; PFN_vkEndCommandBuffer vkEndCommandBuffer; PFN_vkResetCommandBuffer vkResetCommandBuffer; +PFN_vkCmdClearAttachments vkCmdClearAttachments; PFN_vkCmdSetEvent vkCmdSetEvent; PFN_vkCmdResetEvent vkCmdResetEvent; PFN_vkCmdWaitEvents vkCmdWaitEvents; @@ -147,6 +147,7 @@ PFN_vkCmdBlitImage vkCmdBlitImage; PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage; PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer; +// Rare or not used PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds; PFN_vkCmdSetLineWidth vkCmdSetLineWidth; PFN_vkCmdSetDepthBias vkCmdSetDepthBias; @@ -439,125 +440,7 @@ void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanDeviceExtensio LOAD_INSTANCE_FUNC(instance, vkEnumerateDeviceExtensionProperties); LOAD_INSTANCE_FUNC(instance, vkEnumerateDeviceLayerProperties); LOAD_INSTANCE_FUNC(instance, vkGetDeviceQueue); - LOAD_INSTANCE_FUNC(instance, vkQueueSubmit); - LOAD_INSTANCE_FUNC(instance, vkQueueWaitIdle); LOAD_INSTANCE_FUNC(instance, vkDeviceWaitIdle); - LOAD_INSTANCE_FUNC(instance, vkAllocateMemory); - LOAD_INSTANCE_FUNC(instance, vkFreeMemory); - LOAD_INSTANCE_FUNC(instance, vkMapMemory); - LOAD_INSTANCE_FUNC(instance, vkUnmapMemory); - LOAD_INSTANCE_FUNC(instance, vkFlushMappedMemoryRanges); - LOAD_INSTANCE_FUNC(instance, vkInvalidateMappedMemoryRanges); - LOAD_INSTANCE_FUNC(instance, vkGetDeviceMemoryCommitment); - LOAD_INSTANCE_FUNC(instance, vkBindBufferMemory); - LOAD_INSTANCE_FUNC(instance, vkBindImageMemory); - LOAD_INSTANCE_FUNC(instance, vkGetBufferMemoryRequirements); - LOAD_INSTANCE_FUNC(instance, vkGetImageMemoryRequirements); - LOAD_INSTANCE_FUNC(instance, vkGetImageSparseMemoryRequirements); - LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSparseImageFormatProperties); - LOAD_INSTANCE_FUNC(instance, vkQueueBindSparse); - LOAD_INSTANCE_FUNC(instance, vkCreateFence); - LOAD_INSTANCE_FUNC(instance, vkDestroyFence); - LOAD_INSTANCE_FUNC(instance, vkResetFences); - LOAD_INSTANCE_FUNC(instance, vkGetFenceStatus); - LOAD_INSTANCE_FUNC(instance, vkWaitForFences); - LOAD_INSTANCE_FUNC(instance, vkCreateSemaphore); - LOAD_INSTANCE_FUNC(instance, vkDestroySemaphore); - LOAD_INSTANCE_FUNC(instance, vkCreateEvent); - LOAD_INSTANCE_FUNC(instance, vkDestroyEvent); - LOAD_INSTANCE_FUNC(instance, vkGetEventStatus); - LOAD_INSTANCE_FUNC(instance, vkSetEvent); - LOAD_INSTANCE_FUNC(instance, vkResetEvent); - LOAD_INSTANCE_FUNC(instance, vkCreateQueryPool); - LOAD_INSTANCE_FUNC(instance, vkDestroyQueryPool); - LOAD_INSTANCE_FUNC(instance, vkGetQueryPoolResults); - LOAD_INSTANCE_FUNC(instance, vkCreateBuffer); - LOAD_INSTANCE_FUNC(instance, vkDestroyBuffer); - LOAD_INSTANCE_FUNC(instance, vkCreateBufferView); - LOAD_INSTANCE_FUNC(instance, vkDestroyBufferView); - LOAD_INSTANCE_FUNC(instance, vkCreateImage); - LOAD_INSTANCE_FUNC(instance, vkDestroyImage); - LOAD_INSTANCE_FUNC(instance, vkGetImageSubresourceLayout); - LOAD_INSTANCE_FUNC(instance, vkCreateImageView); - LOAD_INSTANCE_FUNC(instance, vkDestroyImageView); - LOAD_INSTANCE_FUNC(instance, vkCreateShaderModule); - LOAD_INSTANCE_FUNC(instance, vkDestroyShaderModule); - LOAD_INSTANCE_FUNC(instance, vkCreatePipelineCache); - LOAD_INSTANCE_FUNC(instance, vkDestroyPipelineCache); - LOAD_INSTANCE_FUNC(instance, vkGetPipelineCacheData); - LOAD_INSTANCE_FUNC(instance, vkMergePipelineCaches); - LOAD_INSTANCE_FUNC(instance, vkCreateGraphicsPipelines); - LOAD_INSTANCE_FUNC(instance, vkCreateComputePipelines); - LOAD_INSTANCE_FUNC(instance, vkDestroyPipeline); - LOAD_INSTANCE_FUNC(instance, vkCreatePipelineLayout); - LOAD_INSTANCE_FUNC(instance, vkDestroyPipelineLayout); - LOAD_INSTANCE_FUNC(instance, vkCreateSampler); - LOAD_INSTANCE_FUNC(instance, vkDestroySampler); - LOAD_INSTANCE_FUNC(instance, vkCreateDescriptorSetLayout); - LOAD_INSTANCE_FUNC(instance, vkDestroyDescriptorSetLayout); - LOAD_INSTANCE_FUNC(instance, vkCreateDescriptorPool); - LOAD_INSTANCE_FUNC(instance, vkDestroyDescriptorPool); - LOAD_INSTANCE_FUNC(instance, vkResetDescriptorPool); - LOAD_INSTANCE_FUNC(instance, vkAllocateDescriptorSets); - LOAD_INSTANCE_FUNC(instance, vkFreeDescriptorSets); - LOAD_INSTANCE_FUNC(instance, vkUpdateDescriptorSets); - LOAD_INSTANCE_FUNC(instance, vkCreateFramebuffer); - LOAD_INSTANCE_FUNC(instance, vkDestroyFramebuffer); - LOAD_INSTANCE_FUNC(instance, vkCreateRenderPass); - LOAD_INSTANCE_FUNC(instance, vkDestroyRenderPass); - LOAD_INSTANCE_FUNC(instance, vkGetRenderAreaGranularity); - LOAD_INSTANCE_FUNC(instance, vkCreateCommandPool); - LOAD_INSTANCE_FUNC(instance, vkDestroyCommandPool); - LOAD_INSTANCE_FUNC(instance, vkResetCommandPool); - LOAD_INSTANCE_FUNC(instance, vkAllocateCommandBuffers); - LOAD_INSTANCE_FUNC(instance, vkFreeCommandBuffers); - LOAD_INSTANCE_FUNC(instance, vkBeginCommandBuffer); - LOAD_INSTANCE_FUNC(instance, vkEndCommandBuffer); - LOAD_INSTANCE_FUNC(instance, vkResetCommandBuffer); - LOAD_INSTANCE_FUNC(instance, vkCmdBindPipeline); - LOAD_INSTANCE_FUNC(instance, vkCmdSetViewport); - LOAD_INSTANCE_FUNC(instance, vkCmdSetScissor); - LOAD_INSTANCE_FUNC(instance, vkCmdSetLineWidth); - LOAD_INSTANCE_FUNC(instance, vkCmdSetDepthBias); - LOAD_INSTANCE_FUNC(instance, vkCmdSetBlendConstants); - LOAD_INSTANCE_FUNC(instance, vkCmdSetDepthBounds); - LOAD_INSTANCE_FUNC(instance, vkCmdSetStencilCompareMask); - LOAD_INSTANCE_FUNC(instance, vkCmdSetStencilWriteMask); - LOAD_INSTANCE_FUNC(instance, vkCmdSetStencilReference); - LOAD_INSTANCE_FUNC(instance, vkCmdBindDescriptorSets); - LOAD_INSTANCE_FUNC(instance, vkCmdBindIndexBuffer); - LOAD_INSTANCE_FUNC(instance, vkCmdBindVertexBuffers); - LOAD_INSTANCE_FUNC(instance, vkCmdDraw); - LOAD_INSTANCE_FUNC(instance, vkCmdDrawIndexed); - LOAD_INSTANCE_FUNC(instance, vkCmdDrawIndirect); - LOAD_INSTANCE_FUNC(instance, vkCmdDrawIndexedIndirect); - LOAD_INSTANCE_FUNC(instance, vkCmdDispatch); - LOAD_INSTANCE_FUNC(instance, vkCmdDispatchIndirect); - LOAD_INSTANCE_FUNC(instance, vkCmdCopyBuffer); - LOAD_INSTANCE_FUNC(instance, vkCmdCopyImage); - LOAD_INSTANCE_FUNC(instance, vkCmdBlitImage); - LOAD_INSTANCE_FUNC(instance, vkCmdCopyBufferToImage); - LOAD_INSTANCE_FUNC(instance, vkCmdCopyImageToBuffer); - LOAD_INSTANCE_FUNC(instance, vkCmdUpdateBuffer); - LOAD_INSTANCE_FUNC(instance, vkCmdFillBuffer); - LOAD_INSTANCE_FUNC(instance, vkCmdClearColorImage); - LOAD_INSTANCE_FUNC(instance, vkCmdClearDepthStencilImage); - LOAD_INSTANCE_FUNC(instance, vkCmdClearAttachments); - LOAD_INSTANCE_FUNC(instance, vkCmdResolveImage); - LOAD_INSTANCE_FUNC(instance, vkCmdSetEvent); - LOAD_INSTANCE_FUNC(instance, vkCmdResetEvent); - LOAD_INSTANCE_FUNC(instance, vkCmdWaitEvents); - LOAD_INSTANCE_FUNC(instance, vkCmdPipelineBarrier); - LOAD_INSTANCE_FUNC(instance, vkCmdBeginQuery); - LOAD_INSTANCE_FUNC(instance, vkCmdEndQuery); - LOAD_INSTANCE_FUNC(instance, vkCmdResetQueryPool); - LOAD_INSTANCE_FUNC(instance, vkCmdWriteTimestamp); - LOAD_INSTANCE_FUNC(instance, vkCmdCopyQueryPoolResults); - LOAD_INSTANCE_FUNC(instance, vkCmdPushConstants); - LOAD_INSTANCE_FUNC(instance, vkCmdBeginRenderPass); - LOAD_INSTANCE_FUNC(instance, vkCmdNextSubpass); - LOAD_INSTANCE_FUNC(instance, vkCmdEndRenderPass); - LOAD_INSTANCE_FUNC(instance, vkCmdExecuteCommands); LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceSupportKHR); LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceSurfaceCapabilitiesKHR); @@ -609,15 +492,129 @@ void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanDeviceExtensio // On some implementations, loading functions (that have Device as their first parameter) via vkGetDeviceProcAddr may // increase performance - but then these function pointers will only work on that specific device. Thus, this loader is not very -// good for multi-device. +// good for multi-device - not likely we'll ever try that anyway though. void VulkanLoadDeviceFunctions(VkDevice device, const VulkanDeviceExtensions &enabledExtensions) { WLOG("Vulkan device functions loaded."); - // TODO: Move more functions VulkanLoadInstanceFunctions to here. - LOAD_DEVICE_FUNC(device, vkCreateSwapchainKHR); - LOAD_DEVICE_FUNC(device, vkDestroySwapchainKHR); - LOAD_DEVICE_FUNC(device, vkGetSwapchainImagesKHR); - LOAD_DEVICE_FUNC(device, vkAcquireNextImageKHR); - LOAD_DEVICE_FUNC(device, vkQueuePresentKHR); + + LOAD_DEVICE_FUNC(device, vkQueueSubmit); + LOAD_DEVICE_FUNC(device, vkQueueWaitIdle); + LOAD_DEVICE_FUNC(device, vkAllocateMemory); + LOAD_DEVICE_FUNC(device, vkFreeMemory); + LOAD_DEVICE_FUNC(device, vkMapMemory); + LOAD_DEVICE_FUNC(device, vkUnmapMemory); + LOAD_DEVICE_FUNC(device, vkFlushMappedMemoryRanges); + LOAD_DEVICE_FUNC(device, vkInvalidateMappedMemoryRanges); + LOAD_DEVICE_FUNC(device, vkGetDeviceMemoryCommitment); + LOAD_DEVICE_FUNC(device, vkBindBufferMemory); + LOAD_DEVICE_FUNC(device, vkBindImageMemory); + LOAD_DEVICE_FUNC(device, vkGetBufferMemoryRequirements); + LOAD_DEVICE_FUNC(device, vkGetImageMemoryRequirements); + LOAD_DEVICE_FUNC(device, vkGetImageSparseMemoryRequirements); + LOAD_DEVICE_FUNC(device, vkGetPhysicalDeviceSparseImageFormatProperties); + LOAD_DEVICE_FUNC(device, vkQueueBindSparse); + LOAD_DEVICE_FUNC(device, vkCreateFence); + LOAD_DEVICE_FUNC(device, vkDestroyFence); + LOAD_DEVICE_FUNC(device, vkResetFences); + LOAD_DEVICE_FUNC(device, vkGetFenceStatus); + LOAD_DEVICE_FUNC(device, vkWaitForFences); + LOAD_DEVICE_FUNC(device, vkCreateSemaphore); + LOAD_DEVICE_FUNC(device, vkDestroySemaphore); + LOAD_DEVICE_FUNC(device, vkCreateEvent); + LOAD_DEVICE_FUNC(device, vkDestroyEvent); + LOAD_DEVICE_FUNC(device, vkGetEventStatus); + LOAD_DEVICE_FUNC(device, vkSetEvent); + LOAD_DEVICE_FUNC(device, vkResetEvent); + LOAD_DEVICE_FUNC(device, vkCreateQueryPool); + LOAD_DEVICE_FUNC(device, vkDestroyQueryPool); + LOAD_DEVICE_FUNC(device, vkGetQueryPoolResults); + LOAD_DEVICE_FUNC(device, vkCreateBuffer); + LOAD_DEVICE_FUNC(device, vkDestroyBuffer); + LOAD_DEVICE_FUNC(device, vkCreateBufferView); + LOAD_DEVICE_FUNC(device, vkDestroyBufferView); + LOAD_DEVICE_FUNC(device, vkCreateImage); + LOAD_DEVICE_FUNC(device, vkDestroyImage); + LOAD_DEVICE_FUNC(device, vkGetImageSubresourceLayout); + LOAD_DEVICE_FUNC(device, vkCreateImageView); + LOAD_DEVICE_FUNC(device, vkDestroyImageView); + LOAD_DEVICE_FUNC(device, vkCreateShaderModule); + LOAD_DEVICE_FUNC(device, vkDestroyShaderModule); + LOAD_DEVICE_FUNC(device, vkCreatePipelineCache); + LOAD_DEVICE_FUNC(device, vkDestroyPipelineCache); + LOAD_DEVICE_FUNC(device, vkGetPipelineCacheData); + LOAD_DEVICE_FUNC(device, vkMergePipelineCaches); + LOAD_DEVICE_FUNC(device, vkCreateGraphicsPipelines); + LOAD_DEVICE_FUNC(device, vkCreateComputePipelines); + LOAD_DEVICE_FUNC(device, vkDestroyPipeline); + LOAD_DEVICE_FUNC(device, vkCreatePipelineLayout); + LOAD_DEVICE_FUNC(device, vkDestroyPipelineLayout); + LOAD_DEVICE_FUNC(device, vkCreateSampler); + LOAD_DEVICE_FUNC(device, vkDestroySampler); + LOAD_DEVICE_FUNC(device, vkCreateDescriptorSetLayout); + LOAD_DEVICE_FUNC(device, vkDestroyDescriptorSetLayout); + LOAD_DEVICE_FUNC(device, vkCreateDescriptorPool); + LOAD_DEVICE_FUNC(device, vkDestroyDescriptorPool); + LOAD_DEVICE_FUNC(device, vkResetDescriptorPool); + LOAD_DEVICE_FUNC(device, vkAllocateDescriptorSets); + LOAD_DEVICE_FUNC(device, vkFreeDescriptorSets); + LOAD_DEVICE_FUNC(device, vkUpdateDescriptorSets); + LOAD_DEVICE_FUNC(device, vkCreateFramebuffer); + LOAD_DEVICE_FUNC(device, vkDestroyFramebuffer); + LOAD_DEVICE_FUNC(device, vkCreateRenderPass); + LOAD_DEVICE_FUNC(device, vkDestroyRenderPass); + LOAD_DEVICE_FUNC(device, vkGetRenderAreaGranularity); + LOAD_DEVICE_FUNC(device, vkCreateCommandPool); + LOAD_DEVICE_FUNC(device, vkDestroyCommandPool); + LOAD_DEVICE_FUNC(device, vkResetCommandPool); + LOAD_DEVICE_FUNC(device, vkAllocateCommandBuffers); + LOAD_DEVICE_FUNC(device, vkFreeCommandBuffers); + LOAD_DEVICE_FUNC(device, vkBeginCommandBuffer); + LOAD_DEVICE_FUNC(device, vkEndCommandBuffer); + LOAD_DEVICE_FUNC(device, vkResetCommandBuffer); + LOAD_DEVICE_FUNC(device, vkCmdBindPipeline); + LOAD_DEVICE_FUNC(device, vkCmdSetViewport); + LOAD_DEVICE_FUNC(device, vkCmdSetScissor); + LOAD_DEVICE_FUNC(device, vkCmdSetLineWidth); + LOAD_DEVICE_FUNC(device, vkCmdSetDepthBias); + LOAD_DEVICE_FUNC(device, vkCmdSetBlendConstants); + LOAD_DEVICE_FUNC(device, vkCmdSetDepthBounds); + LOAD_DEVICE_FUNC(device, vkCmdSetStencilCompareMask); + LOAD_DEVICE_FUNC(device, vkCmdSetStencilWriteMask); + LOAD_DEVICE_FUNC(device, vkCmdSetStencilReference); + LOAD_DEVICE_FUNC(device, vkCmdBindDescriptorSets); + LOAD_DEVICE_FUNC(device, vkCmdBindIndexBuffer); + LOAD_DEVICE_FUNC(device, vkCmdBindVertexBuffers); + LOAD_DEVICE_FUNC(device, vkCmdDraw); + LOAD_DEVICE_FUNC(device, vkCmdDrawIndexed); + LOAD_DEVICE_FUNC(device, vkCmdDrawIndirect); + LOAD_DEVICE_FUNC(device, vkCmdDrawIndexedIndirect); + LOAD_DEVICE_FUNC(device, vkCmdDispatch); + LOAD_DEVICE_FUNC(device, vkCmdDispatchIndirect); + LOAD_DEVICE_FUNC(device, vkCmdCopyBuffer); + LOAD_DEVICE_FUNC(device, vkCmdCopyImage); + LOAD_DEVICE_FUNC(device, vkCmdBlitImage); + LOAD_DEVICE_FUNC(device, vkCmdCopyBufferToImage); + LOAD_DEVICE_FUNC(device, vkCmdCopyImageToBuffer); + LOAD_DEVICE_FUNC(device, vkCmdUpdateBuffer); + LOAD_DEVICE_FUNC(device, vkCmdFillBuffer); + LOAD_DEVICE_FUNC(device, vkCmdClearColorImage); + LOAD_DEVICE_FUNC(device, vkCmdClearDepthStencilImage); + LOAD_DEVICE_FUNC(device, vkCmdClearAttachments); + LOAD_DEVICE_FUNC(device, vkCmdResolveImage); + LOAD_DEVICE_FUNC(device, vkCmdSetEvent); + LOAD_DEVICE_FUNC(device, vkCmdResetEvent); + LOAD_DEVICE_FUNC(device, vkCmdWaitEvents); + LOAD_DEVICE_FUNC(device, vkCmdPipelineBarrier); + LOAD_DEVICE_FUNC(device, vkCmdBeginQuery); + LOAD_DEVICE_FUNC(device, vkCmdEndQuery); + LOAD_DEVICE_FUNC(device, vkCmdResetQueryPool); + LOAD_DEVICE_FUNC(device, vkCmdWriteTimestamp); + LOAD_DEVICE_FUNC(device, vkCmdCopyQueryPoolResults); + LOAD_DEVICE_FUNC(device, vkCmdPushConstants); + LOAD_DEVICE_FUNC(device, vkCmdBeginRenderPass); + LOAD_DEVICE_FUNC(device, vkCmdNextSubpass); + LOAD_DEVICE_FUNC(device, vkCmdEndRenderPass); + LOAD_DEVICE_FUNC(device, vkCmdExecuteCommands); + if (enabledExtensions.EXT_external_memory_host) { LOAD_DEVICE_FUNC(device, vkGetMemoryHostPointerPropertiesEXT); } From 49e64f10d47272ebabbf577c6def844dcb07c3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Aug 2019 23:36:35 +0200 Subject: [PATCH 4/5] Minor code cleanup --- ext/native/thin3d/VulkanRenderManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 81093108ad..84bfcd3266 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -800,7 +800,8 @@ void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, } VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, int aspectBit, int attachment) { - // Should just mark the dependency and return the image. + // Mark the dependency and return the image. + for (int i = (int)steps_.size() - 1; i >= 0; i--) { if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == fb) { // If this framebuffer was rendered to earlier in this frame, make sure to pre-transition it to the correct layout. @@ -817,9 +818,10 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in curRenderStep_->preTransitions.back().targetLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { // We're done. return fb->color.imageView; + } else { + curRenderStep_->preTransitions.push_back({ fb, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }); + return fb->color.imageView; } - curRenderStep_->preTransitions.push_back({ fb, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }); - return fb->color.imageView; } void VulkanRenderManager::Finish() { From d0a341087511e314672fbeab7885f501615ea890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 13 Aug 2019 00:22:47 +0200 Subject: [PATCH 5/5] Typo fix --- ext/native/thin3d/VulkanQueueRunner.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index be7b62cf67..d9ed03a426 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -392,7 +392,6 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector &st for (int j = 0; j < (int)steps.size() - 1; j++) { // Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer. - // Actually let's just bother with the first one for now. This affects Wipeout Pure. if (steps.size() > 1 && steps[j]->stepType == VKRStepType::RENDER && steps[j]->render.numDraws == 0 && steps[j]->render.numReads == 0 && @@ -400,8 +399,8 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector &st steps[j]->render.stencil == VKRRenderPassAction::CLEAR && steps[j]->render.depth == VKRRenderPassAction::CLEAR) { - // Drop the first step, and merge it into the next step that touches the same framebuffer. - for (size_t i = j + 1; i < steps.size(); i++) { + // Drop the clear step, and merge it into the next step that touches the same framebuffer. + for (int i = j + 1; i < (int)steps.size(); i++) { if (steps[i]->stepType == VKRStepType::RENDER && steps[i]->render.framebuffer == steps[j]->render.framebuffer) { if (steps[i]->render.color != VKRRenderPassAction::CLEAR) { @@ -908,8 +907,8 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c break; case VKRRenderCommand::STENCIL: - if (lastStencilReference != c.stencil.stencilWriteMask) { - lastStencilReference = (int)c.stencil.stencilWriteMask; + if (lastStencilWriteMask != c.stencil.stencilWriteMask) { + lastStencilWriteMask = (int)c.stencil.stencilWriteMask; vkCmdSetStencilWriteMask(cmd, VK_STENCIL_FRONT_AND_BACK, c.stencil.stencilWriteMask); } if (lastStencilCompareMask != c.stencil.stencilCompareMask) {