From f42bf16f714817f2567fe24cb8cb16c8f1f43d43 Mon Sep 17 00:00:00 2001 From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com> Date: Fri, 7 Apr 2023 13:44:09 +0200 Subject: [PATCH] wiiu/render: Replace WHBGfx shader loading --- src/render/wiiu/SDL_rqueue_wiiu.c | 2 +- src/render/wiiu/SDL_shaders_wiiu.c | 213 ++++++++++++++++++++++++++--- src/render/wiiu/SDL_shaders_wiiu.h | 11 +- 3 files changed, 207 insertions(+), 19 deletions(-) diff --git a/src/render/wiiu/SDL_rqueue_wiiu.c b/src/render/wiiu/SDL_rqueue_wiiu.c index 166c1b7e5..382212f4f 100644 --- a/src/render/wiiu/SDL_rqueue_wiiu.c +++ b/src/render/wiiu/SDL_rqueue_wiiu.c @@ -269,7 +269,7 @@ static int WIIU_SDL_SetDrawState(WIIU_RenderData * data, const SDL_RenderCommand SDL_bool shaderUpdated = SDL_FALSE; const SDL_BlendMode blendMode = cmd->data.draw.blend; WIIU_ShaderType shader = cmd->data.draw.texture ? SHADER_TEXTURE : SHADER_COLOR; - WHBGfxShaderGroup* shaderGroup = WIIU_SDL_GetShaderGroup(shader); + WiiU_ShaderGroup* shaderGroup = WIIU_SDL_GetShaderGroup(shader); SDL_Texture *texture = cmd->data.draw.texture; if (data->drawState.viewportDirty) { diff --git a/src/render/wiiu/SDL_shaders_wiiu.c b/src/render/wiiu/SDL_shaders_wiiu.c index 679bded96..f06aa3efc 100644 --- a/src/render/wiiu/SDL_shaders_wiiu.c +++ b/src/render/wiiu/SDL_shaders_wiiu.c @@ -26,49 +26,230 @@ #include "SDL_render.h" #include "../SDL_sysrender.h" +#include +#include +#include +#include + #include "shaders/colorShader.inc" #include "shaders/textureShader.inc" -static WHBGfxShaderGroup shaderGroups[NUM_SHADERS]; +static WiiU_ShaderGroup shaderGroups[NUM_SHADERS]; static int shaderRefCount = 0; +static GX2VertexShader* WiiU_LoadGFDVertexShader(uint32_t index, const void* file) +{ + uint32_t headerSize, programSize; + GX2VertexShader* shader = NULL; + void* program = NULL; + + if (index >= GFDGetVertexShaderCount(file)) { + return NULL; + } + + if ((headerSize = GFDGetVertexShaderHeaderSize(index, file)) == 0) { + return NULL; + } + + if ((programSize = GFDGetVertexShaderProgramSize(index, file)) == 0) { + return NULL; + } + + if (!(shader = memalign(0x40, headerSize))) { + return NULL; + } + + shader->gx2rBuffer.flags = GX2R_RESOURCE_BIND_SHADER_PROGRAM | + GX2R_RESOURCE_USAGE_CPU_READ | + GX2R_RESOURCE_USAGE_CPU_WRITE | + GX2R_RESOURCE_USAGE_GPU_READ; + shader->gx2rBuffer.elemSize = programSize; + shader->gx2rBuffer.elemCount = 1; + shader->gx2rBuffer.buffer = NULL; + if (!GX2RCreateBuffer(&shader->gx2rBuffer)) { + free(shader); + return NULL; + } + + program = GX2RLockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_BIND_NONE); + if (!GFDGetVertexShader(shader, program, index, file)) { + GX2RUnlockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_DISABLE_CPU_INVALIDATE | + GX2R_RESOURCE_DISABLE_GPU_INVALIDATE); + GX2RDestroyBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_BIND_NONE); + free(shader); + return NULL; + } + + GX2RUnlockBufferEx(&shader->gx2rBuffer, 0); + // according to wut this needs to be invalidated again for some reason + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, shader->program, shader->size); + return shader; +} + +static GX2PixelShader* WiiU_LoadGFDPixelShader(uint32_t index, const void* file) +{ + uint32_t headerSize, programSize; + GX2PixelShader* shader = NULL; + void* program = NULL; + + if (index >= GFDGetPixelShaderCount(file)) { + return NULL; + } + + if ((headerSize = GFDGetPixelShaderHeaderSize(index, file)) == 0) { + return NULL; + } + + if ((programSize = GFDGetPixelShaderProgramSize(index, file)) == 0) { + return NULL; + } + + if (!(shader = memalign(0x40, headerSize))) { + return NULL; + } + + shader->gx2rBuffer.flags = GX2R_RESOURCE_BIND_SHADER_PROGRAM | + GX2R_RESOURCE_USAGE_CPU_READ | + GX2R_RESOURCE_USAGE_CPU_WRITE | + GX2R_RESOURCE_USAGE_GPU_READ; + shader->gx2rBuffer.elemSize = programSize; + shader->gx2rBuffer.elemCount = 1; + shader->gx2rBuffer.buffer = NULL; + if (!GX2RCreateBuffer(&shader->gx2rBuffer)) { + free(shader); + return NULL; + } + + program = GX2RLockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_BIND_NONE); + if (!GFDGetPixelShader(shader, program, index, file)) { + GX2RUnlockBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_DISABLE_CPU_INVALIDATE | + GX2R_RESOURCE_DISABLE_GPU_INVALIDATE); + GX2RDestroyBufferEx(&shader->gx2rBuffer, GX2R_RESOURCE_BIND_NONE); + free(shader); + return NULL; + } + + GX2RUnlockBufferEx(&shader->gx2rBuffer, 0); + // according to wut this needs to be invalidated again for some reason + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, shader->program, shader->size); + return shader; +} + +static int WiiU_LoadGFDShaderGroup(WiiU_ShaderGroup* group, uint32_t index, const void* file) +{ + group->vertexShader = WiiU_LoadGFDVertexShader(index, file); + if (!group->vertexShader) { + return -1; + } + + group->pixelShader = WiiU_LoadGFDPixelShader(index, file); + if (!group->pixelShader) { + return -1; + } + + return 0; +} + +static int WiiU_CreateFetchShader(WiiU_ShaderGroup* group, GX2AttribStream* attributes, uint32_t numAttributes) +{ + uint32_t size = GX2CalcFetchShaderSizeEx(numAttributes, GX2_FETCH_SHADER_TESSELLATION_NONE, GX2_TESSELLATION_MODE_DISCRETE); + if (!size) { + return -1; + } + + group->fetchShaderProgram = memalign(GX2_SHADER_PROGRAM_ALIGNMENT, size); + if (!group->fetchShaderProgram) { + return -1; + } + + GX2InitFetchShaderEx(&group->fetchShader, + group->fetchShaderProgram, + numAttributes, + attributes, + GX2_FETCH_SHADER_TESSELLATION_NONE, + GX2_TESSELLATION_MODE_DISCRETE); + + GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, group->fetchShaderProgram, size); + return 0; +} + +static void WiiU_FreeShaderGroup(WiiU_ShaderGroup* group) +{ + GX2RDestroyBufferEx(&group->vertexShader->gx2rBuffer, GX2R_RESOURCE_BIND_NONE); + free(group->vertexShader); + + GX2RDestroyBufferEx(&group->pixelShader->gx2rBuffer, GX2R_RESOURCE_BIND_NONE); + free(group->pixelShader); + + free(group->fetchShaderProgram); +} + void WIIU_SDL_CreateShaders(void) { if (!shaderRefCount++) { - WHBGfxShaderGroup* colorShader = &shaderGroups[SHADER_COLOR]; - WHBGfxShaderGroup* textureShader = &shaderGroups[SHADER_TEXTURE]; + GX2AttribStream attributes[3]; - WHBGfxLoadGFDShaderGroup(colorShader, 0, colorShader_gsh); - WHBGfxInitShaderAttribute(colorShader, "a_position", 0, offsetof(SDL_VertexSolid, position), GX2_ATTRIB_FORMAT_FLOAT_32_32); - WHBGfxInitShaderAttribute(colorShader, "a_color", 0, offsetof(SDL_VertexSolid, color), GX2_ATTRIB_FORMAT_UNORM_8_8_8_8); - WHBGfxInitFetchShader(colorShader); + // a_position + attributes[0] = (GX2AttribStream) { + 0, 0, offsetof(SDL_VertexSolid, position), + GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, + GX2_SEL_MASK(GX2_SQ_SEL_X, GX2_SQ_SEL_Y, GX2_SQ_SEL_0, GX2_SQ_SEL_1), + GX2_ENDIAN_SWAP_DEFAULT + }; + // a_color + attributes[1] = (GX2AttribStream) { + 1, 0, offsetof(SDL_VertexSolid, color), + GX2_ATTRIB_FORMAT_UNORM_8_8_8_8, GX2_ATTRIB_INDEX_PER_VERTEX, 0, + GX2_SEL_MASK(GX2_SQ_SEL_X, GX2_SQ_SEL_Y, GX2_SQ_SEL_Z, GX2_SQ_SEL_W), + GX2_ENDIAN_SWAP_DEFAULT + }; + WiiU_LoadGFDShaderGroup(&shaderGroups[SHADER_COLOR], 0, colorShader_gsh); + WiiU_CreateFetchShader(&shaderGroups[SHADER_COLOR], attributes, 2); - WHBGfxLoadGFDShaderGroup(textureShader, 0, textureShader_gsh); - WHBGfxInitShaderAttribute(textureShader, "a_position", 0, offsetof(SDL_Vertex, position), GX2_ATTRIB_FORMAT_FLOAT_32_32); - WHBGfxInitShaderAttribute(textureShader, "a_color", 0, offsetof(SDL_Vertex, color), GX2_ATTRIB_FORMAT_UNORM_8_8_8_8); - WHBGfxInitShaderAttribute(textureShader, "a_texcoord", 0, offsetof(SDL_Vertex, tex_coord), GX2_ATTRIB_FORMAT_FLOAT_32_32); - WHBGfxInitFetchShader(textureShader); + // a_position + attributes[0] = (GX2AttribStream) { + 0, 0, offsetof(SDL_Vertex, position), + GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, + GX2_SEL_MASK(GX2_SQ_SEL_X, GX2_SQ_SEL_Y, GX2_SQ_SEL_0, GX2_SQ_SEL_1), + GX2_ENDIAN_SWAP_DEFAULT + }; + // a_color + attributes[1] = (GX2AttribStream) { + 1, 0, offsetof(SDL_Vertex, color), + GX2_ATTRIB_FORMAT_UNORM_8_8_8_8, GX2_ATTRIB_INDEX_PER_VERTEX, 0, + GX2_SEL_MASK(GX2_SQ_SEL_X, GX2_SQ_SEL_Y, GX2_SQ_SEL_Z, GX2_SQ_SEL_W), + GX2_ENDIAN_SWAP_DEFAULT + }; + // a_texcoord + attributes[2] = (GX2AttribStream) { + 2, 0, offsetof(SDL_Vertex, tex_coord), + GX2_ATTRIB_FORMAT_FLOAT_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, + GX2_SEL_MASK(GX2_SQ_SEL_X, GX2_SQ_SEL_Y, GX2_SQ_SEL_0, GX2_SQ_SEL_1), + GX2_ENDIAN_SWAP_DEFAULT + }; + WiiU_LoadGFDShaderGroup(&shaderGroups[SHADER_TEXTURE], 0, textureShader_gsh); + WiiU_CreateFetchShader(&shaderGroups[SHADER_TEXTURE], attributes, 3); } } void WIIU_SDL_DestroyShaders(void) { if (!--shaderRefCount) { - WHBGfxFreeShaderGroup(&shaderGroups[SHADER_COLOR]); - WHBGfxFreeShaderGroup(&shaderGroups[SHADER_TEXTURE]); + WiiU_FreeShaderGroup(&shaderGroups[SHADER_COLOR]); + WiiU_FreeShaderGroup(&shaderGroups[SHADER_TEXTURE]); } } void WIIU_SDL_SelectShader(WIIU_ShaderType shader) { - WHBGfxShaderGroup* shaderGroup = &shaderGroups[shader]; + WiiU_ShaderGroup* shaderGroup = &shaderGroups[shader]; GX2SetFetchShader(&shaderGroup->fetchShader); GX2SetVertexShader(shaderGroup->vertexShader); GX2SetPixelShader(shaderGroup->pixelShader); } -WHBGfxShaderGroup* WIIU_SDL_GetShaderGroup(WIIU_ShaderType shader) +WiiU_ShaderGroup* WIIU_SDL_GetShaderGroup(WIIU_ShaderType shader) { return &shaderGroups[shader]; } diff --git a/src/render/wiiu/SDL_shaders_wiiu.h b/src/render/wiiu/SDL_shaders_wiiu.h index f4b19c90d..fbb7903af 100644 --- a/src/render/wiiu/SDL_shaders_wiiu.h +++ b/src/render/wiiu/SDL_shaders_wiiu.h @@ -25,7 +25,7 @@ #if SDL_VIDEO_RENDER_WIIU -#include +#include typedef enum { SHADER_INVALID = -1, @@ -34,10 +34,17 @@ typedef enum { NUM_SHADERS } WIIU_ShaderType; +typedef struct { + GX2FetchShader fetchShader; + void* fetchShaderProgram; + GX2VertexShader* vertexShader; + GX2PixelShader* pixelShader; +} WiiU_ShaderGroup; + void WIIU_SDL_CreateShaders(void); void WIIU_SDL_DestroyShaders(void); void WIIU_SDL_SelectShader(WIIU_ShaderType shader); -WHBGfxShaderGroup* WIIU_SDL_GetShaderGroup(WIIU_ShaderType shader); +WiiU_ShaderGroup* WIIU_SDL_GetShaderGroup(WIIU_ShaderType shader); #endif /* SDL_VIDEO_RENDER_WIIU */