Add a samplerUniforms field for FragmentProgram (flutter/engine#29597)
This commit is contained in:
committed by
GitHub
parent
bf71ab3987
commit
87422e6679
@@ -22,14 +22,14 @@ the code will need to adhere to the following rules.
|
||||
- Control flow is prohibited aside from function calls and `return`.
|
||||
`if`, `while`, `for`, `switch`, etc.
|
||||
- No inputs from other shader stages.
|
||||
- Only float, float-vector types, and square float-matrix types.
|
||||
- Only sampler2D, float, float-vector types, and square float-matrix types.
|
||||
- Only square matrices are supported.
|
||||
- Only built-in functions present in GLSL ES 100 are used.
|
||||
- Debug symbols must be stripped, you can use the `spirv-opt` `--strip-debug` flag.
|
||||
- Only the `texture` function is supported for sampling from a sampler2D object.
|
||||
|
||||
These rules may become less strict in future versions. Conformant SPIR-V should successfully transpile from the current version onwards. In other words, a SPIR-V shader you use now that meets these rules should keep working, but the output of the transpiler may change for that shader.
|
||||
|
||||
Support for textures, control flow, and structured types is planned, but not currently included.
|
||||
Support for control flow, and structured types is planned, but not currently included.
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
@@ -38,7 +38,15 @@ class TranspileResult {
|
||||
/// The number of float uniforms used in this shader.
|
||||
final int uniformFloatCount;
|
||||
|
||||
TranspileResult._(this.src, this.uniformFloatCount, this.language);
|
||||
/// The number of samplers (children) used in this shader.
|
||||
final int samplerCount;
|
||||
|
||||
TranspileResult._(
|
||||
this.src,
|
||||
this.uniformFloatCount,
|
||||
this.samplerCount,
|
||||
this.language,
|
||||
);
|
||||
}
|
||||
|
||||
/// Thrown during transpilation due to malformed or unsupported SPIR-V.
|
||||
@@ -64,6 +72,7 @@ TranspileResult transpile(ByteBuffer spirv, TargetLanguage target) {
|
||||
return TranspileResult._(
|
||||
t.src.toString(),
|
||||
t.uniformFloatCount,
|
||||
t.samplerCount,
|
||||
target,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@ const int _decorationLocation = 30;
|
||||
// Explicitly supported builtin types
|
||||
const int _builtinFragCoord = 15;
|
||||
|
||||
// Explicitly supported dimensionalities
|
||||
const int _dim2D = 1;
|
||||
|
||||
// Ops that have no semantic meaning in output and can be safely ignored
|
||||
const int _opSource = 3;
|
||||
const int _opSourceExtension = 4;
|
||||
@@ -55,6 +58,8 @@ const int _opTypeInt = 21;
|
||||
const int _opTypeFloat = 22;
|
||||
const int _opTypeVector = 23;
|
||||
const int _opTypeMatrix = 24;
|
||||
const int _opTypeImage = 25;
|
||||
const int _opTypeSampledImage = 27;
|
||||
const int _opTypePointer = 32;
|
||||
const int _opTypeFunction = 33;
|
||||
const int _opConstantTrue = 41;
|
||||
@@ -74,6 +79,8 @@ const int _opDecorate = 71;
|
||||
const int _opVectorShuffle = 79;
|
||||
const int _opCompositeConstruct = 80;
|
||||
const int _opCompositeExtract = 81;
|
||||
const int _opImageSampleImplicitLod = 87;
|
||||
const int _opImageQuerySize = 104;
|
||||
const int _opConvertFToS = 110;
|
||||
const int _opConvertSToF = 111;
|
||||
const int _opFNegate = 127;
|
||||
|
||||
@@ -51,7 +51,7 @@ const String _mainFunctionName = 'main';
|
||||
/// https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpConstant
|
||||
class _Transpiler {
|
||||
_Transpiler(this.spirv, this.target) {
|
||||
out = src;
|
||||
out = header;
|
||||
}
|
||||
|
||||
final Uint32List spirv;
|
||||
@@ -60,6 +60,23 @@ class _Transpiler {
|
||||
/// The resulting source code of the target language is written to src.
|
||||
final StringBuffer src = StringBuffer();
|
||||
|
||||
/// Contains shader header, constants, and uniforms.
|
||||
final StringBuffer header = StringBuffer();
|
||||
|
||||
/// The main body of code, contains function definitions.
|
||||
final StringBuffer body = StringBuffer();
|
||||
|
||||
/// Uniform declarations.
|
||||
final Map<int, String> uniformDeclarations = <int, String>{};
|
||||
|
||||
/// Declarations for sampler sizes in SkSL.
|
||||
///
|
||||
/// This is because the SkSL eval function uses texel coordinates when
|
||||
/// sampling an ImageShader, and SkSL does not support the textureSize
|
||||
/// function. These uniforms allow adding support for normalized
|
||||
/// coordinates for [opImageSampleImplicitLod].
|
||||
final Map<int, String> samplerSizeDeclarations = <int, String>{};
|
||||
|
||||
/// ID mapped to numerical types.
|
||||
final Map<int, _Type> types = <int, _Type>{};
|
||||
|
||||
@@ -80,6 +97,9 @@ class _Transpiler {
|
||||
/// ID mapped to ID. Used by [OpLoad].
|
||||
final Map<int, int> alias = <int, int>{};
|
||||
|
||||
/// ID mapped to a string to use instead of a generated name.
|
||||
final Map<int, String> nameOverloads = <int, String>{};
|
||||
|
||||
/// The ID for a constant true value.
|
||||
/// See [opConstantTrue].
|
||||
int constantTrue = 0;
|
||||
@@ -113,6 +133,14 @@ class _Transpiler {
|
||||
/// See [opTypeFloat].
|
||||
int floatType = 0;
|
||||
|
||||
/// The ID of the image type.
|
||||
/// See [opTypeImage].
|
||||
int imageType = 0;
|
||||
|
||||
/// The ID of the sampledImage type.
|
||||
/// See [opTypeSampledImage].
|
||||
int sampledImageType = 0;
|
||||
|
||||
/// The ID of the function that is currently being defined.
|
||||
/// Set by [opFunction] and unset by [opFunctionEnd].
|
||||
int currentFunction = 0;
|
||||
@@ -131,9 +159,12 @@ class _Transpiler {
|
||||
/// Set by [opDecorate].
|
||||
int fragCoord = 0;
|
||||
|
||||
/// The number of floats used by uniform
|
||||
/// The number of floats used by uniforms.
|
||||
int uniformFloatCount = 0;
|
||||
|
||||
/// The number of samplers used by uniforms.
|
||||
int samplerCount = 0;
|
||||
|
||||
/// Current indentation to prepend to new lines.
|
||||
String indent = '';
|
||||
|
||||
@@ -147,6 +178,9 @@ class _Transpiler {
|
||||
void transpile() {
|
||||
parseHeader();
|
||||
writeHeader();
|
||||
|
||||
// Parse instructions and write to body.
|
||||
out = body;
|
||||
while (position < spirv.length) {
|
||||
final int lastPosition = position;
|
||||
parseInstruction();
|
||||
@@ -154,10 +188,33 @@ class _Transpiler {
|
||||
assert(position > lastPosition);
|
||||
}
|
||||
|
||||
src.writeln();
|
||||
// TODO(antrob): Investigate if `List<bool>.filled(maxFunctionId, false)` can be used here instead.
|
||||
final Set<int> visited = <int>{};
|
||||
writeFunctionAndDeps(visited, entryPoint);
|
||||
|
||||
// Add uniform declarations to header.
|
||||
if (uniformDeclarations.isNotEmpty) {
|
||||
header.writeln();
|
||||
final List<int> locations = uniformDeclarations.keys.toList();
|
||||
locations.sort((int a, int b) => a - b);
|
||||
for (final int location in locations) {
|
||||
header.writeln(uniformDeclarations[location]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add SkSL sampler size declarations to header.
|
||||
if (samplerSizeDeclarations.isNotEmpty) {
|
||||
header.writeln();
|
||||
final List<int> locations = samplerSizeDeclarations.keys.toList();
|
||||
locations.sort((int a, int b) => a - b);
|
||||
for (final int location in locations) {
|
||||
header.writeln(samplerSizeDeclarations[location]);
|
||||
}
|
||||
}
|
||||
|
||||
src.write(header);
|
||||
src.writeln();
|
||||
src.write(body);
|
||||
}
|
||||
|
||||
TranspileException failure(String why) =>
|
||||
@@ -171,19 +228,19 @@ class _Transpiler {
|
||||
for (final int dep in functionDeps[function]!) {
|
||||
writeFunctionAndDeps(visited, dep);
|
||||
}
|
||||
src.write(functionDefs[function]!.toString());
|
||||
out.write(functionDefs[function]!.toString());
|
||||
}
|
||||
|
||||
void writeHeader() {
|
||||
switch (target) {
|
||||
case TargetLanguage.glslES:
|
||||
src.writeln('#version 100\n');
|
||||
src.writeln('precision mediump float;\n');
|
||||
out.writeln('#version 100\n');
|
||||
out.writeln('precision mediump float;\n');
|
||||
break;
|
||||
case TargetLanguage.glslES300:
|
||||
src.writeln('#version 300 es\n');
|
||||
src.writeln('precision mediump float;\n');
|
||||
src.writeln('layout ( location = 0 ) out vec4 $_colorVariableName;\n');
|
||||
out.writeln('#version 300 es\n');
|
||||
out.writeln('precision mediump float;\n');
|
||||
out.writeln('layout ( location = 0 ) out vec4 $_colorVariableName;\n');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -193,11 +250,14 @@ class _Transpiler {
|
||||
String resolveName(int id) {
|
||||
if (alias.containsKey(id)) {
|
||||
return resolveName(alias[id]!);
|
||||
}
|
||||
if (nameOverloads.containsKey(id)) {
|
||||
return nameOverloads[id]!;
|
||||
} else if (constantTrue > 0 && id == constantTrue) {
|
||||
return 'true';
|
||||
} else if (constantFalse > 0 && id == constantFalse) {
|
||||
return 'false';
|
||||
} else if (id == colorOutput) {
|
||||
} if (id == colorOutput) {
|
||||
if (target == TargetLanguage.glslES) {
|
||||
return _glslESColorName;
|
||||
} else {
|
||||
@@ -259,6 +319,7 @@ class _Transpiler {
|
||||
out.writeln('$indent$type $name = $type($value);');
|
||||
}
|
||||
|
||||
|
||||
/// Read an instruction word, and handle the operation.
|
||||
///
|
||||
/// SPIR-V instructions contain an op-code as well as a
|
||||
@@ -309,6 +370,12 @@ class _Transpiler {
|
||||
case _opTypeMatrix:
|
||||
opTypeMatrix();
|
||||
break;
|
||||
case _opTypeImage:
|
||||
opTypeImage();
|
||||
break;
|
||||
case _opTypeSampledImage:
|
||||
opTypeSampledImage();
|
||||
break;
|
||||
case _opTypePointer:
|
||||
opTypePointer();
|
||||
break;
|
||||
@@ -369,6 +436,9 @@ class _Transpiler {
|
||||
case _opCompositeExtract:
|
||||
opCompositeExtract();
|
||||
break;
|
||||
case _opImageSampleImplicitLod:
|
||||
opImageSampleImplicitLod();
|
||||
break;
|
||||
case _opFNegate:
|
||||
opFNegate();
|
||||
break;
|
||||
@@ -557,6 +627,54 @@ class _Transpiler {
|
||||
types[id] = t;
|
||||
}
|
||||
|
||||
void opTypeImage() {
|
||||
if (imageType != 0) {
|
||||
throw failure('Image type was previously declared.');
|
||||
}
|
||||
final int id = readWord();
|
||||
final int sampledType = readWord();
|
||||
if (types[sampledType] != _Type.float) {
|
||||
throw failure('Sampled type must be float.');
|
||||
}
|
||||
final int dimensionality = readWord();
|
||||
if (dimensionality != _dim2D) {
|
||||
throw failure('Dimensionality must be 2D.');
|
||||
}
|
||||
final int depth = readWord();
|
||||
if (depth != 0) {
|
||||
throw failure('Depth must be 0.');
|
||||
}
|
||||
final int arrayed = readWord();
|
||||
if (arrayed != 0) {
|
||||
throw failure('Arrayed must be 0.');
|
||||
}
|
||||
final int multisampled = readWord();
|
||||
if (multisampled != 0) {
|
||||
throw failure('Multisampled must be 0.');
|
||||
}
|
||||
final int sampled = readWord();
|
||||
if (sampled != 1) {
|
||||
throw failure('Sampled must be 1.');
|
||||
}
|
||||
imageType = id;
|
||||
}
|
||||
|
||||
void opTypeSampledImage() {
|
||||
if (sampledImageType != 0) {
|
||||
throw failure('imageSampledType was previously declared.');
|
||||
}
|
||||
if (imageType == 0) {
|
||||
throw failure('imageType has not yet been declared.');
|
||||
}
|
||||
final int id = readWord();
|
||||
final int imgType = readWord();
|
||||
if (imgType != imageType) {
|
||||
throw failure('Invalid image type.');
|
||||
}
|
||||
sampledImageType = id;
|
||||
types[id] = _Type.sampledImage;
|
||||
}
|
||||
|
||||
void opTypePointer() {
|
||||
final int id = readWord();
|
||||
// ignore storage class
|
||||
@@ -580,14 +698,12 @@ class _Transpiler {
|
||||
}
|
||||
|
||||
void opConstantTrue() {
|
||||
// Skip type operand.
|
||||
position++;
|
||||
position++; // Skip type operand.
|
||||
constantTrue = readWord();
|
||||
}
|
||||
|
||||
void opConstantFalse() {
|
||||
// Skip type operand.
|
||||
position++;
|
||||
position++; // Skip type operand.
|
||||
constantFalse = readWord();
|
||||
}
|
||||
|
||||
@@ -604,21 +720,21 @@ class _Transpiler {
|
||||
valueString = '$v';
|
||||
}
|
||||
final String typeName = resolveType(type);
|
||||
src.writeln('const $typeName $id = $valueString;');
|
||||
header.writeln('const $typeName $id = $valueString;');
|
||||
}
|
||||
|
||||
void opConstantComposite() {
|
||||
final String type = resolveType(readWord());
|
||||
final String id = resolveName(readWord());
|
||||
src.write('const $type $id = $type(');
|
||||
header.write('const $type $id = $type(');
|
||||
final int count = nextPosition - position;
|
||||
for (int i = 0; i < count; i++) {
|
||||
src.write(resolveName(readWord()));
|
||||
header.write(resolveName(readWord()));
|
||||
if (i < count - 1) {
|
||||
src.write(', ');
|
||||
header.write(', ');
|
||||
}
|
||||
}
|
||||
src.writeln(');');
|
||||
header.writeln(');');
|
||||
}
|
||||
|
||||
void opFunction() {
|
||||
@@ -685,7 +801,7 @@ class _Transpiler {
|
||||
// Remove trailing two space characters, if present.
|
||||
indent = indent.substring(0, max(0, indent.length - 2));
|
||||
currentFunction = 0;
|
||||
out = src;
|
||||
out = body;
|
||||
currentFunctionType = null;
|
||||
}
|
||||
|
||||
@@ -721,16 +837,27 @@ class _Transpiler {
|
||||
|
||||
switch (storageClass) {
|
||||
case _storageClassUniformConstant:
|
||||
if (target == TargetLanguage.glslES300) {
|
||||
final String location = locations[id].toString();
|
||||
src.write('layout ( location = $location ) ');
|
||||
int? location = locations[id];
|
||||
if (location == null) {
|
||||
throw failure('$id had no location specified');
|
||||
}
|
||||
src.writeln('uniform $type $name;');
|
||||
String prefix = '';
|
||||
if (target == TargetLanguage.glslES300) {
|
||||
prefix = 'layout ( location = $location ) ';
|
||||
}
|
||||
uniformDeclarations[location] = '${prefix}uniform $type $name;';
|
||||
final _Type? t = types[typeId];
|
||||
if (t == null) {
|
||||
throw failure('$typeId is not a defined type');
|
||||
}
|
||||
uniformFloatCount += _typeFloatCounts[t]!;
|
||||
if (t == _Type.sampledImage) {
|
||||
samplerCount++;
|
||||
if (target == TargetLanguage.sksl) {
|
||||
samplerSizeDeclarations[location] = 'uniform half2 ${name}_size;';
|
||||
}
|
||||
} else {
|
||||
uniformFloatCount += _typeFloatCounts[t]!;
|
||||
}
|
||||
return;
|
||||
case _storageClassInput:
|
||||
return;
|
||||
@@ -772,7 +899,7 @@ class _Transpiler {
|
||||
|
||||
void opAccessChain() {
|
||||
final String type = resolveType(readWord());
|
||||
final String name = resolveName(readWord());
|
||||
final int id = readWord();
|
||||
final String base = resolveName(readWord());
|
||||
|
||||
// opAccessChain currently only supports indexed access.
|
||||
@@ -780,13 +907,13 @@ class _Transpiler {
|
||||
// Currently, structs will be caught before this method is called,
|
||||
// since using the instruction to define a struct type will throw
|
||||
// an exception.
|
||||
out.write('$indent$type $name = $base');
|
||||
String overload = base;
|
||||
final int count = nextPosition - position;
|
||||
for (int i = 0; i < count; i++) {
|
||||
final String index = resolveName(readWord());
|
||||
out.write('[$index]');
|
||||
overload += '[$index]';
|
||||
}
|
||||
out.writeln(';');
|
||||
nameOverloads[id] = overload;
|
||||
}
|
||||
|
||||
void opDecorate() {
|
||||
@@ -853,6 +980,18 @@ class _Transpiler {
|
||||
out.writeln(';');
|
||||
}
|
||||
|
||||
void opImageSampleImplicitLod() {
|
||||
final String type = resolveType(readWord());
|
||||
final String name = resolveName(readWord());
|
||||
final String sampledImage = resolveName(readWord());
|
||||
final String coordinate = resolveName(readWord());
|
||||
if (target == TargetLanguage.sksl) {
|
||||
out.writeln('$indent$type $name = $sampledImage.eval(${sampledImage}_size * $coordinate);');
|
||||
} else {
|
||||
out.writeln('$indent$type $name = texture($sampledImage, $coordinate);');
|
||||
}
|
||||
}
|
||||
|
||||
void opFNegate() {
|
||||
final String type = resolveType(readWord());
|
||||
final String name = resolveName(readWord());
|
||||
|
||||
@@ -15,6 +15,7 @@ enum _Type {
|
||||
float2x2,
|
||||
float3x3,
|
||||
float4x4,
|
||||
sampledImage,
|
||||
}
|
||||
|
||||
class _FunctionType {
|
||||
@@ -47,6 +48,7 @@ const Map<_Type, String> _skslTypeNames = <_Type, String>{
|
||||
_Type.float2x2: 'float2x2',
|
||||
_Type.float3x3: 'float3x3',
|
||||
_Type.float4x4: 'float4x4',
|
||||
_Type.sampledImage: 'shader',
|
||||
};
|
||||
|
||||
const Map<_Type, String> _glslTypeNames = <_Type, String>{
|
||||
@@ -60,6 +62,7 @@ const Map<_Type, String> _glslTypeNames = <_Type, String>{
|
||||
_Type.float2x2: 'mat2',
|
||||
_Type.float3x3: 'mat3',
|
||||
_Type.float4x4: 'mat4',
|
||||
_Type.sampledImage: 'sampler2D',
|
||||
};
|
||||
|
||||
const Map<_Type, int> _typeFloatCounts = <_Type, int>{
|
||||
|
||||
@@ -10,6 +10,16 @@ if (enable_unittests) {
|
||||
tool = "//flutter/lib/spirv/test:spirv_assembler"
|
||||
|
||||
sources = [
|
||||
"image_type_arrayed_must_be_zero.spvasm",
|
||||
"image_type_depth_must_be_zero.spvasm",
|
||||
"image_type_dimensionality_must_be_2D.spvasm",
|
||||
"image_type_multisampled_must_be_zero.spvasm",
|
||||
"image_type_must_be_float.spvasm",
|
||||
"image_type_previously_declared.spvasm",
|
||||
"image_type_sampled_must_be_one.spvasm",
|
||||
"sampled_image_type_image_type_not_declared.spvasm",
|
||||
"sampled_image_type_invalid_image_type.spvasm",
|
||||
"sampled_image_type_previously_declared.spvasm",
|
||||
"unassigned_function_type.spvasm",
|
||||
"unassigned_pointer_type.spvasm",
|
||||
"unassigned_type.spvasm",
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 28
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 43 contains a non-zero-arrayed image type.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 2D 0 1 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 28
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 43 contains a non-zero-depth image type.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 2D 1 0 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 28
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 43 contains a non-2D image type.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 3D 0 0 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 28
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 43 contains a non-zero-multisampled image type.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 2D 0 0 1 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 28
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 43 contains a non-float image type.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %void 2D 0 0 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 29
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 45 contains a second OpTypeImage declaration.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%28 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 28
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 43 contains an image type with 'sampled' not set to one.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 2D 0 0 0 0 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 29
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 43 contains an OpTypeSampledImage before OpImageType has been declared.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%22 = OpTypeSampledImage %21
|
||||
%21 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 29
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 44 contains an OpTypeSampledImage with an invalid image type.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %float
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
; Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
; Use of this source code is governed by a BSD-style license that can be
|
||||
; found in the LICENSE file.
|
||||
;
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 8
|
||||
; Bound: 29
|
||||
; Schema: 0
|
||||
;
|
||||
; Line 45 contains a second OpTypeSampledImage declaration.
|
||||
;
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragCoord %oColor
|
||||
OpExecutionMode %main OriginLowerLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %uv "uv"
|
||||
OpName %gl_FragCoord "gl_FragCoord"
|
||||
OpName %iResolution "iResolution"
|
||||
OpName %oColor "oColor"
|
||||
OpName %iImage "iImage"
|
||||
OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
OpDecorate %iResolution Location 1
|
||||
OpDecorate %oColor Location 0
|
||||
OpDecorate %iImage Location 0
|
||||
OpDecorate %iImage DescriptorSet 0
|
||||
OpDecorate %iImage Binding 0
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v2float = OpTypeVector %float 2
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_UniformConstant_v2float = OpTypePointer UniformConstant %v2float
|
||||
%iResolution = OpVariable %_ptr_UniformConstant_v2float UniformConstant
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%oColor = OpVariable %_ptr_Output_v4float Output
|
||||
%21 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||
%22 = OpTypeSampledImage %21
|
||||
%28 = OpTypeSampledImage %21
|
||||
%_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
|
||||
%iImage = OpVariable %_ptr_UniformConstant_22 UniformConstant
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%uv = OpVariable %_ptr_Function_v2float Function
|
||||
%13 = OpLoad %v4float %gl_FragCoord
|
||||
%14 = OpVectorShuffle %v2float %13 %13 0 1
|
||||
%17 = OpLoad %v2float %iResolution
|
||||
%18 = OpFDiv %v2float %14 %17
|
||||
OpStore %uv %18
|
||||
%25 = OpLoad %22 %iImage
|
||||
%26 = OpLoad %v2float %uv
|
||||
%27 = OpImageSampleImplicitLod %v4float %25 %26
|
||||
OpStore %oColor %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
|
||||
@@ -10,6 +10,8 @@ if (enable_unittests) {
|
||||
tool = "//flutter/lib/spirv/test:glsl_to_spirv"
|
||||
|
||||
sources = [
|
||||
"blue_green_sampler.glsl",
|
||||
"children_and_uniforms.glsl",
|
||||
"functions.glsl",
|
||||
"simple.glsl",
|
||||
"uniforms.glsl",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#version 320 es
|
||||
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
precision highp float;
|
||||
|
||||
layout ( location = 0 ) out vec4 oColor;
|
||||
|
||||
layout ( location = 0 ) uniform sampler2D iChild;
|
||||
|
||||
void main() {
|
||||
// iChild1 is an image that is half blue, half green,
|
||||
// so oColor should be set to vec2(0, 1, 0, 1)
|
||||
oColor = texture(iChild, vec2(1, 0));
|
||||
oColor.a = 1.0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#version 320 es
|
||||
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
precision highp float;
|
||||
|
||||
layout ( location = 0 ) out vec4 color;
|
||||
|
||||
layout ( location = 0 ) uniform sampler2D child1;
|
||||
layout ( location = 1 ) uniform float a;
|
||||
layout ( location = 2 ) uniform sampler2D child2;
|
||||
layout ( location = 3 ) uniform float b;
|
||||
|
||||
void main() {
|
||||
// child1 is a 10x10 image where the left half is blue and the right
|
||||
// half is green, and b should be 1, so c1 should be vec4(0, 1, 0, 1)
|
||||
vec4 c1 = texture(child1, vec2(b, 0));
|
||||
|
||||
// child2 only contains vec4(0, 1, 0, 1).
|
||||
vec4 c2 = texture(child2, vec2(0));
|
||||
|
||||
color = c1 * c2;
|
||||
}
|
||||
|
||||
@@ -3787,16 +3787,15 @@ class FragmentProgram extends NativeFieldWrapperClass1 {
|
||||
);
|
||||
_init(result.src, debugPrint);
|
||||
_uniformFloatCount = result.uniformFloatCount;
|
||||
_samplerCount = result.samplerCount;
|
||||
}
|
||||
|
||||
late final int _uniformFloatCount;
|
||||
late final int _samplerCount;
|
||||
|
||||
void _constructor() native 'FragmentProgram_constructor';
|
||||
void _init(String sksl, bool debugPrint) native 'FragmentProgram_init';
|
||||
|
||||
// TODO(chriscraws): Add `List<ImageShader>? children` as a parameter to [build].
|
||||
// https://github.com/flutter/flutter/issues/85240
|
||||
|
||||
/// Constructs a [Shader] object suitable for use by [Paint.shader] with
|
||||
/// the given uniforms.
|
||||
///
|
||||
@@ -3831,24 +3830,51 @@ class FragmentProgram extends NativeFieldWrapperClass1 {
|
||||
/// c: [4, 5, 6]
|
||||
/// d: [7, 8, 9, 10] // 2x2 matrix in column-major order
|
||||
///
|
||||
/// `imageSamplers` must also be sized correctly, matching the number of UniformConstant
|
||||
/// variables of type SampledImage specified in the SPIR-V code.
|
||||
///
|
||||
/// Consider the following snippit of GLSL code.
|
||||
///
|
||||
/// ```
|
||||
/// layout (location = 0) uniform sampler2D a;
|
||||
/// layout (location = 1) uniform sampler2D b;
|
||||
/// ```
|
||||
///
|
||||
/// After being compiled to SPIR-V `imageSamplers` must have a length
|
||||
/// of 2.
|
||||
///
|
||||
/// Once a [Shader] is built, uniform values cannot be changed. Instead,
|
||||
/// [shader] must be called again with new uniform values.
|
||||
Shader shader({
|
||||
Float32List? floatUniforms,
|
||||
List<ImageShader>? samplerUniforms,
|
||||
}) {
|
||||
if (floatUniforms == null) {
|
||||
floatUniforms = Float32List(_uniformFloatCount);
|
||||
}
|
||||
if (floatUniforms.length != _uniformFloatCount) {
|
||||
throw ArgumentError(
|
||||
'FragmentShader floatUniforms size: ${floatUniforms.length} must match given shader uniform count: $_uniformFloatCount.');
|
||||
'floatUniforms size: ${floatUniforms.length} must match given shader uniform count: $_uniformFloatCount.');
|
||||
}
|
||||
final _FragmentShader shader = _FragmentShader(this, Float32List.fromList(floatUniforms));
|
||||
_shader(shader, floatUniforms);
|
||||
if (_samplerCount > 0 && (samplerUniforms == null || samplerUniforms.length != _samplerCount)) {
|
||||
throw ArgumentError('samplerUniforms must have length $_samplerCount');
|
||||
}
|
||||
if (samplerUniforms == null) {
|
||||
samplerUniforms = <ImageShader>[];
|
||||
} else {
|
||||
samplerUniforms = <ImageShader>[...samplerUniforms];
|
||||
}
|
||||
final _FragmentShader shader = _FragmentShader(
|
||||
this, Float32List.fromList(floatUniforms), samplerUniforms);
|
||||
_shader(shader, floatUniforms, samplerUniforms);
|
||||
return shader;
|
||||
}
|
||||
|
||||
void _shader(_FragmentShader shader, Float32List floatUniforms) native 'FragmentProgram_shader';
|
||||
void _shader(
|
||||
_FragmentShader shader,
|
||||
Float32List floatUniforms,
|
||||
List<ImageShader> samplerUniforms,
|
||||
) native 'FragmentProgram_shader';
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
@@ -3857,10 +3883,15 @@ class _FragmentShader extends Shader {
|
||||
/// or extended directly.
|
||||
///
|
||||
/// To create a [_FragmentShader], use a [FragmentProgram].
|
||||
_FragmentShader(this._builder, this._floatUniforms) : super._();
|
||||
_FragmentShader(
|
||||
this._builder,
|
||||
this._floatUniforms,
|
||||
this._samplerUniforms,
|
||||
) : super._();
|
||||
|
||||
final FragmentProgram _builder;
|
||||
final Float32List _floatUniforms;
|
||||
final List<ImageShader> _samplerUniforms;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
@@ -3870,11 +3901,12 @@ class _FragmentShader extends Shader {
|
||||
return false;
|
||||
return other is _FragmentShader
|
||||
&& other._builder == _builder
|
||||
&& _listEquals<double>(other._floatUniforms, _floatUniforms);
|
||||
&& _listEquals<double>(other._floatUniforms, _floatUniforms)
|
||||
&& _listEquals<ImageShader>(other._samplerUniforms, _samplerUniforms);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(_builder, hashList(_floatUniforms));
|
||||
int get hashCode => hashValues(_builder, hashList(_floatUniforms), hashList(_samplerUniforms));
|
||||
}
|
||||
|
||||
/// Defines how a list of points is interpreted when drawing a set of triangles.
|
||||
|
||||
@@ -55,11 +55,33 @@ void FragmentProgram::init(std::string sksl, bool debugPrintSksl) {
|
||||
|
||||
fml::RefPtr<FragmentShader> FragmentProgram::shader(
|
||||
Dart_Handle shader,
|
||||
const tonic::Float32List& uniforms) {
|
||||
auto sk_shader = runtime_effect_->makeShader(
|
||||
SkData::MakeWithCopy(uniforms.data(),
|
||||
uniforms.num_elements() * sizeof(float)),
|
||||
0, 0, nullptr, false);
|
||||
const tonic::Float32List& uniforms,
|
||||
Dart_Handle samplers) {
|
||||
auto sampler_shaders =
|
||||
tonic::DartConverter<std::vector<ImageShader*>>::FromDart(samplers);
|
||||
size_t uniform_count = uniforms.num_elements();
|
||||
size_t uniform_data_size =
|
||||
(uniform_count + 2 * sampler_shaders.size()) * sizeof(float);
|
||||
sk_sp<SkData> uniform_data = SkData::MakeUninitialized(uniform_data_size);
|
||||
// uniform_floats must only be referenced BEFORE the call to makeShader below.
|
||||
auto* uniform_floats =
|
||||
reinterpret_cast<float*>(uniform_data->writable_data());
|
||||
for (size_t i = 0; i < uniform_count; i++) {
|
||||
uniform_floats[i] = uniforms[i];
|
||||
}
|
||||
std::vector<sk_sp<SkShader>> sk_samplers(sampler_shaders.size());
|
||||
for (size_t i = 0; i < sampler_shaders.size(); i++) {
|
||||
ImageShader* image_shader = sampler_shaders[i];
|
||||
// The default value for SkSamplingOptions is used because ImageShader
|
||||
// uses a cached value set by the user in the Dart constructor.
|
||||
// Users are instructed to make use of this in the Dart docs.
|
||||
sk_samplers[i] = image_shader->shader(SkSamplingOptions());
|
||||
uniform_floats[uniform_count + 2 * i] = image_shader->width();
|
||||
uniform_floats[uniform_count + 2 * i + 1] = image_shader->height();
|
||||
}
|
||||
auto sk_shader =
|
||||
runtime_effect_->makeShader(std::move(uniform_data), sk_samplers.data(),
|
||||
sk_samplers.size(), nullptr, false);
|
||||
return FragmentShader::Create(shader, std::move(sk_shader));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ class FragmentProgram : public RefCountedDartWrappable<FragmentProgram> {
|
||||
void init(std::string sksl, bool debugPrintSksl);
|
||||
|
||||
fml::RefPtr<FragmentShader> shader(Dart_Handle shader,
|
||||
const tonic::Float32List& uniforms);
|
||||
const tonic::Float32List& uniforms,
|
||||
Dart_Handle samplers);
|
||||
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
|
||||
|
||||
@@ -70,6 +70,14 @@ sk_sp<SkShader> ImageShader::shader(SkSamplingOptions sampling) {
|
||||
return cached_shader_.skia_object();
|
||||
}
|
||||
|
||||
int ImageShader::width() {
|
||||
return sk_image_.skia_object()->width();
|
||||
}
|
||||
|
||||
int ImageShader::height() {
|
||||
return sk_image_.skia_object()->height();
|
||||
}
|
||||
|
||||
ImageShader::ImageShader() = default;
|
||||
|
||||
ImageShader::~ImageShader() = default;
|
||||
|
||||
@@ -38,6 +38,9 @@ class ImageShader : public Shader {
|
||||
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
|
||||
int width();
|
||||
int height();
|
||||
|
||||
private:
|
||||
ImageShader();
|
||||
|
||||
|
||||
@@ -812,6 +812,7 @@ class FragmentProgram {
|
||||
FragmentProgram._();
|
||||
|
||||
Shader shader({
|
||||
required Float32List floatUniforms,
|
||||
Float32List? floatUniforms,
|
||||
List<ImageShader>? samplerUniforms,
|
||||
}) => throw UnsupportedError('FragmentProgram is not supported for the CanvasKit or HTML renderers.');
|
||||
}
|
||||
|
||||
@@ -45,6 +45,21 @@ void main() {
|
||||
_expectShaderRendersGreen(shader);
|
||||
});
|
||||
|
||||
test('blue-green image renders green', () async {
|
||||
final ByteBuffer spirv = spvFile('general_shaders', 'blue_green_sampler.spv').readAsBytesSync().buffer;
|
||||
final FragmentProgram program = await FragmentProgram.compile(
|
||||
debugPrint: true,
|
||||
spirv: spirv,
|
||||
);
|
||||
final Image blueGreenImage = await _createBlueGreenImage();
|
||||
final ImageShader imageShader = ImageShader(
|
||||
blueGreenImage, TileMode.clamp, TileMode.clamp, _identityMatrix);
|
||||
final Shader shader = program.shader(
|
||||
samplerUniforms: <ImageShader>[imageShader],
|
||||
);
|
||||
await _expectShaderRendersGreen(shader);
|
||||
});
|
||||
|
||||
test('shader with uniforms renders correctly', () async {
|
||||
final Uint8List shaderBytes = await spvFile('general_shaders', 'uniforms.spv').readAsBytes();
|
||||
final FragmentProgram program = await FragmentProgram.compile(spirv: shaderBytes.buffer);
|
||||
@@ -236,6 +251,7 @@ Map<String, ByteBuffer> _loadSpv(String leafFolderName) {
|
||||
const int _shaderImageDimension = 4;
|
||||
|
||||
const Color _greenColor = Color(0xFF00FF00);
|
||||
const Color _blueColor = Color(0xFF0000FF);
|
||||
|
||||
// Precision for checking uniform values.
|
||||
const double epsilon = 0.5 / 255.0;
|
||||
@@ -244,3 +260,43 @@ const double epsilon = 0.5 / 255.0;
|
||||
double toFloat(int v) => v.toDouble() / 255.0;
|
||||
|
||||
String toHexString(int color) => '#${color.toRadixString(16)}';
|
||||
|
||||
// 10x10 image where the left half is blue and the right half is
|
||||
// green.
|
||||
Future<Image> _createBlueGreenImage() async {
|
||||
final int length = 10;
|
||||
final int bytesPerPixel = 4;
|
||||
final Uint8List pixels = Uint8List(length * length * bytesPerPixel);
|
||||
int i = 0;
|
||||
for (int y = 0; y < length; y++) {
|
||||
for (int x = 0; x < length; x++) {
|
||||
if (x < length/2) {
|
||||
pixels[i+2] = 0xFF; // blue channel
|
||||
} else {
|
||||
pixels[i+1] = 0xFF; // green channel
|
||||
}
|
||||
pixels[i+3] = 0xFF; // alpha channel
|
||||
i += bytesPerPixel;
|
||||
}
|
||||
}
|
||||
final ImageDescriptor descriptor = ImageDescriptor.raw(
|
||||
await ImmutableBuffer.fromUint8List(pixels),
|
||||
width: length,
|
||||
height: length,
|
||||
pixelFormat: PixelFormat.rgba8888,
|
||||
);
|
||||
final Codec codec = await descriptor.instantiateCodec();
|
||||
final FrameInfo frame = await codec.getNextFrame();
|
||||
return frame.image;
|
||||
}
|
||||
|
||||
// A single uniform with value 1.
|
||||
final Float32List _singleUniform = Float32List.fromList(<double>[1]);
|
||||
|
||||
final Float64List _identityMatrix = Float64List.fromList(<double>[
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user