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

Proposal for mapping resource attributes to DXIL and SPIR-V #76

Merged
merged 4 commits into from
Feb 12, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
386 changes: 386 additions & 0 deletions proposals/NNNN-resource-attributes-in-dxil-and-spirv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,386 @@
<!-- {% raw %} -->

# Mapping Resource Attributes to DXIL and SPIR-V

* Proposal: [NNNN](NNNN-resource-attributes-in-dxil-and-spirv.md)
* Author: [Justin Bogner](https://github.com/bogner)
* Status: **Design In Progress**

## Introduction

There are a number of objects in HLSL that map to shader model resources. We
need to represent these in various ways throughout lowering from the HLSL
language to DXIL and SPIR-V program representations suitable for consumption by
GPU drivers.

This document tries to summarize the information that's needed in the various
parts of the compiler, survey DXC's implementation, and ask questions and make
recommendations about how we want to handle all of this in clang.

## Motivation

There are a number of places where we need to represent resource objects
throughout the compiler. From an HLSL language perspective we need to carry
sufficient information in the AST to track these types. At the LLVM IR level we
need target specific types. Finally, the resulting DXIL and SPIR-V have their
own representations.

## Proposed solution

We'll discuss the set of HLSL objects that we need to lower to various types of
resources, how they map to DXIL constructs, how DXC represents these in SPIR-V,
and finally a set of attributes that's sufficient to generate the code we need
in both DXIL and SPIR-V.

### HLSL Objects

The resource objects in HLSL can be divided in a few different ways, but
generally the interesting attributes are the layout and dimensionality and
whether the objects are writeable.

| HLSL Object | |
|------------------------------------|--------------------------------------------------------------|
| Texture1D | Read-only 1D texture |
| Texture1DArray | Read-only array of 1D textures |
| Texture2D | Read-only 2D texture |
| Texture2DArray | Read-only array of 2D textures |
| Texture2DMS | Read-only 2D texture with multisampling |
| Texture2DMSArray | Read-only array of 2D textures with multisampling |
| Texture3D | Read-only 3D texture |
| TextureCUBE | Read-only cubemapped texture |
| TextureCUBEArray | Read-only array of cubemapped textures |
| RWTexture1D | Read/Write 1D texture |
| RWTexture1DArray | Read/Write array of 1D textures |
| RWTexture2D | Read/Write 2D texture |
| RWTexture2DArray | Read/Write array of 2D textures |
| RWTexture2DMS | Read/Write 2D texture with multisampling |
| RWTexture2DMSArray | Read/Write array of 2D textures with multisampling |
| RWTexture3D | Read/Write 3D texture |
| RasterizerOrderedTexture1D | Read/Write 1D texture with ROV guarantees |
| RasterizerOrderedTexture1DArray | Read/Write array of 1D textures with ROV guarantees |
| RasterizerOrderedTexture2D | Read/Write 2D texture with ROV guarantees |
| RasterizerOrderedTexture2DArray | Read/Write array of 2D textures with ROV guarantees |
| RasterizerOrderedTexture3D | Read/Write 3D texture with ROV guarantees |
| FeedbackTexture2D | Texture feedback map |
| FeedbackTexture2DArray | Array of texture feedback maps |
| Buffer | Read-only buffer of scalar or vector types |
| RWBuffer | Read/write buffer of scalar or vector types |
| RasterizerOrderedBuffer | Read/write buffer with ROV guarantees |
| ByteAddressBuffer | Read-only byte-addressable buffer |
| RWByteAddressBuffer | Read-write byte-addressable buffer |
| RasterizerOrderedByteAddressBuffer | Read-write byte-addressable buffer with ROV guarantees |
| StructuredBuffer | Read-only buffer of UDTs |
| RWStructuredBuffer | Read-write buffer of UDTs |
| RasterizerOrderedStructuredBuffer | Read-write buffer of UDTs with ROV guarantees |
| AppendStructuredBuffer | Streaming output buffer |
| ConsumeStructuredBuffer | Streaming Input buffer |
| cbuffer | Struct declaration syntax for legacy format constant buffers |
| ConstantBuffer | Template syntax for legacy format constant buffers |
| tbuffer | Struct declaration syntax for legacy format texture buffers |
| TextureBuffer | Template syntax for legacy format texture buffers |
| SamplerState | Sampler state |
| SamplerComparisonState | Sampler comparison state |

A few notes:
- Textures and Buffer/RWBuffer have requirements that their elements fit in a
scalar or four 4-byte elements, for both historical reasons and because
they're generally mapped to image formats.
- The layouts cbuffer and tbuffer are tied to DXBC's historical 16-byte row
layout rules.
- ByteAddress and Structured buffers aren't constrained by image format or
legacy layout.
- Sampler state is represented by opaque objects that we won't go into too much
detail about here.

### DXIL

DXIL represents resources in two different and subtly incompatible ways. All
versions of DXIL have [metadata resource records], and since shader model 6.6
we also have the [resource properties] that are bit-packed into the
"annotateHandle" DXIL operation. There appears to be have been intent at some
point to replace the metadata with the annotation model, but my understanding
is that we need to continue to generate both in clang's DXIL implementation to
match DXC.

[Metadata resource records]:
https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/DXIL.rst#metadata-resource-records
[resource properties]:
https://github.com/microsoft/DirectXShaderCompiler/blob/v1.8.2407/include/dxc/DXIL/DxilResourceProperties.h#L23

#### DXIL Metadata

The DXIL metadata records a resource class, a "shape", and a few resource class
dependent properties:

- The Resource class is SRV (Shader resource view), UAV (Unordered Access
View), CBV (Constant buffer view), or Sampler. The only difference between
SRV and UAV is whether the object is writeable.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The only difference between SRV and UAV is whether the object is writeable.

The resource class also has implications on the register type that the resource can be bound to. I think I'd expect to see some reference to that (maybe just a link to the other documentation we have about it).

I almost wonder if it would be fair to say that the only reason we track this resource class is to know which register types it belongs to. It's notably absent from any discussion about the SPIR-V implementation, where SPIR-V doesn't distinguish between different types of register.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@bogner - thoughts on this?

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 reworded this to mention resource class but not really go into detail, WDYT?

- The Resource class is SRV (Shader resource view), UAV (Unordered Access
  View), CBV (Constant buffer view), or Sampler. This is largely only used for
  determining which register class a resource belongs to, and is mostly
  valuable in differentiating between (writeable) UAVs and (read-only) SRVs.

- The "shape" is more commonly referred to as "resource kind" outside of the
DXIL docs. This covers all of the texture and buffer types, as well as
"tbuffer" which maps to the cbuffer layout when the resource class is SRV.
- The resource class dependent properties attempt to cover the variety of
possibilities per class but have a few issues. See the footnotes below.

| | RC | "Shape" | MS Count | Element Type | Struct Stride | ROV | CBuf Size | Feedback |
|------------------------------------|------|------------------------|------------|--------------|---------------|-------|-----------|----------|
| Texture1D | SRV | Texture1D | 0 | enum | - | - | - | - |
| Texture1DArray | SRV | Texture1DArray | 0 | enum | - | - | - | - |
| Texture2D | SRV | Texture2D | 0 | enum | - | - | - | - |
| Texture2DArray | SRV | Texture2DArray | 0 | enum | - | - | - | - |
| Texture2DMS | SRV | Texture2DMS | number[^1] | enum | - | - | - | - |
| Texture2DMSArray | SRV | Texture2DMSArray | number[^1] | enum | - | - | - | - |
| Texture3D | SRV | Texture3D | 0 | enum | - | - | - | - |
| TextureCUBE | SRV | TextureCUBE | 0 | enum | - | - | - | - |
| TextureCUBEArray | SRV | TextureCUBEArray | 0 | enum | - | - | - | - |
| RWTexture1D | UAV | Texture1D | - | enum | - | false | - | - |
| RWTexture1DArray | UAV | Texture1DArray | - | enum | - | false | - | - |
| RWTexture2D | UAV | Texture2D | - | enum | - | false | - | - |
| RWTexture2DArray | UAV | Texture2DArray | - | enum | - | false | - | - |
| RWTexture2DMS | UAV | Texture2DMS | -[^2] | enum | - | false | - | - |
| RWTexture2DMSArray | UAV | Texture2DMSArray | -[^2] | enum | - | false | - | - |
| RWTexture3D | UAV | Texture3D | - | enum | - | false | - | - |
| RasterizerOrderedTexture1D | UAV | Texture1D | - | enum | - | true | - | - |
| RasterizerOrderedTexture1DArray | UAV | Texture1DArray | - | enum | - | true | - | - |
| RasterizerOrderedTexture2D | UAV | Texture2D | - | enum | - | true | - | - |
| RasterizerOrderedTexture2DArray | UAV | Texture2DArray | - | enum | - | true | - | - |
| RasterizerOrderedTexture3D | UAV | Texture3D | - | enum | - | true | - | - |
| FeedbackTexture2D | UAV | FeedbackTexture2D | - | - | - | false | - | enum |
| FeedbackTexture2DArray | UAV | FeedbackTexture2DArray | - | - | - | false | - | enum |
| Buffer | SRV | TypedBuffer | 0 | enum | - | - | - | - |
| RWBuffer | UAV | TypedBuffer | - | enum | - | false | - | - |
| RasterizerOrderedBuffer | UAV | TypedBuffer | - | enum | - | true | - | - |
| ByteAddressBuffer | SRV | RawBuffer | 0 | - | - | - | - | - |
| RWByteAddressBuffer | UAV | RawBuffer | - | - | - | false | - | - |
| RasterizerOrderedByteAddressBuffer | UAV | RawBuffer | - | - | - | true | - | - |
| StructuredBuffer | SRV | StructuredBuffer | 0 | - | number | - | - | - |
| RWStructuredBuffer | UAV | StructuredBuffer | - | - | number | false | - | - |
| RasterizerOrderedStructuredBuffer | UAV | StructuredBuffer | - | - | number | true | - | - |
| AppendStructuredBuffer | UAV | StructuredBuffer | - | - | number | false | - | - |
| ConsumeStructuredBuffer | UAV | StructuredBuffer | - | - | number | false | - | - |
| cbuffer | CBuf | - | - | - | - | - | number | - |
| ConstantBuffer | CBuf | - | - | - | - | - | number | - |
| tbuffer | SRV | TBuffer | 0 | u32[^3] | - | - | - | - |
| TextureBuffer | SRV | TBuffer | 0 | u32[^3] | - | - | - | - |

[^1]: All SRVs have a sample count, but it's zero when not multisampled.
[^2]: The metadata does not represent sample count for RW multisample textures.
[^3]: For tbuffer, element type seems to always be the enum value 5, for `u32`

#### DXIL Binding Annotation

DXIL binding annotations bit-pack information into two integers, as represented
by the unions in the [DxilResourceProperties] class. This format isn't really
documented, and is probably most easily understood by looking at the
[loadPropsFromResourceBase] method, which populates the class's members.

[DxilResourceProperties]:
https://github.com/microsoft/DirectXShaderCompiler/blob/v1.8.2407/include/dxc/DXIL/DxilResourceProperties.h#L23
[loadPropsFromResourceBase]:
https://github.com/microsoft/DirectXShaderCompiler/blob/main/lib/DXIL/DxilResourceProperties.cpp#L139

| | RC | Kind | Align | UAV | ROV | Stride | CBuf Size | Feedback | Elt Type | Elt Count | MS Count |
|------------------------------------|------|------------------------|--------|-------|-------|--------|------------|----------|----------|-----------|----------|
| Texture1D | SRV | Texture1D | 0 | false | false | - | - | - | enum | number | 0 |
| Texture1DArray | SRV | Texture1DArray | 0 | false | false | - | - | - | enum | number | 0 |
| Texture2D | SRV | Texture2D | 0 | false | false | - | - | - | enum | number | 0 |
| Texture2DArray | SRV | Texture2DArray | 0 | false | false | - | - | - | enum | number | 0 |
| Texture2DMS | SRV | Texture2DMS | 0 | false | false | - | - | - | enum | number | number |
| Texture2DMSArray | SRV | Texture2DMSArray | 0 | false | false | - | - | - | enum | number | number |
| Texture3D | SRV | Texture3D | 0 | false | false | - | - | - | enum | number | 0 |
| TextureCUBE | SRV | TextureCUBE | 0 | false | false | - | - | - | enum | number | 0 |
| TextureCUBEArray | SRV | TextureCUBEArray | 0 | false | false | - | - | - | enum | number | 0 |
| RWTexture1D | UAV | Texture1D | 0 | true | false | - | - | - | enum | number | 0 |
| RWTexture1DArray | UAV | Texture1DArray | 0 | true | false | - | - | - | enum | number | 0 |
| RWTexture2D | UAV | Texture2D | 0 | true | false | - | - | - | enum | number | 0 |
| RWTexture2DArray | UAV | Texture2DArray | 0 | true | false | - | - | - | enum | number | 0 |
| RWTexture2DMS | UAV | Texture2DMS | 0 | true | false | - | - | - | enum | number | number |
| RWTexture2DMSArray | UAV | Texture2DMSArray | 0 | true | false | - | - | - | enum | number | number |
| RWTexture3D | UAV | Texture3D | 0 | true | false | - | - | - | enum | number | 0 |
| RasterizerOrderedTexture1D | UAV | Texture1D | 0 | true | true | - | - | - | enum | number | 0 |
| RasterizerOrderedTexture1DArray | UAV | Texture1DArray | 0 | true | true | - | - | - | enum | number | 0 |
| RasterizerOrderedTexture2D | UAV | Texture2D | 0 | true | true | - | - | - | enum | number | 0 |
| RasterizerOrderedTexture2DArray | UAV | Texture2DArray | 0 | true | true | - | - | - | enum | number | 0 |
| RasterizerOrderedTexture3D | UAV | Texture3D | 0 | true | true | - | - | - | enum | number | 0 |
| FeedbackTexture2D | SRV | FeedbackTexture2D | 0 | false | false | - | - | enum | - | - | - |
| FeedbackTexture2DArray | SRV | FeedbackTexture2DArray | 0 | false | false | - | - | enum | - | - | - |
| Buffer | SRV | TypedBuffer | 0 | false | false | - | - | - | enum | number | 0 |
| RWBuffer | UAV | TypedBuffer | 0 | true | false | - | - | - | enum | number | 0 |
| RasterizerOrderedBuffer | UAV | Buffer | 0 | true | true | - | - | - | enum | number | 0 |
| ByteAddressBuffer | SRV | RawBuffer | 0 | false | false | - | - | - | - | - | - |
| RWByteAddressBuffer | UAV | RawBuffer | 0 | true | false | - | - | - | - | - | - |
| RasterizerOrderedByteAddressBuffer | UAV | RawBuffer | 0 | true | true | - | - | - | - | - | - |
| StructuredBuffer | SRV | StructuredBuffer | number | false | false | number | - | - | - | - | - |
| RWStructuredBuffer | UAV | StructuredBuffer | number | true | false | number | - | - | - | - | - |
| RasterizerOrderedStructuredBuffer | UAV | StructuredBuffer | number | true | true | number | - | - | - | - | - |
| AppendStructuredBuffer | UAV | StructuredBuffer | number | true | false | number | - | - | - | - | - |
| ConsumeStructuredBuffer | UAV | StructuredBuffer | number | true | false | number | - | - | - | - | - |
| cbuffer | CBuf | CBuffer | 0 | false | false | - | number | - | - | - | - |
| ConstantBuffer | CBuf | CBuffer | 0 | false | false | - | number | - | - | - | - |
| tbuffer | SRV | TBuffer | 0 | false | false | - | number[^4] | - | - | - | - |
| TextureBuffer | SRV | TBuffer | 0 | false | false | - | number[^4] | - | - | - | - |

[^4]: LLVM is probably buggy here currently. It differs from DXC and sets
element type/count instead of cbuf size.

#### Target Extension Types

In LLVM IR we'll represent all of the DXIL resource types via [target extension
types], as described in [proposal 0006] and the [DXILResources docs]. As of
this writing these docs don't yet cover the texture types, but they'll follow
from the constraints described here.

