summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/ShaderCache.cpp
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2019-02-15 11:59:50 +1000
committerStenzek <stenzek@gmail.com>2019-02-19 16:57:54 +1000
commitf039149198657c1891e1c6462ed30c31ed4b8486 (patch)
treeb914fd7b0ef9c937e9334a880a49a26a26f17c8f /Source/Core/VideoCommon/ShaderCache.cpp
parent933f3ba008942cba96ed623c25e61d6ea86582fe (diff)
Move most backend functionality to VideoCommon
Diffstat (limited to 'Source/Core/VideoCommon/ShaderCache.cpp')
-rw-r--r--Source/Core/VideoCommon/ShaderCache.cpp220
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