Per-stage default shaders;

This commit is contained in:
bjorn 2022-08-01 22:10:06 -07:00
parent 67b338a1d8
commit c0dfb414d6
3 changed files with 85 additions and 51 deletions

View File

@ -60,10 +60,11 @@ StringEntry lovrCullMode[] = {
StringEntry lovrDefaultShader[] = {
[SHADER_UNLIT] = ENTRY("unlit"),
[SHADER_CUBE] = ENTRY("cube"),
[SHADER_PANO] = ENTRY("pano"),
[SHADER_FILL] = ENTRY("fill"),
[SHADER_FONT] = ENTRY("font"),
[SHADER_CUBEMAP] = ENTRY("cubemap"),
[SHADER_EQUIRECT] = ENTRY("equirect"),
[SHADER_FILL] = ENTRY("fill"),
[SHADER_STEREOBLIT] = ENTRY("stereoblit"),
{ 0 }
};
@ -1047,7 +1048,7 @@ static int l_lovrGraphicsNewSampler(lua_State* L) {
return 1;
}
static ShaderSource luax_checkshadercode(lua_State* L, int index, ShaderStage stage, bool* allocated) {
static ShaderSource luax_checkshadersource(lua_State* L, int index, ShaderStage stage, bool* allocated) {
ShaderSource source;
if (lua_isstring(L, index)) {
size_t length;
@ -1057,9 +1058,19 @@ static ShaderSource luax_checkshadercode(lua_State* L, int index, ShaderStage st
source.size = length;
*allocated = false;
} else {
for (int i = 0; lovrDefaultShader[i].length; i++) {
if (lovrDefaultShader[i].length == length && !memcmp(lovrDefaultShader[i].string, string, length)) {
return lovrGraphicsGetDefaultShaderSource(i, stage);
}
}
source.code = luax_readfile(string, &source.size);
lovrAssert(source.code, "Could not read shader code from %s", string);
*allocated = true;
if (source.code) {
*allocated = true;
} else {
luaL_argerror(L, index, "single-line string was not filename or DefaultShader");
}
}
} else if (lua_istable(L, index)) {
int length = luax_len(L, index);
@ -1094,7 +1105,7 @@ static ShaderSource luax_checkshadercode(lua_State* L, int index, ShaderStage st
static int l_lovrGraphicsCompileShader(lua_State* L) {
ShaderStage stage = luax_checkenum(L, 1, ShaderStage, NULL);
bool allocated;
ShaderSource spirv = luax_checkshadercode(L, 2, stage, &allocated);
ShaderSource spirv = luax_checkshadersource(L, 2, stage, &allocated);
if (!allocated) {
lua_settop(L, 2);
return 1;
@ -1110,14 +1121,31 @@ static int l_lovrGraphicsNewShader(lua_State* L) {
bool allocated[2];
int index;
// If there's only one source given, it could be a DefaultShader or a compute shader
if (lua_gettop(L) == 1 || (lua_istable(L, 2) && luax_len(L, 2) == 0)) {
info.type = SHADER_COMPUTE;
info.source[0] = luax_checkshadercode(L, 1, STAGE_COMPUTE, &allocated[0]);
if (lua_type(L, 1) == LUA_TSTRING) {
size_t length;
const char* string = lua_tolstring(L, 1, &length);
for (int i = 0; lovrDefaultShader[i].length; i++) {
if (lovrDefaultShader[i].length == length && !memcmp(lovrDefaultShader[i].string, string, length)) {
info.source[0] = lovrGraphicsGetDefaultShaderSource(i, STAGE_VERTEX);
info.source[1] = lovrGraphicsGetDefaultShaderSource(i, STAGE_FRAGMENT);
info.type = SHADER_GRAPHICS;
break;
}
}
}
if (!info.source[0].code) {
info.type = SHADER_COMPUTE;
info.source[0] = luax_checkshadersource(L, 1, STAGE_COMPUTE, &allocated[0]);
}
index = 2;
} else {
info.type = SHADER_GRAPHICS;
info.source[0] = luax_checkshadercode(L, 1, STAGE_VERTEX, &allocated[0]);
info.source[1] = luax_checkshadercode(L, 2, STAGE_FRAGMENT, &allocated[1]);
info.source[0] = luax_checkshadersource(L, 1, STAGE_VERTEX, &allocated[0]);
info.source[1] = luax_checkshadersource(L, 2, STAGE_FRAGMENT, &allocated[1]);
index = 3;
}

View File

@ -1466,46 +1466,51 @@ static void lovrShaderInit(Shader* shader) {
}
}
ShaderSource lovrGraphicsGetDefaultShaderSource(DefaultShader type, ShaderStage stage) {
if (stage == STAGE_COMPUTE) {
return (ShaderSource) { NULL, 0 };
}
const ShaderSource sources[][2] = {
[SHADER_UNLIT] = {
{ lovr_shader_unlit_vert, sizeof(lovr_shader_unlit_vert) },
{ lovr_shader_unlit_frag, sizeof(lovr_shader_unlit_frag) }
},
[SHADER_FONT] = {
{ lovr_shader_unlit_vert, sizeof(lovr_shader_unlit_vert) },
{ lovr_shader_font_frag, sizeof(lovr_shader_font_frag) }
},
[SHADER_CUBEMAP] = {
{ lovr_shader_cubemap_vert, sizeof(lovr_shader_cubemap_vert) },
{ lovr_shader_cubemap_frag, sizeof(lovr_shader_cubemap_frag) }
},
[SHADER_EQUIRECT] = {
{ lovr_shader_cubemap_vert, sizeof(lovr_shader_cubemap_vert) },
{ lovr_shader_equirect_frag, sizeof(lovr_shader_equirect_frag) }
},
[SHADER_FILL] = {
{ lovr_shader_fill_vert, sizeof(lovr_shader_fill_vert) },
{ lovr_shader_unlit_frag, sizeof(lovr_shader_unlit_frag) }
},
[SHADER_STEREOBLIT] = {
{ lovr_shader_fill_vert, sizeof(lovr_shader_fill_vert) },
{ lovr_shader_stereoblit_frag, sizeof(lovr_shader_stereoblit_frag) }
}
};
return sources[type][stage];
}
Shader* lovrGraphicsGetDefaultShader(DefaultShader type) {
if (state.defaultShaders[type]) {
return state.defaultShaders[type];
}
ShaderInfo info = { .type = SHADER_GRAPHICS };
switch (type) {
case SHADER_UNLIT:
info.source[0] = (ShaderSource) { lovr_shader_unlit_vert, sizeof(lovr_shader_unlit_vert) };
info.source[1] = (ShaderSource) { lovr_shader_unlit_frag, sizeof(lovr_shader_unlit_frag) };
info.label = "unlit";
break;
case SHADER_CUBE:
info.source[0] = (ShaderSource) { lovr_shader_cubemap_vert, sizeof(lovr_shader_cubemap_vert) };
info.source[1] = (ShaderSource) { lovr_shader_cubemap_frag, sizeof(lovr_shader_cubemap_frag) };
info.label = "cubemap";
break;
case SHADER_PANO:
info.source[0] = (ShaderSource) { lovr_shader_cubemap_vert, sizeof(lovr_shader_cubemap_vert) };
info.source[1] = (ShaderSource) { lovr_shader_equirect_frag, sizeof(lovr_shader_equirect_frag) };
info.label = "equirect";
break;
case SHADER_FILL:
info.source[0] = (ShaderSource) { lovr_shader_fill_vert, sizeof(lovr_shader_fill_vert) };
info.source[1] = (ShaderSource) { lovr_shader_unlit_frag, sizeof(lovr_shader_unlit_frag) };
info.label = "fill";
break;
case SHADER_FONT:
info.source[0] = (ShaderSource) { lovr_shader_unlit_vert, sizeof(lovr_shader_unlit_vert) };
info.source[1] = (ShaderSource) { lovr_shader_font_frag, sizeof(lovr_shader_font_frag) };
info.label = "font";
break;
case SHADER_STEREOBLIT:
info.source[0] = (ShaderSource) { lovr_shader_fill_vert, sizeof(lovr_shader_fill_vert) };
info.source[1] = (ShaderSource) { lovr_shader_stereoblit_frag, sizeof(lovr_shader_stereoblit_frag) };
info.label = "stereoblit";
break;
default: lovrUnreachable();
}
ShaderInfo info = {
.type = SHADER_GRAPHICS,
.source[0] = lovrGraphicsGetDefaultShaderSource(type, STAGE_VERTEX),
.source[1] = lovrGraphicsGetDefaultShaderSource(type, STAGE_FRAGMENT)
};
return state.defaultShaders[type] = lovrShaderCreate(&info);
}
@ -4719,7 +4724,7 @@ void lovrPassSkybox(Pass* pass, Texture* texture) {
if (texture->info.type == TEXTURE_2D) {
lovrPassDraw(pass, &(Draw) {
.mode = MESH_TRIANGLES,
.shader = SHADER_PANO,
.shader = SHADER_EQUIRECT,
.material = texture ? lovrTextureGetMaterial(texture) : NULL,
.vertex.format = VERTEX_EMPTY,
.count = 6
@ -4727,7 +4732,7 @@ void lovrPassSkybox(Pass* pass, Texture* texture) {
} else {
lovrPassDraw(pass, &(Draw) {
.mode = MESH_TRIANGLES,
.shader = SHADER_CUBE,
.shader = SHADER_CUBEMAP,
.material = texture ? lovrTextureGetMaterial(texture) : NULL,
.vertex.format = VERTEX_EMPTY,
.count = 6

View File

@ -262,10 +262,10 @@ const SamplerInfo* lovrSamplerGetInfo(Sampler* sampler);
typedef enum {
SHADER_UNLIT,
SHADER_CUBE,
SHADER_PANO,
SHADER_FILL,
SHADER_FONT,
SHADER_CUBEMAP,
SHADER_EQUIRECT,
SHADER_FILL,
SHADER_STEREOBLIT,
DEFAULT_SHADER_COUNT
} DefaultShader;
@ -301,6 +301,7 @@ typedef struct {
} ShaderInfo;
ShaderSource lovrGraphicsCompileShader(ShaderStage stage, ShaderSource* source);
ShaderSource lovrGraphicsGetDefaultShaderSource(DefaultShader type, ShaderStage stage);
Shader* lovrGraphicsGetDefaultShader(DefaultShader type);
Shader* lovrShaderCreate(const ShaderInfo* info);
Shader* lovrShaderClone(Shader* parent, ShaderFlag* flags, uint32_t count);