fix viewport and scissor behavior
This commit is contained in:
parent
a819116154
commit
1881e86c43
6 changed files with 89 additions and 64 deletions
|
@ -642,7 +642,7 @@ void RasterizerOpenGL::DrawArrays() {
|
|||
params.DispatchDraw();
|
||||
|
||||
// Disable scissor test
|
||||
state.scissor.enabled = false;
|
||||
state.viewports[0].scissor.enabled = false;
|
||||
|
||||
accelerate_draw = AccelDraw::Disabled;
|
||||
|
||||
|
@ -923,15 +923,15 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
|
|||
|
||||
void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
|
||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumViewports; i++) {
|
||||
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
|
||||
auto& viewport = current_state.viewports[i];
|
||||
viewport.x = viewport_rect.left;
|
||||
viewport.y = viewport_rect.bottom;
|
||||
viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth());
|
||||
viewport.height = static_cast<GLfloat>(viewport_rect.GetHeight());
|
||||
viewport.depth_range_far = regs.viewport[i].depth_range_far;
|
||||
viewport.depth_range_near = regs.viewport[i].depth_range_near;
|
||||
viewport.depth_range_far = regs.viewports[i].depth_range_far;
|
||||
viewport.depth_range_near = regs.viewports[i].depth_range_near;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1079,7 +1079,6 @@ void RasterizerOpenGL::SyncBlendState() {
|
|||
void RasterizerOpenGL::SyncLogicOpState() {
|
||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||
|
||||
// TODO(Subv): Support more than just render target 0.
|
||||
state.logic_op.enabled = regs.logic_op.enable != 0;
|
||||
|
||||
if (!state.logic_op.enabled)
|
||||
|
@ -1092,19 +1091,21 @@ void RasterizerOpenGL::SyncLogicOpState() {
|
|||
}
|
||||
|
||||
void RasterizerOpenGL::SyncScissorTest() {
|
||||
// TODO: what is the correct behavior here, a single scissor for all targets
|
||||
// or scissor disabled for the rest of the targets?
|
||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||
state.scissor.enabled = (regs.scissor_test.enable != 0);
|
||||
if (regs.scissor_test.enable == 0) {
|
||||
return;
|
||||
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumViewports; i++) {
|
||||
const auto& src = regs.scissor_test[i];
|
||||
auto& dst = state.viewports[i].scissor;
|
||||
dst.enabled = (src.enable != 0);
|
||||
if (dst.enabled == 0) {
|
||||
return;
|
||||
}
|
||||
const u32 width = src.max_x - src.min_x;
|
||||
const u32 height = src.max_y - src.min_y;
|
||||
dst.x = src.min_x;
|
||||
dst.y = src.min_y;
|
||||
dst.width = width;
|
||||
dst.height = height;
|
||||
}
|
||||
const u32 width = regs.scissor_test.max_x - regs.scissor_test.min_x;
|
||||
const u32 height = regs.scissor_test.max_y - regs.scissor_test.min_y;
|
||||
state.scissor.x = regs.scissor_test.min_x;
|
||||
state.scissor.y = regs.scissor_test.min_y;
|
||||
state.scissor.width = width;
|
||||
state.scissor.height = height;
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SyncTransformFeedback() {
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs);
|
||||
state.draw.shader_program = 0;
|
||||
state.draw.program_pipeline = pipeline.handle;
|
||||
state.geometry_shaders.enabled = (gs != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,6 +14,7 @@ OpenGLState OpenGLState::cur_state;
|
|||
bool OpenGLState::s_rgb_used;
|
||||
OpenGLState::OpenGLState() {
|
||||
// These all match default OpenGL values
|
||||
geometry_shaders.enabled = false;
|
||||
framebuffer_srgb.enabled = false;
|
||||
cull.enabled = false;
|
||||
cull.mode = GL_BACK;
|
||||
|
@ -50,12 +51,12 @@ OpenGLState::OpenGLState() {
|
|||
item.height = 0;
|
||||
item.depth_range_near = 0.0f;
|
||||
item.depth_range_far = 1.0f;
|
||||
item.scissor.enabled = false;
|
||||
item.scissor.x = 0;
|
||||
item.scissor.y = 0;
|
||||
item.scissor.width = 0;
|
||||
item.scissor.height = 0;
|
||||
}
|
||||
scissor.enabled = false;
|
||||
scissor.x = 0;
|
||||
scissor.y = 0;
|
||||
scissor.width = 0;
|
||||
scissor.height = 0;
|
||||
for (auto& item : blend) {
|
||||
item.enabled = true;
|
||||
item.rgb_equation = GL_FUNC_ADD;
|
||||
|
@ -136,7 +137,7 @@ void OpenGLState::ApplyCulling() const {
|
|||
}
|
||||
|
||||
void OpenGLState::ApplyColorMask() const {
|
||||
if (GLAD_GL_ARB_viewport_array) {
|
||||
if (GLAD_GL_ARB_viewport_array && independant_blend.enabled) {
|
||||
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
|
||||
const auto& updated = color_mask[i];
|
||||
const auto& current = cur_state.color_mask[i];
|
||||
|
@ -230,26 +231,10 @@ void OpenGLState::ApplyStencilTest() const {
|
|||
}
|
||||
}
|
||||
|
||||
void OpenGLState::ApplyScissor() const {
|
||||
const bool scissor_changed = scissor.enabled != cur_state.scissor.enabled;
|
||||
if (scissor_changed) {
|
||||
if (scissor.enabled) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
if (scissor.enabled &&
|
||||
(scissor_changed || scissor.x != cur_state.scissor.x || scissor.y != cur_state.scissor.y ||
|
||||
scissor.width != cur_state.scissor.width || scissor.height != cur_state.scissor.height)) {
|
||||
glScissor(scissor.x, scissor.y, scissor.width, scissor.height);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLState::ApplyViewport() const {
|
||||
if (GLAD_GL_ARB_viewport_array) {
|
||||
for (GLuint i = 0;
|
||||
i < static_cast<GLuint>(Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); i++) {
|
||||
if (GLAD_GL_ARB_viewport_array && geometry_shaders.enabled) {
|
||||
for (GLuint i = 0; i < static_cast<GLuint>(Tegra::Engines::Maxwell3D::Regs::NumViewports);
|
||||
i++) {
|
||||
const auto& current = cur_state.viewports[i];
|
||||
const auto& updated = viewports[i];
|
||||
if (updated.x != current.x || updated.y != current.y ||
|
||||
|
@ -260,6 +245,22 @@ void OpenGLState::ApplyViewport() const {
|
|||
updated.depth_range_far != current.depth_range_far) {
|
||||
glDepthRangeIndexed(i, updated.depth_range_near, updated.depth_range_far);
|
||||
}
|
||||
const bool scissor_changed = updated.scissor.enabled != current.scissor.enabled;
|
||||
if (scissor_changed) {
|
||||
if (updated.scissor.enabled) {
|
||||
glEnablei(GL_SCISSOR_TEST, i);
|
||||
} else {
|
||||
glDisablei(GL_SCISSOR_TEST, i);
|
||||
}
|
||||
}
|
||||
if (updated.scissor.enabled &&
|
||||
(scissor_changed || updated.scissor.x != current.scissor.x ||
|
||||
updated.scissor.y != current.scissor.y ||
|
||||
updated.scissor.width != current.scissor.width ||
|
||||
updated.scissor.height != current.scissor.height)) {
|
||||
glScissorIndexed(i, updated.scissor.x, updated.scissor.y, updated.scissor.width,
|
||||
updated.scissor.height);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto& current = cur_state.viewports[0];
|
||||
|
@ -273,6 +274,21 @@ void OpenGLState::ApplyViewport() const {
|
|||
updated.depth_range_far != current.depth_range_far) {
|
||||
glDepthRange(updated.depth_range_near, updated.depth_range_far);
|
||||
}
|
||||
const bool scissor_changed = updated.scissor.enabled != current.scissor.enabled;
|
||||
if (scissor_changed) {
|
||||
if (updated.scissor.enabled) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
if (updated.scissor.enabled && (scissor_changed || updated.scissor.x != current.scissor.x ||
|
||||
updated.scissor.y != current.scissor.y ||
|
||||
updated.scissor.width != current.scissor.width ||
|
||||
updated.scissor.height != current.scissor.height)) {
|
||||
glScissor(updated.scissor.x, updated.scissor.y, updated.scissor.width,
|
||||
updated.scissor.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,7 +499,6 @@ void OpenGLState::Apply() const {
|
|||
}
|
||||
ApplyColorMask();
|
||||
ApplyViewport();
|
||||
ApplyScissor();
|
||||
ApplyStencilTest();
|
||||
ApplySRgb();
|
||||
ApplyCulling();
|
||||
|
|
|
@ -39,6 +39,10 @@ public:
|
|||
bool enabled; // GL_FRAMEBUFFER_SRGB
|
||||
} framebuffer_srgb;
|
||||
|
||||
struct {
|
||||
bool enabled; // viewports arrays are only supported when geometry shaders are enabled.
|
||||
} geometry_shaders;
|
||||
|
||||
struct {
|
||||
bool enabled; // GL_CULL_FACE
|
||||
GLenum mode; // GL_CULL_FACE_MODE
|
||||
|
@ -150,16 +154,15 @@ public:
|
|||
GLfloat height;
|
||||
GLfloat depth_range_near; // GL_DEPTH_RANGE
|
||||
GLfloat depth_range_far; // GL_DEPTH_RANGE
|
||||
struct {
|
||||
bool enabled; // GL_SCISSOR_TEST
|
||||
GLint x;
|
||||
GLint y;
|
||||
GLsizei width;
|
||||
GLsizei height;
|
||||
} scissor;
|
||||
};
|
||||
std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> viewports;
|
||||
|
||||
struct {
|
||||
bool enabled; // GL_SCISSOR_TEST
|
||||
GLint x;
|
||||
GLint y;
|
||||
GLsizei width;
|
||||
GLsizei height;
|
||||
} scissor;
|
||||
std::array<viewport, Tegra::Engines::Maxwell3D::Regs::NumViewports> viewports;
|
||||
|
||||
struct {
|
||||
float size; // GL_POINT_SIZE
|
||||
|
@ -214,7 +217,6 @@ private:
|
|||
void ApplyLogicOp() const;
|
||||
void ApplyTextures() const;
|
||||
void ApplySamplers() const;
|
||||
void ApplyScissor() const;
|
||||
};
|
||||
|
||||
} // namespace OpenGL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue