Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: Generate Vulkan headers automatically as part of the build #9217

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

smcv
Copy link
Contributor

@smcv smcv commented Mar 7, 2024

If the glslang tool is available, we can regenerate the Vulkan headers with it during the build, rather than having an out-of-band step to produce Vulkan headers on a maintainer's Windows machine and having everyone else rely on the derived files having been committed to git.

On platforms where compiling everything from its preferred from for modification is desired, such as many Linux distributions, the generated headers can be deleted from the source directory to force them to be regenerated.

The derived files are still copied into the source directory to be committed, in case there are platforms where the Vulkan driver is desirable but CMake is not used. This could be removed if no such platform exists.

glslangValidator(1) is an older name for glslang(1), so look for both names.


glslang-tools version 14.0.0 on Debian produces a slightly different VULKAN_VertexShader.h. Is this expected? The current headers seem to have been generated with 13.1.1, and the pixel shaders come out identical except for the comment that indicates the version of glslang that was used to generate them.

If the glslang tool is available, we can regenerate the Vulkan headers
with it during the build, rather than having an out-of-band step to
produce Vulkan headers on a maintainer's Windows machine and having
everyone else rely on the derived files having been committed to git.

On platforms where compiling everything from its preferred from for
modification is desired, such as many Linux distributions, the generated
headers can be deleted from the source directory to force them to be
regenerated.

The derived files are still copied into the source directory to be
committed, in case there are platforms where the Vulkan driver is
desirable but CMake is not used. This could be removed if no such
platform exists.

glslangValidator(1) is an older name for glslang(1), so look for
both names.

Signed-off-by: Simon McVittie <smcv@collabora.com>
@smcv
Copy link
Contributor Author

smcv commented Mar 7, 2024

cc @danginsburg @slouken

My CMake scripting is probably not the most elegant, I'm better at Autotools and Meson.

In principle the D3D shaders could get a similar treatment, but someone who can test in a Windows development environment would have to drive that, and the Linux distributions that strongly prefer the build to be done from first principles aren't going to care about D3D shaders; in the Debian packaging, we currently just delete them, so that they don't have to be reviewed when updating SDL.

Comment on lines +2789 to +2790
set(intermediate "${CMAKE_CURRENT_BINARY_DIR}/${dir}/VULKAN_VertexShader.h")
set(output "${CMAKE_CURRENT_SOURCE_DIR}/${dir}/VULKAN_VertexShader.h")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the generated headers stable between glslang versions?
If they differ, perhaps we should hide the regeneration behind a SDL_DEVEL CMake option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the generated headers stable between glslang versions?

Experimentally: not identical, but if they aren't backwards-compatible then I would have assumed that ought to be considered to be a bug in glslang?

(Analogous: C compiler output isn't stable between compilers or versions, but we don't commit generated object code to git and hide regeneration of it behind a special developer option.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glslang should always emit valid spirv, that's not my concern here.
I'm worrying about people accidentally committing their regenerated headers when doing git add -A.
This will/might cause back and forth in pull requests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point. Perhaps it could be regenerated if either: a special option is set, or the generated "source" file already doesn't exist? Would that be viable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be nice!
I'm thinking about a SDL_DEVEL option, but I'm bad at naming things so that's up to you :)

@sezero
Copy link
Contributor

sezero commented Mar 7, 2024

Keeping vulkan/compile_shaders.bat would be advisable: devs may prefer using it.

@smcv
Copy link
Contributor Author

smcv commented Mar 7, 2024

Keeping vulkan/compile_shaders.bat would be advisable: devs may prefer using it.

Are there SDL maintainers who might update the precompiled shader headers, but are not building with CMake?

My concern about keeping the batch file is that if the batch file and the CMake build system are both responsible for knowing the canonical glslang options to be used, they can get out of sync.

@smcv
Copy link
Contributor Author

smcv commented Mar 7, 2024

Right now, compile_shaders.bat is so simple that it is in fact in the intersection of valid Windows batch file and valid Unix shell script, so it would be entirely possible for Linux distributions that want to regenerate these headers to use sh -e ./compile_shaders.bat; but I'd prefer not to rely on that remaining true forever.

@sezero
Copy link
Contributor

sezero commented Mar 7, 2024

Keeping vulkan/compile_shaders.bat would be advisable: devs may prefer using it.

Are there SDL maintainers who might update the precompiled shader headers, but are not building with CMake?

They can build using Visual Studio project files

@danginsburg
Copy link
Contributor

I don't have any strong opinions here. The original version of the D3D12 renderer I ported had the shader code in comments and just had checked in generated arrays with some comments about how to generate them. At first I did the same in Vulkan, but then @slouken added the build batch files, which were a definite big improvement to development workflow. In principle having it as part of cmake sounds nice, but yeah it does make a new external dependency in glslangValidator and SPIR-V will vary by what version user has on their machine unless we include it or build it as an external dependency at a specific revision.

@smcv
Copy link
Contributor Author

smcv commented Mar 7, 2024

The batch files are definitely better than having no automatic generation at all, but bringing them into the build system seems nicer (to me, at least) than having an out-of-band step, particularly an out-of-band step that in principle only works on Windows (although, as mentioned above, in practice the batch file is so simple that right now it can also be run as a shell script).

it does make a new external dependency in glslangValidator

Only if the packager/developer has chosen to install it - if it's missing, the pre-generated version is still available. I would expect that platforms with a packaging system that knows about build-dependencies (dpkg, RPM, etc.) would prefer to delete the generated files and use this as an external dependency, whereas platforms with no good packaging system would prefer to continue using the pre-generated version.

@slouken
Copy link
Collaborator

slouken commented Mar 7, 2024

What if we have an optional step that's run if the user has specified an glslang executable to use? That gives us the best of both worlds - packagers can specify their dependency and developers can omit it if they're not iterating on shaders, or set it to a specific version if they are.

We could do the same for the D3D shaders - run the generation commands if the user has set the shader generation command, otherwise the pregenerated ones will be used.

@slouken
Copy link
Collaborator

slouken commented Mar 7, 2024

BTW, the unrelated CI failures should be fixed now.

@smcv
Copy link
Contributor Author

smcv commented Mar 7, 2024

What if we have an optional step that's run if the user has specified an glslang executable to use?

Sure, that sounds like a good route. I'll put that in my list (it's a long list).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants