summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp19
-rw-r--r--src/video_core/engines/maxwell_3d.h8
-rw-r--r--src/video_core/renderer_base.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp108
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp36
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_state.h4
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h66
-rw-r--r--src/video_core/surface.cpp4
-rw-r--r--src/video_core/surface.h148
-rw-r--r--src/video_core/textures/decoders.cpp4
-rw-r--r--src/video_core/textures/texture.h13
13 files changed, 251 insertions, 176 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 5ae836aca..6de07ea56 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -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_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) {
@@ -108,10 +121,8 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr);
}
- u32 old = regs.reg_array[method];
- regs.reg_array[method] = value;
-
- if (value != old) {
+ if (regs.reg_array[method] != value) {
+ regs.reg_array[method] = value;
if (method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) &&
method < MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) {
dirty_flags.vertex_attrib_format = true;
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 557795d0f..91ca57883 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -345,6 +345,14 @@ public:
Invert = 6,
IncrWrap = 7,
DecrWrap = 8,
+ KeepOGL = 0x1E00,
+ ZeroOGL = 0,
+ ReplaceOGL = 0x1E01,
+ IncrOGL = 0x1E02,
+ DecrOGL = 0x1E03,
+ InvertOGL = 0x150A,
+ IncrWrapOGL = 0x8507,
+ DecrWrapOGL = 0x8508,
};
enum class MemoryLayout : u32 {
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index 0df3725c2..1482cdb40 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -5,7 +5,6 @@
#include "core/frontend/emu_window.h"
#include "core/settings.h"
#include "video_core/renderer_base.h"
-#include "video_core/renderer_opengl/gl_rasterizer.h"
namespace VideoCore {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index a404764f5..54cc47a9b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -140,7 +140,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
if (is_cache_miss) {
VAO.Create();
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
// around.
@@ -182,7 +182,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
}
}
state.draw.vertex_array = VAO.handle;
- state.Apply();
+ state.ApplyVertexBufferState();
}
void RasterizerOpenGL::SetupVertexBuffer() {
@@ -342,8 +342,6 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
index++;
}
}
-
- state.Apply();
}
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});
}
-void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb,
- bool preserve_contents,
+void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool using_color_fb,
+ bool using_depth_fb, bool preserve_contents,
std::optional<std::size_t> single_color_target) {
MICROPROFILE_SCOPE(OpenGL_Framebuffer);
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");
// Bind the framebuffer surfaces
- state.draw.draw_framebuffer = framebuffer.handle;
- state.Apply();
- state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
+ current_state.draw.draw_framebuffer = framebuffer.handle;
+ current_state.ApplyFramebufferState();
+ current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
if (using_color_fb) {
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,
0);
}
-
- SyncViewport();
-
- state.Apply();
+ SyncViewport(current_state);
}
void RasterizerOpenGL::Clear() {
@@ -525,22 +520,23 @@ void RasterizerOpenGL::Clear() {
bool use_stencil{};
OpenGLState clear_state;
- clear_state.draw.draw_framebuffer = framebuffer.handle;
- 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].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;
-
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].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].alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
+ }
if (regs.clear_buffers.Z) {
ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
use_depth = true;
// 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_func = GL_ALWAYS;
}
@@ -557,11 +553,8 @@ void RasterizerOpenGL::Clear() {
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());
- // 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();
if (use_color) {
@@ -587,7 +580,7 @@ void RasterizerOpenGL::DrawArrays() {
ScopeAcquireGLContext acquire_context{emu_window};
- ConfigureFramebuffers();
+ ConfigureFramebuffers(state);
SyncColorMask();
SyncDepthTestState();
SyncStencilTestState();
@@ -608,7 +601,7 @@ void RasterizerOpenGL::DrawArrays() {
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
state.draw.vertex_buffer = buffer_cache.GetHandle();
- state.Apply();
+ state.ApplyVertexBufferState();
std::size_t buffer_size = CalculateVertexArraysSize();
@@ -740,9 +733,9 @@ void RasterizerOpenGL::SamplerInfo::Create() {
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 Tegra::Texture::TSCEntry& config = info.tsc;
if (mag_filter != config.mag_filter) {
mag_filter = config.mag_filter;
glSamplerParameteri(
@@ -793,6 +786,22 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
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,
@@ -890,7 +899,7 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
continue;
}
- texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
+ texture_samplers[current_bindpoint].SyncWithConfig(texture);
Surface surface = res_cache.GetTextureSurface(texture, entry);
if (surface != nullptr) {
state.texture_units[current_bindpoint].texture = surface->Texture().handle;
@@ -912,15 +921,15 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
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;
for (size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; i++) {
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.y = viewport_rect.bottom;
- viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
- viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
+ 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;
}
@@ -985,9 +994,6 @@ void RasterizerOpenGL::SyncStencilTestState() {
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_ref = regs.stencil_front_func_ref;
state.stencil.front.test_mask = regs.stencil_front_func_mask;
@@ -995,14 +1001,23 @@ void RasterizerOpenGL::SyncStencilTestState() {
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.write_mask = regs.stencil_front_mask;
-
- 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_mask = regs.stencil_back_func_mask;
- state.stencil.back.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_fail);
- 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.write_mask = regs.stencil_back_mask;
+ if (regs.stencil_two_side_enable) {
+ 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_mask = regs.stencil_back_func_mask;
+ state.stencil.back.action_stencil_fail = MaxwellToGL::StencilOp(regs.stencil_back_op_fail);
+ 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.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() {
@@ -1114,9 +1129,8 @@ void RasterizerOpenGL::CheckAlphaTests() {
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
if (regs.alpha_test_enabled != 0 && regs.rt_control.count > 1) {
- LOG_CRITICAL(
- Render_OpenGL,
- "Alpha Testing is enabled with Multiple Render Targets, this behavior is undefined.");
+ LOG_CRITICAL(Render_OpenGL, "Alpha Testing is enabled with Multiple Render Targets, "
+ "this behavior is undefined.");
UNREACHABLE();
}
}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 5eee5f088..8ef0f6c12 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -88,7 +88,7 @@ private:
/// SamplerInfo struct.
void Create();
/// 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:
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 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,
- bool preserve_contents = true,
+ void ConfigureFramebuffers(OpenGLState& current_state, bool use_color_fb = true,
+ bool using_depth_fb = true, bool preserve_contents = true,
std::optional<std::size_t> single_color_target = {});
/*
@@ -134,7 +134,7 @@ private:
GLenum primitive_mode, u32 current_unit);
/// 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
void SyncClipEnabled();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index c8864cce8..26711e6f7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -314,6 +314,8 @@ static constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5
{GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X5_SRGB
+ {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8
+ {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_10X8_SRGB
// Depth formats
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
@@ -456,6 +458,8 @@ static constexpr GLConversionArray morton_to_gl_fns = {
MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
MortonCopy<true, PixelFormat::ASTC_2D_5X5>,
MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
+ MortonCopy<true, PixelFormat::ASTC_2D_10X8>,
+ MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>,
MortonCopy<true, PixelFormat::Z32F>,
MortonCopy<true, PixelFormat::Z16>,
MortonCopy<true, PixelFormat::Z24S8>,
@@ -526,6 +530,8 @@ static constexpr GLConversionArray gl_to_morton_fns = {
nullptr,
nullptr,
nullptr,
+ nullptr,
+ nullptr,
MortonCopy<false, PixelFormat::Z32F>,
MortonCopy<false, PixelFormat::Z16>,
MortonCopy<false, PixelFormat::Z24S8>,
@@ -580,7 +586,7 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
state.draw.draw_framebuffer = draw_fb_handle;
// Set sRGB enabled if the destination surfaces need it
state.framebuffer_srgb.enabled = dst_params.srgb_conversion;
- state.Apply();
+ state.ApplyFramebufferState();
u32 buffers{};
@@ -709,18 +715,18 @@ static void FastCopySurface(const Surface& src_surface, const Surface& dst_surfa
MICROPROFILE_DEFINE(OpenGL_CopySurface, "OpenGL", "CopySurface", MP_RGB(128, 192, 64));
static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
- GLuint copy_pbo_handle, GLenum src_attachment = 0,
- GLenum dst_attachment = 0, std::size_t cubemap_face = 0) {
+ const GLuint copy_pbo_handle, const GLenum src_attachment = 0,
+ const GLenum dst_attachment = 0, const std::size_t cubemap_face = 0) {
MICROPROFILE_SCOPE(OpenGL_CopySurface);
ASSERT_MSG(dst_attachment == 0, "Unimplemented");
const auto& src_params{src_surface->GetSurfaceParams()};
const auto& dst_params{dst_surface->GetSurfaceParams()};
- auto source_format = GetFormatTuple(src_params.pixel_format, src_params.component_type);
- auto dest_format = GetFormatTuple(dst_params.pixel_format, dst_params.component_type);
+ const auto source_format = GetFormatTuple(src_params.pixel_format, src_params.component_type);
+ const auto dest_format = GetFormatTuple(dst_params.pixel_format, dst_params.component_type);
- std::size_t buffer_size = std::max(src_params.size_in_bytes, dst_params.size_in_bytes);
+ const std::size_t buffer_size = std::max(src_params.size_in_bytes, dst_params.size_in_bytes);
glBindBuffer(GL_PIXEL_PACK_BUFFER, copy_pbo_handle);
glBufferData(GL_PIXEL_PACK_BUFFER, buffer_size, nullptr, GL_STREAM_DRAW_ARB);
@@ -744,13 +750,10 @@ static void CopySurface(const Surface& src_surface, const Surface& dst_surface,
LOG_DEBUG(HW_GPU, "Trying to upload extra texture data from the CPU during "
"reinterpretation but the texture is tiled.");
}
- std::size_t remaining_size = dst_params.size_in_bytes - src_params.size_in_bytes;
- std::vector<u8> data(remaining_size);
- std::memcpy(data.data(), Memory::GetPointer(dst_params.addr + src_params.size_in_bytes),
- data.size());
+ const std::size_t remaining_size = dst_params.size_in_bytes - src_params.size_in_bytes;
glBufferSubData(GL_PIXEL_PACK_BUFFER, src_params.size_in_bytes, remaining_size,
- data.data());
+ Memory::GetPointer(dst_params.addr + src_params.size_in_bytes));
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
@@ -932,7 +935,9 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma
case PixelFormat::ASTC_2D_8X8_SRGB:
case PixelFormat::ASTC_2D_8X5_SRGB:
case PixelFormat::ASTC_2D_5X4_SRGB:
- case PixelFormat::ASTC_2D_5X5_SRGB: {
+ case PixelFormat::ASTC_2D_5X5_SRGB:
+ case PixelFormat::ASTC_2D_10X8:
+ case PixelFormat::ASTC_2D_10X8_SRGB: {
// Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
u32 block_width{};
u32 block_height{};
@@ -967,7 +972,11 @@ static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelForm
case PixelFormat::ASTC_2D_4X4:
case PixelFormat::ASTC_2D_8X8:
case PixelFormat::ASTC_2D_4X4_SRGB:
- case PixelFormat::ASTC_2D_8X8_SRGB: {
+ case PixelFormat::ASTC_2D_8X8_SRGB:
+ case PixelFormat::ASTC_2D_5X5:
+ case PixelFormat::ASTC_2D_5X5_SRGB:
+ case PixelFormat::ASTC_2D_10X8:
+ case PixelFormat::ASTC_2D_10X8_SRGB: {
LOG_CRITICAL(HW_GPU, "Conversion of format {} after texture flushing is not implemented",
static_cast<u32>(pixel_format));
UNREACHABLE();
@@ -1336,6 +1345,7 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
break;
case SurfaceTarget::TextureCubemap:
case SurfaceTarget::Texture3D:
+ case SurfaceTarget::Texture2DArray:
case SurfaceTarget::TextureCubeArray:
AccurateCopySurface(old_surface, new_surface);
break;
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 9517285e5..2635f2b0c 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -427,7 +427,7 @@ void OpenGLState::ApplySamplers() const {
}
}
-void OpenGLState::Apply() const {
+void OpenGLState::ApplyFramebufferState() const {
// Framebuffer
if (draw.read_framebuffer != cur_state.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) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.draw_framebuffer);
}
+}
+void OpenGLState::ApplyVertexBufferState() const {
// Vertex array
if (draw.vertex_array != cur_state.draw.vertex_array) {
glBindVertexArray(draw.vertex_array);
@@ -445,7 +447,11 @@ void OpenGLState::Apply() const {
if (draw.vertex_buffer != cur_state.draw.vertex_buffer) {
glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer);
}
+}
+void OpenGLState::Apply() const {
+ ApplyFramebufferState();
+ ApplyVertexBufferState();
// Uniform buffer
if (draw.uniform_buffer != cur_state.draw.uniform_buffer) {
glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer);
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index b8cf1f637..eacca0b9c 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -181,6 +181,10 @@ public:
}
/// Apply this state as the current OpenGL state
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
static void ApplyDefaultState();
/// Resets any references to the given resource
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 87d511c38..3ce2cc6d2 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -159,10 +159,8 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode,
}
}
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}",
- static_cast<u32>(filter_mode));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented texture filter mode={}", static_cast<u32>(filter_mode));
+ return GL_LINEAR;
}
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:
return GL_MIRROR_CLAMP_TO_EDGE;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode));
+ return GL_REPEAT;
}
inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
@@ -207,10 +204,9 @@ inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) {
case Tegra::Texture::DepthCompareFunc::Always:
return GL_ALWAYS;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented texture depth compare function ={}",
- static_cast<u32>(func));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented texture depth compare function ={}",
+ static_cast<u32>(func));
+ return GL_GREATER;
}
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
@@ -226,9 +222,8 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
case Maxwell::Blend::Equation::Max:
return GL_MAX;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation));
+ return GL_FUNC_ADD;
}
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
@@ -291,9 +286,8 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
case Maxwell::Blend::Factor::OneMinusConstantAlphaGL:
return GL_ONE_MINUS_CONSTANT_ALPHA;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
+ return GL_ZERO;
}
inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
@@ -312,9 +306,8 @@ inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
case Tegra::Texture::SwizzleSource::OneFloat:
return GL_ONE;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source));
+ return GL_ZERO;
}
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
@@ -344,33 +337,39 @@ inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
case Maxwell::ComparisonOp::AlwaysOld:
return GL_ALWAYS;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison));
+ return GL_ALWAYS;
}
inline GLenum StencilOp(Maxwell::StencilOp stencil) {
switch (stencil) {
case Maxwell::StencilOp::Keep:
+ case Maxwell::StencilOp::KeepOGL:
return GL_KEEP;
case Maxwell::StencilOp::Zero:
+ case Maxwell::StencilOp::ZeroOGL:
return GL_ZERO;
case Maxwell::StencilOp::Replace:
+ case Maxwell::StencilOp::ReplaceOGL:
return GL_REPLACE;
case Maxwell::StencilOp::Incr:
+ case Maxwell::StencilOp::IncrOGL:
return GL_INCR;
case Maxwell::StencilOp::Decr:
+ case Maxwell::StencilOp::DecrOGL:
return GL_DECR;
case Maxwell::StencilOp::Invert:
+ case Maxwell::StencilOp::InvertOGL:
return GL_INVERT;
case Maxwell::StencilOp::IncrWrap:
+ case Maxwell::StencilOp::IncrWrapOGL:
return GL_INCR_WRAP;
case Maxwell::StencilOp::DecrWrap:
+ case Maxwell::StencilOp::DecrWrapOGL:
return GL_DECR_WRAP;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil));
+ return GL_KEEP;
}
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:
return GL_CCW;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face));
+ return GL_CCW;
}
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:
return GL_FRONT_AND_BACK;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face));
+ return GL_BACK;
}
inline GLenum LogicOp(Maxwell::LogicOperation operation) {
@@ -434,9 +431,8 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) {
case Maxwell::LogicOperation::Set:
return GL_SET;
}
- LOG_CRITICAL(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation));
- UNREACHABLE();
- return {};
+ LOG_ERROR(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation));
+ return GL_COPY;
}
} // namespace MaxwellToGL
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index 051ad3964..9582dd2ca 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -306,6 +306,8 @@ PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;
case Tegra::Texture::TextureFormat::ASTC_2D_8X5:
return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5;
+ case Tegra::Texture::TextureFormat::ASTC_2D_10X8:
+ return is_srgb ? PixelFormat::ASTC_2D_10X8_SRGB : PixelFormat::ASTC_2D_10X8;
case Tegra::Texture::TextureFormat::R16_G16:
switch (component_type) {
case Tegra::Texture::ComponentType::FLOAT:
@@ -453,6 +455,8 @@ bool IsPixelFormatASTC(PixelFormat format) {
case PixelFormat::ASTC_2D_5X5_SRGB:
case PixelFormat::ASTC_2D_8X8_SRGB:
case PixelFormat::ASTC_2D_8X5_SRGB:
+ case PixelFormat::ASTC_2D_10X8:
+ case PixelFormat::ASTC_2D_10X8_SRGB:
return true;
default:
return false;
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index dfdb8d122..0dd3eb2e4 100644
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -74,19 +74,21 @@ enum class PixelFormat {
ASTC_2D_5X4_SRGB = 56,
ASTC_2D_5X5 = 57,
ASTC_2D_5X5_SRGB = 58,
+ ASTC_2D_10X8 = 59,
+ ASTC_2D_10X8_SRGB = 60,
MaxColorFormat,
// Depth formats
- Z32F = 59,
- Z16 = 60,
+ Z32F = 61,
+ Z16 = 62,
MaxDepthFormat,
// DepthStencil formats
- Z24S8 = 61,
- S8Z24 = 62,
- Z32FS8 = 63,
+ Z24S8 = 63,
+ S8Z24 = 64,
+ Z32FS8 = 65,
MaxDepthStencilFormat,
@@ -193,6 +195,8 @@ static constexpr u32 GetCompressionFactor(PixelFormat format) {
4, // ASTC_2D_5X4_SRGB
4, // ASTC_2D_5X5
4, // ASTC_2D_5X5_SRGB
+ 4, // ASTC_2D_10X8
+ 4, // ASTC_2D_10X8_SRGB
1, // Z32F
1, // Z16
1, // Z24S8
@@ -208,70 +212,72 @@ static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
if (format == PixelFormat::Invalid)
return 0;
constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
- 1, // ABGR8U
- 1, // ABGR8S
- 1, // ABGR8UI
- 1, // B5G6R5U
- 1, // A2B10G10R10U
- 1, // A1B5G5R5U
- 1, // R8U
- 1, // R8UI
- 1, // RGBA16F
- 1, // RGBA16U
- 1, // RGBA16UI
- 1, // R11FG11FB10F
- 1, // RGBA32UI
- 4, // DXT1
- 4, // DXT23
- 4, // DXT45
- 4, // DXN1
- 4, // DXN2UNORM
- 4, // DXN2SNORM
- 4, // BC7U
- 4, // BC6H_UF16
- 4, // BC6H_SF16
- 4, // ASTC_2D_4X4
- 1, // G8R8U
- 1, // G8R8S
- 1, // BGRA8
- 1, // RGBA32F
- 1, // RG32F
- 1, // R32F
- 1, // R16F
- 1, // R16U
- 1, // R16S
- 1, // R16UI
- 1, // R16I
- 1, // RG16
- 1, // RG16F
- 1, // RG16UI
- 1, // RG16I
- 1, // RG16S
- 1, // RGB32F
- 1, // RGBA8_SRGB
- 1, // RG8U
- 1, // RG8S
- 1, // RG32UI
- 1, // R32UI
- 8, // ASTC_2D_8X8
- 8, // ASTC_2D_8X5
- 5, // ASTC_2D_5X4
- 1, // BGRA8_SRGB
- 4, // DXT1_SRGB
- 4, // DXT23_SRGB
- 4, // DXT45_SRGB
- 4, // BC7U_SRGB
- 4, // ASTC_2D_4X4_SRGB
- 8, // ASTC_2D_8X8_SRGB
- 8, // ASTC_2D_8X5_SRGB
- 5, // ASTC_2D_5X4_SRGB
- 5, // ASTC_2D_5X5
- 5, // ASTC_2D_5X5_SRGB
- 1, // Z32F
- 1, // Z16
- 1, // Z24S8
- 1, // S8Z24
- 1, // Z32FS8
+ 1, // ABGR8U
+ 1, // ABGR8S
+ 1, // ABGR8UI
+ 1, // B5G6R5U
+ 1, // A2B10G10R10U
+ 1, // A1B5G5R5U
+ 1, // R8U
+ 1, // R8UI
+ 1, // RGBA16F
+ 1, // RGBA16U
+ 1, // RGBA16UI
+ 1, // R11FG11FB10F
+ 1, // RGBA32UI
+ 4, // DXT1
+ 4, // DXT23
+ 4, // DXT45
+ 4, // DXN1
+ 4, // DXN2UNORM
+ 4, // DXN2SNORM
+ 4, // BC7U
+ 4, // BC6H_UF16
+ 4, // BC6H_SF16
+ 4, // ASTC_2D_4X4
+ 1, // G8R8U
+ 1, // G8R8S
+ 1, // BGRA8
+ 1, // RGBA32F
+ 1, // RG32F
+ 1, // R32F
+ 1, // R16F
+ 1, // R16U
+ 1, // R16S
+ 1, // R16UI
+ 1, // R16I
+ 1, // RG16
+ 1, // RG16F
+ 1, // RG16UI
+ 1, // RG16I
+ 1, // RG16S
+ 1, // RGB32F
+ 1, // RGBA8_SRGB
+ 1, // RG8U
+ 1, // RG8S
+ 1, // RG32UI
+ 1, // R32UI
+ 8, // ASTC_2D_8X8
+ 8, // ASTC_2D_8X5
+ 5, // ASTC_2D_5X4
+ 1, // BGRA8_SRGB
+ 4, // DXT1_SRGB
+ 4, // DXT23_SRGB
+ 4, // DXT45_SRGB
+ 4, // BC7U_SRGB
+ 4, // ASTC_2D_4X4_SRGB
+ 8, // ASTC_2D_8X8_SRGB
+ 8, // ASTC_2D_8X5_SRGB
+ 5, // ASTC_2D_5X4_SRGB
+ 5, // ASTC_2D_5X5
+ 5, // ASTC_2D_5X5_SRGB
+ 10, // ASTC_2D_10X8
+ 10, // ASTC_2D_10X8_SRGB
+ 1, // Z32F
+ 1, // Z16
+ 1, // Z24S8
+ 1, // S8Z24
+ 1, // Z32FS8
}};
ASSERT(static_cast<std::size_t>(format) < block_width_table.size());
return block_width_table[static_cast<std::size_t>(format)];
@@ -341,6 +347,8 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
4, // ASTC_2D_5X4_SRGB
5, // ASTC_2D_5X5
5, // ASTC_2D_5X5_SRGB
+ 8, // ASTC_2D_10X8
+ 8, // ASTC_2D_10X8_SRGB
1, // Z32F
1, // Z16
1, // Z24S8
@@ -416,6 +424,8 @@ static constexpr u32 GetFormatBpp(PixelFormat format) {
128, // ASTC_2D_5X4_SRGB
128, // ASTC_2D_5X5
128, // ASTC_2D_5X5_SRGB
+ 128, // ASTC_2D_10X8
+ 128, // ASTC_2D_10X8_SRGB
32, // Z32F
16, // Z16
32, // Z24S8
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 3066abf61..a9d134d14 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -202,6 +202,8 @@ u32 BytesPerPixel(TextureFormat format) {
case TextureFormat::ASTC_2D_5X4:
case TextureFormat::ASTC_2D_8X8:
case TextureFormat::ASTC_2D_8X5:
+ case TextureFormat::ASTC_2D_10X8:
+ case TextureFormat::ASTC_2D_5X5:
case TextureFormat::A8R8G8B8:
case TextureFormat::A2B10G10R10:
case TextureFormat::BF10GF11RF11:
@@ -294,6 +296,8 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
case TextureFormat::BC6H_SF16:
case TextureFormat::ASTC_2D_4X4:
case TextureFormat::ASTC_2D_8X8:
+ case TextureFormat::ASTC_2D_5X5:
+ case TextureFormat::ASTC_2D_10X8:
case TextureFormat::A8R8G8B8:
case TextureFormat::A2B10G10R10:
case TextureFormat::A1B5G5R5:
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index d12d2ecb8..e199d019a 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -168,20 +168,29 @@ struct TICEntry {
// High 16 bits of the pitch value
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;
};
union {
BitField<0, 16, u32> width_minus_1;
BitField<22, 1, u32> srgb_conversion;
BitField<23, 4, TextureType> texture_type;
+ BitField<29, 3, u32> border_size;
};
union {
BitField<0, 16, u32> height_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 {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);