diff --git a/Common/Vulkan/VulkanContext.cpp b/Common/Vulkan/VulkanContext.cpp index e41dde9a0d..daa21b05fc 100644 --- a/Common/Vulkan/VulkanContext.cpp +++ b/Common/Vulkan/VulkanContext.cpp @@ -1047,10 +1047,11 @@ bool VulkanContext::InitSwapchain(VkCommandBuffer cmd) { // TODO: Pre-set them to PRESENT_SRC_KHR, as the first thing we do after acquiring // in image to render to will be to transition them away from that. - TransitionImageLayout(cmd, sc_buffer.image, + TransitionImageLayout2(cmd, sc_buffer.image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); color_image_view.image = sc_buffer.image; @@ -1224,66 +1225,6 @@ bool VulkanContext::CreateShaderModule(const std::vector &spirv, VkSha } } -void TransitionImageLayout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkImageLayout new_image_layout) { - VkImageMemoryBarrier image_memory_barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = 0; - image_memory_barrier.oldLayout = old_image_layout; - image_memory_barrier.newLayout = new_image_layout; - image_memory_barrier.image = image; - image_memory_barrier.subresourceRange.aspectMask = aspectMask; - image_memory_barrier.subresourceRange.baseMipLevel = 0; - image_memory_barrier.subresourceRange.levelCount = 1; - image_memory_barrier.subresourceRange.layerCount = 1; - if (old_image_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { - image_memory_barrier.srcAccessMask |= VK_ACCESS_MEMORY_READ_BIT; - } - if (old_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - image_memory_barrier.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; - } - - if (old_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - image_memory_barrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { - if (old_image_layout == VK_IMAGE_LAYOUT_PREINITIALIZED) { - image_memory_barrier.srcAccessMask |= VK_ACCESS_HOST_WRITE_BIT; - } - image_memory_barrier.dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - /* Make sure anything that was copying from this image has completed */ - image_memory_barrier.dstAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - /* Make sure any Copy or CPU writes to image are flushed */ - if (old_image_layout != VK_IMAGE_LAYOUT_UNDEFINED) { - image_memory_barrier.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT; - } - image_memory_barrier.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - image_memory_barrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - image_memory_barrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { - image_memory_barrier.dstAccessMask |= VK_ACCESS_MEMORY_READ_BIT; - } - - VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - - vkCmdPipelineBarrier(cmd, src_stages, dest_stages, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); -} - void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, diff --git a/Common/Vulkan/VulkanContext.h b/Common/Vulkan/VulkanContext.h index 40391a254c..925240b5c7 100644 --- a/Common/Vulkan/VulkanContext.h +++ b/Common/Vulkan/VulkanContext.h @@ -440,12 +440,6 @@ private: // Stand-alone utility functions void VulkanBeginCommandBuffer(VkCommandBuffer cmd); -void TransitionImageLayout( - VkCommandBuffer cmd, - VkImage image, - VkImageAspectFlags aspectMask, - VkImageLayout old_image_layout, - VkImageLayout new_image_layout); // Detailed control. void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 54dc39bba3..19291746ae 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -8,13 +8,6 @@ VkResult VulkanTexture::Create(int w, int h, VkFormat format) { VkFormatProperties formatProps; vkGetPhysicalDeviceFormatProperties(vulkan_->GetPhysicalDevice(), format, &formatProps); - - // See if we can use a linear tiled image for a texture, if not, we will need a staging image for the texture data. - // Linear tiling is usually only supported for 2D non-array textures. - // needStaging = (!(formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) ? true : false; - // Always stage. - needStaging = true; - return VK_SUCCESS; } @@ -39,7 +32,7 @@ void VulkanTexture::CreateMappableImage() { image_create_info.arrayLayers = 1; image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; image_create_info.tiling = VK_IMAGE_TILING_LINEAR; - image_create_info.usage = needStaging ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : VK_IMAGE_USAGE_SAMPLED_BIT; + image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; image_create_info.queueFamilyIndexCount = 0; image_create_info.pQueueFamilyIndices = NULL; image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -98,15 +91,8 @@ void VulkanTexture::Unlock() { // if we already have an image, queue it for destruction and forget it. Wipe(); - if (!needStaging) { - // If we can use the linear tiled image as a texture, just do it - image = mappableImage; - mem = mappableMemory; - TransitionImageLayout(cmd, image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - // Make sure we don't accidentally delete the main image. - mappableImage = VK_NULL_HANDLE; - mappableMemory = VK_NULL_HANDLE; - } else { + + { // Shrink the diff by not unindenting. If you make major changes, remove this. VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.format = format_; @@ -369,18 +355,20 @@ void VulkanTexture::UploadMip(int mip, int mipWidth, int mipHeight, VkBuffer buf void VulkanTexture::EndCreate() { VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer(); - TransitionImageLayout(cmd, image, + TransitionImageLayout2(cmd, image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); } void VulkanTexture::TransitionForUpload() { VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer(); - TransitionImageLayout(cmd, image, + TransitionImageLayout2(cmd, image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); } void VulkanTexture::Destroy() { diff --git a/Common/Vulkan/VulkanImage.h b/Common/Vulkan/VulkanImage.h index 3b67119946..50b9b0b651 100644 --- a/Common/Vulkan/VulkanImage.h +++ b/Common/Vulkan/VulkanImage.h @@ -11,7 +11,7 @@ public: VulkanTexture(VulkanContext *vulkan, VulkanDeviceAllocator *allocator = nullptr) : vulkan_(vulkan), image(VK_NULL_HANDLE), mem(VK_NULL_HANDLE), view(VK_NULL_HANDLE), tex_width(0), tex_height(0), numMips_(1), format_(VK_FORMAT_UNDEFINED), - mappableImage(VK_NULL_HANDLE), mappableMemory(VK_NULL_HANDLE), needStaging(false), + mappableImage(VK_NULL_HANDLE), mappableMemory(VK_NULL_HANDLE), allocator_(allocator), offset_(0) { memset(&mem_reqs, 0, sizeof(mem_reqs)); } @@ -64,5 +64,4 @@ private: VkMemoryRequirements mem_reqs; VulkanDeviceAllocator *allocator_; size_t offset_; - bool needStaging; }; diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 22e9e91f58..107d667337 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -369,7 +369,6 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag } } - void DrawEngineVulkan::ApplyDrawStateLate(VkCommandBuffer cmd, bool applyStencilRef, uint8_t stencilRef) { // At this point, we know if the vertices are full alpha or not. // TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)? diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 1ade5640a7..5c619407fb 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -1503,39 +1503,40 @@ void CreateImage(VulkanContext *vulkan, VKImage &img, int width, int height, VkF res = vkBindImageMemory(vulkan->GetDevice(), img.image, img.memory, 0); assert(res == VK_SUCCESS); + 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.format = ici.format; ivci.image = img.image; ivci.viewType = VK_IMAGE_VIEW_TYPE_2D; - ivci.subresourceRange.aspectMask = color ? VK_IMAGE_ASPECT_COLOR_BIT : (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + ivci.subresourceRange.aspectMask = aspects; ivci.subresourceRange.layerCount = 1; ivci.subresourceRange.levelCount = 1; res = vkCreateImageView(vulkan->GetDevice(), &ivci, nullptr, &img.view); assert(res == VK_SUCCESS); - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - barrier.subresourceRange.layerCount = 1; - barrier.subresourceRange.levelCount = 1; - barrier.image = img.image; - barrier.srcAccessMask = 0; + VkPipelineStageFlagBits dstStage; + VkAccessFlagBits dstAccessMask; switch (initialLayout) { case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; } - barrier.newLayout = initialLayout; - barrier.subresourceRange.aspectMask = ivci.subresourceRange.aspectMask; - vkCmdPipelineBarrier(vulkan->GetInitCommandBuffer(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); - img.layout = VK_IMAGE_LAYOUT_UNDEFINED; + + TransitionImageLayout2(vulkan->GetInitCommandBuffer(), img.image, aspects, + VK_IMAGE_LAYOUT_UNDEFINED, initialLayout, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, dstStage, + 0, dstAccessMask); } // A VKFramebuffer is a VkFramebuffer (note caps difference) plus all the textures it owns.