shader-slang / slang

Making it easier to work with shaders
MIT License
1.78k stars 159 forks source link

Running examples like "triangle" fails to find corresponding "shader.slang" #4314

Open natevm opened 2 weeks ago

natevm commented 2 weeks ago

Figured I'd post this here, since a new user will likely hit the same issue.

When I run an example like "triangle.exe" within vscode (using the cmake build system), the current working directory for triangle.exe by default is "build/Debug/bin/", which is the same directory containing triangle.exe. This example expects "shader.slang" to be in the current working directory, but the actual shader is at "examples/triangle/shaders.slang"

An easy enough workaround is to just copy the shader.slang file into /build/Debug/bin, but a novice user might not know how to interpret the crash in the example. When the shader is not found, the app kinda just silently fails without any useful error messages being printed out to the terminal.

natevm commented 2 weeks ago

One option for simplicity, for most of my projects, I just embed the shader as part of the executable directly using a cmake script.

That script can be found here: https://github.com/gprt-org/GPRT/blob/master/gprt/cmake/embed_devicecode.cmake

Then, the examples in my projects call the cmake macro, which generates a target for compiling the device code offline and then embedding the binary into a .cpp file following the output target name.

This .cpp is added to a target, which can be linked into the main sample executable. https://github.com/gprt-org/GPRT/blob/master/samples/s01-singleTriangle/CMakeLists.txt#L23-L37

I understand that Slang tends to favor online compilation over offline compilation, but perhaps a similar custom build target could be made to transfer over the shader file into the build folder.

chaoticbob commented 2 weeks ago

Hey @natevm, which commit are you using?

natevm commented 2 weeks ago

This is with top of tree on master.

swoods-nv commented 2 weeks ago

@chaoticbob Any chance you can help out with this one?

chaoticbob commented 1 week ago

I took a quick look at this. There's a couple of minor pain points when working VSCode that I'm not sure how to solve yet:

Having the cwd in the configuration directory isn't necessarily a problem if there's away to copy the shader and assets to it, but it will mean two copies. The MSVC path actually puts the cwd at the top level build directory and avoids duplicate copies.

I'll investigate more soon.

natevm commented 1 week ago

@chaoticbob You'll likely want to make a custom CMake target like I proposed. These take the appearance of a "build", but instead envoke certain commands, like copying shaders to a build directory.

I don't recommend editing launch.json, as not everyone will be using VSCode as their editor. The benefits of CMake enable workflows like these which for the most part are agnostic to the end user's editor.

natevm commented 1 week ago

Just for some context, here's an example where in CMake I add a custom command which calls into the slangc commandline compiler. But really, any commandline arg is an option:

https://github.com/gprt-org/GPRT/blob/fbec2267e7e2fb670b681880b8c9bd399731a12e/gprt/cmake/embed_devicecode.cmake#L91-L105

These custom commands can have dependencies listed. Whenever any of those dependencies change, the command is marked as "dirty" and indicates to any subsequent depending targets that this command needs to re-run itself.

Finally, those commands are associated with an "object library" target, which subsequent "executable targets" like this triangle example can supply as a dependency via "target_link_libraries".

Here's where I create an example library target: https://github.com/gprt-org/GPRT/blob/fbec2267e7e2fb670b681880b8c9bd399731a12e/gprt/cmake/embed_devicecode.cmake#L123-L124

In the examples case here, you might make one singular library target that just copies over all example .slang shaders via one or multiple separate add_custom_commands to the build directory. Usually you'd figure out this path using something like the "CMAKE_CURRENT_BINARY_DIR" variable.

If it's helpful, this is where I call my particular macro (which stores the object library handle in the OUTPUT_TARGET variable) . You can see me passing that object library in as the input to target_link_libraries right after my add_executable command. https://github.com/gprt-org/GPRT/blob/fbec2267e7e2fb670b681880b8c9bd399731a12e/samples/s01-singleTriangle/CMakeLists.txt#L23-L37

jkwak-work commented 3 days ago

@venkataram-nv mentioned a similar problem on Linux system today. Venki, can you describe the problem here again for future reference?

venkataram-nv commented 2 days ago

There is a similar problem with the shaders not being copied over to build/{Mode}/bin/ in Linux. In this case though it is mainly because the fix from here only adds the copy step for Windows/MSVC systems. So far I have tried removing the if(...)s for MSVC, and after that it does indeed copy the resources, but the only remaining step is to perhaps copy the actual example executable file to the same directory as well.