[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,
|
Extension::NV_shader_subgroup_partitioned,
|
||||||
{spv::Capability::GroupNonUniformPartitionedNV});
|
{spv::Capability::GroupNonUniformPartitionedNV});
|
||||||
|
|
||||||
|
addCapability(spv::Capability::InterpolationFunction);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9366,6 +9366,12 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
|
||||||
case hlsl::IntrinsicOp::IOP_isfinite:
|
case hlsl::IntrinsicOp::IOP_isfinite:
|
||||||
retVal = processIntrinsicIsFinite(callExpr);
|
retVal = processIntrinsicIsFinite(callExpr);
|
||||||
break;
|
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, DPdx, true);
|
||||||
INTRINSIC_SPIRV_OP_CASE(ddx_coarse, DPdxCoarse, false);
|
INTRINSIC_SPIRV_OP_CASE(ddx_coarse, DPdxCoarse, false);
|
||||||
INTRINSIC_SPIRV_OP_CASE(ddx_fine, DPdxFine, false);
|
INTRINSIC_SPIRV_OP_CASE(ddx_fine, DPdxFine, false);
|
||||||
|
@ -11939,6 +11945,44 @@ SpirvInstruction *SpirvEmitter::processIntrinsicUsingGLSLInst(
|
||||||
return nullptr;
|
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 *
|
SpirvInstruction *
|
||||||
SpirvEmitter::processIntrinsicLog10(const CallExpr *callExpr) {
|
SpirvEmitter::processIntrinsicLog10(const CallExpr *callExpr) {
|
||||||
// Since there is no log10 instruction in SPIR-V, we can use:
|
// Since there is no log10 instruction in SPIR-V, we can use:
|
||||||
|
|
|
@ -622,6 +622,12 @@ private:
|
||||||
SpirvInstruction *processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
|
SpirvInstruction *processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
|
||||||
hlsl::IntrinsicOp opcode);
|
hlsl::IntrinsicOp opcode);
|
||||||
|
|
||||||
|
/// Processes EvaluateAttributeAt* intrinsic calls.
|
||||||
|
SpirvInstruction *processEvaluateAttributeAt(const CallExpr *expr,
|
||||||
|
hlsl::IntrinsicOp opcode,
|
||||||
|
SourceLocation loc,
|
||||||
|
SourceRange range);
|
||||||
|
|
||||||
/// Processes Interlocked* intrinsic functions.
|
/// Processes Interlocked* intrinsic functions.
|
||||||
SpirvInstruction *processIntrinsicInterlockedMethod(const CallExpr *,
|
SpirvInstruction *processIntrinsicInterlockedMethod(const CallExpr *,
|
||||||
hlsl::IntrinsicOp);
|
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));
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче