Skip to content

Commit c2f85a6

Browse files
author
Greg Roth
committed
revise overload resolution for splats/truncations
Allow truncations when matching arguments for intrinsic overloads. This eliminates the need for explicit scalar extractions from vectors for arguments that are scalar by nature. This encompasses any vectors passed for scalars, allowing the truncation, but emitting a warning the same as is done for other assignments of vectors to scalars. This maintains splats as the preferred transformations and promotes perfect matches to be preferred over that. This has the effect of removing the need to carefully order intrinsics to ensure that the right variant gets matched first before another one incorrectly takes its place with a faulty cast. Allowing truncations causes a problems with a small subset of intrinsics that have explicit overloads for various matrix,vector, scalar combinations. Namely the mul overloads. These could be simplified to accept a new range of template types except the dimensions need to be matched in unconventional ways. For these, the notion of uncastable or "ONLY" variants of the template/layout types are introduced. These are indicated with a trailing "!" after the parameter typename in gen_intrin_main, which directs them to an array that contains a NOCAST enum that, when encountered, will skip the attempts to splat or truncate. Fixes microsoft#7079
1 parent ac1c623 commit c2f85a6

File tree

8 files changed

+93
-103
lines changed

8 files changed

+93
-103
lines changed

include/dxc/dxcapi.internal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ enum LEGAL_INTRINSIC_TEMPLATES {
4646
4, // Any one of scalar, vector or matrix types (but not object).
4747
LITEMPLATE_OBJECT = 5, // Object types.
4848
LITEMPLATE_ARRAY = 6, // Scalar array.
49+
LITEMPLATE_SCALAR_ONLY = 7, // Uncastable scalar types.
50+
LITEMPLATE_VECTOR_ONLY = 8, // Uncastable vector types (eg. float3).
51+
LITEMPLATE_MATRIX_ONLY = 9, // Uncastable matrix types (eg. float3x3).
4952

50-
LITEMPLATE_COUNT = 7
53+
LITEMPLATE_COUNT = 10
5154
};
5255

5356
// INTRIN_COMPTYPE_FROM_TYPE_ELT0 is for object method intrinsics to indicate

lib/HLSL/HLOperationLower.cpp

