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

[DirectX] Introduce llvm.dx.bufferGetDimensions and lower it to getDimensions dxil ops #112982

Open
Tracked by #88
hekota opened this issue Oct 18, 2024 · 3 comments
Open
Tracked by #88
Assignees

Comments

@hekota
Copy link
Member

hekota commented Oct 18, 2024

We need LLVM intrinsic for bufferGetDimensions which will be lowered to the op.dx.getDimensions dxil operations. These will be used on structured buffers.

https://godbolt.org/z/bz7zxsf5n

@damyanp
Copy link
Contributor

damyanp commented Oct 29, 2024

@hekota - can you compare this to #101579 please and figure out which one we should go forward with?

@farzonl
Copy link
Member

farzonl commented Nov 14, 2024

  • In clang/include/clang/Basic/Builtins.td Add
def HLSLBufferGetDimensions : LangBuiltin<"HLSL_LANG"> {
  let Spellings = ["__builtin_hlsl_buffer_get_dimensions"];
  let Attributes = [NoThrow, CustomTypeChecking];
  let Prototype = "void(...)";
}
  • Prototype is a struct return but no way to represent that in Builtins.td
  • Other Struct return builtins have CustomTypeChecking
  • The form of the intrinsic is:
struct Astruct {float a;};
RWStructuredBuffer<Astruct > Buf : register(u0);
uint count, stride;
Buf.GetDimensions(count, stride);

It should generate DXIL that looks like so.

%8 = call %dx.types.Dimensions @dx.op.getDimensions(i32 72, %dx.types.Handle %7, i32 undef)
%9 = extractvalue %dx.types.Dimensions %8
  • In HLSLExternalSemaSource.cpp create a addGetDimensionsMethods function that defines a GetDimensions TokenKind::identifier.
  • In HLSLExternalSemaSource.cpp call addGetDimensionsMethods for 23 types:
    • Texture1D
    • Texture1DArray
    • Texture2D
    • Texture2DMS
    • Texture2DArray
    • Texture2DArrayMS
    • Texture3D
    • TextureCUBE
    • TextureCUBEArray
    • Buffer
    • RWTexture1D
    • RWTexture1DArray
    • RWTexture2D
    • RWTexture2DArray
    • RWTexture2DMS
    • RWTexture2DMSArray
    • RWTexture3D
    • RWBuffer
    • ByteAddressBuffer
    • RWByteAddressBuffer
    • StructuredBuffer
    • RWStructuredBuffer
    • AppendStructuredBuffer,
    • ConsumeStructuredBuffer
  • In llvm/include/llvm/IR/IntrinsicsDirectX.td and llvm/include/llvm/IR/IntrinsicsSPIRV.td define an intrinsic whose first parameter is the buffer handle and whose return type is an anonymous struct. The struct return type is used to represent out parameters for the above count and stride. An Example of this was done in the splitDouble pr.
  • Add the intrinsic toggle preprocessor macro to clang/lib/CodeGen/CGHLSLRuntime.h.
  • Add the builtin to intrinsic mapping in clang/lib/CodeGen/CGBuiltin.cpp. should be a standard Builder.CreateIntrinsic calling
    CGM.getHLSLRuntime().getBufferGetDimensionsIntrinsic(), where the first argument is the buffer handle Value *ResHandle = EmitScalarExpr(E->getArg(0));
  • TODO investigate SEMA requirements
  • TODO we likely need backend changes to convert from named structs to anonymous structs gracefully in DXIL.
  • In DXIL.td add a def DimensionsTy : : DXILOpParamType; to map out params.
  • In DXILOpBuilder.h define a getter for %dx.types.Dimensions.
  • In DXILOpBuilder.cpp implemented the getter getDimensionsType which returns a StructType.
  • The struct must be made up of 4 integers not all integers will be set depending on handle. see docs

@farzonl farzonl moved this from Designing to Planning in HLSL Support Nov 19, 2024
@pow2clk pow2clk moved this from Planning to Designing in HLSL Support Nov 19, 2024
@farzonl
Copy link
Member

farzonl commented Nov 22, 2024

There are 54 cases of GetDimensions we need to support. Below is how they are used per Handle type.

Texture1D

  • void [[]] GetDimensions(in uint x, out uint_only width, out $type2 levels) : resinfo_uint;
  • void [[]] GetDimensions(in uint x, out float_like width, out $type2 levels) : resinfo;
  • void [[]] GetDimensions(out uint_only width) : resinfo_o;
  • void [[]] GetDimensions(out float_like width) : resinfo_o;

