Image uniforms;

This commit is contained in:
bjorn 2018-08-10 03:37:02 -07:00
parent d961614184
commit 9ce462a67f
4 changed files with 56 additions and 36 deletions

View File

@ -37,7 +37,7 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
memcpy(dest, blob->data, elements * sizeof(int));
break;
case UNIFORM_SAMPLER:
case UNIFORM_TEXTURE:
lovrThrow("Texture uniform '%s' can not be updated with a Blob", debug);
}
@ -54,7 +54,7 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
switch (uniform->type) {
case UNIFORM_FLOAT: *((float*) dest + i) = luaL_checknumber(L, -1); break;
case UNIFORM_INT: *((int*) dest + i) = luaL_checkinteger(L, -1); break;
case UNIFORM_SAMPLER: *((Texture**) dest + i) = luax_checktype(L, -1, Texture); break;
case UNIFORM_TEXTURE: *((Texture**) dest + i) = luax_checktype(L, -1, Texture); break;
default: break;
}
lua_pop(L, 1);
@ -64,7 +64,7 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
switch (uniform->type) {
case UNIFORM_FLOAT: *((float*) dest + i) = luaL_checknumber(L, index + i); break;
case UNIFORM_INT: *((int*) dest + i) = luaL_checkinteger(L, index + i); break;
case UNIFORM_SAMPLER: *((Texture**) dest + i) = luax_checktype(L, index + i, Texture); break;
case UNIFORM_TEXTURE: *((Texture**) dest + i) = luax_checktype(L, index + i, Texture); break;
default: break;
}
}
@ -98,7 +98,7 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
*((int*) dest + i * components + j) = luaL_checkinteger(L, -1);
break;
case UNIFORM_SAMPLER: lovrThrow("Unreachable");
case UNIFORM_TEXTURE: lovrThrow("Unreachable");
}
lua_pop(L, 1);
}
@ -125,7 +125,7 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
*((float*) dest + i * components + j) = luaL_checknumber(L, -1);
break;
case UNIFORM_SAMPLER: lovrThrow("Unreachable");
case UNIFORM_TEXTURE: lovrThrow("Unreachable");
}
}
}
@ -193,7 +193,7 @@ int l_lovrShaderSend(lua_State* L) {
case UNIFORM_FLOAT: lovrShaderSetFloat(shader, uniform->name, tempData.data, uniform->count * uniform->components); break;
case UNIFORM_INT: lovrShaderSetInt(shader, uniform->name, tempData.data, uniform->count * uniform->components); break;
case UNIFORM_MATRIX: lovrShaderSetMatrix(shader, uniform->name, tempData.data, uniform->count * uniform->components * uniform->components); break;
case UNIFORM_SAMPLER: lovrShaderSetTexture(shader, uniform->name, tempData.data, uniform->count); break;
case UNIFORM_TEXTURE: lovrShaderSetTexture(shader, uniform->name, tempData.data, uniform->count); break;
}
return 0;
}

View File

@ -247,6 +247,4 @@ void lovrGpuClear(Canvas** canvas, int canvasCount, Color* color, float* depth,
void lovrGpuDraw(DrawCommand* command);
void lovrGpuCompute(Shader* shader, int x, int y, int z);
void lovrGpuPresent();
void lovrGpuBindTexture(Texture* texture, int slot);
void lovrGpuDirtyTexture(int slot);

View File

@ -23,6 +23,7 @@
// Types
#define MAX_TEXTURES 16
#define MAX_IMAGES 8
#define MAX_BLOCK_BUFFERS 8
#define LOVR_SHADER_POSITION 0
@ -54,6 +55,7 @@ static struct {
uint32_t indexBuffer;
uint32_t program;
Texture* textures[MAX_TEXTURES];
Texture* images[MAX_IMAGES];
uint32_t blockBuffers[2][MAX_BLOCK_BUFFERS];
uint32_t vertexArray;
uint32_t vertexBuffer;
@ -288,7 +290,13 @@ static UniformType getUniformType(GLenum type, const char* debug) {
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
return UNIFORM_SAMPLER;
#ifdef GL_ARB_shader_image_load_store
case GL_IMAGE_2D:
case GL_IMAGE_3D:
case GL_IMAGE_CUBE:
case GL_IMAGE_2D_ARRAY:
#endif
return UNIFORM_TEXTURE;
default:
lovrThrow("Unsupported uniform type for uniform '%s'", debug);
return UNIFORM_FLOAT;
@ -297,13 +305,6 @@ static UniformType getUniformType(GLenum type, const char* debug) {
static int getUniformComponents(GLenum type) {
switch (type) {
case GL_FLOAT:
case GL_INT:
case GL_SAMPLER_2D:
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
return 1;
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_FLOAT_MAT2:
@ -373,6 +374,16 @@ static const char* getUniformTypeName(const Uniform* uniform) {
return "";
}
static Texture* lovrGpuGetDefaultTexture() {
if (!state.defaultTexture) {
TextureData* textureData = lovrTextureDataGetBlank(1, 1, 0xff, FORMAT_RGBA);
state.defaultTexture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true, false);
lovrRelease(textureData);
}
return state.defaultTexture;
}
// GPU
static void lovrGpuBindFramebuffer(uint32_t framebuffer) {
@ -389,25 +400,16 @@ static void lovrGpuBindIndexBuffer(uint32_t indexBuffer) {
}
}
void lovrGpuBindTexture(Texture* texture, int slot) {
static void lovrGpuBindTexture(Texture* texture, int slot) {
lovrAssert(slot >= 0 && slot < MAX_TEXTURES, "Invalid texture slot %d", slot);
if (!texture) {
if (!state.defaultTexture) {
TextureData* textureData = lovrTextureDataGetBlank(1, 1, 0xff, FORMAT_RGBA);
state.defaultTexture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true, false);
lovrRelease(textureData);
}
texture = state.defaultTexture;
}
texture = texture ? texture : lovrGpuGetDefaultTexture();
if (texture != state.textures[slot]) {
lovrRetain(texture);
lovrRelease(state.textures[slot]);
state.textures[slot] = texture;
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(texture->target, lovrTextureGetId(texture));
glBindTexture(texture->target, texture->id);
}
}
@ -416,6 +418,20 @@ void lovrGpuDirtyTexture(int slot) {
state.textures[slot] = NULL;
}
static void lovrGpuBindImage(Texture* texture, int slot) {
#ifndef EMSCRIPTEN
lovrAssert(slot >= 0 && slot < MAX_IMAGES, "Invalid image slot %d", slot);
texture = texture ? texture : lovrGpuGetDefaultTexture();
if (texture != state.images[slot]) {
lovrRetain(texture);
lovrRelease(state.textures[slot]);
state.images[slot] = texture;
glBindImageTexture(slot, texture->id, 0, false, 0, GL_READ_WRITE, texture->slices[0]->format);
}
#endif
}
static void lovrGpuBindBlockBuffer(BlockType type, uint32_t buffer, int slot) {
if (state.blockBuffers[type][slot] != buffer) {
state.blockBuffers[type][slot] = buffer;
@ -1390,7 +1406,8 @@ static void lovrShaderSetupUniforms(Shader* shader) {
uniform.location = glGetUniformLocation(program, uniform.name);
uniform.type = getUniformType(glType, uniform.name);
uniform.components = getUniformComponents(glType);
uniform.baseTextureSlot = (uniform.type == UNIFORM_SAMPLER) ? textureSlot : -1;
uniform.baseTextureSlot = uniform.type == UNIFORM_TEXTURE ? textureSlot : -1;
uniform.image = glType == GL_IMAGE_2D || glType == GL_IMAGE_3D || glType == GL_IMAGE_CUBE || glType == GL_IMAGE_2D_ARRAY;
int blockIndex;
glGetActiveUniformsiv(program, 1, &i, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
@ -1432,7 +1449,7 @@ static void lovrShaderSetupUniforms(Shader* shader) {
uniform.value.data = calloc(1, uniform.size);
break;
case UNIFORM_SAMPLER:
case UNIFORM_TEXTURE:
uniform.size = uniform.components * uniform.count * MAX(sizeof(Texture*), sizeof(int));
uniform.value.data = calloc(1, uniform.size);
@ -1477,7 +1494,7 @@ static void lovrShaderSetupUniforms(Shader* shader) {
map_set(&shader->uniformMap, uniform.name, shader->uniforms.length);
vec_push(&shader->uniforms, uniform);
textureSlot += (uniform.type == UNIFORM_SAMPLER) ? uniform.count : 0;
textureSlot += uniform.type == UNIFORM_TEXTURE ? uniform.count : 0;
}
}
@ -1598,7 +1615,7 @@ void lovrShaderBind(Shader* shader) {
int i;
Uniform* uniform;
vec_foreach_ptr(&shader->uniforms, uniform, i) {
if (uniform->type != UNIFORM_SAMPLER && !uniform->dirty) {
if (uniform->type != UNIFORM_TEXTURE && !uniform->dirty) {
continue;
}
@ -1633,9 +1650,13 @@ void lovrShaderBind(Shader* shader) {
}
break;
case UNIFORM_SAMPLER:
case UNIFORM_TEXTURE:
for (int i = 0; i < count; i++) {
lovrGpuBindTexture(uniform->value.textures[i], uniform->baseTextureSlot + i);
if (uniform->image) {
//lovrGpuBindImage(uniform->value.textures[i], uniform->baseTextureSlot + i);
} else {
lovrGpuBindTexture(uniform->value.textures[i], uniform->baseTextureSlot + i);
}
}
break;
}
@ -1714,7 +1735,7 @@ void lovrShaderSetMatrix(Shader* shader, const char* name, float* data, int coun
}
void lovrShaderSetTexture(Shader* shader, const char* name, Texture** data, int count) {
lovrShaderSetUniform(shader, name, UNIFORM_SAMPLER, data, count, sizeof(Texture*), "texture");
lovrShaderSetUniform(shader, name, UNIFORM_TEXTURE, data, count, sizeof(Texture*), "texture");
}
ShaderBlock* lovrShaderGetBlock(Shader* shader, const char* name) {

View File

@ -23,7 +23,7 @@ typedef enum {
UNIFORM_FLOAT,
UNIFORM_MATRIX,
UNIFORM_INT,
UNIFORM_SAMPLER
UNIFORM_TEXTURE
} UniformType;
typedef enum {
@ -55,6 +55,7 @@ typedef struct {
Texture** textures;
} value;
int baseTextureSlot;
bool image;
bool dirty;
} Uniform;