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.h20
-rw-r--r--src/video_core/engines/maxwell_compute.cpp19
-rw-r--r--src/video_core/engines/maxwell_compute.h36
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp29
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h11
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h21
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h3
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp31
-rw-r--r--src/video_core/renderer_opengl/gl_state.h7
-rw-r--r--src/video_core/textures/decoders.cpp117
-rw-r--r--src/video_core/utils.h22
13 files changed, 260 insertions, 65 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index b81b0723d..9f5581045 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -41,6 +41,7 @@ public:
static constexpr std::size_t NumCBData = 16;
static constexpr std::size_t NumVertexArrays = 32;
static constexpr std::size_t NumVertexAttributes = 32;
+ static constexpr std::size_t NumTextureSamplers = 32;
static constexpr std::size_t MaxShaderProgram = 6;
static constexpr std::size_t MaxShaderStage = 5;
// Maximum number of const buffers per shader stage.
@@ -461,7 +462,11 @@ public:
u32 entry;
} macros;
- INSERT_PADDING_WORDS(0x1B8);
+ INSERT_PADDING_WORDS(0x189);
+
+ u32 tfb_enabled;
+
+ INSERT_PADDING_WORDS(0x2E);
RenderTargetConfig rt[NumRenderTargets];
@@ -594,7 +599,9 @@ public:
u32 depth_write_enabled;
- INSERT_PADDING_WORDS(0x7);
+ u32 alpha_test_enabled;
+
+ INSERT_PADDING_WORDS(0x6);
u32 d3d_cull_mode;
@@ -635,7 +642,11 @@ public:
u32 vb_element_base;
- INSERT_PADDING_WORDS(0x40);
+ INSERT_PADDING_WORDS(0x38);
+
+ float point_size;
+
+ INSERT_PADDING_WORDS(0x7);
u32 zeta_enable;
@@ -977,6 +988,7 @@ private:
"Field " #field_name " has invalid position")
ASSERT_REG_POSITION(macros, 0x45);
+ASSERT_REG_POSITION(tfb_enabled, 0x1D1);
ASSERT_REG_POSITION(rt, 0x200);
ASSERT_REG_POSITION(viewport_transform[0], 0x280);
ASSERT_REG_POSITION(viewport, 0x300);
@@ -996,6 +1008,7 @@ ASSERT_REG_POSITION(zeta_height, 0x48b);
ASSERT_REG_POSITION(depth_test_enable, 0x4B3);
ASSERT_REG_POSITION(independent_blend_enable, 0x4B9);
ASSERT_REG_POSITION(depth_write_enabled, 0x4BA);
+ASSERT_REG_POSITION(alpha_test_enabled, 0x4BB);
ASSERT_REG_POSITION(d3d_cull_mode, 0x4C2);
ASSERT_REG_POSITION(depth_test_func, 0x4C3);
ASSERT_REG_POSITION(blend, 0x4CF);
@@ -1009,6 +1022,7 @@ ASSERT_REG_POSITION(stencil_front_func_mask, 0x4E6);
ASSERT_REG_POSITION(stencil_front_mask, 0x4E7);
ASSERT_REG_POSITION(screen_y_control, 0x4EB);
ASSERT_REG_POSITION(vb_element_base, 0x50D);
+ASSERT_REG_POSITION(point_size, 0x546);
ASSERT_REG_POSITION(zeta_enable, 0x54E);
ASSERT_REG_POSITION(tsc, 0x557);
ASSERT_REG_POSITION(tic, 0x55D);
diff --git a/src/video_core/engines/maxwell_compute.cpp b/src/video_core/engines/maxwell_compute.cpp
index e4e5f9e5e..59e28b22d 100644
--- a/src/video_core/engines/maxwell_compute.cpp
+++ b/src/video_core/engines/maxwell_compute.cpp
@@ -2,12 +2,29 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/logging/log.h"
+#include "core/core.h"
#include "video_core/engines/maxwell_compute.h"
namespace Tegra {
namespace Engines {
-void MaxwellCompute::WriteReg(u32 method, u32 value) {}
+void MaxwellCompute::WriteReg(u32 method, u32 value) {
+ ASSERT_MSG(method < Regs::NUM_REGS,
+ "Invalid MaxwellCompute register, increase the size of the Regs structure");
+
+ regs.reg_array[method] = value;
+
+ switch (method) {
+ case MAXWELL_COMPUTE_REG_INDEX(compute): {
+ LOG_CRITICAL(HW_GPU, "Compute shaders are not implemented");
+ UNREACHABLE();
+ break;
+ }
+ default:
+ break;
+ }
+}
} // namespace Engines
} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_compute.h b/src/video_core/engines/maxwell_compute.h
index 2b3e4ced6..6ea934fb9 100644
--- a/src/video_core/engines/maxwell_compute.h
+++ b/src/video_core/engines/maxwell_compute.h
@@ -4,17 +4,53 @@
#pragma once
+#include <array>
+#include "common/assert.h"
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
#include "common/common_types.h"
namespace Tegra::Engines {
+#define MAXWELL_COMPUTE_REG_INDEX(field_name) \
+ (offsetof(Tegra::Engines::MaxwellCompute::Regs, field_name) / sizeof(u32))
+
class MaxwellCompute final {
public:
MaxwellCompute() = default;
~MaxwellCompute() = default;
+ struct Regs {
+ static constexpr std::size_t NUM_REGS = 0xCF8;
+
+ union {
+ struct {
+ INSERT_PADDING_WORDS(0x281);
+
+ union {
+ u32 compute_end;
+ BitField<0, 1, u32> unknown;
+ } compute;
+
+ INSERT_PADDING_WORDS(0xA76);
+ };
+ std::array<u32, NUM_REGS> reg_array;
+ };
+ } regs{};
+
+ static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32),
+ "MaxwellCompute Regs has wrong size");
+
/// Write the value to the register identified by method.
void WriteReg(u32 method, u32 value);
};
+#define ASSERT_REG_POSITION(field_name, position) \
+ static_assert(offsetof(MaxwellCompute::Regs, field_name) == position * 4, \
+ "Field " #field_name " has invalid position")
+
+ASSERT_REG_POSITION(compute, 0x281);
+
+#undef ASSERT_REG_POSITION
+
} // namespace Tegra::Engines
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 70fb54507..1fcd13f04 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -450,6 +450,9 @@ void RasterizerOpenGL::DrawArrays() {
SyncBlendState();
SyncLogicOpState();
SyncCullMode();
+ SyncAlphaTest();
+ SyncTransformFeedback();
+ SyncPointState();
// TODO(bunnei): Sync framebuffer_scale uniform here
// TODO(bunnei): Sync scissorbox uniform(s) here
@@ -883,4 +886,30 @@ void RasterizerOpenGL::SyncLogicOpState() {
state.logic_op.operation = MaxwellToGL::LogicOp(regs.logic_op.operation);
}
+void RasterizerOpenGL::SyncAlphaTest() {
+ const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
+
+ // TODO(Rodrigo): Alpha testing is a legacy OpenGL feature, but it can be
+ // implemented with a test+discard in fragment shaders.
+ if (regs.alpha_test_enabled != 0) {
+ LOG_CRITICAL(Render_OpenGL, "Alpha testing is not implemented");
+ UNREACHABLE();
+ }
+}
+
+void RasterizerOpenGL::SyncTransformFeedback() {
+ const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
+
+ if (regs.tfb_enabled != 0) {
+ LOG_CRITICAL(Render_OpenGL, "Transform feedbacks are not implemented");
+ UNREACHABLE();
+ }
+}
+
+void RasterizerOpenGL::SyncPointState() {
+ const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
+
+ state.point.size = regs.point_size;
+}
+
} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index bf9560bdc..4c8ecbd1c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -158,6 +158,15 @@ private:
/// Syncs the LogicOp state to match the guest state
void SyncLogicOpState();
+ /// Syncs the alpha test state to match the guest state
+ void SyncAlphaTest();
+
+ /// Syncs the transform feedback state to match the guest state
+ void SyncTransformFeedback();
+
+ /// Syncs the point state to match the guest state
+ void SyncPointState();
+
bool has_ARB_direct_state_access = false;
bool has_ARB_multi_bind = false;
bool has_ARB_separate_shader_objects = false;
@@ -178,7 +187,7 @@ private:
OGLVertexArray>
vertex_array_cache;
- std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers;
+ std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers;
static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
OGLBufferCache buffer_cache;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 86682d7cb..24a540258 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -141,8 +141,8 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
{GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
true}, // BC7U
{GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, GL_RGB, GL_UNSIGNED_INT_8_8_8_8,
- ComponentType::UNorm, true}, // BC6H_UF16
- {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
+ ComponentType::Float, true}, // BC6H_UF16
+ {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, ComponentType::Float,
true}, // BC6H_SF16
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4
{GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // G8R8U
@@ -501,6 +501,9 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ VideoCore::LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
+ SurfaceParams::SurfaceTargetName(params.target));
}
static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index d7a4bc37f..80c5f324b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -137,6 +137,27 @@ struct SurfaceParams {
}
}
+ static std::string SurfaceTargetName(SurfaceTarget target) {
+ switch (target) {
+ case SurfaceTarget::Texture1D:
+ return "Texture1D";
+ case SurfaceTarget::Texture2D:
+ return "Texture2D";
+ case SurfaceTarget::Texture3D:
+ return "Texture3D";
+ case SurfaceTarget::Texture1DArray:
+ return "Texture1DArray";
+ case SurfaceTarget::Texture2DArray:
+ return "Texture2DArray";
+ case SurfaceTarget::TextureCubemap:
+ return "TextureCubemap";
+ default:
+ LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
+ UNREACHABLE();
+ return fmt::format("TextureUnknown({})", static_cast<u32>(target));
+ }
+ }
+
/**
* Gets the compression factor for the specified PixelFormat. This applies to just the
* "compressed width" and "compressed height", not the overall compression factor of a
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 894fe6eae..7cd8f91e4 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -8,6 +8,7 @@
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_shader_cache.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
+#include "video_core/utils.h"
namespace OpenGL {
@@ -83,6 +84,7 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
shader.Create(program_result.first.c_str(), gl_type);
program.Create(true, shader.handle);
SetShaderUniformBlockBindings(program.handle);
+ VideoCore::LabelGLObject(GL_PROGRAM, program.handle, addr);
}
GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) {
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index b86cd96e8..3de15ba9b 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -11,9 +11,6 @@
namespace OpenGL::GLShader {
-/// Number of OpenGL texture samplers that can be used in the fragment shader
-static constexpr std::size_t NumTextureSamplers = 32;
-
using Tegra::Engines::Maxwell3D;
/// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index e5173e20a..1fe26a2a9 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -79,6 +79,8 @@ OpenGLState::OpenGLState() {
viewport.height = 0;
clip_distance = {};
+
+ point.size = 1;
}
void OpenGLState::Apply() const {
@@ -205,9 +207,6 @@ void OpenGLState::Apply() const {
glActiveTexture(TextureUnits::MaxwellTexture(static_cast<int>(i)).Enum());
glBindTexture(texture_unit.target, texture_unit.texture);
}
- if (texture_unit.sampler != cur_state_texture_unit.sampler) {
- glBindSampler(static_cast<GLuint>(i), texture_unit.sampler);
- }
// Update the texture swizzle
if (texture_unit.swizzle.r != cur_state_texture_unit.swizzle.r ||
texture_unit.swizzle.g != cur_state_texture_unit.swizzle.g ||
@@ -219,6 +218,27 @@ void OpenGLState::Apply() const {
}
}
+ // Samplers
+ {
+ bool has_delta{};
+ std::size_t first{}, last{};
+ std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> samplers;
+ for (std::size_t i = 0; i < std::size(samplers); ++i) {
+ samplers[i] = texture_units[i].sampler;
+ if (samplers[i] != cur_state.texture_units[i].sampler) {
+ if (!has_delta) {
+ first = i;
+ has_delta = true;
+ }
+ last = i;
+ }
+ }
+ if (has_delta) {
+ glBindSamplers(static_cast<GLuint>(first), static_cast<GLsizei>(last - first + 1),
+ samplers.data());
+ }
+ }
+
// Framebuffer
if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
@@ -283,6 +303,11 @@ void OpenGLState::Apply() const {
}
}
+ // Point
+ if (point.size != cur_state.point.size) {
+ glPointSize(point.size);
+ }
+
cur_state = *this;
}
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 9a93029d8..dc21a2ee3 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -6,6 +6,7 @@
#include <array>
#include <glad/glad.h>
+#include "video_core/engines/maxwell_3d.h"
namespace OpenGL {
@@ -114,7 +115,7 @@ public:
target = GL_TEXTURE_2D;
}
};
- std::array<TextureUnit, 32> texture_units;
+ std::array<TextureUnit, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_units;
struct {
GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING
@@ -141,6 +142,10 @@ public:
GLsizei height;
} viewport;
+ struct {
+ float size; // GL_POINT_SIZE
+ } point;
+
std::array<bool, 2> clip_distance; // GL_CLIP_DISTANCE
OpenGLState();
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 20ba6d4f6..3d5476e5d 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -13,47 +13,20 @@
namespace Tegra::Texture {
/**
+ * This table represents the internal swizzle of a gob,
+ * in format 16 bytes x 2 sector packing.
* Calculates the offset of an (x, y) position within a swizzled texture.
- * Taken from the Tegra X1 TRM.
+ * Taken from the Tegra X1 Technical Reference Manual. pages 1187-1188
*/
-static u32 GetSwizzleOffset(u32 x, u32 y, u32 image_width, u32 bytes_per_pixel, u32 block_height) {
- // Round up to the next gob
- const u32 image_width_in_gobs{(image_width * bytes_per_pixel + 63) / 64};
-
- u32 GOB_address = 0 + (y / (8 * block_height)) * 512 * block_height * image_width_in_gobs +
- (x * bytes_per_pixel / 64) * 512 * block_height +
- (y % (8 * block_height) / 8) * 512;
- x *= bytes_per_pixel;
- u32 address = GOB_address + ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 +
- (y % 2) * 16 + (x % 16);
-
- return address;
-}
-
-void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
- u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height) {
- u8* data_ptrs[2];
- for (unsigned y = 0; y < height; ++y) {
- for (unsigned x = 0; x < width; ++x) {
- u32 swizzle_offset = GetSwizzleOffset(x, y, width, bytes_per_pixel, block_height);
- u32 pixel_index = (x + y * width) * out_bytes_per_pixel;
-
- data_ptrs[unswizzle] = swizzled_data + swizzle_offset;
- data_ptrs[!unswizzle] = &unswizzled_data[pixel_index];
-
- std::memcpy(data_ptrs[0], data_ptrs[1], bytes_per_pixel);
- }
- }
-}
-
-template <std::size_t N, std::size_t M>
+template <std::size_t N, std::size_t M, u32 Align>
struct alignas(64) SwizzleTable {
+ static_assert(M * Align == 64, "Swizzle Table does not align to GOB");
constexpr SwizzleTable() {
for (u32 y = 0; y < N; ++y) {
for (u32 x = 0; x < M; ++x) {
- const u32 x2 = x * 16;
+ const u32 x2 = x * Align;
values[y][x] = static_cast<u16>(((x2 % 64) / 32) * 256 + ((y % 8) / 2) * 64 +
- ((x2 % 32) / 16) * 32 + (y % 2) * 16);
+ ((x2 % 32) / 16) * 32 + (y % 2) * 16 + (x2 % 16));
}
}
}
@@ -63,24 +36,60 @@ struct alignas(64) SwizzleTable {
std::array<std::array<u16, M>, N> values{};
};
-constexpr auto swizzle_table = SwizzleTable<8, 4>();
+constexpr auto legacy_swizzle_table = SwizzleTable<8, 64, 1>();
+constexpr auto fast_swizzle_table = SwizzleTable<8, 4, 16>();
-void FastSwizzleData(u32 width, u32 height, u32 bytes_per_pixel, u8* swizzled_data,
- u8* unswizzled_data, bool unswizzle, u32 block_height) {
+static void LegacySwizzleData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
+ u8* swizzled_data, u8* unswizzled_data, bool unswizzle,
+ u32 block_height) {
+ std::array<u8*, 2> data_ptrs;
+ const std::size_t stride = width * bytes_per_pixel;
+ const std::size_t gobs_in_x = 64;
+ const std::size_t gobs_in_y = 8;
+ const std::size_t gobs_size = gobs_in_x * gobs_in_y;
+ const std::size_t image_width_in_gobs{(stride + gobs_in_x - 1) / gobs_in_x};
+ for (std::size_t y = 0; y < height; ++y) {
+ const std::size_t gob_y_address =
+ (y / (gobs_in_y * block_height)) * gobs_size * block_height * image_width_in_gobs +
+ (y % (gobs_in_y * block_height) / gobs_in_y) * gobs_size;
+ const auto& table = legacy_swizzle_table[y % gobs_in_y];
+ for (std::size_t x = 0; x < width; ++x) {
+ const std::size_t gob_address =
+ gob_y_address + (x * bytes_per_pixel / gobs_in_x) * gobs_size * block_height;
+ const std::size_t x2 = x * bytes_per_pixel;
+ const std::size_t swizzle_offset = gob_address + table[x2 % gobs_in_x];
+ const std::size_t pixel_index = (x + y * width) * out_bytes_per_pixel;
+
+ data_ptrs[unswizzle] = swizzled_data + swizzle_offset;
+ data_ptrs[!unswizzle] = unswizzled_data + pixel_index;
+
+ std::memcpy(data_ptrs[0], data_ptrs[1], bytes_per_pixel);
+ }
+ }
+}
+
+static void FastSwizzleData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
+ u8* swizzled_data, u8* unswizzled_data, bool unswizzle,
+ u32 block_height) {
std::array<u8*, 2> data_ptrs;
const std::size_t stride{width * bytes_per_pixel};
- const std::size_t image_width_in_gobs{(stride + 63) / 64};
+ const std::size_t gobs_in_x = 64;
+ const std::size_t gobs_in_y = 8;
+ const std::size_t gobs_size = gobs_in_x * gobs_in_y;
+ const std::size_t image_width_in_gobs{(stride + gobs_in_x - 1) / gobs_in_x};
const std::size_t copy_size{16};
for (std::size_t y = 0; y < height; ++y) {
const std::size_t initial_gob =
- (y / (8 * block_height)) * 512 * block_height * image_width_in_gobs +
- (y % (8 * block_height) / 8) * 512;
- const std::size_t pixel_base{y * width * bytes_per_pixel};
- const auto& table = swizzle_table[y % 8];
+ (y / (gobs_in_y * block_height)) * gobs_size * block_height * image_width_in_gobs +
+ (y % (gobs_in_y * block_height) / gobs_in_y) * gobs_size;
+ const std::size_t pixel_base{y * width * out_bytes_per_pixel};
+ const auto& table = fast_swizzle_table[y % gobs_in_y];
for (std::size_t xb = 0; xb < stride; xb += copy_size) {
- const std::size_t gob_address{initial_gob + (xb / 64) * 512 * block_height};
+ const std::size_t gob_address{initial_gob +
+ (xb / gobs_in_x) * gobs_size * block_height};
const std::size_t swizzle_offset{gob_address + table[(xb / 16) % 4]};
- const std::size_t pixel_index{xb + pixel_base};
+ const std::size_t out_x = xb * out_bytes_per_pixel / bytes_per_pixel;
+ const std::size_t pixel_index{out_x + pixel_base};
data_ptrs[unswizzle] = swizzled_data + swizzle_offset;
data_ptrs[!unswizzle] = unswizzled_data + pixel_index;
std::memcpy(data_ptrs[0], data_ptrs[1], copy_size);
@@ -88,6 +97,17 @@ void FastSwizzleData(u32 width, u32 height, u32 bytes_per_pixel, u8* swizzled_da
}
}
+void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
+ u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height) {
+ if (bytes_per_pixel % 3 != 0 && (width * bytes_per_pixel) % 16 == 0) {
+ FastSwizzleData(width, height, bytes_per_pixel, out_bytes_per_pixel, swizzled_data,
+ unswizzled_data, unswizzle, block_height);
+ } else {
+ LegacySwizzleData(width, height, bytes_per_pixel, out_bytes_per_pixel, swizzled_data,
+ unswizzled_data, unswizzle, block_height);
+ }
+}
+
u32 BytesPerPixel(TextureFormat format) {
switch (format) {
case TextureFormat::DXT1:
@@ -134,13 +154,8 @@ u32 BytesPerPixel(TextureFormat format) {
std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
u32 height, u32 block_height) {
std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
- if (bytes_per_pixel % 3 != 0 && (width * bytes_per_pixel) % 16 == 0) {
- FastSwizzleData(width / tile_size, height / tile_size, bytes_per_pixel,
- Memory::GetPointer(address), unswizzled_data.data(), true, block_height);
- } else {
- CopySwizzledData(width / tile_size, height / tile_size, bytes_per_pixel, bytes_per_pixel,
- Memory::GetPointer(address), unswizzled_data.data(), true, block_height);
- }
+ CopySwizzledData(width / tile_size, height / tile_size, bytes_per_pixel, bytes_per_pixel,
+ Memory::GetPointer(address), unswizzled_data.data(), true, block_height);
return unswizzled_data;
}
diff --git a/src/video_core/utils.h b/src/video_core/utils.h
index e0a14d48f..681919ae3 100644
--- a/src/video_core/utils.h
+++ b/src/video_core/utils.h
@@ -161,4 +161,26 @@ static inline void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixe
}
}
+static void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr,
+ std::string extra_info = "") {
+ if (!GLAD_GL_KHR_debug) {
+ return; // We don't need to throw an error as this is just for debugging
+ }
+ const std::string nice_addr = fmt::format("0x{:016x}", addr);
+ std::string object_label;
+
+ switch (identifier) {
+ case GL_TEXTURE:
+ object_label = extra_info + "@" + nice_addr;
+ break;
+ case GL_PROGRAM:
+ object_label = "ShaderProgram@" + nice_addr;
+ break;
+ default:
+ object_label = fmt::format("Object(0x{:x})@{}", identifier, nice_addr);
+ break;
+ }
+ glObjectLabel(identifier, handle, -1, static_cast<const GLchar*>(object_label.c_str()));
+}
+
} // namespace VideoCore