c9abb7ff6ef35de3fa2975fd1c1b4a76769a7804
The pointer/offset parameter is often NULL or a small number with VBOs.
The idea is:
- If the pointer/offset parameter is NULL/0, use a different cmd structure
and unmarshal function that doesn't contain the pointer/offset parameter
to save 8 bytes per call.
- If the cmd structure has a hole and the pointer/offset parameter is
a small number that fits into the hole, use a different cmd structure
and unmarshal function that stores the value within the hole using
a smaller type to save 8 bytes per call.
This implements those ideas. It will continue generating the most optimal
code even if we change the packing of other parameters.
This decreases the size of 1 frame in glthread batches by 21%
in Viewperf2020/Catia1.
Example of generated code for glVertexPointer with and without the pointer
parameter if it's NULL. See the arrows for comments.
/* VertexPointer: marshalled asynchronously */
struct marshal_cmd_VertexPointer
{
struct marshal_cmd_base cmd_base;
GLpacked16i size;
GLenum16 type;
GLclamped16i stride;
const GLvoid * pointer;
};
struct marshal_cmd_VertexPointer_packed
{
struct marshal_cmd_base cmd_base;
GLpacked16i size;
GLenum16 type;
GLclamped16i stride; // <------- no "pointer"
};
uint32_t _mesa_unmarshal_VertexPointer(struct gl_context *ctx, const struct marshal_cmd_VertexPointer *restrict cmd)
{
GLpacked16i size = cmd->size;
GLenum16 type = cmd->type;
GLclamped16i stride = cmd->stride;
const GLvoid * pointer = cmd->pointer;
CALL_VertexPointer(ctx->Dispatch.Current, (size, type, stride, pointer));
return align(sizeof(struct marshal_cmd_VertexPointer), 8) / 8;
}
uint32_t _mesa_unmarshal_VertexPointer_packed(struct gl_context *ctx, const struct marshal_cmd_VertexPointer_packed *restrict cmd)
{
GLpacked16i size = cmd->size;
GLenum16 type = cmd->type;
GLclamped16i stride = cmd->stride;
const GLvoid * pointer = (const GLvoid *)(uintptr_t)0; // <------- using NULL
CALL_VertexPointer(ctx->Dispatch.Current, (size, type, stride, pointer));
return align(sizeof(struct marshal_cmd_VertexPointer_packed), 8) / 8;
}
static void GLAPIENTRY
_mesa_marshal_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
if (!pointer) { // <------- the condition
int cmd_size = sizeof(struct marshal_cmd_VertexPointer_packed);
struct marshal_cmd_VertexPointer_packed *cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_VertexPointer_packed, cmd_size);
cmd->size = size < 0 ? UINT16_MAX : MIN2(size, UINT16_MAX);
cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->stride = CLAMP(stride, INT16_MIN, INT16_MAX);
} else {
int cmd_size = sizeof(struct marshal_cmd_VertexPointer);
struct marshal_cmd_VertexPointer *cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_VertexPointer, cmd_size);
cmd->size = size < 0 ? UINT16_MAX : MIN2(size, UINT16_MAX);
cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->stride = CLAMP(stride, INT16_MIN, INT16_MAX);
cmd->pointer = pointer;
}
_mesa_glthread_AttribPointer(ctx, VERT_ATTRIB_POS, MESA_PACK_VFORMAT(type, size, 0, 0, 0), stride, pointer);
}
Example of generated code for glNormalPointer using a smaller type:
/* NormalPointer: marshalled asynchronously */
struct marshal_cmd_NormalPointer
{
struct marshal_cmd_base cmd_base;
GLenum16 type;
GLclamped16i stride;
const GLvoid * pointer;
};
struct marshal_cmd_NormalPointer_packed
{
struct marshal_cmd_base cmd_base;
GLenum16 type;
GLclamped16i stride;
GLushort pointer; // <-------- truncated "pointer"
};
uint32_t _mesa_unmarshal_NormalPointer(struct gl_context *ctx, const struct marshal_cmd_NormalPointer *restrict cmd)
{
GLenum16 type = cmd->type;
GLclamped16i stride = cmd->stride;
const GLvoid * pointer = cmd->pointer;
CALL_NormalPointer(ctx->Dispatch.Current, (type, stride, pointer));
return align(sizeof(struct marshal_cmd_NormalPointer), 8) / 8;
}
uint32_t _mesa_unmarshal_NormalPointer_packed(struct gl_context *ctx, const struct marshal_cmd_NormalPointer_packed *restrict cmd)
{
GLenum16 type = cmd->type;
GLclamped16i stride = cmd->stride;
const GLvoid * pointer = (const GLvoid *)(uintptr_t)cmd->pointer; // <-------- upcasting
CALL_NormalPointer(ctx->Dispatch.Current, (type, stride, pointer));
return align(sizeof(struct marshal_cmd_NormalPointer_packed), 8) / 8;
}
static void GLAPIENTRY
_mesa_marshal_NormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
{
GET_CURRENT_CONTEXT(ctx);
if (((uintptr_t)pointer & 0xffff) == (uintptr_t)pointer) { // <-------- the condition
int cmd_size = sizeof(struct marshal_cmd_NormalPointer_packed);
struct marshal_cmd_NormalPointer_packed *cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_NormalPointer_packed, cmd_size);
cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->stride = CLAMP(stride, INT16_MIN, INT16_MAX);
cmd->pointer = (uintptr_t)pointer; /* truncated */ // <-------- the truncation
} else {
int cmd_size = sizeof(struct marshal_cmd_NormalPointer);
struct marshal_cmd_NormalPointer *cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_NormalPointer, cmd_size);
cmd->type = MIN2(type, 0xffff); /* clamped to 0xffff (invalid enum) */
cmd->stride = CLAMP(stride, INT16_MIN, INT16_MAX);
cmd->pointer = pointer;
}
_mesa_glthread_AttribPointer(ctx, VERT_ATTRIB_NORMAL, MESA_PACK_VFORMAT(type, 3, 1, 0, 0), stride, pointer);
}
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27350>
`Mesa <https://mesa3d.org>`_ - The 3D Graphics Library ====================================================== Source ------ This repository lives at https://gitlab.freedesktop.org/mesa/mesa. Other repositories are likely forks, and code found there is not supported. Build & install --------------- You can find more information in our documentation (`docs/install.rst <https://mesa3d.org/install.html>`_), but the recommended way is to use Meson (`docs/meson.rst <https://mesa3d.org/meson.html>`_): .. code-block:: sh $ mkdir build $ cd build $ meson .. $ sudo ninja install Support ------- Many Mesa devs hang on IRC; if you're not sure which channel is appropriate, you should ask your question on `OFTC's #dri-devel <irc://irc.oftc.net/dri-devel>`_, someone will redirect you if necessary. Remember that not everyone is in the same timezone as you, so it might take a while before someone qualified sees your question. To figure out who you're talking to, or which nick to ping for your question, check out `Who's Who on IRC <https://dri.freedesktop.org/wiki/WhosWho/>`_. The next best option is to ask your question in an email to the mailing lists: `mesa-dev\@lists.freedesktop.org <https://lists.freedesktop.org/mailman/listinfo/mesa-dev>`_ Bug reports ----------- If you think something isn't working properly, please file a bug report (`docs/bugs.rst <https://mesa3d.org/bugs.html>`_). Contributing ------------ Contributions are welcome, and step-by-step instructions can be found in our documentation (`docs/submittingpatches.rst <https://mesa3d.org/submittingpatches.html>`_). Note that Mesa uses gitlab for patches submission, review and discussions.
Description
Languages
C
75.5%
C++
17.2%
Python
2.7%
Rust
1.8%
Assembly
1.5%
Other
1%