Open ukari opened 3 years ago
It's definitely worth investigating what information can be extracted from a shader or shader pipeline which would allow for automation of Vulkan operations (such as creation of a graphics pipeline and binding of appropriate resources).
Given that Vulkan is based on SPIR-V
, I think it makes the most sense to have something that handles SPIR-V
directly and extracts relevant information. Yet it still seems quite difficult as there are a lot of features one needs to take into account: descriptor sets, binding numbers, arrayed descriptors, visibility of descriptors in different stages, different storage classes (uniform buffers, storage buffers, push constants, acceleration structures,...), and so on. I doubt it's really possible to come up with a comprehensive solution that would avoid having to manually handle resource management on the Vulkan side in general. That's what I keep finding with the Vulkan API: you try to come up with some abstractions to simplify your tasks, but then when your requirements change ever so slightly you realise you needed access to some part or other. So at some level I believe there's no bypassing the low-level nature of Vulkan unless you start strongly restricting functionality.
You might be interested in the approach I took here for handling descriptor sets. You specify a bunch of different descriptors and it will go ahead and figure out everything it needs to handle
See for instance this example in which I declare the kind of descriptor sets I want, and then later on the shader stage flags and the data to use for initialisation. The functions from Vulkan.Resource
then allocate everything, returning the descriptor set layouts, descriptor sets, and functions that allow you to update the underlying data that the descriptors point to (e.g. to move the camera).
@sheaf Hi, I read a bit of your example. I have some questions but don't know it is suitable to open a issue under FIR so I ask here.
FIR seems directly generate spirv code from AST, why there is a example/CreateDirs which helps to compile shader to a spv file. This weird me a bit. I thought it could use a temporary directory for storage spv file or directly pass spv code to vulkan api. Or maybe this is just for better generated spirv debug experience?
Thy way FIR use to write shader is a eDSL -> spv
approach. It would be more nice if there could be a vulkan glsl -> eDSL
or spv -> eDSL
because people mostly teach shader in glsl or hlsl. Write spriv with eDSL is a little difficult.
The data directory thing is just a way of writing the shader files to disk in a portable way. I'm using it to implement live shader reloading (by watching the files change on disk), and it's also useful to have the SPIR-V
on disk so that you can run the various SPIR-V
tools on it. However it's also possible to directly pass the SPIR-V
data to Vulkan without writing to disk (personally I find it more convenient to have them on disk).
I wrote the FIR
library specifically to avoid having to write GLSL
(and in fact I started the project when I realised I could bypass GLSL entirely by compiling directly to SPIR-V
), but I understand that it's not for everyone.
Thanks!
In general this kind of stuff seems like a really good fit for vulkan-utils
.
with the Vulkan API: you try to come up with some abstractions to simplify your tasks, but then when your requirements change ever so slightly you realise you needed access to some part or other
This is certainly true, but as long as there's some "escape hatch" then covering the simple cases is very handy.
Whatever ends up in utils would have to have some good documentation and an example due to the trickyness of this in vulkan.
There can be a package that has only the base types for SPIR-V derived data (and maybe code generation build-tools).
Shader-producing packages (vulkan-utils, FIR, shader libraries) then can provide types and values to shader-consuming packages (vulkan examples, frameworks and projects) with compile-time compatibility checks. There is jQuery on hackage, why not bloom postprocessing code?
Same energy: https://github.com/embarkstudios/rust-gpu#why-embark
@dpwiz What is a SPIR-V derived data? Does it means types for the json of spirv-cross reflection?
@dpwiz What is a SPIR-V derived data? Does it means types for the json of spirv-cross reflection?
Yes, the reflection data.
Is anyone works on this? I am not sure how to contribute it due to the example I wrote only support the few part of reflection data now.
Should I put the WIP stuff into Vulkan.Utils module though the feature is still weak? Or just put it into the examples?
I'd suggest sending a PR with the code packaged as vulkan-reflect
. Maybe there can be a part that works without even depending on the big vulkan
package.
note
The api in current example
makeDescriptorInfo :: Vector (Shader, Reflection) -> Vector (DescriptorSetLayoutCreateInfo '[])
-- ^ not rely `vulkan` ^ rely on `vulkan`
-- ^ not rely `vulkan`
And in this reflect
package(in imagination), the api could be like
data DescriptorSetLayout = ...
-- ^ not rely `vulkan`
makeDescriptorInfo :: Vector (Shader, Reflection) -> (DescriptorSetLayout -> a) -> Vector a
-- ^ not rely `vulkan`
-- ^ not rely `vulkan`
@dpwiz I noticed that FIR
examples also use stuffs like PipelineShaderStageCreateInfo from vulkan
package. Is it worth to abstract a part which not rely on vulkan
? There seems no more active projects(except fir
and vulkan
) about vulkan in haskell
I imagine some CLI or web tool that can be used to inspect shader binaries and maybe generate code. They may not need to actually instantiate Vulkan data or use any libvulkan
code.
But things like "just give me an appropriate CreateInfo" can be a great addition to vulkan-utils
.
I make a vulkan-reflect branch locally https://github.com/ukari/vulkan/tree/vulkan-reflect
reflect'
, reflection'
makePipelineVertexInputStateCreateInfo
only support single binding for input vertex, there could be a new helper function to support multiple binding with signature MultipleBinding -> PipelineVertexInputStateCreateInfo '[] -> PipelineVertexInputStateCreateInfo '[]
Sampler2D -> DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
You can start a PR so we can post comments attached to actual code.
I may be wrong, but it seems you decode from Aeson's Text
into String
type to fields only to use fromString
function via type class. You can add FromJSON
instances directly to types like ShaderStage
and use Aeson.withText
wrappers to decode its values right away.
data EntryPoint = EntryPoint
{ name :: Text
, mode :: ShaderStage
} deriving (Show, Generic, FromJSON, ToJSON)
BTW, there are now 2 packages to query spirv-reflect
instead of spirv-cross
I haven't tried to generate haskell types, but it contains a bit more information about types and their layouts.
I write a example https://gist.github.com/ukari/6b9d94b04c3c26ff63ffd4663914c7da
and inlined some examples which could easily run by excute
test2
(formakeShaderInfo
),test3
(formakeDescriptorInfo
),test4
(formakeInputInfo
)now this only support single binding for input vertex, which let all input vertex attribute have a default binding = 0.
maybe can provide a binding map parameter to specify individual binding by name, like
foo [(1, ["inPos", "inColor"]) (2, ["texCoord"])]
speficies that(binding = 1) inPos, (binding = 1) inColor, (binding = 2) texCoord
here is some related references:
SaschaWillems - Multiple Vulkan buffer binding points
island pipeline