Repository navigation
Conversation
SPIRV-Cross is pinned to vulkan-sdk-1.4.363.0 and built as a host tool. sleak_cross_compile_shader() turns a shader's SPIR-V into GL GLSL and SM 5.0 HLSL in the build tree, staged next to the .spv. Only the shaders listed in ENGINE_CROSS_SHADERS are generated.
5 of 6 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Shaders can now be written once as Vulkan GLSL and the build generates the OpenGL GLSL and SM 5.0 HLSL from the SPIR-V. SPIRV-Cross is vendored as a submodule (
vendors/SPIRV-Cross, pinned tovulkan-sdk-1.4.363.0) and its CLI is built as a host tool.sleak_cross_compile_shader()writesname.vert.glsl/name.frag.glslandname.vert.hlsl/name.frag.hlslinto<build>/Engine/shaders, and they are staged next to the.spvwith the same mechanism as #196.OpenGLShadernow loads the generatedname.<stage>.glslwhen it exists and falls back toname_gl.<stage>per stage.First migrations:
debug_line,ibl_irradiance,ibl_prefilter,ibl_brdf_lutand the vertex stage oflighting_pass. Their hand-written_glfiles are deleted.Stacked on #196, review that one first.
Why
Every shader has up to four hand-written copies and they have drifted (
default_shaderis 543/467/186/134 lines across its variants). Most of the GL copies are the Vulkan file withlayout(location)stripped andgl_VertexIndexrenamed, and nothing checks them until a driver compiles them at runtime.Only glslc is assumed on the machine (no dxc, slangc or spirv-cross), so SPIRV-Cross comes in as source and builds with the engine. It only needs SPIR-V as input, so on a machine without glslc it runs on the committed
.spvand the GL shaders still get generated. That is what keeps Windows CI and Windows builds without the Vulkan SDK working after the_glfiles are gone. When cross compiling (USE_MINGW) the vendored tool can not run, so configure looks for a hostspirv-crossand fails with a message if there is none.Some choices that are not obvious from the diff:
GL_ARB_shading_language_420pack. At 4.10 and up SPIRV-Cross putslayout(location)on varyings, and a generated stage with locations does not link against a hand-written stage without them (GL only matches by name when neither side has one). At 4.00 varyings match by name, so a generatedlighting_pass.vertlinks with anylighting_pass_gl.frag, including SleakCraft's own.bindingstill comes through via 420pack.std140uniform block with no binding (--glsl-emit-push-constant-as-ubo), which GL puts at binding 0. That is exactly where the GL backend already bindsDebugLineUBO,FaceUBOandPrefilterUBO.bindingwith thesetdropped. That is why generation is opt in throughENGINE_CROSS_SHADERSand not every shader: it is only correct when the Vulkan layout already matches what the GL backend binds. I checked each listed shader against its GL call site (OpenGLIBL.cpp, the debug line pass,ExecuteDeferredLightingPass).debug_line.vertnegatesgl_Position.yfor Vulkan, so it is listed underENGINE_CROSS_SHADERS_FLIP_Yand SPIRV-Cross negates it back (--flip-vert-y). The other migrated vertex shaders do not flip.The HLSL is generated but nothing loads it. The DX11 and DX12 loaders still read the hand-written
name.hlsl/name_dx12.hlsl. The generated files usemainas the entry point,TEXCOORDninput semantics and compiler assigned registers, while the DX backends expectVS_Main/PS_Main,POSITION/NORMAL/... semantics and their own register and root signature layout. Switching them needs per shader semantic and register mapping I can not run on Linux, so I left the DX loaders alone rather than ship something only CI has compiled. CI now compiles every generated HLSL file with fxc on Windows, so that side is at least known to be valid HLSL.Not covered here:
lighting_pass.fragis not generated for GL. The GL and Vulkan lighting passes have different data contracts (GL readsLightUBOat binding 2 with up to 16 point and directional lights and tone maps in the pass, Vulkan reads a single directional light plus three fill lights fromShadowLightUBOand leaves tone mapping to bloom composite). Unifying that means changing what one backend feeds the shader, which is a behavior change, not a port. The GL fragment shader that is missing from the engine (OpenGL deferred rendering can never initialize:lighting_pass_gl.fragdoes not exist #144) is a separate PR on top of this one.ssao,ssao_blur,gbuffer,skybox,default_shader,skinned_shaderstay hand-written for the same reason: the GL and Vulkan versions bind different things (or the GL skybox tone maps and the Vulkan one does not), so generating GL from the Vulkan file would change what GL renders.tonemap_gl.*is not loaded by anything (only DX11 usestonemap.hlsl), it is just dead. Left for a cleanup PR.add_subdirectory(Engine), but SleakCraft's shaders are not wired to it here.name.<stage>.glslovername_gl.<stage>.-j4. It isEXCLUDE_FROM_ALLand only the CLI and the libraries it needs get built.How it was verified
Clean SleakCraft debug build against this branch (
-j4, Ninja). All nine generated pairs were written tobuild/Engine/shadersand staged intobin/assets/shaders, the spirv-cross binary and its static libs stay in the build tree, and the engine checkout had no changes besides mine. Every generated GL file also compiles withglslangValidatorand withglslc --target-env=opengl, which is what the new Linux CI step runs.Without glslc (
-DGLSLC=): configure warns as in #196, and the generation runs on the committed.spvand produces byte identical GL files.OpenGL on llvmpipe under xvfb, from SleakCraft's
bin: ran until the 90 s timeout, created worldcitest,OpenGL GBuffer created ... deferred rendering active,OpenGLIBL: precompute complete, no errors. strace shows it openeddebug_line.{vert,frag}.glsl, all sixibl_*.glslandlighting_pass.vert.glsl, and the hand-writtenlighting_pass_gl.frag(SleakCraft's copy), so the mixed generated/hand-written program links on Mesa. I also took a 640x360 frame at 45 s with the generated shaders and again with the old hand-written_glfiles put back inbin. The pictures are the same apart from the HUD numbers (FPS, vertex counts).Vulkan on the real GPU under xvfb: ran until the 60 s timeout, loaded the world, no new validation output. The Vulkan
.spvare not touched by this PR.Checklist
_glcopy and get generated ones instead///comments (no public header changed)src/orinclude/private/in public headers