Pass:setSampler;

This is an experimental take on the "default filter" system.  Each
render Pass has its own "global sampler", initialized to trilinear.  The
global sampler will be used by default to sample textures/materials in
shaders.  You can set it to a filter mode or a full Sampler object.  You
can always send your own Sampler objects to Shaders if you want
per-texture sampler settings.  The global sampler is designed to be set a
small number of times per pass instead of on every draw.  Basically,
just do Pass:setSampler('nearest') and draw your minecraft world.
This commit is contained in:
bjorn 2022-06-07 20:42:10 -07:00
parent a26e732ab0
commit ef19a334a9
3 changed files with 56 additions and 10 deletions

View File

@ -238,6 +238,19 @@ static int l_lovrPassSetDepthClamp(lua_State* L) {
return 0; return 0;
} }
static int l_lovrPassSetSampler(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
if (lua_type(L, 2) != LUA_TUSERDATA) {
FilterMode filter = luax_checkenum(L, 2, FilterMode, "linear");
Sampler* sampler = lovrGraphicsGetDefaultSampler(filter);
lovrPassSetSampler(pass, sampler);
} else {
Sampler* sampler = luax_checktype(L, 2, Sampler);
lovrPassSetSampler(pass, sampler);
}
return 0;
}
static int l_lovrPassSetScissor(lua_State* L) { static int l_lovrPassSetScissor(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass); Pass* pass = luax_checktype(L, 1, Pass);
uint32_t scissor[4]; uint32_t scissor[4];
@ -668,6 +681,7 @@ const luaL_Reg lovrPass[] = {
{ "setDepthWrite", l_lovrPassSetDepthWrite }, { "setDepthWrite", l_lovrPassSetDepthWrite },
{ "setDepthOffset", l_lovrPassSetDepthOffset }, { "setDepthOffset", l_lovrPassSetDepthOffset },
{ "setDepthClamp", l_lovrPassSetDepthClamp }, { "setDepthClamp", l_lovrPassSetDepthClamp },
{ "setSampler", l_lovrPassSetSampler },
{ "setScissor", l_lovrPassSetScissor }, { "setScissor", l_lovrPassSetScissor },
{ "setShader", l_lovrPassSetShader }, { "setShader", l_lovrPassSetShader },
{ "setStencilTest", l_lovrPassSetStencilTest }, { "setStencilTest", l_lovrPassSetStencilTest },

View File

@ -107,6 +107,7 @@ typedef struct {
typedef struct { typedef struct {
float color[4]; float color[4];
Shader* shader; Shader* shader;
Sampler* sampler;
uint64_t formatHash; uint64_t formatHash;
gpu_pipeline_info info; gpu_pipeline_info info;
float viewport[4]; float viewport[4];
@ -139,6 +140,7 @@ struct Pass {
Pipeline* pipeline; Pipeline* pipeline;
Pipeline pipelines[4]; Pipeline pipelines[4];
uint32_t pipelineIndex; uint32_t pipelineIndex;
bool samplerDirty;
char constants[256]; char constants[256];
bool constantsDirty; bool constantsDirty;
gpu_binding bindings[32]; gpu_binding bindings[32];
@ -237,7 +239,7 @@ static struct {
Attachment attachments[16]; Attachment attachments[16];
Buffer* defaultBuffer; Buffer* defaultBuffer;
Texture* defaultTexture; Texture* defaultTexture;
Sampler* defaultSampler; Sampler* defaultSamplers[2];
Shader* defaultShaders[DEFAULT_SHADER_COUNT]; Shader* defaultShaders[DEFAULT_SHADER_COUNT];
VertexFormat vertexFormats[DEFAULT_FORMAT_COUNT]; VertexFormat vertexFormats[DEFAULT_FORMAT_COUNT];
map_t pipelineLookup; map_t pipelineLookup;
@ -349,12 +351,14 @@ bool lovrGraphicsInit(bool debug, bool vsync) {
lovrRelease(image, lovrImageDestroy); lovrRelease(image, lovrImageDestroy);
state.defaultSampler = lovrSamplerCreate(&(SamplerInfo) { for (uint32_t i = 0; i < 2; i++) {
.min = FILTER_LINEAR, state.defaultSamplers[i] = lovrSamplerCreate(&(SamplerInfo) {
.mag = FILTER_LINEAR, .min = i == 0 ? FILTER_NEAREST : FILTER_LINEAR,
.mip = FILTER_LINEAR, .mag = i == 0 ? FILTER_NEAREST : FILTER_LINEAR,
.wrap = { WRAP_REPEAT, WRAP_REPEAT, WRAP_REPEAT } .mip = i == 0 ? FILTER_NEAREST : FILTER_LINEAR,
}); .wrap = { WRAP_REPEAT, WRAP_REPEAT, WRAP_REPEAT }
});
}
gpu_stream* transfers = getTransfers(); gpu_stream* transfers = getTransfers();
gpu_clear_buffer(transfers, state.defaultBuffer->gpu, 0, 4096); gpu_clear_buffer(transfers, state.defaultBuffer->gpu, 0, 4096);
@ -399,7 +403,8 @@ void lovrGraphicsDestroy() {
} }
lovrRelease(state.defaultBuffer, lovrBufferDestroy); lovrRelease(state.defaultBuffer, lovrBufferDestroy);
lovrRelease(state.defaultTexture, lovrTextureDestroy); lovrRelease(state.defaultTexture, lovrTextureDestroy);
lovrRelease(state.defaultSampler, lovrSamplerDestroy); lovrRelease(state.defaultSamplers[0], lovrSamplerDestroy);
lovrRelease(state.defaultSamplers[1], lovrSamplerDestroy);
for (uint32_t i = 0; i < COUNTOF(state.defaultShaders); i++) { for (uint32_t i = 0; i < COUNTOF(state.defaultShaders); i++) {
lovrRelease(state.defaultShaders[i], lovrShaderDestroy); lovrRelease(state.defaultShaders[i], lovrShaderDestroy);
} }
@ -901,6 +906,10 @@ const TextureInfo* lovrTextureGetInfo(Texture* texture) {
// Sampler // Sampler
Sampler* lovrGraphicsGetDefaultSampler(FilterMode mode) {
return state.defaultSamplers[mode];
}
Sampler* lovrSamplerCreate(SamplerInfo* info) { Sampler* lovrSamplerCreate(SamplerInfo* info) {
lovrCheck(info->range[1] < 0.f || info->range[1] >= info->range[0], "Invalid Sampler mipmap range"); lovrCheck(info->range[1] < 0.f || info->range[1] >= info->range[0], "Invalid Sampler mipmap range");
lovrCheck(info->anisotropy <= state.limits.anisotropy, "Sampler anisotropy (%f) exceeds anisotropy limit (%f)", info->anisotropy, state.limits.anisotropy); lovrCheck(info->anisotropy <= state.limits.anisotropy, "Sampler anisotropy (%f) exceeds anisotropy limit (%f)", info->anisotropy, state.limits.anisotropy);
@ -1458,6 +1467,7 @@ Pass* lovrGraphicsGetPass(PassInfo* info) {
pass->pipeline->formatHash = 0; pass->pipeline->formatHash = 0;
pass->pipeline->shader = NULL; pass->pipeline->shader = NULL;
pass->pipeline->dirty = true; pass->pipeline->dirty = true;
pass->samplerDirty = true;
memset(pass->constants, 0, sizeof(pass->constants)); memset(pass->constants, 0, sizeof(pass->constants));
pass->constantsDirty = true; pass->constantsDirty = true;
@ -1480,7 +1490,9 @@ Pass* lovrGraphicsGetPass(PassInfo* info) {
pass->builtins[0] = (gpu_binding) { 0, GPU_SLOT_UNIFORM_BUFFER, .buffer = cameras }; pass->builtins[0] = (gpu_binding) { 0, GPU_SLOT_UNIFORM_BUFFER, .buffer = cameras };
pass->builtins[1] = (gpu_binding) { 1, GPU_SLOT_UNIFORM_BUFFER, .buffer = draws }; pass->builtins[1] = (gpu_binding) { 1, GPU_SLOT_UNIFORM_BUFFER, .buffer = draws };
pass->builtins[2] = (gpu_binding) { 2, GPU_SLOT_SAMPLER, .sampler = state.defaultSampler->gpu }; pass->builtins[2] = (gpu_binding) { 2, GPU_SLOT_SAMPLER, .sampler = NULL };
pass->pipeline->sampler = state.defaultSamplers[FILTER_LINEAR];
pass->samplerDirty = true;
pass->vertexBuffer = NULL; pass->vertexBuffer = NULL;
pass->indexBuffer = NULL; pass->indexBuffer = NULL;
@ -1536,6 +1548,7 @@ void lovrPassPush(Pass* pass, StackType stack) {
lovrCheck(pass->pipelineIndex < COUNTOF(pass->pipelines), "%s stack overflow (more pushes than pops?)", "Pipeline"); lovrCheck(pass->pipelineIndex < COUNTOF(pass->pipelines), "%s stack overflow (more pushes than pops?)", "Pipeline");
memcpy(pass->pipeline, &pass->pipelines[pass->pipelineIndex - 1], sizeof(Pipeline)); memcpy(pass->pipeline, &pass->pipelines[pass->pipelineIndex - 1], sizeof(Pipeline));
lovrRetain(pass->pipeline->shader); lovrRetain(pass->pipeline->shader);
lovrRetain(pass->pipeline->sampler);
break; break;
default: break; default: break;
} }
@ -1553,6 +1566,8 @@ void lovrPassPop(Pass* pass, StackType stack) {
lovrCheck(pass->pipelineIndex < COUNTOF(pass->pipelines), "%s stack underflow (more pops than pushes?)", "Pipeline"); lovrCheck(pass->pipelineIndex < COUNTOF(pass->pipelines), "%s stack underflow (more pops than pushes?)", "Pipeline");
gpu_set_viewport(pass->stream, pass->pipeline->viewport, pass->pipeline->depthRange); gpu_set_viewport(pass->stream, pass->pipeline->viewport, pass->pipeline->depthRange);
gpu_set_scissor(pass->stream, pass->pipeline->scissor); gpu_set_scissor(pass->stream, pass->pipeline->scissor);
pass->pipeline->dirty = true;
pass->samplerDirty = true;
break; break;
default: break; default: break;
} }
@ -1701,6 +1716,15 @@ void lovrPassSetDepthClamp(Pass* pass, bool clamp) {
} }
} }
void lovrPassSetSampler(Pass* pass, Sampler* sampler) {
if (sampler != pass->pipeline->sampler) {
lovrRetain(sampler);
lovrRelease(pass->pipeline->sampler, lovrSamplerDestroy);
pass->pipeline->sampler = sampler;
pass->samplerDirty = true;
}
}
void lovrPassSetScissor(Pass* pass, uint32_t scissor[4]) { void lovrPassSetScissor(Pass* pass, uint32_t scissor[4]) {
gpu_set_scissor(pass->stream, scissor); gpu_set_scissor(pass->stream, scissor);
memcpy(pass->pipeline->scissor, scissor, 4 * sizeof(uint32_t)); memcpy(pass->pipeline->scissor, scissor, 4 * sizeof(uint32_t));
@ -1747,7 +1771,7 @@ void lovrPassSetShader(Pass* pass, Shader* shader) {
} else if (shader->textureMask & bit) { } else if (shader->textureMask & bit) {
pass->bindings[i].texture = state.defaultTexture->gpu; pass->bindings[i].texture = state.defaultTexture->gpu;
} else if (shader->samplerMask & bit) { } else if (shader->samplerMask & bit) {
pass->bindings[i].sampler = state.defaultSampler->gpu; pass->bindings[i].sampler = state.defaultSamplers[FILTER_LINEAR]->gpu;
} }
pass->bindingMask |= bit; pass->bindingMask |= bit;
@ -2044,6 +2068,12 @@ static void flushBuiltins(Pass* pass, Draw* draw, Shader* shader) {
rebind = true; rebind = true;
} }
if (pass->samplerDirty) {
pass->builtins[2].sampler = pass->pipeline->sampler->gpu;
pass->samplerDirty = false;
rebind = true;
}
if (rebind) { if (rebind) {
gpu_bundle_info bundleInfo = { gpu_bundle_info bundleInfo = {
.layout = state.layouts.data[state.builtinLayout].gpu, .layout = state.layouts.data[state.builtinLayout].gpu,

View File

@ -236,6 +236,7 @@ typedef struct {
float range[2]; float range[2];
} SamplerInfo; } SamplerInfo;
Sampler* lovrGraphicsGetDefaultSampler(FilterMode mode);
Sampler* lovrSamplerCreate(SamplerInfo* info); Sampler* lovrSamplerCreate(SamplerInfo* info);
void lovrSamplerDestroy(void* ref); void lovrSamplerDestroy(void* ref);
const SamplerInfo* lovrSamplerGetInfo(Sampler* sampler); const SamplerInfo* lovrSamplerGetInfo(Sampler* sampler);
@ -380,6 +381,7 @@ void lovrPassSetDepthTest(Pass* pass, CompareMode test);
void lovrPassSetDepthWrite(Pass* pass, bool write); void lovrPassSetDepthWrite(Pass* pass, bool write);
void lovrPassSetDepthOffset(Pass* pass, float offset, float sloped); void lovrPassSetDepthOffset(Pass* pass, float offset, float sloped);
void lovrPassSetDepthClamp(Pass* pass, bool clamp); void lovrPassSetDepthClamp(Pass* pass, bool clamp);
void lovrPassSetSampler(Pass* pass, Sampler* sampler);
void lovrPassSetScissor(Pass* pass, uint32_t scissor[4]); void lovrPassSetScissor(Pass* pass, uint32_t scissor[4]);
void lovrPassSetShader(Pass* pass, Shader* shader); void lovrPassSetShader(Pass* pass, Shader* shader);
void lovrPassSetStencilTest(Pass* pass, CompareMode test, uint8_t value, uint8_t mask); void lovrPassSetStencilTest(Pass* pass, CompareMode test, uint8_t value, uint8_t mask);