Move GL sampler state tracking into GLRenderManager/QueueRunner.

This commit is contained in:
Henrik Rydgård 2017-12-27 14:33:18 +01:00
parent 43ebbbcdb6
commit 5c7c7ce192
6 changed files with 72 additions and 38 deletions

View file

@ -1965,6 +1965,8 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32
}
// No need to free on failure, that's the caller's job (it likely will reuse a buffer.)
bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w);
// After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
// That may have unbound the framebuffer, rebind to avoid crashes when debugging.
RebindFramebuffer();
return retval;

View file

@ -148,16 +148,8 @@ struct TexCacheEntry {
u32 framesUntilNextFullHash;
u32 fullhash;
u32 cluthash;
float lodBias;
u16 maxSeenV;
// Cache the current filter settings so we can avoid setting it again.
// (OpenGL ES 2.0 madness where filter settings are attached to each texture. Unused in other backends).
u8 magFilt;
u8 minFilt;
bool sClamp;
bool tClamp;
TexStatus GetHashStatus() {
return TexStatus(status & STATUS_MASK);
}

View file

@ -171,7 +171,6 @@ void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
dxstate.texMaxMipLevel.set(0);
dxstate.texMipLodBias.set(0.0f);
}
entry.lodBias = lodBias;
} else {
dxstate.texMaxMipLevel.set(0);
dxstate.texMipLodBias.set(0.0f);

View file

@ -130,7 +130,7 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
float maxLod = 0.0f;
if (maxLevel != 0) {
// TODO: What about a swap of autoMip mode?
if (force || entry.lodBias != lodBias) {
if (true) {
if (mode == GE_TEXLEVEL_MODE_AUTO) {
minLod = 0.0f;
maxLod = (float)maxLevel;
@ -147,7 +147,6 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
minLod = 0.0f;
maxLod = (float)maxLevel;
}
entry.lodBias = lodBias;
}
} else {
minLod = 0.0f;
@ -156,14 +155,8 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
render_->SetTextureLod(minLod, maxLod, lodBias);
}
if (force || entry.minFilt != minFilt || entry.magFilt != magFilt || entry.sClamp != sClamp || entry.tClamp != tClamp) {
float aniso = 0.0f;
render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso);
entry.minFilt = minFilt;
entry.magFilt = magFilt;
entry.sClamp = sClamp;
entry.tClamp = tClamp;
}
float aniso = 0.0f;
render_->SetTextureSampler(sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso);
CHECK_GL_ERROR_IF_DEBUG();
}

View file

@ -409,8 +409,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
GLRFramebuffer *fb = step.render.framebuffer;
GLRProgram *curProgram = nullptr;
int activeTexture = 0;
glActiveTexture(GL_TEXTURE0 + activeTexture);
int activeSlot = 0;
glActiveTexture(GL_TEXTURE0 + activeSlot);
// State filtering tracking.
int attrMask = 0;
@ -426,6 +426,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
GLuint blendEqColor = (GLuint)-1;
GLuint blendEqAlpha = (GLuint)-1;
GLRTexture *curTex[8]{};
auto &commands = step.commands;
for (const auto &c : commands) {
switch (c.cmd) {
@ -604,23 +606,27 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
case GLRRenderCommand::BINDTEXTURE:
{
GLint slot = c.texture.slot;
if (slot != activeTexture) {
if (slot != activeSlot) {
glActiveTexture(GL_TEXTURE0 + slot);
activeTexture = slot;
activeSlot = slot;
}
if (c.texture.texture) {
glBindTexture(c.texture.texture->target, c.texture.texture->texture);
if (curTex[slot] != c.texture.texture) {
glBindTexture(c.texture.texture->target, c.texture.texture->texture);
curTex[slot] = c.texture.texture;
}
} else {
glBindTexture(GL_TEXTURE_2D, 0); // Which target? Well we only use this one anyway...
curTex[slot] = nullptr;
}
break;
}
case GLRRenderCommand::BIND_FB_TEXTURE:
{
GLint slot = c.bind_fb_texture.slot;
if (slot != activeTexture) {
if (slot != activeSlot) {
glActiveTexture(GL_TEXTURE0 + slot);
activeTexture = slot;
activeSlot = slot;
}
if (c.bind_fb_texture.aspect == GL_COLOR_BUFFER_BIT) {
glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->color_texture);
@ -695,21 +701,55 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
}
break;
case GLRRenderCommand::TEXTURESAMPLER:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
if (c.textureSampler.anisotropy != 0.0f) {
{
GLRTexture *tex = curTex[activeSlot];
if (!tex) {
break;
}
if (tex->wrapS != c.textureSampler.wrapS) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
tex->wrapS = c.textureSampler.wrapS;
}
if (tex->wrapT != c.textureSampler.wrapT) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
tex->wrapT = c.textureSampler.wrapT;
}
if (tex->magFilter != c.textureSampler.magFilter) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
tex->magFilter = c.textureSampler.magFilter;
}
if (tex->minFilter != c.textureSampler.minFilter) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
tex->minFilter = c.textureSampler.minFilter;
}
if (tex->anisotropy != c.textureSampler.anisotropy) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
tex->anisotropy = c.textureSampler.anisotropy;
}
break;
}
case GLRRenderCommand::TEXTURELOD:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
{
GLRTexture *tex = curTex[activeSlot];
if (!tex) {
break;
}
#ifndef USING_GLES2
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
if (tex->lodBias != c.textureLod.lodBias) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
tex->lodBias = c.textureLod.lodBias;
}
#endif
if (tex->minLod != c.textureLod.minLod) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
tex->minLod = c.textureLod.minLod;
}
if (tex->maxLod != c.textureLod.maxLod) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
tex->maxLod = c.textureLod.maxLod;
}
break;
}
case GLRRenderCommand::RASTER:
if (c.raster.cullEnable) {
if (!cullEnabled) {
@ -744,7 +784,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
}
}
if (activeTexture != 0)
if (activeSlot != 0)
glActiveTexture(GL_TEXTURE0);
// Wipe out the current state.

View file

@ -111,9 +111,17 @@ public:
glDeleteTextures(1, &texture);
}
}
GLuint texture;
GLenum target;
// TODO: Move sampler params here so we can move the dirty-tracking from TextureCacheGLES to here.
GLuint texture = 0;
// Could also trust OpenGL defaults I guess..
GLenum target = 0xFFFF;
GLenum wrapS = 0xFFFF;
GLenum wrapT = 0xFFFF;
GLenum magFilter = 0xFFFF;
GLenum minFilter = 0xFFFF;
float anisotropy = -100000.0f;
float minLod = -100000.0f;
float maxLod = 100000.0f;
float lodBias = 0.0f;
};
class GLRBuffer {