Skip to content

use spirv-cross for generate some shader related vkCreateInfo in Vulkan.Util? #260

Open

Description

@ukari

I write a example https://gist.github.com/ukari/6b9d94b04c3c26ff63ffd4663914c7da

and inlined some examples which could easily run by excute test2(for makeShaderInfo), test3(for makeDescriptorInfo), test4(for makeInputInfo)

module SpirV
  ( reflection
  , makeShaderInfo
  , makeDescriptorInfo
  , makeInputInfo
  ) where

import Vulkan.Core10.Shader (ShaderModule)

data Shader = Shader
  { stage :: ShaderStage
  , code :: B.ByteString
  } deriving (Show)

data Reflection = Reflection
  { entryPoints :: Vector EntryPoint
  , inputs :: Maybe (Vector Input)
  , textures :: Maybe (Vector Texture)
  , ubos :: Maybe (Vector Ubo)
  } deriving (Show, Generic, FromJSON, ToJSON)

data ShaderInfo = ShaderInfo
  { shaderModuleCreateInfo:: ShaderModuleCreateInfo '[]
  , pipelineShaderStageCreateInfos :: ShaderModule -> Vector (PipelineShaderStageCreateInfo '[])
  }

reflection :: MonadIO m => ShaderStage -> "code" ::: String -> m (Shader, Reflection)

makeShaderInfo :: (Shader, Reflection) -> ShaderInfo

makeDescriptorInfo :: Vector (Shader, Reflection) -> Vector (DescriptorSetLayoutCreateInfo '[])

makeInputInfo :: Vector (Shader, Reflection) -> Maybe (PipelineVertexInputStateCreateInfo '[])

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

Activity

  1. sheaf commented on Feb 12, 2021

    @sheaf
    Collaborator

    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

    • creation of descriptor set layouts,
    • allocation of descriptor sets,
    • initialisation of resources (e.g. writing data to buffers),
    • binding of resources (descriptor sets, vertex buffers, etc).

    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).

  2. ukari commented on Feb 15, 2021

    @ukari
    ContributorAuthor

    @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.

  3. sheaf commented on Feb 15, 2021

    @sheaf
    Collaborator

    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.

  4. expipiplus1 commented on Feb 18, 2021

    @expipiplus1
    Owner

    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.

  5. dpwiz commented on Mar 1, 2021

    @dpwiz
    Collaborator

    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

  6. ukari commented on Mar 2, 2021

    @ukari
    ContributorAuthor

    @dpwiz What is a SPIR-V derived data? Does it means types for the json of spirv-cross reflection?

  7. dpwiz commented on Mar 4, 2021

    @dpwiz
    Collaborator

    @dpwiz What is a SPIR-V derived data? Does it means types for the json of spirv-cross reflection?

    Yes, the reflection data.

  8. ukari commented on Mar 12, 2021

    @ukari
    ContributorAuthor

    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?

  9. dpwiz commented on Mar 13, 2021

    @dpwiz
    Collaborator

    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.

  10. ukari commented on Mar 14, 2021

    @ukari
    ContributorAuthor

    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`
  11. ukari commented on Mar 14, 2021

    @ukari
    ContributorAuthor

    @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

  12. dpwiz commented on Mar 15, 2021

    @dpwiz
    Collaborator

    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.

  13. ukari commented on Mar 17, 2021

    @ukari
    ContributorAuthor

    I make a vulkan-reflect branch locally https://github.com/ukari/vulkan/tree/vulkan-reflect

    some stuffs might need to be done

    • error process
    • reformat
    • haddock
    • some api might need to be removed or redesigned, like reflect', reflection'
    • some function name could be changed to have a more precise name
    • makePipelineVertexInputStateCreateInfo only support single binding for input vertex, there could be a new helper function to support multiple binding with signature MultipleBinding -> PipelineVertexInputStateCreateInfo '[] -> PipelineVertexInputStateCreateInfo '[]
    • support more feature, like Sampler2D -> DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
    • support both GLSL and HLSL
  14. dpwiz commented on Mar 18, 2021

    @dpwiz
    Collaborator

    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)
  15. dpwiz commented on Jul 7, 2022

    @dpwiz
    Collaborator

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions