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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <cstddef>
#include <cstring>
#include <memory>
#include <unordered_map>
#include <vector>
#include <glad/glad.h>
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/hash.h"
#include "common/vector_math.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h"
struct ScreenInfo;
class RasterizerOpenGL : public VideoCore::RasterizerInterface {
public:
RasterizerOpenGL();
~RasterizerOpenGL() override;
void DrawTriangles() override;
void NotifyMaxwellRegisterChanged(u32 id) override;
void FlushAll() override;
void FlushRegion(PAddr addr, u32 size) override;
void InvalidateRegion(PAddr addr, u32 size) override;
void FlushAndInvalidateRegion(PAddr addr, u32 size) override;
bool AccelerateDisplayTransfer(const void* config) override;
bool AccelerateTextureCopy(const void* config) override;
bool AccelerateFill(const void* config) override;
bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer, PAddr framebuffer_addr,
u32 pixel_stride, ScreenInfo& screen_info) override;
bool AccelerateDrawBatch(bool is_indexed) override;
/// OpenGL shader generated for a given Maxwell register state
struct MaxwellShader {
/// OpenGL shader resource
OGLShader shader;
};
struct VertexShader {
OGLShader shader;
};
struct FragmentShader {
OGLShader shader;
};
/// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
// NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at
// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
// Not following that rule will cause problems on some AMD drivers.
struct UniformData {};
// static_assert(
// sizeof(UniformData) == 0x460,
// "The size of the UniformData structure has changed, update the structure in the shader");
static_assert(sizeof(UniformData) < 16384,
"UniformData structure must be less than 16kb as per the OpenGL spec");
struct VSUniformData {};
// static_assert(
// sizeof(VSUniformData) == 1856,
// "The size of the VSUniformData structure has changed, update the structure in the
// shader");
static_assert(sizeof(VSUniformData) < 16384,
"VSUniformData structure must be less than 16kb as per the OpenGL spec");
struct FSUniformData {};
// static_assert(
// sizeof(FSUniformData) == 1856,
// "The size of the FSUniformData structure has changed, update the structure in the
// shader");
static_assert(sizeof(FSUniformData) < 16384,
"FSUniformData structure must be less than 16kb as per the OpenGL spec");
private:
struct SamplerInfo {};
/// Syncs the clip enabled status to match the guest state
void SyncClipEnabled();
/// Syncs the clip coefficients to match the guest state
void SyncClipCoef();
/// Sets the OpenGL shader in accordance with the current guest state
void SetShader();
/// Syncs the cull mode to match the guest state
void SyncCullMode();
/// Syncs the depth scale to match the guest state
void SyncDepthScale();
/// Syncs the depth offset to match the guest state
void SyncDepthOffset();
/// Syncs the blend enabled status to match the guest state
void SyncBlendEnabled();
/// Syncs the blend functions to match the guest state
void SyncBlendFuncs();
/// Syncs the blend color to match the guest state
void SyncBlendColor();
bool has_ARB_buffer_storage;
bool has_ARB_direct_state_access;
bool has_ARB_separate_shader_objects;
bool has_ARB_vertex_attrib_binding;
OpenGLState state;
RasterizerCacheOpenGL res_cache;
/// Shader used for test renderering - to be removed once we have emulated shaders
MaxwellShader test_shader{};
const MaxwellShader* current_shader{};
bool shader_dirty{};
struct {
UniformData data;
bool dirty;
} uniform_block_data = {};
OGLPipeline pipeline;
OGLVertexArray sw_vao;
OGLVertexArray hw_vao;
std::array<bool, 16> hw_vao_enabled_attributes;
std::array<SamplerInfo, 3> texture_samplers;
static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024;
std::unique_ptr<OGLStreamBuffer> vertex_buffer;
OGLBuffer uniform_buffer;
OGLFramebuffer framebuffer;
static constexpr size_t STREAM_BUFFER_SIZE = 4 * 1024 * 1024;
std::unique_ptr<OGLStreamBuffer> stream_buffer;
GLsizeiptr vs_input_size;
void AnalyzeVertexArray(bool is_indexed);
void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset);
OGLBuffer vs_uniform_buffer;
std::unordered_map<GLShader::MaxwellVSConfig, VertexShader*> vs_shader_map;
std::unordered_map<std::string, VertexShader> vs_shader_cache;
OGLShader vs_default_shader;
void SetupVertexShader(VSUniformData* ub_ptr, GLintptr buffer_offset);
OGLBuffer fs_uniform_buffer;
std::unordered_map<GLShader::MaxwellFSConfig, FragmentShader*> fs_shader_map;
std::unordered_map<std::string, FragmentShader> fs_shader_cache;
OGLShader fs_default_shader;
void SetupFragmentShader(FSUniformData* ub_ptr, GLintptr buffer_offset);
enum class AccelDraw { Disabled, Arrays, Indexed };
AccelDraw accelerate_draw;
};
|