Merge pull request #1660 from Tinob/master
Map more missing opengl states
This commit is contained in:
commit
2c6efda235
|
@ -53,6 +53,19 @@ void Maxwell3D::InitializeRegisterDefaults() {
|
||||||
regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One;
|
regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One;
|
||||||
regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero;
|
regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero;
|
||||||
}
|
}
|
||||||
|
regs.stencil_front_op_fail = Regs::StencilOp::Keep;
|
||||||
|
regs.stencil_front_op_zfail = Regs::StencilOp::Keep;
|
||||||
|
regs.stencil_front_op_zpass = Regs::StencilOp::Keep;
|
||||||
|
regs.stencil_front_func_func = Regs::ComparisonOp::Always;
|
||||||
|
regs.stencil_front_func_mask = 0xFFFFFFFF;
|
||||||
|
regs.stencil_front_mask = 0xFFFFFFFF;
|
||||||
|
regs.stencil_two_side_enable = 1;
|
||||||
|
regs.stencil_back_op_fail = Regs::StencilOp::Keep;
|
||||||
|
regs.stencil_back_op_zfail = Regs::StencilOp::Keep;
|
||||||
|
regs.stencil_back_op_zpass = Regs::StencilOp::Keep;
|
||||||
|
regs.stencil_back_func_func = Regs::ComparisonOp::Always;
|
||||||
|
regs.stencil_back_func_mask = 0xFFFFFFFF;
|
||||||
|
regs.stencil_back_mask = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
|
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
|
||||||
|
|
|
@ -345,6 +345,14 @@ public:
|
||||||
Invert = 6,
|
Invert = 6,
|
||||||
IncrWrap = 7,
|
IncrWrap = 7,
|
||||||
DecrWrap = 8,
|
DecrWrap = 8,
|
||||||
|
KeepOGL = 0x1E00,
|
||||||
|
ZeroOGL = 0,
|
||||||
|
ReplaceOGL = 0x1E01,
|
||||||
|
IncrOGL = 0x1E02,
|
||||||
|
DecrOGL = 0x1E03,
|
||||||
|
InvertOGL = 0x150A,
|
||||||
|
IncrWrapOGL = 0x8507,
|
||||||
|
DecrWrapOGL = 0x8508,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class MemoryLayout : u32 {
|
enum class MemoryLayout : u32 {
|
||||||
|
|
|
@ -140,7 +140,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
|
||||||
if (is_cache_miss) {
|
if (is_cache_miss) {
|
||||||
VAO.Create();
|
VAO.Create();
|
||||||
state.draw.vertex_array = VAO.handle;
|
state.draw.vertex_array = VAO.handle;
|
||||||
state.Apply();
|
state.ApplyVertexBufferState();
|
||||||
|
|
||||||
// The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work
|
// The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work
|
||||||
// around.
|
// around.
|
||||||
|
@ -182,7 +182,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.draw.vertex_array = VAO.handle;
|
state.draw.vertex_array = VAO.handle;
|
||||||
state.Apply();
|
state.ApplyVertexBufferState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupVertexBuffer() {
|
void RasterizerOpenGL::SetupVertexBuffer() {
|
||||||
|
@ -342,8 +342,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.Apply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
|
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
|
||||||
|
@ -412,8 +410,8 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
|
||||||
cached_pages.add({pages_interval, delta});
|
cached_pages.add({pages_interval, delta});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb,
|
void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool using_color_fb,
|
||||||
bool preserve_contents,
|
bool using_depth_fb, bool preserve_contents,
|
||||||
std::optional<std::size_t> single_color_target) {
|
std::optional<std::size_t> single_color_target) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_Framebuffer);
|
MICROPROFILE_SCOPE(OpenGL_Framebuffer);
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
@ -429,9 +427,9 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
|
||||||
ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented");
|
ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented");
|
||||||
|
|
||||||
// Bind the framebuffer surfaces
|
// Bind the framebuffer surfaces
|
||||||
state.draw.draw_framebuffer = framebuffer.handle;
|
current_state.draw.draw_framebuffer = framebuffer.handle;
|
||||||
state.Apply();
|
current_state.ApplyFramebufferState();
|
||||||
state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
|
current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
|
||||||
|
|
||||||
if (using_color_fb) {
|
if (using_color_fb) {
|
||||||
if (single_color_target) {
|
if (single_color_target) {
|
||||||
|
@ -509,10 +507,7 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
SyncViewport(current_state);
|
||||||
SyncViewport();
|
|
||||||
|
|
||||||
state.Apply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::Clear() {
|
void RasterizerOpenGL::Clear() {
|
||||||
|
@ -525,22 +520,23 @@ void RasterizerOpenGL::Clear() {
|
||||||
bool use_stencil{};
|
bool use_stencil{};
|
||||||
|
|
||||||
OpenGLState clear_state;
|
OpenGLState clear_state;
|
||||||
clear_state.draw.draw_framebuffer = framebuffer.handle;
|
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
||||||
|
regs.clear_buffers.A) {
|
||||||
|
use_color = true;
|
||||||
|
}
|
||||||
|
if (use_color) {
|
||||||
clear_state.color_mask[0].red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].red_enabled = regs.clear_buffers.R ? GL_TRUE : GL_FALSE;
|
||||||
clear_state.color_mask[0].green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].green_enabled = regs.clear_buffers.G ? GL_TRUE : GL_FALSE;
|
||||||
clear_state.color_mask[0].blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
|
||||||
clear_state.color_mask[0].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
|
clear_state.color_mask[0].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
|
||||||
|
|
||||||
if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
|
|
||||||
regs.clear_buffers.A) {
|
|
||||||
use_color = true;
|
|
||||||
}
|
}
|
||||||
if (regs.clear_buffers.Z) {
|
if (regs.clear_buffers.Z) {
|
||||||
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
|
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
|
||||||
use_depth = true;
|
use_depth = true;
|
||||||
|
|
||||||
// Always enable the depth write when clearing the depth buffer. The depth write mask is
|
// Always enable the depth write when clearing the depth buffer. The depth write mask is
|
||||||
// ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true.
|
// ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to
|
||||||
|
// true.
|
||||||
clear_state.depth.test_enabled = true;
|
clear_state.depth.test_enabled = true;
|
||||||
clear_state.depth.test_func = GL_ALWAYS;
|
clear_state.depth.test_func = GL_ALWAYS;
|
||||||
}
|
}
|
||||||
|
@ -557,11 +553,8 @@ void RasterizerOpenGL::Clear() {
|
||||||
|
|
||||||
ScopeAcquireGLContext acquire_context{emu_window};
|
ScopeAcquireGLContext acquire_context{emu_window};
|
||||||
|
|
||||||
ConfigureFramebuffers(use_color, use_depth || use_stencil, false,
|
ConfigureFramebuffers(clear_state, use_color, use_depth || use_stencil, false,
|
||||||
regs.clear_buffers.RT.Value());
|
regs.clear_buffers.RT.Value());
|
||||||
// Copy the sRGB setting to the clear state to avoid problem with
|
|
||||||
// specific driver implementations
|
|
||||||
clear_state.framebuffer_srgb.enabled = state.framebuffer_srgb.enabled;
|
|
||||||
clear_state.Apply();
|
clear_state.Apply();
|
||||||
|
|
||||||
if (use_color) {
|
if (use_color) {
|
||||||
|
@ -587,7 +580,7 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
|
|
||||||
ScopeAcquireGLContext acquire_context{emu_window};
|
ScopeAcquireGLContext acquire_context{emu_window};
|
||||||
|
|
||||||
ConfigureFramebuffers();
|
ConfigureFramebuffers(state);
|
||||||
SyncColorMask();
|
SyncColorMask();
|
||||||
SyncDepthTestState();
|
SyncDepthTestState();
|
||||||
SyncStencilTestState();
|
SyncStencilTestState();
|
||||||
|
@ -608,7 +601,7 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
|
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
|
||||||
|
|
||||||
state.draw.vertex_buffer = buffer_cache.GetHandle();
|
state.draw.vertex_buffer = buffer_cache.GetHandle();
|
||||||
state.Apply();
|
state.ApplyVertexBufferState();
|
||||||
|
|
||||||
std::size_t buffer_size = CalculateVertexArraysSize();
|
std::size_t buffer_size = CalculateVertexArraysSize();
|
||||||
|
|
||||||
|
@ -740,9 +733,9 @@ void RasterizerOpenGL::SamplerInfo::Create() {
|
||||||
glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
|
glSamplerParameteri(sampler.handle, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntry& config) {
|
void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::FullTextureInfo& info) {
|
||||||
const GLuint s = sampler.handle;
|
const GLuint s = sampler.handle;
|
||||||
|
const Tegra::Texture::TSCEntry& config = info.tsc;
|
||||||
if (mag_filter != config.mag_filter) {
|
if (mag_filter != config.mag_filter) {
|
||||||
mag_filter = config.mag_filter;
|
mag_filter = config.mag_filter;
|
||||||
glSamplerParameteri(
|
glSamplerParameteri(
|
||||||
|
@ -793,6 +786,22 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
|
||||||
glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data());
|
glSamplerParameterfv(s, GL_TEXTURE_BORDER_COLOR, border_color.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (info.tic.use_header_opt_control == 0) {
|
||||||
|
if (GLAD_GL_ARB_texture_filter_anisotropic) {
|
||||||
|
glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY,
|
||||||
|
static_cast<float>(1 << info.tic.max_anisotropy.Value()));
|
||||||
|
} else if (GLAD_GL_EXT_texture_filter_anisotropic) {
|
||||||
|
glSamplerParameterf(s, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||||
|
static_cast<float>(1 << info.tic.max_anisotropy.Value()));
|
||||||
|
}
|
||||||
|
glSamplerParameterf(s, GL_TEXTURE_MIN_LOD,
|
||||||
|
static_cast<float>(info.tic.res_min_mip_level.Value()));
|
||||||
|
glSamplerParameterf(s, GL_TEXTURE_MAX_LOD,
|
||||||
|
static_cast<float>(info.tic.res_max_mip_level.Value() == 0
|
||||||
|
? 16
|
||||||
|
: info.tic.res_max_mip_level.Value()));
|
||||||
|
glSamplerParameterf(s, GL_TEXTURE_LOD_BIAS, info.tic.mip_lod_bias.Value() / 256.f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader,
|
u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader,
|
||||||
|
@ -890,7 +899,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
|
texture_samplers[current_bindpoint].SyncWithConfig(texture);
|
||||||
Surface surface = res_cache.GetTextureSurface(texture, entry);
|
Surface surface = res_cache.GetTextureSurface(texture, entry);
|
||||||
if (surface != nullptr) {
|
if (surface != nullptr) {
|
||||||
state.texture_units[current_bindpoint].texture = surface->Texture().handle;
|
state.texture_units[current_bindpoint].texture = surface->Texture().handle;
|
||||||
|
@ -912,11 +921,11 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
|
||||||
return current_unit + static_cast<u32>(entries.size());
|
return current_unit + static_cast<u32>(entries.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncViewport() {
|
void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
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::NumRenderTargets; i++) {
|
||||||
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
|
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[i].GetRect()};
|
||||||
auto& viewport = state.viewports[i];
|
auto& viewport = current_state.viewports[i];
|
||||||
viewport.x = viewport_rect.left;
|
viewport.x = viewport_rect.left;
|
||||||
viewport.y = viewport_rect.bottom;
|
viewport.y = viewport_rect.bottom;
|
||||||
viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth());
|
viewport.width = static_cast<GLfloat>(viewport_rect.GetWidth());
|
||||||
|
@ -985,9 +994,6 @@ void RasterizerOpenGL::SyncStencilTestState() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bunnei): Verify behavior when this is not set
|
|
||||||
ASSERT(regs.stencil_two_side_enable);
|
|
||||||
|
|
||||||
state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func);
|
state.stencil.front.test_func = MaxwellToGL::ComparisonOp(regs.stencil_front_func_func);
|
||||||
state.stencil.front.test_ref = regs.stencil_front_func_ref;
|
state.stencil.front.test_ref = regs.stencil_front_func_ref;
|
||||||
state.stencil.front.test_mask = regs.stencil_front_func_mask;
|
state.stencil.front.test_mask = regs.stencil_front_func_mask;
|
||||||
|
@ -995,7 +1001,7 @@ void RasterizerOpenGL::SyncStencilTestState() {
|
||||||
state.stencil.front.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_zfail);
|
state.stencil.front.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_front_op_zfail);
|
||||||
state.stencil.front.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_front_op_zpass);
|
state.stencil.front.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_front_op_zpass);
|
||||||
state.stencil.front.write_mask = regs.stencil_front_mask;
|
state.stencil.front.write_mask = regs.stencil_front_mask;
|
||||||
|
if (regs.stencil_two_side_enable) {
|
||||||
state.stencil.back.test_func = MaxwellToGL::ComparisonOp(regs.stencil_back_func_func);
|
state.stencil.back.test_func = MaxwellToGL::ComparisonOp(regs.stencil_back_func_func);
|
||||||
state.stencil.back.test_ref = regs.stencil_back_func_ref;
|
state.stencil.back.test_ref = regs.stencil_back_func_ref;
|
||||||
state.stencil.back.test_mask = regs.stencil_back_func_mask;
|
state.stencil.back.test_mask = regs.stencil_back_func_mask;
|
||||||
|
@ -1003,6 +1009,15 @@ void RasterizerOpenGL::SyncStencilTestState() {
|
||||||
state.stencil.back.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_zfail);
|
state.stencil.back.action_depth_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_zfail);
|
||||||
state.stencil.back.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_back_op_zpass);
|
state.stencil.back.action_depth_pass = MaxwellToGL::StencilOp(regs.stencil_back_op_zpass);
|
||||||
state.stencil.back.write_mask = regs.stencil_back_mask;
|
state.stencil.back.write_mask = regs.stencil_back_mask;
|
||||||
|
} else {
|
||||||
|
state.stencil.back.test_func = GL_ALWAYS;
|
||||||
|
state.stencil.back.test_ref = 0;
|
||||||
|
state.stencil.back.test_mask = 0xFFFFFFFF;
|
||||||
|
state.stencil.back.write_mask = 0xFFFFFFFF;
|
||||||
|
state.stencil.back.action_stencil_fail = GL_KEEP;
|
||||||
|
state.stencil.back.action_depth_fail = GL_KEEP;
|
||||||
|
state.stencil.back.action_depth_pass = GL_KEEP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SyncColorMask() {
|
void RasterizerOpenGL::SyncColorMask() {
|
||||||
|
@ -1114,9 +1129,8 @@ void RasterizerOpenGL::CheckAlphaTests() {
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
if (regs.alpha_test_enabled != 0 && regs.rt_control.count > 1) {
|
if (regs.alpha_test_enabled != 0 && regs.rt_control.count > 1) {
|
||||||
LOG_CRITICAL(
|
LOG_CRITICAL(Render_OpenGL, "Alpha Testing is enabled with Multiple Render Targets, "
|
||||||
Render_OpenGL,
|
"this behavior is undefined.");
|
||||||
"Alpha Testing is enabled with Multiple Render Targets, this behavior is undefined.");
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ private:
|
||||||
/// SamplerInfo struct.
|
/// SamplerInfo struct.
|
||||||
void Create();
|
void Create();
|
||||||
/// Syncs the sampler object with the config, updating any necessary state.
|
/// Syncs the sampler object with the config, updating any necessary state.
|
||||||
void SyncWithConfig(const Tegra::Texture::TSCEntry& config);
|
void SyncWithConfig(const Tegra::Texture::FullTextureInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tegra::Texture::TextureFilter mag_filter;
|
Tegra::Texture::TextureFilter mag_filter;
|
||||||
|
@ -109,8 +109,8 @@ private:
|
||||||
* @param preserve_contents If true, tries to preserve data from a previously used framebuffer.
|
* @param preserve_contents If true, tries to preserve data from a previously used framebuffer.
|
||||||
* @param single_color_target Specifies if a single color buffer target should be used.
|
* @param single_color_target Specifies if a single color buffer target should be used.
|
||||||
*/
|
*/
|
||||||
void ConfigureFramebuffers(bool use_color_fb = true, bool using_depth_fb = true,
|
void ConfigureFramebuffers(OpenGLState& current_state, bool use_color_fb = true,
|
||||||
bool preserve_contents = true,
|
bool using_depth_fb = true, bool preserve_contents = true,
|
||||||
std::optional<std::size_t> single_color_target = {});
|
std::optional<std::size_t> single_color_target = {});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -134,7 +134,7 @@ private:
|
||||||
GLenum primitive_mode, u32 current_unit);
|
GLenum primitive_mode, u32 current_unit);
|
||||||
|
|
||||||
/// Syncs the viewport and depth range to match the guest state
|
/// Syncs the viewport and depth range to match the guest state
|
||||||
void SyncViewport();
|
void SyncViewport(OpenGLState& current_state);
|
||||||
|
|
||||||
/// Syncs the clip enabled status to match the guest state
|
/// Syncs the clip enabled status to match the guest state
|
||||||
void SyncClipEnabled();
|
void SyncClipEnabled();
|
||||||
|
|
|
@ -580,7 +580,7 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
|
||||||
state.draw.draw_framebuffer = draw_fb_handle;
|
state.draw.draw_framebuffer = draw_fb_handle;
|
||||||
// Set sRGB enabled if the destination surfaces need it
|
// Set sRGB enabled if the destination surfaces need it
|
||||||
state.framebuffer_srgb.enabled = dst_params.srgb_conversion;
|
state.framebuffer_srgb.enabled = dst_params.srgb_conversion;
|
||||||
state.Apply();
|
state.ApplyFramebufferState();
|
||||||
|
|
||||||
u32 buffers{};
|
u32 buffers{};
|
||||||
|
|
||||||
|
|
|
@ -427,7 +427,7 @@ void OpenGLState::ApplySamplers() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLState::Apply() const {
|
void OpenGLState::ApplyFramebufferState() const {
|
||||||
// Framebuffer
|
// Framebuffer
|
||||||
if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
|
if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
|
||||||
|
@ -435,7 +435,9 @@ void OpenGLState::Apply() const {
|
||||||
if (draw.draw_framebuffer != cur_state.draw.draw_framebuffer) {
|
if (draw.draw_framebuffer != cur_state.draw.draw_framebuffer) {
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.draw_framebuffer);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.draw_framebuffer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLState::ApplyVertexBufferState() const {
|
||||||
// Vertex array
|
// Vertex array
|
||||||
if (draw.vertex_array != cur_state.draw.vertex_array) {
|
if (draw.vertex_array != cur_state.draw.vertex_array) {
|
||||||
glBindVertexArray(draw.vertex_array);
|
glBindVertexArray(draw.vertex_array);
|
||||||
|
@ -445,7 +447,11 @@ void OpenGLState::Apply() const {
|
||||||
if (draw.vertex_buffer != cur_state.draw.vertex_buffer) {
|
if (draw.vertex_buffer != cur_state.draw.vertex_buffer) {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLState::Apply() const {
|
||||||
|
ApplyFramebufferState();
|
||||||
|
ApplyVertexBufferState();
|
||||||
// Uniform buffer
|
// Uniform buffer
|
||||||
if (draw.uniform_buffer != cur_state.draw.uniform_buffer) {
|
if (draw.uniform_buffer != cur_state.draw.uniform_buffer) {
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer);
|
glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer);
|
||||||
|
|
|
@ -181,6 +181,10 @@ public:
|
||||||
}
|
}
|
||||||
/// Apply this state as the current OpenGL state
|
/// Apply this state as the current OpenGL state
|
||||||
void Apply() const;
|
void Apply() const;
|
||||||
|
/// Apply only the state afecting the framebuffer
|
||||||
|
void ApplyFramebufferState() const;
|
||||||
|
/// Apply only the state afecting the vertex buffer
|
||||||
|
void ApplyVertexBufferState() const;
|
||||||
/// Set the initial OpenGL state
|
/// Set the initial OpenGL state
|
||||||
static void ApplyDefaultState();
|
static void ApplyDefaultState();
|
||||||
/// Resets any references to the given resource
|
/// Resets any references to the given resource
|
||||||
|
|
|
@ -159,10 +159,8 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}",
|
LOG_ERROR(Render_OpenGL, "Unimplemented texture filter mode={}", static_cast<u32>(filter_mode));
|
||||||
static_cast<u32>(filter_mode));
|
return GL_LINEAR;
|
||||||
UNREACHABLE();
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
|
inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
|
||||||
|
@ -183,9 +181,8 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
|
||||||
case Tegra::Texture::WrapMode::MirrorOnceClampToEdge:
|
case Tegra::Texture::WrapMode::MirrorOnceClampToEdge:
|
||||||
return GL_MIRROR_CLAMP_TO_EDGE;
|
return GL_MIRROR_CLAMP_TO_EDGE;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode));
|
LOG_ERROR(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode));
|
||||||
UNREACHABLE();
|
return GL_REPEAT;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
|
inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
|
||||||
|
@ -207,10 +204,9 @@ inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
|
||||||
case Tegra::Texture::DepthCompareFunc::Always:
|
case Tegra::Texture::DepthCompareFunc::Always:
|
||||||
return GL_ALWAYS;
|
return GL_ALWAYS;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture depth compare function ={}",
|
LOG_ERROR(Render_OpenGL, "Unimplemented texture depth compare function ={}",
|
||||||
static_cast<u32>(func));
|
static_cast<u32>(func));
|
||||||
UNREACHABLE();
|
return GL_GREATER;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
|
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
|
||||||
|
@ -226,9 +222,8 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
|
||||||
case Maxwell::Blend::Equation::Max:
|
case Maxwell::Blend::Equation::Max:
|
||||||
return GL_MAX;
|
return GL_MAX;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation));
|
LOG_ERROR(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation));
|
||||||
UNREACHABLE();
|
return GL_FUNC_ADD;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
||||||
|
@ -291,9 +286,8 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
||||||
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
|
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
|
||||||
return GL_ONE_MINUS_CONSTANT_ALPHA;
|
return GL_ONE_MINUS_CONSTANT_ALPHA;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
|
LOG_ERROR(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
|
||||||
UNREACHABLE();
|
return GL_ZERO;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
|
inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
|
||||||
|
@ -312,9 +306,8 @@ inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
|
||||||
case Tegra::Texture::SwizzleSource::OneFloat:
|
case Tegra::Texture::SwizzleSource::OneFloat:
|
||||||
return GL_ONE;
|
return GL_ONE;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source));
|
LOG_ERROR(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source));
|
||||||
UNREACHABLE();
|
return GL_ZERO;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
||||||
|
@ -344,33 +337,39 @@ inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
||||||
case Maxwell::ComparisonOp::AlwaysOld:
|
case Maxwell::ComparisonOp::AlwaysOld:
|
||||||
return GL_ALWAYS;
|
return GL_ALWAYS;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison));
|
LOG_ERROR(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison));
|
||||||
UNREACHABLE();
|
return GL_ALWAYS;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum StencilOp(Maxwell::StencilOp stencil) {
|
inline GLenum StencilOp(Maxwell::StencilOp stencil) {
|
||||||
switch (stencil) {
|
switch (stencil) {
|
||||||
case Maxwell::StencilOp::Keep:
|
case Maxwell::StencilOp::Keep:
|
||||||
|
case Maxwell::StencilOp::KeepOGL:
|
||||||
return GL_KEEP;
|
return GL_KEEP;
|
||||||
case Maxwell::StencilOp::Zero:
|
case Maxwell::StencilOp::Zero:
|
||||||
|
case Maxwell::StencilOp::ZeroOGL:
|
||||||
return GL_ZERO;
|
return GL_ZERO;
|
||||||
case Maxwell::StencilOp::Replace:
|
case Maxwell::StencilOp::Replace:
|
||||||
|
case Maxwell::StencilOp::ReplaceOGL:
|
||||||
return GL_REPLACE;
|
return GL_REPLACE;
|
||||||
case Maxwell::StencilOp::Incr:
|
case Maxwell::StencilOp::Incr:
|
||||||
|
case Maxwell::StencilOp::IncrOGL:
|
||||||
return GL_INCR;
|
return GL_INCR;
|
||||||
case Maxwell::StencilOp::Decr:
|
case Maxwell::StencilOp::Decr:
|
||||||
|
case Maxwell::StencilOp::DecrOGL:
|
||||||
return GL_DECR;
|
return GL_DECR;
|
||||||
case Maxwell::StencilOp::Invert:
|
case Maxwell::StencilOp::Invert:
|
||||||
|
case Maxwell::StencilOp::InvertOGL:
|
||||||
return GL_INVERT;
|
return GL_INVERT;
|
||||||
case Maxwell::StencilOp::IncrWrap:
|
case Maxwell::StencilOp::IncrWrap:
|
||||||
|
case Maxwell::StencilOp::IncrWrapOGL:
|
||||||
return GL_INCR_WRAP;
|
return GL_INCR_WRAP;
|
||||||
case Maxwell::StencilOp::DecrWrap:
|
case Maxwell::StencilOp::DecrWrap:
|
||||||
|
case Maxwell::StencilOp::DecrWrapOGL:
|
||||||
return GL_DECR_WRAP;
|
return GL_DECR_WRAP;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil));
|
LOG_ERROR(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil));
|
||||||
UNREACHABLE();
|
return GL_KEEP;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
|
inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
|
||||||
|
@ -380,9 +379,8 @@ inline GLenum FrontFace(Maxwell::Cull::FrontFace front_face) {
|
||||||
case Maxwell::Cull::FrontFace::CounterClockWise:
|
case Maxwell::Cull::FrontFace::CounterClockWise:
|
||||||
return GL_CCW;
|
return GL_CCW;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face));
|
LOG_ERROR(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face));
|
||||||
UNREACHABLE();
|
return GL_CCW;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) {
|
inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) {
|
||||||
|
@ -394,9 +392,8 @@ inline GLenum CullFace(Maxwell::Cull::CullFace cull_face) {
|
||||||
case Maxwell::Cull::CullFace::FrontAndBack:
|
case Maxwell::Cull::CullFace::FrontAndBack:
|
||||||
return GL_FRONT_AND_BACK;
|
return GL_FRONT_AND_BACK;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face));
|
LOG_ERROR(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face));
|
||||||
UNREACHABLE();
|
return GL_BACK;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum LogicOp(Maxwell::LogicOperation operation) {
|
inline GLenum LogicOp(Maxwell::LogicOperation operation) {
|
||||||
|
@ -434,9 +431,8 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) {
|
||||||
case Maxwell::LogicOperation::Set:
|
case Maxwell::LogicOperation::Set:
|
||||||
return GL_SET;
|
return GL_SET;
|
||||||
}
|
}
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation));
|
LOG_ERROR(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation));
|
||||||
UNREACHABLE();
|
return GL_COPY;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace MaxwellToGL
|
} // namespace MaxwellToGL
|
||||||
|
|
|
@ -168,20 +168,29 @@ struct TICEntry {
|
||||||
|
|
||||||
// High 16 bits of the pitch value
|
// High 16 bits of the pitch value
|
||||||
BitField<0, 16, u32> pitch_high;
|
BitField<0, 16, u32> pitch_high;
|
||||||
|
BitField<26, 1, u32> use_header_opt_control;
|
||||||
|
BitField<27, 1, u32> depth_texture;
|
||||||
BitField<28, 4, u32> max_mip_level;
|
BitField<28, 4, u32> max_mip_level;
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
BitField<0, 16, u32> width_minus_1;
|
BitField<0, 16, u32> width_minus_1;
|
||||||
BitField<22, 1, u32> srgb_conversion;
|
BitField<22, 1, u32> srgb_conversion;
|
||||||
BitField<23, 4, TextureType> texture_type;
|
BitField<23, 4, TextureType> texture_type;
|
||||||
|
BitField<29, 3, u32> border_size;
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
BitField<0, 16, u32> height_minus_1;
|
BitField<0, 16, u32> height_minus_1;
|
||||||
BitField<16, 15, u32> depth_minus_1;
|
BitField<16, 15, u32> depth_minus_1;
|
||||||
};
|
};
|
||||||
|
union {
|
||||||
|
BitField<6, 13, u32> mip_lod_bias;
|
||||||
|
BitField<27, 3, u32> max_anisotropy;
|
||||||
|
};
|
||||||
|
|
||||||
INSERT_PADDING_BYTES(8);
|
union {
|
||||||
|
BitField<0, 4, u32> res_min_mip_level;
|
||||||
|
BitField<4, 4, u32> res_max_mip_level;
|
||||||
|
};
|
||||||
|
|
||||||
GPUVAddr Address() const {
|
GPUVAddr Address() const {
|
||||||
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);
|
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);
|
||||||
|
|
Loading…
Reference in a new issue