[target extension types]:
https://llvm.org/docs/LangRef.html#target-extension-type
[proposal 0006]:
https://github.com/llvm/wg-hlsl/blob/main/proposals/0006-resource-representations.md
[DXILResources docs]:
https://llvm.org/docs/DirectX/DXILResources.html

### SPIR-V

DXC's SPIR-V backend treats "Buffer" as a texture and maps [DXC textures]
directly to [OpTypeImage]. In LLVM IR there is a 1-1 correspondence between the
set of SPIR-V target extension types and the resulting OpTypeImage for the
simple cases:

[DXC textures]:
https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#textures
[OpTypeImage]:
https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage


| | Dim | Depth | Arrayed | MS | Sampled | Access |
|---------------------------------|--------|-------------|---------|-------|---------|--------|
| Texture1D | 1D | Unknown (2) | false | false | r/o (1) | r/o |
| Texture1DArray | 1D | Unknown (2) | true | false | r/o (1) | r/o |
| Texture2D | 2D | Unknown (2) | false | false | r/o (1) | r/o |
| Texture2DArray | 2D | Unknown (2) | true | false | r/o (1) | r/o |
| Texture2DMS | 2D | Unknown (2) | false | true | r/o (1) | r/o |
| Texture2DMSArray | 2D | Unknown (2) | true | true | r/o (1) | r/o |
| Texture3D | 3D | Unknown (2) | false | false | r/o (1) | r/o |
| TextureCUBE | Cube | Unknown (2) | false | false | r/o (1) | r/o |
| TextureCUBEArray | Cube | Unknown (2) | true | false | r/o (1) | r/o |
| RWTexture1D | 1D | Unknown (2) | false | false | r/w (2) | r/w |
| RWTexture1DArray | 1D | Unknown (2) | true | false | r/w (2) | r/w |
| RWTexture2D | 2D | Unknown (2) | false | false | r/w (2) | r/w |
| RWTexture2DArray | 2D | Unknown (2) | true | false | r/w (2) | r/w |
| RWTexture2DMS | 2D | Unknown (2) | false | true | r/w (2) | r/w |
| RWTexture2DMSArray | 2D | Unknown (2) | true | true | r/w (2) | r/w |
| RWTexture3D | 3D | Unknown (2) | false | false | r/w (2) | r/w |
| Buffer | Buffer | Unknown (2) | false | false | r/o (1) | r/o |
| RWBuffer | Buffer | Unknown (2) | false | false | r/w (2) | r/w |
Copy link
Collaborator

