2018-04-07 11:12:38 +02:00
|
|
|
// Copyright 2018 yuzu Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2019-04-11 00:26:27 +02:00
|
|
|
#include <cstddef>
|
|
|
|
|
2018-04-07 11:12:38 +02:00
|
|
|
#include <glad/glad.h>
|
2018-08-23 23:30:27 +02:00
|
|
|
|
2018-04-07 11:12:38 +02:00
|
|
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
2018-11-06 10:40:49 +01:00
|
|
|
#include "video_core/renderer_opengl/gl_state.h"
|
2018-04-07 11:12:38 +02:00
|
|
|
#include "video_core/renderer_opengl/maxwell_to_gl.h"
|
|
|
|
|
2018-08-21 10:18:27 +02:00
|
|
|
namespace OpenGL::GLShader {
|
2018-04-07 11:12:38 +02:00
|
|
|
|
|
|
|
/// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
|
2019-03-27 18:10:40 +01:00
|
|
|
/// @note Always keep a vec4 at the end. The GL spec is not clear whether 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.
|
2018-04-07 11:12:38 +02:00
|
|
|
struct MaxwellUniformData {
|
2019-03-27 18:25:59 +01:00
|
|
|
void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage);
|
2019-03-27 18:17:35 +01:00
|
|
|
|
2018-04-18 22:42:40 +02:00
|
|
|
alignas(16) GLvec4 viewport_flip;
|
2018-11-25 08:37:29 +01:00
|
|
|
struct alignas(16) {
|
|
|
|
GLuint instance_id;
|
|
|
|
GLuint flip_stage;
|
|
|
|
GLfloat y_direction;
|
|
|
|
};
|
2018-10-10 22:34:15 +02:00
|
|
|
struct alignas(16) {
|
|
|
|
GLuint enabled;
|
|
|
|
GLuint func;
|
|
|
|
GLfloat ref;
|
|
|
|
GLuint padding;
|
|
|
|
} alpha_test;
|
2018-04-07 11:12:38 +02:00
|
|
|
};
|
2018-11-25 08:37:29 +01:00
|
|
|
static_assert(sizeof(MaxwellUniformData) == 48, "MaxwellUniformData structure size is incorrect");
|
2018-04-07 11:12:38 +02:00
|
|
|
static_assert(sizeof(MaxwellUniformData) < 16384,
|
|
|
|
"MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
|
|
|
|
|
|
|
|
class ProgramManager {
|
|
|
|
public:
|
2019-04-11 00:26:27 +02:00
|
|
|
explicit ProgramManager();
|
|
|
|
~ProgramManager();
|
|
|
|
|
|
|
|
void ApplyTo(OpenGLState& state);
|
2018-04-07 11:12:38 +02:00
|
|
|
|
2018-08-23 23:30:27 +02:00
|
|
|
void UseProgrammableVertexShader(GLuint program) {
|
2019-04-11 00:26:27 +02:00
|
|
|
current_state.vertex_shader = program;
|
2018-04-07 11:12:38 +02:00
|
|
|
}
|
|
|
|
|
2018-10-07 04:17:31 +02:00
|
|
|
void UseProgrammableGeometryShader(GLuint program) {
|
2019-04-11 00:26:27 +02:00
|
|
|
current_state.geometry_shader = program;
|
2018-10-07 04:17:31 +02:00
|
|
|
}
|
|
|
|
|
2018-08-23 23:30:27 +02:00
|
|
|
void UseProgrammableFragmentShader(GLuint program) {
|
2019-04-11 00:26:27 +02:00
|
|
|
current_state.fragment_shader = program;
|
2018-04-15 21:14:57 +02:00
|
|
|
}
|
|
|
|
|
2018-04-08 05:45:09 +02:00
|
|
|
void UseTrivialGeometryShader() {
|
2019-04-11 00:26:27 +02:00
|
|
|
current_state.geometry_shader = 0;
|
2018-11-29 07:24:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2019-04-11 00:26:27 +02:00
|
|
|
struct PipelineState {
|
|
|
|
bool operator==(const PipelineState& rhs) const {
|
|
|
|
return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader &&
|
|
|
|
geometry_shader == rhs.geometry_shader;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator!=(const PipelineState& rhs) const {
|
|
|
|
return !operator==(rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
GLuint vertex_shader{};
|
|
|
|
GLuint fragment_shader{};
|
|
|
|
GLuint geometry_shader{};
|
|
|
|
};
|
|
|
|
|
|
|
|
void UpdatePipeline();
|
2018-04-07 11:12:38 +02:00
|
|
|
|
|
|
|
OGLPipeline pipeline;
|
2019-04-11 00:26:27 +02:00
|
|
|
PipelineState current_state;
|
|
|
|
PipelineState old_state;
|
2018-04-07 11:12:38 +02:00
|
|
|
};
|
|
|
|
|
2018-08-21 10:18:27 +02:00
|
|
|
} // namespace OpenGL::GLShader
|