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.
|
|
|
|
|
2020-03-11 05:03:01 +01:00
|
|
|
#include <glad/glad.h>
|
|
|
|
|
2019-04-11 00:26:27 +02:00
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "video_core/engines/maxwell_3d.h"
|
2020-05-18 03:32:49 +02:00
|
|
|
#include "video_core/renderer_opengl/gl_device.h"
|
2018-04-07 11:12:38 +02:00
|
|
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
|
|
|
|
2020-05-18 03:32:49 +02:00
|
|
|
namespace OpenGL {
|
2018-04-07 11:12:38 +02:00
|
|
|
|
2020-06-25 22:12:33 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
void BindProgram(GLenum stage, GLuint current, GLuint old, bool& enabled) {
|
|
|
|
if (current == old) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (current == 0) {
|
|
|
|
if (enabled) {
|
|
|
|
enabled = false;
|
|
|
|
glDisable(stage);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!enabled) {
|
|
|
|
enabled = true;
|
|
|
|
glEnable(stage);
|
|
|
|
}
|
|
|
|
glBindProgramARB(stage, current);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
ProgramManager::ProgramManager(const Device& device)
|
|
|
|
: use_assembly_programs{device.UseAssemblyShaders()} {
|
2020-05-18 03:32:49 +02:00
|
|
|
if (use_assembly_programs) {
|
|
|
|
glEnable(GL_COMPUTE_PROGRAM_NV);
|
|
|
|
} else {
|
|
|
|
graphics_pipeline.Create();
|
|
|
|
glBindProgramPipeline(graphics_pipeline.handle);
|
|
|
|
}
|
|
|
|
}
|
2019-03-27 18:25:59 +01:00
|
|
|
|
2019-04-11 00:26:27 +02:00
|
|
|
ProgramManager::~ProgramManager() = default;
|
|
|
|
|
2020-05-18 03:32:49 +02:00
|
|
|
void ProgramManager::BindCompute(GLuint program) {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
glBindProgramARB(GL_COMPUTE_PROGRAM_NV, program);
|
|
|
|
} else {
|
|
|
|
is_graphics_bound = false;
|
|
|
|
glUseProgram(program);
|
|
|
|
}
|
2019-04-11 00:26:27 +02:00
|
|
|
}
|
|
|
|
|
2020-03-11 05:03:01 +01:00
|
|
|
void ProgramManager::BindGraphicsPipeline() {
|
2020-06-25 22:12:33 +02:00
|
|
|
if (!use_assembly_programs) {
|
2020-05-18 03:32:49 +02:00
|
|
|
UpdateSourcePrograms();
|
2020-03-11 05:03:01 +01:00
|
|
|
}
|
2020-05-18 03:32:49 +02:00
|
|
|
}
|
2020-03-11 05:03:01 +01:00
|
|
|
|
2020-05-18 03:32:49 +02:00
|
|
|
void ProgramManager::BindHostPipeline(GLuint pipeline) {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
if (geometry_enabled) {
|
|
|
|
geometry_enabled = false;
|
|
|
|
old_state.geometry = 0;
|
|
|
|
glDisable(GL_GEOMETRY_PROGRAM_NV);
|
|
|
|
}
|
2020-05-26 09:20:39 +02:00
|
|
|
} else {
|
|
|
|
if (!is_graphics_bound) {
|
|
|
|
glUseProgram(0);
|
|
|
|
}
|
2019-04-11 00:26:27 +02:00
|
|
|
}
|
2020-05-18 03:32:49 +02:00
|
|
|
glBindProgramPipeline(pipeline);
|
|
|
|
}
|
2019-04-11 00:26:27 +02:00
|
|
|
|
2020-05-18 03:32:49 +02:00
|
|
|
void ProgramManager::RestoreGuestPipeline() {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
glBindProgramPipeline(0);
|
|
|
|
} else {
|
|
|
|
glBindProgramPipeline(graphics_pipeline.handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-30 06:25:23 +01:00
|
|
|
void ProgramManager::BindHostCompute(GLuint program) {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
glDisable(GL_COMPUTE_PROGRAM_NV);
|
|
|
|
}
|
|
|
|
glUseProgram(program);
|
|
|
|
is_graphics_bound = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProgramManager::RestoreGuestCompute() {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
glEnable(GL_COMPUTE_PROGRAM_NV);
|
|
|
|
glUseProgram(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-25 22:12:33 +02:00
|
|
|
void ProgramManager::UseVertexShader(GLuint program) {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
BindProgram(GL_VERTEX_PROGRAM_NV, program, current_state.vertex, vertex_enabled);
|
|
|
|
}
|
|
|
|
current_state.vertex = program;
|
|
|
|
}
|
2020-05-18 03:32:49 +02:00
|
|
|
|
2020-06-25 22:12:33 +02:00
|
|
|
void ProgramManager::UseGeometryShader(GLuint program) {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
BindProgram(GL_GEOMETRY_PROGRAM_NV, program, current_state.vertex, geometry_enabled);
|
|
|
|
}
|
|
|
|
current_state.geometry = program;
|
|
|
|
}
|
2019-04-11 00:26:27 +02:00
|
|
|
|
2020-06-25 22:12:33 +02:00
|
|
|
void ProgramManager::UseFragmentShader(GLuint program) {
|
|
|
|
if (use_assembly_programs) {
|
|
|
|
BindProgram(GL_FRAGMENT_PROGRAM_NV, program, current_state.vertex, fragment_enabled);
|
|
|
|
}
|
|
|
|
current_state.fragment = program;
|
2019-04-11 00:26:27 +02:00
|
|
|
}
|
|
|
|
|
2020-05-18 03:32:49 +02:00
|
|
|
void ProgramManager::UpdateSourcePrograms() {
|
|
|
|
if (!is_graphics_bound) {
|
|
|
|
is_graphics_bound = true;
|
|
|
|
glUseProgram(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
const GLuint handle = graphics_pipeline.handle;
|
|
|
|
const auto update_state = [handle](GLenum stage, GLuint current, GLuint old) {
|
|
|
|
if (current == old) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
glUseProgramStages(handle, stage, current);
|
|
|
|
};
|
|
|
|
update_state(GL_VERTEX_SHADER_BIT, current_state.vertex, old_state.vertex);
|
|
|
|
update_state(GL_GEOMETRY_SHADER_BIT, current_state.geometry, old_state.geometry);
|
|
|
|
update_state(GL_FRAGMENT_SHADER_BIT, current_state.fragment, old_state.fragment);
|
|
|
|
|
|
|
|
old_state = current_state;
|
2020-03-11 05:03:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void MaxwellUniformData::SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell) {
|
2019-03-27 18:17:35 +01:00
|
|
|
const auto& regs = maxwell.regs;
|
2018-04-18 22:42:40 +02:00
|
|
|
|
2018-11-25 08:37:29 +01:00
|
|
|
// Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value.
|
2019-10-30 04:23:09 +01:00
|
|
|
y_direction = regs.screen_y_control.y_negate == 0 ? 1.0f : -1.0f;
|
2018-04-18 22:42:40 +02:00
|
|
|
}
|
2018-04-07 11:12:38 +02:00
|
|
|
|
2020-05-18 03:32:49 +02:00
|
|
|
} // namespace OpenGL
|