-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
ProgramShaderCache.h
134 lines (111 loc) · 4 KB
/
ProgramShaderCache.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2011 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <atomic>
#include <memory>
#include <mutex>
#include <tuple>
#include <unordered_map>
#include "Common/GL/GLUtil.h"
#include "VideoCommon/AsyncShaderCompiler.h"
namespace OGL
{
class OGLShader;
class GLVertexFormat;
class StreamBuffer;
struct SHADER
{
void Destroy()
{
DestroyShaders();
if (glprogid)
{
glDeleteProgram(glprogid);
glprogid = 0;
}
}
GLuint vsid = 0;
GLuint gsid = 0;
GLuint psid = 0;
GLuint glprogid = 0;
void SetProgramVariables();
void SetProgramBindings(bool is_compute);
void Bind() const;
void DestroyShaders();
};
struct PipelineProgramKey
{
u64 vertex_shader_id;
u64 geometry_shader_id;
u64 pixel_shader_id;
bool operator==(const PipelineProgramKey& rhs) const;
bool operator!=(const PipelineProgramKey& rhs) const;
bool operator<(const PipelineProgramKey& rhs) const;
};
struct PipelineProgramKeyHash
{
std::size_t operator()(const PipelineProgramKey& key) const;
};
struct PipelineProgram
{
PipelineProgramKey key;
SHADER shader;
std::atomic_size_t reference_count{1};
bool binary_retrieved = false;
};
class ProgramShaderCache
{
public:
static void BindVertexFormat(const GLVertexFormat* vertex_format);
static bool IsValidVertexFormatBound();
static void InvalidateVertexFormat();
static void InvalidateLastProgram();
static bool CompileShader(SHADER& shader, const std::string& vcode, const std::string& pcode,
const std::string& gcode = "");
static bool CompileComputeShader(SHADER& shader, const std::string& code);
static GLuint CompileSingleShader(GLenum type, const std::string& code);
static bool CheckShaderCompileResult(GLuint id, GLenum type, const std::string& code);
static bool CheckProgramLinkResult(GLuint id, const std::string& vcode, const std::string& pcode,
const std::string& gcode);
static StreamBuffer* GetUniformBuffer();
static u32 GetUniformBufferAlignment();
static void UploadConstants();
static void UploadConstants(const void* data, u32 data_size);
static void Init();
static void Shutdown();
static void CreateHeader();
// This counter increments with each shader object allocated, in order to give it a unique ID.
// Since the shaders can be destroyed after a pipeline is created, we can't use the shader pointer
// as a key for GL programs. For the same reason, we can't use the GL objects either. This ID is
// guaranteed to be unique for the emulation session, even if the memory allocator or GL driver
// re-uses pointers, therefore we won't have any collisions where the shaders attached to a
// pipeline do not match the pipeline configuration.
static u64 GenerateShaderID();
static PipelineProgram* GetPipelineProgram(const GLVertexFormat* vertex_format,
const OGLShader* vertex_shader,
const OGLShader* geometry_shader,
const OGLShader* pixel_shader, const void* cache_data,
size_t cache_data_size);
static void ReleasePipelineProgram(PipelineProgram* prog);
private:
typedef std::unordered_map<PipelineProgramKey, std::unique_ptr<PipelineProgram>,
PipelineProgramKeyHash>
PipelineProgramMap;
static void CreateAttributelessVAO();
static PipelineProgramMap s_pipeline_programs;
static std::mutex s_pipeline_program_lock;
static u32 s_ubo_buffer_size;
static s32 s_ubo_align;
static GLuint s_attributeless_VBO;
static GLuint s_attributeless_VAO;
static GLuint s_last_VAO;
};
class SharedContextAsyncShaderCompiler : public VideoCommon::AsyncShaderCompiler
{
protected:
bool WorkerThreadInitMainThread(void** param) override;
bool WorkerThreadInitWorkerThread(void* param) override;
void WorkerThreadExit(void* param) override;
};
} // namespace OGL