Texture1DArray

  • void [[]] GetDimensions(in uint x, out uint_only width, out $type2 elements, out $type2 levels) : resinfo_uint;
  • void [[]] GetDimensions(in uint x, out float_like width, out $type2 elements, out $type2 levels) : resinfo;
  • void [[]] GetDimensions(out uint_only width, out $type1 elements) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 elements) : resinfo_o;

Texture2D

  • void [[]] GetDimensions(in uint x, out uint_only width, out $type2 height, out $type2 levels) : resinfo_uint;
  • void [[]] GetDimensions(in uint x, out float_like width, out $type2 height, out $type2 levels) : resinfo;
  • void [[]] GetDimensions(out uint_only width, out $type1 height) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height) : resinfo_o;

Texture2DMS

  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type2 samples) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type2 samples) : resinfo_o;

Texture2DArray

  • void [[]] GetDimensions(in uint x, out uint_only width, out $type2 height, out $type2 elements, out $type2 levels) : resinfo_uint;
  • void [[]] GetDimensions(in uint x, out float_like width, out $type2 height, out $type2 elements, out $type2 levels) : resinfo;
  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type1 elements) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type1 elements) : resinfo_o;

Texture2DArrayMS

  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type1 elements, out $type1 samples) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type1 elements, out $type1 samples) : resinfo_o;

Texture3D

  • void [[]] GetDimensions(in uint x, out uint_only width, out $type2 height, out $type2 depth, out $type2 levels) : resinfo_uint;
  • void [[]] GetDimensions(in uint x, out float_like width, out $type2 height, out $type2 depth, out $type2 levels) : resinfo;
  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type1 depth) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type1 depth) : resinfo_o;

TextureCUBE

  • void [[]] GetDimensions(in uint x, out uint_only width, out $type2 height, out $type2 levels) : resinfo_uint;
  • void [[]] GetDimensions(in uint x, out float_like width, out $type2 height, out $type2 levels) : resinfo;
  • void [[]] GetDimensions(out uint_only width, out $type1 height) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height) : resinfo_o;

TextureCUBEArray

  • void [[]] GetDimensions(in uint x, out uint_only width, out $type2 height, out $type2 elements, out $type2 levels) : resinfo_uint;
  • void [[]] GetDimensions(in uint x, out float_like width, out $type2 height, out $type2 elements, out $type2 levels) : resinfo;
  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type1 elements) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type1 elements) : resinfo_o;

Buffer

  • void [[]] GetDimensions(out uint_only width) : bufinfo;

RWTexture1D

  • void [[]] GetDimensions(out uint_only width) : resinfo_o;
  • void [[]] GetDimensions(out float_like width) : resinfo_o;

RWTexture1DArray

  • void [[]] GetDimensions(out uint_only width, out $type1 elements) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 elements) : resinfo_o;

RWTexture2D

  • void [[]] GetDimensions(out uint_only width, out $type1 height) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height) : resinfo_o;

RWTexture2DArray

  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type1 elements) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type1 elements) : resinfo_o;

RWTexture2DMS

  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type2 samples);
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type2 samples);
    RWTexture2DMSArray
    -void [[]] GetDimensions(out uint_only width, out $type1 height, out $type1 elements, out $type1 samples);
    -void [[]] GetDimensions(out float_like width, out $type1 height, out $type1 elements, out $type1 samples);

RWTexture3D

  • void [[]] GetDimensions(out uint_only width, out $type1 height, out $type1 depth) : resinfo_uint_o;
  • void [[]] GetDimensions(out float_like width, out $type1 height, out $type1 depth) : resinfo_o;

RWBuffer

  • void [[]] GetDimensions(out uint_only width) : bufinfo;

ByteAddressBuffer

  • void [[]] GetDimensions(out uint_only width) : bufinfo;

RWByteAddressBuffer

  • void [[]] GetDimensions(out uint_only width) : bufinfo;

StructuredBuffer

  • void [[]] GetDimensions(out uint_only count, out uint_only stride) : bufinfo;

RWStructuredBuffer

  • void [[]] GetDimensions(out uint_only count, out uint_only stride) : bufinfo;

AppendStructuredBuffer

  • void [[]] GetDimensions(out uint_only count, out uint_only stride) : bufinfo;

ConsumeStructuredBuffer

  • void [[]] GetDimensions(out uint_only count, out uint_only stride) : bufinfo;

@damyanp damyanp assigned V-FEXrt and bogner and unassigned V-FEXrt Jan 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Designing
Development

No branches or pull requests

6 participants