Choose a reason for hiding this comment

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

The Access Qualifier is for Kernel (think OpenCL) only. The value after "Sampled" is the Image Format.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated the table to add an Image format column but largely leave it blank. See my replies to your other comments


DXC lowers [Constant/Texture/Structured/Byte Buffers] to [OpTypeStruct] in
SPIR-V with a uniform storage class and various layout decorations. DXC tracks
Copy link
Collaborator

Choose a reason for hiding this comment

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

The storage class should depend on the version of Vulkan that is targeted. Starting with Vulkan 1.2 the storage class is StorageBuffer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated to be somewhat handwavey about this but mention the version dependency

the necessary information to lower these in side structures, and we'll likely
need to keep track of that information in new SPIR-V target extension types in
our implementation.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree we will need a new target type.

I've been thinking about this a bit. SPIR-V does not have a "handle" for structured buffers. There is a global variable, which is accessed using the same instructions used to access function scope variables.

In Vulkan SPIR-V, a structured buffer StructuredBuffer<T> is represented as struct { T[] }. We could make the handle a pointer to the struct or a pointer to the array. In any case, you want it to be a pointer type.

One option is to have CreateHandleFromBinding return a pointer. Then use use standard llvm-ir instruction to access it. The problem with that is that we will have to expose the layout of T, and the type information may be hard to recover. That is why I agree we need a target type.

We should be able to define a target type to represent a spir-v pointer.


[Constant/Texture/Structured/Byte Buffers]:
https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#constant-texture-structured-byte-buffers
[OpTypeStruct]:
https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeStruct

| | Vulkan Buffer Type | SPIR-V Decoration |
|-------------------------|--------------------|-------------------|
| ByteAddressBuffer | Storage | BufferBlock |
| RWByteAddressBuffer | Storage | BufferBlock |
| StructuredBuffer | Storage | BufferBlock |
| RWStructuredBuffer | Storage | BufferBlock |
| AppendStructuredBuffer | Storage | BufferBlock |
| ConsumeStructuredBuffer | Storage | BufferBlock |
| cbuffer | Uniform | Block |
| ConstantBuffer | Uniform | Block |
| tbuffer | Storage | BufferBlock |
| TextureBuffer | Storage | BufferBlock |

The "RasterizerOrdered" (or ROV) resources in HLSL don't map directly to
SPIR-V. In DXC, we emulate ROV by treating these the same as their non-ROV
counterparts but wrapping accesses to the resource in critical sections using
[SPV_EXT_fragment_shader_interlock]. We will probably need to extend the SPIR-V
target extension types to represent these unless we want to emit the critical
sections awkwardly early in the compiler.

[SPV_EXT_fragment_shader_interlock]:
https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_fragment_shader_interlock.asciidoc

