Move ProgramKind and ProgramSettings types out of SkSL::Program.

This change will allow these types to be forward-declared; C++ doesn't
allow forward declaration of types declared inside a struct. Moving
these types out of Programs resulted in a large diff.

The Settings::Value helper class has been moved inside of the
IRGenerator. In practice, it was actually just an implementation detail
of how IRGenerator looks up caps-values by name. It seems very unlikely
that this will be necessary elsewhere going forward.

Change-Id: I6119417fae608f1c492a27de746d2b550ef8ca20
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/370836
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2021-02-16 13:29:15 -05:00
parent ff0cd8c506
commit dbd4e6f0c0
43 changed files with 283 additions and 279 deletions

View File

@ -79,7 +79,7 @@ protected:
void onDraw(int loops, SkCanvas* canvas) override {
for (int i = 0; i < loops; i++) {
std::unique_ptr<SkSL::Program> program = fCompiler.convertProgram(
SkSL::Program::kFragment_Kind,
SkSL::ProgramKind::kFragment,
fSrc,
fSettings);
if (fCompiler.errorCount()) {
@ -124,8 +124,7 @@ protected:
}
void onDelayedSetup() override {
SkSL::ParsedModule module = fCompiler.moduleForProgramKind(
SkSL::Program::Kind::kFragment_Kind);
SkSL::ParsedModule module = fCompiler.moduleForProgramKind(SkSL::ProgramKind::kFragment);
fCompiler.irGenerator().setSymbolTable(module.fSymbols);
}
@ -584,8 +583,8 @@ void RunSkSLMemoryBenchmarks(NanoJSONResultsWriter* log) {
int before = heap_bytes_used();
GrShaderCaps caps(GrContextOptions{});
SkSL::Compiler compiler(&caps);
compiler.moduleForProgramKind(SkSL::Program::kVertex_Kind);
compiler.moduleForProgramKind(SkSL::Program::kFragment_Kind);
compiler.moduleForProgramKind(SkSL::ProgramKind::kVertex);
compiler.moduleForProgramKind(SkSL::ProgramKind::kFragment);
int after = heap_bytes_used();
bench("sksl_compiler_gpu", after - before);
}
@ -595,7 +594,7 @@ void RunSkSLMemoryBenchmarks(NanoJSONResultsWriter* log) {
int before = heap_bytes_used();
GrShaderCaps caps(GrContextOptions{});
SkSL::Compiler compiler(&caps);
compiler.moduleForProgramKind(SkSL::Program::kRuntimeEffect_Kind);
compiler.moduleForProgramKind(SkSL::ProgramKind::kRuntimeEffect);
int after = heap_bytes_used();
bench("sksl_compiler_runtimeeffect", after - before);
}

View File

@ -16,7 +16,7 @@ bool FuzzSKSL2GLSL(sk_sp<SkData> bytes) {
SkSL::String output;
SkSL::Program::Settings settings;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kFragment_Kind,
SkSL::ProgramKind::kFragment,
SkSL::String((const char*) bytes->data(),
bytes->size()),
settings);

View File

@ -16,7 +16,7 @@ bool FuzzSKSL2Metal(sk_sp<SkData> bytes) {
SkSL::String output;
SkSL::Program::Settings settings;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kFragment_Kind,
SkSL::ProgramKind::kFragment,
SkSL::String((const char*) bytes->data(),
bytes->size()),
settings);

View File

@ -18,7 +18,7 @@ bool FuzzSKSL2Pipeline(sk_sp<SkData> bytes) {
SkSL::Compiler compiler(caps.get());
SkSL::Program::Settings settings;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kRuntimeEffect_Kind,
SkSL::ProgramKind::kRuntimeEffect,
SkSL::String((const char*) bytes->data(),
bytes->size()),
settings);

View File

@ -16,7 +16,7 @@ bool FuzzSKSL2SPIRV(sk_sp<SkData> bytes) {
SkSL::String output;
SkSL::Program::Settings settings;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kFragment_Kind,
SkSL::ProgramKind::kFragment,
SkSL::String((const char*) bytes->data(),
bytes->size()),
settings);

View File

@ -161,7 +161,7 @@ void SkParticleEffectParams::prepare(const skresources::ResourceProvider* resour
}
auto program =
compiler.convertProgram(SkSL::Program::kGeneric_Kind, code, settings, &externalFns);
compiler.convertProgram(SkSL::ProgramKind::kGeneric, code, settings, &externalFns);
if (!program) {
SkDebugf("%s\n", compiler.errorText().c_str());
return nullptr;

View File

@ -137,7 +137,7 @@ SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl, const Options& opti
SkSL::Program::Settings settings;
settings.fInlineThreshold = options.inlineThreshold;
settings.fAllowNarrowingConversions = true;
auto program = compiler->convertProgram(SkSL::Program::kRuntimeEffect_Kind,
auto program = compiler->convertProgram(SkSL::ProgramKind::kRuntimeEffect,
SkSL::String(sksl.c_str(), sksl.size()),
settings);
// TODO: Many errors aren't caught until we process the generated Program here. Catching those

View File

@ -214,12 +214,12 @@ GrContextOptions::ShaderErrorHandler* DefaultShaderErrorHandler() {
return &gHandler;
}
void PrintShaderBanner(SkSL::Program::Kind programKind) {
void PrintShaderBanner(SkSL::ProgramKind programKind) {
const char* typeName = "Unknown";
switch (programKind) {
case SkSL::Program::kVertex_Kind: typeName = "Vertex"; break;
case SkSL::Program::kGeometry_Kind: typeName = "Geometry"; break;
case SkSL::Program::kFragment_Kind: typeName = "Fragment"; break;
case SkSL::ProgramKind::kVertex: typeName = "Vertex"; break;
case SkSL::ProgramKind::kGeometry: typeName = "Geometry"; break;
case SkSL::ProgramKind::kFragment: typeName = "Fragment"; break;
default: break;
}
SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);

View File

@ -29,7 +29,7 @@ inline void PrintLineByLine(const SkSL::String& text) {
GrContextOptions::ShaderErrorHandler* DefaultShaderErrorHandler();
void PrintShaderBanner(SkSL::Program::Kind programKind);
void PrintShaderBanner(SkSL::ProgramKind programKind);
} // namespace GrShaderUtils

View File

@ -72,16 +72,16 @@ void GrD3DPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outp
static gr_cp<ID3DBlob> GrCompileHLSLShader(GrD3DGpu* gpu,
const SkSL::String& hlsl,
SkSL::Program::Kind kind) {
SkSL::ProgramKind kind) {
const char* compileTarget = nullptr;
switch (kind) {
case SkSL::Program::kVertex_Kind:
case SkSL::ProgramKind::kVertex:
compileTarget = "vs_5_1";
break;
case SkSL::Program::kGeometry_Kind:
case SkSL::ProgramKind::kGeometry:
compileTarget = "gs_5_1";
break;
case SkSL::Program::kFragment_Kind:
case SkSL::ProgramKind::kFragment:
compileTarget = "ps_5_1";
break;
default:
@ -116,7 +116,7 @@ bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID
return false;
}
auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) {
auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) {
if (inputs[shaderType].fRTHeight) {
this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
}
@ -124,14 +124,14 @@ bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID
return shaders[shaderType].get();
};
return compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) &&
compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType) &&
return compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) &&
compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType) &&
(hlsl[kGeometry_GrShaderType].empty() ||
compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType));
compile(SkSL::ProgramKind::kGeometry, kGeometry_GrShaderType));
}
gr_cp<ID3DBlob> GrD3DPipelineStateBuilder::compileD3DProgram(
SkSL::Program::Kind kind,
SkSL::ProgramKind kind,
const SkSL::String& sksl,
const SkSL::Program::Settings& settings,
SkSL::Program::Inputs* outInputs,
@ -601,19 +601,19 @@ sk_sp<GrD3DPipelineState> GrD3DPipelineStateBuilder::finalize() {
}
}
auto compile = [&](SkSL::Program::Kind kind, GrShaderType shaderType) {
auto compile = [&](SkSL::ProgramKind kind, GrShaderType shaderType) {
shaders[shaderType] = this->compileD3DProgram(kind, *sksl[shaderType], settings,
&inputs[shaderType], &hlsl[shaderType]);
return shaders[shaderType].get();
};
if (!compile(SkSL::Program::kVertex_Kind, kVertex_GrShaderType) ||
!compile(SkSL::Program::kFragment_Kind, kFragment_GrShaderType)) {
if (!compile(SkSL::ProgramKind::kVertex, kVertex_GrShaderType) ||
!compile(SkSL::ProgramKind::kFragment, kFragment_GrShaderType)) {
return nullptr;
}
if (primProc.willUseGeoShader()) {
if (!compile(SkSL::Program::kGeometry_Kind, kGeometry_GrShaderType)) {
if (!compile(SkSL::ProgramKind::kGeometry, kGeometry_GrShaderType)) {
return nullptr;
}
}

View File

@ -49,7 +49,7 @@ private:
bool loadHLSLFromCache(SkReadBuffer* reader, gr_cp<ID3DBlob> shaders[]);
gr_cp<ID3DBlob> compileD3DProgram(SkSL::Program::Kind kind,
gr_cp<ID3DBlob> compileD3DProgram(SkSL::ProgramKind kind,
const SkSL::String& sksl,
const SkSL::Program::Settings& settings,
SkSL::Program::Inputs* outInputs,

View File

@ -704,7 +704,7 @@ bool GrDawnGpu::onRegenerateMipMapLevels(GrTexture* tex) {
" texCoord = texCoords[sk_VertexID];\n"
"}\n";
SkSL::String vsSPIRV =
this->SkSLToSPIRV(vs, SkSL::Program::kVertex_Kind, false, 0, nullptr);
this->SkSLToSPIRV(vs, SkSL::ProgramKind::kVertex, false, 0, nullptr);
const char* fs =
"layout(set = 0, binding = 0) uniform sampler samp;\n"
@ -714,7 +714,7 @@ bool GrDawnGpu::onRegenerateMipMapLevels(GrTexture* tex) {
" sk_FragColor = sample(makeSampler2D(tex, samp), texCoord);\n"
"}\n";
SkSL::String fsSPIRV =
this->SkSLToSPIRV(fs, SkSL::Program::kFragment_Kind, false, 0, nullptr);
this->SkSLToSPIRV(fs, SkSL::ProgramKind::kFragment, false, 0, nullptr);
wgpu::ProgrammableStageDescriptor vsDesc;
vsDesc.module = this->createShaderModule(vsSPIRV);
@ -925,7 +925,7 @@ void GrDawnGpu::moveStagingBuffersToBusyAndMapAsync() {
fSubmittedStagingBuffers.clear();
}
SkSL::String GrDawnGpu::SkSLToSPIRV(const char* shaderString, SkSL::Program::Kind kind, bool flipY,
SkSL::String GrDawnGpu::SkSLToSPIRV(const char* shaderString, SkSL::ProgramKind kind, bool flipY,
uint32_t rtHeightOffset, SkSL::Program::Inputs* inputs) {
SkSL::Program::Settings settings;
settings.fFlipY = flipY;

View File

@ -99,7 +99,7 @@ public:
void appendCommandBuffer(wgpu::CommandBuffer commandBuffer);
void waitOnAllBusyStagingBuffers();
SkSL::String SkSLToSPIRV(const char* shaderString, SkSL::Program::Kind, bool flipY,
SkSL::String SkSLToSPIRV(const char* shaderString, SkSL::ProgramKind, bool flipY,
uint32_t rtHeightOffset, SkSL::Program::Inputs*);
wgpu::ShaderModule createShaderModule(const SkSL::String& spirvSource);

View File

@ -277,9 +277,9 @@ sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
SkSL::Program::Inputs vertInputs, fragInputs;
bool flipY = programInfo.origin() != kTopLeft_GrSurfaceOrigin;
auto vsModule = builder.createShaderModule(builder.fVS, SkSL::Program::kVertex_Kind, flipY,
auto vsModule = builder.createShaderModule(builder.fVS, SkSL::ProgramKind::kVertex, flipY,
&vertInputs);
auto fsModule = builder.createShaderModule(builder.fFS, SkSL::Program::kFragment_Kind, flipY,
auto fsModule = builder.createShaderModule(builder.fFS, SkSL::ProgramKind::kFragment, flipY,
&fragInputs);
GrSPIRVUniformHandler::UniformInfoArray& uniforms = builder.fUniformHandler.fUniforms;
uint32_t uniformBufferSize = builder.fUniformHandler.fCurrentUBOOffset;
@ -426,7 +426,7 @@ GrDawnProgramBuilder::GrDawnProgramBuilder(GrDawnGpu* gpu,
}
wgpu::ShaderModule GrDawnProgramBuilder::createShaderModule(const GrGLSLShaderBuilder& builder,
SkSL::Program::Kind kind,
SkSL::ProgramKind kind,
bool flipY,
SkSL::Program::Inputs* inputs) {
wgpu::Device device = fGpu->device();

View File

@ -93,7 +93,7 @@ private:
GrRenderTarget*,
const GrProgramInfo&,
GrProgramDesc*);
wgpu::ShaderModule createShaderModule(const GrGLSLShaderBuilder&, SkSL::Program::Kind,
wgpu::ShaderModule createShaderModule(const GrGLSLShaderBuilder&, SkSL::ProgramKind,
bool flipY, SkSL::Program::Inputs* inputs);
GrDawnGpu* fGpu;
GrSPIRVVaryingHandler fVaryingHandler;

View File

@ -3062,14 +3062,14 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) {
SkSL::String sksl(vshaderTxt.c_str(), vshaderTxt.size());
SkSL::Program::Settings settings;
SkSL::String glsl;
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(this, SkSL::Program::kVertex_Kind,
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(this, SkSL::ProgramKind::kVertex,
sksl, settings, &glsl, errorHandler);
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
GR_GL_VERTEX_SHADER, glsl, &fStats, errorHandler);
SkASSERT(program->fInputs.isEmpty());
sksl.assign(fshaderTxt.c_str(), fshaderTxt.size());
program = GrSkSLtoGLSL(this, SkSL::Program::kFragment_Kind, sksl, settings, &glsl,
program = GrSkSLtoGLSL(this, SkSL::ProgramKind::kFragment, sksl, settings, &glsl,
errorHandler);
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
GR_GL_FRAGMENT_SHADER, glsl, &fStats,
@ -3215,14 +3215,14 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
SkSL::String sksl(vshaderTxt.c_str(), vshaderTxt.size());
SkSL::Program::Settings settings;
SkSL::String glsl;
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(this, SkSL::Program::kVertex_Kind,
std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(this, SkSL::ProgramKind::kVertex,
sksl, settings, &glsl, errorHandler);
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
GR_GL_VERTEX_SHADER, glsl, &fStats, errorHandler);
SkASSERT(program->fInputs.isEmpty());
sksl.assign(fshaderTxt.c_str(), fshaderTxt.size());
program = GrSkSLtoGLSL(this, SkSL::Program::kFragment_Kind, sksl, settings, &glsl,
program = GrSkSLtoGLSL(this, SkSL::ProgramKind::kFragment, sksl, settings, &glsl,
errorHandler);
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
GR_GL_FRAGMENT_SHADER, glsl, &fStats,

View File

@ -334,7 +334,7 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
settings.fForceHighPrecision = true;
}
std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(this->gpu(),
SkSL::Program::kFragment_Kind,
SkSL::ProgramKind::kFragment,
*sksl[kFragment_GrShaderType],
settings,
&glsl[kFragment_GrShaderType],
@ -359,7 +359,7 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
if (glsl[kVertex_GrShaderType].empty()) {
// Don't have cached GLSL, need to compile SkSL->GLSL
std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(this->gpu(),
SkSL::Program::kVertex_Kind,
SkSL::ProgramKind::kVertex,
*sksl[kVertex_GrShaderType],
settings,
&glsl[kVertex_GrShaderType],
@ -423,7 +423,7 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
// Don't have cached GLSL, need to compile SkSL->GLSL
std::unique_ptr<SkSL::Program> gs;
gs = GrSkSLtoGLSL(this->gpu(),
SkSL::Program::kGeometry_Kind,
SkSL::ProgramKind::kGeometry,
*sksl[kGeometry_GrShaderType],
settings,
&glsl[kGeometry_GrShaderType],
@ -603,7 +603,7 @@ bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledPr
SkTDArray<GrGLuint> shadersToDelete;
auto compileShader = [&](SkSL::Program::Kind kind, const SkSL::String& sksl, GrGLenum type) {
auto compileShader = [&](SkSL::ProgramKind kind, const SkSL::String& sksl, GrGLenum type) {
SkSL::String glsl;
auto program = GrSkSLtoGLSL(gpu, kind, sksl, settings, &glsl, errorHandler);
if (!program) {
@ -619,14 +619,14 @@ bool GrGLProgramBuilder::PrecompileProgram(GrGLPrecompiledProgram* precompiledPr
}
};
if (!compileShader(SkSL::Program::kFragment_Kind,
if (!compileShader(SkSL::ProgramKind::kFragment,
shaders[kFragment_GrShaderType],
GR_GL_FRAGMENT_SHADER) ||
!compileShader(SkSL::Program::kVertex_Kind,
!compileShader(SkSL::ProgramKind::kVertex,
shaders[kVertex_GrShaderType],
GR_GL_VERTEX_SHADER) ||
(!shaders[kGeometry_GrShaderType].empty() &&
!compileShader(SkSL::Program::kGeometry_Kind,
!compileShader(SkSL::ProgramKind::kGeometry,
shaders[kGeometry_GrShaderType],
GR_GL_GEOMETRY_SHADER))) {
cleanup_program(gpu, programID, shadersToDelete);

View File

@ -18,7 +18,7 @@ static const bool gPrintSKSL = false;
static const bool gPrintGLSL = false;
std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLGpu* gpu,
SkSL::Program::Kind programKind,
SkSL::ProgramKind programKind,
const SkSL::String& sksl,
const SkSL::Program::Settings& settings,
SkSL::String* glsl,

View File

@ -15,7 +15,7 @@
#include "src/sksl/SkSLGLSLCodeGenerator.h"
std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLGpu* gpu,
SkSL::Program::Kind programKind,
SkSL::ProgramKind programKind,
const SkSL::String& sksl,
const SkSL::Program::Settings& settings,
SkSL::String* glsl,

View File

@ -52,7 +52,7 @@ private:
void finalizeFragmentSecondaryColor(GrShaderVar& outputColor) override;
id<MTLLibrary> generateMtlShaderLibrary(const SkSL::String& sksl,
SkSL::Program::Kind kind,
SkSL::ProgramKind kind,
const SkSL::Program::Settings& settings,
SkSL::String* msl,
SkSL::Program::Inputs* inputs,

View File

@ -86,7 +86,7 @@ void GrMtlPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[]
id<MTLLibrary> GrMtlPipelineStateBuilder::generateMtlShaderLibrary(
const SkSL::String& shader,
SkSL::Program::Kind kind,
SkSL::ProgramKind kind,
const SkSL::Program::Settings& settings,
SkSL::String* msl,
SkSL::Program::Inputs* inputs,
@ -433,14 +433,14 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTa
shaderLibraries[kVertex_GrShaderType] = this->generateMtlShaderLibrary(
*sksl[kVertex_GrShaderType],
SkSL::Program::kVertex_Kind,
SkSL::ProgramKind::kVertex,
settings,
&shaders[kVertex_GrShaderType],
&inputs[kVertex_GrShaderType],
errorHandler);
shaderLibraries[kFragment_GrShaderType] = this->generateMtlShaderLibrary(
*sksl[kFragment_GrShaderType],
SkSL::Program::kFragment_Kind,
SkSL::ProgramKind::kFragment,
settings,
&shaders[kFragment_GrShaderType],
&inputs[kFragment_GrShaderType],

View File

@ -70,7 +70,7 @@ MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture);
*/
id<MTLLibrary> GrGenerateMtlShaderLibrary(const GrMtlGpu* gpu,
const SkSL::String& sksl,
SkSL::Program::Kind kind,
SkSL::ProgramKind kind,
const SkSL::Program::Settings& settings,
SkSL::String* msl,
SkSL::Program::Inputs* outInputs,

View File

@ -53,7 +53,7 @@ static const bool gPrintMSL = false;
id<MTLLibrary> GrGenerateMtlShaderLibrary(const GrMtlGpu* gpu,
const SkSL::String& sksl,
SkSL::Program::Kind programKind,
SkSL::ProgramKind programKind,
const SkSL::Program::Settings& settings,
SkSL::String* msl,
SkSL::Program::Inputs* outInputs,

View File

@ -74,15 +74,15 @@ bool GrSampleCountToVkSampleCount(uint32_t samples, VkSampleCountFlagBits* vkSam
}
}
SkSL::Program::Kind vk_shader_stage_to_skiasl_kind(VkShaderStageFlagBits stage) {
SkSL::ProgramKind vk_shader_stage_to_skiasl_kind(VkShaderStageFlagBits stage) {
if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
return SkSL::Program::kVertex_Kind;
return SkSL::ProgramKind::kVertex;
}
if (VK_SHADER_STAGE_GEOMETRY_BIT == stage) {
return SkSL::Program::kGeometry_Kind;
return SkSL::ProgramKind::kGeometry;
}
SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
return SkSL::Program::kFragment_Kind;
return SkSL::ProgramKind::kFragment;
}
bool GrCompileVkShaderModule(GrVkGpu* gpu,

View File

@ -174,14 +174,14 @@ Compiler::~Compiler() {}
const ParsedModule& Compiler::loadGPUModule() {
if (!fGPUModule.fSymbols) {
fGPUModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(gpu), fPrivateModule);
fGPUModule = this->parseModule(ProgramKind::kFragment, MODULE_DATA(gpu), fPrivateModule);
}
return fGPUModule;
}
const ParsedModule& Compiler::loadFragmentModule() {
if (!fFragmentModule.fSymbols) {
fFragmentModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(frag),
fFragmentModule = this->parseModule(ProgramKind::kFragment, MODULE_DATA(frag),
this->loadGPUModule());
}
return fFragmentModule;
@ -189,7 +189,7 @@ const ParsedModule& Compiler::loadFragmentModule() {
const ParsedModule& Compiler::loadVertexModule() {
if (!fVertexModule.fSymbols) {
fVertexModule = this->parseModule(Program::kVertex_Kind, MODULE_DATA(vert),
fVertexModule = this->parseModule(ProgramKind::kVertex, MODULE_DATA(vert),
this->loadGPUModule());
}
return fVertexModule;
@ -197,7 +197,7 @@ const ParsedModule& Compiler::loadVertexModule() {
const ParsedModule& Compiler::loadGeometryModule() {
if (!fGeometryModule.fSymbols) {
fGeometryModule = this->parseModule(Program::kGeometry_Kind, MODULE_DATA(geom),
fGeometryModule = this->parseModule(ProgramKind::kGeometry, MODULE_DATA(geom),
this->loadGPUModule());
}
return fGeometryModule;
@ -205,7 +205,7 @@ const ParsedModule& Compiler::loadGeometryModule() {
const ParsedModule& Compiler::loadFPModule() {
if (!fFPModule.fSymbols) {
fFPModule = this->parseModule(Program::kFragmentProcessor_Kind, MODULE_DATA(fp),
fFPModule = this->parseModule(ProgramKind::kFragmentProcessor, MODULE_DATA(fp),
this->loadGPUModule());
}
return fFPModule;
@ -213,14 +213,14 @@ const ParsedModule& Compiler::loadFPModule() {
const ParsedModule& Compiler::loadPublicModule() {
if (!fPublicModule.fSymbols) {
fPublicModule = this->parseModule(Program::kGeneric_Kind, MODULE_DATA(public), fRootModule);
fPublicModule = this->parseModule(ProgramKind::kGeneric, MODULE_DATA(public), fRootModule);
}
return fPublicModule;
}
const ParsedModule& Compiler::loadRuntimeEffectModule() {
if (!fRuntimeEffectModule.fSymbols) {
fRuntimeEffectModule = this->parseModule(Program::kRuntimeEffect_Kind, MODULE_DATA(runtime),
fRuntimeEffectModule = this->parseModule(ProgramKind::kRuntimeEffect, MODULE_DATA(runtime),
this->loadPublicModule());
// Add some aliases to the runtime effect module so that it's friendlier, and more like GLSL
@ -241,19 +241,19 @@ const ParsedModule& Compiler::loadRuntimeEffectModule() {
return fRuntimeEffectModule;
}
const ParsedModule& Compiler::moduleForProgramKind(Program::Kind kind) {
const ParsedModule& Compiler::moduleForProgramKind(ProgramKind kind) {
switch (kind) {
case Program::kVertex_Kind: return this->loadVertexModule(); break;
case Program::kFragment_Kind: return this->loadFragmentModule(); break;
case Program::kGeometry_Kind: return this->loadGeometryModule(); break;
case Program::kFragmentProcessor_Kind: return this->loadFPModule(); break;
case Program::kRuntimeEffect_Kind: return this->loadRuntimeEffectModule(); break;
case Program::kGeneric_Kind: return this->loadPublicModule(); break;
case ProgramKind::kVertex: return this->loadVertexModule(); break;
case ProgramKind::kFragment: return this->loadFragmentModule(); break;
case ProgramKind::kGeometry: return this->loadGeometryModule(); break;
case ProgramKind::kFragmentProcessor: return this->loadFPModule(); break;
case ProgramKind::kRuntimeEffect: return this->loadRuntimeEffectModule(); break;
case ProgramKind::kGeneric: return this->loadPublicModule(); break;
}
SkUNREACHABLE;
}
LoadedModule Compiler::loadModule(Program::Kind kind,
LoadedModule Compiler::loadModule(ProgramKind kind,
ModuleData data,
std::shared_ptr<SymbolTable> base) {
if (!base) {
@ -281,6 +281,7 @@ LoadedModule Compiler::loadModule(Program::Kind kind,
SkASSERT(fIRGenerator->fCanInline);
fIRGenerator->fCanInline = false;
settings.fReplaceSettings = false;
ParsedModule baseModule = {base, /*fIntrinsics=*/nullptr};
IRGenerator::IRBundle ir =
fIRGenerator->convertProgram(kind, &settings, baseModule,
@ -305,7 +306,7 @@ LoadedModule Compiler::loadModule(Program::Kind kind,
return module;
}
ParsedModule Compiler::parseModule(Program::Kind kind, ModuleData data, const ParsedModule& base) {
ParsedModule Compiler::parseModule(ProgramKind kind, ModuleData data, const ParsedModule& base) {
LoadedModule module = this->loadModule(kind, data, base.fSymbols);
this->optimize(module);
@ -1564,11 +1565,11 @@ bool Compiler::scanCFG(FunctionDefinition& f, ProgramUsage* usage) {
}
std::unique_ptr<Program> Compiler::convertProgram(
Program::Kind kind,
ProgramKind kind,
String text,
const Program::Settings& settings,
const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions) {
SkASSERT(!externalFunctions || (kind == Program::kGeneric_Kind));
SkASSERT(!externalFunctions || (kind == ProgramKind::kGeneric));
// Loading and optimizing our base module might reset the inliner, so do that first,
// *then* configure the inliner with the settings for this program.
@ -1745,7 +1746,7 @@ bool Compiler::optimize(Program& program) {
program.fSharedElements.end());
}
if (program.fKind != Program::kFragmentProcessor_Kind) {
if (program.fKind != ProgramKind::kFragmentProcessor) {
// Remove declarations of dead global variables
auto isDeadVariable = [&](const ProgramElement* element) {
if (!element->is<GlobalVarDeclaration>()) {

View File

@ -55,7 +55,7 @@ class IRIntrinsicMap;
class ProgramUsage;
struct LoadedModule {
Program::Kind fKind;
ProgramKind fKind;
std::shared_ptr<SymbolTable> fSymbols;
std::vector<std::unique_ptr<ProgramElement>> fElements;
};
@ -103,7 +103,7 @@ public:
* Program, but ownership is *not* transferred. It is up to the caller to keep them alive.
*/
std::unique_ptr<Program> convertProgram(
Program::Kind kind,
ProgramKind kind,
String text,
const Program::Settings& settings,
const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions = nullptr);
@ -160,14 +160,14 @@ public:
return ModuleData{/*fPath=*/nullptr, data, size};
}
LoadedModule loadModule(Program::Kind kind, ModuleData data, std::shared_ptr<SymbolTable> base);
ParsedModule parseModule(Program::Kind kind, ModuleData data, const ParsedModule& base);
LoadedModule loadModule(ProgramKind kind, ModuleData data, std::shared_ptr<SymbolTable> base);
ParsedModule parseModule(ProgramKind kind, ModuleData data, const ParsedModule& base);
IRGenerator& irGenerator() {
return *fIRGenerator;
}
const ParsedModule& moduleForProgramKind(Program::Kind kind);
const ParsedModule& moduleForProgramKind(ProgramKind kind);
private:
const ParsedModule& loadGPUModule();

View File

@ -17,6 +17,9 @@
namespace SkSL {
struct ProgramSettings;
enum class ProgramKind : int8_t;
/**
* Contains compiler-wide objects, which currently means the core types.
*/

View File

@ -873,7 +873,7 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
if (precedence >= parentPrecedence) {
this->write("(");
}
bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind &&
bool positionWorkaround = fProgramKind == ProgramKind::kVertex &&
op.isAssignment() &&
left.is<FieldAccess>() &&
is_sk_position(left.as<FieldAccess>()) &&
@ -1082,8 +1082,8 @@ void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
} else if (modifiers.fFlags & Modifiers::kIn_Flag) {
if (globalContext &&
fProgram.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
: "varying ");
this->write(fProgramKind == ProgramKind::kVertex ? "attribute "
: "varying ");
} else {
this->write("in ");
}
@ -1517,7 +1517,7 @@ void GLSLCodeGenerator::writeInputVars() {
bool GLSLCodeGenerator::generateCode() {
this->writeHeader();
if (Program::kGeometry_Kind == fProgramKind &&
if (ProgramKind::kGeometry == fProgramKind &&
fProgram.fCaps->geometryShaderExtensionString()) {
this->writeExtension(fProgram.fCaps->geometryShaderExtensionString());
}
@ -1548,7 +1548,7 @@ bool GLSLCodeGenerator::generateCode() {
if (!fProgram.fCaps->canUseFragCoord()) {
Layout layout;
switch (fProgram.fKind) {
case Program::kVertex_Kind: {
case ProgramKind::kVertex: {
Modifiers modifiers(layout, Modifiers::kOut_Flag);
this->writeModifiers(modifiers, true);
if (this->usesPrecisionModifiers()) {
@ -1557,7 +1557,7 @@ bool GLSLCodeGenerator::generateCode() {
this->write("vec4 sk_FragCoord_Workaround;\n");
break;
}
case Program::kFragment_Kind: {
case ProgramKind::kFragment: {
Modifiers modifiers(layout, Modifiers::kIn_Flag);
this->writeModifiers(modifiers, true);
if (this->usesPrecisionModifiers()) {

View File

@ -181,7 +181,7 @@ protected:
StringStream fGlobals;
StringStream fExtraFunctions;
String fFunctionHeader;
Program::Kind fProgramKind;
ProgramKind fProgramKind;
int fVarCount = 0;
int fIndentation = 0;
bool fAtLineStart = false;

View File

@ -78,9 +78,9 @@ public:
std::shared_ptr<SymbolTable> fPrevious;
};
static void fill_caps(const SkSL::ShaderCapsClass& caps,
std::unordered_map<String, Program::Settings::Value>* capsMap) {
#define CAP(name) capsMap->insert({String(#name), Program::Settings::Value(caps.name())})
void IRGenerator::FillCapsMap(const SkSL::ShaderCapsClass& caps,
std::unordered_map<String, CapsValue>* capsMap) {
#define CAP(name) capsMap->insert({String(#name), CapsValue(caps.name())})
CAP(fbFetchSupport);
CAP(fbFetchNeedsCustomOutput);
CAP(flatInterpolationSupport);
@ -101,15 +101,33 @@ static void fill_caps(const SkSL::ShaderCapsClass& caps,
#undef CAP
}
std::unique_ptr<Expression> IRGenerator::CapsValue::literal(const Context& context,
int offset) const {
switch (fKind) {
case kBool_Kind:
return std::make_unique<BoolLiteral>(context, offset, fValue);
case kInt_Kind:
return std::make_unique<IntLiteral>(context, offset, fValue);
case kFloat_Kind:
return std::make_unique<FloatLiteral>(context, offset, fValueF);
default:
SkDEBUGFAILF("unrecognized caps kind: %d", fKind);
return nullptr;
}
}
IRGenerator::IRGenerator(const Context* context,
const ShaderCapsClass* caps)
: fContext(*context)
, fCaps(caps)
, fModifiers(new ModifiersPool()) {
if (fCaps) {
fill_caps(*fCaps, &fCapsMap);
FillCapsMap(*fCaps, &fCapsMap);
} else {
fCapsMap.insert({String("integerSupport"), Program::Settings::Value(true)});
fCapsMap.insert({String("integerSupport"), CapsValue(true)});
}
}
@ -156,9 +174,9 @@ bool IRGenerator::detectVarDeclarationWithoutScope(const Statement& stmt) {
}
std::unique_ptr<Extension> IRGenerator::convertExtension(int offset, StringFragment name) {
if (fKind != Program::kFragment_Kind &&
fKind != Program::kVertex_Kind &&
fKind != Program::kGeometry_Kind) {
if (fKind != ProgramKind::kFragment &&
fKind != ProgramKind::kVertex &&
fKind != ProgramKind::kGeometry) {
this->errorReporter().error(offset, "extensions are not allowed here");
return nullptr;
}
@ -202,7 +220,7 @@ std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& st
default:
// it's an expression
std::unique_ptr<Statement> result = this->convertExpressionStatement(statement);
if (fRTAdjust && fKind == Program::kGeometry_Kind) {
if (fRTAdjust && fKind == ProgramKind::kGeometry) {
SkASSERT(result->kind() == Statement::Kind::kExpression);
Expression& expr = *result->as<ExpressionStatement>().expression();
if (expr.kind() == Expression::Kind::kFunctionCall) {
@ -320,7 +338,7 @@ void IRGenerator::checkVarDeclaration(int offset, const Modifiers& modifiers, co
offset,
"variables of type '" + baseType->displayName() + "' must be global");
}
if (fKind != Program::kFragmentProcessor_Kind) {
if (fKind != ProgramKind::kFragmentProcessor) {
if ((modifiers.fFlags & Modifiers::kIn_Flag) && baseType->isMatrix()) {
this->errorReporter().error(offset, "'in' variables may not have matrix type");
}
@ -347,7 +365,7 @@ void IRGenerator::checkVarDeclaration(int offset, const Modifiers& modifiers, co
"'key' is only permitted within fragment processors");
}
}
if (fKind == Program::kRuntimeEffect_Kind) {
if (fKind == ProgramKind::kRuntimeEffect) {
if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
*baseType != *fContext.fTypes.fFragmentProcessor) {
this->errorReporter().error(offset,
@ -358,7 +376,7 @@ void IRGenerator::checkVarDeclaration(int offset, const Modifiers& modifiers, co
this->errorReporter().error(offset, "'key' is not permitted on 'uniform' variables");
}
if (modifiers.fLayout.fMarker.fLength) {
if (fKind != Program::kRuntimeEffect_Kind) {
if (fKind != ProgramKind::kRuntimeEffect) {
this->errorReporter().error(offset,
"'marker' is only permitted in runtime effects");
}
@ -372,7 +390,7 @@ void IRGenerator::checkVarDeclaration(int offset, const Modifiers& modifiers, co
}
}
if (modifiers.fLayout.fFlags & Layout::kSRGBUnpremul_Flag) {
if (fKind != Program::kRuntimeEffect_Kind) {
if (fKind != ProgramKind::kRuntimeEffect) {
this->errorReporter().error(offset,
"'srgb_unpremul' is only permitted in runtime effects");
}
@ -392,7 +410,7 @@ void IRGenerator::checkVarDeclaration(int offset, const Modifiers& modifiers, co
}
}
if (modifiers.fFlags & Modifiers::kVarying_Flag) {
if (fKind != Program::kRuntimeEffect_Kind) {
if (fKind != ProgramKind::kRuntimeEffect) {
this->errorReporter().error(offset, "'varying' is only permitted in runtime effects");
}
if (!baseType->isFloat() &&
@ -422,7 +440,7 @@ std::unique_ptr<Statement> IRGenerator::convertVarDeclaration(int offset,
std::unique_ptr<Expression> value,
Variable::Storage storage) {
if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
(modifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
(modifiers.fFlags & Modifiers::kOut_Flag) && fKind == ProgramKind::kFragment &&
name != "sk_FragColor") {
this->errorReporter().error(offset,
"out location=0, index=0 is reserved for sk_FragColor");
@ -522,9 +540,9 @@ StatementArray IRGenerator::convertVarDeclarations(const ASTNode& decls,
}
std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(const ASTNode& m) {
if (fKind != Program::kFragment_Kind &&
fKind != Program::kVertex_Kind &&
fKind != Program::kGeometry_Kind) {
if (fKind != ProgramKind::kFragment &&
fKind != ProgramKind::kVertex &&
fKind != ProgramKind::kGeometry) {
this->errorReporter().error(m.fOffset, "layout qualifiers are not allowed here");
return nullptr;
}
@ -532,7 +550,7 @@ std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(c
SkASSERT(m.fKind == ASTNode::Kind::kModifiers);
Modifiers modifiers = m.getModifiers();
if (modifiers.fLayout.fInvocations != -1) {
if (fKind != Program::kGeometry_Kind) {
if (fKind != ProgramKind::kGeometry) {
this->errorReporter().error(m.fOffset,
"'invocations' is only legal in geometry shaders");
return nullptr;
@ -858,7 +876,7 @@ std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTNode& c) {
std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTNode& d) {
SkASSERT(d.fKind == ASTNode::Kind::kDiscard);
if (fKind != Program::kFragment_Kind && fKind != Program::kFragmentProcessor_Kind) {
if (fKind != ProgramKind::kFragment && fKind != ProgramKind::kFragmentProcessor) {
this->errorReporter().error(d.fOffset,
"discard statement is only permitted in fragment shaders");
return nullptr;
@ -1052,7 +1070,7 @@ void IRGenerator::finalizeFunction(FunctionDefinition& f) {
// normalization, so SkASSERT that we aren't doing that. It is of course
// possible to fix this by adding a normalization before each return, but it
// will probably never actually be necessary.
SkASSERT(fIRGenerator->fKind != Program::kVertex_Kind ||
SkASSERT(fIRGenerator->fKind != ProgramKind::kVertex ||
!fIRGenerator->fRTAdjust ||
fFunction->name() != "main");
ReturnStatement& r = stmt.as<ReturnStatement>();
@ -1170,8 +1188,8 @@ void IRGenerator::convertFunction(const ASTNode& f) {
}
Modifiers m = pd.fModifiers;
if (funcData.fName == "main" && (fKind == Program::kRuntimeEffect_Kind ||
fKind == Program::kFragmentProcessor_Kind)) {
if (funcData.fName == "main" && (fKind == ProgramKind::kRuntimeEffect ||
fKind == ProgramKind::kFragmentProcessor)) {
if (i == 0) {
// We verify that the type is correct later, for now, if there is a parameter to
// a .fp or runtime-effect main(), it's supposed to be the coords:
@ -1193,7 +1211,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
if (funcData.fName == "main") {
switch (fKind) {
case Program::kRuntimeEffect_Kind: {
case ProgramKind::kRuntimeEffect: {
// (half4|float4) main() -or- (half4|float4) main(float2)
if (*returnType != *fContext.fTypes.fHalf4 &&
*returnType != *fContext.fTypes.fFloat4) {
@ -1210,7 +1228,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
}
break;
}
case Program::kFragmentProcessor_Kind: {
case ProgramKind::kFragmentProcessor: {
if (*returnType != *fContext.fTypes.fHalf4) {
this->errorReporter().error(f.fOffset, ".fp 'main' must return 'half4'");
return;
@ -1224,7 +1242,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
}
break;
}
case Program::kGeneric_Kind:
case ProgramKind::kGeneric:
break;
default:
if (parameters.size()) {
@ -1330,7 +1348,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
if (needInvocationIDWorkaround) {
body = this->applyInvocationIDWorkaround(std::move(body));
}
if (Program::kVertex_Kind == fKind && funcData.fName == "main" && fRTAdjust) {
if (ProgramKind::kVertex == fKind && funcData.fName == "main" && fRTAdjust) {
body->children().push_back(this->getNormalizeSkPositionCode());
}
auto result = std::make_unique<FunctionDefinition>(
@ -1360,9 +1378,9 @@ std::unique_ptr<StructDefinition> IRGenerator::convertStructDefinition(const AST
}
std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode& intf) {
if (fKind != Program::kFragment_Kind &&
fKind != Program::kVertex_Kind &&
fKind != Program::kGeometry_Kind) {
if (fKind != ProgramKind::kFragment &&
fKind != ProgramKind::kVertex &&
fKind != ProgramKind::kGeometry) {
this->errorReporter().error(intf.fOffset, "interface block is not allowed here");
return nullptr;
}
@ -1631,7 +1649,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(int offset, StringFra
}
#endif
}
if (fKind == Program::kFragmentProcessor_Kind &&
if (fKind == ProgramKind::kFragmentProcessor &&
(modifiers.fFlags & Modifiers::kIn_Flag) &&
!(modifiers.fFlags & Modifiers::kUniform_Flag) &&
!modifiers.fLayout.fKey &&
@ -1686,7 +1704,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
}
std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
if (fKind != Program::kFragmentProcessor_Kind) {
if (fKind != ProgramKind::kFragmentProcessor) {
this->errorReporter().error(s.fOffset, "syntax error");
return nullptr;
}
@ -2640,9 +2658,9 @@ const Type* IRGenerator::typeForSetting(int offset, String name) const {
return nullptr;
}
switch (found->second.fKind) {
case Program::Settings::Value::kBool_Kind: return fContext.fTypes.fBool.get();
case Program::Settings::Value::kFloat_Kind: return fContext.fTypes.fFloat.get();
case Program::Settings::Value::kInt_Kind: return fContext.fTypes.fInt.get();
case CapsValue::kBool_Kind: return fContext.fTypes.fBool.get();
case CapsValue::kFloat_Kind: return fContext.fTypes.fFloat.get();
case CapsValue::kInt_Kind: return fContext.fTypes.fInt.get();
}
SkUNREACHABLE;
return nullptr;
@ -2947,7 +2965,7 @@ void IRGenerator::findAndDeclareBuiltinVariables() {
}
switch (fKind) {
case Program::kFragment_Kind:
case ProgramKind::kFragment:
// Vulkan requires certain builtin variables be present, even if they're unused. At one
// time, validation errors would result if sk_Clockwise was missing. Now, it's just
// (Adreno) driver bugs that drop or corrupt draws if they're missing.
@ -2962,7 +2980,7 @@ void IRGenerator::findAndDeclareBuiltinVariables() {
}
IRGenerator::IRBundle IRGenerator::convertProgram(
Program::Kind kind,
ProgramKind kind,
const Program::Settings* settings,
const ParsedModule& base,
bool isBuiltinCode,
@ -2992,7 +3010,7 @@ IRGenerator::IRBundle IRGenerator::convertProgram(
AutoSymbolTable table(this);
if (kind == Program::kGeometry_Kind && !fIsBuiltinCode) {
if (kind == ProgramKind::kGeometry && !fIsBuiltinCode) {
// Declare sk_InvocationID programmatically. With invocations support, it's an 'in' builtin.
// If we're applying the workaround, then it's a plain global.
bool workaround = fCaps && !fCaps->gsInvocationsSupport();

View File

@ -121,7 +121,7 @@ public:
* Program, but ownership is *not* transferred. It is up to the caller to keep them alive.
*/
IRBundle convertProgram(
Program::Kind kind,
ProgramKind kind,
const Program::Settings* settings,
const ParsedModule& base,
bool isBuiltinCode,
@ -281,16 +281,40 @@ private:
// Runtime effects (and the interpreter, which uses the same CPU runtime) require adherence to
// the strict rules from The OpenGL ES Shading Language Version 1.00. (Including Appendix A).
bool strictES2Mode() const {
return fKind == Program::kRuntimeEffect_Kind || fKind == Program::kGeneric_Kind;
return fKind == ProgramKind::kRuntimeEffect || fKind == ProgramKind::kGeneric;
}
Program::Inputs fInputs;
const Program::Settings* fSettings = nullptr;
const ShaderCapsClass* fCaps = nullptr;
Program::Kind fKind;
ProgramKind fKind;
std::unique_ptr<ASTFile> fFile;
std::unordered_map<String, Program::Settings::Value> fCapsMap;
struct CapsValue {
CapsValue(bool b) : fKind(kBool_Kind), fValue(b) {}
CapsValue(int i) : fKind(kInt_Kind), fValue(i) {}
CapsValue(unsigned int i) : fKind(kInt_Kind), fValue(i) {}
CapsValue(float f) : fKind(kFloat_Kind), fValueF(f) {}
std::unique_ptr<Expression> literal(const Context& context, int offset) const;
enum {
kBool_Kind,
kInt_Kind,
kFloat_Kind,
} fKind;
union {
int fValue; // for kBool_Kind and kInt_Kind
float fValueF; // for kFloat_Kind
};
};
static void FillCapsMap(const SkSL::ShaderCapsClass& caps,
std::unordered_map<String, CapsValue>* capsMap);
std::unordered_map<String, CapsValue> fCapsMap;
std::shared_ptr<SymbolTable> fSymbolTable = nullptr;
// additional statements that need to be inserted before the one that convertStatement is
// currently working on

View File

@ -268,18 +268,18 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
return ResultCode::kInputError;
}
SkSL::Program::Kind kind;
SkSL::ProgramKind kind;
const SkSL::String& inputPath = args[1];
if (inputPath.endsWith(".vert")) {
kind = SkSL::Program::kVertex_Kind;
kind = SkSL::ProgramKind::kVertex;
} else if (inputPath.endsWith(".frag") || inputPath.endsWith(".sksl")) {
kind = SkSL::Program::kFragment_Kind;
kind = SkSL::ProgramKind::kFragment;
} else if (inputPath.endsWith(".geom")) {
kind = SkSL::Program::kGeometry_Kind;
kind = SkSL::ProgramKind::kGeometry;
} else if (inputPath.endsWith(".fp")) {
kind = SkSL::Program::kFragmentProcessor_Kind;
kind = SkSL::ProgramKind::kFragmentProcessor;
} else if (inputPath.endsWith(".rte")) {
kind = SkSL::Program::kRuntimeEffect_Kind;
kind = SkSL::ProgramKind::kRuntimeEffect;
} else {
printf("input filename must end in '.vert', '.frag', '.geom', '.fp', '.rte', or '.sksl'\n");
return ResultCode::kInputError;

View File

@ -1452,10 +1452,10 @@ bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f)
const char* separator = "";
if ("main" == f.name()) {
switch (fProgram.fKind) {
case Program::kFragment_Kind:
case ProgramKind::kFragment:
this->write("fragment Outputs fragmentMain");
break;
case Program::kVertex_Kind:
case ProgramKind::kVertex:
this->write("vertex Outputs vertexMain");
break;
default:
@ -1508,14 +1508,14 @@ bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f)
this->write(")]]");
}
}
if (fProgram.fKind == Program::kFragment_Kind) {
if (fProgram.fKind == ProgramKind::kFragment) {
if (fProgram.fInputs.fRTHeight && fInterfaceBlockNameMap.empty()) {
this->write(", constant sksl_synthetic_uniforms& _anonInterface0 [[buffer(1)]]");
fRTHeightName = "_anonInterface0.u_skRTHeight";
}
this->write(", bool _frontFacing [[front_facing]]");
this->write(", float4 _fragCoord [[position]]");
} else if (fProgram.fKind == Program::kVertex_Kind) {
} else if (fProgram.fKind == ProgramKind::kVertex) {
this->write(", uint sk_VertexID [[vertex_id]], uint sk_InstanceID [[instance_id]]");
}
separator = ", ";
@ -1871,10 +1871,10 @@ void MetalCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
void MetalCodeGenerator::writeReturnStatementFromMain() {
// main functions in Metal return a magic _out parameter that doesn't exist in SkSL.
switch (fProgram.fKind) {
case Program::kFragment_Kind:
case ProgramKind::kFragment:
this->write("return _out;");
break;
case Program::kVertex_Kind:
case ProgramKind::kVertex:
this->write("return (_out.sk_Position.y = -_out.sk_Position.y, _out);");
break;
default:
@ -1954,10 +1954,10 @@ void MetalCodeGenerator::writeInputStruct() {
this->write(" ");
this->writeName(var.name());
if (-1 != var.modifiers().fLayout.fLocation) {
if (fProgram.fKind == Program::kVertex_Kind) {
if (fProgram.fKind == ProgramKind::kVertex) {
this->write(" [[attribute(" +
to_string(var.modifiers().fLayout.fLocation) + ")]]");
} else if (fProgram.fKind == Program::kFragment_Kind) {
} else if (fProgram.fKind == ProgramKind::kFragment) {
this->write(" [[user(locn" +
to_string(var.modifiers().fLayout.fLocation) + ")]]");
}
@ -1971,9 +1971,9 @@ void MetalCodeGenerator::writeInputStruct() {
void MetalCodeGenerator::writeOutputStruct() {
this->write("struct Outputs {\n");
if (fProgram.fKind == Program::kVertex_Kind) {
if (fProgram.fKind == ProgramKind::kVertex) {
this->write(" float4 sk_Position [[position]];\n");
} else if (fProgram.fKind == Program::kFragment_Kind) {
} else if (fProgram.fKind == ProgramKind::kFragment) {
this->write(" float4 sk_FragColor [[color(0)]];\n");
}
for (const ProgramElement* e : fProgram.elements()) {
@ -1991,9 +1991,9 @@ void MetalCodeGenerator::writeOutputStruct() {
if (location < 0) {
fErrors.error(var.fOffset,
"Metal out variables must have 'layout(location=...)'");
} else if (fProgram.fKind == Program::kVertex_Kind) {
} else if (fProgram.fKind == ProgramKind::kVertex) {
this->write(" [[user(locn" + to_string(location) + ")]]");
} else if (fProgram.fKind == Program::kFragment_Kind) {
} else if (fProgram.fKind == ProgramKind::kFragment) {
this->write(" [[color(" + to_string(location) + ")");
int colorIndex = var.modifiers().fLayout.fIndex;
if (colorIndex) {
@ -2005,7 +2005,7 @@ void MetalCodeGenerator::writeOutputStruct() {
}
}
}
if (fProgram.fKind == Program::kVertex_Kind) {
if (fProgram.fKind == ProgramKind::kVertex) {
this->write(" float sk_PointSize [[point_size]];\n");
}
this->write("};\n");

View File

@ -289,7 +289,7 @@ protected:
const Context& fContext;
String fFunctionHeader;
StringStream fExtraFunctions;
Program::Kind fProgramKind;
ProgramKind fProgramKind;
int fVarCount = 0;
int fIndentation = 0;
bool fAtLineStart = false;

View File

@ -375,7 +375,7 @@ void SPIRVCodeGenerator::writeCapabilities(OutputStream& out) {
this->writeInstruction(SpvOpCapability, (SpvId) i, out);
}
}
if (fProgram.fKind == Program::kGeometry_Kind) {
if (fProgram.fKind == ProgramKind::kGeometry) {
this->writeInstruction(SpvOpCapability, SpvCapabilityGeometry, out);
}
else {
@ -2884,7 +2884,7 @@ static bool is_dead(const Variable& var, const ProgramUsage* usage) {
return var.modifiers().fLayout.fBuiltin == SK_SAMPLEMASK_BUILTIN;
}
void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration& varDecl) {
void SPIRVCodeGenerator::writeGlobalVar(ProgramKind kind, const VarDeclaration& varDecl) {
const Variable& var = varDecl.var();
// These haven't been implemented in our SPIR-V generator yet and we only currently use them
// in the OpenGL backend.
@ -2900,7 +2900,7 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
return;
}
if (var.modifiers().fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN &&
kind != Program::kFragment_Kind) {
kind != ProgramKind::kFragment) {
SkASSERT(!fProgram.fSettings.fFragColorIsInOut);
return;
}
@ -3165,7 +3165,7 @@ void SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, OutputSt
}
void SPIRVCodeGenerator::writeGeometryShaderExecutionMode(SpvId entryPoint, OutputStream& out) {
SkASSERT(fProgram.fKind == Program::kGeometry_Kind);
SkASSERT(fProgram.fKind == ProgramKind::kGeometry);
int invocations = 1;
for (const ProgramElement* e : fProgram.elements()) {
if (e->is<ModifiersDeclaration>()) {
@ -3408,13 +3408,13 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (main->name().fLength + 4) / 4) +
(int32_t) interfaceVars.size(), out);
switch (program.fKind) {
case Program::kVertex_Kind:
case ProgramKind::kVertex:
this->writeWord(SpvExecutionModelVertex, out);
break;
case Program::kFragment_Kind:
case ProgramKind::kFragment:
this->writeWord(SpvExecutionModelFragment, out);
break;
case Program::kGeometry_Kind:
case ProgramKind::kGeometry:
this->writeWord(SpvExecutionModelGeometry, out);
break;
default:
@ -3426,10 +3426,10 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
for (int var : interfaceVars) {
this->writeWord(var, out);
}
if (program.fKind == Program::kGeometry_Kind) {
if (program.fKind == ProgramKind::kGeometry) {
this->writeGeometryShaderExecutionMode(entryPoint, out);
}
if (program.fKind == Program::kFragment_Kind) {
if (program.fKind == ProgramKind::kFragment) {
this->writeInstruction(SpvOpExecutionMode,
fFunctionMap[main],
SpvExecutionModeOriginUpperLeft,

View File

@ -201,7 +201,7 @@ private:
SpvId writeFunction(const FunctionDefinition& f, OutputStream& out);
void writeGlobalVar(Program::Kind kind, const VarDeclaration& v);
void writeGlobalVar(ProgramKind kind, const VarDeclaration& v);
void writeVarDeclaration(const VarDeclaration& var, OutputStream& out);

View File

@ -25,7 +25,7 @@ namespace dsl {
DSLWriter::DSLWriter(SkSL::Compiler* compiler)
: fCompiler(compiler) {
SkSL::ParsedModule module = fCompiler->moduleForProgramKind(SkSL::Program::kFragment_Kind);
SkSL::ParsedModule module = fCompiler->moduleForProgramKind(SkSL::ProgramKind::kFragment);
SkSL::IRGenerator& ir = *fCompiler->fIRGenerator;
ir.fSymbolTable = module.fSymbols;
ir.fSettings = &fSettings;

View File

@ -58,104 +58,72 @@ public:
SkTHashMap<const FunctionDeclaration*, int> fCallCounts;
};
/**
* Holds the compiler settings for a program.
*/
struct ProgramSettings {
// if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
// must be flipped.
bool fFlipY = false;
// If true the destination fragment color is read sk_FragColor. It must be declared inout.
bool fFragColorIsInOut = false;
// if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
// constant equivalents during compilation
bool fReplaceSettings = true;
// if true, all halfs are forced to be floats
bool fForceHighPrecision = false;
// if true, add -0.5 bias to LOD of all texture lookups
bool fSharpenTextures = false;
// if the program needs to create an RTHeight uniform, this is its offset in the uniform
// buffer
int fRTHeightOffset = -1;
// if the program needs to create an RTHeight uniform and is creating spriv, this is the
// binding and set number of the uniform buffer.
int fRTHeightBinding = -1;
int fRTHeightSet = -1;
// If layout(set=S, binding=B) is not specified for a uniform, these values will be used.
// At present, zero is always used by our backends.
int fDefaultUniformSet = 0;
int fDefaultUniformBinding = 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;
// Sets an upper limit on the acceptable amount of code growth from inlining.
// A value of zero will disable the inliner entirely.
int fInlineThreshold = SkSL::kDefaultInlineThreshold;
// true to enable optimization passes
bool fOptimize = true;
// If true, implicit conversions to lower precision numeric types are allowed
// (eg, float to half)
bool fAllowNarrowingConversions = false;
// If true, then Debug code will run SPIR-V output through the validator to ensure its
// correctness
bool fValidateSPIRV = true;
// If true, any synthetic uniforms must use push constant syntax
bool fUsePushConstants = false;
// Permits static if/switch statements to be used with non-constant tests. This is used when
// producing H and CPP code; the static tests don't have to have constant values *yet*, but
// the generated code will contain a static test which then does have to be a constant.
bool fPermitInvalidStaticTests = false;
};
/**
* SkSL supports several different program kinds.
*/
enum class ProgramKind : int8_t {
kFragment,
kVertex,
kGeometry,
kFragmentProcessor,
kRuntimeEffect,
kGeneric,
};
/**
* Represents a fully-digested program, ready for code generation.
*/
struct Program {
struct Settings {
struct Value {
Value(bool b)
: fKind(kBool_Kind)
, fValue(b) {}
Value(int i)
: fKind(kInt_Kind)
, fValue(i) {}
Value(unsigned int i)
: fKind(kInt_Kind)
, fValue(i) {}
Value(float f)
: fKind(kFloat_Kind)
, fValueF(f) {}
std::unique_ptr<Expression> literal(const Context& context, int offset) const {
switch (fKind) {
case Program::Settings::Value::kBool_Kind:
return std::unique_ptr<Expression>(new BoolLiteral(context,
offset,
fValue));
case Program::Settings::Value::kInt_Kind:
return std::unique_ptr<Expression>(new IntLiteral(context,
offset,
fValue));
case Program::Settings::Value::kFloat_Kind:
return std::unique_ptr<Expression>(new FloatLiteral(context,
offset,
fValueF));
default:
SkASSERT(false);
return nullptr;
}
}
enum {
kBool_Kind,
kInt_Kind,
kFloat_Kind,
} fKind;
union {
int fValue; // for kBool_Kind and kInt_Kind
float fValueF; // for kFloat_Kind
};
};
// if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate
// must be flipped.
bool fFlipY = false;
// If true the destination fragment color is read sk_FragColor. It must be declared inout.
bool fFragColorIsInOut = false;
// if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their
// constant equivalents during compilation
bool fReplaceSettings = true;
// if true, all halfs are forced to be floats
bool fForceHighPrecision = false;
// if true, add -0.5 bias to LOD of all texture lookups
bool fSharpenTextures = false;
// if the program needs to create an RTHeight uniform, this is its offset in the uniform
// buffer
int fRTHeightOffset = -1;
// if the program needs to create an RTHeight uniform and is creating spriv, this is the
// binding and set number of the uniform buffer.
int fRTHeightBinding = -1;
int fRTHeightSet = -1;
// If layout(set=S, binding=B) is not specified for a uniform, these values will be used.
// At present, zero is always used by our backends.
int fDefaultUniformSet = 0;
int fDefaultUniformBinding = 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;
// Sets an upper limit on the acceptable amount of code growth from inlining.
// A value of zero will disable the inliner entirely.
int fInlineThreshold = SkSL::kDefaultInlineThreshold;
// true to enable optimization passes
bool fOptimize = true;
// If true, implicit conversions to lower precision numeric types are allowed
// (eg, float to half)
bool fAllowNarrowingConversions = false;
// If true, then Debug code will run SPIR-V output through the validator to ensure its
// correctness
bool fValidateSPIRV = true;
// If true, any synthetic uniforms must use push constant syntax
bool fUsePushConstants = false;
// Permits static if/switch statements to be used with non-constant tests. This is used when
// producing H and CPP code; the static tests don't have to have constant values *yet*, but
// the generated code will contain a static test which then does have to be a constant.
bool fPermitInvalidStaticTests = false;
};
using Settings = ProgramSettings;
struct Inputs {
// if true, this program requires the render target width uniform to be defined
@ -179,16 +147,7 @@ struct Program {
}
};
enum Kind {
kFragment_Kind,
kVertex_Kind,
kGeometry_Kind,
kFragmentProcessor_Kind,
kRuntimeEffect_Kind,
kGeneric_Kind,
};
Program(Kind kind,
Program(ProgramKind kind,
std::unique_ptr<String> source,
Settings settings,
const ShaderCapsClass* caps,
@ -298,7 +257,7 @@ struct Program {
// The iterator's value type is 'std::unique_ptr<ProgramElement>', and mutation is allowed.
const std::vector<std::unique_ptr<ProgramElement>>& ownedElements() const { return fElements; }
Kind fKind;
ProgramKind fKind;
std::unique_ptr<String> fSource;
Settings fSettings;
const ShaderCapsClass* fCaps;

View File

@ -16,7 +16,7 @@ static void test(skiatest::Reporter* r, const GrShaderCaps& caps, const char* sr
SkSL::Compiler compiler(&caps);
SkSL::StringStream output;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kFragmentProcessor_Kind,
SkSL::ProgramKind::kFragmentProcessor,
SkSL::String(src),
settings);
if (!program) {

View File

@ -12,7 +12,7 @@
static void test(skiatest::Reporter* r,
const GrShaderCaps& caps,
const char* src,
SkSL::Program::Kind kind = SkSL::Program::kFragment_Kind) {
SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment) {
SkSL::Compiler compiler(&caps);
SkSL::Program::Settings settings;
SkSL::String output;

View File

@ -23,7 +23,7 @@ struct ProgramBuilder {
// For convenience, so we can test functions other than (and not called by) main.
settings.fRemoveDeadFunctions = false;
fProgram = fCompiler.convertProgram(SkSL::Program::kGeneric_Kind, SkSL::String(src),
fProgram = fCompiler.convertProgram(SkSL::ProgramKind::kGeneric, SkSL::String(src),
settings);
if (!fProgram) {
ERRORF(r, "Program failed to compile:\n%s\n%s\n", src, fCompiler.errorText().c_str());
@ -626,7 +626,7 @@ static void expect_failure(skiatest::Reporter* r, const char* src) {
GrShaderCaps caps(GrContextOptions{});
SkSL::Compiler compiler(&caps);
SkSL::Program::Settings settings;
auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind,
auto program = compiler.convertProgram(SkSL::ProgramKind::kGeneric,
SkSL::String(src), settings);
REPORTER_ASSERT(r, !program);
}
@ -906,7 +906,7 @@ DEF_TEST(SkSLInterpreterExternalFunction, r) {
std::vector<std::unique_ptr<SkSL::ExternalFunction>> externalFunctions;
externalFunctions.push_back(std::make_unique<ExternalSqrt>("external", compiler));
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kGeneric_Kind, SkSL::String(src), settings, &externalFunctions);
SkSL::ProgramKind::kGeneric, SkSL::String(src), settings, &externalFunctions);
REPORTER_ASSERT(r, program);
const SkSL::FunctionDefinition* main = SkSL::Program_GetFunction(*program, "main");
@ -964,7 +964,7 @@ DEF_TEST(SkSLInterpreterExternalTable, r) {
externalFunctions.push_back(std::make_unique<ExternalTable>("table", compiler, &u));
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kGeneric_Kind, SkSL::String(src), settings, &externalFunctions);
SkSL::ProgramKind::kGeneric, SkSL::String(src), settings, &externalFunctions);
REPORTER_ASSERT(r, program);
const SkSL::FunctionDefinition* main = SkSL::Program_GetFunction(*program, "main");

View File

@ -12,7 +12,7 @@
static void test(skiatest::Reporter* r,
const GrShaderCaps& caps,
const char* src,
SkSL::Program::Kind kind = SkSL::Program::kFragment_Kind) {
SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment) {
SkSL::Compiler compiler(&caps);
SkSL::Program::Settings settings;
SkSL::String output;

View File

@ -12,7 +12,7 @@
static void test(skiatest::Reporter* r,
const GrShaderCaps& caps,
const char* src,
SkSL::Program::Kind kind = SkSL::Program::kFragment_Kind) {
SkSL::ProgramKind kind = SkSL::ProgramKind::kFragment) {
SkSL::Compiler compiler(&caps);
SkSL::Program::Settings settings;
SkSL::String output;