summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/OGLPipeline.cpp
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2019-04-15 23:38:10 +1000
committerStenzek <stenzek@gmail.com>2019-04-16 00:39:43 +1000
commit616ad378b7e129645714858ebd0e541471704487 (patch)
tree39f3b0d19670b07de65a122d6152533ec5c9424d /Source/Core/VideoBackends/OGL/OGLPipeline.cpp
parent5cef09e383c7f9c3bf006407d06f68d18b2db438 (diff)
OGL: Support returning pipeline cache data
Diffstat (limited to 'Source/Core/VideoBackends/OGL/OGLPipeline.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/OGLPipeline.cpp43
1 files changed, 39 insertions, 4 deletions
diff --git a/Source/Core/VideoBackends/OGL/OGLPipeline.cpp b/Source/Core/VideoBackends/OGL/OGLPipeline.cpp
index bd439898db..00ae8aa873 100644
--- a/Source/Core/VideoBackends/OGL/OGLPipeline.cpp
+++ b/Source/Core/VideoBackends/OGL/OGLPipeline.cpp
@@ -9,6 +9,7 @@
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/Render.h"
#include "VideoBackends/OGL/VertexManager.h"
+#include "VideoCommon/VideoConfig.h"
namespace OGL
{
@@ -31,7 +32,7 @@ static GLenum MapToGLPrimitive(PrimitiveType primitive_type)
OGLPipeline::OGLPipeline(const GLVertexFormat* vertex_format,
const RasterizationState& rasterization_state,
const DepthState& depth_state, const BlendingState& blending_state,
- const PipelineProgram* program, GLuint gl_primitive)
+ PipelineProgram* program, GLuint gl_primitive)
: m_vertex_format(vertex_format), m_rasterization_state(rasterization_state),
m_depth_state(depth_state), m_blending_state(blending_state), m_program(program),
m_gl_primitive(gl_primitive)
@@ -44,13 +45,47 @@ OGLPipeline::~OGLPipeline()
ProgramShaderCache::ReleasePipelineProgram(m_program);
}
-std::unique_ptr<OGLPipeline> OGLPipeline::Create(const AbstractPipelineConfig& config)
+AbstractPipeline::CacheData OGLPipeline::GetCacheData() const
{
- const PipelineProgram* program = ProgramShaderCache::GetPipelineProgram(
+ // More than one pipeline can share the same shaders. To avoid bloating the cache with multiple
+ // copies of the same program combination, we set a flag on the program object so that it can't
+ // be retrieved again. When booting, the pipeline cache is loaded in-order, so the additional
+ // pipelines which use the program combination will re-use the already-created object.
+ if (!g_ActiveConfig.backend_info.bSupportsPipelineCacheData || m_program->binary_retrieved)
+ return {};
+
+ GLint program_size = 0;
+ glGetProgramiv(m_program->shader.glprogid, GL_PROGRAM_BINARY_LENGTH, &program_size);
+ if (program_size == 0)
+ return {};
+
+ // Clear any existing error.
+ glGetError();
+
+ // We pack the format at the start of the buffer.
+ CacheData data(program_size + sizeof(u32));
+ GLsizei data_size = 0;
+ GLenum program_format = 0;
+ glGetProgramBinary(m_program->shader.glprogid, program_size, &data_size, &program_format,
+ &data[sizeof(u32)]);
+ if (glGetError() != GL_NO_ERROR || data_size == 0)
+ return {};
+
+ u32 program_format_u32 = static_cast<u32>(program_format);
+ std::memcpy(&data[0], &program_format_u32, sizeof(u32));
+ data.resize(data_size + sizeof(u32));
+ m_program->binary_retrieved = true;
+ return data;
+}
+
+std::unique_ptr<OGLPipeline> OGLPipeline::Create(const AbstractPipelineConfig& config,
+ const void* cache_data, size_t cache_data_size)
+{
+ PipelineProgram* program = ProgramShaderCache::GetPipelineProgram(
static_cast<const GLVertexFormat*>(config.vertex_format),
static_cast<const OGLShader*>(config.vertex_shader),
static_cast<const OGLShader*>(config.geometry_shader),
- static_cast<const OGLShader*>(config.pixel_shader));
+ static_cast<const OGLShader*>(config.pixel_shader), cache_data, cache_data_size);
if (!program)
return nullptr;