| |
|------------------------------------|
| RasterizerOrderedTexture1D |
| RasterizerOrderedTexture1DArray |
| RasterizerOrderedTexture2D |
| RasterizerOrderedTexture2DArray |
| RasterizerOrderedTexture3D |
| RasterizerOrderedBuffer |
| RasterizerOrderedByteAddressBuffer |
| RasterizerOrderedStructuredBuffer |

Feedback textures aren't implemented in DXC.

| |
|------------------------------------|
| FeedbackTexture2D |
| FeedbackTexture2DArray |

### Attributes

From all of this, we're able to come up with a set of attributes that can
represent all of the texture and buffer types. These should carry sufficient
information to lower to both of the targets:

| | RC | Type | ROV | Dim | MS | Feedback | Array | Raw | Row |
|------------------------------------|------|--------|-----|------|-----|----------|-------|-----|-----|
| Texture1D | SRV | vec4 | - | 1D | - | - | - | - | - |
| Texture1DArray | SRV | vec4 | - | 1D | - | - | yes | - | - |
| Texture2D | SRV | vec4 | - | 2D | - | - | - | - | - |
| Texture2DArray | SRV | vec4 | - | 2D | - | - | yes | - | - |
| Texture2DMS | SRV | vec4 | - | 2D | yes | - | - | - | - |
| Texture2DMSArray | SRV | vec4 | - | 2D | yes | - | yes | - | - |
| Texture3D | SRV | vec4 | - | 3D | - | - | - | - | - |
| TextureCUBE | SRV | vec4 | - | Cube | - | - | - | - | - |
| TextureCUBEArray | SRV | vec4 | - | Cube | - | - | yes | - | - |
| RWTexture1D | UAV | vec4 | - | 1D | - | - | - | - | - |
| RWTexture1DArray | UAV | vec4 | - | 1D | - | - | yes | - | - |
| RWTexture2D | UAV | vec4 | - | 2D | - | - | - | - | - |
| RWTexture2DArray | UAV | vec4 | - | 2D | - | - | yes | - | - |
| RWTexture2DMS | UAV | vec4 | - | 2D | yes | - | - | - | - |
| RWTexture2DMSArray | UAV | vec4 | - | 2D | yes | - | yes | - | - |
| RWTexture3D | UAV | vec4 | - | 3D | - | - | - | - | - |
Copy link
Collaborator

