mirror of
https://github.com/encounter/aurora.git
synced 2026-07-09 18:19:33 -07:00
139 lines
6.0 KiB
C++
139 lines
6.0 KiB
C++
#pragma once
|
|
#include <dolphin/gx.h>
|
|
|
|
#include <utility>
|
|
|
|
#include "common.hpp"
|
|
|
|
namespace aurora::gfx {
|
|
struct TextureUpload {
|
|
wgpu::TexelCopyBufferLayout layout;
|
|
wgpu::TexelCopyTextureInfo tex;
|
|
wgpu::Extent3D size;
|
|
wgpu::Buffer buffer;
|
|
|
|
TextureUpload(wgpu::TexelCopyBufferLayout layout, wgpu::TexelCopyTextureInfo tex, wgpu::Extent3D size) noexcept
|
|
: layout(layout), tex(std::move(tex)), size(size) {}
|
|
TextureUpload(wgpu::TexelCopyBufferLayout layout, wgpu::TexelCopyTextureInfo tex, wgpu::Extent3D size,
|
|
wgpu::Buffer buffer) noexcept
|
|
: layout(layout), tex(std::move(tex)), size(size), buffer(std::move(buffer)) {}
|
|
};
|
|
void queue_texture_upload(TextureUpload upload);
|
|
void queue_texture_upload_data(const uint8_t* data, size_t length, uint32_t bytesPerRow, uint32_t rowsPerImage,
|
|
wgpu::TexelCopyTextureInfo tex, wgpu::Extent3D size);
|
|
|
|
struct TextureFormatInfo {
|
|
uint8_t blockWidth;
|
|
uint8_t blockHeight;
|
|
uint8_t blockSize;
|
|
bool compressed;
|
|
};
|
|
TextureFormatInfo format_info(wgpu::TextureFormat format) noexcept;
|
|
uint64_t calc_texture_size(wgpu::TextureFormat format, uint32_t width, uint32_t height, uint32_t mips) noexcept;
|
|
bool is_block_aligned(wgpu::TextureFormat format, uint32_t width, uint32_t height) noexcept;
|
|
|
|
constexpr u32 InvalidTextureFormat = -1;
|
|
struct TextureRef {
|
|
wgpu::Texture texture;
|
|
wgpu::TextureView sampleTextureView;
|
|
wgpu::TextureView attachmentTextureView;
|
|
wgpu::Extent3D size;
|
|
wgpu::TextureFormat format;
|
|
uint32_t mipCount;
|
|
u32 gxFormat;
|
|
bool hasArbitraryMips = false;
|
|
bool isReplacement = false;
|
|
|
|
TextureRef(wgpu::Texture texture, wgpu::TextureView sampleTextureView, wgpu::TextureView attachmentTextureView,
|
|
wgpu::Extent3D size, wgpu::TextureFormat format, uint32_t mipCount, u32 gxFormat)
|
|
: texture(std::move(texture))
|
|
, sampleTextureView(std::move(sampleTextureView))
|
|
, attachmentTextureView(std::move(attachmentTextureView))
|
|
, size(size)
|
|
, format(format)
|
|
, mipCount(mipCount)
|
|
, gxFormat(gxFormat) {}
|
|
};
|
|
|
|
TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mips, u32 gxFormat,
|
|
ArrayRef<uint8_t> data, bool tlut, const char* label) noexcept;
|
|
TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, u32 gxFormat,
|
|
const char* label) noexcept;
|
|
TextureHandle new_render_texture(uint32_t width, uint32_t height, u32 gxFormat, const char* label) noexcept;
|
|
TextureHandle new_conv_texture(uint32_t width, uint32_t height, u32 gxFormat, const char* label) noexcept;
|
|
void write_texture(TextureRef& ref, ArrayRef<uint8_t> data) noexcept;
|
|
}; // namespace aurora::gfx
|
|
|
|
struct GXTexObj_ {
|
|
u32 mode0 = 0;
|
|
u32 mode1 = 0;
|
|
u32 image0 = UINT32_MAX;
|
|
u32 image3 = 0;
|
|
const void* userData = nullptr;
|
|
const void* data = nullptr;
|
|
u32 mWidth = 0;
|
|
u32 mHeight = 0;
|
|
u32 mFormat = aurora::gfx::InvalidTextureFormat;
|
|
GXTlut tlut = GX_TLUT0;
|
|
u32 texObjId = 0;
|
|
u32 texDataVersion = 0;
|
|
u8 flags = 0;
|
|
|
|
static constexpr u32 get_bits(u32 reg, u32 size, u32 shift) noexcept { return (reg >> shift) & ((1u << size) - 1); }
|
|
|
|
u32 width() const noexcept { return mWidth != 0 ? mWidth : get_bits(image0, 10, 0) + 1 & 0x3FF; }
|
|
u32 height() const noexcept { return mHeight != 0 ? mHeight : get_bits(image0, 10, 10) + 1 & 0x3FF; }
|
|
u32 raw_format() const noexcept { return get_bits(image0, 4, 20); }
|
|
u32 format() const noexcept { return mFormat != aurora::gfx::InvalidTextureFormat ? mFormat : raw_format(); }
|
|
GXTexWrapMode wrap_s() const noexcept { return static_cast<GXTexWrapMode>(get_bits(mode0, 2, 0)); }
|
|
GXTexWrapMode wrap_t() const noexcept { return static_cast<GXTexWrapMode>(get_bits(mode0, 2, 2)); }
|
|
GXTexFilter min_filter() const noexcept {
|
|
constexpr GXTexFilter kHwToGxFilter[8] = {
|
|
GX_NEAR, GX_NEAR_MIP_NEAR, GX_LIN_MIP_NEAR, GX_NEAR, GX_LINEAR, GX_NEAR_MIP_LIN, GX_LIN_MIP_LIN, GX_NEAR,
|
|
};
|
|
return kHwToGxFilter[get_bits(mode0, 3, 5)];
|
|
}
|
|
GXTexFilter mag_filter() const noexcept { return get_bits(mode0, 1, 4) != 0 ? GX_LINEAR : GX_NEAR; }
|
|
GXBool has_mips() const noexcept { return (flags & 1u) != 0 ? GX_TRUE : GX_FALSE; }
|
|
u32 mip_count() const noexcept { return has_mips() ? std::max<u32>(static_cast<u32>(max_lod()) + 1, 1u) : 1; }
|
|
GXBool do_edge_lod() const noexcept { return get_bits(mode0, 1, 8) == 0 ? GX_TRUE : GX_FALSE; }
|
|
float lod_bias() const noexcept { return static_cast<float>(static_cast<int8_t>(get_bits(mode0, 8, 9))) / 32.0f; }
|
|
GXAnisotropy max_aniso() const noexcept { return static_cast<GXAnisotropy>(get_bits(mode0, 2, 19)); }
|
|
GXBool bias_clamp() const noexcept { return get_bits(mode0, 1, 21) != 0 ? GX_TRUE : GX_FALSE; }
|
|
float min_lod() const noexcept { return static_cast<float>(get_bits(mode1, 8, 0)) / 16.0f; }
|
|
float max_lod() const noexcept { return static_cast<float>(get_bits(mode1, 8, 8)) / 16.0f; }
|
|
|
|
// Custom flag for texture caching
|
|
bool no_cache() const noexcept { return (flags & 0x80) != 0; }
|
|
void set_no_cache(bool value) noexcept { flags = value ? flags | 0x80 : flags & ~0x80; }
|
|
};
|
|
static_assert(sizeof(GXTexObj_) <= sizeof(GXTexObj), "GXTexObj too small!");
|
|
struct GXTlutObj_ {
|
|
u32 tlut = 0;
|
|
u32 loadTlut0 = 0;
|
|
u16 numEntries = 0;
|
|
const void* data = nullptr;
|
|
GXTlutFmt format = GX_TL_IA8;
|
|
u32 tlutObjId = 0;
|
|
u32 tlutDataVersion = 0;
|
|
u8 flags = 0;
|
|
|
|
// Custom flag for texture caching
|
|
bool no_cache() const noexcept { return (flags & 0x80) != 0; }
|
|
void set_no_cache(bool value) noexcept { flags = value ? flags | 0x80 : flags & ~0x80; }
|
|
};
|
|
static_assert(sizeof(GXTlutObj_) <= sizeof(GXTlutObj), "GXTlutObj too small!");
|
|
|
|
namespace aurora::gfx {
|
|
struct TextureBind {
|
|
TextureHandle ref;
|
|
GXTexObj_ texObj;
|
|
|
|
TextureBind() noexcept = default;
|
|
TextureBind(const GXTexObj_& obj, TextureHandle handle) noexcept : ref(std::move(handle)), texObj(obj) {}
|
|
void reset() noexcept { ref.reset(); }
|
|
[[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept;
|
|
operator bool() const noexcept { return ref.operator bool(); }
|
|
};
|
|
} // namespace aurora::gfx
|