RandyGaul / cute_framework

The *cutest* framework out there for creating 2D games in C++!
https://randygaul.github.io/cute_framework/#/
Other
546 stars 31 forks source link

Make runtime shader compilation optional #251

Open bullno1 opened 1 week ago

bullno1 commented 1 week ago

Huge changes:

As of this writing, windows build in CI is blocked by: https://github.com/actions/runner-images/issues/10978.

Allso, #include within the cf_shader_directory is not yet resolved. (Implemented) I'm posting this early for feedbacks.

RandyGaul commented 1 week ago

Would also be quite nice to document in the code as comment a rough plan on transitioning to SDL shader tools in the future, explaining how the current SPIRV handling is temporary until SDL evolves more thoroughly.

bullno1 commented 1 week ago

Is the shader compiler a standalone program? Which source is it exactly? I didn't want to spend time trawling the cmake file to find out. Is it just cute_shaderc.cpp and associated header?

Yes, it is just src/cute_shader/cute_shaderc.cpp.

Could you outline here what the major individual build targets are exactly and outline their dependencies to each other?

First, all glslang and spriv targets are now unconditionally fetched.

cute-shader is a library that wraps glslang compilation into spirv. It depends on glslang.

cute-shaderc is a CLI program that can compile glsl to spriv and generate a C header. It depends on cute-shader. Notably it is also used to generate src/data/builtin_shaders_bytecode.h with the -type=builtin flag. Mostly because I didn't want to make another program just for that. This is done through a add_custom_command so whenever src/cute_shader/builtin_shaders.h is edited, cute-shaderc will get rebuilt and the bytecode header will be regenerated, keeping it in sync.

cute itself always depend on SPIRV tools since it still needs to do reflection even without runtime compilation. The cute-shader dependency is conditional.

When CF_GLSLANG=OFF it will not link to cute-shader. All compilation functions just return NULL. Samples using inline string shader will crash (with a message in stderr).

When CF_GLSLANG=ON it will link to cute-shader. All compilation functions will call cute_shader_compile. Include now works with VFS and it will search in the cf_shader_directory if set. The directory is passed to cute-shader as an include directory, similar to the -I flag in cute-shaderc.

Can the shader compiler be linked in statically into cute.lib or cute.dll (static or dynamic libs, but not as a standalone exe), as a simple cmake option?

Yes. It is the CF_GLSLANG option.

Is this easy for users to toggle on/off in cmake? I want runtime shaders in CF on by default, and behind a single cmake option to turn them off and NOT compile or pull in any SPIRV nonsense. Is that the way things work here as of now?

Not quite yet. glslang is always pulled because the shader compiler requires that. I can make it so that cute-shaderc is not built. Then when CF_GLSLANG=OFF and CF_CUTE_SHADERC=OFF, glslang will not be pulled.

SPIRV-tool is still needed regardless of options because I have only implemented bytecode compilation, not reflection. I plan to do that next.

Do you have plans yet to add in a dedicated website page for documenting the compiler?

Yes, I can do that.

Can the compiler output serialized SPIRV blobs directly, and not just C headers?

It was possible earlier but I reverted it because draw shader, the most common case, is a couple of shaders. This can be added back and it will error on cases other than -type=vertex or -type=fragment. The other values are:

I can add a -obytecode= flag.

Can the compiler output reflection info required for passing into SDL_Gpu (various input counts for specific resource sets)?

Not yet. That should be next in the list. This will truly get rid of SPIRV and co from cute with CF_GLSLANG=OFF. With CF_CUTE_SHADERC=OFF they will not even be pulled.

Is the plan to distribute cute-shaderc as a prebuilt binary to save users from the pain?

I'd prefer only one or two samples to use bytecode. The rest should just use runtime shaders alone to reduce complexity.

Sure. I will only make changes to samples that already use shader in file and revert changes from samples with inline shaders.

bullno1 commented 1 week ago

Would also be quite nice to document in the code as comment a rough plan on transitioning to SDL shader tools in the future, explaining how the current SPIRV handling is temporary until SDL evolves more thoroughly.

Tbh, I have no idea where SDL shader tool is heading. This is my reference: https://github.com/libsdl-org/SDL_shader_tools.

I'll add some comment on how it is a temporary solution. But I think what we can somewhat guarantee is that the API will remain the same. That includes the compiler and all its flags, the include behaviour etc...

Shader syntax may change depending on what SDL_shader tool is doing.

RandyGaul commented 1 week ago

But I think what we can somewhat guarantee is that the API will remain the same.

Thanks! Excellent.

Edit: I'll get to the rest of your updates later.

RandyGaul commented 1 week ago

cute itself always depend on SPIRV tools since it still needs to do reflection even without runtime compilation.

If we attach reflection info can we instead cut out SPIRV from CF runtime (other than SPIRV-Cross), unless online shader compilation is required? We can augment the bytecode blob struct with all necessary info. Thoughts? Just a few more structs to store extra reflection info for CF runtime, mainly uniform information.

The shader compiler has all it needs to output prebuilt shaders and setup a little reflection table of information. It could be a static array of structs holding uniform information and counts. CF_ShaderBytecode can store a pointer to the static table for prebuilt shaders. For runtime compilation, the reflection info could be initialized on the stack as-needed for online compilation.

bullno1 commented 1 week ago

If we attach reflection info can we instead cut out SPIRV from CF runtime (other than SPIRV-Cross), unless online shader compilation is required? We can augment the bytecode blob struct with all necessary info. Thoughts? Just a few more structs to store extra reflection info for CF runtime, mainly uniform information.

Yes, that's the plan. My previous comment was about the current state of the PR but I'm heading towards moving all Spirv dependencies (except for SPIRV-Cross) into cute-shader.

RandyGaul commented 1 week ago

Looking quite good, and nice job on the documentation. Let me know when you feel like it's ready for me to pull it down and try things out.

bullno1 commented 1 week ago

Except for stylistic changes, which I'll get to later today, there should not be anymore implementation changes.