Merge branch 'master' into shader-purge
This commit is contained in:
commit
244fe13219
16 changed files with 178 additions and 47 deletions
|
@ -484,6 +484,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
|
|||
|
||||
SyncViewport();
|
||||
SyncRasterizeEnable();
|
||||
SyncPolygonModes();
|
||||
SyncColorMask();
|
||||
SyncFragmentColorClampState();
|
||||
SyncMultiSampleState();
|
||||
|
@ -562,7 +563,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
|
|||
bind_ubo_pushbuffer.Bind();
|
||||
bind_ssbo_pushbuffer.Bind();
|
||||
|
||||
program_manager.Update();
|
||||
program_manager.BindGraphicsPipeline();
|
||||
|
||||
if (texture_cache.TextureBarrier()) {
|
||||
glTextureBarrier();
|
||||
|
@ -619,7 +620,7 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
|
|||
auto kernel = shader_cache.GetComputeKernel(code_addr);
|
||||
SetupComputeTextures(kernel);
|
||||
SetupComputeImages(kernel);
|
||||
glUseProgramStages(program_manager.GetHandle(), GL_COMPUTE_SHADER_BIT, kernel->GetHandle());
|
||||
program_manager.BindComputeShader(kernel->GetHandle());
|
||||
|
||||
const std::size_t buffer_size =
|
||||
Tegra::Engines::KeplerCompute::NumConstBuffers *
|
||||
|
@ -1089,6 +1090,45 @@ void RasterizerOpenGL::SyncRasterizeEnable() {
|
|||
oglEnable(GL_RASTERIZER_DISCARD, gpu.regs.rasterize_enable == 0);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SyncPolygonModes() {
|
||||
auto& gpu = system.GPU().Maxwell3D();
|
||||
auto& flags = gpu.dirty.flags;
|
||||
if (!flags[Dirty::PolygonModes]) {
|
||||
return;
|
||||
}
|
||||
flags[Dirty::PolygonModes] = false;
|
||||
|
||||
if (gpu.regs.fill_rectangle) {
|
||||
if (!GLAD_GL_NV_fill_rectangle) {
|
||||
LOG_ERROR(Render_OpenGL, "GL_NV_fill_rectangle used and not supported");
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
return;
|
||||
}
|
||||
|
||||
flags[Dirty::PolygonModeFront] = true;
|
||||
flags[Dirty::PolygonModeBack] = true;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_RECTANGLE_NV);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpu.regs.polygon_mode_front == gpu.regs.polygon_mode_back) {
|
||||
flags[Dirty::PolygonModeFront] = false;
|
||||
flags[Dirty::PolygonModeBack] = false;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front));
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags[Dirty::PolygonModeFront]) {
|
||||
flags[Dirty::PolygonModeFront] = false;
|
||||
glPolygonMode(GL_FRONT, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_front));
|
||||
}
|
||||
|
||||
if (flags[Dirty::PolygonModeBack]) {
|
||||
flags[Dirty::PolygonModeBack] = false;
|
||||
glPolygonMode(GL_BACK, MaxwellToGL::PolygonMode(gpu.regs.polygon_mode_back));
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SyncColorMask() {
|
||||
auto& gpu = system.GPU().Maxwell3D();
|
||||
auto& flags = gpu.dirty.flags;
|
||||
|
|
|
@ -177,6 +177,9 @@ private:
|
|||
/// Syncs the rasterizer enable state to match the guest state
|
||||
void SyncRasterizeEnable();
|
||||
|
||||
/// Syncs polygon modes to match the guest state
|
||||
void SyncPolygonModes();
|
||||
|
||||
/// Syncs Color Mask
|
||||
void SyncColorMask();
|
||||
|
||||
|
|
|
@ -2,21 +2,29 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/engines/maxwell_3d.h"
|
||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||
|
||||
namespace OpenGL::GLShader {
|
||||
|
||||
using Tegra::Engines::Maxwell3D;
|
||||
ProgramManager::ProgramManager() = default;
|
||||
|
||||
ProgramManager::~ProgramManager() = default;
|
||||
|
||||
void ProgramManager::Create() {
|
||||
pipeline.Create();
|
||||
graphics_pipeline.Create();
|
||||
glBindProgramPipeline(graphics_pipeline.handle);
|
||||
}
|
||||
|
||||
void ProgramManager::Update() {
|
||||
void ProgramManager::BindGraphicsPipeline() {
|
||||
if (!is_graphics_bound) {
|
||||
is_graphics_bound = true;
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
// Avoid updating the pipeline when values have no changed
|
||||
if (old_state == current_state) {
|
||||
return;
|
||||
|
@ -25,16 +33,21 @@ void ProgramManager::Update() {
|
|||
// Workaround for AMD bug
|
||||
static constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT |
|
||||
GL_FRAGMENT_SHADER_BIT};
|
||||
glUseProgramStages(pipeline.handle, all_used_stages, 0);
|
||||
|
||||
glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader);
|
||||
glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader);
|
||||
glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader);
|
||||
const GLuint handle = graphics_pipeline.handle;
|
||||
glUseProgramStages(handle, all_used_stages, 0);
|
||||
glUseProgramStages(handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader);
|
||||
glUseProgramStages(handle, GL_GEOMETRY_SHADER_BIT, current_state.geometry_shader);
|
||||
glUseProgramStages(handle, GL_FRAGMENT_SHADER_BIT, current_state.fragment_shader);
|
||||
|
||||
old_state = current_state;
|
||||
}
|
||||
|
||||
void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell) {
|
||||
void ProgramManager::BindComputeShader(GLuint program) {
|
||||
is_graphics_bound = false;
|
||||
glUseProgram(program);
|
||||
}
|
||||
|
||||
void MaxwellUniformData::SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell) {
|
||||
const auto& regs = maxwell.regs;
|
||||
|
||||
// Y_NEGATE controls what value S2R returns for the Y_DIRECTION system value.
|
||||
|
|
|
@ -28,11 +28,16 @@ static_assert(sizeof(MaxwellUniformData) < 16384,
|
|||
|
||||
class ProgramManager {
|
||||
public:
|
||||
explicit ProgramManager();
|
||||
~ProgramManager();
|
||||
|
||||
void Create();
|
||||
|
||||
void Update();
|
||||
/// Updates the graphics pipeline and binds it.
|
||||
void BindGraphicsPipeline();
|
||||
|
||||
/// Binds a compute shader.
|
||||
void BindComputeShader(GLuint program);
|
||||
|
||||
void UseVertexShader(GLuint program) {
|
||||
current_state.vertex_shader = program;
|
||||
|
@ -46,33 +51,27 @@ public:
|
|||
current_state.fragment_shader = program;
|
||||
}
|
||||
|
||||
GLuint GetHandle() const {
|
||||
return pipeline.handle;
|
||||
}
|
||||
|
||||
void UseTrivialFragmentShader() {
|
||||
current_state.fragment_shader = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
struct PipelineState {
|
||||
bool operator==(const PipelineState& rhs) const {
|
||||
bool operator==(const PipelineState& rhs) const noexcept {
|
||||
return vertex_shader == rhs.vertex_shader && fragment_shader == rhs.fragment_shader &&
|
||||
geometry_shader == rhs.geometry_shader;
|
||||
}
|
||||
|
||||
bool operator!=(const PipelineState& rhs) const {
|
||||
bool operator!=(const PipelineState& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
GLuint vertex_shader{};
|
||||
GLuint fragment_shader{};
|
||||
GLuint geometry_shader{};
|
||||
GLuint vertex_shader = 0;
|
||||
GLuint fragment_shader = 0;
|
||||
GLuint geometry_shader = 0;
|
||||
};
|
||||
|
||||
OGLPipeline pipeline;
|
||||
OGLPipeline graphics_pipeline;
|
||||
OGLPipeline compute_pipeline;
|
||||
PipelineState current_state;
|
||||
PipelineState old_state;
|
||||
bool is_graphics_bound = true;
|
||||
};
|
||||
|
||||
} // namespace OpenGL::GLShader
|
||||
|
|
|
@ -94,6 +94,15 @@ void SetupDirtyShaders(Tables& tables) {
|
|||
Shaders);
|
||||
}
|
||||
|
||||
void SetupDirtyPolygonModes(Tables& tables) {
|
||||
tables[0][OFF(polygon_mode_front)] = PolygonModeFront;
|
||||
tables[0][OFF(polygon_mode_back)] = PolygonModeBack;
|
||||
|
||||
tables[1][OFF(polygon_mode_front)] = PolygonModes;
|
||||
tables[1][OFF(polygon_mode_back)] = PolygonModes;
|
||||
tables[0][OFF(fill_rectangle)] = PolygonModes;
|
||||
}
|
||||
|
||||
void SetupDirtyDepthTest(Tables& tables) {
|
||||
auto& table = tables[0];
|
||||
table[OFF(depth_test_enable)] = DepthTest;
|
||||
|
@ -211,6 +220,7 @@ void StateTracker::Initialize() {
|
|||
SetupDirtyVertexArrays(tables);
|
||||
SetupDirtyVertexFormat(tables);
|
||||
SetupDirtyShaders(tables);
|
||||
SetupDirtyPolygonModes(tables);
|
||||
SetupDirtyDepthTest(tables);
|
||||
SetupDirtyStencilTest(tables);
|
||||
SetupDirtyAlphaTest(tables);
|
||||
|
|
|
@ -59,6 +59,10 @@ enum : u8 {
|
|||
Shaders,
|
||||
ClipDistances,
|
||||
|
||||
PolygonModes,
|
||||
PolygonModeFront,
|
||||
PolygonModeBack,
|
||||
|
||||
ColorMask,
|
||||
FrontFace,
|
||||
CullTest,
|
||||
|
@ -111,6 +115,13 @@ public:
|
|||
flags[OpenGL::Dirty::VertexInstance0 + 1] = true;
|
||||
}
|
||||
|
||||
void NotifyPolygonModes() {
|
||||
auto& flags = system.GPU().Maxwell3D().dirty.flags;
|
||||
flags[OpenGL::Dirty::PolygonModes] = true;
|
||||
flags[OpenGL::Dirty::PolygonModeFront] = true;
|
||||
flags[OpenGL::Dirty::PolygonModeBack] = true;
|
||||
}
|
||||
|
||||
void NotifyViewport0() {
|
||||
auto& flags = system.GPU().Maxwell3D().dirty.flags;
|
||||
flags[OpenGL::Dirty::Viewports] = true;
|
||||
|
|
|
@ -488,5 +488,18 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) {
|
|||
return GL_COPY;
|
||||
}
|
||||
|
||||
inline GLenum PolygonMode(Maxwell::PolygonMode polygon_mode) {
|
||||
switch (polygon_mode) {
|
||||
case Maxwell::PolygonMode::Point:
|
||||
return GL_POINT;
|
||||
case Maxwell::PolygonMode::Line:
|
||||
return GL_LINE;
|
||||
case Maxwell::PolygonMode::Fill:
|
||||
return GL_FILL;
|
||||
}
|
||||
UNREACHABLE_MSG("Invalid polygon mode={}", static_cast<int>(polygon_mode));
|
||||
return GL_FILL;
|
||||
}
|
||||
|
||||
} // namespace MaxwellToGL
|
||||
} // namespace OpenGL
|
||||
|
|
|
@ -443,7 +443,6 @@ void RendererOpenGL::InitOpenGLObjects() {
|
|||
|
||||
// Create program pipeline
|
||||
program_manager.Create();
|
||||
glBindProgramPipeline(program_manager.GetHandle());
|
||||
|
||||
// Generate VBO handle for drawing
|
||||
vertex_buffer.Create();
|
||||
|
@ -577,6 +576,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
|||
|
||||
// TODO: Signal state tracker about these changes
|
||||
state_tracker.NotifyScreenDrawVertexArray();
|
||||
state_tracker.NotifyPolygonModes();
|
||||
state_tracker.NotifyViewport0();
|
||||
state_tracker.NotifyScissor0();
|
||||
state_tracker.NotifyColorMask0();
|
||||
|
@ -596,7 +596,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
|||
program_manager.UseVertexShader(vertex_program.handle);
|
||||
program_manager.UseGeometryShader(0);
|
||||
program_manager.UseFragmentShader(fragment_program.handle);
|
||||
program_manager.Update();
|
||||
program_manager.BindGraphicsPipeline();
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
if (screen_info.display_srgb) {
|
||||
|
@ -612,6 +612,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
|||
glDisable(GL_ALPHA_TEST);
|
||||
glDisablei(GL_BLEND, 0);
|
||||
glDisablei(GL_SCISSOR_TEST, 0);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CW);
|
||||
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue