Add support for qualifiers like noperspective, do some rewriting on framepasses

This commit is contained in:
EmeraldLoc 2026-06-17 18:53:16 -05:00
parent 0f4fa7a664
commit 14fdb5187c
9 changed files with 99 additions and 44 deletions

View file

@ -88,6 +88,7 @@ struct CombineMode {
uint8_t use_dither : 1;
uint8_t use_2cycle : 1;
uint8_t light_map : 1;
uint8_t tex_persp : 1;
uint8_t world_geometry : 1;
};
u32 flags;

View file

@ -621,13 +621,13 @@ static void gfx_d3d11_shader_get_info(struct ShaderProgram *prg, uint8_t *num_in
used_textures[1] = p->used_textures[1];
}
static void gfx_d3d11_create_framebuffer(UNUSED u32 *fbo, UNUSED u32 *depthBuffer, UNUSED u32 *tex, UNUSED u32 width, UNUSED u32 height) {
static void gfx_d3d11_create_framebuffer(UNUSED struct FramePass *framePass) {
}
static void gfx_d3d11_delete_framebuffer(UNUSED u32 fbo, UNUSED u32 depthBuffer, UNUSED u32 tex) {
static void gfx_d3d11_delete_framebuffer(UNUSED struct FramePass *framePass) {
}
static void gfx_d3d11_set_framebuffer(UNUSED u32 fbo, UNUSED u32 width, UNUSED u32 height) {
static void gfx_d3d11_set_framebuffer(UNUSED struct FramePass *framePass) {
}
static void gfx_d3d11_reset_framebuffer(void) {
@ -950,7 +950,13 @@ static void gfx_d3d11_start_frame(void) {
d3d.context->OMSetRenderTargets(1, d3d.backbuffer_view.GetAddressOf(), d3d.depth_stencil_view.Get());
// Clear render targets
const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
struct FramePass *framePass = gfx_get_current_frame_pass();
const float clearColor[] = {
framePass->clearColor[0] / 255.0f,
framePass->clearColor[1] / 255.0f,
framePass->clearColor[2] / 255.0f,
framePass->clearColor[3] / 255.0f
};
d3d.context->ClearRenderTargetView(d3d.backbuffer_view.Get(), clearColor);
d3d.context->ClearDepthStencilView(d3d.depth_stencil_view.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);

View file

@ -154,13 +154,13 @@ static void gfx_dummy_renderer_shader_get_info(UNUSED struct ShaderProgram *prg,
used_textures[1] = false;
}
static void gfx_dummy_renderer_create_framebuffer(UNUSED u32 *fbo, UNUSED u32 *depthBuffer, UNUSED u32 *tex, UNUSED u32 width, UNUSED u32 height) {
static void gfx_dummy_renderer_create_framebuffer(UNUSED struct FramePass *framePass) {
}
static void gfx_dummy_renderer_delete_framebuffer(UNUSED u32 fbo, UNUSED u32 depthBuffer, UNUSED u32 tex) {
static void gfx_dummy_renderer_delete_framebuffer(UNUSED struct FramePass *framePass) {
}
static void gfx_dummy_renderer_set_framebuffer(UNUSED u32 fbo, UNUSED u32 width, UNUSED u32 height) {
static void gfx_dummy_renderer_set_framebuffer(UNUSED struct FramePass *framePass) {
}
static void gfx_dummy_renderer_reset_framebuffer(void) {

View file

@ -561,24 +561,24 @@ static void gfx_opengl_shader_get_info(struct ShaderProgram *prg, uint8_t *num_i
used_textures[1] = prg->used_textures[1];
}
static void gfx_opengl_create_framebuffer(u32 *fbo, u32 *depthBuffer, u32 *tex, u32 width, u32 height) {
glGenFramebuffers(1, fbo);
glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
static void gfx_opengl_create_framebuffer(struct FramePass *framePass) {
glGenFramebuffers(1, &framePass->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, framePass->fbo);
glGenTextures(1, tex);
glBindTexture(GL_TEXTURE_2D, *tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenTextures(1, &framePass->passTexture);
glBindTexture(GL_TEXTURE_2D, framePass->passTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, framePass->width, framePass->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framePass->passTexture, 0);
// create depth buffer
glGenRenderbuffers(1, depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, *depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *depthBuffer);
glGenRenderbuffers(1, &framePass->depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, framePass->depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, framePass->width, framePass->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, framePass->depthBuffer);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
LOG_ERROR("Framebuffer is not complete!");
@ -587,15 +587,15 @@ static void gfx_opengl_create_framebuffer(u32 *fbo, u32 *depthBuffer, u32 *tex,
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
static void gfx_opengl_delete_framebuffer(u32 fbo, u32 depthBuffer, u32 tex) {
if (fbo > 0) glDeleteFramebuffers(1, &fbo);
if (depthBuffer > 0) glDeleteRenderbuffers(1, &depthBuffer);
if (tex > 0) glDeleteTextures(1, &tex);
static void gfx_opengl_delete_framebuffer(struct FramePass *framePass) {
if (framePass->fbo > 0) { glDeleteFramebuffers(1, &framePass->fbo); }
if (framePass->depthBuffer > 0) { glDeleteRenderbuffers(1, &framePass->depthBuffer); }
if (framePass->passTexture > 0) { glDeleteTextures(1, &framePass->passTexture); }
}
static void gfx_opengl_set_framebuffer(u32 fbo, u32 width, u32 height) {
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, width, height);
static void gfx_opengl_set_framebuffer(struct FramePass *framePass) {
glBindFramebuffer(GL_FRAMEBUFFER, framePass->fbo);
glViewport(0, 0, framePass->width, framePass->height);
}
static void gfx_opengl_reset_framebuffer(void) {
@ -777,7 +777,15 @@ static void gfx_opengl_start_frame(void) {
glDisable(GL_SCISSOR_TEST);
glDepthMask(GL_TRUE); // Must be set to clear Z-buffer
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
struct FramePass *framePass = gfx_get_current_frame_pass();
glClearColor(
framePass->clearColor[0] / 255.0f,
framePass->clearColor[1] / 255.0f,
framePass->clearColor[2] / 255.0f,
framePass->clearColor[3] / 255.0f
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
}

View file

@ -1108,12 +1108,13 @@ static void OPTIMIZE_O3 gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t
struct CombineMode* cm = &rdp.combine_mode;
cm->use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0;
cm->texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA;
cm->use_dither = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER;
cm->use_2cycle = (rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_2CYCLE;
cm->use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG;
cm->light_map = (rsp.geometry_mode & G_LIGHT_MAP_EXT) == G_LIGHT_MAP_EXT;
cm->use_alpha = (rdp.other_mode_l & (G_BL_A_MEM << 18)) == 0;
cm->texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA;
cm->use_dither = (rdp.other_mode_l & G_AC_DITHER) == G_AC_DITHER;
cm->use_2cycle = (rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE)) == G_CYC_2CYCLE;
cm->use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG;
cm->light_map = (rsp.geometry_mode & G_LIGHT_MAP_EXT) == G_LIGHT_MAP_EXT;
cm->tex_persp = (rdp.other_mode_h & G_TP_PERSP) == G_TP_PERSP;
cm->world_geometry = gShaderFlagsEnabled && (v1->world_geometry && v2->world_geometry && v3->world_geometry);
if (cm->texture_edge) {
@ -2095,6 +2096,14 @@ void gfx_start_frame(void) {
gfx_current_dimensions.x_adjust_ratio = (4.0f / 3.0f) / gfx_current_dimensions.aspect_ratio;
}
struct FramePass *gfx_get_current_frame_pass(void) {
if (gCurrentFramePassIndex < 0) {
return &gDefaultGeoFramePass;
} else {
return &gFramePasses[gCurrentFramePassIndex];
}
}
static void gfx_process_lua_passes(Gfx *commands, bool *isLuaPassesActive) {
for (int i = 0; i < MAX_CUSTOM_FRAME_PASSES; i++) {
struct FramePass *framePass = &gFramePasses[i];
@ -2103,7 +2112,7 @@ static void gfx_process_lua_passes(Gfx *commands, bool *isLuaPassesActive) {
// remove default frame pass if we have lua frame pass
if (gDefaultGeoFramePass.active) {
gfx_rapi->delete_framebuffer(gDefaultGeoFramePass.fbo, gDefaultGeoFramePass.depthBuffer, gDefaultGeoFramePass.passTexture);
gfx_rapi->delete_framebuffer(&gDefaultGeoFramePass);
memset(&gDefaultGeoFramePass, 0, sizeof(struct FramePass));
}
@ -2111,9 +2120,9 @@ static void gfx_process_lua_passes(Gfx *commands, bool *isLuaPassesActive) {
// setup framebuffer
if (framePass->fbo == 0) {
gfx_rapi->create_framebuffer(&framePass->fbo, &framePass->depthBuffer, &framePass->passTexture, framePass->width, framePass->height);
gfx_rapi->create_framebuffer(framePass);
}
gfx_rapi->set_framebuffer(framePass->fbo, framePass->width, framePass->height);
gfx_rapi->set_framebuffer(framePass);
gfx_rapi->start_frame(); // resets color and depth
@ -2167,6 +2176,7 @@ void gfx_run_basic(Gfx *commands) { // for dummy frames we don't want to do a mu
}
void gfx_run(Gfx *commands) {
// Shader TODO: Give directx support for frame passes
if (gRenderApi == &gfx_direct3d11_api) {
gfx_run_basic(commands);
return;
@ -2189,16 +2199,17 @@ void gfx_run(Gfx *commands) {
memset(&gDefaultGeoFramePass, 0, sizeof(struct FramePass));
gDefaultGeoFramePass.active = true;
gDefaultGeoFramePass.drawWorldGeometry = true;
gDefaultGeoFramePass.clearColor[3] = 255;
}
// create/update fbo
if (gDefaultGeoFramePass.fbo == 0 || gDefaultGeoFramePass.width != gfx_current_dimensions.width || gDefaultGeoFramePass.height != gfx_current_dimensions.height) {
gfx_rapi->delete_framebuffer(gDefaultGeoFramePass.fbo, gDefaultGeoFramePass.depthBuffer, gDefaultGeoFramePass.passTexture);
gfx_rapi->delete_framebuffer(&gDefaultGeoFramePass);
gfx_get_dimensions(&gDefaultGeoFramePass.width, &gDefaultGeoFramePass.height);
gfx_rapi->create_framebuffer(&gDefaultGeoFramePass.fbo, &gDefaultGeoFramePass.depthBuffer, &gDefaultGeoFramePass.passTexture, gDefaultGeoFramePass.width, gDefaultGeoFramePass.height);
gfx_rapi->create_framebuffer(&gDefaultGeoFramePass);
}
gfx_rapi->set_framebuffer(gDefaultGeoFramePass.fbo, gDefaultGeoFramePass.width, gDefaultGeoFramePass.height);
gfx_rapi->set_framebuffer(&gDefaultGeoFramePass);
gfx_rapi->start_frame(); // resets color and depth

View file

@ -55,6 +55,7 @@ struct FramePass {
u32 height;
bool active;
bool drawWorldGeometry;
u8 clearColor[4];
};
extern struct RSP rsp;
@ -84,6 +85,7 @@ extern "C" {
void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, const char *window_title);
struct GfxRenderingAPI *gfx_get_current_rendering_api(void);
void gfx_start_frame(void);
struct FramePass *gfx_get_current_frame_pass(void);
void gfx_run_basic(Gfx *commands);
void gfx_run(Gfx *commands);
void gfx_end_frame_render(void);

View file

@ -21,9 +21,9 @@ struct GfxRenderingAPI {
struct ShaderProgram *(*lookup_shader)(struct ColorCombiner* cc);
struct ShaderProgram *(*lookup_shader_using_index)(uint8_t shaderIndex, uint8_t framePassIndex);
void (*shader_get_info)(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]);
void (*create_framebuffer)(uint32_t *fbo, uint32_t *depthBuffer, uint32_t *tex, uint32_t width, uint32_t height);
void (*delete_framebuffer)(uint32_t fbo, uint32_t depthBuffer, uint32_t tex);
void (*set_framebuffer)(uint32_t fbo, uint32_t width, uint32_t height);
void (*create_framebuffer)(struct FramePass *framePass);
void (*delete_framebuffer)(struct FramePass *framePass);
void (*set_framebuffer)(struct FramePass *framePass);
void (*reset_framebuffer)(void);
void (*set_uniform)(struct ShaderProgram *prg, const char *name, ShaderUniformType type, const void *data, uint32_t numElements);
uint32_t (*new_texture)(void);

View file

@ -210,6 +210,7 @@ char *gfx_generate_default_fragment_shader_from_cc(struct ColorCombiner *cc) {
bool opt_texture_edge = cc->cm.texture_edge;
bool opt_2cycle = cc->cm.use_2cycle;
bool opt_light_map = cc->cm.light_map;
bool opt_tex_persp = cc->cm.tex_persp;
bool world_geometry = cc->cm.world_geometry;
bool opt_dither = cc->cm.use_dither;
@ -219,6 +220,7 @@ char *gfx_generate_default_fragment_shader_from_cc(struct ColorCombiner *cc) {
append_line(fs_buf, &fs_len, "#version 410 core");
append_line(fs_buf, &fs_len, "out vec4 fragColor;");
for (int t = 0; t < 2; t++) {
if (!opt_tex_persp) { append_str(fs_buf, &fs_len, "noperspective "); }
fs_len += sprintf(fs_buf + fs_len, "in vec2 vTexCoord%d;\n", t);
}
append_line(fs_buf, &fs_len, "in vec4 vFog;");
@ -549,9 +551,20 @@ void gfx_init_shaders() {
}
static void process_shader_line(struct Shader *shader, struct ShaderInput *referenceInputs, char *output, const char *line) {
char type[32], name[MAX_SHADER_VARIABLE_NAME];
char qualifier[32] = { 0 }, type[32] = { 0 }, name[MAX_SHADER_VARIABLE_NAME] = { 0 };
// parse inputs for inputs equivalent to reference inputs
if (sscanf(line, "%31s in %31s %31[^; \t\n]", qualifier, type, name) == 3) {
for (int i = 0; i < MAX_SHADER_INPUTS; i++) {
if (referenceInputs[i].name[0] != '\0' && strcmp(referenceInputs[i].name, name) == 0) {
char layoutLine[sizeof(type) + MAX_SHADER_VARIABLE_NAME + 64];
snprintf(layoutLine, sizeof(layoutLine), "%s layout(location=%d) in %s %s", qualifier, referenceInputs[i].location, type, name);
strncat(output, layoutLine, MAX_SHADER_CODE - strlen(output) - 1);
return;
}
}
}
if (sscanf(line, " in %31s %31[^; \t\n]", type, name) == 2) {
for (int i = 0; i < MAX_SHADER_INPUTS; i++) {
if (referenceInputs[i].name[0] != '\0' && strcmp(referenceInputs[i].name, name) == 0) {
@ -564,6 +577,19 @@ static void process_shader_line(struct Shader *shader, struct ShaderInput *refer
}
// look for and parse outputs
if (sscanf(line, "%31s out %31s %31[^; \t\n]", qualifier, type, name) == 3) {
// add name to our shader outputs
if (shader) {
snprintf(shader->shaderOutputs[sShaderOutputCount].name, MAX_SHADER_VARIABLE_NAME, "%s", name);
shader->shaderOutputs[sShaderOutputCount].location = sShaderOutputCount;
}
char layoutLine[sizeof(type) + MAX_SHADER_VARIABLE_NAME + 64];
snprintf(layoutLine, sizeof(layoutLine), "%s layout(location=%d) out %s %s", qualifier, sShaderOutputCount, type, name);
strncat(output, layoutLine, MAX_SHADER_CODE - strlen(output) - 1);
if (sShaderOutputCount < MAX_SHADER_OUTPUTS - 1) { sShaderOutputCount++; }
return;
}
if (sscanf(line, " out %31s %31[^; \t\n]", type, name) == 2) {
// add name to our shader outputs
if (shader) {

View file

@ -460,6 +460,7 @@ int gfx_shader_create_frame_pass() {
// set default values
framePass->active = true;
gfx_get_dimensions(&framePass->width, &framePass->height);
framePass->clearColor[3] = 255; // clear color is black from memset, set alpha to 255
return i;
}
@ -474,7 +475,7 @@ void gfx_shader_remove_frame_pass(int framePassIndex) {
struct FramePass *framePass = &gFramePasses[framePassIndex];
if (!framePass->active) return;
gfx_get_current_rendering_api()->delete_framebuffer(framePass->fbo, framePass->depthBuffer, framePass->passTexture);
gfx_get_current_rendering_api()->delete_framebuffer(framePass);
memset(framePass, 0, sizeof(struct FramePass));
}
@ -488,7 +489,7 @@ void gfx_shader_set_frame_pass_viewport(int framePassIndex, int width, int heigh
framePass->height = height;
// needs to be recreated
gfx_get_current_rendering_api()->delete_framebuffer(framePass->fbo, framePass->depthBuffer, framePass->passTexture);
gfx_get_current_rendering_api()->delete_framebuffer(framePass);
framePass->fbo = 0;
framePass->depthBuffer = 0;
framePass->passTexture = 0;