Lines changed: 7 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4315,12 +4315,10 @@ void TranslateLoad(ResLoadHelper &helper, HLResource::Kind RK,
43154315
loadArgs.emplace_back(opArg); // opcode
43164316
loadArgs.emplace_back(helper.handle); // resource handle
43174317

4318+
// offsets
43184319
if (opcode == OP::OpCode::TextureLoad) {
43194320
// set mip level
43204321
loadArgs.emplace_back(helper.mipLevel);
4321-
}
4322-
4323-
if (opcode == OP::OpCode::TextureLoad) {
43244322
// texture coord
43254323
unsigned coordSize = DxilResource::GetNumCoords(RK);
43264324
bool isVectorAddr = helper.addr->getType()->isVectorTy();
@@ -4332,22 +4330,6 @@ void TranslateLoad(ResLoadHelper &helper, HLResource::Kind RK,
43324330
} else
43334331
loadArgs.emplace_back(undefI);
43344332
}
4335-
} else {
4336-
if (helper.addr->getType()->isVectorTy()) {
4337-
Value *scalarOffset =
4338-
Builder.CreateExtractElement(helper.addr, (uint64_t)0);
4339-
4340-
// TODO: calculate the real address based on opcode
4341-
4342-
loadArgs.emplace_back(scalarOffset); // offset
4343-
} else {
4344-
// TODO: calculate the real address based on opcode
4345-
4346-
loadArgs.emplace_back(helper.addr); // offset
4347-
}
4348-
}
4349-
// offset 0
4350-
if (opcode == OP::OpCode::TextureLoad) {
43514333
if (helper.offset && !isa<llvm::UndefValue>(helper.offset)) {
43524334
unsigned offsetSize = DxilResource::GetNumOffsets(RK);
43534335
for (unsigned i = 0; i < 3; i++) {
@@ -4361,11 +4343,9 @@ void TranslateLoad(ResLoadHelper &helper, HLResource::Kind RK,
43614343
loadArgs.emplace_back(undefI);
43624344
loadArgs.emplace_back(undefI);
43634345
}
4364-
}
4365-
4366-
// Offset 1
4367-
if (RK == DxilResource::Kind::TypedBuffer) {
4368-
loadArgs.emplace_back(undefI);
4346+
} else {
4347+
loadArgs.emplace_back(helper.addr); // c0
4348+
loadArgs.emplace_back(undefI); // c1
43694349
}
43704350

43714351
Value *ResRet = Builder.CreateCall(F, loadArgs, OP->GetOpCodeName(opcode));
@@ -4539,12 +4519,7 @@ void TranslateStore(DxilResource::Kind RK, Value *handle, Value *val,
45394519
if (RK == DxilResource::Kind::RawBuffer ||
45404520
RK == DxilResource::Kind::TypedBuffer) {
45414521
// Offset 0
4542-
if (offset->getType()->isVectorTy()) {
4543-
Value *scalarOffset = Builder.CreateExtractElement(offset, (uint64_t)0);
4544-
storeArgs.emplace_back(scalarOffset); // offset
4545-
} else {
4546-
storeArgs.emplace_back(offset); // offset
4547-
}
4522+
storeArgs.emplace_back(offset); // offset
45484523

45494524
// Store offset0 for later use
45504525
offset0Idx = storeArgs.size() - 1;
@@ -6278,7 +6253,7 @@ Value *StreamOutputLower(CallInst *CI, IntrinsicOp IOP, DXIL::OpCode opcode,
62786253
HLOperationLowerHelper &helper,
62796254
HLObjectOperationLowerHelper *pObjHelper,
62806255
bool &Translated) {
6281-
// Translated in DxilGenerationPass::GenerateStreamOutputOperation.
6256+
// Translated in HLSignatureLower::GenerateStreamOutputOperation.
62826257
// Do nothing here.
62836258
// Mark not translated.
62846259
Translated = false;
@@ -7983,7 +7958,7 @@ static Value *ExtractFromTypedBufferLoad(const ResRetValueArray &ResRet,
79837958
DXASSERT_NOMSG(FirstElemIdx <= ResRet.size() - ElemCount);
79847959
for (unsigned ElemIdx = 0; ElemIdx < ElemCount; ++ElemIdx) {
79857960
Elems.emplace_back(
7986-
ResRet[std::min<size_t>(FirstElemIdx + ElemIdx, ResRet.size() - 1)]);
7961+
ResRet[std::min<size_t>(FirstElemIdx + ElemIdx, ResRet.size() - 1)]);// there is no way this is right. why add the offset here?
79877962
}
79887963
} else {
79897964
Value *ArrayAlloca = SpillValuesToArrayAlloca(
@@ -8368,15 +8343,6 @@ void TranslateStructBufSubscriptUser(Instruction *user, Value *handle,
83688343
if (group == HLOpcodeGroup::HLIntrinsic) {
83698344
IntrinsicOp IOP = static_cast<IntrinsicOp>(opcode);
83708345
switch (IOP) {
8371-
case IntrinsicOp::MOP_Load: {
8372-
if (userCall->getType()->isPointerTy()) {
8373-
// Struct will return pointers which like []
8374-
8375-
} else {
8376-
// Use builtin types on structuredBuffer.
8377-
}
8378-
DXASSERT(0, "not implement yet");
8379-
} break;
83808346
case IntrinsicOp::IOP_InterlockedAdd: {
83818347
AtomicHelper helper(userCall, DXIL::OpCode::AtomicBinOp, handle, bufIdx,
83828348
baseOffset);

lib/HLSL/HLSignatureLower.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,8 +1653,7 @@ void HLSignatureLower::GenerateStreamOutputOperation(Value *streamVal,
16531653
if (group == HLOpcodeGroup::NotHL)
16541654
continue;
16551655
unsigned opcode = GetHLOpcode(CI);
1656-
DXASSERT_LOCALVAR(group, group == HLOpcodeGroup::HLIntrinsic,
1657-
"Must be HLIntrinsic here");
1656+
DXASSERT(group == HLOpcodeGroup::HLIntrinsic, "Must be HLIntrinsic here");
16581657
IntrinsicOp IOP = static_cast<IntrinsicOp>(opcode);
16591658
switch (IOP) {
16601659
case IntrinsicOp::MOP_Append:

tools/clang/lib/Sema/SemaHLSL.cpp

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ enum ArTypeObjectKind {
662662
// indexer object used to implement .mips[1].
663663
AR_TOBJ_STRING, // Represents a string
664664
AR_TOBJ_DEPENDENT, // Dependent type for template.
665+
AR_TOBJ_NOCAST, // Parameter should not have layout casts (splat,trunc)
665666
};
666667

667668
enum TYPE_CONVERSION_FLAGS {
@@ -989,9 +990,15 @@ static const ArTypeObjectKind g_NullTT[] = {AR_TOBJ_VOID, AR_TOBJ_UNKNOWN};
989990

990991
static const ArTypeObjectKind g_ArrayTT[] = {AR_TOBJ_ARRAY, AR_TOBJ_UNKNOWN};
991992

993+
static const ArTypeObjectKind g_ScalarOnlyTT[] = {AR_TOBJ_SCALAR, AR_TOBJ_NOCAST, AR_TOBJ_UNKNOWN};
994+
995+
static const ArTypeObjectKind g_VectorOnlyTT[] = {AR_TOBJ_VECTOR, AR_TOBJ_NOCAST, AR_TOBJ_UNKNOWN};
996+
997+
static const ArTypeObjectKind g_MatrixOnlyTT[] = {AR_TOBJ_MATRIX, AR_TOBJ_NOCAST, AR_TOBJ_UNKNOWN};
998+
992999
const ArTypeObjectKind *g_LegalIntrinsicTemplates[] = {
9931000
g_NullTT, g_ScalarTT, g_VectorTT, g_MatrixTT,
994-
g_AnyTT, g_ObjectTT, g_ArrayTT,
1001+
g_AnyTT, g_ObjectTT, g_ArrayTT, g_ScalarOnlyTT, g_VectorOnlyTT, g_MatrixOnlyTT,
9951002
};
9961003
C_ASSERT(ARRAYSIZE(g_LegalIntrinsicTemplates) == LITEMPLATE_COUNT);
9971004

@@ -6109,7 +6116,7 @@ bool HLSLExternalSource::MatchArguments(
61096116
ArBasicKind
61106117
ComponentType[MaxIntrinsicArgs]; // Component type for each argument,
61116118
// AR_BASIC_UNKNOWN if unspecified.
6112-
UINT uSpecialSize[IA_SPECIAL_SLOTS]; // row/col matching types, UNUSED_INDEX32
6119+
UINT uSpecialSize[IA_SPECIAL_SLOTS]; // row/col matching types, UnusedSize
61136120
// if unspecified.
61146121
badArgIdx = MaxIntrinsicArgs;
61156122

@@ -6245,19 +6252,23 @@ bool HLSLExternalSource::MatchArguments(
62456252
"otherwise intrinsic table was modified and g_MaxIntrinsicParamCount "
62466253
"was not updated (or uTemplateId is out of bounds)");
62476254

6248-
// Compare template
6255+
// Compare template to any type matching params requirements.
62496256
if ((AR_TOBJ_UNKNOWN == Template[pIntrinsicArg->uTemplateId]) ||
62506257
((AR_TOBJ_SCALAR == Template[pIntrinsicArg->uTemplateId]) &&
62516258
(AR_TOBJ_VECTOR == TypeInfoShapeKind ||
62526259
AR_TOBJ_MATRIX == TypeInfoShapeKind))) {
6253-
// Unrestricted or truncation of tuples to scalars are allowed
6260+
// Previous params gave no type restrictions
6261+
// or truncation of tuples to scalars are allowed
6262+
// I'm not sure this ever results in truncations.
6263+
// Later steps harmonize common typed params and will always convert the earlier arg into a splat instead.
62546264
Template[pIntrinsicArg->uTemplateId] = TypeInfoShapeKind;
62556265
} else if (AR_TOBJ_SCALAR == TypeInfoShapeKind) {
62566266
if (AR_TOBJ_SCALAR != Template[pIntrinsicArg->uTemplateId] &&
62576267
AR_TOBJ_VECTOR != Template[pIntrinsicArg->uTemplateId] &&
62586268
AR_TOBJ_MATRIX != Template[pIntrinsicArg->uTemplateId]) {
62596269
// Scalars to tuples can be splatted, scalar to anything else is not
62606270
// allowed
6271+
// Dead code. The only params with requirements are already one of these three.
62616272
badArgIdx = std::min(badArgIdx, iArg);
62626273
}
62636274
} else {
@@ -6288,6 +6299,11 @@ bool HLSLExternalSource::MatchArguments(
62886299
}
62896300
}
62906301

6302+
// If the intrinsic parameter has variable rows or columns but must match
6303+
// other argument dimensions, it will be specified in pIntrinsicArg with
6304+
// a special value indicating that the dimension depends on the passed values.
6305+
// uSpecialSize stores the dimensions of the actual passed type.
6306+
62916307
// Rows
62926308
if (AR_TOBJ_SCALAR != TypeInfoShapeKind) {
62936309
if (pIntrinsicArg->uRows >= IA_SPECIAL_BASE) {
@@ -6394,18 +6410,37 @@ bool HLSLExternalSource::MatchArguments(
63946410
const ArTypeObjectKind *pTT =
63956411
g_LegalIntrinsicTemplates[pArgument->uLegalTemplates];
63966412
if (AR_TOBJ_UNKNOWN != Template[i]) {
6397-
if ((AR_TOBJ_SCALAR == Template[i]) &&
6398-
(AR_TOBJ_VECTOR == *pTT || AR_TOBJ_MATRIX == *pTT)) {
6399-
Template[i] = *pTT;
6400-
} else {
6413+
// See if a perfect match overload is available
6414+
while (AR_TOBJ_UNKNOWN != *pTT && AR_TOBJ_NOCAST != *pTT) {
6415+
if (Template[i] == *pTT)
6416+
break;
6417+
pTT++;
6418+
}
6419+
6420+
if (AR_TOBJ_UNKNOWN == *pTT) {
6421+
// Perfect match failed and casts are allowed.
6422+
// Try splats and truncations to get a match.
6423+
pTT = g_LegalIntrinsicTemplates[pArgument->uLegalTemplates];
64016424
while (AR_TOBJ_UNKNOWN != *pTT) {
6402-
if (Template[i] == *pTT)
6425+
if (AR_TOBJ_SCALAR == Template[i] &&
6426+
(AR_TOBJ_VECTOR == *pTT || AR_TOBJ_MATRIX == *pTT)) {
6427+
// If a scalar was passed in and the expected value was matrix/vector
6428+
// convert to the template type for a splat.
6429+
// Only applicable to VectorTT and MatrixTT, since the vec/mtx has to be first in the list.
6430+
Template[i] = *pTT;
64036431
break;
6432+
} else if (AR_TOBJ_VECTOR == Template[i] && AR_TOBJ_SCALAR == *pTT) {
6433+
// If a vector was passed in and the expected value was scalar
6434+
// convert to the template type for a truncation.
6435+
// Only applicable to ScalarTT, since the scalar has to be first in the list.
6436+
Template[i] = AR_TOBJ_SCALAR;
6437+
break;
6438+
}
64046439
pTT++;
64056440
}
64066441
}
64076442

6408-
if (AR_TOBJ_UNKNOWN == *pTT) {
6443+
if (AR_TOBJ_UNKNOWN == *pTT || AR_TOBJ_NOCAST == *pTT) {
64096444
Template[i] = g_LegalIntrinsicTemplates[pArgument->uLegalTemplates][0];
64106445
badArgIdx = std::min(badArgIdx, i);
64116446
}

tools/clang/test/HLSLFileCheck/hlsl/intrinsics/compound/refract.hlsl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@
1313
// RUN: %dxc -E main -T vs_6_2 -DTY1=float3 -DTY2=bool -enable-16bit-types %s | FileCheck %s
1414
// RUN: %dxc -E main -T vs_6_2 -DTY1=float4 -DTY2=uint16_t -enable-16bit-types %s | FileCheck %s
1515

16+
// RUN: %dxc -E main -T vs_6_2 -DTY1=float4 -DTY2=uint16_t4 -enable-16bit-types %s | FileCheck %s -check-prefix=CHECK
17+
// RUN: %dxc -E main -T vs_6_2 -DTY1=float4 -DTY2=float16_t2 -enable-16bit-types %s | FileCheck %s -check-prefix=CHECK
18+
1619
// RUN: %dxc -E main -T vs_6_2 -DTY1=float4 -DTY2=uint16_t4x4 -enable-16bit-types %s | FileCheck %s -check-prefix=CHECK_ERROR
17-
// RUN: %dxc -E main -T vs_6_2 -DTY1=float4 -DTY2=uint16_t4 -enable-16bit-types %s | FileCheck %s -check-prefix=CHECK_ERROR
18-
// RUN: %dxc -E main -T vs_6_2 -DTY1=float4 -DTY2=float16_t2 -enable-16bit-types %s | FileCheck %s -check-prefix=CHECK_ERROR
1920
// RUN: %dxc -E main -T vs_6_2 -DTY1=uint16_t4x4 -DTY2=float16_t -enable-16bit-types %s | FileCheck %s -check-prefix=CHECK_ERROR
2021

2122
// CHECK: define void @main()
2223
// CHECK_ERROR: note: candidate function not viable: no known conversion from
2324

2425
TY1 main (TY1 a: IN0, TY1 b : IN1, TY2 c : IN2) : OUT {
2526
return refract(a, b, c);
26-
}
27+
}

tools/clang/test/SemaHLSL/intrinsic-examples.hlsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ float4 RWByteAddressBufferMain(uint2 a : A, uint2 b : B) : SV_Target
1818
uint status;
1919
// TODO - fix the following error - the subscript exist, but the indexer type is incorrect - message is misleading
2020
r += uav1[b]; // expected-error {{type 'RWByteAddressBuffer' does not provide a subscript operator}} fxc-error {{X3121: array, matrix, vector, or indexable object type expected in index expression}}
21-
r += uav1.Load(a); // expected-error {{no matching member function for call to 'Load'}} expected-note {{candidate function template not viable: requires 2 arguments, but 1 was provided}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint)}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint, out uint status)}} fxc-error {{X3013: 'Load': no matching 1 parameter intrinsic method}} fxc-error {{X3013: Possible intrinsic methods are:}}
22-
uav1.Load(a, status); // expected-error {{no matching member function for call to 'Load'}} expected-note {{candidate function template not viable: requires single argument 'byteOffset', but 2 arguments were provided}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint)}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint, out uint status)}} fxc-error {{X3013: 'Load': no matching 2 parameter intrinsic method}} fxc-error {{X3013: Possible intrinsic methods are:}}
21+
r += uav1.Load(a); // expected-warning {{implicit truncation of vector type}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint)}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint, out uint status)}} fxc-error {{X3013: 'Load': no matching 1 parameter intrinsic method}} fxc-error {{X3013: Possible intrinsic methods are:}}
22+
uav1.Load(a, status); // expected-warning {{implicit truncation of vector type}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint)}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint, out uint status)}} fxc-error {{X3013: 'Load': no matching 2 parameter intrinsic method}} fxc-error {{X3013: Possible intrinsic methods are:}}
2323
r += status;
24-
uav1.Load(a, status); // expected-error {{no matching member function for call to 'Load'}} expected-note {{requires single argument 'byteOffset', but 2 arguments were provided}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint)}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint, out uint status)}} fxc-error {{X3013: 'Load': no matching 2 parameter intrinsic method}} fxc-error {{X3013: Possible intrinsic methods are:}}
24+
uav1.Load(a, status); // expected-warning {{implicit truncation of vector type}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint)}} fxc-error {{X3013: RWByteAddressBuffer<uint>.Load(uint, out uint status)}} fxc-error {{X3013: 'Load': no matching 2 parameter intrinsic method}} fxc-error {{X3013: Possible intrinsic methods are:}}
2525
r += status;
2626
uav1[b] = r; // expected-error {{type 'RWByteAddressBuffer' does not provide a subscript operator}} fxc-error {{X3121: array, matrix, vector, or indexable object type expected in index expression}}
2727
uav1.Load(a.x, status);

utils/hct/gen_intrin_main.txt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,15 @@ $type1 [[rn,unsigned_op=umax]] max(in numeric<> a, in $type1 b);
198198
$type1 [[rn,unsigned_op=umin]] min(in numeric<> a, in $type1 b);
199199
$type1 [[]] modf(in float_like<> x, out $type1 ip);
200200
uint<4> [[rn]] msad4(in uint reference, in uint<2> source, in uint<4> accum);
201-
numeric [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric a, in $match<2, 0> numeric b) : mul_ss;
202-
numeric<c2> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric a, in $match<2, 0> numeric<c2> b) : mul_sv;
203-
numeric<r2, c2> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric a, in $match<2, 0> numeric<r2, c2> b) : mul_sm;
204-
numeric<c> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<c> a, in $match<2, 0> numeric b) : mul_vs;
205-
numeric [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<c> a, in $match<2, 0> numeric<c> b) : mul_vv;
206-
numeric<c2> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<c> a, in col_major $match<2, 0> numeric<c, c2> b) : mul_vm;
207-
numeric<r, c> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<r, c> a, in $match<2, 0> numeric b) : mul_ms;
208-
numeric<r> [[rn,unsigned_op=umul]] mul(in row_major $match<1, 0> numeric<r, c> a, in $match<2, 0> numeric<c> b) : mul_mv;
209-
numeric<r, c2> [[rn,unsigned_op=umul]] mul(in row_major $match<1, 0> numeric<r, c> a, in col_major $match<2, 0> numeric<c, c2> b) : mul_mm;
201+
numeric [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric! a, in $match<2, 0> numeric! b) : mul_ss;
202+
numeric<c2> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric! a, in $match<2, 0> numeric<c2>! b) : mul_sv;
203+
numeric<r2, c2> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric! a, in $match<2, 0> numeric<r2, c2>! b) : mul_sm;
204+
numeric<c> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<c>! a, in $match<2, 0> numeric! b) : mul_vs;
205+
numeric [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<c>! a, in $match<2, 0> numeric<c>! b) : mul_vv;
206+
numeric<c2> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<c>! a, in col_major $match<2, 0> numeric<c, c2>! b) : mul_vm;
207+
numeric<r, c> [[rn,unsigned_op=umul]] mul(in $match<1, 0> numeric<r, c>! a, in $match<2, 0> numeric! b) : mul_ms;
208+
numeric<r> [[rn,unsigned_op=umul]] mul(in row_major $match<1, 0> numeric<r, c>! a, in $match<2, 0> numeric<c>! b) : mul_mv;
209+
numeric<r, c2> [[rn,unsigned_op=umul]] mul(in row_major $match<1, 0> numeric<r, c>! a, in col_major $match<2, 0> numeric<c, c2>! b) : mul_mm;
210210
$type1 [[rn]] normalize(in float_like<c> x);
211211
$type1 [[rn]] pow(in float_like<> x, in $type1 y);
212212
void [[]] printf(in string Format, ...);
@@ -849,8 +849,8 @@ $match<0, -1> void<4> [[]] GatherCmpAlpha(in sampler_cmp s, in float<4> x, in fl
849849
namespace BufferMethods {
850850

851851
void [[]] GetDimensions(out uint_only width) : bufinfo;
852-
$classT [[ro]] Load(in int<1> x) : buffer_load;
853-
$classT [[]] Load(in int<1> x, out uint_only status) : buffer_load_s;
852+
$classT [[ro]] Load(in int x) : buffer_load;
853+
$classT [[]] Load(in int x, out uint_only status) : buffer_load_s;
854854

855855
} namespace
856856

0 commit comments

Comments
 (0)