Add default uniform set value to SkSL Program settings.

This allows uniforms to be specified without an explicit `layout(set=N)`
modifier. They will assume a default set value instead.

This turns out to fix a handful of tests in Metal/SPIR-V which were
written with GLSL in mind, or adapted from real generated GLSL code, and
didn't have layout information specified on their uniforms. It will also
make it easier to write SkSL tests using uniforms that can compile
either as a runtime effect or as plain Metal/SPIR-V code.

Change-Id: Id79ec06f278b913a45c09c2e6211195dc98b42c0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/359838
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2021-01-26 16:22:53 -05:00 committed by Skia Commit-Bot
parent 1604ad6b48
commit d8fc95dc02
13 changed files with 31 additions and 41 deletions

View File

@ -1,3 +1,3 @@
layout(set=0) uniform float arr[3];
uniform float arr[3];
void main() {}

View File

@ -1940,17 +1940,19 @@ void MetalCodeGenerator::writeUniformStruct() {
const Variable& var = decls.declaration()->as<VarDeclaration>().var();
if (var.modifiers().fFlags & Modifiers::kUniform_Flag &&
var.type().typeKind() != Type::TypeKind::kSampler) {
// If the uniform has the `layout(set=N)` attribute, honor that. If not, use the
// default uniform-set value from settings.
int uniformSet = var.modifiers().fLayout.fSet;
if (uniformSet == -1) {
uniformSet = fProgram.fSettings.fDefaultUniformSet;
}
// Make sure that the program's uniform-set value is consistent throughout.
if (-1 == fUniformBuffer) {
this->write("struct Uniforms {\n");
fUniformBuffer = var.modifiers().fLayout.fSet;
if (-1 == fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal uniforms must have 'layout(set=...)'");
}
} else if (var.modifiers().fLayout.fSet != fUniformBuffer) {
if (-1 == fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal backend requires all uniforms to have "
"the same 'layout(set=...)'");
}
fUniformBuffer = uniformSet;
} else if (uniformSet != fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal backend requires all uniforms to have "
"the same 'layout(set=...)'");
}
this->write(" ");
this->writeBaseType(var.type());

View File

@ -2898,6 +2898,7 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
}
const Type& type = var.type();
SpvStorageClass_ storageClass;
Layout layout = var.modifiers().fLayout;
if (var.modifiers().fFlags & Modifiers::kIn_Flag) {
storageClass = SpvStorageClassInput;
} else if (var.modifiers().fFlags & Modifiers::kOut_Flag) {
@ -2910,6 +2911,9 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
} else {
storageClass = SpvStorageClassUniform;
}
if (layout.fSet < 0) {
layout.fSet = fProgram.fSettings.fDefaultUniformSet;
}
} else {
storageClass = SpvStorageClassPrivate;
}
@ -2933,7 +2937,7 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuffer);
fCurrentBlock = 0;
}
this->writeLayout(var.modifiers().fLayout, id);
this->writeLayout(layout, id);
if (var.modifiers().fFlags & Modifiers::kFlat_Flag) {
this->writeInstruction(SpvOpDecorate, id, SpvDecorationFlat, fDecorationBuffer);
}

View File

