[SPIR-V] Implement EvaluateAttribute* functions (#6945)
Emits SPIR-V InterpolateAt* instructions from the GLSL.std.450 extended instruction set for EvaluateAttribute*. Relies on the optimizer's copy propagate passes to ensure that these instructions are passed valid pointers in the Input storage class after legalization. Fixes #3649
This commit is contained in:
Родитель
b48341e403
Коммит
b26fd8099a
|
@ -1 +1 @@
|
|||
Subproject commit c173df736cb89ba4daba0beec039317292f22e0d
|
||||
Subproject commit 522dfead39eb232b3873f0e7cfe57cde6b9e69c1
|
|
@ -895,6 +895,8 @@ bool CapabilityVisitor::visit(SpirvModule *, Visitor::Phase phase) {
|
|||
Extension::NV_shader_subgroup_partitioned,
|
||||
{spv::Capability::GroupNonUniformPartitionedNV});
|
||||
|
||||
addCapability(spv::Capability::InterpolationFunction);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -9366,6 +9366,12 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
|
|||
case hlsl::IntrinsicOp::IOP_isfinite:
|
||||
retVal = processIntrinsicIsFinite(callExpr);
|
||||
break;
|
||||
case hlsl::IntrinsicOp::IOP_EvaluateAttributeCentroid:
|
||||
case hlsl::IntrinsicOp::IOP_EvaluateAttributeAtSample:
|
||||
case hlsl::IntrinsicOp::IOP_EvaluateAttributeSnapped: {
|
||||
retVal = processEvaluateAttributeAt(callExpr, hlslOpcode, srcLoc, srcRange);
|
||||
break;
|
||||
}
|
||||
INTRINSIC_SPIRV_OP_CASE(ddx, DPdx, true);
|
||||
INTRINSIC_SPIRV_OP_CASE(ddx_coarse, DPdxCoarse, false);
|
||||
INTRINSIC_SPIRV_OP_CASE(ddx_fine, DPdxFine, false);
|
||||
|
@ -11939,6 +11945,44 @@ SpirvInstruction *SpirvEmitter::processIntrinsicUsingGLSLInst(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
SpirvInstruction *SpirvEmitter::processEvaluateAttributeAt(
|
||||
const CallExpr *callExpr, hlsl::IntrinsicOp opcode, SourceLocation loc,
|
||||
SourceRange range) {
|
||||
QualType returnType = callExpr->getType();
|
||||
SpirvInstruction *arg0Instr = doExpr(callExpr->getArg(0));
|
||||
SpirvInstruction *interpolant =
|
||||
turnIntoLValue(callExpr->getType(), arg0Instr, callExpr->getExprLoc());
|
||||
|
||||
switch (opcode) {
|
||||
case hlsl::IntrinsicOp::IOP_EvaluateAttributeCentroid:
|
||||
return spvBuilder.createGLSLExtInst(
|
||||
returnType, GLSLstd450InterpolateAtCentroid, {interpolant}, loc, range);
|
||||
case hlsl::IntrinsicOp::IOP_EvaluateAttributeAtSample: {
|
||||
SpirvInstruction *sample = doExpr(callExpr->getArg(1));
|
||||
return spvBuilder.createGLSLExtInst(returnType,
|
||||
GLSLstd450InterpolateAtSample,
|
||||
{interpolant, sample}, loc, range);
|
||||
}
|
||||
case hlsl::IntrinsicOp::IOP_EvaluateAttributeSnapped: {
|
||||
const Expr *arg1 = callExpr->getArg(1);
|
||||
SpirvInstruction *arg1Inst = doExpr(arg1);
|
||||
|
||||
QualType float2Type = astContext.getExtVectorType(astContext.FloatTy, 2);
|
||||
SpirvInstruction *offset =
|
||||
castToFloat(arg1Inst, arg1->getType(), float2Type, arg1->getLocStart(),
|
||||
arg1->getSourceRange());
|
||||
|
||||
return spvBuilder.createGLSLExtInst(returnType,
|
||||
GLSLstd450InterpolateAtOffset,
|
||||
{interpolant, offset}, loc, range);
|
||||
}
|
||||
default:
|
||||
assert(false && "processEvaluateAttributeAt must be called with an "
|
||||
"EvaluateAttribute* opcode");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SpirvInstruction *
|
||||
SpirvEmitter::processIntrinsicLog10(const CallExpr *callExpr) {
|
||||
// Since there is no log10 instruction in SPIR-V, we can use:
|
||||
|
|
|
@ -622,6 +622,12 @@ private:
|
|||
SpirvInstruction *processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
|
||||
hlsl::IntrinsicOp opcode);
|
||||
|
||||
/// Processes EvaluateAttributeAt* intrinsic calls.
|
||||
SpirvInstruction *processEvaluateAttributeAt(const CallExpr *expr,
|
||||
hlsl::IntrinsicOp opcode,
|
||||
SourceLocation loc,
|
||||
SourceRange range);
|
||||
|
||||
/// Processes Interlocked* intrinsic functions.
|
||||
SpirvInstruction *processIntrinsicInterlockedMethod(const CallExpr *,
|
||||
hlsl::IntrinsicOp);
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// RUN: %dxc -T ps_6_0 -E main -fcgl %s -spirv -Vd | FileCheck %s
|
||||
|
||||
RWStructuredBuffer<float4> a;
|
||||
|
||||
[[vk::ext_builtin_input(/* PointCoord */ 16)]]
|
||||
static const float2 gl_PointCoord;
|
||||
|
||||
// CHECK: [[instSet:%[0-9]+]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
void setValue(float4 input);
|
||||
|
||||
// CHECK: %src_main = OpFunction
|
||||
void main(float4 color : COLOR, float instance : SV_InstanceID) {
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %color
|
||||
// CHECK: OpStore %temp_var_v4float [[val]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtSample %temp_var_v4float %uint_0
|
||||
a[0] = EvaluateAttributeAtSample(color, 0);
|
||||
|
||||
setValue(color);
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %c2
|
||||
// CHECK: OpStore %temp_var_v4float_0 [[val]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtSample %temp_var_v4float_0 %uint_2
|
||||
float4 c2 = color;
|
||||
a[2] = EvaluateAttributeAtSample(c2, 2);
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %float %instance
|
||||
// CHECK: OpStore %temp_var_float [[val]]
|
||||
// CHECK: OpExtInst %float [[instSet]] InterpolateAtSample %temp_var_float %uint_3
|
||||
a[3] = EvaluateAttributeAtSample(instance, 3);
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v2float %gl_PointCoord
|
||||
// CHECK: OpStore %temp_var_v2float [[val]]
|
||||
// CHECK: OpExtInst %v2float [[instSet]] InterpolateAtSample %temp_var_v2float %uint_4
|
||||
a[4] = float4(EvaluateAttributeAtSample(gl_PointCoord, 4), 0, 0);
|
||||
}
|
||||
|
||||
// CHECK: %setValue = OpFunction
|
||||
void setValue(float4 input) {
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %input
|
||||
// CHECK: OpStore %temp_var_v4float_1 [[val]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtSample %temp_var_v4float_1 %uint_1
|
||||
a[1] = EvaluateAttributeAtSample(input, 1);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// RUN: %dxc -T ps_6_0 -E main -fcgl %s -spirv -Vd | FileCheck %s
|
||||
|
||||
RWStructuredBuffer<float4> a;
|
||||
|
||||
[[vk::ext_builtin_input(/* PointCoord */ 16)]]
|
||||
static const float2 gl_PointCoord;
|
||||
|
||||
// CHECK: [[instSet:%[0-9]+]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
void setValue(float4 input);
|
||||
|
||||
// CHECK: %src_main = OpFunction
|
||||
void main(float4 color : COLOR, float instance : SV_InstanceID) {
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %color
|
||||
// CHECK: OpStore %temp_var_v4float [[val]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtCentroid %temp_var_v4float
|
||||
a[0] = EvaluateAttributeCentroid(color);
|
||||
|
||||
setValue(color);
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %c2
|
||||
// CHECK: OpStore %temp_var_v4float_0 [[val]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtCentroid %temp_var_v4float_0
|
||||
float4 c2 = color;
|
||||
a[2] = EvaluateAttributeCentroid(c2);
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %float %instance
|
||||
// CHECK: OpStore %temp_var_float [[val]]
|
||||
// CHECK: OpExtInst %float [[instSet]] InterpolateAtCentroid %temp_var_float
|
||||
a[3] = EvaluateAttributeCentroid(instance);
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v2float %gl_PointCoord
|
||||
// CHECK: OpStore %temp_var_v2float [[val]]
|
||||
// CHECK: OpExtInst %v2float [[instSet]] InterpolateAtCentroid %temp_var_v2float
|
||||
a[4] = float4(EvaluateAttributeCentroid(gl_PointCoord), 0, 0);
|
||||
}
|
||||
|
||||
|
||||
// CHECK: %setValue = OpFunction
|
||||
void setValue(float4 input) {
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %input
|
||||
// CHECK: OpStore %temp_var_v4float_1 [[val]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtCentroid %temp_var_v4float_1
|
||||
a[1] = EvaluateAttributeCentroid(input);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
// RUN: %dxc -T ps_6_0 -E main -fcgl %s -spirv -Vd | FileCheck %s
|
||||
|
||||
RWStructuredBuffer<float4> a;
|
||||
|
||||
[[vk::ext_builtin_input(/* PointCoord */ 16)]]
|
||||
static const float2 gl_PointCoord;
|
||||
|
||||
// CHECK: [[instSet:%[0-9]+]] = OpExtInstImport "GLSL.std.450"
|
||||
|
||||
// CHECK: [[v2int_0_0:%[0-9]+]] = OpConstantComposite %v2int %int_0 %int_0
|
||||
// CHECK: [[v2int_2_2:%[0-9]+]] = OpConstantComposite %v2int %int_2 %int_2
|
||||
// CHECK: [[v2int_3_3:%[0-9]+]] = OpConstantComposite %v2int %int_3 %int_3
|
||||
// CHECK: [[v2int_4_4:%[0-9]+]] = OpConstantComposite %v2int %int_4 %int_4
|
||||
// CHECK: [[v2int_1_1:%[0-9]+]] = OpConstantComposite %v2int %int_1 %int_1
|
||||
|
||||
void setValue(float4 input);
|
||||
|
||||
// CHECK: %src_main = OpFunction
|
||||
void main(float4 color : COLOR, float instance : SV_InstanceID) {
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %color
|
||||
// CHECK: OpStore %temp_var_v4float [[val]]
|
||||
// CHECK: [[offset:%[0-9]+]] = OpConvertSToF %v2float [[v2int_0_0]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtOffset %temp_var_v4float [[offset]]
|
||||
a[0] = EvaluateAttributeSnapped(color, int2(0,0));
|
||||
|
||||
setValue(color);
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %c2
|
||||
// CHECK: OpStore %temp_var_v4float_0 [[val]]
|
||||
// CHECK: [[offset:%[0-9]+]] = OpConvertSToF %v2float [[v2int_2_2]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtOffset %temp_var_v4float_0 [[offset]]
|
||||
float4 c2 = color;
|
||||
a[2] = EvaluateAttributeSnapped(c2, int2(2,2));
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %float %instance
|
||||
// CHECK: OpStore %temp_var_float [[val]]
|
||||
// CHECK: [[offset:%[0-9]+]] = OpConvertSToF %v2float [[v2int_3_3]]
|
||||
// CHECK: OpExtInst %float [[instSet]] InterpolateAtOffset %temp_var_float [[offset]]
|
||||
a[3] = EvaluateAttributeSnapped(instance, int2(3,3));
|
||||
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v2float %gl_PointCoord
|
||||
// CHECK: OpStore %temp_var_v2float [[val]]
|
||||
// CHECK: [[offset:%[0-9]+]] = OpConvertSToF %v2float [[v2int_4_4]]
|
||||
// CHECK: OpExtInst %v2float [[instSet]] InterpolateAtOffset %temp_var_v2float [[offset]]
|
||||
a[4] = float4(EvaluateAttributeSnapped(gl_PointCoord, int2(4, 4)), 0, 0);
|
||||
}
|
||||
|
||||
// CHECK: %setValue = OpFunction
|
||||
void setValue(float4 input) {
|
||||
// CHECK: [[val:%[0-9]+]] = OpLoad %v4float %input
|
||||
// CHECK: OpStore %temp_var_v4float_1 [[val]]
|
||||
// CHECK: [[offset:%[0-9]+]] = OpConvertSToF %v2float [[v2int_1_1]]
|
||||
// CHECK: OpExtInst %v4float [[instSet]] InterpolateAtOffset %temp_var_v4float_1 [[offset]]
|
||||
a[1] = EvaluateAttributeSnapped(input, int2(1,1));
|
||||
}
|
Загрузка…
Ссылка в новой задаче