Jump to content
  • Advertisement
Sign in to follow this  
CirdanValen

Very strange problem with Texture Units

This topic is 487 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have the following code:

    BindTextureUnit(&editor->devTexture, 0);
    BindTextureUnit(&editor->renderBuffer, 1);
    BindTextureUnit(&editor->lightBuffer, 2);
    BindTextureUnit(&editor->uiSprites, 3);
    GLenum err = glGetError();    

Which consists of:

_INTERNAL void
BindTextureUnit(Texture* texture, u32 unit)
{
    glActiveTexture(GL_TEXTURE0 + unit);
    glBindTexture(GL_TEXTURE_2D, texture->handle);
    texture->unit = unit;
}

This section before the game loop is the only place where I bind textures to texture units. Rest of the time I set the sampler in shaders. Also note that the GL Error is set to 0 through all of this.

The first three textures work as expected, no problems. I recently added the fourth texture "uiSprites". When I render anything with that texture, it comes out white. Now supposedly my GPU can handle 192 texture units, so I'm not running out...but for some reason the texture units above 2 don't work properly.

Here is what I've found in my investigations

- I know for sure that the textures are being loaded correctly. If I put uiSprites into the first texture unit, it renders correctly. Similarly, if I put devTexture into the 3rd unit, it renders white.

- If I comment out the first line, where devTexture is being bound, then I bind uiSprites to unit 0 AFTER binding the renderBuffer and lightBuffer...the texture is rendered as white. This means that the only time binding to texture unit 0 works is if I do it before the other two.

 

renderBuffer and lightBuffer are both Framebuffers and work correctly the whole time while testing this. I'm wracking my brain trying to figure out why a) the 3rd texture unit is white b) why is this order dependent?

 

 

 

 

 

Share this post


Link to post
Share on other sites
Advertisement

RenderDoc may give you some insight into what exactly the pipeline is seeing and where. Personally, I'm suspicious that you're not setting the sampler assignments correctly for the shader, since you still need to assign samplers to units. 

Share this post


Link to post
Share on other sites

Basically, I store the assigned texture unit in the Texture struct as seen above. When I go to set the uniform in the texture, I use that texture.unit. 

_INTERNAL void
UseTexture(RenderContext* context, Texture texture, u32 loc)
{
    if(context->cmdBufferSize > 0)
    {
        ASSERT(!"InvalidPath");
    }
    glUniform1i(loc, texture.unit);
}

The render part looks like this

glClearColor(0.0f, 0.0f, 0.0f, 1.f);
BeginRenderPass(&editor->renderContext, editor->spriteShader, SPRITE_SHADER_UNIFORM_TRANSFORM_MAT, viewMatrix, editor->renderBuffer);
{
    UseTexture(&editor->renderContext, editor->devTexture, SPRITE_SHADER_UNIFORM_TEXTURE);
    PushVertexBuffer(&editor->renderContext, editor->floorVbo, 6, RenderMode_Triangles);  
}
EndRenderPass(&editor->renderContext); 

So all I do to test this is change editor->devTexture to editor->uiSprite.   devTexture works, uiSprite doesn't. The same shader is used, so the sampler location doesn't change.

 

Renderdoc doesn't work on my application for some reason (Doesn't support OpenGL 4.5?). But i can use GLintercept to post the GL calls log if needed.

Edited by CirdanValen

Share this post


Link to post
Share on other sites

Quick update: I went through and did glBindTexture(GL_TEXTURE_2D, 0) after creating the frame buffers. Now instead of being white, the texture comes out as black. Same order dependency as before. Calling glGetError() at the end of the game loop still returns 0.

Share this post


Link to post
Share on other sites

random guess from the dark: it's trying to mipmap a texture that doesn't have mipmaps, i.e. it has nothing to do with texture units and all to do with how you're using the texture bound to the unit.

Share this post


Link to post
Share on other sites

regular tex parameters

 

_INTERNAL Texture
CreateTexture(Bitmap bitmap, b32 convertToLinear) 
{
    Texture result = {};
    result.handle = UINT_MAX;
    result.width = bitmap.width;
    result.height = bitmap.height;




    glGenTextures(1, &result.handle);
    glBindTexture(GL_TEXTURE_2D, result.handle);


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);


GLenum colorType = (convertToLinear) ? GL_SRGB8_ALPHA8 : GL_RGBA;


    glTexImage2D(GL_TEXTURE_2D, 0, colorType, bitmap.width, bitmap.height, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, bitmap.pixels);


    glBindTexture(GL_TEXTURE_2D, 0);


    return result;
}

Share this post


Link to post
Share on other sites

EDIT: here's the GL command call log http://pastebin.com/0xxVqDQq

Couple more points to add:

Another strange discovery I found is that if I comment out the last texture bind, by doing this:

    BindTextureUnit(&editor->devTexture, 0);
    BindTextureUnit(&editor->renderBuffer, 1);
    BindTextureUnit(&editor->lightBuffer, 2);
    //BindTextureUnit(&editor->uiSprites, 3);

The first texture, devTexture at unit 0, renders as black. If I uncomment it, it works fine.

 

Secondly, I have a previous revision of this code that works with all four texture units bound. The difference between this code base and the previous one, is this one I have converted to 3D rendering with depth testing. This is how I build the frame buffers with depth texture:

_INTERNAL RenderBuffer 
CreateRenderBuffer(u32 width, u32 height, b32 hasDepthBuffer = true) 
{
    RenderBuffer result = {};


    result.width = width;
    result.height = height;


    glGenFramebuffers(1, &result.fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, result.fbo);


    glGenTextures(1, &result.texture);
    glBindTexture(GL_TEXTURE_2D, result.texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);


    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, result.texture, 0);


    
    if(hasDepthBuffer)
    {
        glGenTextures(1, &result.depth);
        glBindTexture(GL_TEXTURE_2D, result.depth);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);        


        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0,
                     GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);    


        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, result.depth, 0);        
    } 


    GLenum drawBuffers[1] = {
       GL_COLOR_ATTACHMENT0
    };    


    glDrawBuffers(1, drawBuffers);
    
    GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    ASSERT(fboStatus == GL_FRAMEBUFFER_COMPLETE);
    
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);


    return result;
}

Could the two be somehow related? I've double checked the generated texture IDs and none of them are overlapping. No gl errors even after multiple frames and the frambuffers don't trigger the assert.

Edited by CirdanValen

Share this post


Link to post
Share on other sites

Hi, do you sample your depth texture with a samplerShadow ?
This is usually what I use the compare func for, and except for that, I don't use it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!