[Mesa-dev] [PATCH 2/5] meta: fix meta clear of layered framebuffers
Marek Olšák
maraeo at gmail.com
Thu Nov 21 05:21:20 PST 2013
I currently work on a simpler solution for Gallium. I'm using
AMD_vertex_shader_layer and this vertex shader (I wrote it in TGSI
though):
void main()
{
gl_Position = gl_Vertex;
gl_TexCoord[0] = MultiTexCoord0; // clear color
gl_Layer = gl_InstanceID;
}
Then I render the quad with DrawArraysInstanced and set the instance
count = NumLayers. That way each instance (each quad) is sent to a
different layer and everything is cleared in one draw call.
Drivers not supporting AMD_vertex_shader_layer will have to use a GS though.
Marek
On Wed, Nov 20, 2013 at 5:47 AM, Paul Berry <stereotype441 at gmail.com> wrote:
> From section 4.4.7 (Layered Framebuffers) of the GLSL 3.2 spec:
>
> When the Clear or ClearBuffer* commands are used to clear a
> layered framebuffer attachment, all layers of the attachment are
> cleared.
>
> This patch fixes meta clears to properly clear all layers of a layered
> framebuffer attachment. We accomplish this by adding a geometry
> shader to the meta clear program which sets gl_Layer to a uniform
> value. When clearing a layered framebuffer, we execute in a loop,
> setting the uniform to point to each layer in turn.
>
> Cc: "10.0" <mesa-stable at lists.freedesktop.org>
> ---
> src/mesa/drivers/common/meta.c | 51 +++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 48 insertions(+), 3 deletions(-)
>
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index 99b02ba..a6d5098 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -241,9 +241,11 @@ struct clear_state
> GLuint VBO;
> GLuint ShaderProg;
> GLint ColorLocation;
> + GLint LayerLocation;
>
> GLuint IntegerShaderProg;
> GLint IntegerColorLocation;
> + GLint IntegerLayerLocation;
> };
>
>
> @@ -2145,6 +2147,19 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
> "{\n"
> " gl_Position = position;\n"
> "}\n";
> + const char *gs_source =
> + "#version 150\n"
> + "layout(triangles) in;\n"
> + "layout(triangle_strip, max_vertices = 4) out;\n"
> + "uniform int layer;\n"
> + "void main()\n"
> + "{\n"
> + " for (int i = 0; i < 3; i++) {\n"
> + " gl_Layer = layer;\n"
> + " gl_Position = gl_in[i].gl_Position;\n"
> + " EmitVertex();\n"
> + " }\n"
> + "}\n";
> const char *fs_source =
> "#ifdef GL_ES\n"
> "precision highp float;\n"
> @@ -2154,7 +2169,7 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
> "{\n"
> " gl_FragColor = color;\n"
> "}\n";
> - GLuint vs, fs;
> + GLuint vs, gs = 0, fs;
> bool has_integer_textures;
>
> if (clear->ArrayObj != 0)
> @@ -2176,6 +2191,12 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
> _mesa_ShaderSource(vs, 1, &vs_source, NULL);
> _mesa_CompileShader(vs);
>
> + if (_mesa_has_geometry_shaders(ctx)) {
> + gs = _mesa_CreateShaderObjectARB(GL_GEOMETRY_SHADER);
> + _mesa_ShaderSource(gs, 1, &gs_source, NULL);
> + _mesa_CompileShader(gs);
> + }
> +
> fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER);
> _mesa_ShaderSource(fs, 1, &fs_source, NULL);
> _mesa_CompileShader(fs);
> @@ -2183,6 +2204,8 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
> clear->ShaderProg = _mesa_CreateProgramObjectARB();
> _mesa_AttachShader(clear->ShaderProg, fs);
> _mesa_DeleteObjectARB(fs);
> + if (gs != 0)
> + _mesa_AttachShader(clear->ShaderProg, gs);
> _mesa_AttachShader(clear->ShaderProg, vs);
> _mesa_DeleteObjectARB(vs);
> _mesa_BindAttribLocation(clear->ShaderProg, 0, "position");
> @@ -2190,6 +2213,10 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
>
> clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg,
> "color");
> + if (gs != 0) {
> + clear->LayerLocation = _mesa_GetUniformLocation(clear->ShaderProg,
> + "layer");
> + }
>
> has_integer_textures = _mesa_is_gles3(ctx) ||
> (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130);
> @@ -2227,6 +2254,8 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
> clear->IntegerShaderProg = _mesa_CreateProgramObjectARB();
> _mesa_AttachShader(clear->IntegerShaderProg, fs);
> _mesa_DeleteObjectARB(fs);
> + if (gs != 0)
> + _mesa_AttachShader(clear->IntegerShaderProg, gs);
> _mesa_AttachShader(clear->IntegerShaderProg, vs);
> _mesa_DeleteObjectARB(vs);
> _mesa_BindAttribLocation(clear->IntegerShaderProg, 0, "position");
> @@ -2240,7 +2269,13 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear)
>
> clear->IntegerColorLocation =
> _mesa_GetUniformLocation(clear->IntegerShaderProg, "color");
> + if (gs != 0) {
> + clear->IntegerLayerLocation =
> + _mesa_GetUniformLocation(clear->IntegerShaderProg, "layer");
> + }
> }
> + if (gs != 0)
> + _mesa_DeleteObjectARB(gs);
> }
>
> static void
> @@ -2371,8 +2406,18 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
> _mesa_BufferData(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
> GL_DYNAMIC_DRAW_ARB);
>
> - /* draw quad */
> - _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
> + /* draw quad(s) */
> + if (fb->Layered) {
> + for (unsigned layer = 0; layer < fb->NumLayers; layer++) {
> + if (fb->_IntegerColor)
> + _mesa_Uniform1i(clear->IntegerLayerLocation, layer);
> + else
> + _mesa_Uniform1i(clear->LayerLocation, layer);
> + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
> + }
> + } else {
> + _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
> + }
>
> _mesa_meta_end(ctx);
> }
> --
> 1.8.4.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list