diff options
| author | Tilka <tilkax@gmail.com> | 2019-02-26 04:21:05 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-02-26 04:21:05 +0000 |
| commit | 6ce7f44b8a0bb3b95d3f12ebffbef7a71a443fdd (patch) | |
| tree | 98380ce3a3284c52597a6fba86589c847219ecd5 /Source/Core/VideoBackends/Vulkan/TextureCache.cpp | |
| parent | 19673ce79af814ca3b77d7f8ea60458e564bfa51 (diff) | |
| parent | f039149198657c1891e1c6462ed30c31ed4b8486 (diff) | |
Merge pull request #7753 from stenzek/videocommon-all-the-things
Move a significant amount of video backend logic to VideoCommon
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/TextureCache.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/TextureCache.cpp | 316 |
1 files changed, 0 insertions, 316 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp b/Source/Core/VideoBackends/Vulkan/TextureCache.cpp deleted file mode 100644 index 3f26b28a7c..0000000000 --- a/Source/Core/VideoBackends/Vulkan/TextureCache.cpp +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2016 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "VideoBackends/Vulkan/TextureCache.h" - -#include <algorithm> -#include <cstring> -#include <string> -#include <vector> - -#include "Common/Assert.h" -#include "Common/CommonFuncs.h" -#include "Common/Logging/Log.h" -#include "Common/MsgHandler.h" - -#include "VideoBackends/Vulkan/CommandBufferManager.h" -#include "VideoBackends/Vulkan/FramebufferManager.h" -#include "VideoBackends/Vulkan/ObjectCache.h" -#include "VideoBackends/Vulkan/Renderer.h" -#include "VideoBackends/Vulkan/StateTracker.h" -#include "VideoBackends/Vulkan/StreamBuffer.h" -#include "VideoBackends/Vulkan/Texture2D.h" -#include "VideoBackends/Vulkan/TextureConverter.h" -#include "VideoBackends/Vulkan/Util.h" -#include "VideoBackends/Vulkan/VKTexture.h" -#include "VideoBackends/Vulkan/VulkanContext.h" - -#include "VideoCommon/ImageWrite.h" -#include "VideoCommon/TextureConfig.h" - -namespace Vulkan -{ -TextureCache::TextureCache() -{ -} - -TextureCache::~TextureCache() -{ - TextureCache::DeleteShaders(); -} - -VkShaderModule TextureCache::GetCopyShader() const -{ - return m_copy_shader; -} - -TextureCache* TextureCache::GetInstance() -{ - return static_cast<TextureCache*>(g_texture_cache.get()); -} - -bool TextureCache::Initialize() -{ - m_texture_converter = std::make_unique<TextureConverter>(); - if (!m_texture_converter->Initialize()) - { - PanicAlert("Failed to initialize texture converter"); - return false; - } - - if (!CompileShaders()) - { - PanicAlert("Failed to compile one or more shaders"); - return false; - } - - return true; -} - -void TextureCache::ConvertTexture(TCacheEntry* destination, TCacheEntry* source, - const void* palette, TLUTFormat format) -{ - m_texture_converter->ConvertTexture(destination, source, palette, format); - - // Ensure both textures remain in the SHADER_READ_ONLY layout so they can be bound. - static_cast<VKTexture*>(source->texture.get()) - ->GetRawTexIdentifier() - ->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - static_cast<VKTexture*>(destination->texture.get()) - ->GetRawTexIdentifier() - ->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); -} - -void TextureCache::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, - u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, - const EFBRectangle& src_rect, bool scale_by_half, float y_scale, - float gamma, bool clamp_top, bool clamp_bottom, - const CopyFilterCoefficientArray& filter_coefficients) -{ - // Flush EFB pokes first, as they're expected to be included. - FramebufferManager::GetInstance()->FlushEFBPokes(); - - // MSAA case where we need to resolve first. - // An out-of-bounds source region is valid here, and fine for the draw (since it is converted - // to texture coordinates), but it's not valid to resolve an out-of-range rectangle. - TargetRectangle scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); - VkRect2D region = {{scaled_src_rect.left, scaled_src_rect.top}, - {static_cast<u32>(scaled_src_rect.GetWidth()), - static_cast<u32>(scaled_src_rect.GetHeight())}}; - region = Util::ClampRect2D(region, FramebufferManager::GetInstance()->GetEFBWidth(), - FramebufferManager::GetInstance()->GetEFBHeight()); - Texture2D* src_texture; - if (params.depth) - src_texture = FramebufferManager::GetInstance()->ResolveEFBDepthTexture(region); - else - src_texture = FramebufferManager::GetInstance()->ResolveEFBColorTexture(region); - - // End render pass before barrier (since we have no self-dependencies). - // The barrier has to happen after the render pass, not inside it, as we are going to be - // reading from the texture immediately afterwards. - StateTracker::GetInstance()->EndRenderPass(); - - // Transition to shader resource before reading. - VkImageLayout original_layout = src_texture->GetLayout(); - src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - m_texture_converter->EncodeTextureToMemory( - src_texture->GetView(), dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride, - src_rect, scale_by_half, y_scale, gamma, clamp_top, clamp_bottom, filter_coefficients); - - // Transition back to original state - src_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(), original_layout); - - StateTracker::GetInstance()->OnEFBCopyToRAM(); -} - -bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TLUTFormat palette_format) -{ - return m_texture_converter->SupportsTextureDecoding(format, palette_format); -} - -void TextureCache::DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data, - size_t data_size, TextureFormat format, u32 width, u32 height, - u32 aligned_width, u32 aligned_height, u32 row_stride, - const u8* palette, TLUTFormat palette_format) -{ - // Group compute shader dispatches together in the init command buffer. That way we don't have to - // pay a penalty for switching from graphics->compute, or end/restart our render pass. - VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentInitCommandBuffer(); - m_texture_converter->DecodeTexture(command_buffer, entry, dst_level, data, data_size, format, - width, height, aligned_width, aligned_height, row_stride, - palette, palette_format); - - // Last mip level? Ensure the texture is ready for use. - if (dst_level == (entry->GetNumLevels() - 1)) - { - static_cast<VKTexture*>(entry->texture.get()) - ->GetRawTexIdentifier() - ->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } -} - -bool TextureCache::CompileShaders() -{ - static const char COPY_SHADER_SOURCE[] = R"( - layout(set = 1, binding = 0) uniform sampler2DArray samp0; - - layout(location = 0) in float3 uv0; - layout(location = 1) in float4 col0; - layout(location = 0) out float4 ocol0; - - void main() - { - ocol0 = texture(samp0, uv0); - } - )"; - - std::string header = g_shader_cache->GetUtilityShaderHeader(); - std::string source = header + COPY_SHADER_SOURCE; - - m_copy_shader = Util::CompileAndCreateFragmentShader(source); - - return m_copy_shader != VK_NULL_HANDLE; -} - -void TextureCache::DeleteShaders() -{ - // It is safe to destroy shader modules after they are consumed by creating a pipeline. - // Therefore, no matter where this function is called from, it won't cause an issue due to - // pending commands, although at the time of writing should only be called at the end of - // a frame. See Vulkan spec, section 2.3.1. Object Lifetime. - if (m_copy_shader != VK_NULL_HANDLE) - { - vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_copy_shader, nullptr); - m_copy_shader = VK_NULL_HANDLE; - } - - for (auto& shader : m_efb_copy_to_tex_shaders) - { - vkDestroyShaderModule(g_vulkan_context->GetDevice(), shader.second, nullptr); - } - m_efb_copy_to_tex_shaders.clear(); -} - -void TextureCache::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, - const EFBRectangle& src_rect, bool scale_by_half, - EFBCopyFormat dst_format, bool is_intensity, float gamma, - bool clamp_top, bool clamp_bottom, - const CopyFilterCoefficientArray& filter_coefficients) -{ - VKTexture* texture = static_cast<VKTexture*>(entry->texture.get()); - - // A better way of doing this would be nice. - FramebufferManager* framebuffer_mgr = - static_cast<FramebufferManager*>(g_framebuffer_manager.get()); - TargetRectangle scaled_src_rect = g_renderer->ConvertEFBRectangle(src_rect); - - // Flush EFB pokes first, as they're expected to be included. - framebuffer_mgr->FlushEFBPokes(); - - // Has to be flagged as a render target. - ASSERT(texture->GetFramebuffer() != VK_NULL_HANDLE); - - // Can't be done in a render pass, since we're doing our own render pass! - VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer(); - StateTracker::GetInstance()->EndRenderPass(); - - // Fill uniform buffer. - struct PixelUniforms - { - float filter_coefficients[3]; - float gamma_rcp; - float clamp_top; - float clamp_bottom; - float pixel_height; - u32 padding; - }; - PixelUniforms uniforms; - for (size_t i = 0; i < filter_coefficients.size(); i++) - uniforms.filter_coefficients[i] = filter_coefficients[i]; - uniforms.gamma_rcp = 1.0f / gamma; - uniforms.clamp_top = clamp_top ? src_rect.top / float(EFB_HEIGHT) : 0.0f; - uniforms.clamp_bottom = clamp_bottom ? src_rect.bottom / float(EFB_HEIGHT) : 1.0f; - uniforms.pixel_height = - g_ActiveConfig.bCopyEFBScaled ? 1.0f / g_renderer->GetTargetHeight() : 1.0f / EFB_HEIGHT; - uniforms.padding = 0; - - // Transition EFB to shader resource before binding. - // An out-of-bounds source region is valid here, and fine for the draw (since it is converted - // to texture coordinates), but it's not valid to resolve an out-of-range rectangle. - VkRect2D region = {{scaled_src_rect.left, scaled_src_rect.top}, - {static_cast<u32>(scaled_src_rect.GetWidth()), - static_cast<u32>(scaled_src_rect.GetHeight())}}; - region = Util::ClampRect2D(region, FramebufferManager::GetInstance()->GetEFBWidth(), - FramebufferManager::GetInstance()->GetEFBHeight()); - Texture2D* src_texture; - if (is_depth_copy) - src_texture = FramebufferManager::GetInstance()->ResolveEFBDepthTexture(region); - else - src_texture = FramebufferManager::GetInstance()->ResolveEFBColorTexture(region); - - VkSampler src_sampler = - scale_by_half ? g_object_cache->GetLinearSampler() : g_object_cache->GetPointSampler(); - VkImageLayout original_layout = src_texture->GetLayout(); - src_texture->TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - texture->GetRawTexIdentifier()->TransitionToLayout(command_buffer, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - auto uid = TextureConversionShaderGen::GetShaderUid(dst_format, is_depth_copy, is_intensity, - scale_by_half, - NeedsCopyFilterInShader(filter_coefficients)); - - auto it = m_efb_copy_to_tex_shaders.emplace(uid, VkShaderModule(VK_NULL_HANDLE)); - VkShaderModule& shader = it.first->second; - bool created = it.second; - - if (created) - { - std::string source = g_shader_cache->GetUtilityShaderHeader(); - source += - TextureConversionShaderGen::GenerateShader(APIType::Vulkan, uid.GetUidData()).GetBuffer(); - - shader = Util::CompileAndCreateFragmentShader(source); - } - - VkRenderPass render_pass = g_object_cache->GetRenderPass( - texture->GetRawTexIdentifier()->GetFormat(), VK_FORMAT_UNDEFINED, - texture->GetRawTexIdentifier()->GetSamples(), VK_ATTACHMENT_LOAD_OP_DONT_CARE); - - UtilityShaderDraw draw(command_buffer, - g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD), render_pass, - g_shader_cache->GetPassthroughVertexShader(), - g_shader_cache->GetPassthroughGeometryShader(), shader); - - u8* ubo_ptr = draw.AllocatePSUniforms(sizeof(PixelUniforms)); - std::memcpy(ubo_ptr, &uniforms, sizeof(PixelUniforms)); - draw.CommitPSUniforms(sizeof(PixelUniforms)); - - draw.SetPSSampler(0, src_texture->GetView(), src_sampler); - - VkRect2D dest_region = {{0, 0}, {texture->GetConfig().width, texture->GetConfig().height}}; - - draw.BeginRenderPass(texture->GetFramebuffer(), dest_region); - - draw.DrawQuad(0, 0, texture->GetConfig().width, texture->GetConfig().height, scaled_src_rect.left, - scaled_src_rect.top, 0, scaled_src_rect.GetWidth(), scaled_src_rect.GetHeight(), - framebuffer_mgr->GetEFBWidth(), framebuffer_mgr->GetEFBHeight()); - - draw.EndRenderPass(); - - // We touched everything, so put it back. - StateTracker::GetInstance()->SetPendingRebind(); - - // Transition the EFB back to its original layout. - src_texture->TransitionToLayout(command_buffer, original_layout); - - // Ensure texture is in SHADER_READ_ONLY layout, ready for usage. - texture->GetRawTexIdentifier()->TransitionToLayout(command_buffer, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); -} - -} // namespace Vulkan |
