yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
00746bf09
master
Design Document: Slang IR Module Backwards Compatibility
Overview
This document describes the design and implementation of backwards compatibility support for serialized Slang IR modules. The feature enables Slang to load IR modules compiled with different versions of the compiler, providing version information and graceful handling of incompatible modules.
Motivation
As Slang evolves, the intermediate representation (IR) may change with new instructions being added or existing ones being modified. Without backwards compatibility:
- Users cannot load modules compiled with older versions of Slang
- There's no way to detect version mismatches between modules
- Module compatibility issues are opaque to users
This feature addresses these issues by introducing versioning and stable instruction naming.
User-Facing Changes
New Command Line Options
-
-get-module-info <module-file>- Prints information about a serialized IR module without loading it
- Output includes:
- Module name
- Module version
- Compiler version that created the module
- Example usage:
slangc -get-module-info mymodule.slang-module
-
-get-supported-module-versions- Prints the range of module versions this compiler supports
- Output includes minimum and maximum supported versions
- Example usage:
slangc -get-supported-module-versions
API Changes
New method in ISession interface:
SlangResult loadModuleInfoFromIRBlob ( slang::IBlob * source ,SlangInt & outModuleVersion ,const char *& outModuleCompilerVersion ,const char *& outModuleName );
This allows programmatic inspection of module metadata without full deserialization.
Technical Design
Stable Instruction Names
The core mechanism for backwards compatibility is the introduction of stable names for IR instructions:
-
Stable Name Table (
slang-ir-insts-stable-names.lua)- Maps instruction names to unique integer IDs
- IDs are permanent once assigned
- New instructions get new IDs, never reusing old ones
-
Runtime Mapping
getOpcodeStableName(IROp): Convert runtime opcode to stable IDgetStableNameOpcode(UInt): Convert stable ID back to runtime opcode- Unknown stable IDs map to
kIROp_Unrecognized
Module Versioning
Two types of versions are tracked:
-
Module Version (
IRModule::m_version)- Semantic version of the IR instruction set
- Range:
k_minSupportedModuleVersiontok_maxSupportedModuleVersion - Stored in each serialized module
-
Serialization Version (
IRModuleInfo::serializationVersion)- Version of the serialization format itself
- Currently version 0
- Allows future changes to serialization structure
Compiler Version Tracking
Each module stores the exact compiler version (SLANG_TAG_VERSION) that created it. This enables version-specific workarounds if needed in the future.
Validation System
A GitHub Actions workflow (check-ir-stable-names.yml) ensures consistency:
-
Check Mode: Validates that:
- All IR instructions have stable names
- No duplicate stable IDs exist
- The stable name table is a bijection with current instructions
-
Update Mode: Automatically assigns stable IDs to new instructions
The validation is implemented in check-ir-stable-names.lua which:
- Loads instruction definitions from
slang-ir-insts.lua - Compares against
slang-ir-insts-stable-names.lua - Reports missing entries or inconsistencies
Breaking Changes and Version Management
When to Update Module Version
The module version must be updated when:
-
Adding Instructions (Minor Version Bump)
- Increment
k_maxSupportedModuleVersion - Older compilers can still load modules that don't use new instructions
- Increment
-
Removing Instructions (Major Version Bump)
- Increment
k_maxSupportedModuleVersion - Update
k_minSupportedModuleVersionto exclude versions with removed instructions - This breaks compatibility with older modules using removed instructions
- Increment
-
Changing Instruction Semantics
- Even if the instruction name remains the same
- Requires version bump to prevent incorrect behavior
- To avoid bumping the minimum supported version, one may instead introduce
a new instruction and just bump
k_maxSupportedModuleVersion
Serialization Format Changes
Changes to how data is serialized (not what data) require updating serializationVersion:
- Changes to the RIFF container structure
- Different encoding for instruction payloads
- Reordering of serialized data
Implementation Details
Module Loading Flow
-
Version Check
if (fossilizedModuleInfo -> serializationVersion != IRModuleInfo ::kSupportedSerializationVersion )return SLANG_FAIL ; -
Instruction Deserialization
- Stable IDs are converted to runtime opcodes
- Unknown IDs become
kIROp_Unrecognized
-
Validation Pass
- After deserialization, check for any
kIROp_Unrecognizedinstructions - Fail loading if any are found
- After deserialization, check for any
Error Handling
- Incompatible serialization versions: Immediate failure
- Unknown instructions: Mark as unrecognized, fail after full deserialization (this should be caught by the next check)
- Module version out of range: Fail after deserialization
Future Considerations
Potential Enhancements
-
Graceful Degradation
- Skip unrecognized instructions if they're not critical
- Provide compatibility shims for removed instructions
-
Module Migration Tools
- Utility to upgrade old modules to new formats
- Batch processing for large codebases
Maintenance Guidelines
-
Regular CI Validation
- The GitHub Action ensures stable names stay synchronized
- Catches missing entries before merge
-
Version Documentation
- Maintain changelog of what changed in each module version
- Document any version-specific workarounds
-
Testing
- Test loading of modules from previous versions
- Verify error messages for incompatible modules
Conclusion
This backwards compatibility system provides a robust foundation for Slang IR evolution while maintaining compatibility where possible. The combination of stable instruction naming, comprehensive versioning, and automated validation ensures that:
- Users can reliably use modules across Slang versions
- Developers can evolve the IR with clear compatibility boundaries
- Version mismatches are detected and reported clearly
The system is designed to be maintainable and extensible, with clear guidelines for when and how to make breaking changes.
1# Design Document: Slang IR Module Backwards Compatibility 2 3## Overview 4 5This document describes the design and implementation of backwards compatibility support for serialized Slang IR modules. The feature enables Slang to load IR modules compiled with different versions of the compiler, providing version information and graceful handling of incompatible modules. 6 7## Motivation 8 9As Slang evolves, the intermediate representation (IR) may change with new instructions being added or existing ones being modified. Without backwards compatibility: 10 11- Users cannot load modules compiled with older versions of Slang 12- There's no way to detect version mismatches between modules 13- Module compatibility issues are opaque to users 14 15This feature addresses these issues by introducing versioning and stable instruction naming. 16 17## User-Facing Changes 18 19### New Command Line Options 20 211. **`-get-module-info <module-file>`** 22 23- Prints information about a serialized IR module without loading it 24- Output includes: 25- Module name 26- Module version 27- Compiler version that created the module 28- Example usage: `slangc -get-module-info mymodule.slang-module` 29 302. **`-get-supported-module-versions`** 31- Prints the range of module versions this compiler supports 32- Output includes minimum and maximum supported versions 33- Example usage: `slangc -get-supported-module-versions` 34 35### API Changes 36 37New method in `ISession` interface: 38 39``` cpp 40SlangResult loadModuleInfoFromIRBlob ( 41slang:: IBlob * source , 42SlangInt & outModuleVersion , 43const char *& outModuleCompilerVersion , 44const char *& outModuleName ); 45``` 46 47This allows programmatic inspection of module metadata without full deserialization. 48 49## Technical Design 50 51### Stable Instruction Names 52 53The core mechanism for backwards compatibility is the introduction of stable names for IR instructions: 54 551. **Stable Name Table** (`slang-ir-insts-stable-names.lua`) 56 57- Maps instruction names to unique integer IDs 58- IDs are permanent once assigned 59- New instructions get new IDs, never reusing old ones 60 612. **Runtime Mapping** 62- `getOpcodeStableName(IROp)`: Convert runtime opcode to stable ID 63- `getStableNameOpcode(UInt)`: Convert stable ID back to runtime opcode 64- Unknown stable IDs map to `kIROp_Unrecognized` 65 66### Module Versioning 67 68Two types of versions are tracked: 69 701. **Module Version** (`IRModule::m_version`) 71 72- Semantic version of the IR instruction set 73- Range: `k_minSupportedModuleVersion` to `k_maxSupportedModuleVersion` 74- Stored in each serialized module 75 762. **Serialization Version** (`IRModuleInfo::serializationVersion`) 77- Version of the serialization format itself 78- Currently version 0 79- Allows future changes to serialization structure 80 81### Compiler Version Tracking 82 83Each module stores the exact compiler version (`SLANG_TAG_VERSION`) that created it. This enables version-specific workarounds if needed in the future. 84 85### Validation System 86 87A GitHub Actions workflow (`check-ir-stable-names.yml`) ensures consistency: 88 891. **Check Mode**: Validates that: 90 91- All IR instructions have stable names 92- No duplicate stable IDs exist 93- The stable name table is a bijection with current instructions 94 952. **Update Mode**: Automatically assigns stable IDs to new instructions 96 97The validation is implemented in `check-ir-stable-names.lua` which: 98 99- Loads instruction definitions from `slang-ir-insts.lua` 100- Compares against `slang-ir-insts-stable-names.lua` 101- Reports missing entries or inconsistencies 102 103## Breaking Changes and Version Management 104 105### When to Update Module Version 106 107The module version must be updated when: 108 1091. **Adding Instructions** (Minor Version Bump) 110 111- Increment `k_maxSupportedModuleVersion` 112- Older compilers can still load modules that don't use new instructions 113 1142. **Removing Instructions** (Major Version Bump) 115 116- Increment `k_maxSupportedModuleVersion` 117- Update `k_minSupportedModuleVersion` to exclude versions with removed instructions 118- This breaks compatibility with older modules using removed instructions 119 1203. **Changing Instruction Semantics** 121- Even if the instruction name remains the same 122- Requires version bump to prevent incorrect behavior 123- To avoid bumping the minimum supported version, one may instead introduce 124a new instruction and just bump `k_maxSupportedModuleVersion` 125 126### Serialization Format Changes 127 128Changes to how data is serialized (not what data) require updating `serializationVersion`: 129 130- Changes to the RIFF container structure 131- Different encoding for instruction payloads 132- Reordering of serialized data 133 134## Implementation Details 135 136### Module Loading Flow 137 1381. **Version Check** 139 140```cpp 141if ( fossilizedModuleInfo -> serializationVersion != IRModuleInfo :: kSupportedSerializationVersion ) 142return SLANG_FAIL ; 143``` 144 1452. **Instruction Deserialization** 146 147- Stable IDs are converted to runtime opcodes 148- Unknown IDs become `kIROp_Unrecognized` 149 1503. **Validation Pass** 151- After deserialization, check for any `kIROp_Unrecognized` instructions 152- Fail loading if any are found 153 154### Error Handling 155 156- Incompatible serialization versions: Immediate failure 157- Unknown instructions: Mark as unrecognized, fail after full deserialization 158(this should be caught by the next check) 159- Module version out of range: Fail after deserialization 160 161## Future Considerations 162 163### Potential Enhancements 164 1651. **Graceful Degradation** 166 167- Skip unrecognized instructions if they're not critical 168- Provide compatibility shims for removed instructions 169 1702. **Module Migration Tools** 171 172- Utility to upgrade old modules to new formats 173- Batch processing for large codebases 174 175### Maintenance Guidelines 176 1771. **Regular CI Validation** 178 179- The GitHub Action ensures stable names stay synchronized 180- Catches missing entries before merge 181 1822. **Version Documentation** 183 184- Maintain changelog of what changed in each module version 185- Document any version-specific workarounds 186 1873. **Testing** 188- Test loading of modules from previous versions 189- Verify error messages for incompatible modules 190 191## Conclusion 192 193This backwards compatibility system provides a robust foundation for Slang IR evolution while maintaining compatibility where possible. The combination of stable instruction naming, comprehensive versioning, and automated validation ensures that: 194 195- Users can reliably use modules across Slang versions 196- Developers can evolve the IR with clear compatibility boundaries 197- Version mismatches are detected and reported clearly 198 199The system is designed to be maintainable and extensible, with clear guidelines for when and how to make breaking changes.