Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: Rendering with transform feedback

  1. #1
    Junior Member Regular Contributor
    Join Date
    Mar 2009
    Location
    Seattle, WA
    Posts
    214

    Rendering with transform feedback

    I'm implementing a vegetation rendering system using GPU-based frustum culling with transform feedback. I write the instance IDs into a texture during the culling pre-pass, and then I read the IDs back in the rendering pass.

    On Nvidia hardware this works fine. On AMD hardware I am receiving an INVALID_OPERATION error on glDrawElements() during the rendering pass. I'm not seeing anything in the documentation that really explains this:
    https://www.opengl.org/sdk/docs/man/...Elements.xhtml

    I also notice that if the pre-pass shader emits no vertices, the error does not occur. An error only occurs when data has been written into the transform feedback buffer.

    This is my pre-pass function. Is there something else I need to call to make the transform feedback texture ready for reading?
    Code :
        void VegetationLayer::PrePass(Camera* camera)    {
            if (variationmatrices == NULL) BuildVariationMatrices();
            model->surfaces[0]->material->SetTexture(variationmap, 5);
     
     
            if (query[camera] == 0)
            {
                glGenQueries(1, &query[camera]);
                glGenTransformFeedbacks(1, &transformfeedback[camera]);
                glGenBuffers(1, &feedbackbuffer[camera]);
                glBindBuffer(GL_TEXTURE_BUFFER, feedbackbuffer[camera]);
                glBufferData(GL_TEXTURE_BUFFER, maxinstancesdrawn * 4, NULL, GL_DYNAMIC_COPY);
                glGenTextures(1, &buffertexture);
                glBindTexture(GL_TEXTURE_BUFFER, buffertexture);
                glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, feedbackbuffer[camera]);
            }
     
     
            Mat4 mat;
            Vec4 color = Vec4(1.0);
            Vec3 campos = camera->GetPosition(true);
            int count = cellresolution * cellresolution * cellcount * cellcount;
     
     
            instancesurface->Enable();
            shader_frustumcull->Enable();
            for (int n = 0; n < 6; n++)
            {
                shader_frustumcull->SetVec4("frustumplane" + String(n), Vec4(camera->frustum->face[n]->plane.x, camera->frustum->face[n]->plane.y, camera->frustum->face[n]->plane.z, camera->frustum->face[n]->plane.d));
            }
            shader_frustumcull->SetVec3("aabbmin", model->localaabb.min);
            shader_frustumcull->SetVec3("aabbmax", model->localaabb.max);
            shader_frustumcull->SetFloat("TerrainSize", terrain->resolution * terrain->scale.x);
            shader_frustumcull->SetFloat("TerrainHeight", terrain->scale.y);
            shader_frustumcull->SetFloat("TerrainResolution", terrain->resolution);
            shader_frustumcull->SetFloat("CellResolution", cellresolution * cellcount);
            shader_frustumcull->SetFloat("Density", density);
            shader_frustumcull->SetFloat("BillboardDistance", billboarddistance);
            shader_frustumcull->SetVec2("InstanceOffset", Vec2(0));
            shader_frustumcull->SetInt("VBOSize", instancesurface->CountVertices());
            shader_frustumcull->SetInt("NumInstances", count);
     
     
            terrain->heightmap->SetFilter(Texture::Smooth);
            terrain->heightmap->Bind(6);
            terrain->normalmap->Bind(7);
     
     
            glEnable(GL_RASTERIZER_DISCARD);
            glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, feedbackbuffer[camera]);
            glBeginTransformFeedback(GL_POINTS);
            glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query[camera]);
     
     
            int passsize = instancesurface->CountVertices();
            int passes = ceil((float)count / (float)passsize);
     
     
            instancesurface->Draw(passes);
     
     
            glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
            glEndTransformFeedback();
            instancesurface->Disable();
            glDisable(GL_RASTERIZER_DISCARD);
        }
    Last edited by JoshKlint; 09-03-2015 at 10:01 AM.

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,730
    If the buffer still bound to GL_TRANSFORM_FEEDBACK_BUFFER when you try to use it as a source texture?

    I think that this shouldn't matter provided that transform-feedback is disabled (and according to the documentation, the only thing that should result in an error is if the buffer is mapped), but I make a habit of unbinding objects as soon as the binding isn't strictly required.

    Also: have you confirmed that the error is originating from glDrawElements() (I.e. glGetError() returns GL_NO_ERROR immediately prior to that call)?

  3. #3
    Junior Member Regular Contributor
    Join Date
    Mar 2009
    Location
    Seattle, WA
    Posts
    214
    It's definitely occurring on glDrawElements(), and it's definitely due to the texture lookup in the vertex shader. Adding a call to glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0) at the end of the prepass function has no effect.

  4. #4
    Junior Member Regular Contributor
    Join Date
    Mar 2009
    Location
    Seattle, WA
    Posts
    214
    I got it working by switching over to render into vertex buffers. This probably didn't directly do anything, but it simplified the code:
    http://rastergrid.com/blog/2010/06/i...tion-reloaded/

    I also found that Intel drivers produce an INVALID_OPERATION error if no fragment shader is present. No other explanation, they just throw the error on any glDraw function.

    1.6 million polys on Intel integrated graphics. No billboarding yet, but zero mem usage and zero client-side culling expense:

    Click image for larger version. 

Name:	blogentry-1-0-58957100-1441927840_thumb.jpg 
Views:	115 
Size:	63.8 KB 
ID:	2085

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •