Added hooks to interact with the rendering api [OpenGL / DirectX]

This commit is contained in:
KiritoDv 2021-07-05 01:31:11 -05:00
parent 2369bf8ce1
commit fa71b56cb0
6 changed files with 118 additions and 345 deletions

View File

@ -14,6 +14,19 @@ struct HookParameter {
#define SAVE_GRAPH_NODE "SaveGraphNode"
#define LOAD_GRAPH_NODE "LoadGraphNode"
// Graphics API Hooks
#define GFX_PRE_START_FRAME "GFXApiPreStartFrame"
#define GFX_POST_START_FRAME "GFXApiPostStartFrame"
#define GFX_PRE_END_FRAME "GFXApiPreEndFrame"
#define GFX_POST_END_FRAME "GFXApiPostEndFrame"
#define GFX_ON_REZISE "GFXApiOnResize"
#define GFX_INIT "GFXApiInit"
#define GFX_SHUTDOWN "GFXApiShutdown"
// End
#ifdef __cplusplus
#include <string>

View File

@ -26,6 +26,7 @@
#include "gfx_dxgi.h"
#include "gfx_screen_config.h"
#include "moon/mod-engine/hooks/hook.h"
#define THREE_POINT_FILTERING 0
#define DEBUG_D3D 0
@ -303,6 +304,10 @@ static void gfx_d3d11_init(void) {
gfx_dxgi_get_h_wnd(), "Failed to create per-draw constant buffer.");
d3d.context->PSSetConstantBuffers(1, 1, d3d.per_draw_cb.GetAddressOf());
MoonInternal::bindHook(GFX_INIT);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
@ -664,9 +669,16 @@ static void gfx_d3d11_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t
static void gfx_d3d11_on_resize(void) {
create_render_target_views(true);
MoonInternal::bindHook(GFX_ON_REZISE);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
static void gfx_d3d11_start_frame(void) {
MoonInternal::bindHook(GFX_PRE_START_FRAME);
MoonInternal::initBindHook(0);
if(MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d})) return;
// Set render targets
d3d.context->OMSetRenderTargets(1, d3d.backbuffer_view.GetAddressOf(), d3d.depth_stencil_view.Get());
@ -693,9 +705,20 @@ static void gfx_d3d11_start_frame(void) {
d3d.context->Map(d3d.per_frame_cb.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &ms);
memcpy(ms.pData, &d3d.per_frame_cb_data, sizeof(PerFrameCB));
d3d.context->Unmap(d3d.per_frame_cb.Get(), 0);
MoonInternal::bindHook(GFX_POST_START_FRAME);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
static void gfx_d3d11_end_frame(void) {
MoonInternal::bindHook(GFX_PRE_END_FRAME);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
MoonInternal::bindHook(GFX_POST_END_FRAME);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
static void gfx_d3d11_finish_render(void) {

View File

@ -38,6 +38,7 @@
#include "gfx_direct3d_common.h"
#include "gfx_screen_config.h"
#include "moon/mod-engine/hooks/hook.h"
#define DEBUG_D3D 0
@ -582,6 +583,11 @@ static void gfx_direct3d12_draw_triangles(float buf_vbo[], size_t buf_vbo_len, s
}
static void gfx_direct3d12_start_frame(void) {
MoonInternal::bindHook(GFX_PRE_START_FRAME);
MoonInternal::initBindHook(0);
if(MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d})) return;
++d3d.frame_counter;
d3d.srv_pos = 0;
texture_uploads = 0;
@ -614,6 +620,10 @@ static void gfx_direct3d12_start_frame(void) {
memcpy(d3d.mapped_noise_cb_address, &d3d.noise_cb_data, sizeof(struct NoiseCB));
d3d.vbuf_pos = 0;
MoonInternal::bindHook(GFX_POST_START_FRAME);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
static void create_render_target_views(void) {
@ -675,6 +685,9 @@ static void gfx_direct3d12_on_resize(void) {
d3d.frame_index = d3d.swap_chain->GetCurrentBackBufferIndex();
create_render_target_views();
create_depth_buffer();
MoonInternal::bindHook(GFX_ON_REZISE);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
}
@ -866,9 +879,17 @@ static void gfx_direct3d12_init(void ) {
CD3DX12_RANGE read_range(0, 0); // Read not possible from CPU
ThrowIfFailed(d3d.vertex_buffer->Map(0, &read_range, &d3d.mapped_vbuf_address));
}
MoonInternal::bindHook(GFX_INIT);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
static void gfx_direct3d12_end_frame(void) {
MoonInternal::bindHook(GFX_PRE_END_FRAME);
MoonInternal::initBindHook(0);
if(MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d})) return;
if (max_texture_uploads < texture_uploads && texture_uploads != 38 && texture_uploads != 34 && texture_uploads != 29) {
max_texture_uploads = texture_uploads;
}
@ -902,6 +923,9 @@ static void gfx_direct3d12_end_frame(void) {
QueryPerformanceCounter(&t0);
//printf("Present: %llu %u\n", (unsigned long long)(t0.QuadPart - d3d.qpc_init), d3d.length_in_vsync_frames);
}
MoonInternal::bindHook(GFX_POST_END_FRAME);
MoonInternal::initBindHook(0);
MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d});
}
static void gfx_direct3d12_finish_render(void) {

View File

@ -32,6 +32,7 @@
#include "../configfile.h"
#include "gfx_cc.h"
#include "gfx_rendering_api.h"
#include "moon/mod-engine/hooks/hook.h"
#define TEX_CACHE_STEP 512
@ -632,12 +633,26 @@ static void gfx_opengl_init(void) {
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
moon_bind_hook(GFX_INIT);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_on_resize(void) {
moon_bind_hook(GFX_ON_REZISE);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_start_frame(void) {
moon_bind_hook(GFX_PRE_START_FRAME);
moon_init_hook(0);
if(moon_call_hook(0)){
return;
}
frame_count++;
glDisable(GL_SCISSOR_TEST);
@ -645,15 +660,29 @@ static void gfx_opengl_start_frame(void) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
moon_bind_hook(GFX_POST_START_FRAME);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_end_frame(void) {
moon_bind_hook(GFX_PRE_END_FRAME);
moon_init_hook(0);
moon_call_hook(0);
moon_bind_hook(GFX_POST_END_FRAME);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_finish_render(void) {
}
static void gfx_opengl_shutdown(void) {
moon_bind_hook(GFX_SHUTDOWN);
moon_init_hook(0);
moon_call_hook(0);
}
struct GfxRenderingAPI gfx_opengl_api = {

View File

@ -1,344 +0,0 @@
#ifndef RAPI_GL
#include <stdint.h>
#include <stdbool.h>
#ifndef _LANGUAGE_C
# define _LANGUAGE_C
#endif
#include <PR/gbi.h>
#ifdef __MINGW32__
# define FOR_WINDOWS 1
#else
# define FOR_WINDOWS 0
#endif
#if FOR_WINDOWS || defined(OSX_BUILD)
# define GLEW_STATIC
# include <GL/glew.h>
#endif
#include <SDL2/SDL.h>
#define GL_GLEXT_PROTOTYPES 1
#ifdef USE_GLES
# include <SDL2/SDL_opengles2.h>
#else
# include <SDL2/SDL_opengl.h>
#endif
extern "C" {
#include "../configfile.h"
#include "../../game/area.h"
#include "../../game/level_update.h"
#include "../fs/fs.h"
#include "../pc_main.h"
#include "../../goddard/gd_math.h"
#include "gfx_cc.h"
}
#include <cassert>
#include <fstream>
#include <iomanip>
#include <stdint.h>
#include <string>
#include <unordered_map>
#define TEX_CACHE_STEP 512
struct ShaderProgram {
uint32_t shader_id;
GLuint opengl_program_id;
uint8_t num_inputs;
bool used_textures[2];
uint8_t num_floats;
GLint attrib_locations[7];
GLint uniform_locations[5];
uint8_t attrib_sizes[7];
uint8_t num_attribs;
bool used_noise;
};
struct GLTexture {
GLuint gltex;
GLfloat size[2];
bool filter;
};
static struct ShaderProgram shader_program_pool[64];
static uint8_t shader_program_pool_size;
static GLuint opengl_vbo;
static int tex_cache_size = 0;
static int num_textures = 0;
static struct GLTexture *tex_cache = NULL;
static struct ShaderProgram *opengl_prg = NULL;
static struct GLTexture *opengl_tex[2];
static int opengl_curtex = 0;
static uint32_t frame_count;
static bool gfx_opengl_z_is_from_0_to_1(void) {
return false;
}
static void gfx_opengl_vertex_array_set_attribs(struct ShaderProgram *prg) {
size_t num_floats = prg->num_floats;
size_t pos = 0;
for (int i = 0; i < prg->num_attribs; i++) {
glEnableVertexAttribArray(prg->attrib_locations[i]);
glVertexAttribPointer(prg->attrib_locations[i], prg->attrib_sizes[i], GL_FLOAT, GL_FALSE, num_floats * sizeof(float), (void *) (pos * sizeof(float)));
pos += prg->attrib_sizes[i];
}
}
static inline void gfx_opengl_set_shader_uniforms(struct ShaderProgram *prg) {
if (prg->used_noise)
glUniform1f(prg->uniform_locations[4], (float)frame_count);
}
static inline void gfx_opengl_set_texture_uniforms(struct ShaderProgram *prg, const int tile) {
if (prg->used_textures[tile] && opengl_tex[tile]) {
glUniform2f(prg->uniform_locations[tile*2 + 0], opengl_tex[tile]->size[0], opengl_tex[tile]->size[1]);
glUniform1i(prg->uniform_locations[tile*2 + 1], opengl_tex[tile]->filter);
}
}
static void gfx_opengl_unload_shader(struct ShaderProgram *old_prg) {
}
static void gfx_opengl_load_shader(struct ShaderProgram *new_prg) {
}
static struct ShaderProgram *gfx_opengl_create_and_load_new_shader(uint32_t shader_id) {
ShaderProgram *shaderProgram = new ShaderProgram();
int c[2][4];
for (int i = 0; i < 4; i++) {
c[0][i] = (shader_id >> (i * 3)) & 7;
c[1][i] = (shader_id >> (12 + i * 3)) & 7;
}
shaderProgram->shader_id = shader_id;
shaderProgram->used_textures[0] = false;
shaderProgram->used_textures[1] = false;
shaderProgram->num_inputs = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
if (c[i][j] >= SHADER_INPUT_1 && c[i][j] <= SHADER_INPUT_4) {
if (c[i][j] > shaderProgram->num_inputs) {
shaderProgram->num_inputs = c[i][j];
}
}
if (c[i][j] == SHADER_TEXEL0 || c[i][j] == SHADER_TEXEL0A) {
shaderProgram->used_textures[0] = true;
}
if (c[i][j] == SHADER_TEXEL1) {
shaderProgram->used_textures[1] = true;
}
}
}
return shaderProgram;
}
static struct ShaderProgram *gfx_opengl_lookup_shader(uint32_t shader_id) {
for (size_t i = 0; i < shader_program_pool_size; i++) {
if (shader_program_pool[i].shader_id == shader_id) {
return &shader_program_pool[i];
}
}
return NULL;
}
static void gfx_opengl_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
*num_inputs = prg->num_inputs;
used_textures[0] = prg->used_textures[0];
used_textures[1] = prg->used_textures[1];
}
static GLuint gfx_opengl_new_texture(void) {
if (num_textures >= tex_cache_size) {
tex_cache_size += TEX_CACHE_STEP;
tex_cache = realloc(tex_cache, sizeof(struct GLTexture) * tex_cache_size);
if (!tex_cache) sys_fatal("out of memory allocating texture cache");
// invalidate these because they might be pointing to garbage now
opengl_tex[0] = NULL;
opengl_tex[1] = NULL;
}
glGenTextures(1, &tex_cache[num_textures].gltex);
return num_textures++;
}
static void gfx_opengl_select_texture(int tile, GLuint texture_id) {
opengl_tex[tile] = tex_cache + texture_id;
opengl_curtex = tile;
glActiveTexture(GL_TEXTURE0 + tile);
glBindTexture(GL_TEXTURE_2D, opengl_tex[tile]->gltex);
gfx_opengl_set_texture_uniforms(opengl_prg, tile);
}
static void gfx_opengl_upload_texture(uint8_t *rgba32_buf, int width, int height) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf);
opengl_tex[opengl_curtex]->size[0] = width;
opengl_tex[opengl_curtex]->size[1] = height;
}
static uint32_t gfx_cm_to_opengl(uint32_t val) {
if (val & G_TX_CLAMP) {
return GL_CLAMP_TO_EDGE;
}
return (val & G_TX_MIRROR) ? GL_MIRRORED_REPEAT : GL_REPEAT;
}
static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) {
const GLenum filter = linear_filter ? GL_LINEAR : GL_NEAREST;
glActiveTexture(GL_TEXTURE0 + tile);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gfx_cm_to_opengl(cms));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gfx_cm_to_opengl(cmt));
opengl_curtex = tile;
if (opengl_tex[tile]) {
opengl_tex[tile]->filter = linear_filter;
gfx_opengl_set_texture_uniforms(opengl_prg, tile);
}
}
static void gfx_opengl_set_depth_test(bool depth_test) {
if (depth_test) {
glEnable(GL_DEPTH_TEST);
} else {
glDisable(GL_DEPTH_TEST);
}
}
static void gfx_opengl_set_depth_mask(bool z_upd) {
glDepthMask(z_upd ? GL_TRUE : GL_FALSE);
}
static void gfx_opengl_set_zmode_decal(bool zmode_decal) {
if (zmode_decal) {
glPolygonOffset(-2, -2);
glEnable(GL_POLYGON_OFFSET_FILL);
} else {
glPolygonOffset(0, 0);
glDisable(GL_POLYGON_OFFSET_FILL);
}
}
static void gfx_opengl_set_viewport(int x, int y, int width, int height) {
glViewport(x, y, width, height);
}
static void gfx_opengl_set_scissor(int x, int y, int width, int height) {
glScissor(x, y, width, height);
}
static void gfx_opengl_set_use_alpha(bool use_alpha) {
if (use_alpha) {
glEnable(GL_BLEND);
} else {
glDisable(GL_BLEND);
}
}
static void gfx_opengl_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) {
//printf("flushing %d tris\n", buf_vbo_num_tris);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * buf_vbo_len, buf_vbo, GL_STREAM_DRAW);
glDrawArrays(GL_TRIANGLES, 0, 3 * buf_vbo_num_tris);
}
static inline bool gl_get_version(int *major, int *minor, bool *is_es) {
const char *vstr = (const char *)glGetString(GL_VERSION);
if (!vstr || !vstr[0]) return false;
if (!strncmp(vstr, "OpenGL ES ", 10)) {
vstr += 10;
*is_es = true;
} else if (!strncmp(vstr, "OpenGL ES-CM ", 13)) {
vstr += 13;
*is_es = true;
}
return (sscanf(vstr, "%d.%d", major, minor) == 2);
}
static void gfx_opengl_init(void) {
#if FOR_WINDOWS || defined(OSX_BUILD)
GLenum err;
if ((err = glewInit()) != GLEW_OK)
sys_fatal("could not init GLEW:\n%s", glewGetErrorString(err));
#endif
tex_cache_size = TEX_CACHE_STEP;
tex_cache = calloc(tex_cache_size, sizeof(struct GLTexture));
if (!tex_cache) sys_fatal("out of memory allocating texture cache");
// check GL version
int vmajor, vminor;
bool is_es = false;
gl_get_version(&vmajor, &vminor, &is_es);
if (vmajor < 2 && vminor < 1 && !is_es)
sys_fatal("OpenGL 2.1+ is required.\nReported version: %s%d.%d", is_es ? "ES" : "", vmajor, vminor);
glGenBuffers(1, &opengl_vbo);
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
static void gfx_opengl_on_resize(void) {
}
static void gfx_opengl_start_frame(void) {
frame_count++;
glDisable(GL_SCISSOR_TEST);
glDepthMask(GL_TRUE); // Must be set to clear Z-buffer
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
}
static void gfx_opengl_end_frame(void) {
}
static void gfx_opengl_finish_render(void) {
}
static void gfx_opengl_shutdown(void) {
}
struct GfxRenderingAPI gfx_opengl_api = {
gfx_opengl_z_is_from_0_to_1,
gfx_opengl_unload_shader,
gfx_opengl_load_shader,
gfx_opengl_create_and_load_new_shader,
gfx_opengl_lookup_shader,
gfx_opengl_shader_get_info,
gfx_opengl_new_texture,
gfx_opengl_select_texture,
gfx_opengl_upload_texture,
gfx_opengl_set_sampler_parameters,
gfx_opengl_set_depth_test,
gfx_opengl_set_depth_mask,
gfx_opengl_set_zmode_decal,
gfx_opengl_set_viewport,
gfx_opengl_set_scissor,
gfx_opengl_set_use_alpha,
gfx_opengl_draw_triangles,
gfx_opengl_init,
gfx_opengl_on_resize,
gfx_opengl_start_frame,
gfx_opengl_end_frame,
gfx_opengl_finish_render,
gfx_opengl_shutdown
};
#endif // RAPI_GL

View File

@ -42,8 +42,9 @@ static PFNMGLFOGCOORDPOINTERPROC mglFogCoordPointer = NULL;
#include "../platform.h"
#include "gfx_cc.h"
#include "gfx_rendering_api.h"
#include "macros.h"
#include "gfx_rendering_api.h"
#include "moon/mod-engine/hooks/hook.h"
enum MixFlags {
SH_MF_OVERRIDE_ALPHA = 1,
@ -567,26 +568,53 @@ static void gfx_opengl_init(void) {
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, c_white);
TEXENV_COMBINE_OP(0, GL_SRC_COLOR, GL_SRC_ALPHA);
TEXENV_COMBINE_OP(1, GL_SRC_COLOR, GL_SRC_ALPHA);
moon_bind_hook(GFX_INIT);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_on_resize(void) {
moon_bind_hook(GFX_ON_REZISE);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_start_frame(void) {
moon_bind_hook(GFX_PRE_START_FRAME);
moon_init_hook(0);
if(moon_call_hook(0)){
return;
}
glDisable(GL_SCISSOR_TEST);
glDepthMask(GL_TRUE); // Must be set to clear Z-buffer
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
moon_bind_hook(GFX_POST_START_FRAME);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_end_frame(void) {
moon_bind_hook(GFX_PRE_END_FRAME);
moon_init_hook(0);
moon_call_hook(0);
moon_bind_hook(GFX_POST_END_FRAME);
moon_init_hook(0);
moon_call_hook(0);
}
static void gfx_opengl_finish_render(void) {
}
static void gfx_opengl_shutdown(void) {
moon_bind_hook(GFX_SHUTDOWN);
moon_init_hook(0);
moon_call_hook(0);
}
struct GfxRenderingAPI gfx_opengl_api = {