baldurk / renderdoc

RenderDoc is a stand-alone graphics debugging tool.
https://renderdoc.org
MIT License
8.62k stars 1.3k forks source link

[Bug][OpenGLES] Sample mip1 and render into mip2 of same texture on mobile, renderdoc can not display texture result correctly #3297

Closed idovelemon closed 2 months ago

idovelemon commented 2 months ago

Description

I was doing texture downsampling with opengles on mobile. I have a texture which mip1 has some valid color in it, then i want to render into mip2 of the same texture with a pixel shader sampling from mip1. It works fine on my mobile device. But when i capture it with renderdoc, it display nothing on my rendertexture, and sometime it just disconnect with my device when i click the drawcall api in event browser.

Steps to reproduce

miplevel_read_write.zip

This is a demo project using android studio. You can run this demo with a android mobile device, and capture it with renderdoc to reproduce this bug.

Environment

baldurk commented 2 months ago

I can look into this in more detail soon hopefully but I took a quick look at the code and I think I might know what the problem is.

Does the problem still occur if you reset BASE_LEVEL and MAX_LEVEL to their proper values covering the whole texture after modifying them during the draw function? Something like this:

Java_com_example_myapplication_MyGLRenderer_glDraw(JNIEnv *env, jobject thiz, int width, int height) {
    GLint maxLevel = 0;
    glBindTexture(GL_TEXTURE_2D, texID);
    glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, &maxLevel);

    // ... rest of the code here ...

    glBindTexture(GL_TEXTURE_2D, texID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
    glCheckError();
}
idovelemon commented 2 months ago

I tried this, it won't work on my mobile device, nothing can display.

According OpenGLES 3.2 Spec, it will become "Rendering Feedback Loops" when you sample and render same miplevel. So it must be set by GL_TEXTURE_BASE_LEVEL/GL_TEXTURE_MAX_LEVEL to control which miplevel you can access in pixel shader, so that we do not conflict with render texture mipmap level.

In my example, i sample miplevel 1 and render into miplevel 2 to avoid rendering feedback loops.

baldurk commented 2 months ago

I understand what you're doing and yes it is valid, but I'm not sure why that change would break anything.

Just to be clear, I'm saying you should change BASE_LEVEL and MAX_LEVEL to their normal values after doing the rendering. Did you change which levels you were setting during the mip rendering? It won't sample and render to the same mip level because of the code you had originally, I'm just saying you suggesting you try restoring those values after rendering.

idovelemon commented 2 months ago

Sorry for the misunderstanding of your suggestion.

I try your reset method at the end of my code, it works correctly now.

Thanks for help!

baldurk commented 2 months ago

Aha that's good to know. In this case yes your application is doing nothing wrong and this change I suggested is not necessary for a legal application. But this is a scenario which is too difficult to be worth implementing proper handling for in RenderDoc.

GL is a poorly designed API and this modification of BASE/MAX_LEVEL is quite error prone since it controls both which mips are temporarily used as well as which are part of the texture in the first place - especially when using glTexImage for mutable texture dimensions.

RenderDoc will only work if these values change temporarily during rendering but are then restored to describe the full texture afterwards as with my suggested code. Otherwise it may determine the texture to be a different size or different number of mips than it really is. On proper GL this situation is a little better because you can use immutable texture storage and texture views, but on GLES you are limited to mutable textures only.

I'm going to close this issue since as above I don't think this is worth adding the extra handling for, for an API like GL.