Summary
Any mod that registers its own RenderPipeline pointing at shaders bundled in that mod's own jar fails silently under VulkanMod, because ShaderLoadUtil's shader source lookup only ever searches inside VulkanMod's own jar and discards the Identifier's namespace when building the file path. This affects malilib's custom terrain pipelines (used by Litematica for schematic rendering), and presumably any other mod doing the same normal, spec-compliant thing with the RenderPipeline API.
Reproduction
- Install Fabric 1.21.11 + VulkanMod + malilib + Litematica.
- Load into a world with a schematic loaded in Litematica.
- Schematic renders blank, invisible, or with wrong/garbage coloring instead of the expected ghost-block overlay. Disabling VulkanMod (falling back to the vanilla renderer) fixes it immediately.
Root cause
net.vulkanmod.render.shader.ShaderLoadUtil:
public static final String RESOURCES_PATH =
SpirvCompiler.class.getResource("/assets/vulkanmod").toExternalForm();
...
public static String getShaderSource(Identifier resourceLocation, ShaderType type) {
String path = resourceLocation.getPath(); // namespace discarded here
String[] splitPath = splitPath(path);
String shaderName = "%s%s".formatted(splitPath[1], shaderExtension);
String shaderFile = "%s/shaders/%s/%s".formatted(RESOURCES_PATH, path, shaderName);
// falls back to "%s/shaders/%s%s".formatted(RESOURCES_PATH, path, shaderExtension)
...
}
RESOURCES_PATH is hardcoded to VulkanMod's own jar (/assets/vulkanmod), and resourceLocation.getNamespace() is never consulted. So when VkGpuDevice.compilePipeline (via VkRenderPass.setPipeline's lazy on-demand compile path) needs to resolve, say, malilib:legacy_terrain, it only ever looks for .../assets/vulkanmod/shaders/legacy_terrain... inside VulkanMod's own jar. It never finds it (the file actually lives in malilib's jar at assets/malilib/shaders/legacy_terrain.vsh/.fsh), getShaderSource returns null, and the pipeline compiles incorrectly/incompletely.
I confirmed this by cloning both xCollateral/VulkanMod (dev branch, MC 1.21.11) and sakura-ryoko/malilib (LTS/1.21.11) and tracing the actual call path:
fi.dy.masa.malilib.mixin.render.MixinRenderPipelines registers LEGACY_SOLID_TERRAIN_MASA etc. via the standard RenderPipelines/RenderPipeline.builder(...) API, pointing at getId("legacy_terrain") (i.e. malilib:legacy_terrain), with the actual shader files at src/main/resources/assets/malilib/shaders/legacy_terrain.vsh / .fsh in malilib's own jar.
fi.dy.masa.litematica.render.schematic.ChunkRenderLayers uses those pipelines for schematic terrain rendering.
net.vulkanmod.render.engine.VkRenderPass#setPipeline lazily calls VkGpuDevice#compilePipeline the first time a given RenderPipeline is drawn, which is otherwise a nice generic design (not a hardcoded whitelist) -- it's specifically the shader source lookup inside that path that's jar-scoped and namespace-blind.
Suggested fix
In getShaderSource(Identifier, ShaderType), when the in-jar lookup misses, fall back to resolving the Identifier's namespace to its owning mod (e.g. via Fabric Loader's FabricLoader.getInstance().getModContainer(namespace) and ModContainer#findPath(...)) and read the shader from there, mirroring the same two-tier path/name.ext -> path.ext lookup order already used for VulkanMod's own shaders. Happy to open a PR with this if useful -- I already wrote and tested the approach as a standalone compat mod (mixin into getShaderSource, fallback via ModContainer#findPath) and it's a small, self-contained change.
Environment
- Minecraft 1.21.11
- VulkanMod
dev branch / 0.6.8+1.21.11-dev
- malilib LTS/1.21.11 (sakura-ryoko fork), Litematica LTS/1.21.11 (sakura-ryoko fork)
- Fabric Loader 0.19.3
Summary
Any mod that registers its own
RenderPipelinepointing at shaders bundled in that mod's own jar fails silently under VulkanMod, becauseShaderLoadUtil's shader source lookup only ever searches inside VulkanMod's own jar and discards theIdentifier's namespace when building the file path. This affects malilib's custom terrain pipelines (used by Litematica for schematic rendering), and presumably any other mod doing the same normal, spec-compliant thing with theRenderPipelineAPI.Reproduction
Root cause
net.vulkanmod.render.shader.ShaderLoadUtil:RESOURCES_PATHis hardcoded to VulkanMod's own jar (/assets/vulkanmod), andresourceLocation.getNamespace()is never consulted. So whenVkGpuDevice.compilePipeline(viaVkRenderPass.setPipeline's lazy on-demand compile path) needs to resolve, say,malilib:legacy_terrain, it only ever looks for.../assets/vulkanmod/shaders/legacy_terrain...inside VulkanMod's own jar. It never finds it (the file actually lives in malilib's jar atassets/malilib/shaders/legacy_terrain.vsh/.fsh),getShaderSourcereturnsnull, and the pipeline compiles incorrectly/incompletely.I confirmed this by cloning both
xCollateral/VulkanMod(devbranch, MC 1.21.11) andsakura-ryoko/malilib(LTS/1.21.11) and tracing the actual call path:fi.dy.masa.malilib.mixin.render.MixinRenderPipelinesregistersLEGACY_SOLID_TERRAIN_MASAetc. via the standardRenderPipelines/RenderPipeline.builder(...)API, pointing atgetId("legacy_terrain")(i.e.malilib:legacy_terrain), with the actual shader files atsrc/main/resources/assets/malilib/shaders/legacy_terrain.vsh/.fshin malilib's own jar.fi.dy.masa.litematica.render.schematic.ChunkRenderLayersuses those pipelines for schematic terrain rendering.net.vulkanmod.render.engine.VkRenderPass#setPipelinelazily callsVkGpuDevice#compilePipelinethe first time a givenRenderPipelineis drawn, which is otherwise a nice generic design (not a hardcoded whitelist) -- it's specifically the shader source lookup inside that path that's jar-scoped and namespace-blind.Suggested fix
In
getShaderSource(Identifier, ShaderType), when the in-jar lookup misses, fall back to resolving the Identifier's namespace to its owning mod (e.g. via Fabric Loader'sFabricLoader.getInstance().getModContainer(namespace)andModContainer#findPath(...)) and read the shader from there, mirroring the same two-tierpath/name.ext->path.extlookup order already used for VulkanMod's own shaders. Happy to open a PR with this if useful -- I already wrote and tested the approach as a standalone compat mod (mixin intogetShaderSource, fallback viaModContainer#findPath) and it's a small, self-contained change.Environment
devbranch / 0.6.8+1.21.11-dev