[jak2] WIP minimap (#2280)

Work in progress minimap. Known issues:
- "path finding" doesn't appear to work - it gets stuck forever in many
cases
- some nasty patches around timer-based code
- jak arrow blending issues
- would be nice to make it higher resolution

if the search is forced to terminate due to iteration/time limits, the
icon is not in the right place

![image](https://user-images.githubusercontent.com/48171810/221432792-678d6124-a6a6-4875-a91f-7eceedbfec98.png)
This commit is contained in:
water111
2023-02-27 19:51:14 -05:00
committed by GitHub
parent 1d0a5ade8d
commit 2c12a4e00b
14 changed files with 938 additions and 729 deletions
+9 -3
View File
@@ -1059,7 +1059,9 @@ goos::Object decompile_structure(const TypeSpec& type,
enum ByteStatus : u8 { ZERO_UNREAD, HAS_DATA_UNREAD, ZERO_READ, HAS_DATA_READ };
std::vector<int> field_status_per_byte;
for (int i = 0; i < byte_count; i++) {
auto& w = obj_words.at(i / 4);
// auto& w = obj_words.at(i / 4);
int b = (offset_location + i);
auto& w = words.at(label.target_segment).at(b / 4);
switch (w.kind()) {
case LinkedWord::TYPE_PTR:
case LinkedWord::PTR:
@@ -1068,7 +1070,7 @@ goos::Object decompile_structure(const TypeSpec& type,
field_status_per_byte.push_back(HAS_DATA_UNREAD);
break;
case LinkedWord::PLAIN_DATA: {
field_status_per_byte.push_back(w.get_byte(i % 4) ? HAS_DATA_UNREAD : ZERO_UNREAD);
field_status_per_byte.push_back(w.get_byte(b % 4) ? HAS_DATA_UNREAD : ZERO_UNREAD);
} break;
default:
throw std::runtime_error("Unsupported word in static data");
@@ -1209,7 +1211,11 @@ goos::Object decompile_structure(const TypeSpec& type,
}
std::vector<u8> bytes_out;
for (int byte_idx = field_start; byte_idx < field_end; byte_idx++) {
bytes_out.push_back(obj_words.at(byte_idx / 4).get_byte(byte_idx % 4));
int byte_idx_in_seg = byte_idx + label.offset - type_info->get_offset();
bytes_out.push_back(words.at(label.target_segment)
.at(byte_idx_in_seg / 4)
.get_byte(byte_idx_in_seg % 4));
// bytes_out.push_back(obj_words.at(byte_idx / 4).get_byte(byte_idx % 4));
}
// use more specific types for gif tags.
+1
View File
@@ -158,6 +158,7 @@ set(RUNTIME_SOURCE
graphics/opengl_renderer/opengl_utils.cpp
graphics/opengl_renderer/OpenGLRenderer.cpp
graphics/opengl_renderer/Profiler.cpp
graphics/opengl_renderer/ProgressRenderer.cpp
graphics/opengl_renderer/Shader.cpp
graphics/opengl_renderer/Shadow_PS2.cpp
graphics/opengl_renderer/ShadowRenderer.cpp
@@ -54,6 +54,15 @@ DirectRenderer::DirectRenderer(const std::string& name, int my_id, int batch_siz
sizeof(Vertex), //
(void*)offsetof(Vertex, tex_unit) // offset in array (why is this a pointer...)
);
glEnableVertexAttribArray(4);
glVertexAttribIPointer(
4, // location 4 in the shader
1, // 3 floats per vert
GL_UNSIGNED_BYTE, // floats
sizeof(Vertex), //
(void*)offsetof(Vertex, use_uv) // offset in array (why is this a pointer...)
);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
@@ -69,6 +78,7 @@ DirectRenderer::~DirectRenderer() {
void DirectRenderer::render(DmaFollower& dma,
SharedRenderState* render_state,
ScopedProfilerNode& prof) {
pre_render();
// if we're rendering from a bucket, we should start off we a totally reset state:
reset_state();
setup_common_state(render_state);
@@ -91,6 +101,8 @@ void DirectRenderer::render(DmaFollower& dma,
if (m_enabled) {
flush_pending(render_state, prof);
}
post_render();
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
void DirectRenderer::reset_state() {
@@ -135,6 +147,7 @@ void DirectRenderer::draw_debug_window() {
ImGui::Text(" tex1: %d", m_stats.flush_from_tex_1);
ImGui::Text(" zbuf: %d", m_stats.flush_from_zbuf);
ImGui::Text(" test: %d", m_stats.flush_from_test);
ImGui::Text(" ta0: %d", m_stats.flush_from_ta0);
ImGui::Text(" alph: %d", m_stats.flush_from_alpha);
ImGui::Text(" clmp: %d", m_stats.flush_from_clamp);
ImGui::Text(" prim: %d", m_stats.flush_from_prim);
@@ -251,6 +264,7 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
case GsTest::AlphaTest::ALWAYS:
break;
case GsTest::AlphaTest::GEQUAL:
case GsTest::AlphaTest::GREATER: // todo
alpha_reject = m_test_state.aref / 128.f;
break;
case GsTest::AlphaTest::NEVER:
@@ -274,6 +288,12 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
"fog_color"),
render_state->fog_color[0] / 255.f, render_state->fog_color[1] / 255.f,
render_state->fog_color[2] / 255.f, render_state->fog_intensity / 255);
glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
"offscreen_mode"),
m_offscreen_mode);
glUniform1f(
glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(), "ta0"),
state.ta0 / 255.f);
} else {
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
@@ -359,6 +379,7 @@ void DirectRenderer::update_gl_blend() {
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
} else if (state.a == GsAlpha::BlendMode::SOURCE &&
state.b == GsAlpha::BlendMode::ZERO_OR_FIXED &&
state.c == GsAlpha::BlendMode::SOURCE && state.d == GsAlpha::BlendMode::DEST) {
@@ -442,6 +463,12 @@ void DirectRenderer::update_gl_test() {
} else {
glDepthMask(GL_FALSE);
}
if (state.write_rgb) {
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
} else {
glColorMaski(0, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
}
}
void DirectRenderer::setup_common_state(SharedRenderState* /*render_state*/) {
@@ -658,7 +685,7 @@ void DirectRenderer::handle_ad(const u8* data,
handle_tex1_1(value);
break;
case GsRegisterAddress::TEXA:
handle_texa(value);
handle_texa(value, render_state, prof);
break;
case GsRegisterAddress::TEXCLUT:
// TODO
@@ -679,6 +706,7 @@ void DirectRenderer::handle_ad(const u8* data,
case GsRegisterAddress::TEXFLUSH:
break;
case GsRegisterAddress::FRAME_1:
handle_frame(value, render_state, prof);
break;
case GsRegisterAddress::RGBAQ:
// shadow scissor does this?
@@ -690,11 +718,28 @@ void DirectRenderer::handle_ad(const u8* data,
memcpy(&m_prim_building.Q, data + 4, 4);
}
break;
case GsRegisterAddress::SCISSOR_1:
// fmt::print("ignoring scissor\n");
break;
case GsRegisterAddress::XYOFFSET_1:
ASSERT(render_state->version == GameVersion::Jak2); // hardcoded jak 2 scissor vals in handle
handle_xyoffset(value);
break;
default:
ASSERT_MSG(false, fmt::format("Address {} is not supported", register_address_name(addr)));
}
}
void DirectRenderer::handle_frame(u64, SharedRenderState*, ScopedProfilerNode&) {}
void DirectRenderer::handle_xyoffset(u64 val) {
GsXYOffset xyo(val);
// :ofx #x7000 :ofy #x7300
float scale = -65536;
m_prim_buffer.x_off = scale * ((s32)xyo.ofx() - 0x7000) / float(UINT32_MAX);
m_prim_buffer.y_off = scale * ((s32)xyo.ofy() - 0x7300) / float(UINT32_MAX);
}
void DirectRenderer::handle_tex1_1(u64 val) {
GsTex1 reg(val);
// for now, we aren't going to handle mipmapping. I don't think it's used with direct.
@@ -750,17 +795,6 @@ void DirectRenderer::handle_tex0_1(u64 val) {
// csm: assume they got it right
}
void DirectRenderer::handle_texa(u64 val) {
GsTexa reg(val);
// rgba16 isn't used so this doesn't matter?
// but they use sane defaults anyway
ASSERT(reg.ta0() == 0);
ASSERT(reg.ta1() == 0x80); // note: check rgba16_to_rgba32 if this changes.
ASSERT(reg.aem() == false);
}
void DirectRenderer::handle_st_packed(const u8* data) {
memcpy(&m_prim_building.st_reg.x(), data + 0, 4);
memcpy(&m_prim_building.st_reg.y(), data + 4, 4);
@@ -773,7 +807,7 @@ void DirectRenderer::handle_uv_packed(const u8* data) {
memcpy(&v, data + 4, 4);
m_prim_building.st_reg.x() = u;
m_prim_building.st_reg.y() = v;
m_prim_building.Q = 16.f;
m_prim_building.Q = 1;
}
void DirectRenderer::handle_rgbaq_packed(const u8* data) {
@@ -852,7 +886,26 @@ void DirectRenderer::handle_test1(u64 val,
m_prim_gl_state_needs_gl_update = true;
}
}
void DirectRenderer::handle_texa(u64 val,
SharedRenderState* render_state,
ScopedProfilerNode& prof) {
GsTexa reg(val);
// rgba16 isn't used so this doesn't matter?
// but they use sane defaults anyway
// ASSERT(reg.ta0() == 0); TODO
if (m_prim_gl_state.ta0 != reg.ta0()) {
m_stats.flush_from_ta0++;
flush_pending(render_state, prof);
m_prim_gl_state.ta0 = reg.ta0();
m_test_state_needs_gl_update = true;
m_prim_gl_state_needs_gl_update = true;
m_blend_state_needs_gl_update = true;
}
ASSERT(reg.ta1() == 0x80); // note: check rgba16_to_rgba32 if this changes.
ASSERT(reg.aem() == false);
}
void DirectRenderer::handle_alpha1(u64 val,
SharedRenderState* render_state,
ScopedProfilerNode& prof) {
@@ -965,6 +1018,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
bool tcc = m_buffered_tex_state[tex_unit].tcc;
bool decal = m_buffered_tex_state[tex_unit].decal;
bool fge = m_prim_gl_state.fogging_enable;
bool use_uv = m_prim_gl_state.use_uv;
switch (m_prim_building.kind) {
case GsPrim::Kind::SPRITE: {
@@ -990,12 +1044,12 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
auto& corner3_rgba = corner2_rgba;
auto& corner4_rgba = corner2_rgba;
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge);
m_prim_buffer.push(corner3_rgba, corner3_vert, corner3_stq, 0, tcc, decal, fge);
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge);
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge);
m_prim_buffer.push(corner4_rgba, corner4_vert, corner4_stq, 0, tcc, decal, fge);
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge);
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge, use_uv);
m_prim_buffer.push(corner3_rgba, corner3_vert, corner3_stq, 0, tcc, decal, fge, use_uv);
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge, use_uv);
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge, use_uv);
m_prim_buffer.push(corner4_rgba, corner4_vert, corner4_stq, 0, tcc, decal, fge, use_uv);
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge, use_uv);
m_prim_building.building_idx = 0;
}
} break;
@@ -1011,7 +1065,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
if (advance) {
for (int i = 0; i < 3; i++) {
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge, use_uv);
}
}
}
@@ -1023,7 +1077,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
m_prim_building.building_idx = 0;
for (int i = 0; i < 3; i++) {
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge, use_uv);
}
}
break;
@@ -1039,7 +1093,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
}
for (int i = 0; i < 3; i++) {
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge, use_uv);
}
}
} break;
@@ -1064,13 +1118,13 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
math::Vector<u32, 4> di{d.x(), d.y(), d.z(), 0};
// ACB:
m_prim_buffer.push(m_prim_building.building_rgba[0], ai, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ai, {}, 0, false, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false, false);
// b c d
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], di, {}, 0, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false, false);
m_prim_buffer.push(m_prim_building.building_rgba[1], di, {}, 0, false, false, false, false);
//
m_prim_building.building_idx = 0;
@@ -1142,11 +1196,14 @@ void DirectRenderer::PrimitiveBuffer::push(const math::Vector<u8, 4>& rgba,
int unit,
bool tcc,
bool decal,
bool fog_enable) {
bool fog_enable,
bool use_uv) {
auto& v = vertices[vert_count];
v.rgba = rgba;
v.xyzf[0] = (float)vert[0] / (float)UINT32_MAX;
v.xyzf[0] += x_off;
v.xyzf[1] = (float)vert[1] / (float)UINT32_MAX;
v.xyzf[1] += y_off;
v.xyzf[2] = (float)vert[2] / (float)0xffffff;
v.xyzf[3] = (float)vert[3];
v.stq = st;
@@ -1154,5 +1211,6 @@ void DirectRenderer::PrimitiveBuffer::push(const math::Vector<u8, 4>& rgba,
v.tcc = tcc;
v.decal = decal;
v.fog_enable = fog_enable;
v.use_uv = use_uv;
vert_count++;
}
+29 -23
View File
@@ -23,7 +23,8 @@ class DirectRenderer : public BucketRenderer {
DirectRenderer(const std::string& name, int my_id, int batch_size);
~DirectRenderer();
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
virtual void pre_render() {}
virtual void post_render() {}
/*!
* Render directly from _VIF_ data.
* You can optionally provide two vif tags that come in front of data.
@@ -66,22 +67,9 @@ class DirectRenderer : public BucketRenderer {
}
void set_mipmap(bool en) { m_debug_state.disable_mipmap = !en; }
private:
void handle_ad(const u8* data, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_zbuf1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_test1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_alpha1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_pabe(u64 val);
void handle_clamp1(u64 val);
void handle_prim(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_prim_packed(const u8* data,
SharedRenderState* render_state,
ScopedProfilerNode& prof);
void handle_rgbaq(u64 val);
void handle_xyzf2(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_ad(const u8* data, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_st_packed(const u8* data);
void handle_uv_packed(const u8* data);
void handle_rgbaq_packed(const u8* data);
void handle_xyzf2_packed(const u8* data,
SharedRenderState* render_state,
@@ -89,11 +77,25 @@ class DirectRenderer : public BucketRenderer {
void handle_xyz2_packed(const u8* data,
SharedRenderState* render_state,
ScopedProfilerNode& prof);
void handle_prim_packed(const u8* data,
SharedRenderState* render_state,
ScopedProfilerNode& prof);
void handle_tex0_1_packed(const u8* data);
void handle_uv_packed(const u8* data);
void handle_rgbaq(u64 val);
void handle_xyzf2(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
protected:
virtual void handle_frame(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_zbuf1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_test1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_alpha1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_pabe(u64 val);
void handle_clamp1(u64 val);
void handle_tex0_1(u64 val);
void handle_tex1_1(u64 val);
void handle_texa(u64 val);
void handle_texa(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_xyoffset(u64 val);
void handle_xyzf2_common(u32 x,
u32 y,
u32 z,
@@ -106,6 +108,7 @@ class DirectRenderer : public BucketRenderer {
void update_gl_blend();
void update_gl_test();
void update_gl_texture(SharedRenderState* render_state, int unit);
bool m_offscreen_mode = false;
struct TestState {
void from_register(GsTest reg);
@@ -120,7 +123,7 @@ class DirectRenderer : public BucketRenderer {
bool datm = false;
bool zte = true;
GsTest::ZTest ztst = GsTest::ZTest::GEQUAL;
bool write_rgb = true;
bool depth_writes = true;
} m_test_state;
@@ -151,6 +154,7 @@ class DirectRenderer : public BucketRenderer {
bool use_uv = false; // todo: might not require a gl state change
bool ctxt = false; // do they ever use ctxt2?
bool fix = false; // what does this even do?
u32 ta0 = 0;
} m_prim_gl_state;
static constexpr int TEXTURE_STATE_COUNT = 1;
@@ -161,7 +165,6 @@ class DirectRenderer : public BucketRenderer {
bool using_mt4hh = false;
bool tcc = false;
bool decal = false;
bool enable_tex_filt = true;
struct ClampState {
@@ -206,7 +209,6 @@ class DirectRenderer : public BucketRenderer {
int tri_strip_startup = 0;
float Q = 1.0;
} m_prim_building;
struct Vertex {
@@ -217,7 +219,8 @@ class DirectRenderer : public BucketRenderer {
u8 tcc;
u8 decal;
u8 fog_enable;
math::Vector<u8, 28> pad;
u8 use_uv;
math::Vector<u8, 27> pad;
};
static_assert(sizeof(Vertex) == 64);
static_assert(offsetof(Vertex, tex_unit) == 32);
@@ -227,7 +230,8 @@ class DirectRenderer : public BucketRenderer {
std::vector<Vertex> vertices;
int vert_count = 0;
int max_verts = 0;
float x_off = 0;
float y_off = 0;
// leave 6 free on the end so we always have room to flush one last primitive.
bool is_full() { return max_verts < (vert_count + 18); }
void push(const math::Vector<u8, 4>& rgba,
@@ -236,7 +240,8 @@ class DirectRenderer : public BucketRenderer {
int unit,
bool tcc,
bool decal,
bool fog_enable);
bool fog_enable,
bool use_uv);
} m_prim_buffer;
struct {
@@ -264,6 +269,7 @@ class DirectRenderer : public BucketRenderer {
int flush_from_tex_1 = 0;
int flush_from_zbuf = 0;
int flush_from_test = 0;
int flush_from_ta0 = 0;
int flush_from_alpha = 0;
int flush_from_clamp = 0;
int flush_from_prim = 0;
@@ -7,6 +7,7 @@
#include "game/graphics/opengl_renderer/DirectRenderer.h"
#include "game/graphics/opengl_renderer/EyeRenderer.h"
#include "game/graphics/opengl_renderer/LightningRenderer.h"
#include "game/graphics/opengl_renderer/ProgressRenderer.h"
#include "game/graphics/opengl_renderer/ShadowRenderer.h"
#include "game/graphics/opengl_renderer/SkyRenderer.h"
#include "game/graphics/opengl_renderer/TextureUploadHandler.h"
@@ -310,8 +311,8 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
init_bucket_renderer<TextureUploadHandler>("tex-all-map", BucketCategory::TEX,
BucketId::TEX_ALL_MAP);
// 320
init_bucket_renderer<DirectRenderer>("progress", BucketCategory::OTHER, BucketId::PROGRESS,
0x8000);
init_bucket_renderer<ProgressRenderer>("progress", BucketCategory::OTHER, BucketId::PROGRESS,
0x8000);
init_bucket_renderer<DirectRenderer>("screen-filter", BucketCategory::OTHER,
BucketId::SCREEN_FILTER, 256);
init_bucket_renderer<DirectRenderer>("bucket-322", BucketCategory::OTHER, BucketId::BUCKET_322,
@@ -0,0 +1,64 @@
#include "ProgressRenderer.h"
ProgressRenderer::ProgressRenderer(const std::string& name, int my_id, int batch_size)
: DirectRenderer(name, my_id, batch_size),
m_minimap_fb(kMinimapWidth, kMinimapHeight, GL_UNSIGNED_INT_8_8_8_8_REV) {}
void ProgressRenderer::pre_render() {
m_current_fbp = kScreenFbp;
}
void ProgressRenderer::post_render() {
m_fb_ctxt.reset();
m_offscreen_mode = false;
}
void ProgressRenderer::init_textures(TexturePool& texture_pool, GameVersion) {
TextureInput in;
in.gpu_texture = m_minimap_fb.texture();
in.w = kMinimapWidth;
in.h = kMinimapHeight;
in.debug_page_name = "PC-MAP";
in.debug_name = "map";
in.id = texture_pool.allocate_pc_port_texture();
m_minimap_gpu_tex = texture_pool.give_texture_and_load_to_vram(in, kMinimapVramAddr);
}
void ProgressRenderer::handle_frame(u64 val,
SharedRenderState* render_state,
ScopedProfilerNode& prof) {
GsFrame f(val);
u32 fbp = f.fbp();
bool flushed = false;
if (fbp != m_current_fbp) {
flush_pending(render_state, prof);
flushed = true;
m_prim_gl_state_needs_gl_update = true;
m_current_fbp = fbp;
switch (f.fbp()) {
case kScreenFbp: // 408
m_fb_ctxt.reset();
m_offscreen_mode = false;
break;
case kMinimapFbp: // 126
m_fb_ctxt.emplace(m_minimap_fb);
m_offscreen_mode = true;
break;
default:
fmt::print("Unknown fbp in ProgressRenderer: {}\n", f.fbp());
ASSERT(false);
}
}
bool write_rgb = f.fbmsk() != 0xffffff;
if (write_rgb != m_test_state.write_rgb) {
if (!flushed) {
m_stats.flush_from_test++;
flush_pending(render_state, prof);
}
m_test_state.write_rgb = write_rgb;
m_test_state_needs_gl_update = true;
m_prim_gl_state_needs_gl_update = true;
}
}
@@ -0,0 +1,28 @@
#pragma once
#include "game/graphics/opengl_renderer/BucketRenderer.h"
#include "game/graphics/opengl_renderer/DirectRenderer.h"
#include "game/graphics/opengl_renderer/opengl_utils.h"
/*!
* Renderer for the "Progress Bucket" of Jak 2.
*/
class ProgressRenderer : public DirectRenderer {
public:
static constexpr int kMinimapVramAddr = 4032;
static constexpr int kMinimapWidth = 128;
static constexpr int kMinimapHeight = 128;
static constexpr int kScreenFbp = 408;
static constexpr int kMinimapFbp = 126;
ProgressRenderer(const std::string& name, int my_id, int batch_size);
void init_textures(TexturePool& texture_pool, GameVersion) override;
void handle_frame(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
void pre_render() override;
void post_render() override;
private:
GpuTexture* m_minimap_gpu_tex = nullptr;
FramebufferTexturePair m_minimap_fb;
std::optional<FramebufferTexturePairContext> m_fb_ctxt;
u32 m_current_fbp = kScreenFbp;
};
@@ -4,10 +4,12 @@ out vec4 color;
in vec4 fragment_color;
in vec3 tex_coord;
in flat uint use_uv;
uniform float alpha_reject;
uniform float color_mult;
uniform float alpha_mult;
uniform float alpha_sub;
uniform float ta0;
uniform vec4 fog_color;
@@ -41,10 +43,37 @@ vec4 sample_tex(vec2 coord, uint unit) {
}
}
vec4 sample_tex_px(vec2 coordf, uint unit) {
ivec2 coord;
coord.x = int(coordf.x / 16);
coord.y = int(coordf.y / 16);
switch (unit) {
case 0: return texelFetch(tex_T0, coord, 0);
case 1: return texelFetch(tex_T1, coord, 0);
case 2: return texelFetch(tex_T2, coord, 0);
case 3: return texelFetch(tex_T3, coord, 0);
case 4: return texelFetch(tex_T4, coord, 0);
case 5: return texelFetch(tex_T5, coord, 0);
case 6: return texelFetch(tex_T6, coord, 0);
case 7: return texelFetch(tex_T7, coord, 0);
case 8: return texelFetch(tex_T8, coord, 0);
case 9: return texelFetch(tex_T9, coord, 0);
default : return vec4(1.0, 0, 1.0, 1.0);
}
}
void main() {
vec4 T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
vec4 T0;
if (use_uv == 1) {
T0 = sample_tex_px(tex_coord.xy, tex_info.x);
} else {
T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
}
// y is tcc
// z is decal
if (T0.w == 0) {
T0.w = ta0;
}
if (tex_info.y == 0) {
if (tex_info.z == 0) {
@@ -10,14 +10,23 @@ out float fog;
// putting all texture info stuff here so it's easier to copy-paste
layout (location = 3) in uvec4 tex_info_in;
layout (location = 4) in uint use_uv_in;
out flat uvec4 tex_info;
out flat uint use_uv;
uniform int offscreen_mode;
void main() {
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32 * HEIGHT_SCALE, position_in.z * 2 - 1., 1.0);
// scissoring area adjust
gl_Position.y *= SCISSOR_ADJUST;
if (offscreen_mode == 1) {
gl_Position = vec4((position_in.x - 0.453125) * 64., (position_in.y - 0.5 + (2.25 / 64)) * 64, position_in.z * 2 - 1., 1.0);
} else {
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32 * HEIGHT_SCALE, position_in.z * 2 - 1., 1.0);
// scissoring area adjust
gl_Position.y *= SCISSOR_ADJUST;
}
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w * 2.);
tex_coord = tex_coord_in;
tex_info = tex_info_in;
fog = 255 - position_in.w;
use_uv = use_uv_in;
}
+1 -1
View File
@@ -7,7 +7,7 @@
;; DECOMP BEGINS
(defglobalconstant SKIP_MINIMAP_DRAW #t)
(defglobalconstant SKIP_MINIMAP_DRAW #f)
;; WARN: Failed store: (s.w! (+ v1-35 8) 0) at op 135
;; WARN: Failed store: (s.w! (+ v1-35 12) 0) at op 136
+2
View File
@@ -990,6 +990,8 @@
)
)
)
;; added in PC port: they timed stuff, we just allow it to run a fixed number of iterations.
(+! v1-1 100)
(.mfc0 v1-1 Count)
)
)
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -751,7 +751,11 @@
(let ((v0-0 (the-as int (-> obj mode))))
0
(.mfc0 v1-1 Count)
(while (and (= v0-0 1) (< (the-as uint v1-1) (the-as uint arg0)))
(while (and (= v0-0 1)
;; changed in PC port: they used to abort early if searching takes too long
;; it is fast enough on PC that we don't care.
;; (< (the-as uint v1-1) (the-as uint arg0)) HACK
)
(set! v0-0 (do-some-work obj))
(.mfc0 v1-1 Count)
)
File diff suppressed because it is too large Load Diff