4747#endif
4848
4949/* ---- Function name table -------------------------------------------------
50- Indexed by command.index. Used for bootstrapping and by the PFN-range
51- loader to call getProcAddr(name) for each slot. */
52- static const char * const kFnNames_{{ fs.spec_name | spec_display }}[] = {
50+ Command names stored as a single NUL-terminated string blob with a parallel
51+ offset table for O(1) indexing. This avoids one pointer (8 bytes on 64-bit)
52+ plus one relocation entry (~24 bytes in PIC builds) per command compared to
53+ the traditional const char * const [] approach. */
54+ #define kFnCount_{{ fs.spec_name | spec_display }} {{ fs.commands | length }}
55+
56+ static const char kFnNameData_{{ fs.spec_name | spec_display }}[] =
57+ {% - for cmd in fs .commands %}
58+ /* {{ fn_name_offsets[cmd.index] | rjust(5) }} */ "{{ cmd.name }}\0"
59+ {% - endfor %}
60+ ;
61+
62+ static const {{ fn_name_offset_type }} kFnNameOffsets_{{ fs.spec_name | spec_display }}[] = {
5363{% - for cmd in fs .commands %}
54- /* {{ cmd.index | rjust(4) }} */ " {{ cmd.name }}" {% if not loop .last %} ,{% endif %}
64+ /* {{ cmd.index | rjust(4) }} */ {{ fn_name_offsets[ cmd.inde x] | rjust(5) }} {% if not loop .last %} ,{% endif %} /* {{ cmd.name }} */
5565{% - endfor %}
5666};
5767
5868{% if fs .is_vulkan -%}
5969/* ---- Command scope table -------------------------------------------------
60- Indexed in lockstep with kFnNames_ {{ fs.spec_name | spec_display }}[]. Each entry is the GloamCommandScope
70+ Indexed in lockstep with kFnNameOffsets_ {{ fs.spec_name | spec_display }}[]. Each entry is the GloamCommandScope
6171 value for that slot — stored as uint8_t so the whole table is one byte per
6272 command (compares well against the alternatives: a parallel pointer array
6373 or a switch inside the loop). */
@@ -95,8 +105,10 @@ static const GloamPfnRange_t kFeatPfnRanges_{{ fs.spec_name | spec_display }}[]
95105static void gloam_load_pfn_range_{{ fs.spec_name }}({{ u.ctx_arg(', ') }}GloamLoadFunc getProcAddr,
96106 uint16_t start, uint16_t count) {
97107 uint16_t i;
98- for (i = start; i < (uint16_t)(start + count); ++i)
99- context->pfnArray[i] = (void *)getProcAddr(kFnNames_{{ fs.spec_name | spec_display }}[i]);
108+ for (i = start; i < (uint16_t)(start + count); ++i) {
109+ const char *pfnName = &kFnNameData_{{ fs.spec_name | spec_display }}[kFnNameOffsets_{{ fs.spec_name | spec_display }}[i]];
110+ context->pfnArray[i] = (void *)getProcAddr(pfnName);
111+ }
100112}
101113{% else -%}
102114/* ---- Vulkan scope-aware PFN range helper ---------------------------------
@@ -110,9 +122,11 @@ static void gloam_load_pfn_range_{{ fs.spec_name }}({{ u.ctx_arg(', ') }}GloamLo
110122static void gloam_load_pfn_range_{{ fs.spec_name }}({{ u.ctx_arg(', ') }}GloamVkUserptrLoadFunc load,
111123 void *userptr, uint16_t start, uint16_t count) {
112124 uint16_t i;
113- for (i = start; i < (uint16_t)(start + count); ++i)
114- context->pfnArray[i] = (void *)load(userptr, kFnNames_{{ fs.spec_name | spec_display }}[i],
115- (GloamCommandScope)kCommandScopes_{{ fs.spec_name | spec_display }}[i]);
125+ for (i = start; i < (uint16_t)(start + count); ++i) {
126+ const char *pfnName = &kFnNameData_{{ fs.spec_name | spec_display }}[kFnNameOffsets_{{ fs.spec_name | spec_display }}[i]];
127+ const GloamCommandScope cmdScope = (GloamCommandScope)kCommandScopes_{{ fs.spec_name | spec_display }}[i];
128+ context->pfnArray[i] = (void *)load(userptr, pfnName, cmdScope);
129+ }
116130}
117131{% endif %}
118132{% if alias and fs .alias_pairs | length > 0 -%}
@@ -719,8 +733,8 @@ int gloamLoad{{ api | api_display }}Context({{ u.ctx_arg(', ') }}Display *displa
719733 if (!version) return 0;
720734
721735 /* Load all PFNs upfront. */
722- for (i = 0; i < GLOAM_ARRAYSIZE(kFnNames_ {{ fs.spec_name | spec_display }}) ; ++i)
723- context->pfnArray[i] = (void *)getProcAddr(kFnNames_ {{ fs.spec_name | spec_display }}[i]);
736+ for (i = 0; i < kFnCount_ {{ fs.spec_name | spec_display }}; ++i)
737+ context->pfnArray[i] = (void *)getProcAddr((kFnNameData_ {{ fs.spec_name | spec_display }} + kFnNameOffsets_{{ fs.spec_name | spec_display }} [i]) );
724738
725739 /* Mark features based on PFN availability. */
726740 for (i = 0; i < GLOAM_ARRAYSIZE(kFeatPfnRanges_{{ fs.spec_name | spec_display }}); ++i) {
@@ -765,8 +779,8 @@ int gloamLoad{{ api | api_display }}Context({{ u.ctx_arg(', ') }}HDC hdc, GloamL
765779 if (!version) return 0;
766780
767781 /* Load all PFNs upfront. */
768- for (i = 0; i < GLOAM_ARRAYSIZE(kFnNames_ {{ fs.spec_name | spec_display }}) ; ++i)
769- context->pfnArray[i] = (void *)getProcAddr(kFnNames_ {{ fs.spec_name | spec_display }}[i]);
782+ for (i = 0; i < kFnCount_ {{ fs.spec_name | spec_display }}; ++i)
783+ context->pfnArray[i] = (void *)getProcAddr((kFnNameData_ {{ fs.spec_name | spec_display }} + kFnNameOffsets_{{ fs.spec_name | spec_display }} [i]) );
770784
771785 /* Mark features based on PFN availability. */
772786 for (i = 0; i < GLOAM_ARRAYSIZE(kFeatPfnRanges_{{ fs.spec_name | spec_display }}); ++i) {
0 commit comments