Skip to content

Conversation

@blueskythlikesclouds
Copy link
Contributor

@blueskythlikesclouds blueskythlikesclouds commented Oct 30, 2025

Introduction

This PR adds a point size emulation path in the higher level rendering code to handle D3D12 not supporting it natively.

Implementation Details

Instead of using the point primitive type, two triangles forming a quad are rendered instead. To correctly pass per-point data to each quad, all elements in the mesh's vertex array are modified to have per-instance frequency. The quad itself is procedurally generated in the vertex shader using the vertex index.

Essentially, the draw call changes from:

  • Vertex count: Point count
  • Instance count: Instance count

To:

  • Vertex count: Instance count x 6
  • Instance count: Point count

This also means any shader code that uses vertex or instance indices needs to be adjusted accordingly. This is handled using specialized macros, which change to the following definitions when point size emulation is enabled:

  • Vertex index: Instance index
  • Instance index: Vertex index / 6

Caveats

  • Index buffers cannot be used without passing every single vertex buffer as input uniforms to the shader. I'm avoiding this approach because using index buffers with point primitives doesn't make much sense anyway.
  • Indirect calls cannot be supported due to the modifications made to the draw call arguments.

These two issues likely could be solved with geometry shaders but Godot has no support for them and they are horribly inefficient.

Notes

From what I've seen, instance frequency is not used anywhere else in Godot, so I want to make sure the changes I made here make sense:

  • The vertex array create function takes a vertex count argument, and draw lists use this value to determine how many vertices to draw, rather than taking it from the draw command. I decided to pass 0 as the count when point size emulation is used, since technically the array only contains instanced data, and the quads themselves are procedurally generated in the vertex shader. The actual number of "procedurally generated" vertices is passed to the draw command instead.
  • I removed the validation check from the procedural draw path because I'm using instanced vertex data to draw procedural quads, which should be a valid use case.

I'm also not entirely sure about the way I'm passing EMULATE_POINT_SIZE to the shader compiler. Could that cause issues with the shader cache or shader baker?


Fixes #106078.

Comment on lines 840 to 842
if (emulate_point_size) {
point_size_usage_defines += "#define EMULATE_POINT_SIZE\n";
}
Copy link
Member

Choose a reason for hiding this comment

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

This will break shader baking. Since if you bake a shader when the editor is running Vulkan, it will report that point size is supported. But then you will end up with a D3D12 shader without emulate point size being true.

In #102552 Dario had to systematically remove all the places where we changed shader code based on the underlying platform.

Off the top of my head I don't see an easy way out of this issue unless we can somehow push these changes down to an even lower level.

Copy link
Contributor Author

@blueskythlikesclouds blueskythlikesclouds Oct 31, 2025

Choose a reason for hiding this comment

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

That's what I was afraid of. Maybe a specialization constant could do the job? It would add an extra unused interpolator when point size is natively supported though, but only when point coordinate is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed it to a specialization constant, seems to work well.

@blueskythlikesclouds blueskythlikesclouds force-pushed the point-size-emulation-forward-shader branch from 308f94b to 239f9d1 Compare October 31, 2025 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSG nodes' resize handles don't render with the D3D12 driver

3 participants