diff --git a/docs/gallium/screen.rst b/docs/gallium/screen.rst index 8458cada7a1..ab9087f68eb 100644 --- a/docs/gallium/screen.rst +++ b/docs/gallium/screen.rst @@ -629,6 +629,7 @@ The integer capabilities: * ``PIPE_CAP_SUPPORTED_PRIM_MODES_WITH_RESTART``: A bitmask of the ``pipe_prim_type`` enum values that the driver can natively support for primitive restart. Only useful if ``PIPE_CAP_PRIMITIVE_RESTART`` is also exported. * ``PIPE_CAP_PREFER_BACK_BUFFER_REUSE``: Only applies to DRI_PRIME. If 1, the driver prefers that DRI3 tries to use the same back buffer each frame. If 0, this means DRI3 will at least use 2 back buffers and ping-pong between them to allow the tiled->linear copy to run in parallel. * ``PIPE_CAP_DRAW_VERTEX_STATE``: Driver supports `pipe_screen::create_vertex_state/vertex_state_destroy` and `pipe_context::draw_vertex_state`. Only used by display lists and designed to serve vbo_save. +* ``PIPE_CAP_PREFER_POT_ALIGNED_VARYINGS``: Driver prefers varyings to be aligned to power of two in a slot. If this cap is enabled, vec4 varying will be placed in .xyzw components of the varying slot, vec3 in .xyz and vec2 in .xy or .zw .. _pipe_capf: diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp index 30f83b21d32..4f8e5566d1c 100644 --- a/src/compiler/glsl/link_varyings.cpp +++ b/src/compiler/glsl/link_varyings.cpp @@ -1719,6 +1719,7 @@ public: bool disable_xfb_packing, bool xfb_enabled, bool enhanced_layouts_enabled, + bool prefer_pot_aligned_varyings, gl_shader_stage producer_stage, gl_shader_stage consumer_stage); ~varying_matches(); @@ -1760,6 +1761,12 @@ private: const bool enhanced_layouts_enabled; + /** + * If true, this driver prefers varyings to be aligned to power of two + * in a slot. + */ + const bool prefer_pot_aligned_varyings; + /** * Enum representing the order in which varyings are packed within a * packing class. @@ -1838,12 +1845,14 @@ varying_matches::varying_matches(bool disable_varying_packing, bool disable_xfb_packing, bool xfb_enabled, bool enhanced_layouts_enabled, + bool prefer_pot_aligned_varyings, gl_shader_stage producer_stage, gl_shader_stage consumer_stage) : disable_varying_packing(disable_varying_packing), disable_xfb_packing(disable_xfb_packing), xfb_enabled(xfb_enabled), enhanced_layouts_enabled(enhanced_layouts_enabled), + prefer_pot_aligned_varyings(prefer_pot_aligned_varyings), producer_stage(producer_stage), consumer_stage(consumer_stage) { @@ -2046,10 +2055,15 @@ varying_matches::assign_locations(struct gl_shader_program *prog, * packing vec3 attributes can cause trouble because splitting a vec3 * effectively creates an additional transform feedback output. The * extra TFB output may exceed device driver limits. + * + * Also don't pack vec3 if the driver prefers power of two aligned + * varyings. Packing order guarantees that vec4, vec2 and vec1 will be + * pot-aligned, we only need to take care of vec3s */ const bool dont_pack_vec3 = (prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS && - prog->TransformFeedback.NumVarying > 0); + prog->TransformFeedback.NumVarying > 0) || + this->prefer_pot_aligned_varyings; for (unsigned i = 0; i < this->num_matches; i++) { unsigned *location = &generic_location; @@ -2794,10 +2808,14 @@ assign_varying_locations(struct gl_context *ctx, if (prog->SeparateShader && (producer == NULL || consumer == NULL)) disable_varying_packing = true; + bool prefer_pot_aligned_varyings = + ctx->Const.PreferPOTAlignedVaryings; + varying_matches matches(disable_varying_packing, disable_xfb_packing, xfb_enabled, ctx->Extensions.ARB_enhanced_layouts, + prefer_pot_aligned_varyings, producer ? producer->Stage : MESA_SHADER_NONE, consumer ? consumer->Stage : MESA_SHADER_NONE); void *hash_table_ctx = ralloc_context(NULL); diff --git a/src/gallium/auxiliary/util/u_screen.c b/src/gallium/auxiliary/util/u_screen.c index c7e26d54da4..399c8c7c815 100644 --- a/src/gallium/auxiliary/util/u_screen.c +++ b/src/gallium/auxiliary/util/u_screen.c @@ -476,6 +476,9 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen, case PIPE_CAP_DRAW_VERTEX_STATE: return 0; + case PIPE_CAP_PREFER_POT_ALIGNED_VARYINGS: + return 0; + default: unreachable("bad PIPE_CAP_*"); } diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 0bcc5de7e26..46220b00423 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -998,6 +998,7 @@ enum pipe_cap PIPE_CAP_SUPPORTED_PRIM_MODES_WITH_RESTART, PIPE_CAP_PREFER_BACK_BUFFER_REUSE, PIPE_CAP_DRAW_VERTEX_STATE, + PIPE_CAP_PREFER_POT_ALIGNED_VARYINGS, PIPE_CAP_LAST, /* XXX do not add caps after PIPE_CAP_LAST! */ diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 85672a63892..acf28cbd6cc 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -4155,6 +4155,14 @@ struct gl_constants */ GLboolean DisableTransformFeedbackPacking; + /** + * Align varyings to POT in a slot + * + * Drivers that prefer varyings to be aligned to POT must set this value to GL_TRUE + */ + GLboolean PreferPOTAlignedVaryings; + + /** * UBOs and SSBOs can be packed tightly by the OpenGL implementation when * layout is set as shared (the default) or packed. However most Mesa drivers diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 214c38e1349..850dd1236e8 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -1550,6 +1550,9 @@ void st_init_extensions(struct pipe_screen *screen, if (!screen->get_param(screen, PIPE_CAP_PACKED_STREAM_OUTPUT)) consts->DisableTransformFeedbackPacking = GL_TRUE; + if (screen->get_param(screen, PIPE_CAP_PREFER_POT_ALIGNED_VARYINGS)) + consts->PreferPOTAlignedVaryings = GL_TRUE; + unsigned max_fb_fetch_rts = screen->get_param(screen, PIPE_CAP_FBFETCH); bool coherent_fb_fetch = screen->get_param(screen, PIPE_CAP_FBFETCH_COHERENT);