rasterizer_cache: Separate texture swizzling to utils
This commit is contained in:
@ -1,11 +1,10 @@
|
||||
# CMake 3.12 required for 20 to be a valid value for CXX_STANDARD
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.15)
|
||||
# Don't override the warning flags in MSVC:
|
||||
cmake_policy(SET CMP0092 NEW)
|
||||
# Enforce new LTO setting
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
endif()
|
||||
# CMake 3.20 required for 23 to be a valid value for CXX_STANDARD
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
# Don't override the warning flags in MSVC:
|
||||
cmake_policy(SET CMP0092 NEW)
|
||||
# Enforce new LTO setting
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
|
||||
@ -158,7 +157,7 @@ message(STATUS "Target architecture: ${ARCHITECTURE}")
|
||||
# Configure C++ standard
|
||||
# ===========================
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# set up output paths for executable binaries
|
||||
|
@ -32,12 +32,17 @@ void CachedSurface::LoadGLBuffer(PAddr load_start, PAddr load_end) {
|
||||
const bool need_swap =
|
||||
GLES && (pixel_format == PixelFormat::RGBA8 || pixel_format == PixelFormat::RGB8);
|
||||
|
||||
const u8* const texture_src_data = VideoCore::g_memory->GetPhysicalPointer(addr);
|
||||
if (texture_src_data == nullptr)
|
||||
const u8* texture_ptr = VideoCore::g_memory->GetPhysicalPointer(addr);
|
||||
if (texture_ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const u32 byte_size = width * height * GetBytesPerPixel(pixel_format);
|
||||
const auto texture_data = std::span<const std::byte>{reinterpret_cast<const std::byte*>(texture_ptr),
|
||||
byte_size};
|
||||
|
||||
if (gl_buffer.empty()) {
|
||||
gl_buffer.resize(width * height * GetBytesPerPixel(pixel_format));
|
||||
gl_buffer.resize(byte_size);
|
||||
}
|
||||
|
||||
// TODO: Should probably be done in ::Memory:: and check for other regions too
|
||||
@ -59,58 +64,38 @@ void CachedSurface::LoadGLBuffer(PAddr load_start, PAddr load_end) {
|
||||
// cannot fully test this
|
||||
if (pixel_format == PixelFormat::RGBA8) {
|
||||
for (std::size_t i = start_offset; i < load_end - addr; i += 4) {
|
||||
gl_buffer[i] = texture_src_data[i + 3];
|
||||
gl_buffer[i + 1] = texture_src_data[i + 2];
|
||||
gl_buffer[i + 2] = texture_src_data[i + 1];
|
||||
gl_buffer[i + 3] = texture_src_data[i];
|
||||
gl_buffer[i] = texture_ptr[i + 3];
|
||||
gl_buffer[i + 1] = texture_ptr[i + 2];
|
||||
gl_buffer[i + 2] = texture_ptr[i + 1];
|
||||
gl_buffer[i + 3] = texture_ptr[i];
|
||||
}
|
||||
} else if (pixel_format == PixelFormat::RGB8) {
|
||||
for (std::size_t i = start_offset; i < load_end - addr; i += 3) {
|
||||
gl_buffer[i] = texture_src_data[i + 2];
|
||||
gl_buffer[i + 1] = texture_src_data[i + 1];
|
||||
gl_buffer[i + 2] = texture_src_data[i];
|
||||
gl_buffer[i] = texture_ptr[i + 2];
|
||||
gl_buffer[i + 1] = texture_ptr[i + 1];
|
||||
gl_buffer[i + 2] = texture_ptr[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
|
||||
std::memcpy(&gl_buffer[start_offset], texture_ptr + start_offset,
|
||||
load_end - load_start);
|
||||
}
|
||||
} else {
|
||||
if (type == SurfaceType::Texture) {
|
||||
Pica::Texture::TextureInfo tex_info{};
|
||||
tex_info.width = width;
|
||||
tex_info.height = height;
|
||||
tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(pixel_format);
|
||||
tex_info.SetDefaultStride();
|
||||
tex_info.physical_address = addr;
|
||||
|
||||
const SurfaceInterval load_interval(load_start, load_end);
|
||||
const auto rect = GetSubRect(FromInterval(load_interval));
|
||||
ASSERT(FromInterval(load_interval).GetInterval() == load_interval);
|
||||
|
||||
for (unsigned y = rect.bottom; y < rect.top; ++y) {
|
||||
for (unsigned x = rect.left; x < rect.right; ++x) {
|
||||
auto vec4 =
|
||||
Pica::Texture::LookupTexture(texture_src_data, x, height - 1 - y, tex_info);
|
||||
const std::size_t offset = (x + (width * y)) * 4;
|
||||
std::memcpy(&gl_buffer[offset], vec4.AsArray(), 4);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const u32 func_index = static_cast<u32>(pixel_format);
|
||||
const MortonFunc func = UNSWIZZLE_TABLE[func_index];
|
||||
func(stride, height, &gl_buffer[0], addr, load_start, load_end);
|
||||
}
|
||||
const auto dest_data = std::span<std::byte>{reinterpret_cast<std::byte*>(gl_buffer.data()),
|
||||
byte_size};
|
||||
UnswizzleTexture(*this, load_start, load_end, texture_data, dest_data);
|
||||
}
|
||||
}
|
||||
|
||||
MICROPROFILE_DEFINE(RasterizerCache_SurfaceFlush, "RasterizerCache", "Surface Flush", MP_RGB(128, 192, 64));
|
||||
void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) {
|
||||
u8* const dst_buffer = VideoCore::g_memory->GetPhysicalPointer(addr);
|
||||
if (dst_buffer == nullptr)
|
||||
if (dst_buffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(gl_buffer.size() == width * height * GetBytesPerPixel(pixel_format));
|
||||
const u32 byte_size = width * height * GetBytesPerPixel(pixel_format);
|
||||
DEBUG_ASSERT(gl_buffer.size() == byte_size);
|
||||
|
||||
// TODO: Should probably be done in ::Memory:: and check for other regions too
|
||||
// same as loadglbuffer()
|
||||
@ -130,8 +115,9 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) {
|
||||
const u32 coarse_start_offset = start_offset - (start_offset % fill_size);
|
||||
const u32 backup_bytes = start_offset % fill_size;
|
||||
std::array<u8, 4> backup_data;
|
||||
if (backup_bytes)
|
||||
if (backup_bytes) {
|
||||
std::memcpy(&backup_data[0], &dst_buffer[coarse_start_offset], backup_bytes);
|
||||
}
|
||||
|
||||
for (u32 offset = coarse_start_offset; offset < end_offset; offset += fill_size) {
|
||||
std::memcpy(&dst_buffer[offset], &fill_data[0],
|
||||
@ -160,9 +146,9 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) {
|
||||
flush_end - flush_start);
|
||||
}
|
||||
} else {
|
||||
const u32 func_index = static_cast<u32>(pixel_format);
|
||||
const MortonFunc func = SWIZZLE_TABLE[func_index];
|
||||
func(stride, height, &gl_buffer[0], addr, flush_start, flush_end);
|
||||
const auto source_data = std::span<std::byte>{reinterpret_cast<std::byte*>(gl_buffer.data()),
|
||||
byte_size};
|
||||
SwizzleTexture(*this, flush_start, flush_end, source_data, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,7 +449,8 @@ Surface RasterizerCache::GetTextureSurface(const Pica::Texture::TextureInfo& inf
|
||||
|
||||
const Subresource dst_subresource = {
|
||||
.aspect = aspect,
|
||||
.region = surface_params.GetScaledRect()
|
||||
.region = surface_params.GetScaledRect(),
|
||||
.level = level
|
||||
};
|
||||
|
||||
runtime.BlitTextures(level_surface->texture, src_subresource,
|
||||
|
@ -5,6 +5,8 @@
|
||||
#pragma once
|
||||
#include <glad/glad.h>
|
||||
#include "video_core/texture/texture_decode.h"
|
||||
#include "video_core/rasterizer_cache/morton_swizzle.h"
|
||||
#include "video_core/rasterizer_cache/surface_params.h"
|
||||
#include "video_core/rasterizer_cache/utils.h"
|
||||
#include "video_core/renderer_opengl/gl_vars.h"
|
||||
|
||||
@ -54,6 +56,49 @@ const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
|
||||
return tex_tuple;
|
||||
}
|
||||
|
||||
void SwizzleTexture(const SurfaceParams& params, u32 flush_start, u32 flush_end,
|
||||
std::span<std::byte> source, std::span<std::byte> dest) {
|
||||
const u32 func_index = static_cast<u32>(params.pixel_format);
|
||||
const MortonFunc swizzle = SWIZZLE_TABLE[func_index];
|
||||
u8* source_data = reinterpret_cast<u8*>(source.data());
|
||||
|
||||
// TODO: Move memory access out of the morton function
|
||||
swizzle(params.stride, params.height, source_data, params.addr, flush_start, flush_end);
|
||||
}
|
||||
|
||||
void UnswizzleTexture(const SurfaceParams& params, u32 load_start, u32 load_end,
|
||||
std::span<const std::byte> source, std::span<std::byte> dest) {
|
||||
// TODO: Integrate this to UNSWIZZLE_TABLE
|
||||
if (params.type == SurfaceType::Texture) {
|
||||
Pica::Texture::TextureInfo tex_info{};
|
||||
tex_info.width = params.width;
|
||||
tex_info.height = params.height;
|
||||
tex_info.format = static_cast<Pica::TexturingRegs::TextureFormat>(params.pixel_format);
|
||||
tex_info.SetDefaultStride();
|
||||
tex_info.physical_address = params.addr;
|
||||
|
||||
const SurfaceInterval load_interval(load_start, load_end);
|
||||
const auto rect = params.GetSubRect(params.FromInterval(load_interval));
|
||||
DEBUG_ASSERT(params.FromInterval(load_interval).GetInterval() == load_interval);
|
||||
|
||||
const u8* source_data = reinterpret_cast<const u8*>(source.data());
|
||||
for (u32 y = rect.bottom; y < rect.top; y++) {
|
||||
for (u32 x = rect.left; x < rect.right; x++) {
|
||||
auto vec4 =
|
||||
Pica::Texture::LookupTexture(source_data, x, params.height - 1 - y, tex_info);
|
||||
const std::size_t offset = (x + (params.width * y)) * 4;
|
||||
std::memcpy(dest.data() + offset, vec4.AsArray(), 4);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const u32 func_index = static_cast<u32>(params.pixel_format);
|
||||
const MortonFunc deswizzle = UNSWIZZLE_TABLE[func_index];
|
||||
u8* dest_data = reinterpret_cast<u8*>(dest.data());
|
||||
|
||||
deswizzle(params.stride, params.height, dest_data, params.addr, load_start, load_end);
|
||||
}
|
||||
}
|
||||
|
||||
ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data) {
|
||||
ClearValue result{};
|
||||
switch (aspect) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <span>
|
||||
#include "common/hash.h"
|
||||
#include "video_core/rasterizer_cache/pixel_format.h"
|
||||
#include "video_core/rasterizer_cache/types.h"
|
||||
@ -47,6 +48,14 @@ struct TextureCubeConfig {
|
||||
}
|
||||
};
|
||||
|
||||
class SurfaceParams;
|
||||
|
||||
void SwizzleTexture(const SurfaceParams& params, u32 flush_start, u32 flush_end,
|
||||
std::span<std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
void UnswizzleTexture(const SurfaceParams& params, u32 load_start, u32 load_end,
|
||||
std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
[[nodiscard]] ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data);
|
||||
|
||||
[[nodiscard]] Aspect ToAspect(SurfaceType type);
|
||||
|
@ -2,10 +2,10 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <bit>
|
||||
#include "common/assert.h"
|
||||
#include "common/color.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/math_util.h"
|
||||
#include "common/swap.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "video_core/regs_texturing.h"
|
||||
@ -222,4 +222,23 @@ TextureInfo TextureInfo::FromPicaRegister(const TexturingRegs::TextureConfig& co
|
||||
return info;
|
||||
}
|
||||
|
||||
void ConvertBGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest) {
|
||||
u32 j = 0;
|
||||
for (u32 i = 0; i < source.size(); i += 3) {
|
||||
dest[j] = source[i + 2];
|
||||
dest[j + 1] = source[i + 1];
|
||||
dest[j + 2] = source[i];
|
||||
dest[j + 3] = std::byte{0xFF};
|
||||
j += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertABGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest) {
|
||||
for (u32 i = 0; i < source.size(); i += 4) {
|
||||
const u32 abgr = *reinterpret_cast<const u32*>(source.data() + i);
|
||||
const u32 rgba = std::byteswap(abgr);
|
||||
std::memcpy(dest.data() + i, &rgba, 4);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Pica::Texture
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include "common/common_types.h"
|
||||
#include "common/vector_math.h"
|
||||
#include "video_core/regs_texturing.h"
|
||||
@ -55,4 +55,21 @@ Common::Vec4<u8> LookupTexture(const u8* source, unsigned int x, unsigned int y,
|
||||
Common::Vec4<u8> LookupTexelInTile(const u8* source, unsigned int x, unsigned int y,
|
||||
const TextureInfo& info, bool disable_alpha);
|
||||
|
||||
/**
|
||||
* Converts pixel data encoded in BGR format to RGBA
|
||||
*
|
||||
* @param source Span to the source pixel data
|
||||
* @param dest Span to the destination pixel data
|
||||
*/
|
||||
void ConvertBGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
|
||||
/**
|
||||
* Converts pixel data encoded in ABGR format to RGBA
|
||||
*
|
||||
* @param source Span to the source pixel data
|
||||
* @param dest Span to the destination pixel data
|
||||
*/
|
||||
void ConvertABGRToRGBA(std::span<const std::byte> source, std::span<std::byte> dest);
|
||||
|
||||
} // namespace Pica::Texture
|
||||
|
Reference in New Issue
Block a user