summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_rasterizer.h
blob: 1cd46c96a2b977069088ee4983bdb6a6667bf788 (plain) (blame)
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
173
174
175
// 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 DrawArrays() override;
    void NotifyMaxwellRegisterChanged(u32 id) override;
    void FlushAll() override;
    void FlushRegion(VAddr addr, u64 size) override;
    void InvalidateRegion(VAddr addr, u64 size) override;
    void FlushAndInvalidateRegion(VAddr addr, u64 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, VAddr 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 viewport to match the guest state
    void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale);

    /// 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, 32> 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;
};