generator
FreeBodyEngine.graphics.gl44.generator
#
GLSL 440 core code generator - the GL44 backend's key difference from GL33 is that compute/raytrace shaders here are REAL GL_COMPUTE_SHADER stages (GL 4.3+ has actual glDispatchCompute, writable SSBOs, and image load/store), not GL33's fullscreen-fragment-shader emulation. Vertex/ fragment/geometry codegen, expressions, literals, control flow, etc. don't change at all between GL 3.3 and 4.4, so this subclasses GL33Generator and inherits all of that unchanged - only what compute/raytrace/buffer semantics actually need to differ is overridden here.
IMAGE_FORMAT = {'float': 'r32f', 'int': 'r32i', 'vec2': 'rg32f', 'vec4': 'rgba32f'}
module-attribute
#
GL44Generator(tree, shader_type=fbusl.ShaderType.FRAGMENT)
#
Bases: GL33Generator
Emits GLSL 440 core. Subclasses GL33Generator and inherits its vertex/
fragment/geometry codegen unchanged (only the emitted #version line
differs there); compute/raytrace shaders are overridden here to target a
real GL_COMPUTE_SHADER stage - real SSBOs and image2D/imageStore instead
of GL33's fullscreen-fragment-shader emulation with buffer-texture reads
- which is why CAPABILITIES additionally advertises
"compute.buffer_write", "compute.image_write", "compute.shared_memory",
"compute.barrier" and "compute.atomics" on top of GL33's set.
Sets up GL44-specific codegen state on top of GL33Generator's:
a private copy of implementations with sample() renamed to
_ENGINE_sample() (GLSL reserves sample as a keyword from version
4.0 on, so GL33's unrenamed helper is a hard syntax error under
#version 440); _output_fields, so a compute/raytrace Setter
targeting an @output field can be recognized and lowered to
imageStore(); and image_bindings, populated the first time
generate() runs for a compute/raytrace stage so
GL44ComputeShader can read back the same unit numbers baked into
the emitted layout(binding=N) declarations.
CAPABILITIES = frozenset({'compute.dispatch', 'compute.invocation_id', 'compute.buffer_read', 'compute.buffer_write', 'compute.image_read', 'compute.image_write', 'compute.shared_memory', 'compute.barrier', 'compute.atomics', 'geometry.native', 'raytrace.query_emulated'})
class-attribute
instance-attribute
#
image_bindings = {}
instance-attribute
#
implementations = dict(self.implementations)
instance-attribute
#
generate()
#
Emits the full GLSL source for self.tree: a real compute-shader
stage (_generate_compute()) for COMPUTE/RAYTRACE, or GL33's
vertex/fragment/geometry codegen otherwise - with #version 330
core swapped for #version 440 core in that inherited output,
since nothing else about that codegen path differs between the two
backends.
generate_buffer_block(node)
#
Generates a layout(std430) buffer block declaration (a real
SSBO) for one BufferBlock's fields, each as a native GLSL unsized
array (<type> <field>[];) - unlike GL33, which has no real SSBOs
and instead emulates buffer reads via samplerBuffer/texelFetch.
No require() gate is needed here (unlike GL33's
generate_buffer_block()): "compute.buffer_write" is a real
capability of this backend, so a non-readonly buffer is simply
generated as such rather than rejected. Struct-typed fields aren't
supported yet and raise an FBUSL error.
generate_identifier(node)
#
Lowers the three compute "invocation id" builtins to GL 4.4's
real gl_GlobalInvocationID/gl_WorkGroupID/gl_LocalInvocationID
(genuinely uvec3, cast to ivec3 to match what FBUSL's semantic
analyser already typed them as) rather than GL33's gl_FragCoord-
derived arithmetic emulation. Any other identifier falls through to
GL33Generator's IMPLEMENTATIONS-table lookup.
generate_inout(node)
#
Routes a compute/raytrace @output field to
_generate_image_output() (a real image2D/iimage2D binding, not
a GLSL out variable); every other in/out/uniform declaration,
in any stage, falls through to GL33Generator's implementation
unchanged.
generate_setter(node)
#
In a compute/raytrace stage, lowers an assignment to a known
@output field into an imageStore() call (padding the value out
to a vec4/ivec4 per _pad_to_vec4(), and indexing by
gl_GlobalInvocationID.xy) instead of GLSL's plain =, since a
compute @output is a bound image, not a writable out variable.
Every other assignment, in any stage, falls through to
GL33Generator's plain left = right codegen.