summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_rasterizer.h
blob: 893fc530f5ff04f4ee5363c3e94649802b20b323 (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
// 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 void* config, PAddr framebuffer_addr, u32 pixel_stride,
                           ScreenInfo& screen_info) override;
    bool AccelerateDrawBatch(bool is_indexed) override;

    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;

    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;

    GLint vs_input_index_min;
    GLint vs_input_index_max;
    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;
};