Choose a reason for hiding this comment

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

These look good. The individual attributes map nicely to individual operands to spirv.Image.

| RasterizerOrderedTexture1D | UAV | vec4 | yes | 1D | - | - | - | - | - |
| RasterizerOrderedTexture1DArray | UAV | vec4 | yes | 1D | - | - | yes | - | - |
| RasterizerOrderedTexture2D | UAV | vec4 | yes | 2D | - | - | - | - | - |
| RasterizerOrderedTexture2DArray | UAV | vec4 | yes | 2D | - | - | yes | - | - |
| RasterizerOrderedTexture3D | UAV | vec4 | yes | 3D | - | - | - | - | - |
| FeedbackTexture2D | SRV | - | - | - | - | fbtype | - | - | - |
| FeedbackTexture2DArray | SRV | - | - | - | - | fbtype | yes | - | - |
| Buffer | SRV | vec4 | - | - | - | - | - | - | - |
| RWBuffer | UAV | vec4 | - | - | - | - | - | - | - |
| RasterizerOrderedBuffer | UAV | vec4 | yes | - | - | - | - | - | - |
| ByteAddressBuffer | SRV | - | - | - | - | - | - | yes | - |
| RWByteAddressBuffer | UAV | - | - | - | - | - | - | yes | - |
Copy link
Collaborator

