Skip to content
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

Initial implementation of SP#015 DescriptorHandle<T>. #6028

Merged
merged 24 commits into from
Jan 10, 2025

Conversation

csyonghe
Copy link
Collaborator

@csyonghe csyonghe commented Jan 8, 2025

Closes #6038.

Closes #6010.

@csyonghe csyonghe added the pr: non-breaking PRs without breaking changes label Jan 8, 2025
@csyonghe
Copy link
Collaborator Author

csyonghe commented Jan 8, 2025

/format

@slangbot
Copy link
Contributor

slangbot commented Jan 8, 2025

🌈 Formatted, please merge the changes from this PR

@csyonghe csyonghe changed the title Initial implementation of ResourcePtr<T>. Initial implementation of SP#016 DescriptorHandle<T>. Jan 8, 2025
@csyonghe csyonghe changed the title Initial implementation of SP#016 DescriptorHandle<T>. Initial implementation of SP#015 DescriptorHandle<T>. Jan 9, 2025
@natevm
Copy link
Contributor

natevm commented Jan 9, 2025

Just looked over the proposal. LGTM 👍🏻

jkwak-work
jkwak-work previously approved these changes Jan 9, 2025
Copy link
Collaborator

@jkwak-work jkwak-work left a comment

Choose a reason for hiding this comment

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

Looks good to me.

I left some questions, but I probably have some misunderstandings.

docs/proposals/015-descriptor-handle.md Outdated Show resolved Hide resolved
docs/proposals/015-descriptor-handle.md Outdated Show resolved Hide resolved
source/slang/hlsl.meta.slang Outdated Show resolved Hide resolved
jkwak-work
jkwak-work previously approved these changes Jan 9, 2025
Copy link
Collaborator

@jkwak-work jkwak-work left a comment

Choose a reason for hiding this comment

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

Looks good to me.

docs/user-guide/03-convenience-features.md Outdated Show resolved Hide resolved
jkwak-work
jkwak-work previously approved these changes Jan 9, 2025
Copy link
Collaborator

@jkwak-work jkwak-work left a comment

Choose a reason for hiding this comment

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

Looks good to me.

