Skip to content

Commit 11465ea

Browse files
authored
Merge branch 'master' into coerce-constraint
2 parents 5f9ef8a + 9580e31 commit 11465ea

8 files changed

+319
-8
lines changed

source/slang/slang-emit-hlsl.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -1252,23 +1252,30 @@ void HLSLSourceEmitter::emitSimpleValueImpl(IRInst* inst)
12521252
{
12531253
case IRConstant::FloatKind::Nan:
12541254
{
1255-
m_writer->emit("(0.0 / 0.0)");
1255+
m_writer->emit("(0.0f / 0.0f)");
12561256
return;
12571257
}
12581258
case IRConstant::FloatKind::PositiveInfinity:
12591259
{
1260-
m_writer->emit("(1.0 / 0.0)");
1260+
m_writer->emit("(1.0f / 0.0f)");
12611261
return;
12621262
}
12631263
case IRConstant::FloatKind::NegativeInfinity:
12641264
{
1265-
m_writer->emit("(-1.0 / 0.0)");
1265+
m_writer->emit("(-1.0f / 0.0f)");
12661266
return;
12671267
}
12681268
default:
1269-
break;
1269+
{
1270+
m_writer->emit(constantInst->value.floatVal);
1271+
// Add 'f' suffix for 32-bit float literals to ensure DXC treats them as float
1272+
if (constantInst->getDataType()->getOp() == kIROp_FloatType)
1273+
{
1274+
m_writer->emit("f");
1275+
}
1276+
return;
1277+
}
12701278
}
1271-
break;
12721279
}
12731280

12741281
default:

source/slang/slang-ir-lower-binding-query.cpp