Choose a reason for hiding this comment

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

ByteAddressBuffers are hard in SPIR-V. Without untyped pointers, we cannot cast from one pointer type to another. This make it very hard to do some thing, and impossible to do others. For, example, it is impossible to have both 32-bit atomic operations and 64-bit atomic operations.

For now, we cannot have a common implementation for all of the raw buffer resources.

| RasterizerOrderedByteAddressBuffer | UAV | - | yes | - | - | - | - | yes | - |
| StructuredBuffer | SRV | struct | - | - | - | - | - | yes | - |
| RWStructuredBuffer | UAV | struct | - | - | - | - | - | yes | - |
| RasterizerOrderedStructuredBuffer | UAV | struct | yes | - | - | - | - | yes | - |
| AppendStructuredBuffer | UAV | struct | - | - | - | - | - | yes | - |
| ConsumeStructuredBuffer | UAV | struct | - | - | - | - | - | yes | - |
Copy link
Collaborator

Choose a reason for hiding this comment

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

To generate or use these types, the SPIR-V backend will have to know the layout of any structs. In DXC, we have a few different layout options. I feel like it should be the FE's job to specify the layout. Let me know what you think.

| cbuffer | CBuf | struct | - | - | - | - | - | - | yes |
| ConstantBuffer | CBuf | struct | - | - | - | - | - | - | yes |
| tbuffer | SRV | struct | - | - | - | - | - | - | yes |
| TextureBuffer | SRV | struct | - | - | - | - | - | - | yes |

## Alternatives considered

We could also forgo the large set of specific attributes and boil things down
to mostly resource class and resource kind. This is in some ways simpler, but
has two main downsides:

1. Not quite everything is represented, so we still need attributes for various
numeric values, and some parameters like feedback type.
2. The resource kind ties us fairly tightly to design decisions in DXIL, so may
come across as anachronistic as we move to SPIR-V.

For these reasons, I think the broader set of specific attributes is a better
approach.

<!-- {% endraw %} -->