Add .stage output to skslc for runtime effects

This emits SkSL that is more-or-less what the compiler re-ingests when a
runtime effect is used to create a GrFragmentProcessor.

Change-Id: I0926be44fc4493e722a5edc18198e161e4192cde
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/367883
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Brian Osman 2021-02-08 13:49:53 -05:00 committed by Skia Commit-Bot
parent cb208d4c1f
commit 62b039b36d
15 changed files with 211 additions and 4 deletions

View File

@ -570,6 +570,7 @@ if (skia_compile_processors || skia_compile_sksl_tests) {
"src/core/SkVM.cpp",
"src/gpu/GrBlockAllocator.cpp",
"src/gpu/GrMemoryPool.cpp",
"src/gpu/GrShaderUtils.cpp",
"src/ports/SkMemory_malloc.cpp",
"src/ports/SkOSFile_stdio.cpp",
"src/sksl/SkSLMain.cpp",
@ -781,6 +782,12 @@ if (skia_compile_sksl_tests) {
lang = "--skvm"
settings = "--settings"
}
compile_sksl("stage_tests") {
sources = sksl_stage_tests_sources
outExtensions = [ ".stage" ]
lang = "--stage"
settings = "--settings"
}
compile_sksl("spirv_tests") {
sources = sksl_spirv_tests_sources
outExtensions = [ ".asm.frag" ]

View File

@ -96,8 +96,12 @@ for input, targetDir in pairwise(inputs):
worklist.write(input + "\n")
worklist.write(target + ".skvm\n")
worklist.write(settings + "\n\n")
elif lang == "--stage":
worklist.write(input + "\n")
worklist.write(target + ".stage\n")
worklist.write(settings + "\n\n")
else:
sys.exit("### Expected one of: --fp --glsl --metal --spirv --skvm, got " + lang)
sys.exit("### Expected one of: --fp --glsl --metal --spirv --skvm --stage, got " + lang)
# Compile items one at a time.
if not batchCompile:

View File

@ -574,3 +574,7 @@ sksl_spirv_tests_sources =
## Tests in sksl_skvm_tests_sources will be compiled with --settings on, and are expected to
## generate a .skvm output file.
sksl_skvm_tests_sources = sksl_rte_tests + sksl_rte_error_tests
## Tests in sksl_stage_tests_sources will be compiled with --settings on, and are expected to
## generate a .stage output file.
sksl_stage_tests_sources = sksl_rte_tests

View File

@ -9,10 +9,12 @@
#include "src/opts/SkChecksum_opts.h"
#include "src/opts/SkVM_opts.h"
#include "src/gpu/GrShaderUtils.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLDehydrator.h"
#include "src/sksl/SkSLFileOutputStream.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/SkSLVMGenerator.h"
@ -397,6 +399,44 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
builder.done().dump(redirect.get());
return true;
});
} else if (outputPath.endsWith(".stage")) {
return compileProgram(SkSL::Compiler::kNone_Flags,
[](SkSL::Compiler&, SkSL::Program& program, SkSL::OutputStream& out) {
class Callbacks : public SkSL::PipelineStage::Callbacks {
public:
using String = SkSL::String;
String declareUniform(const SkSL::VarDeclaration* decl) override {
fOutput += decl->description();
if (decl->var().type().name() == "fragmentProcessor") {
fChildNames.push_back(decl->var().name());
}
return decl->var().name();
}
String defineFunction(const SkSL::FunctionDeclaration* decl,
String body) override {
fOutput += (decl->description() + "{" + body + "}");
return decl->name();
}
String sampleChild(int index, String coords) override {
return String::printf("sample(%s%s%s)", fChildNames[index].c_str(),
coords.empty() ? "" : ", ", coords.c_str());
}
String sampleChildWithMatrix(int index, String matrix) override {
return String::printf("sample(%s%s%s)", fChildNames[index].c_str(),
matrix.empty() ? "" : ", ", matrix.c_str());
}
String fOutput;
std::vector<String> fChildNames;
};
Callbacks callbacks;
SkSL::PipelineStage::ConvertProgram(program, "_coords", &callbacks);
out.writeString(GrShaderUtils::PrettyPrint(callbacks.fOutput));
return true;
});
} else if (outputPath.endsWith(".dehydrated.sksl")) {
SkSL::FileOutputStream out(outputPath);
SkSL::Compiler compiler(caps);

View File

@ -32,7 +32,7 @@
#include <unordered_map>
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#if defined(SKSL_STANDALONE) || SK_SUPPORT_GPU
namespace SkSL {
namespace PipelineStage {

View File

@ -10,8 +10,7 @@
#include "src/sksl/SkSLString.h"
// TODO: This can now be used in SKSL_STANDALONE, with shim code for all of the callbacks.
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#if defined(SKSL_STANDALONE) || SK_SUPPORT_GPU
namespace SkSL {

View File

@ -0,0 +1,26 @@
uniform float u1[4];
uniform float u2[4];
uniform float u3[4];
uniform float u4[16];
float4 main()
{
float _2_sum = 0.0;
for (int _3_i = 3;_3_i >= 0; --_3_i)
{
_2_sum += u2[_3_i];
}
float _5_prod = 1.0;
for (int _6_i = 0;_6_i < 4; ++_6_i)
{
_5_prod *= u3[_6_i < 2 ? 0 : _6_i];
}
float _8_sum = 0.0;
for (float _9_f = -2.2999999523162842;_9_f < 17.0; _9_f += 3.7000000476837158)
{
if (_9_f > 0.0 && _9_f < 16.0)
{
_8_sum -= u4[int(_9_f)];
}
}
return half4(float4(u1[0], _2_sum, _5_prod, _8_sum));
}

View File

@ -0,0 +1,9 @@
uniform half f;
uniform int i;
uniform bool b;
half4 main()
{
half x = bool(f) ? half(b) : half(i);
int y = bool(i) ? int(b) : int(f);
return half4(half4(x) * half(y));
}

View File

@ -0,0 +1,38 @@
float return_loop()
{
for (float i = 0.0;i < 10.0; ++i)
{
if (i == 5.0)
{
return i;
}
}
return 0.0;
}
half4 main()
{
float _1_sum = 0.0;
for (float _2_i = 0.0;_2_i < 10.0; ++_2_i)
{
if (_2_i < 5.0)
{
continue;
}
_1_sum += _2_i;
}
float _4_sum = 0.0;
for (float _5_i = 0.0;_5_i < 10.0; ++_5_i)
{
if (_5_i > 5.0)
{
break;
}
_4_sum += _5_i;
}
float _7_sum = 0.0;
for (float _8_i = 0.12300000339746475;_8_i < 0.60000002384185791; _8_i += 0.11100000143051147)
{
_7_sum += _8_i;
}
return half4(half4(half(return_loop()), half(_1_sum), half(_4_sum), half(_7_sum)));
}

View File

@ -0,0 +1,33 @@
int return_loop()
{
for (int i = 0;i < 10; ++i)
{
if (i == 5)
{
return i;
}
}
return 0;
}
half4 main()
{
int _1_sum = 0;
for (int _2_i = 0;_2_i < 10; ++_2_i)
{
if (_2_i < 5)
{
continue;
}
_1_sum += _2_i;
}
int _4_sum = 0;
for (int _5_i = 0;_5_i < 10; ++_5_i)
{
if (_5_i > 5)
{
break;
}
_4_sum += _5_i;
}
return half4(half4(half(return_loop()), half(_1_sum), half(_4_sum), 1.0));
}

View File

@ -0,0 +1,5 @@
uniform fragmentProcessor child;
half4 main()
{
return half4(sample(child, float3x3(2.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)));
}

View File

@ -0,0 +1,5 @@
uniform fragmentProcessor child;
half4 main(float2 p)
{
return half4(sample(child, _coords.yx));
}

View File

@ -0,0 +1,6 @@
uniform fragmentProcessor child;
uniform float3x3 matrix;
half4 main()
{
return half4(sample(child, matrix));
}

View File

@ -0,0 +1,6 @@
uniform fragmentProcessor child;
half4 main()
{
float x = sqrt(1.0);
return half4(sample(child, float3x3(x, 0.0, 0.0, 0.0, x, 0.0, 0.0, 0.0, 1.0)));
}

View File

@ -0,0 +1,25 @@
uniform float4 u1;
uniform float4 u2;
uniform float4 u3;
uniform float4 u4;
float index_clamped_out_of_bounds()
{
for (int i = 7;i < 8; i++)
{
return u4[i];
}
}
float4 main()
{
float _2_sum = 0.0;
for (int _3_i = 0;_3_i < 4; ++_3_i)
{
_2_sum += u2[_3_i];
}
float _5_prod = 1.0;
for (int _6_i = 0;_6_i < 4; ++_6_i)
{
_5_prod *= u3[_6_i < 2 ? 0 : _6_i];
}
return half4(float4(u1.x, _2_sum, _5_prod, index_clamped_out_of_bounds()));
}