1 // Copyright 2018 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <memory>
8 #include <glad/glad.h>
9 #include "video_core/rasterizer_interface.h"
10 #include "video_core/regs_lighting.h"
11 #include "video_core/renderer_opengl/gl_resource_manager.h"
12 #include "video_core/renderer_opengl/gl_shader_gen.h"
13 #include "video_core/renderer_opengl/gl_state.h"
14 #include "video_core/renderer_opengl/pica_to_gl.h"
15 
16 namespace Core {
17 class System;
18 }
19 
20 namespace OpenGL {
21 
22 enum class UniformBindings : GLuint { Common, VS, GS };
23 
24 struct LightSrc {
25     alignas(16) GLvec3 specular_0;
26     alignas(16) GLvec3 specular_1;
27     alignas(16) GLvec3 diffuse;
28     alignas(16) GLvec3 ambient;
29     alignas(16) GLvec3 position;
30     alignas(16) GLvec3 spot_direction; // negated
31     GLfloat dist_atten_bias;
32     GLfloat dist_atten_scale;
33 };
34 
35 /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
36 // NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at
37 //       the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
38 //       Not following that rule will cause problems on some AMD drivers.
39 struct UniformData {
40     GLint framebuffer_scale;
41     GLint alphatest_ref;
42     GLfloat depth_scale;
43     GLfloat depth_offset;
44     GLfloat shadow_bias_constant;
45     GLfloat shadow_bias_linear;
46     GLint scissor_x1;
47     GLint scissor_y1;
48     GLint scissor_x2;
49     GLint scissor_y2;
50     GLint fog_lut_offset;
51     GLint proctex_noise_lut_offset;
52     GLint proctex_color_map_offset;
53     GLint proctex_alpha_map_offset;
54     GLint proctex_lut_offset;
55     GLint proctex_diff_lut_offset;
56     GLfloat proctex_bias;
57     GLint shadow_texture_bias;
58     alignas(16) GLivec4 lighting_lut_offset[Pica::LightingRegs::NumLightingSampler / 4];
59     alignas(16) GLvec3 fog_color;
60     alignas(8) GLvec2 proctex_noise_f;
61     alignas(8) GLvec2 proctex_noise_a;
62     alignas(8) GLvec2 proctex_noise_p;
63     alignas(16) GLvec3 lighting_global_ambient;
64     LightSrc light_src[8];
65     alignas(16) GLvec4 const_color[6]; // A vec4 color for each of the six tev stages
66     alignas(16) GLvec4 tev_combiner_buffer_color;
67     alignas(16) GLvec4 clip_coef;
68 };
69 
70 static_assert(
71     sizeof(UniformData) == 0x4F0,
72     "The size of the UniformData structure has changed, update the structure in the shader");
73 static_assert(sizeof(UniformData) < 16384,
74               "UniformData structure must be less than 16kb as per the OpenGL spec");
75 
76 /// Uniform struct for the Uniform Buffer Object that contains PICA vertex/geometry shader uniforms.
77 // NOTE: the same rule from UniformData also applies here.
78 struct PicaUniformsData {
79     void SetFromRegs(const Pica::ShaderRegs& regs, const Pica::Shader::ShaderSetup& setup);
80 
81     struct BoolAligned {
82         alignas(16) GLint b;
83     };
84 
85     std::array<BoolAligned, 16> bools;
86     alignas(16) std::array<GLuvec4, 4> i;
87     alignas(16) std::array<GLvec4, 96> f;
88 };
89 
90 struct VSUniformData {
91     PicaUniformsData uniforms;
92 };
93 static_assert(
94     sizeof(VSUniformData) == 1856,
95     "The size of the VSUniformData structure has changed, update the structure in the shader");
96 static_assert(sizeof(VSUniformData) < 16384,
97               "VSUniformData structure must be less than 16kb as per the OpenGL spec");
98 
99 /// A class that manage different shader stages and configures them with given config data.
100 class ShaderProgramManager {
101 public:
102     ShaderProgramManager(bool separable, bool is_amd);
103     ~ShaderProgramManager();
104 
105     void LoadDiskCache(const std::atomic_bool& stop_loading,
106                        const VideoCore::DiskResourceLoadCallback& callback);
107 
108     bool UseProgrammableVertexShader(const Pica::Regs& config, Pica::Shader::ShaderSetup& setup);
109 
110     void UseTrivialVertexShader();
111 
112     void UseFixedGeometryShader(const Pica::Regs& regs);
113 
114     void UseTrivialGeometryShader();
115 
116     void UseFragmentShader(const Pica::Regs& config);
117 
118     void ApplyTo(OpenGLState& state);
119 
120 private:
121     class Impl;
122     std::unique_ptr<Impl> impl;
123 };
124 } // namespace OpenGL
125