+112-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,118 @@ struct BindingQueryLoweringContext : public WorkListPass
288288
//
289289
OpaqueValueInfo computeOpaqueValueInfo(IRInst* opaqueValue)
290290
{
291-
if (auto globalParam = as<IRGlobalParam>(opaqueValue))
291+
if (auto getElement = as<IRGetElement>(opaqueValue))
292+
{
293+
IRInst* baseInst = getElement->getBase();
294+
IRInst* indexInst = getElement->getIndex();
295+
296+
IRInst* elementType = getElement->getDataType();
297+
298+
// TODO(JS): This a hack to make this work for arrays of resource type.
299+
// It won't work in the general case as it stands because we would need
300+
// to propogate layout kind types needed at usage sites.
301+
// Without knowing the resource kind that is being processed it's not possible
302+
// to accumulate the calculation.
303+
//
304+
// So presumably we need to request a binding query for a specific resource kind.
305+
// We could do this by making the type of the binding query hold the type.
306+
307+
// We need to add instructions which will work out the binding for the base
308+
OpaqueValueInfo baseInfo = findOrComputeOpaqueValueInfo(baseInst);
309+
310+
// If we couldn't find it we are done
311+
if (baseInfo.registerIndex == nullptr || baseInfo.registerSpace == nullptr)
312+
{
313+
return baseInfo;
314+
}
315+
316+
317+
LayoutResourceKind kind = LayoutResourceKind::None;
318+
Index stride = 1;
319+
320+
if (auto resourceType = as<IRResourceType>(elementType))
321+
{
322+
const auto shape = resourceType->getShape();
323+
324+
switch (shape)
325+
{
326+
case SLANG_TEXTURE_1D:
327+
case SLANG_TEXTURE_2D:
328+
case SLANG_TEXTURE_3D:
329+
case SLANG_TEXTURE_CUBE:
330+
case SLANG_STRUCTURED_BUFFER:
331+
case SLANG_BYTE_ADDRESS_BUFFER:
332+
case SLANG_TEXTURE_BUFFER:
333+
{
334+
const auto access = resourceType->getAccess();
335+
bool isReadOnly = (access == SLANG_RESOURCE_ACCESS_READ);
336+
337+
kind = isReadOnly ? LayoutResourceKind::ShaderResource
338+
: LayoutResourceKind::UnorderedAccess;
339+
break;
340+
}
341+
default:
342+
break;
343+
}
344+
}
345+
else if (as<IRSamplerStateTypeBase>(elementType))
346+
{
347+
kind = LayoutResourceKind::SamplerState;
348+
}
349+
else if (as<IRConstantBufferType>(elementType))
350+
{
351+
kind = LayoutResourceKind::ConstantBuffer;
352+
}
353+
354+
if (kind == LayoutResourceKind::None)
355+
{
356+
// Can't determine the kind
357+
return OpaqueValueInfo();
358+
}
359+
360+
// If the element type has type layout we can try and use that
361+
if (auto layoutDecoration = elementType->findDecoration<IRLayoutDecoration>())
362+
{
363+
// We have to calculate
364+
if (auto elementTypeLayout = as<IRTypeLayout>(layoutDecoration->getLayout()))
365+
{
366+
IRTypeSizeAttr* sizeAttr = elementTypeLayout->findSizeAttr(kind);
367+
sizeAttr = sizeAttr ? sizeAttr
368+
: elementTypeLayout->findSizeAttr(
369+
LayoutResourceKind::DescriptorTableSlot);
370+
371+
if (!sizeAttr)
372+
{
373+
// Couldn't work it out
374+
return OpaqueValueInfo();
375+
}
376+
377+
// TODO(JS): Perhaps we have to do something else if not finite?
378+
stride = sizeAttr->getFiniteSize();
379+
}
380+
}
381+
382+
SLANG_UNUSED(indexInst);
383+
384+
// Okay we need to create an instruction which is
385+
// base + stride * index
386+
387+
IRBuilder builder(module);
388+
389+
builder.setInsertBefore(opaqueValue);
390+
391+
auto calcRegisterInst = builder.emitAdd(
392+
indexType,
393+
builder.emitMul(indexType, builder.getIntValue(indexType, stride), indexInst),
394+
baseInfo.registerIndex);
395+
396+
OpaqueValueInfo finalInfo;
397+
finalInfo.registerIndex = calcRegisterInst;
398+
finalInfo.registerSpace = baseInfo.registerSpace;
399+
400+
return finalInfo;
401+
}
402+
else if (auto globalParam = as<IRGlobalParam>(opaqueValue))
292403
{
293404
// The simple/base case is when we have a global shader
294405
// parameter that has layout information attached.

source/slang/slang-ir-specialize-resources.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,10 @@ bool isIllegalGLSLParameterType(IRType* type)
13591359
return true;
13601360
if (as<IRDynamicResourceType>(type))
13611361
return true;
1362+
if (as<IRHLSLInputPatchType>(type))
1363+
return true;
1364+
if (as<IRHLSLOutputPatchType>(type))
1365+
return true;
13621366
return false;
13631367
}
13641368

source/slang/slang-ir.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -5279,6 +5279,11 @@ IRInst* IRBuilder::emitElementAddress(IRInst* basePtr, IRInst* index)
52795279
SLANG_ASSERT(as<IRIntLit>(index));
52805280
type = (IRType*)tupleType->getOperand(getIntVal(index));
52815281
}
5282+
else if (auto hlslInputPatchType = as<IRHLSLInputPatchType>(valueType))
5283+
{
5284+
type = hlslInputPatchType->getElementType();
5285+
}
5286+
52825287
SLANG_RELEASE_ASSERT(type);
52835288
auto inst = createInst<IRGetElementPtr>(
52845289
this,

tests/expected-failure-github.txt

-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
tests/language-feature/spirv-asm/imageoperands-warning.slang (vk)
21
tests/language-feature/saturated-cooperation/simple.slang (vk)
32
tests/language-feature/saturated-cooperation/fuse3.slang (vk)
43
tests/language-feature/saturated-cooperation/fuse-product.slang (vk)
54
tests/language-feature/saturated-cooperation/fuse.slang (vk)
6-
tests/bugs/byte-address-buffer-interlocked-add-f32.slang (vk)
75
tests/render/render0.hlsl (mtl)
86
tests/render/multiple-stage-io-locations.slang (mtl)
97
tests/render/nointerpolation.hlsl (mtl)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//DISABLE_TEST:SIMPLE:-target dxil-assembly -entry fragmentMain -profile sm_6_5 -stage fragment -DNV_SHADER_EXTN_SLOT=u0
2+
3+
//TEST:SIMPLE(filecheck=SPIRV):-target spirv-assembly -entry fragmentMain -stage fragment
4+
//TEST:SIMPLE(filecheck=DXIL):-target dxil-assembly -entry fragmentMain -profile sm_6_5 -stage fragment -DNV_SHADER_EXTN_SLOT=u0
5+
//TEST:SIMPLE(filecheck=HLSL):-target hlsl -entry fragmentMain -stage fragment
6+
7+
//DISABLED_TEST:SIMPLE:-target spirv-assembly -entry fragmentMain -stage fragment
8+
//DISABLED_TEST:SIMPLE:-target dxil-assembly -entry fragmentMain -stage fragment
9+
//DISABLED_TEST:SIMPLE:-target hlsl -entry fragmentMain -stage fragment
10+
11+
uniform Texture2D textures[] : register(t2, space10);
12+
uniform SamplerState sampler;
13+
uniform RWStructuredBuffer<uint> outputBuffer;
14+
15+
static Texture2D _getBindlessTexture2d(uint texIdx)
16+
{
17+
return textures[NonUniformResourceIndex(texIdx)];
18+
}
19+
20+
void accumulate(inout uint r, uint u)
21+
{
22+
r = r ^ u;
23+
}
24+
25+
void accumulate(inout uint r, bool b)
26+
{
27+
accumulate(r, uint(b));
28+
}
29+
30+
void accumulate(inout uint r, uint2 u)
31+
{
32+
accumulate(r, u.x);
33+
accumulate(r, u.y);
34+
}
35+
36+
void accumulate(inout uint r, uint3 u)
37+
{
38+
accumulate(r, u.x);
39+
accumulate(r, u.y);
40+
accumulate(r, u.z);
41+
}
42+
43+
void accumulate(inout uint r, TextureFootprint2D f)
44+
{
45+
accumulate(r, f.anchor);
46+
accumulate(r, f.offset);
47+
accumulate(r, f.mask);
48+
accumulate(r, f.lod);
49+
accumulate(r, f.granularity);
50+
accumulate(r, f.isSingleLevel);
51+
}
52+
53+
cbuffer Uniforms
54+
{
55+
uniform float2 coords;
56+
uniform uint granularity;
57+
};
58+
59+
void fragmentMain(
60+
float v : VARYING)
61+
{
62+
uint index = uint(v);
63+
uint r = 0;
64+
65+
accumulate(r, _getBindlessTexture2d(index).queryFootprintCoarse(granularity, sampler, coords));
66+
67+
// SPIRV: Extension "SPV_NV_shader_image_footprint"
68+
// SPIRV: ImageSampleFootprintNV
69+
70+
// DXIL: struct struct.NvShaderExtnStruct
71+
72+
// HLSL: NvFootprintCoarse
73+
74+
outputBuffer[index] = r;
75+
}
76+

tests/hlsl/float-literal-suffix.slang

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//TEST:SIMPLE(filecheck=HLSL):-target hlsl -profile ps_6_6 -entry fragmentMain
2+
//TEST:SIMPLE(filecheck=DXIL):-target dxil -profile ps_6_6 -entry fragmentMain
3+
4+
float4 fragmentMain(float2 uv : TEXCOORD) : SV_Target
5+
{
6+
//HLSL:, ddx({{.*}}1.5f)
7+
//DXIL: = call float @dx.op.unary.f32(i32 {{.*}} ; DerivCoarseX(value)
8+
float val = 1.5;
9+
return float4(1.0, ddx(val), 0.0, 1.0);
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//TEST:SIMPLE(filecheck=HULL): -target spirv -stage hull -entry hullMain
2+
//TEST:SIMPLE(filecheck=DOMAIN): -target spirv -stage domain -entry domainMain
3+
4+
// Testing if `InputPatch` and `OutputPatch` can be used as function arguments.
5+
// `[ForceInline]` can be used to workaround but it should work without it.
6+
7+
// HULL: OpEntryPoint TessellationControl %hullMain
8+
// HULL: = OpVariable %{{[a-zA-Z_0-9]*}} Input
9+
10+
// DOMAIN: OpEntryPoint TessellationEvaluation %domainMain
11+
// DOMAIN: = OpVariable %{{[a-zA-Z_0-9]*}} Output
12+
13+
struct VS_OUT
14+
{
15+
float3 position : POSITION;
16+
};
17+
18+
struct HS_OUT
19+
{
20+
float3 position : POSITION;
21+
};
22+
23+
struct HSC_OUT
24+
{
25+
float EdgeTessFactor[4] : SV_TessFactor;
26+
float InsideTessFactor[2] : SV_InsideTessFactor;
27+
};
28+
29+
struct DS_OUT
30+
{
31+
float4 position : SV_Position;
32+
};
33+
34+
35+
VS_OUT GetInputPatch(InputPatch<VS_OUT, 4> patch, int index)
36+
{
37+
return patch[index];
38+
}
39+
40+
// Hull Shader (HS)
41+
[domain("quad")]
42+
[partitioning("integer")]
43+
[outputtopology("triangle_cw")]
44+
[outputcontrolpoints(4)]
45+
[patchconstantfunc("constants")]
46+
HS_OUT hullMain(InputPatch<VS_OUT, 4> patch, uint i : SV_OutputControlPointID)
47+
{
48+
HS_OUT o;
49+
o.position = patch[i].position;
50+
return o;
51+
}
52+
53+
HSC_OUT constants(InputPatch<VS_OUT, 4> patch)
54+
{
55+
float3 p0 = GetInputPatch(patch, 0).position;
56+
float3 p1 = patch[1].position;
57+
float3 p2 = patch[2].position;
58+
float3 p3 = patch[3].position;
59+
60+
HSC_OUT o;
61+
o.EdgeTessFactor[0] = dot(p0, p1);
62+
o.EdgeTessFactor[1] = dot(p0, p3);
63+
o.EdgeTessFactor[2] = dot(p2, p3);
64+
o.EdgeTessFactor[3] = dot(p1, p2);
65+
o.InsideTessFactor[0] = lerp(o.EdgeTessFactor[1], o.EdgeTessFactor[3], 0.5);
66+
o.InsideTessFactor[1] = lerp(o.EdgeTessFactor[0], o.EdgeTessFactor[2], 0.5);
67+
return o;
68+
}
69+
70+
HS_OUT GetOutputPatch(const OutputPatch<HS_OUT, 4> patch, int index)
71+
{
72+
return patch[index];
73+
}
74+
75+
[domain("quad")]
76+
DS_OUT domainMain(
77+
float2 uv : SV_DomainLocation, // Tessellated coordinates (u, v)
78+
const OutputPatch<HS_OUT, 4> patch, // Control points from the hull shader
79+
const HSC_OUT patchConstants // Patch constants calculated by the hull shader
80+
)
81+
{
82+
DS_OUT o;
83+
84+
// Interpolate the position of the tessellated point within the patch
85+
float3 p0 = GetOutputPatch(patch, 0).position;
86+
float3 p1 = patch[1].position;
87+
float3 p2 = patch[2].position;
88+
float3 p3 = patch[3].position;
89+
90+
// Bilinear interpolation of the position in the quad
91+
float3 interpolatedPosition =
92+
p0 * (1 - uv.x) * (1 - uv.y)
93+
+ p1 * uv.x * (1 - uv.y)
94+
+ p3 * uv.x * uv.y
95+
+ p2 * (1 - uv.x) * uv.y;
96+
97+
// Output final position in clip space
98+
o.position = float4(interpolatedPosition, 1.0);
99+
return o;
100+
}

0 commit comments

Comments
 (0)