pub const OBJECT_COMMON: &str = "// The per-object vertex vocabulary every GPU-driven pass shares: the bindless\n// object record, the object-id reconstruction the engine\'s first-instance\n// encoding needs, and the normal matrix.\n//\n// Spliced at the OBJECT_COMMON marker rather than imported as a Slang module,\n// for the same reason the variant defines ride the source text: the\n// replacement lands in the assembled source, so the content-addressed shader\n// cache keys it. `slang_source::assemble` is the runtime half of the splice and\n// `SLANG_SHADER_FRAGMENTS` in the device build script the build-time half.\n//\n// This is the record\'s only declaration: `shader_layout` in concinnity-device\n// reflects it against `GpuObjectData` on every target, and its\n// `no_shader_redeclares_the_object_record` scan keeps it that way.\n\n// Mirrors `GpuObjectData` in concinnity-core/src/gfx/render_types.rs (144 B).\n// Each (vec3, scalar) pair is spelled as one float4: MSL sizes a float3 at 16\n// bytes in a structured buffer as well as in a constant buffer, so a literal\n// transcription pushes every following field four bytes late on Metal alone.\nstruct GpuObjectData\n{\n float4x4 model;\n // xyz = tint, w = roughness.\n float4 tint_roughness;\n // xyz = emissive, w = metallic.\n float4 emissive_metallic;\n uint albedo_index;\n uint normal_index;\n uint emissive_map_index;\n uint orm_map_index;\n // xyz = bounding-box minimum, w = cull distance.\n float4 bb_min_cull_distance;\n // xyz = bounding-box maximum, w = alpha cutoff.\n float4 bb_max_alpha_cutoff;\n};\n\n// Mirrors `GpuDrawArgs` in concinnity-core/src/gfx/render_types.rs (16 B): the\n// per-frame cull decision + indexed-draw slice for the record at the same index\n// as the `GpuObjectData` above. Declared here rather than in the cull, because\n// the G-buffer pre-pass reads `flags` too.\nstruct GpuDrawArgs\n{\n uint index_count;\n uint index_offset;\n uint base_vertex;\n uint flags;\n};\n\n// `GpuDrawArgs::flags` bits, locked to gfx::render_types::DrawArgsFlags.\nstatic const uint DRAW_ENABLED = 1u;\nstatic const uint DRAW_CULLABLE = 2u;\n// The record\'s history entry in the model-history ring belongs to a different\n// occupant, so a motion vector must fall back to the current model.\nstatic const uint DRAW_NO_HISTORY = 4u;\n\n// The record\'s shader bucket rides the upper flag bits; values and layout are\n// locked to gfx::render_types::{DrawArgsFlags::BUCKET_SHIFT, MAX_SHADER_BUCKETS}.\nstatic const uint DRAW_BUCKET_SHIFT = 8u;\nstatic const uint DRAW_BUCKET_MASK = 0xFFu;\n\n// The engine encodes the object id as the draw\'s first-instance value. The\n// targets disagree on what an instance-id builtin contains: SPIR-V\'s\n// InstanceIndex and Metal\'s instance_id include the base instance, while\n// SV_InstanceID is defined zero-based (Slang subtracts the base to honor\n// that). Reconstruct the object id explicitly from both builtins.\nuint object_instance_index(uint zero_based_iid, uint first_instance)\n{\n __target_switch\n {\n case metal:\n // Slang\'s Metal lowering passes instance_id through unsubtracted, and\n // instance_id already includes base_instance.\n return zero_based_iid;\n default:\n return zero_based_iid + first_instance;\n }\n}\n\nfloat3x3 normal_matrix(float4x4 model)\n{\n // Slang subscripts a matrix by row, so these are the upper 3x3\'s rows. The\n // cofactor matrix built from them is the inverse-transpose scaled by the\n // determinant; the normalize() at every use site absorbs that scale.\n float3 a0 = model[0].xyz;\n float3 a1 = model[1].xyz;\n float3 a2 = model[2].xyz;\n float3 r0 = cross(a1, a2);\n float3 r1 = cross(a2, a0);\n float3 r2 = cross(a0, a1);\n // mul(M, v) with these as rows applies the inverse-transpose to v.\n return float3x3(r0, r1, r2);\n}\n";Expand description
object_common.slang.