Add support for viewport_transform_enabled

fix Clear viewport area by calculating overlapping area when viewport and scissor are enabled at the same time.
add warning messages for extension that are not required but are needed for a correct emulation.
This commit is contained in:
Rodolfo Bogado
2018-11-22 00:59:14 -03:00
parent 0749600ca8
commit 3ae614c493
4 changed files with 86 additions and 13 deletions

View File

@@ -728,7 +728,20 @@ public:
u32 vb_element_base;
INSERT_PADDING_WORDS(0x38);
INSERT_PADDING_WORDS(0x36);
union {
BitField<0, 1, u32> c0;
BitField<1, 1, u32> c1;
BitField<2, 1, u32> c2;
BitField<3, 1, u32> c3;
BitField<4, 1, u32> c4;
BitField<5, 1, u32> c5;
BitField<6, 1, u32> c6;
BitField<7, 1, u32> c7;
} clip_distance_enabled;
INSERT_PADDING_WORDS(0x1);
float point_size;
@@ -872,7 +885,13 @@ public:
Cull cull;
INSERT_PADDING_WORDS(0x6);
u32 pixel_center_integer;
INSERT_PADDING_WORDS(0x1);
u32 viewport_transform_enabled;
INSERT_PADDING_WORDS(0x3);
union {
BitField<0, 1, u32> depth_range_0_1;
@@ -1182,6 +1201,7 @@ ASSERT_REG_POSITION(stencil_front_mask, 0x4E7);
ASSERT_REG_POSITION(frag_color_clamp, 0x4EA);
ASSERT_REG_POSITION(screen_y_control, 0x4EB);
ASSERT_REG_POSITION(vb_element_base, 0x50D);
ASSERT_REG_POSITION(clip_distance_enabled, 0x544);
ASSERT_REG_POSITION(point_size, 0x546);
ASSERT_REG_POSITION(zeta_enable, 0x54E);
ASSERT_REG_POSITION(multisample_control, 0x54F);
@@ -1200,6 +1220,8 @@ ASSERT_REG_POSITION(primitive_restart, 0x591);
ASSERT_REG_POSITION(index_array, 0x5F2);
ASSERT_REG_POSITION(instanced_arrays, 0x620);
ASSERT_REG_POSITION(cull, 0x646);
ASSERT_REG_POSITION(pixel_center_integer, 0x649);
ASSERT_REG_POSITION(viewport_transform_enabled, 0x64B);
ASSERT_REG_POSITION(clip_distance_mode, 0x650);
ASSERT_REG_POSITION(logic_op, 0x671);
ASSERT_REG_POSITION(clear_buffers, 0x674);

View File

@@ -118,10 +118,43 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniform_buffer_alignment);
LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
CheckExtensions();
}
RasterizerOpenGL::~RasterizerOpenGL() {}
void RasterizerOpenGL::CheckExtensions() {
if (!GLAD_GL_ARB_texture_filter_anisotropic && !GLAD_GL_EXT_texture_filter_anisotropic) {
LOG_WARNING(
Render_OpenGL,
"Anisotropic filter is not supported! this can cause graphical issues in some games.");
}
if (!GLAD_GL_ARB_viewport_array) {
LOG_WARNING(Render_OpenGL, "Viewport arrays are not supported! this can potyentially cause "
"issues in games that use geometry shaders.");
}
if (!GLAD_GL_ARB_color_buffer_float) {
LOG_WARNING(
Render_OpenGL,
"Color clamp control is not supported! this can cause graphical issues in some games.");
}
if (!GLAD_GL_ARB_buffer_storage) {
LOG_WARNING(
Render_OpenGL,
"Buffer storage control is not supported! this can cause performance degradation.");
}
if (!GLAD_GL_AMD_depth_clamp_separate) {
if (!GLAD_GL_ARB_depth_clamp) {
LOG_WARNING(
Render_OpenGL,
"Depth Clamp is not supported! this can cause graphical issues in some games.");
} else {
LOG_WARNING(Render_OpenGL, "Separate Depth Clamp is not supported! this can cause "
"graphical issues in some games.");
}
}
}
void RasterizerOpenGL::SetupVertexFormat() {
auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
const auto& regs = gpu.regs;
@@ -976,17 +1009,25 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
for (std::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 = viewport_rect.GetWidth();
viewport.height = viewport_rect.GetHeight();
const auto& src = regs.viewports[i];
if (regs.viewport_transform_enabled) {
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
viewport.x = viewport_rect.left;
viewport.y = viewport_rect.bottom;
viewport.width = viewport_rect.GetWidth();
viewport.height = viewport_rect.GetHeight();
} else {
viewport.x = src.x;
viewport.y = src.y;
viewport.width = src.width;
viewport.height = src.height;
}
viewport.depth_range_far = regs.viewports[i].depth_range_far;
viewport.depth_range_near = regs.viewports[i].depth_range_near;
}
state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0;
state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0;
current_state.depth_clamp.far_plane = regs.view_volume_clip_control.depth_clamp_far != 0;
current_state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0;
}
void RasterizerOpenGL::SyncClipEnabled() {

View File

@@ -186,6 +186,10 @@ private:
/// Check asserts for alpha testing.
void CheckAlphaTests();
/// check for extension that are not strictly required
/// but are needed for correct emulation
void CheckExtensions();
bool has_ARB_direct_state_access = false;
bool has_ARB_multi_bind = false;
bool has_ARB_separate_shader_objects = false;

View File

@@ -239,10 +239,16 @@ void OpenGLState::ApplyStencilTest() const {
void OpenGLState::TranslateViewportToScissor() {
auto& current = this->viewports[0];
if (current.scissor.enabled) {
current.scissor.x = std::max(current.x, current.scissor.x);
current.scissor.y = std::max(current.y, current.scissor.y);
current.scissor.width = std::min(current.width, current.scissor.width);
current.scissor.height = std::min(current.height, current.scissor.height);
GLint left = std::max(current.x, current.scissor.x);
GLint right =
std::max(current.x + current.width, current.scissor.x + current.scissor.width);
GLint bottom = std::max(current.y, current.scissor.y);
GLint top =
std::max(current.y + current.height, current.scissor.y + current.scissor.height);
current.scissor.x = std::max(left, 0);
current.scissor.y = std::max(bottom, 0);
current.scissor.width = std::max(right - left, 0);
current.scissor.height = std::max(top - bottom, 0);
} else {
current.scissor.enabled = true;
current.scissor.x = current.x;