Skip to content
New issue

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

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

Already on GitHub? # to your account

WIP: Initial stub for mesh shaders #3236

Merged
merged 1 commit into from
May 7, 2020
Merged

WIP: Initial stub for mesh shaders #3236

merged 1 commit into from
May 7, 2020

Conversation

MatusT
Copy link
Contributor

@MatusT MatusT commented Apr 28, 2020

This is my attempt at adding support for mesh shaders.

This (first) PR only stubs the API. From my investigation, the extension is relatively simple(it effectively only adds new shaders and 3 draw commands mirroring the original ones) and seems to be the same across Direct3D and Vulkan.

Even though the Vulkan only has NV extension so far, based on announcements of RDNA2 and DirectX Ultimate we can expect KHR version and I don't see how it could diverge in any way. Thus, both Vulkan and DX12 implementations should be trivial.

I know nothing about Metal and I am not aware of information about support for mesh shaders. At worst, they could be emulated using compute shaders but It would probably be so slow that It would be practically worthless.

Tasks:

  • Stub the API
  • Implement empty backend
  • Implement non-functional Vulkan backend
  • Implement non-functional DirectX 12 backend
  • Implement non-functional DirectX 11 backend
  • Implement non-functional Metal backend
  • Implement non-functional OpenGL backend
  • Fix examples compilation errors
  • Fix warden compilation errors

PR checklist:

  • make succeeds (on *nix)
  • make reftests succeeds
  • tested examples with the following backends
    • DX12
    • Vulkan
    • OpenGL
    • Metal (have no way of testing)
  • rustfmt run on changed code

Resources:
Vulkan specification of mesh shaders
DirectX specification of mesh shader

@monocodus
Copy link

monocodus bot commented Apr 28, 2020

The .monocodus config file is invalid. The code review has not been performed.
Check config documentation here

Click to expand the list of errors ocurred.

.monocodus
Invalid config version: None


2 similar comments
@monocodus
Copy link

monocodus bot commented Apr 28, 2020

The .monocodus config file is invalid. The code review has not been performed.
Check config documentation here

Click to expand the list of errors ocurred.

.monocodus
Invalid config version: None


@monocodus
Copy link

monocodus bot commented Apr 28, 2020

The .monocodus config file is invalid. The code review has not been performed.
Check config documentation here

Click to expand the list of errors ocurred.

.monocodus
Invalid config version: None


@kvark
Copy link
Member

kvark commented Apr 28, 2020

Thank you, that's amazing to see! I'll do a proper review shortly.
Just wanted to comment on Metal and platforms without the mesh shaders.

IIRC from WebGPU discussions, the whole idea of the mesh shaders was kicked off by some research work of doing them on compute, long before it became available in hardware/drivers. Therefore, compute path should be possible, even if not as efficient. I'd like us to have that path available at some point. We have Hints specifically to tell the users whether something is natively supported versus emulated.

@kvark
Copy link
Member

kvark commented Apr 28, 2020

there be MeshPipelineDesc as counterpart to GraphicsPipelineDesc?

Only if Vulkan or D3D12 define a separate pipeline kind for this. As far as I see from a brief look, it's all the same graphics pipeline, just a bunch of stages are replaced. So let's keep it GraphicsPipelineDesc

GraphicsPipelineDesc silently ignores input_assembler and contents of vertex_buffers and attributes

Can we have an enum?

enum PrimitiveAssemer {
  Vertex(InputAssemer, VertexBuffers),
  Mesh(...),
}

@MatusT
Copy link
Contributor Author

MatusT commented Apr 28, 2020

Can we have an enum?

enum PrimitiveAssemer {
  Vertex(InputAssemer, VertexBuffers),
  Mesh(...),
}

I will try to summarise here what options I see.

Firstly, just the struct itself:

  1. Follow what Vulkan/DX12 does and silently ignore unnecessary attributes.
  • Pros:
    • Backwards compatible API, since members are public. I see this as a very important attribute.
  • Cons:
    • Vec<VertexBufferDesc> and Vec<AttributeDesc> must be set empty. Not that annoying.
    • InputAssemblerDesc must be filled with some values, which does not really make sense and seems annoying. However, I would personally circumvent this by implementing Default for it + Default for GraphicsPipelineDesc itself so that a user could create the struct with only necessary attributes and just .. Default::default() the rest.
  1. Make an enum
  • Pros:
    • You now have only one member and it kind of makes sense.
  • Cons:
    • Breaking change.
    • Enum must contain 3 whole members inside one variant and absolutely none in the second:
    enum PrimitiveAssembler {
      Vertex(Vec<VertexBufferDesc>, Vec<AttributeDesc>, InputAssemblerDesc),
      Mesh, // literally nothing
    }
    
    You can of course have any variation: make those 3 members optional or make only InputAssemblerDesc optional

Secondly, there is a question of GraphicsPipelineDesc::new() function. Similar questions with respect to API apply as above:

  • Make primitive and rasterizer optional? Remove them altogether from the new function?
  • Make a new new_mesh function? I am personally in favour of this option.

Since I have started writing about breakage of the API, I have realised that the API of GraphicsShaderSet will be broken in any case because vertex becomes optional and task+mesh must be filled. I don't know how many projects rely on the stability of gfx, so I am unable to asses the potential disruption in the ecosystem.

As you are the maintainer, you should choose the course of action and I will modify the code accordingly.

@kvark
Copy link
Member

kvark commented Apr 28, 2020

the API of GraphicsShaderSet will be broken in any case because vertex becomes optional

Right, I don't think we should try too hard to avoid API breakage here. Consider this to be experimental, we'll adjust as we go, and master is where experimentation happens.

Mesh, // literally nothing

I think we can do better than that. We can exclude the task and mesh stages from the graphics shader set and put them here:

enum PrimitiveAssember<'a, B> {
  Vertex {
    buffers: Vec<VertexBufferDesc>,
    attributes: Vec<AttributeDesc>,
    input_assember: InputAssemblerDesc,
  },
  Mesh {
    task_shader: EntryPoint<'a, B>,
    mesh_shader: EntryPoint<'a, B>,
  },
}

@msiglreith
Copy link
Contributor

+1 for the enum variant - totally replacing the GraphicsShaderSet might be an option here and move all old pipeline stages into the Vertex variant. Fragment shader entrypoint could live then as field in the GraphicsPipelineDesc or be part of some other sub desc.

@MatusT
Copy link
Contributor Author

MatusT commented Apr 29, 2020

I updated the API with the Enum idea. I must admit that the solution is slowly growing on me.

I also added 2 new errors to the pipeline CreationError, one for when the mesh shader is not supported and the other one for when the vertex stage is missing in vertex primitive assembly.

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

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

Thank you! I believe this is great amount of good work here.
Just a few notes on how we should polish this more before landing.

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

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

Ok, looks like we are almost there :)

@MatusT
Copy link
Contributor Author

MatusT commented May 2, 2020

We have one final big problem to resolve that I just realized.

There is one major difference between DX12 and Vulkan.
Vulkan only allows 1D Tasks https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdDrawMeshTasksNV.html.
While DX12 allows specifying all 3 dimensions https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html#dispatchmesh-api. In addition, It does not have offsets(first_task).

I modelled the API according to Vulkan, which is currently the lowest common denominator.

Alternative could be:

  • allowing all 3 dimensions and reporting maximum sizes of Y, Z as 1 on the Vulkan backend
  • maybe patch the shader to transform 1D to 3D?

Maybe this will change with KHR version of the extension and we should wait until then. Unless, NVIDIA/Khronos/AMD could give use some more formation.

@kvark
Copy link
Member

kvark commented May 2, 2020

Let's model this after Vulkan for now, and then reconsider when KHR extension comes out.
Are you in Khronos by any chance? We could use some early insights on what the API will be, if it happens at all :)

@MatusT
Copy link
Contributor Author

MatusT commented May 2, 2020

Let's model this after Vulkan for now, and then reconsider when KHR extension comes out.

I will leave It as is It is then.

Are you in Khronos by any chance? We could use some early insights on what the API will be, if it happens at all :)

I thought you were part of Khronos on behalf of Mozilla :D. What I would give for being part of Khronos. No, I am merely a master's student who is using WebGPU for my diploma thesis and I wanted to use mesh shaders for that.

@kvark
Copy link
Member

kvark commented May 2, 2020

I am a part of Khronos, just having more than I can chew on my plate. I can dive and check the archives though to see where things are going, at least.
CI mac is experiencing strange failures - https://travis-ci.org/github/gfx-rs/gfx/jobs/682350838#L3665

@kvark
Copy link
Member

kvark commented May 4, 2020

bors try

bors bot added a commit that referenced this pull request May 4, 2020
@bors
Copy link
Contributor

bors bot commented May 4, 2020

try

Build failed:

@kvark
Copy link
Member

kvark commented May 4, 2020

Could you rebase and squash please?

@MatusT
Copy link
Contributor Author

MatusT commented May 4, 2020

Could you rebase and squash please?

Done.

@kvark
Copy link
Member

kvark commented May 4, 2020

bors try

bors bot added a commit that referenced this pull request May 4, 2020
@bors
Copy link
Contributor

bors bot commented May 4, 2020

try

Build failed:

@kvark
Copy link
Member

kvark commented May 4, 2020

I'm confused as to why some PRs are landing fine, and others aren't :/
Anyhow, this nightly error appears to be fixed upstream, just going to wait for the next nightly.

Initial stub for mesh shaders to flesh out the API changes.
Stub mesh shaders


address some details

DX12: remove mesh shaders from the indented block

Improve the code based on review

fix metal backend
@MatusT
Copy link
Contributor Author

MatusT commented May 7, 2020

@kvark CI finally succeeded!

Copy link
Member

@kvark kvark left a comment

Choose a reason for hiding this comment

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

Sweet!
bors r+

@bors
Copy link
Contributor

bors bot commented May 7, 2020

Build succeeded:

@bors bors bot merged commit 7d7159a into gfx-rs:master May 7, 2020
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants