Skip to content

New Proposal: Draft proposal to modify resource typing in HLSL #461

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

Tobski
Copy link

@Tobski Tobski commented Mar 26, 2025

In discussion with @llvm-beanz about how resources should be handled in future, myself and others (including @llvm-beanz) have been working on a proposed overhaul to HLSL's resource model, with the following properties:

  • Resource type handling overhauled for consistency
  • Stronger typing added to resource heap access
  • "Raw" buffer types added for handling GPU VAs
  • Recursive typing (e.g. buffers can contain buffers or images)
  • "Bindless" access for root and local root data
  • Enables deprecation of descriptor tables

The big wins here for shader authors are the ability to reason clearly about how resource types map to real data, the ability to define recursive types, and having the ability to more strongly type their accesses.

For example, the following shader code would be valid and meaningful with this proposal:

struct SomeResources {
	Texture2D texture;
	RWStructuredBuffer<Texture2D> bufferOfTextures;
};

ConstantBuffer<SomeResources> resourceBuffer;

In the above, each resource is actually a handle into the heap, set as a 32-bit integer value in memory, noting that these can also be written to memory as well.

POINTERS: Handling for GPU VAs is added, enabling shader authors to declare GPU VA anywhere in memory as a "Raw" buffer type, mirroring the regular resource types. These can be loaded and stored in the same way as other resources, except they are a 64-bit VA rather than a 32-bit heap offset. There's also a currently open issue about adding a way to subset them which I'd like to explore as well, to enable a limited form of pointer math.

This does not, as currently proposed, require any changes to the DX12 or Vulkan resource models, though some features may need some driver changes, and there are some open issues and suggested directions which would require changes.

 - Resource type handling overhauled for consistency
 - Stronger typing added to resource heap access
 - "Raw" buffer types added for handling GPU VAs
 - Recursive typing (e.g. buffers can contain buffers or images)
 - "Bindless" access for root and local root data
 - Enables deprecation of descriptor tables
@Tobski
Copy link
Author

Tobski commented Mar 28, 2025

Some external discussion has been thrown around about type handling, and I've retooled ResourceEntry to be a type now, with a 32-bit in-memory representation just like resource types are proposed as. The option for the function is still there, but under an open issue, with rationale for why it's not part of the proposal anymore.

@Tobski
Copy link
Author

Tobski commented Mar 28, 2025

Also just added an issue about bounds checking and VA buffer sizing as this has also come up in conversation repeatedly.

@Jasper-Bekkers
Copy link

Some external discussion has been thrown around about type handling, and I've retooled ResourceEntry to be a type now, with a 32-bit in-memory representation just like resource types are proposed as. The option for the function is still there, but under an open issue, with rationale for why it's not part of the proposal anymore.

Since this is a 32-bit valued type, can I construct this type from a uint myself? For example, we have this in our API and we bitpack the equivalent of this into our GpuMaterial struct together with a flat color. Since this proposal very closely matches our bindless rendering blog posts, I'd like to make sure we can still at least get that behavior (https://blog.traverseresearch.nl/bindless-rendering-setup-afeb678d77fc and co).

For us, this type is modeled with the following core features:

  • RenderResourceHandle::unsafeFromUint(uint handle) this disables all validation, but makes it so we can construct this type from any uint.
  • RenderResourceHandle::invalid()
  • RenderResourceHandle::isValid()

And the following validation features

  • RenderResourceHandle::resourceTag() (texture, buffer, tlas)
  • RenderResourceHandle::isWritable()
  • RenderResourceHandle::version() (bumped if the slot gets recycled)
  • RenderResourceHandle::readIndex() (points to SRV)
  • RenderResourceHandle::writeIndex() (points to UAV)

@Tobski
Copy link
Author

Tobski commented Mar 28, 2025

Some external discussion has been thrown around about type handling, and I've retooled ResourceEntry to be a type now, with a 32-bit in-memory representation just like resource types are proposed as. The option for the function is still there, but under an open issue, with rationale for why it's not part of the proposal anymore.

Since this is a 32-bit valued type, can I construct this type from a uint myself? For example, we have this in our API and we bitpack the equivalent of this into our GpuMaterial struct together with a flat color. Since this proposal very closely matches our bindless rendering blog posts, I'd like to make sure we can still at least get that behavior (https://blog.traverseresearch.nl/bindless-rendering-setup-afeb678d77fc and co).

For us, this type is modeled with the following core features:

* `RenderResourceHandle::unsafeFromUint(uint handle)` this disables all validation, but makes it so we can construct this type from any uint.

* `RenderResourceHandle::invalid()`

* `RenderResourceHandle::isValid()`

And the following validation features

* `RenderResourceHandle::resourceTag()` (texture, buffer, tlas)

* `RenderResourceHandle::isWritable()`

* `RenderResourceHandle::version()`  (bumped if the slot gets recycled)

* `RenderResourceHandle::readIndex()` (points to SRV)

* `RenderResourceHandle::writeIndex()` (points to UAV)

Right now there's an open issue about this - the issue with providing a "let me construct it" function is just that it enables developers to not construct it until the last second; making it hard for a compiler (or more importantly debugger) to reason about - but this is a good use case that I think is justification enough to add the constructor. I'm mostly just wary of people misusing it.

@Tobski
Copy link
Author

Tobski commented Mar 28, 2025

I do like that you have "unsafe" on the direct construction though, maybe it's worth doing the same.

@Tobski
Copy link
Author

Tobski commented Apr 3, 2025

@Jasper-Bekkers I've re-added the construction of resource entries from indices, so your use case should be covered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

4 participants