mirror of
https://github.com/encounter/aurora.git
synced 2026-07-09 18:19:33 -07:00
Migrate remaining GX functions to FIFO
This commit is contained in:
@@ -76,11 +76,11 @@ void GX2SetPolygonOffset(f32 mFrontOffset, f32 mFrontScale, f32 mBackOffset, f32
|
||||
}
|
||||
|
||||
void GXCreateFrameBuffer(u32 width, u32 height) {
|
||||
aurora::gx::fifo::drain();
|
||||
aurora::gfx::begin_offscreen(width, height);
|
||||
GX_WRITE_AURORA(GX_AURORA_BEGIN_OFFSCREEN);
|
||||
GX_WRITE_U32(width);
|
||||
GX_WRITE_U32(height);
|
||||
}
|
||||
|
||||
void GXRestoreFrameBuffer() {
|
||||
aurora::gx::fifo::drain();
|
||||
aurora::gfx::end_offscreen();
|
||||
GX_WRITE_AURORA(GX_AURORA_END_OFFSCREEN);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "gx.hpp"
|
||||
#include "__gx.h"
|
||||
|
||||
#include "../../gfx/depth_peek.hpp"
|
||||
|
||||
#include <dolphin/gx/GXAurora.h>
|
||||
#include <dolphin/gx/GXCpu2Efb.h>
|
||||
|
||||
void GXPeekZ(u16 x, u16 y, u32* z) {
|
||||
@@ -10,9 +12,9 @@ void GXPeekZ(u16 x, u16 y, u32* z) {
|
||||
if (aurora::gfx::depth_peek::read_latest(x, y, value)) {
|
||||
*z = value;
|
||||
} else {
|
||||
*z = g_gxState.clearDepth & 0x00ffffffu;
|
||||
*z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
aurora::gfx::depth_peek::request_snapshot();
|
||||
GX_WRITE_AURORA(GX_AURORA_REQUEST_DEPTH_SNAPSHOT);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "gx.hpp"
|
||||
#include "__gx.h"
|
||||
|
||||
#include "../../gx/command_processor.hpp"
|
||||
#include "../../gx/fifo.hpp"
|
||||
|
||||
#include <cstring>
|
||||
@@ -66,23 +65,4 @@ void GXCallDisplayList(const void* data, u32 nbytes) {
|
||||
// aurora::gx::fifo::process(static_cast<const u8*>(data), nbytes, true);
|
||||
}
|
||||
|
||||
void GXCallDisplayListLE(const void* data, u32 nbytes) {
|
||||
// Flush any pending dirty state before calling
|
||||
if (__gx->dirtyState != 0) {
|
||||
__GXSetDirtyState();
|
||||
}
|
||||
|
||||
// Flush pending primitives
|
||||
if (*reinterpret_cast<u32*>(&__gx->vNum) != 0) {
|
||||
__GXSendFlushPrim();
|
||||
}
|
||||
|
||||
// Drain the internal FIFO so that any pending CP register writes
|
||||
// (VCD, VAT, etc.) are processed into g_gxState before the display
|
||||
// list's draw commands reference them.
|
||||
aurora::gx::fifo::drain();
|
||||
|
||||
// Process the display list through the command processor (little-endian)
|
||||
aurora::gx::fifo::process(static_cast<const u8*>(data), nbytes, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,60 @@ aurora::Vec2<uint32_t> scale_copy_dst(u32 logicalWidth, u32 logicalHeight) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace aurora::gx {
|
||||
void copy_tex(const void* dest, GXBool clear) noexcept {
|
||||
const auto rect = map_logical_scissor(g_gxState.texCopySrc);
|
||||
const auto [dstWidth, dstHeight] = scale_copy_dst(g_gxState.texCopyDstWidth, g_gxState.texCopyDstHeight);
|
||||
const auto texCopyFmt = g_gxState.texCopyFmt;
|
||||
|
||||
const GXState::CopyTextureKey key{
|
||||
.dest = dest,
|
||||
.width = dstWidth,
|
||||
.height = dstHeight,
|
||||
.format = texCopyFmt,
|
||||
};
|
||||
auto it = g_gxState.copyTextureCache.find(key);
|
||||
if (it == g_gxState.copyTextureCache.end()) {
|
||||
gfx::TextureHandle handle;
|
||||
if (gfx::tex_copy_conv::needs_conversion(texCopyFmt)) {
|
||||
handle = gfx::new_conv_texture(dstWidth, dstHeight, texCopyFmt, "Copy Conv Texture");
|
||||
} else {
|
||||
// Configure the texture swizzle to use alpha 1.0 if targeting RGB565 or EFB doesn't have alpha
|
||||
const auto fmt = texCopyFmt == GX_TF_RGB565 || g_gxState.pixelFmt == GX_PF_RGB8_Z24 ||
|
||||
g_gxState.pixelFmt == GX_PF_RGB565_Z16
|
||||
? GX_TF_RGB565
|
||||
: GX_TF_RGBA8;
|
||||
handle = gfx::new_render_texture(dstWidth, dstHeight, fmt, "Resolved Texture");
|
||||
}
|
||||
it = g_gxState.copyTextureCache.emplace(key, GXState::CopyTextureRef{.handle = handle, .revision = 0}).first;
|
||||
}
|
||||
auto& handle = it->second;
|
||||
|
||||
if (g_gxState.alphaUpdate && g_gxState.dstAlpha != UINT32_MAX) {
|
||||
if (!clear) {
|
||||
// TODO: figure out the right behavior here.
|
||||
// should the copy have a specific alpha value but the EFB remains untouched?
|
||||
}
|
||||
// Overwrite alpha before resolving
|
||||
gfx::push_draw_command(gfx::clear::DrawData{
|
||||
.pipeline = gfx::pipeline_ref(gfx::clear::PipelineConfig{
|
||||
.clearColor = false,
|
||||
.clearAlpha = true,
|
||||
.clearDepth = false,
|
||||
}),
|
||||
.color = wgpu::Color{0.f, 0.f, 0.f, g_gxState.dstAlpha / 255.f},
|
||||
});
|
||||
}
|
||||
const auto clearColor = clear && g_gxState.colorUpdate;
|
||||
const auto clearAlpha = clear && g_gxState.alphaUpdate;
|
||||
const auto clearDepth = clear && g_gxState.depthUpdate;
|
||||
gfx::resolve_pass(handle.handle, rect, clearColor, clearAlpha, clearDepth, g_gxState.clearColor, clear_depth_value(),
|
||||
texCopyFmt);
|
||||
++handle.revision;
|
||||
g_gxState.copyTextures[dest] = handle;
|
||||
}
|
||||
} // namespace aurora::gx
|
||||
|
||||
extern "C" {
|
||||
GXRenderModeObj GXNtsc480IntDf = {
|
||||
VI_TVMODE_NTSC_INT,
|
||||
@@ -103,14 +157,22 @@ void GXAdjustForOverscan(GXRenderModeObj* rmin, GXRenderModeObj* rmout, u16 hor,
|
||||
|
||||
void GXSetDispCopySrc(u16 left, u16 top, u16 wd, u16 ht) {}
|
||||
|
||||
void GXSetTexCopySrc(u16 left, u16 top, u16 wd, u16 ht) { g_gxState.texCopySrc = {left, top, wd, ht}; }
|
||||
void GXSetTexCopySrc(u16 left, u16 top, u16 wd, u16 ht) {
|
||||
GX_WRITE_AURORA(GX_AURORA_LOAD_COPY_SRC);
|
||||
GX_WRITE_U32(left);
|
||||
GX_WRITE_U32(top);
|
||||
GX_WRITE_U32(wd);
|
||||
GX_WRITE_U32(ht);
|
||||
}
|
||||
|
||||
void GXSetDispCopyDst(u16 wd, u16 ht) {}
|
||||
|
||||
void GXSetTexCopyDst(u16 wd, u16 ht, GXTexFmt fmt, GXBool mipmap) {
|
||||
g_gxState.texCopyFmt = fmt;
|
||||
g_gxState.texCopyDstWidth = wd;
|
||||
g_gxState.texCopyDstHeight = ht;
|
||||
GX_WRITE_AURORA(GX_AURORA_LOAD_COPY_DST);
|
||||
GX_WRITE_U32(wd);
|
||||
GX_WRITE_U32(ht);
|
||||
GX_WRITE_U32(fmt);
|
||||
GX_WRITE_U8(mipmap != GX_FALSE);
|
||||
}
|
||||
|
||||
// TODO GXSetDispCopyFrame2Field
|
||||
@@ -148,57 +210,13 @@ void GXSetDispCopyGamma(GXGamma gamma) {}
|
||||
void GXCopyDisp(void* dest, GXBool clear) {}
|
||||
|
||||
void GXCopyTex(void* dest, GXBool clear) {
|
||||
aurora::gx::fifo::drain();
|
||||
GX_WRITE_AURORA(GX_AURORA_LOAD_COPY_DEST);
|
||||
GX_WRITE_U64(reinterpret_cast<u64>(dest));
|
||||
|
||||
const auto rect = aurora::gx::map_logical_scissor(g_gxState.texCopySrc);
|
||||
const auto [dstWidth, dstHeight] = scale_copy_dst(g_gxState.texCopyDstWidth, g_gxState.texCopyDstHeight);
|
||||
const auto texCopyFmt = g_gxState.texCopyFmt;
|
||||
|
||||
const aurora::gx::GXState::CopyTextureKey key{
|
||||
.dest = dest,
|
||||
.width = dstWidth,
|
||||
.height = dstHeight,
|
||||
.format = texCopyFmt,
|
||||
};
|
||||
auto it = g_gxState.copyTextureCache.find(key);
|
||||
if (it == g_gxState.copyTextureCache.end()) {
|
||||
aurora::gfx::TextureHandle handle;
|
||||
if (aurora::gfx::tex_copy_conv::needs_conversion(texCopyFmt)) {
|
||||
handle = aurora::gfx::new_conv_texture(dstWidth, dstHeight, texCopyFmt, "Copy Conv Texture");
|
||||
} else {
|
||||
// Configure the texture swizzle to use alpha 1.0 if targeting RGB565 or EFB doesn't have alpha
|
||||
const auto fmt = texCopyFmt == GX_TF_RGB565 || g_gxState.pixelFmt == GX_PF_RGB8_Z24 ||
|
||||
g_gxState.pixelFmt == GX_PF_RGB565_Z16
|
||||
? GX_TF_RGB565
|
||||
: GX_TF_RGBA8;
|
||||
handle = aurora::gfx::new_render_texture(dstWidth, dstHeight, fmt, "Resolved Texture");
|
||||
}
|
||||
it = g_gxState.copyTextureCache.emplace(key, aurora::gx::GXState::CopyTextureRef{.handle = handle, .revision = 0}).first;
|
||||
}
|
||||
auto& handle = it->second;
|
||||
|
||||
if (g_gxState.alphaUpdate && g_gxState.dstAlpha != UINT32_MAX) {
|
||||
if (!clear) {
|
||||
// TODO: figure out the right behavior here.
|
||||
// should the copy have a specific alpha value but the EFB remains untouched?
|
||||
}
|
||||
// Overwrite alpha before resolving
|
||||
aurora::gfx::push_draw_command(aurora::gfx::clear::DrawData{
|
||||
.pipeline = aurora::gfx::pipeline_ref(aurora::gfx::clear::PipelineConfig{
|
||||
.clearColor = false,
|
||||
.clearAlpha = true,
|
||||
.clearDepth = false,
|
||||
}),
|
||||
.color = wgpu::Color{0.f, 0.f, 0.f, g_gxState.dstAlpha / 255.f},
|
||||
});
|
||||
}
|
||||
const auto clearColor = clear && g_gxState.colorUpdate;
|
||||
const auto clearAlpha = clear && g_gxState.alphaUpdate;
|
||||
const auto clearDepth = clear && g_gxState.depthUpdate;
|
||||
aurora::gfx::resolve_pass(handle.handle, rect, clearColor, clearAlpha, clearDepth, g_gxState.clearColor,
|
||||
aurora::gx::clear_depth_value(), texCopyFmt);
|
||||
++handle.revision;
|
||||
g_gxState.copyTextures[dest] = handle;
|
||||
SET_REG_FIELD(0, __gx->cpTex, 1, 11, clear != GX_FALSE);
|
||||
SET_REG_FIELD(0, __gx->cpTex, 1, 14, 0);
|
||||
SET_REG_FIELD(0, __gx->cpTex, 8, 24, 0x52);
|
||||
GX_WRITE_RAS_REG(__gx->cpTex);
|
||||
}
|
||||
|
||||
// TODO GXGetYScaleFactor
|
||||
|
||||
@@ -71,6 +71,7 @@ GXFifoObj* GXInit(void* base, u32 size) {
|
||||
SET_REG_FIELD(0, __gx->cmode1, 8, 24, 0x42);
|
||||
SET_REG_FIELD(0, __gx->zmode, 8, 24, 0x40);
|
||||
SET_REG_FIELD(0, __gx->peCtrl, 8, 24, 0x43);
|
||||
SET_REG_FIELD(0, __gx->cpTex, 2, 7, 0);
|
||||
SET_REG_FIELD(0, __gx->IndTexScale0, 8, 24, 0x25);
|
||||
SET_REG_FIELD(0, __gx->IndTexScale1, 8, 24, 0x26);
|
||||
|
||||
|
||||
@@ -83,8 +83,7 @@
|
||||
GX_WRITE_U32(value); \
|
||||
} while (0)
|
||||
|
||||
// Shadow register struct - mirrors the hardware GX state
|
||||
// This is the subset of __GXData_struct needed for aurora's TARGET_PC emulation.
|
||||
// Shadow register struct
|
||||
struct __GXData_struct {
|
||||
u16 vNum; // vertex count for flush prim
|
||||
u16 bpSent; // BP register was sent (need flush prim before next draw)
|
||||
@@ -126,6 +125,7 @@ struct __GXData_struct {
|
||||
u32 cmode1; // destination alpha register
|
||||
u32 zmode; // Z-buffer mode register
|
||||
u32 peCtrl; // pixel engine control
|
||||
u32 cpTex; // copy texture trigger register
|
||||
|
||||
u32 genMode; // general mode (numTexGens, numChans, numTevStages, cullMode, numIndStages)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "command_processor.hpp"
|
||||
|
||||
#include "../gfx/common.hpp"
|
||||
#include "../gfx/depth_peek.hpp"
|
||||
#include "dolphin/gx/GXAurora.h"
|
||||
#include "gx.hpp"
|
||||
#include "gx_fmt.hpp"
|
||||
@@ -12,6 +13,7 @@
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
@@ -502,7 +504,7 @@ static void handle_bp(u32 value, bool bigEndian) {
|
||||
g_gxState.bpRegCache[0xFE] = 0x00FFFFFF;
|
||||
const u32 merged = (g_gxState.bpRegCache[regId] & ~ssMask) | (value & ssMask);
|
||||
value = (regId << 24) | (merged & 0x00FFFFFF);
|
||||
if (g_gxState.bpRegCache[regId] == value)
|
||||
if (g_gxState.bpRegCache[regId] == value && regId != 0x52)
|
||||
return;
|
||||
g_gxState.bpRegCache[regId] = value;
|
||||
}
|
||||
@@ -785,6 +787,17 @@ static void handle_bp(u32 value, bool bigEndian) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Texture copy
|
||||
case 0x52: {
|
||||
const bool clear = bp_get(value, 1, 11) != 0;
|
||||
if (bp_get(value, 1, 14) != 0) {
|
||||
Log.warn("STUB: display copy is not implemented");
|
||||
} else {
|
||||
copy_tex(g_gxState.texCopyDest, clear);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// TLUT load address / execute (0x64, 0x65)
|
||||
case 0x64:
|
||||
break;
|
||||
@@ -1808,6 +1821,41 @@ void handle_aurora(const u8* data, u32& pos, u32 size, bool bigEndian) {
|
||||
g_gxState.clamp = read_f32(data + pos, bigEndian);
|
||||
pos += 4;
|
||||
g_gxState.stateDirty = true;
|
||||
} else if (subCmd == GX_AURORA_LOAD_COPY_SRC) {
|
||||
CHECK(pos + 16 <= size, "GX_AURORA_LOAD_COPY_SRC read overrun");
|
||||
const int32_t left = static_cast<int32_t>(read_u32(data + pos, bigEndian));
|
||||
pos += 4;
|
||||
const int32_t top = static_cast<int32_t>(read_u32(data + pos, bigEndian));
|
||||
pos += 4;
|
||||
const int32_t width = static_cast<int32_t>(read_u32(data + pos, bigEndian));
|
||||
pos += 4;
|
||||
const int32_t height = static_cast<int32_t>(read_u32(data + pos, bigEndian));
|
||||
pos += 4;
|
||||
g_gxState.texCopySrc = {left, top, width, height};
|
||||
} else if (subCmd == GX_AURORA_LOAD_COPY_DST) {
|
||||
CHECK(pos + 13 <= size, "GX_AURORA_LOAD_COPY_DST read overrun");
|
||||
g_gxState.texCopyDstWidth = read_u32(data + pos, bigEndian);
|
||||
pos += 4;
|
||||
g_gxState.texCopyDstHeight = read_u32(data + pos, bigEndian);
|
||||
pos += 4;
|
||||
g_gxState.texCopyFmt = static_cast<GXTexFmt>(read_u32(data + pos, bigEndian));
|
||||
pos += 4;
|
||||
g_gxState.texCopyDstWide = true;
|
||||
} else if (subCmd == GX_AURORA_LOAD_COPY_DEST) {
|
||||
CHECK(pos + 8 <= size, "GX_AURORA_LOAD_COPY_DEST read overrun");
|
||||
g_gxState.texCopyDest = reinterpret_cast<const void*>(read_u64(data + pos, bigEndian));
|
||||
pos += 8;
|
||||
} else if (subCmd == GX_AURORA_REQUEST_DEPTH_SNAPSHOT) {
|
||||
gfx::depth_peek::request_snapshot();
|
||||
} else if (subCmd == GX_AURORA_BEGIN_OFFSCREEN) {
|
||||
CHECK(pos + 8 <= size, "GX_AURORA_BEGIN_OFFSCREEN read overrun");
|
||||
const u32 width = read_u32(data + pos, bigEndian);
|
||||
pos += 4;
|
||||
const u32 height = read_u32(data + pos, bigEndian);
|
||||
pos += 4;
|
||||
gfx::begin_offscreen(width, height);
|
||||
} else if (subCmd == GX_AURORA_END_OFFSCREEN) {
|
||||
gfx::end_offscreen();
|
||||
} else if (subCmd == GX_AURORA_DESTROY_TEXOBJ) {
|
||||
CHECK(pos + 4 <= size, "GX_AURORA_DESTROY_TEXOBJ read overrun");
|
||||
evict_texture_object(read_u32(data + pos, bigEndian));
|
||||
|
||||
+5
-2
@@ -345,8 +345,10 @@ struct GXState {
|
||||
std::array<AttrArray, MaxVtxAttr> arrays;
|
||||
gfx::ClipRect texCopySrc;
|
||||
GXTexFmt texCopyFmt;
|
||||
u16 texCopyDstWidth = 0;
|
||||
u16 texCopyDstHeight = 0;
|
||||
u32 texCopyDstWidth = 0;
|
||||
u32 texCopyDstHeight = 0;
|
||||
bool texCopyDstWide = false;
|
||||
const void* texCopyDest = nullptr;
|
||||
struct CopyTextureKey {
|
||||
const void* dest = nullptr;
|
||||
u32 width = 0;
|
||||
@@ -406,6 +408,7 @@ void set_logical_viewport(const gfx::Viewport& viewport) noexcept;
|
||||
void set_render_viewport(const gfx::Viewport& viewport) noexcept;
|
||||
void set_logical_scissor(const gfx::ClipRect& scissor) noexcept;
|
||||
void set_render_scissor(const gfx::ClipRect& scissor) noexcept;
|
||||
void copy_tex(const void* dest, GXBool clear) noexcept;
|
||||
const gfx::TextureBind& get_texture(GXTexMapID id) noexcept;
|
||||
void resolve_sampled_textures(const ShaderInfo& info) noexcept;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user