diff --git a/renderdoc/data/glsl/debug_sample.frag b/renderdoc/data/glsl/debug_sample.frag index bff7afb00..17e7b9898 100644 --- a/renderdoc/data/glsl/debug_sample.frag +++ b/renderdoc/data/glsl/debug_sample.frag @@ -199,6 +199,66 @@ RESULT DoFetch2DMSArray() } #endif +/////////////////////////////////// +// OpImageSampleImplicitLodBias (used with bias on GLES due to inability to bias in samplers) + +RESULT DoSampleBias2D() +{ + return textureOffset(tex2D, input_uvwa.xy, fetch_offset.xy, debugsample.gles_bias); +} + +RESULT DoSampleBias3D() +{ + return textureOffset(tex3D, input_uvwa.xyz, fetch_offset.xyz, debugsample.gles_bias); +} + +RESULT DoSampleBiasCube() +{ +#if FLOAT_TEX + + // no offsets for cubes + return texture(texCube, input_uvwa.xyz, debugsample.gles_bias); + +#else + // cubes are only handled on float type + return RESULT(0, 0, 0, 0); +#endif +} + +RESULT DoSampleBias2DArray() +{ + return textureOffset(tex2DArray, input_uvwa.xyz, fetch_offset.xy, debugsample.gles_bias); +} + +#ifdef TEXSAMPLE_CUBE_ARRAY +RESULT DoSampleBiasCubeArray() +{ +#if FLOAT_TEX + + // no offsets for cubes + return texture(texCubeArray, input_uvwa.xyzw, debugsample.gles_bias); + +#else + // cubes are only handled on float type + return RESULT(0, 0, 0, 0); +#endif +} +#endif + +RESULT DoSampleDrefBias2D() +{ +#if FLOAT_TEX + + return vec4(textureOffset(tex2DShadow, vec3(input_uvwa.xy, debugsample.compare), fetch_offset.xy, + debugsample.gles_bias), + 0, 0, 0); + +#else + // shadow samplers only for FLOAT_TEX + return RESULT(0, 0, 0, 0); +#endif +} + /////////////////////////////////// // OpImageQueryLod diff --git a/renderdoc/data/glsl/glsl_ubos.h b/renderdoc/data/glsl/glsl_ubos.h index 8f0749fd8..7fa1e220f 100644 --- a/renderdoc/data/glsl/glsl_ubos.h +++ b/renderdoc/data/glsl/glsl_ubos.h @@ -240,6 +240,7 @@ BINDING(0) uniform DebugSampleUBO float compare; float lod; float minlod; + float gles_bias; } INST_NAME(debugsample); diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index eab48c3bf..393e80f46 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -1399,7 +1399,38 @@ GLuint GLReplay::MakeShaderDebugSampleProg(const SamplingProgramConfig &config) case SamplingProgramConfig::Tex2DMS: dim = "2DMS"; break; case SamplingProgramConfig::Tex2DMSArray: dim = "2DMSArray"; break; } - defines += StringFormat::Fmt("#define OPERATION %s%s\n", operation.c_str(), dim.c_str()); + + rdcstr manualBias = config.manualBias ? "Bias" : ""; + + if(config.manualBias) + { + if(config.op == SamplingProgramConfig::Sample) + { + switch(config.dim) + { + case SamplingProgramConfig::Tex2D: + case SamplingProgramConfig::Tex3D: + case SamplingProgramConfig::TexCube: + case SamplingProgramConfig::Tex2DArray: + case SamplingProgramConfig::TexCubeArray: + // these are fine + break; + default: RDCERR("Unsupported dimension %u with manual bias on sample", config.dim); + } + } + else if(config.op == SamplingProgramConfig::SampleDref) + { + RDCASSERT(config.dim == SamplingProgramConfig::Tex2D, (uint32_t)config.dim); + } + else + { + RDCERR("Unsupported operation with manual bias"); + } + } + + defines += StringFormat::Fmt("#define OPERATION %s%s%s\n", operation.c_str(), manualBias.c_str(), + dim.c_str()); + defines += StringFormat::Fmt("#define USE_GRAD %u\n", config.useGrad); ShaderType shaderType; diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index b3f1d62b1..5c404b718 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -156,6 +156,7 @@ struct SamplingProgramConfig uint32_t gatherChannel = 0; bool useGatherOffs = false; bool useGrad = false; + bool manualBias = false; rdcfixedarray gatherOffsets = {}; Vec3i fetchOffset; @@ -168,6 +169,7 @@ struct SamplingProgramConfig hash = ((hash << 5) + hash) + gatherChannel; hash = ((hash << 5) + hash) + useGatherOffs; hash = ((hash << 5) + hash) + useGrad; + hash = ((hash << 5) + hash) + manualBias; hash = ((hash << 5) + hash) + fetchOffset.x; hash = ((hash << 5) + hash) + fetchOffset.y; hash = ((hash << 5) + hash) + fetchOffset.z; diff --git a/renderdoc/driver/gl/gl_shaderdebug.cpp b/renderdoc/driver/gl/gl_shaderdebug.cpp index df29c0308..744cbd432 100644 --- a/renderdoc/driver/gl/gl_shaderdebug.cpp +++ b/renderdoc/driver/gl/gl_shaderdebug.cpp @@ -842,18 +842,27 @@ public: // explicit lod operations. So we instead push the bias into the sampler itself, which is // entirely equivalent. - lodBiasRestore = true; - if(sampler.name) + // can't do this on GLES, so we have to use implicit lod path + if(IsGLES) { - GL.glGetSamplerParameterfv(sampler.name, eGL_TEXTURE_LOD_BIAS, &lodBiasRestoreValue); - GL.glSamplerParameterf(sampler.name, eGL_TEXTURE_LOD_BIAS, lodBiasRestoreValue + bias); + uniformParams.gles_bias = bias; + config.manualBias = true; } else { - GL.glGetTextureParameterfvEXT(texture.name, texDetails.curType, eGL_TEXTURE_LOD_BIAS, - &lodBiasRestoreValue); - float val = lodBiasRestoreValue + bias; - GL.glTextureParameterfvEXT(texture.name, texDetails.curType, eGL_TEXTURE_LOD_BIAS, &val); + lodBiasRestore = true; + if(sampler.name) + { + GL.glGetSamplerParameterfv(sampler.name, eGL_TEXTURE_LOD_BIAS, &lodBiasRestoreValue); + GL.glSamplerParameterf(sampler.name, eGL_TEXTURE_LOD_BIAS, lodBiasRestoreValue + bias); + } + else + { + GL.glGetTextureParameterfvEXT(texture.name, texDetails.curType, eGL_TEXTURE_LOD_BIAS, + &lodBiasRestoreValue); + float val = lodBiasRestoreValue + bias; + GL.glTextureParameterfvEXT(texture.name, texDetails.curType, eGL_TEXTURE_LOD_BIAS, &val); + } } } } diff --git a/util/test/demos/gl/gl_shader_debug_zoo.cpp b/util/test/demos/gl/gl_shader_debug_zoo.cpp index 5a68a99a7..59d05558b 100644 --- a/util/test/demos/gl/gl_shader_debug_zoo.cpp +++ b/util/test/demos/gl/gl_shader_debug_zoo.cpp @@ -218,6 +218,7 @@ layout(binding = 0, std430) buffer ssbo_test layout(binding = 0) uniform sampler2D tex2d_test; layout(binding = 1) uniform samplerBuffer texBuf_test; +layout(binding = 2) uniform sampler2D bias_test; layout(location = 1) in vec4 v2fColor; layout(location = 2) in vec2 v2fUV; @@ -238,6 +239,7 @@ void main() col += dFdx(v2fUV).xyxy; col += texture(tex2d_test, v2fUV); col += texelFetch(texBuf_test, int(v2fUV.x*10)); + col += texture(bias_test, v2fUV, -0.8f); outColor = col; } @@ -564,6 +566,32 @@ void main() glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rgba8.width, rgba8.height, GL_RGBA, GL_UNSIGNED_BYTE, rgba8.data.data()); + int dim = 128, x = 0; + GLuint bias_tex = MakeTexture(); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, bias_tex); + glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA8, dim, dim); + std::vector mipdata; + + uint32_t bias_col[10] = { + 0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff00ff, + 0xffffff00, 0xff00ffff, 0xff000000, 0xffffffff, + }; + while(dim > 0) + { + mipdata.resize(dim * dim); + for(uint32_t &p : mipdata) + p = bias_col[x]; + + glTexSubImage2D(GL_TEXTURE_2D, x, 0, 0, dim, dim, GL_RGBA, GL_UNSIGNED_BYTE, mipdata.data()); + dim >>= 1; + x++; + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + // render offscreen to make picked values accurate GLuint fbo = MakeFBO(); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -571,6 +599,7 @@ void main() // Color render texture GLuint colattach = MakeTexture(); + glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, colattach); glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, screenWidth, screenHeight); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colattach, 0);