mirror of https://github.com/bjornbytes/lovr.git
ShaderBlock:getValue; Shader:send vector fixes;
Allows you to read back values from a ShaderBlock. - This is also probably useful for Shaders. - This creates SO MANY tables. It feels so bad to expose this. But also it's the only way to read values back from a compute operation, so it's pretty indispensable. In the future there could be a Blob variant.
This commit is contained in:
parent
3d2488a577
commit
ee7544eba8
|
@ -936,6 +936,7 @@ static int l_lovrGraphicsNewShaderBlock(lua_State* L) {
|
||||||
|
|
||||||
BlockType type = BLOCK_UNIFORM;
|
BlockType type = BLOCK_UNIFORM;
|
||||||
BufferUsage usage = USAGE_DYNAMIC;
|
BufferUsage usage = USAGE_DYNAMIC;
|
||||||
|
bool readable = false;
|
||||||
|
|
||||||
if (lua_istable(L, 2)) {
|
if (lua_istable(L, 2)) {
|
||||||
lua_getfield(L, 2, "usage");
|
lua_getfield(L, 2, "usage");
|
||||||
|
@ -945,11 +946,15 @@ static int l_lovrGraphicsNewShaderBlock(lua_State* L) {
|
||||||
lua_getfield(L, 2, "writable");
|
lua_getfield(L, 2, "writable");
|
||||||
type = lua_toboolean(L, -1) ? BLOCK_STORAGE : BLOCK_UNIFORM;
|
type = lua_toboolean(L, -1) ? BLOCK_STORAGE : BLOCK_UNIFORM;
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
lua_getfield(L, 2, "readable");
|
||||||
|
readable = lua_toboolean(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lovrAssert(type != BLOCK_STORAGE || lovrGraphicsGetSupported()->computeShaders, "Writable ShaderBlocks are not supported on this system");
|
lovrAssert(type != BLOCK_STORAGE || lovrGraphicsGetSupported()->computeShaders, "Writable ShaderBlocks are not supported on this system");
|
||||||
size_t size = lovrShaderComputeUniformLayout(&uniforms);
|
size_t size = lovrShaderComputeUniformLayout(&uniforms);
|
||||||
Buffer* buffer = lovrBufferCreate(size, NULL, type == BLOCK_STORAGE ? BUFFER_SHADER_STORAGE : BUFFER_UNIFORM, usage, false);
|
Buffer* buffer = lovrBufferCreate(size, NULL, type == BLOCK_STORAGE ? BUFFER_SHADER_STORAGE : BUFFER_UNIFORM, usage, readable);
|
||||||
ShaderBlock* block = lovrShaderBlockCreate(type, buffer, &uniforms);
|
ShaderBlock* block = lovrShaderBlockCreate(type, buffer, &uniforms);
|
||||||
luax_pushobject(L, block);
|
luax_pushobject(L, block);
|
||||||
vec_deinit(&uniforms);
|
vec_deinit(&uniforms);
|
||||||
|
|
|
@ -86,10 +86,13 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
luaL_checktype(L, index, LUA_TTABLE);
|
bool wrappedTable = false;
|
||||||
lua_rawgeti(L, index, 1);
|
|
||||||
bool wrappedTable = !lua_isnumber(L, -1);
|
if (lua_istable(L, index)) {
|
||||||
lua_pop(L, 1);
|
lua_rawgeti(L, index, 1);
|
||||||
|
wrappedTable = !lua_isnumber(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (wrappedTable) {
|
if (wrappedTable) {
|
||||||
int length = lua_objlen(L, index);
|
int length = lua_objlen(L, index);
|
||||||
|
|
|
@ -47,6 +47,56 @@ int l_lovrShaderBlockSend(lua_State* L) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int l_lovrShaderBlockGetValue(lua_State* L) {
|
||||||
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
||||||
|
const char* name = luaL_checkstring(L, 2);
|
||||||
|
const Uniform* uniform = lovrShaderBlockGetUniform(block, name);
|
||||||
|
lovrAssert(uniform, "Unknown uniform for ShaderBlock '%s'", name);
|
||||||
|
Buffer* buffer = lovrShaderBlockGetBuffer(block);
|
||||||
|
lovrAssert(lovrBufferIsReadable(buffer), "ShaderBlock:getValue requires the ShaderBlock to be created with the readable flag");
|
||||||
|
union { float* floats; int* ints; } data = { .floats = lovrBufferMap(buffer, uniform->offset) };
|
||||||
|
int components = uniform->components;
|
||||||
|
|
||||||
|
if (uniform->type == UNIFORM_MATRIX) {
|
||||||
|
components *= components;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_createtable(L, uniform->count, 0);
|
||||||
|
for (int i = 0; i < uniform->count; i++) {
|
||||||
|
if (components == 1) {
|
||||||
|
switch (uniform->type) {
|
||||||
|
case UNIFORM_FLOAT:
|
||||||
|
lua_pushnumber(L, data.floats[i]);
|
||||||
|
lua_rawseti(L, -2, i + 1);
|
||||||
|
break;
|
||||||
|
case UNIFORM_INT:
|
||||||
|
lua_pushinteger(L, data.ints[i]);
|
||||||
|
lua_rawseti(L, -2, i + 1);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lua_createtable(L, components, 0);
|
||||||
|
for (int j = 0; j < components; j++) {
|
||||||
|
switch (uniform->type) {
|
||||||
|
case UNIFORM_FLOAT:
|
||||||
|
case UNIFORM_MATRIX:
|
||||||
|
lua_pushnumber(L, data.floats[i * components + j]);
|
||||||
|
lua_rawseti(L, -2, j + 1);
|
||||||
|
break;
|
||||||
|
case UNIFORM_INT:
|
||||||
|
lua_pushinteger(L, data.ints[i * components + j]);
|
||||||
|
lua_rawseti(L, -2, j + 1);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lua_rawseti(L, -2, i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int l_lovrShaderBlockGetShaderCode(lua_State* L) {
|
int l_lovrShaderBlockGetShaderCode(lua_State* L) {
|
||||||
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
||||||
const char* blockName = luaL_checkstring(L, 2);
|
const char* blockName = luaL_checkstring(L, 2);
|
||||||
|
@ -61,6 +111,7 @@ const luaL_Reg lovrShaderBlock[] = {
|
||||||
{ "getSize", l_lovrShaderBlockGetSize },
|
{ "getSize", l_lovrShaderBlockGetSize },
|
||||||
{ "getOffset", l_lovrShaderBlockGetOffset },
|
{ "getOffset", l_lovrShaderBlockGetOffset },
|
||||||
{ "send", l_lovrShaderBlockSend },
|
{ "send", l_lovrShaderBlockSend },
|
||||||
|
{ "getValue", l_lovrShaderBlockGetValue },
|
||||||
{ "getShaderCode", l_lovrShaderBlockGetShaderCode },
|
{ "getShaderCode", l_lovrShaderBlockGetShaderCode },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue