mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-27 10:30:08 +01:00
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>
|
||
|---|---|---|
| .. | ||
| es1api | ||
| es2api | ||
| glapi | ||
| new | ||
| shared-glapi | ||
| entry.c | ||
| entry.h | ||
| entry_ppc64le_tls.h | ||
| entry_x86-64_tls.h | ||
| entry_x86_tls.h | ||
| mapi_abi.py | ||
| mapi_tmp.h | ||
| meson.build | ||
| u_current.c | ||
| u_current.h | ||