diff options
Diffstat (limited to 'Source/Core/VideoCommon/ShaderCache.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/ShaderCache.cpp | 220 |
1 files changed, 184 insertions, 36 deletions
diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 3b0c110f96..b42587a2d4 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -9,7 +9,8 @@ #include "Common/MsgHandler.h" #include "Core/ConfigManager.h" -#include "VideoCommon/FramebufferManagerBase.h" +#include "VideoCommon/FramebufferManager.h" +#include "VideoCommon/FramebufferShaderGen.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexLoaderManager.h" @@ -22,17 +23,26 @@ std::unique_ptr<VideoCommon::ShaderCache> g_shader_cache; namespace VideoCommon { ShaderCache::ShaderCache() = default; -ShaderCache::~ShaderCache() = default; +ShaderCache::~ShaderCache() +{ + ClearShaderCaches(); + ClearPipelineCaches(); +} bool ShaderCache::Initialize() { m_api_type = g_ActiveConfig.backend_info.api_type; m_host_config = ShaderHostConfig::GetCurrent(); - m_efb_depth_format = FramebufferManagerBase::GetEFBDepthFormat(); - m_efb_multisamples = g_ActiveConfig.iMultisamples; - // Create the async compiler, and start the worker threads. + if (!CompileSharedPipelines()) + return false; + m_async_shader_compiler = g_renderer->CreateAsyncShaderCompiler(); + return true; +} + +void ShaderCache::InitializeShaderCache() +{ m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderPrecompilerThreads()); // Load shader and UID caches. @@ -53,17 +63,6 @@ bool ShaderCache::Initialize() // Switch to the runtime shader compiler thread configuration. m_async_shader_compiler->ResizeWorkerThreads(g_ActiveConfig.GetShaderCompilerThreads()); - return true; -} - -void ShaderCache::SetHostConfig(const ShaderHostConfig& host_config, u32 efb_multisamples) -{ - if (m_host_config.bits == host_config.bits && m_efb_multisamples == efb_multisamples) - return; - - m_host_config = host_config; - m_efb_multisamples = efb_multisamples; - Reload(); } void ShaderCache::Reload() @@ -99,8 +98,6 @@ void ShaderCache::Shutdown() // until everything has finished compiling. m_async_shader_compiler->StopWorkerThreads(); ClosePipelineUIDCache(); - ClearShaderCaches(); - ClearPipelineCaches(); } const AbstractPipeline* ShaderCache::GetPipelineForUid(const GXPipelineUid& uid) @@ -445,6 +442,11 @@ bool ShaderCache::NeedsGeometryShader(const GeometryShaderUid& uid) const return m_host_config.backend_geometry_shaders && !uid.GetUidData()->IsPassthrough(); } +bool ShaderCache::UseGeometryShaderForEFBCopies() const +{ + return m_host_config.backend_geometry_shaders && m_host_config.stereo; +} + AbstractPipelineConfig ShaderCache::GetGXPipelineConfig( const NativeVertexFormat* vertex_format, const AbstractShader* vertex_shader, const AbstractShader* geometry_shader, const AbstractShader* pixel_shader, @@ -460,10 +462,7 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig( config.rasterization_state = rasterization_state; config.depth_state = depth_state; config.blending_state = blending_state; - config.framebuffer_state.color_texture_format = AbstractTextureFormat::RGBA8; - config.framebuffer_state.depth_texture_format = m_efb_depth_format; - config.framebuffer_state.per_sample_shading = m_host_config.ssaa; - config.framebuffer_state.samples = m_efb_multisamples; + config.framebuffer_state = g_framebuffer_manager->GetEFBFramebufferState(); return config; } @@ -967,8 +966,9 @@ void ShaderCache::QueueUberShaderPipelines() config.vs_uid = vs_uid; config.gs_uid = gs_uid; config.ps_uid = ps_uid; - config.rasterization_state = RenderState::GetNoCullRasterizationState(); - config.depth_state = RenderState::GetNoDepthTestingDepthStencilState(); + config.rasterization_state = + RenderState::GetCullBackFaceRasterizationState(PrimitiveType::TriangleStrip); + config.depth_state = RenderState::GetNoDepthTestingDepthState(); config.blending_state = RenderState::GetNoBlendingBlendState(); auto iter = m_gx_uber_pipeline_cache.find(config); @@ -998,24 +998,172 @@ void ShaderCache::QueueUberShaderPipelines() }); } -std::string ShaderCache::GetUtilityShaderHeader() const +const AbstractPipeline* +ShaderCache::GetEFBCopyToVRAMPipeline(const TextureConversionShaderGen::TCShaderUid& uid) +{ + auto iter = m_efb_copy_to_vram_pipelines.find(uid); + if (iter != m_efb_copy_to_vram_pipelines.end()) + return iter->second.get(); + + auto shader_code = TextureConversionShaderGen::GeneratePixelShader(m_api_type, uid.GetUidData()); + auto shader = g_renderer->CreateShaderFromSource(ShaderStage::Pixel, shader_code.GetBuffer()); + if (!shader) + { + m_efb_copy_to_vram_pipelines.emplace(uid, nullptr); + return nullptr; + } + + AbstractPipelineConfig config = {}; + config.vertex_format = nullptr; + config.vertex_shader = m_efb_copy_vertex_shader.get(); + config.geometry_shader = + UseGeometryShaderForEFBCopies() ? m_texcoord_geometry_shader.get() : nullptr; + config.pixel_shader = shader.get(); + config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles); + config.depth_state = RenderState::GetNoDepthTestingDepthState(); + config.blending_state = RenderState::GetNoBlendingBlendState(); + config.framebuffer_state = RenderState::GetRGBA8FramebufferState(); + config.usage = AbstractPipelineUsage::Utility; + auto iiter = m_efb_copy_to_vram_pipelines.emplace(uid, g_renderer->CreatePipeline(config)); + return iiter.first->second.get(); +} + +const AbstractPipeline* ShaderCache::GetEFBCopyToRAMPipeline(const EFBCopyParams& uid) +{ + auto iter = m_efb_copy_to_ram_pipelines.find(uid); + if (iter != m_efb_copy_to_ram_pipelines.end()) + return iter->second.get(); + + auto shader_code = TextureConversionShaderTiled::GenerateEncodingShader(uid, m_api_type); + auto shader = + g_renderer->CreateShaderFromSource(ShaderStage::Pixel, shader_code, std::strlen(shader_code)); + if (!shader) + { + m_efb_copy_to_ram_pipelines.emplace(uid, nullptr); + return nullptr; + } + + AbstractPipelineConfig config = {}; + config.vertex_format = nullptr; + config.vertex_shader = m_screen_quad_vertex_shader.get(); + config.geometry_shader = + UseGeometryShaderForEFBCopies() ? m_texcoord_geometry_shader.get() : nullptr; + config.pixel_shader = shader.get(); + config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles); + config.depth_state = RenderState::GetNoDepthTestingDepthState(); + config.blending_state = RenderState::GetNoBlendingBlendState(); + config.framebuffer_state = RenderState::GetColorFramebufferState(AbstractTextureFormat::BGRA8); + config.usage = AbstractPipelineUsage::Utility; + auto iiter = m_efb_copy_to_ram_pipelines.emplace(uid, g_renderer->CreatePipeline(config)); + return iiter.first->second.get(); +} + +bool ShaderCache::CompileSharedPipelines() { - std::stringstream ss; + m_screen_quad_vertex_shader = g_renderer->CreateShaderFromSource( + ShaderStage::Vertex, FramebufferShaderGen::GenerateScreenQuadVertexShader()); + m_texture_copy_vertex_shader = g_renderer->CreateShaderFromSource( + ShaderStage::Vertex, FramebufferShaderGen::GenerateTextureCopyVertexShader()); + m_efb_copy_vertex_shader = g_renderer->CreateShaderFromSource( + ShaderStage::Vertex, + TextureConversionShaderGen::GenerateVertexShader(m_api_type).GetBuffer()); + if (!m_screen_quad_vertex_shader || !m_texture_copy_vertex_shader || !m_efb_copy_vertex_shader) + return false; + + if (UseGeometryShaderForEFBCopies()) + { + m_texcoord_geometry_shader = g_renderer->CreateShaderFromSource( + ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(1, 0)); + m_color_geometry_shader = g_renderer->CreateShaderFromSource( + ShaderStage::Geometry, FramebufferShaderGen::GeneratePassthroughGeometryShader(0, 1)); + if (!m_texcoord_geometry_shader || !m_color_geometry_shader) + return false; + } + + m_texture_copy_pixel_shader = g_renderer->CreateShaderFromSource( + ShaderStage::Pixel, FramebufferShaderGen::GenerateTextureCopyPixelShader()); + m_color_pixel_shader = g_renderer->CreateShaderFromSource( + ShaderStage::Pixel, FramebufferShaderGen::GenerateColorPixelShader()); + if (!m_texture_copy_pixel_shader || !m_color_pixel_shader) + return false; + + AbstractPipelineConfig config; + config.vertex_format = nullptr; + config.vertex_shader = m_texture_copy_vertex_shader.get(); + config.geometry_shader = nullptr; + config.pixel_shader = m_texture_copy_pixel_shader.get(); + config.rasterization_state = RenderState::GetNoCullRasterizationState(PrimitiveType::Triangles); + config.depth_state = RenderState::GetNoDepthTestingDepthState(); + config.blending_state = RenderState::GetNoBlendingBlendState(); + config.framebuffer_state = RenderState::GetRGBA8FramebufferState(); + config.usage = AbstractPipelineUsage::Utility; + m_copy_rgba8_pipeline = g_renderer->CreatePipeline(config); + if (!m_copy_rgba8_pipeline) + return false; + + if (UseGeometryShaderForEFBCopies()) + { + config.geometry_shader = m_texcoord_geometry_shader.get(); + m_rgba8_stereo_copy_pipeline = g_renderer->CreatePipeline(config); + if (!m_rgba8_stereo_copy_pipeline) + return false; + } + + if (m_host_config.backend_palette_conversion) + { + config.vertex_shader = m_screen_quad_vertex_shader.get(); + config.geometry_shader = nullptr; + + for (size_t i = 0; i < NUM_PALETTE_CONVERSION_SHADERS; i++) + { + auto shader = g_renderer->CreateShaderFromSource( + ShaderStage::Pixel, TextureConversionShaderTiled::GeneratePaletteConversionShader( + static_cast<TLUTFormat>(i), m_api_type)); + if (!shader) + return false; + + config.pixel_shader = shader.get(); + m_palette_conversion_pipelines[i] = g_renderer->CreatePipeline(config); + if (!m_palette_conversion_pipelines[i]) + return false; + } + } + + return true; +} - ss << "#define API_D3D " << (m_api_type == APIType::D3D ? 1 : 0) << "\n"; - ss << "#define API_OPENGL " << (m_api_type == APIType::OpenGL ? 1 : 0) << "\n"; - ss << "#define API_VULKAN " << (m_api_type == APIType::Vulkan ? 1 : 0) << "\n"; +const AbstractPipeline* ShaderCache::GetPaletteConversionPipeline(TLUTFormat format) +{ + ASSERT(static_cast<size_t>(format) < NUM_PALETTE_CONVERSION_SHADERS); + return m_palette_conversion_pipelines[static_cast<size_t>(format)].get(); +} - if (m_efb_multisamples > 1) +const AbstractShader* ShaderCache::GetTextureDecodingShader(TextureFormat format, + TLUTFormat palette_format) +{ + const auto key = std::make_pair(static_cast<u32>(format), static_cast<u32>(palette_format)); + auto iter = m_texture_decoding_shaders.find(key); + if (iter != m_texture_decoding_shaders.end()) + return iter->second.get(); + + std::string shader_source = + TextureConversionShaderTiled::GenerateDecodingShader(format, palette_format, APIType::OpenGL); + if (shader_source.empty()) { - ss << "#define MSAA_ENABLED 1" << std::endl; - ss << "#define MSAA_SAMPLES " << m_efb_multisamples << std::endl; - if (m_host_config.ssaa) - ss << "#define SSAA_ENABLED 1" << std::endl; + m_texture_decoding_shaders.emplace(key, nullptr); + return nullptr; } - ss << "#define EFB_LAYERS " << (m_host_config.stereo ? 2 : 1) << std::endl; + std::unique_ptr<AbstractShader> shader = + g_renderer->CreateShaderFromSource(ShaderStage::Compute, shader_source); + if (!shader) + { + m_texture_decoding_shaders.emplace(key, nullptr); + return nullptr; + } - return ss.str(); + auto iiter = m_texture_decoding_shaders.emplace(key, std::move(shader)); + return iiter.first->second.get(); } + } // namespace VideoCommon |
