Skip to content

[SPIRV] Implements vk::BufferPointer proposal #7163

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

Merged
merged 1 commit into from
Apr 2, 2025

Conversation

danbrown-amd
Copy link
Contributor

Implements vk::BufferPointer proposal.
Closes #6489.

Copy link
Contributor

github-actions bot commented Feb 28, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@Keenuts Keenuts left a comment

Choose a reason for hiding this comment

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

I need to look more, early feedback

Comment on lines +547 to +559
/// <summary>Adds a constructor declaration to the specified class
/// record.</summary> <param name="context">ASTContext that owns
/// declarations.</param> <param name="recordDecl">Record declaration in which
/// to add constructor.</param> <param name="resultType">Result type for
/// constructor.</param> <param name="paramTypes">Types for constructor
/// parameters.</param> <param name="paramNames">Names for constructor
/// parameters.</param> <param name="declarationName">Name for
/// constructor.</param> <param name="isConst">Whether the constructor is a
/// const function.</param> <returns>The method declaration for the
/// constructor.</returns>
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit:
Is doxygen still generatable? (Couldn't make it work).
If no, might be more readable to have a normal comment.

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 don't know, but I did it that way for consistency with the rest of the file. Let me know if you still want it changed.

Copy link
Collaborator

@s-perron s-perron left a comment

Choose a reason for hiding this comment

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

This generally looks go. Thanks for getting this done. It is seems solidly implemented. I have a few concerns about the potential for future errors. With a few asserts we could address that.

I have not looked at the tests yet, nor have I tried running anything yet. I'll try to tomorrow.

@danbrown-amd danbrown-amd force-pushed the vk-buffer-pointer-pr branch from 75cd0be to 2354f87 Compare March 5, 2025 04:54
Copy link
Collaborator

@s-perron s-perron left a comment

Choose a reason for hiding this comment

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

I have a suggestion for a a few extra tests. Once they are in, I feel comfortable approving.

Can you also add a tests where an atomic operation is done? We want to be sure that works too.

Is the has_feature uses anywhere? We should make sure that works.

s-perron
s-perron previously approved these changes Mar 17, 2025
Copy link
Collaborator

@Keenuts Keenuts left a comment

Choose a reason for hiding this comment

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

Thanks for the work!
Good improvements, but looks like there are still some failure cases:

Seems like I also reach an assert when this snippet:

// RUN: %dxc -E main -T cs_6_7  %s -spirv -E main | FileCheck %s

struct Content {
  float a;
};

typedef vk::BufferPointer<Content> BufferContent;
typedef vk::BufferPointer<BufferContent> BufferBufferContent;

[[vk::push_constant]]
BufferContent buffer;

[numthreads(1, 1, 1)]
void main() {
  float tmp = buffer.Get().a;
  buffer.Get().a = tmp;
}

@Keenuts
Copy link
Collaborator

Keenuts commented Mar 18, 2025

Also get an assert/validation errors with those 2 snippets:

// RUN: %dxc -E main -T cs_6_7  %s -spirv -E main | FileCheck %s

struct Content {
  uint a;
};

typedef vk::BufferPointer<uint> BufferContent;

[[vk::push_constant]]
BufferContent buffer;

[numthreads(1, 1, 1)]
void main() {
  uint data = buffer.Get();
  buffer.Get() = data;
}
Error: assert(IsPtr(ptr_id) && "Cannot get the variable when input is not a pointer.")
(assert in SPIRV-Tools)

Looks like removing optimizations or changing the snippet to this shows the validation error instead:

// RUN: %dxc -E main -T cs_6_7  %s -spirv -E main | FileCheck %s

struct Content {
  uint a;
};

typedef vk::BufferPointer<uint> BufferContent;

[[vk::push_constant]]
BufferContent buffer;

[numthreads(1, 1, 1)]
void main() {
  buffer.Get() = 1;
}

@Keenuts
Copy link
Collaborator

Keenuts commented Mar 18, 2025

Found 2 other case:

// RUN: %dxc -E main -T cs_6_7  %s -spirv -E main | FileCheck %s

struct Content {
  int a;
};

typedef vk::BufferPointer<Content> BufferContent;
typedef vk::BufferPointer<BufferContent> BufferBuffer;

//[[vk::push_constant]]
//BufferContent buffer;

RWStructuredBuffer<BufferBuffer> rwbuf;

void foo(BufferContent bc) {
  bc.Get().a = 1;
}

[numthreads(1, 1, 1)]
void main() {
  foo(rwbuf[0].Get());
}
fatal error: generated SPIR-V is invalid: [VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708] Memory accesses with PhysicalStorageBuffer must use Aligned.
  %21 = OpLoad %_ptr_PhysicalStorageBuffer_Content %20
// RUN: %dxc -E main -T cs_6_7  %s -spirv -E main | FileCheck %s

struct Content {
  int a;
};

typedef vk::BufferPointer<Content> BufferContent;
typedef vk::BufferPointer<BufferContent> BufferBuffer;

//[[vk::push_constant]]
//BufferContent buffer;

RWStructuredBuffer<BufferBuffer> rwbuf;

// Wrong type in the parameter.
void foo(BufferContent bc) {
  bc.Get().a = 1;
}

[numthreads(1, 1, 1)]
void main() {
  foo(rwbuf[0]);
}
fatal error: generated SPIR-V is invalid: OpAccessChain reached non-composite type while indexes still remain to be traversed.
  %21 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %20 %int_0

@Keenuts
Copy link
Collaborator

Keenuts commented Mar 18, 2025

Looks like casting would also need additional restrictions:

// RUN: %dxc -E main -T cs_6_7  %s -spirv -E main | FileCheck %s

struct Content {
  int a;
};

typedef vk::BufferPointer<Content> BufferContent;
typedef vk::BufferPointer<BufferContent> BufferBuffer;

RWStructuredBuffer<BufferContent> buf;

void foo(const BufferContent bc) {
  bc.Get().a = 1;
}

[numthreads(1, 1, 1)]
void main() {
  static BufferContent bcs = buf[0];
  static BufferBuffer bbs = (BufferBuffer)bcs;
}
fatal error: generated SPIR-V is invalid: Expected unsigned int scalar type as Result Type: ConvertPtrToU
  %19 = OpConvertPtrToU %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_Content %18

@danbrown-amd
Copy link
Contributor Author

Should it actually be legal to have buffer pointer push constants? The front end rejects non-struct push constant declarations., and although values of type vk::BufferPointer are objects, they don't have data members and thus aren't treated as records.

@Keenuts
Copy link
Collaborator

Keenuts commented Mar 19, 2025

Should it actually be legal to have buffer pointer push constants?

Mmmm, I don't think there is something that forbids it since we allow it for ConstantBuffers (at least we have one test checking this vk.push-constant.constantbuffer.assign.hlsl)
(@s-perron in case I'm saying something wrong)

What frontend are you referring to?

@s-perron
Copy link
Collaborator

Should it actually be legal to have buffer pointer push constants?

Mmmm, I don't think there is something that forbids it since we allow it for ConstantBuffers (at least we have one test checking this vk.push-constant.constantbuffer.assign.hlsl) (@s-perron in case I'm saying something wrong)

What frontend are you referring to?

I believe the issue is that Vulkan requires that the type of a push constant must be a struct. That is enforced by the compiler: https://godbolt.org/z/8r38xss5o. Since the vk::BufferPointer is a pointer and not a struct, we should not allow it as a push constant unless it is contained in another struct.

@Keenuts
Copy link
Collaborator

Keenuts commented Mar 19, 2025

Ah that's right,
And the ConstantBuffer<MyStruct> is allowed only because it's a struct it contains, but ConstantBuffer<int> is not allowed.

@danbrown-amd
Copy link
Contributor Author

I've ruled out buffer pointers as push constants, tightened up the typing/casting rules, and fixed the missing load alignment bug.

Copy link
Collaborator

@Keenuts Keenuts left a comment

Choose a reason for hiding this comment

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

Hello! Thanks for the changes!
I'm fine moving forward with this PR so we can find more bugs with the first users, but I'd like for the fixed bugs to have test cases.
(I provided snippets/run lines, so making them into tests is mostly adding a 2>&1 | FileCheck and CHECK: <expected-error>)

@danbrown-amd
Copy link
Contributor Author

I've pushed the requested tests.

I've rebased on the most recent main and fixed the conflicts locally, but a recent (March 4) change to SPIRV-Tools causes non-termination on the linked list example. It appears that Handler_OpTypePointer_StorageBuffer16BitAccess() in trim_capabilities_pass.cpp doesn't account for recursive types.

Keenuts added a commit to Keenuts/SPIRV-Tools that referenced this pull request Mar 27, 2025
When a type was recursive (or for the matter any instruction ID
usage), the DFSWhile implementation would loop indefinitely.
Added a history map to keep track of the visited instructions.

Required for microsoft/DirectXShaderCompiler#7163

Signed-off-by: Nathan Gauër <brioche@google.com>
Keenuts added a commit to Keenuts/SPIRV-Tools that referenced this pull request Mar 27, 2025
When a type was recursive (or for the matter any instruction ID
usage), the DFSWhile implementation would loop indefinitely.
Added a history map to keep track of the visited instructions.

Required for microsoft/DirectXShaderCompiler#7163

Signed-off-by: Nathan Gauër <brioche@google.com>
@Keenuts
Copy link
Collaborator

Keenuts commented Mar 27, 2025

Handler_OpTypePointer_StorageBuffer16BitAccess

Ah right, thanks for finding, sent KhronosGroup/SPIRV-Tools#6070 to fix the issue.

s-perron pushed a commit to KhronosGroup/SPIRV-Tools that referenced this pull request Mar 27, 2025
When a type was recursive (or for the matter any instruction ID
usage), the DFSWhile implementation would loop indefinitely.
Added a history map to keep track of the visited instructions.

Required for microsoft/DirectXShaderCompiler#7163

Signed-off-by: Nathan Gauër <brioche@google.com>
@Keenuts
Copy link
Collaborator

Keenuts commented Mar 27, 2025

Once #7269 is merged you'll be able to rebase 👍️

@Keenuts Keenuts requested a review from s-perron April 1, 2025 16:27
@s-perron s-perron enabled auto-merge (squash) April 1, 2025 21:26
@s-perron s-perron merged commit 9eb7119 into microsoft:main Apr 2, 2025
12 checks passed
@github-project-automation github-project-automation bot moved this from New to Done in HLSL Roadmap Apr 2, 2025
@@ -1232,6 +1237,9 @@ static const ArBasicKind g_AnyOutputRecordCT[] = {
static const ArBasicKind g_DxHitObjectCT[] = {AR_OBJECT_HIT_OBJECT,
AR_BASIC_UNKNOWN};

static const ArBasicKind g_VKBufferPointerCT[] = {AR_OBJECT_VK_BUFFER_POINTER,
Copy link
Collaborator

Choose a reason for hiding this comment

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

We're getting build breaks in Chromium where ENABLE_SPIRV_CODEGEN is not defined. I think this decl should be wrapped in #ifdef ENABLE_SPIRV_CODEGEN?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm working on a patch.

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'm testing a fix now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created pull request.

dneto0 added a commit to dneto0/DirectXShaderCompiler that referenced this pull request Apr 3, 2025
PR microsoft#7163 added support for vk::BufferPointer

It did not build when building for non-SPIR-V scenarios.

Bug: crbug.com/408215487
dneto0 added a commit to dneto0/DirectXShaderCompiler that referenced this pull request Apr 3, 2025
PR microsoft#7163 added support for vk::BufferPointer

It did not build when building for non-SPIR-V scenarios.

Bug: crbug.com/408215487
danbrown-amd added a commit to danbrown-amd/DirectXShaderCompiler that referenced this pull request Apr 3, 2025
([SPIRV] Implements vk::BufferPointer proposal)
s-perron pushed a commit that referenced this pull request Apr 3, 2025
…fferPointer proposal) (#7306)

#ifdef ENABLE_SPIRV_CODEGEN was omitted in several places.
pow2clk pushed a commit that referenced this pull request May 22, 2025
Modification copyright notices were added in error to files changed in
[PR
#7163](#7163).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[SPIR-V][Feature Request] Implement Buffer Pointers in HLSL With vk::BufferPointer
5 participants