@ -130,6 +130,9 @@ struct Program {
// binding and set number of the uniform buffer.
int fRTHeightBinding = -1;
int fRTHeightSet = -1;
// If layout(binding=N) is not specified for a uniform, this value will be used. At present,
// zero is always used by our backends.
int fDefaultUniformSet = 0;
// If true, remove any uncalled functions other than main(). Note that a function which
// starts out being used may end up being uncalled after optimization.
bool fRemoveDeadFunctions = true;

View File

@ -24,6 +24,7 @@ OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %colorXform DescriptorSet 0
OpDecorate %s RelaxedPrecision
OpDecorate %s Binding 0
OpDecorate %s DescriptorSet 0
OpDecorate %23 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4

View File

@ -1,10 +1,3 @@
### Compilation failed:
error: SPIR-V validation error: UniformConstant id '20' is missing DescriptorSet decoration.
From Vulkan spec, section 14.5.2:
These variables must have DescriptorSet and Binding decorations specified
%uTextureSampler_0_Stage1 = OpVariable %_ptr_UniformConstant_22 UniformConstant
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
@ -57,6 +50,7 @@ OpDecorate %sk_Clockwise RelaxedPrecision
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %uTextureSampler_0_Stage1 RelaxedPrecision
OpDecorate %uTextureSampler_0_Stage1 Binding 0
OpDecorate %uTextureSampler_0_Stage1 DescriptorSet 0
OpDecorate %vLocalCoord_Stage0 Location 0
OpDecorate %67 RelaxedPrecision
OpDecorate %100 RelaxedPrecision
@ -809,5 +803,3 @@ OpStore %output_Stage1 %496
OpStore %sk_FragColor %497
OpReturn
OpFunctionEnd
1 error

View File

@ -23,6 +23,7 @@ OpMemberDecorate %sk_PerVertex 0 BuiltIn Position
OpMemberDecorate %sk_PerVertex 1 BuiltIn PointSize
OpDecorate %_arr_sk_PerVertex_int_1 ArrayStride 32
OpDecorate %sk_InvocationID BuiltIn InvocationId
OpDecorate %sk_RTAdjust DescriptorSet 0
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%sk_PerVertex = OpTypeStruct %v4float %float

View File

@ -1,5 +1,4 @@
### Compilation failed:
error: 3: Metal uniforms must have 'layout(set=...)'
error: unsupported kind of program
2 errors
1 error

View File

@ -1,10 +1,3 @@
### Compilation failed:
error: SPIR-V validation error: UniformConstant id '10' is missing DescriptorSet decoration.
From Vulkan spec, section 14.5.2:
These variables must have DescriptorSet and Binding decorations specified
%test2D = OpVariable %_ptr_UniformConstant_12 UniformConstant
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
@ -22,8 +15,10 @@ OpDecorate %sk_Clockwise RelaxedPrecision
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %test2D RelaxedPrecision
OpDecorate %test2D Binding 0
OpDecorate %test2D DescriptorSet 0
OpDecorate %test2DRect RelaxedPrecision
OpDecorate %test2DRect Binding 1
OpDecorate %test2DRect DescriptorSet 0
OpDecorate %19 RelaxedPrecision
OpDecorate %24 RelaxedPrecision
OpDecorate %26 RelaxedPrecision
@ -59,5 +54,3 @@ OpStore %sk_FragColor %23
OpStore %sk_FragColor %25
OpReturn
OpFunctionEnd
1 error

View File

@ -21,6 +21,7 @@ OpDecorate %sk_Clockwise RelaxedPrecision
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %tex RelaxedPrecision
OpDecorate %tex Binding 0
OpDecorate %tex DescriptorSet 0
OpDecorate %20 RelaxedPrecision
OpDecorate %24 RelaxedPrecision
%float = OpTypeFloat 32

View File

@ -1,10 +1,3 @@
### Compilation failed:
error: SPIR-V validation error: UniformConstant id '10' is missing DescriptorSet decoration.
From Vulkan spec, section 14.5.2:
These variables must have DescriptorSet and Binding decorations specified
%tex = OpVariable %_ptr_UniformConstant_12 UniformConstant
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
@ -23,6 +16,7 @@ OpDecorate %sk_Clockwise RelaxedPrecision
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %tex RelaxedPrecision
OpDecorate %tex Binding 0
OpDecorate %tex DescriptorSet 0
OpDecorate %20 RelaxedPrecision
OpDecorate %26 RelaxedPrecision
%float = OpTypeFloat 32
@ -66,5 +60,3 @@ OpStore %b %25
OpStore %sk_FragColor %37
OpReturn
OpFunctionEnd
1 error

View File

@ -24,8 +24,10 @@ OpDecorate %sk_Clockwise RelaxedPrecision
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %one RelaxedPrecision
OpDecorate %one Binding 0
OpDecorate %one DescriptorSet 0
OpDecorate %two RelaxedPrecision
OpDecorate %two Binding 1
OpDecorate %two DescriptorSet 0
OpDecorate %24 RelaxedPrecision
OpDecorate %29 RelaxedPrecision
OpDecorate %34 RelaxedPrecision

View File

@ -1,4 +1,4 @@
layout (set = 0) uniform float arr[3];
uniform float arr[3];
void main() {
}