mirror of
https://github.com/open-goal/jak-project
synced 2026-07-09 14:55:51 -04:00
fix merge issues
This commit is contained in:
@@ -106,6 +106,7 @@ int InitMainDisplay(int width, int height, const char* title, GfxSettings& setti
|
||||
return 1;
|
||||
}
|
||||
set_main_display(display);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KillDisplay(std::shared_ptr<GfxDisplay> display) {
|
||||
@@ -117,7 +118,7 @@ void KillDisplay(std::shared_ptr<GfxDisplay> display) {
|
||||
|
||||
if (GetMainDisplay() == display) {
|
||||
// killing the main display, kill all children displays too!
|
||||
for (int i = 1; i < g_displays.size(); ++i) {
|
||||
for (size_t i = 1; i < g_displays.size(); ++i) {
|
||||
KillDisplay(g_displays.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
+62
-76
@@ -17,88 +17,74 @@ std::string DmaTag::print() {
|
||||
std::string VifCode::print() {
|
||||
std::string result;
|
||||
|
||||
bool special_kind = false;
|
||||
switch (kind) {
|
||||
// case Kind::NOP:
|
||||
// result = "NOP";
|
||||
// break;
|
||||
// case Kind::STCYCL:
|
||||
// result = "STCYCL";
|
||||
// break;
|
||||
// case Kind::OFFSET:
|
||||
// result = "OFFSET";
|
||||
// break;
|
||||
// case Kind::BASE:
|
||||
// result = "BASE";
|
||||
// break;
|
||||
// case Kind::ITOP:
|
||||
// result = "ITOP";
|
||||
// break;
|
||||
// case Kind::STMOD:
|
||||
// result = "STMOD";
|
||||
// break;
|
||||
// case Kind::MSK3PATH:
|
||||
// result = "MSK3PATH";
|
||||
// break;
|
||||
// case Kind::MARK:
|
||||
// result = "MARK";
|
||||
// break;
|
||||
// case Kind::FLUSHE:
|
||||
// result = "FLUSHE";
|
||||
// break;
|
||||
// case Kind::FLUSH:
|
||||
// result = "FLUSH";
|
||||
// break;
|
||||
//
|
||||
// case Kind::FLUSHA:
|
||||
// result = "FLUSHA";
|
||||
// break;
|
||||
// case Kind::MSCAL:
|
||||
// result = "MSCAL";
|
||||
// break;
|
||||
// case Kind::MSCNT:
|
||||
// result = "MSCNT";
|
||||
// break;
|
||||
// case Kind::MSCALF:
|
||||
// result = "MSCALF";
|
||||
// break;
|
||||
// case Kind::STMASK:
|
||||
// result = "STMASK";
|
||||
// break;
|
||||
// case Kind::STROW:
|
||||
// result = "STROW";
|
||||
// break;
|
||||
// case Kind::STCOL:
|
||||
// result = "STCOL";
|
||||
// break;
|
||||
// case Kind::MPG:
|
||||
// result = "MPG";
|
||||
// break;
|
||||
// case Kind::DIRECT:
|
||||
// result = "DIRECT";
|
||||
// break;
|
||||
// case Kind::DIRECTHL:
|
||||
// result = "DIRECTHL";
|
||||
// break;
|
||||
case Kind::NOP:
|
||||
result = "NOP";
|
||||
break;
|
||||
case Kind::STCYCL:
|
||||
result = "STCYCL";
|
||||
break;
|
||||
case Kind::OFFSET:
|
||||
result = "OFFSET";
|
||||
break;
|
||||
case Kind::BASE:
|
||||
result = "BASE";
|
||||
break;
|
||||
case Kind::ITOP:
|
||||
result = "ITOP";
|
||||
break;
|
||||
case Kind::STMOD:
|
||||
result = "STMOD";
|
||||
break;
|
||||
case Kind::MSK3PATH:
|
||||
result = "MSK3PATH";
|
||||
break;
|
||||
case Kind::MARK:
|
||||
result = "MARK";
|
||||
break;
|
||||
case Kind::FLUSHE:
|
||||
result = "FLUSHE";
|
||||
break;
|
||||
case Kind::FLUSH:
|
||||
result = "FLUSH";
|
||||
break;
|
||||
|
||||
case Kind::FLUSHA:
|
||||
result = "FLUSHA";
|
||||
break;
|
||||
case Kind::MSCAL:
|
||||
result = "MSCAL";
|
||||
break;
|
||||
case Kind::MSCNT:
|
||||
result = "MSCNT";
|
||||
break;
|
||||
case Kind::MSCALF:
|
||||
result = "MSCALF";
|
||||
break;
|
||||
case Kind::STMASK:
|
||||
result = "STMASK";
|
||||
break;
|
||||
case Kind::STROW:
|
||||
result = "STROW";
|
||||
break;
|
||||
case Kind::STCOL:
|
||||
result = "STCOL";
|
||||
break;
|
||||
case Kind::MPG:
|
||||
result = "MPG";
|
||||
break;
|
||||
case Kind::DIRECT:
|
||||
result = "DIRECT";
|
||||
break;
|
||||
case Kind::DIRECTHL:
|
||||
result = "DIRECTHL";
|
||||
break;
|
||||
default:
|
||||
fmt::print("Unhandled vif code {}", (int)kind);
|
||||
assert(false);
|
||||
// special_kind = true;
|
||||
break;
|
||||
}
|
||||
//
|
||||
// if (special_kind) {
|
||||
// if (((u32)kind & (u32)Kind::UNPACK_MASK) == (u32)Kind::UNPACK_MASK) {
|
||||
// result = "UNPACK";
|
||||
// assert(false);
|
||||
// } else {
|
||||
// assert(false);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// result += ' ';
|
||||
//
|
||||
// TODO: the rest of the VIF code.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,4 +85,20 @@ u32 Exit() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 vsync() {
|
||||
return g_settings.renderer->vsync();
|
||||
}
|
||||
|
||||
void send_chain(const void* data, u32 offset) {
|
||||
g_settings.renderer->send_chain(data, offset);
|
||||
}
|
||||
|
||||
void texture_upload_now(const u8* tpage, int mode, u32 s7_ptr) {
|
||||
g_settings.renderer->texture_upload_now(tpage, mode, s7_ptr);
|
||||
}
|
||||
|
||||
void texture_relocate(u32 destination, u32 source) {
|
||||
g_settings.renderer->texture_relocate(destination, source);
|
||||
}
|
||||
|
||||
} // namespace Gfx
|
||||
|
||||
@@ -25,6 +25,10 @@ struct GfxRendererModule {
|
||||
std::function<void(GfxDisplay* display)> kill_display;
|
||||
std::function<void(GfxDisplay* display)> render_display;
|
||||
std::function<void()> exit;
|
||||
std::function<u32()> vsync;
|
||||
std::function<void(const void*, u32)> send_chain;
|
||||
std::function<void(const u8*, int, u32)> texture_upload_now;
|
||||
std::function<void(u32, u32)> texture_relocate;
|
||||
|
||||
GfxPipeline pipeline;
|
||||
const char* name;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "game/graphics/dma/gs.h"
|
||||
#include "common/log/log.h"
|
||||
#include "third-party/fmt/core.h"
|
||||
#include "game/graphics/opengl.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
|
||||
DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batch_size)
|
||||
: BucketRenderer(name, my_id), m_prim_buffer(batch_size) {
|
||||
@@ -236,7 +236,7 @@ void DirectRenderer::update_gl_test() {
|
||||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::setup_common_state(SharedRenderState* render_state) {
|
||||
void DirectRenderer::setup_common_state(SharedRenderState* /*render_state*/) {
|
||||
// todo texture clamp.
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ void DirectRenderer::render_gif(const u8* data, u32 size, SharedRenderState* ren
|
||||
handle_rgbaq_packed(data + offset);
|
||||
break;
|
||||
case GifTag::RegisterDescriptor::XYZF2:
|
||||
handle_xyzf2_packed(data + offset);
|
||||
handle_xyzf2_packed(data + offset, render_state);
|
||||
break;
|
||||
default:
|
||||
fmt::print("Register {} is not supported in packed mode yet\n",
|
||||
@@ -512,7 +512,7 @@ float u32_to_float(u32 in) {
|
||||
return x * 2 - 1;
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_xyzf2_packed(const u8* data) {
|
||||
void DirectRenderer::handle_xyzf2_packed(const u8* data, SharedRenderState* render_state) {
|
||||
u32 x, y;
|
||||
memcpy(&x, data, 4);
|
||||
memcpy(&y, data + 4, 4);
|
||||
@@ -524,7 +524,7 @@ void DirectRenderer::handle_xyzf2_packed(const u8* data) {
|
||||
bool adc = upper & (1ull << 47);
|
||||
assert(!adc);
|
||||
assert(!f);
|
||||
handle_xyzf2_common(x, y, z, f);
|
||||
handle_xyzf2_common(x, y, z, f, render_state);
|
||||
}
|
||||
|
||||
void debug_print_vtx(const math::Vector<u32, 3>& vtx) {
|
||||
@@ -594,7 +594,14 @@ void DirectRenderer::handle_rgbaq(u64 val) {
|
||||
memcpy(m_prim_building.rgba_reg.data(), &val, 4);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_xyzf2_common(u32 x, u32 y, u32 z, u8 f) {
|
||||
void DirectRenderer::handle_xyzf2_common(u32 x,
|
||||
u32 y,
|
||||
u32 z,
|
||||
u8 f,
|
||||
SharedRenderState* render_state) {
|
||||
if (m_prim_buffer.is_full()) {
|
||||
flush_pending(render_state);
|
||||
}
|
||||
assert(f == 0);
|
||||
m_prim_building.building_st.at(m_prim_building.building_idx) = m_prim_building.st_reg;
|
||||
m_prim_building.building_rgba.at(m_prim_building.building_idx) = m_prim_building.rgba_reg;
|
||||
@@ -685,11 +692,6 @@ void DirectRenderer::handle_xyzf2_common(u32 x, u32 y, u32 z, u8 f) {
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_xyzf2(u64 val, SharedRenderState* render_state) {
|
||||
if (m_prim_buffer.is_full()) {
|
||||
fmt::print("update from full\n");
|
||||
flush_pending(render_state);
|
||||
}
|
||||
|
||||
// m_prim_buffer.rgba_u8[m_prim_buffer.vert_count] = m_prim_building.rgba;
|
||||
|
||||
u32 x = val & 0xffff;
|
||||
@@ -697,7 +699,7 @@ void DirectRenderer::handle_xyzf2(u64 val, SharedRenderState* render_state) {
|
||||
u32 z = (val >> 32) & 0xfffff;
|
||||
u32 f = (val >> 56) & 0xff;
|
||||
|
||||
handle_xyzf2_common(x, y, z, f);
|
||||
handle_xyzf2_common(x, y, z, f, render_state);
|
||||
}
|
||||
|
||||
void DirectRenderer::reset_state() {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "game/graphics/types.h"
|
||||
#include "common/math/Vector.h"
|
||||
#include "common/util/SmallVector.h"
|
||||
#include "game/graphics/opengl.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
|
||||
/*!
|
||||
* The direct renderer will handle rendering GIFtags directly.
|
||||
@@ -59,12 +59,12 @@ class DirectRenderer : public BucketRenderer {
|
||||
void handle_xyzf2(u64 val, SharedRenderState* render_state);
|
||||
void handle_st_packed(const u8* data);
|
||||
void handle_rgbaq_packed(const u8* data);
|
||||
void handle_xyzf2_packed(const u8* data);
|
||||
void handle_xyzf2_packed(const u8* data, SharedRenderState* render_state);
|
||||
void handle_tex0_1(u64 val, SharedRenderState* render_state);
|
||||
void handle_tex1_1(u64 val);
|
||||
void handle_texa(u64 val);
|
||||
|
||||
void handle_xyzf2_common(u32 x, u32 y, u32 z, u8 f);
|
||||
void handle_xyzf2_common(u32 x, u32 y, u32 z, u8 f, SharedRenderState* render_state);
|
||||
|
||||
void update_gl_prim(SharedRenderState* render_state);
|
||||
void update_gl_blend();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "OpenGLRenderer.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "game/graphics/opengl.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
|
||||
// for the vif callback
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "Shader.h"
|
||||
#include "common/util/assert.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "game/graphics/opengl.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
|
||||
Shader::Shader(const std::string& shader_name) {
|
||||
// read the shader source
|
||||
|
||||
@@ -3,18 +3,51 @@
|
||||
* Lower-level OpenGL implementation.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#include "opengl.h"
|
||||
|
||||
#include "game/graphics/gfx.h"
|
||||
#include "game/graphics/display.h"
|
||||
|
||||
#include "game/graphics/opengl_renderer/OpenGLRenderer.h"
|
||||
#include "game/graphics/texture/TexturePool.h"
|
||||
#include "game/graphics/dma/dma_copy.h"
|
||||
#include "common/log/log.h"
|
||||
#include <memory>
|
||||
#include "common/goal_constants.h"
|
||||
#include "game/runtime.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct GraphicsData {
|
||||
// vsync
|
||||
std::mutex sync_mutex;
|
||||
std::condition_variable sync_cv;
|
||||
|
||||
// dma chain transfer
|
||||
std::mutex dma_mutex;
|
||||
std::condition_variable dma_cv;
|
||||
u64 frame_idx = 0;
|
||||
bool has_data_to_render = false;
|
||||
FixedChunkDmaCopier dma_copier;
|
||||
|
||||
// texture pool
|
||||
std::shared_ptr<TexturePool> texture_pool;
|
||||
|
||||
// temporary opengl renderer
|
||||
OpenGLRenderer ogl_renderer;
|
||||
|
||||
GraphicsData()
|
||||
: dma_copier(EE_MAIN_MEM_SIZE),
|
||||
texture_pool(std::make_shared<TexturePool>()),
|
||||
ogl_renderer(texture_pool) {}
|
||||
};
|
||||
|
||||
std::unique_ptr<GraphicsData> g_gfx_data;
|
||||
|
||||
void SetDisplayCallbacks(GLFWwindow* d) {
|
||||
glfwSetKeyCallback(d, [](GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
glfwSetKeyCallback(d, [](GLFWwindow* /*window*/, int key, int scancode, int action, int mods) {
|
||||
if (action == GlfwKeyAction::Press) {
|
||||
lg::debug("KEY PRESS: key: {} scancode: {} mods: {:X}", key, scancode, mods);
|
||||
} else if (action == GlfwKeyAction::Release) {
|
||||
@@ -52,8 +85,10 @@ static int gl_init() {
|
||||
}
|
||||
|
||||
static void gl_exit() {
|
||||
g_gfx_data.reset();
|
||||
glfwTerminate();
|
||||
glfwSetErrorCallback(NULL);
|
||||
gl_inited = false;
|
||||
}
|
||||
|
||||
static std::shared_ptr<GfxDisplay> gl_make_main_display(int width,
|
||||
@@ -73,6 +108,7 @@ static std::shared_ptr<GfxDisplay> gl_make_main_display(int width,
|
||||
lg::error("GL init fail");
|
||||
return NULL;
|
||||
}
|
||||
g_gfx_data = std::make_unique<GraphicsData>();
|
||||
gl_inited = true;
|
||||
|
||||
// enable vsync by default
|
||||
@@ -101,11 +137,42 @@ static void gl_render_display(GfxDisplay* display) {
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// render graphics
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// wait for a copied chain.
|
||||
bool got_chain = false;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(g_gfx_data->dma_mutex);
|
||||
// note: there's a timeout here. If the engine is messed up and not sending us frames,
|
||||
// we still want to run the glfw loop.
|
||||
got_chain = g_gfx_data->dma_cv.wait_for(lock, std::chrono::milliseconds(20),
|
||||
[=] { return g_gfx_data->has_data_to_render; });
|
||||
}
|
||||
|
||||
// render that chain.
|
||||
if (got_chain) {
|
||||
auto& chain = g_gfx_data->dma_copier.get_last_result();
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
g_gfx_data->ogl_renderer.render(DmaFollower(chain.data.data(), chain.start_offset), width,
|
||||
height);
|
||||
}
|
||||
|
||||
// before vsync, mark the chain as rendered.
|
||||
{
|
||||
// should be fine to remove this mutex if the game actually waits for vsync to call
|
||||
// send_chain again. but let's be safe for now.
|
||||
std::unique_lock<std::mutex> lock(g_gfx_data->dma_mutex);
|
||||
g_gfx_data->has_data_to_render = false;
|
||||
}
|
||||
|
||||
// actual vsync
|
||||
glfwSwapBuffers(window);
|
||||
|
||||
// toggle even odd and wake up engine waiting on vsync.
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(g_gfx_data->sync_mutex);
|
||||
g_gfx_data->frame_idx++;
|
||||
g_gfx_data->sync_cv.notify_all();
|
||||
}
|
||||
// poll events TODO integrate input with cpad
|
||||
glfwPollEvents();
|
||||
|
||||
@@ -116,12 +183,81 @@ static void gl_render_display(GfxDisplay* display) {
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Wait for the next vsync. Returns 0 or 1 depending on if frame is even or odd.
|
||||
* Called from the game thread, on a GOAL stack.
|
||||
*/
|
||||
u32 gl_vsync() {
|
||||
if (!g_gfx_data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(g_gfx_data->sync_mutex);
|
||||
auto init_frame = g_gfx_data->frame_idx;
|
||||
g_gfx_data->sync_cv.wait(lock, [=] { return g_gfx_data->frame_idx > init_frame; });
|
||||
|
||||
return g_gfx_data->frame_idx & 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Send DMA to the renderer.
|
||||
* Called from the game thread, on a GOAL stack.
|
||||
*/
|
||||
void gl_send_chain(const void* data, u32 offset) {
|
||||
if (g_gfx_data) {
|
||||
std::unique_lock<std::mutex> lock(g_gfx_data->dma_mutex);
|
||||
if (g_gfx_data->has_data_to_render) {
|
||||
lg::error(
|
||||
"Gfx::send_chain called when the graphics renderer has pending data. Was this called "
|
||||
"multiple times per frame?");
|
||||
return;
|
||||
}
|
||||
|
||||
// we copy the dma data and give a copy of it to the render.
|
||||
// the copy has a few advantages:
|
||||
// - if the game code has a bug and corrupts the DMA buffer, the renderer won't see it.
|
||||
// - the copied DMA is much smaller than the entire game memory, so it can be dumped to a file
|
||||
// separate of the entire RAM.
|
||||
// - it verifies the DMA data is valid early on.
|
||||
// but it may also be pretty expensive. Both the renderer and the game wait on this to complete.
|
||||
|
||||
// The renderers should just operate on DMA chains, so eliminating this step in the future may
|
||||
// be easy.
|
||||
|
||||
// Timer copy_timer;
|
||||
g_gfx_data->dma_copier.run(data, offset);
|
||||
// fmt::print("copy took {:.3f}ms\n", copy_timer.getMs());
|
||||
|
||||
g_gfx_data->has_data_to_render = true;
|
||||
g_gfx_data->dma_cv.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
void gl_texture_upload_now(const u8* tpage, int mode, u32 s7_ptr) {
|
||||
if (g_gfx_data) {
|
||||
// just pass it to the texture pool.
|
||||
// the texture pool will take care of locking.
|
||||
// we don't want to lock here for the entire duration of the conversion.
|
||||
g_gfx_data->texture_pool->handle_upload_now(tpage, mode, g_ee_main_mem, s7_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void gl_texture_relocate(u32 destination, u32 source) {
|
||||
if (g_gfx_data) {
|
||||
g_gfx_data->texture_pool->relocate(destination, source);
|
||||
}
|
||||
}
|
||||
|
||||
const GfxRendererModule moduleOpenGL = {
|
||||
gl_init, // init
|
||||
gl_make_main_display, // make_main_display
|
||||
gl_kill_display, // kill_display
|
||||
gl_render_display, // render_display
|
||||
gl_exit, // exit
|
||||
GfxPipeline::OpenGL, // pipeline
|
||||
"OpenGL 3.0" // name
|
||||
gl_init, // init
|
||||
gl_make_main_display, // make_main_display
|
||||
gl_kill_display, // kill_display
|
||||
gl_render_display, // render_display
|
||||
gl_exit, // exit
|
||||
gl_vsync, // vsync
|
||||
gl_send_chain, // send_chain
|
||||
gl_texture_upload_now, // texture_upload_now
|
||||
gl_texture_relocate, // texture_relocate
|
||||
GfxPipeline::OpenGL, // pipeline
|
||||
"OpenGL 3.0" // name
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user