tangent-vector
tangent-vector previously approved these changes Jan 10, 2025
where T : IOpaqueDescriptor
{
[require(hlsl_glsl_spirv)]
__init(uint2 value); // For HLSL, GLSL and SPIRV targets only.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm guessing this constructor also requires a certain shader model version of SPIR-V capability.

Copy link
Contributor

Choose a reason for hiding this comment

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

Another note is that I'd expect that operation to be de facto available for CPU and CUDA targets as well, since the representation of a handle on those platforms is "just bits" and should fit in 64 bits.

Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice to have a convenience constructor that takes a UInt64 on targets that support such a type. That could be directly implemented on targets that can support it that way, and can decompose the 64-bit integer into a uint2 on the others.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

On CPU and CUDA, a StructuredBuffer is actually 16 bytes, storing both a pointer and a size to support the GetDimension operation, so we can't actually support this constructor on CPU/CUDA for all resource types, unfortunately.

}
```

All builtin types that implements `IOpaqueDescriptor` interface provide a convenience typealias for `DescriptorHandle<T>`. For example, `Texture2D.Handle` is an alias for `DescriptorHandle<Texture2D>`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a comment on this proposal, but I wonder if that behavior could be provided automatically via an extension on types that conform to IOpaqueDescriptor along the lines of:

extension<T : IOpaqueDescriptor> T
{
    typealias Handle = DescriptorHandle<T>;
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this is originally implemented this way but I hit a bug in the type system. I need to fix the type system first before this is possible.


- `operator *` to deference the pointer and obatin the actual descriptor handle `T`.
- Implicit conversion to `T` when used in a location that expects `T`.
- When targeting HLSL, GLSL and SPIRV, `DescriptorHandle<T>` can be casted to and from a `uint2` value.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we be explicit that this only supports explicit casts, and not implicit type conversions?

In my own usage, I try to distinguish (explicit) casting from (implicit) conversion of types, but the distinction might be too subtle to rely on somebody reading this document to know off-hand (and there are also people who apply those terms differently).

- `operator *` to deference the pointer and obatin the actual descriptor handle `T`.
- Implicit conversion to `T` when used in a location that expects `T`.
- When targeting HLSL, GLSL and SPIRV, `DescriptorHandle<T>` can be casted to and from a `uint2` value.
- Equality comparison.
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume this implicitly means equality and inequality.

If we end up adding some kind of IHashable interface to the core library, then we'd also want descriptor handles to be hashable.

Comment on lines +91 to +93
// Alternatively, the following syntax is also allowed, to
// make `DescriptorHandle` appear more like a pointer:
t->Sample(*sampler, float2(0, 0));
Copy link
Contributor

Choose a reason for hiding this comment

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

Unrelated to this proposal, but I find it distasteful that we are adding more and more C++-isms to our language.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ack, but not something we can do here since this was already added to the language along with the pointer support.

If the descriptor handle value is not uniform and `nonuniform` is not called, the result may be
undefined.

### Combind Texture Samplers
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: "Combind" -> "Combined"

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't expect the following to change in this document, but in order to raise a discussion point:

The term "combined texture sampler" is one I find unfortunate, because a "texture sampler" superficially sounds like a thing that samples textures, rather than a pair of two things: a texture and a sampler. Adding the adjective "combined" doesn't do a whole lot to dissuade somebody from that interpretation.

When possible, I tend to refer to such things as "combined texture-sampler pairs." A "texture-sampler pair" clearly communicates that it is (semantically) a pair, and what it is a pair of: a texture and a sampler. In this context the "combined" prefix makes it clear that while the thing is semantically a pair, something might be done as part of combining them, so that the resulting combination could be different from what would result from forming such a pair type in user code.


### Combind Texture Samplers

On platforms without native support for combined texture samplers, we will use both components of the
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah... this part of things makes subtle use of the fact that the (current) D3D case only needs 32 bits to represent a handle, so that a uint2 is actually sufficient for storing two handles (a texture handle and a sampler handle).

This choice would break down the line if handles on D3D eventually become 64-bit values. All of the descriptor types except combined texture-sampler pairs would be able to adapt (using all the bits of the uint2), but combined texture-sampler pairs would require changes to the DescriptorHandle<> type given here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is true, and in that case we will need to change the size of DescriptorHandle<Sampler2D> on D3D. Note that with this revised proposal, DescriptorHandle size is target dependent and we are allowed to make it having different size based on the underlying descriptor type.

docs/proposals/015-descriptor-handle.md Show resolved Hide resolved
source/slang/hlsl.meta.slang Show resolved Hide resolved
Comment on lines +4043 to +4054
// At this stage, we can safely remove the generic `getDescriptorFromHandle` function
// despite it being marked `export`.
for (auto inst : module->getGlobalInsts())
{
if (auto genFunc = as<IRGeneric>(inst))
{
if (!genFunc->hasUses())
{
toRemove.add(genFunc);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a risk that this logic could remove IR generics that it shouldn't, in some future scenario?

I suppose that we don't anticipate any of our targets supporting actual generics in binary code (only specialized or dynamic-dispatch-ified versions).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree there is risk, and we would have to deal with this issue in the future.

@csyonghe csyonghe dismissed stale reviews from tangent-vector and jkwak-work via 0666eb5 January 10, 2025 18:56
@csyonghe csyonghe merged commit 5290c58 into shader-slang:master Jan 10, 2025
15 of 16 checks passed
juliusikkala pushed a commit to juliusikkala/slang that referenced this pull request Jan 12, 2025
…#6028)

* Initial implementation of `ResourcePtr<T>`.

* Update docs

* Fix build error.

* Add more discussion.

* Update documentation.

* Update TOC.

* Fix.

* Fix.

* Add test case for custom `getResourceFromBindlessHandle`.

* Add namehint to generated descriptor heap param.

* Fix.

* Fix.

* format code

* Rename to `DescriptorHandle`, and add `T.Handle` alias.

* Fix compiler error.

* Fix.

* Fix build.

* Renames.

* Fix documentation.

* Documentation fix.

---------

Co-authored-by: slangbot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr: non-breaking PRs without breaking changes
Projects
None yet
5 participants