initial checkin of SkSL compiler

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1984363002
CQ_EXTRA_TRYBOTS=client.skia.compile:Build-Ubuntu-GCC-x86_64-Release-CMake-Trybot,Build-Mac-Clang-x86_64-Release-CMake-Trybot

Review-Url: https://codereview.chromium.org/1984363002
This commit is contained in:
ethannicholas 2016-07-01 08:22:01 -07:00 committed by Commit bot
parent e7d1b24ff0
commit b3058bdb10
114 changed files with 15397 additions and 2 deletions

View File

@ -59,6 +59,9 @@ remove_srcs (../src/ports/SkFontHost_fontconfig.cpp
../src/ports/SkFontConfigInterface_direct_google3_factory.cpp)
# Alternative font managers.
remove_srcs (../src/ports/SkFontMgr_custom*.cpp)
# skslc main()
remove_srcs (../src/sksl/SkSLMain.cpp)
# Skia sure ships a lot of code no one uses.
remove_srcs (../src/animator/* ../src/*nacl* ../src/svg/* ../src/views/* ../src/xml/*)

View File

@ -88,6 +88,7 @@
'utils.gyp:utils',
'etc1.gyp:libetc1',
'ktx.gyp:libSkKTX',
'sksl.gyp:sksl',
],
'includes': [
'gpu.gypi',
@ -98,6 +99,7 @@
'../src/core',
'../src/gpu',
'../src/image/',
'../src/sksl',
],
'sources': [
'<@(skgpu_sources)',

View File

@ -27,6 +27,7 @@
'pathops_skpclip.gyp:*',
'dm.gyp:dm',
'fuzz.gyp:fuzz',
'skslc.gyp:skslc',
],
'conditions': [
[ 'skia_gpu == 0', {

24
gyp/sksl.gyp Normal file
View File

@ -0,0 +1,24 @@
# Copyright 2016 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'targets': [
{
'target_name': 'sksl',
'type': 'static_library',
'standalone_static_library': 1,
'includes': [
'sksl.gypi',
],
'defines': [
'SKIA'
],
'all_dependent_settings': {
'include_dirs': [
'../src/sksl',
],
},
},
],
}

22
gyp/sksl.gypi Normal file
View File

@ -0,0 +1,22 @@
# Copyright 2016 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'include_dirs': [
'../include',
'../include/config',
'../include/core',
'../include/private',
'../src/sksl',
],
'sources': [
'../src/sksl/SkSLCompiler.cpp',
'../src/sksl/SkSLIRGenerator.cpp',
'../src/sksl/SkSLParser.cpp',
'../src/sksl/SkSLSPIRVCodeGenerator.cpp',
'../src/sksl/SkSLUtil.cpp',
'../src/sksl/ir/SkSLSymbolTable.cpp',
'../src/sksl/ir/SkSLType.cpp',
],
}

28
gyp/skslc.gyp Normal file
View File

@ -0,0 +1,28 @@
# Copyright 2016 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'includes': [
'apptype_console.gypi',
],
'targets': [
{
'target_name': 'skslc',
'type': 'executable',
'includes' : [
'sksl.gypi',
],
'sources': [
'../src/sksl/SkSLMain.cpp',
],
'configurations': {
'Debug': {
'defines': [
'DEBUG',
],
},
},
},
],
}

View File

@ -36,6 +36,10 @@
#include "vk/GrVkInterface.h"
#include "vk/GrVkTypes.h"
#if USE_SKSL
#include "SkSLCompiler.h"
#endif
#define VK_CALL(X) GR_VK_CALL(this->vkInterface(), X)
#define VK_CALL_RET(RET, X) GR_VK_CALL_RET(this->vkInterface(), RET, X)
#define VK_CALL_ERRCHECK(X) GR_VK_CALL_ERRCHECK(this->vkInterface(), X)
@ -110,7 +114,11 @@ GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
}
#endif
#if USE_SKSL
fCompiler = new SkSL::Compiler();
#else
fCompiler = shaderc_compiler_initialize();
#endif
fVkCaps.reset(new GrVkCaps(options, this->vkInterface(), backendCtx->fPhysicalDevice,
backendCtx->fFeatures, backendCtx->fExtensions));
@ -176,7 +184,11 @@ GrVkGpu::~GrVkGpu() {
VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
#if USE_SKSL
delete fCompiler;
#else
shaderc_compiler_release(fCompiler);
#endif
#ifdef ENABLE_VK_LAYERS
if (fCallback) {

View File

@ -8,6 +8,8 @@
#ifndef GrVkGpu_DEFINED
#define GrVkGpu_DEFINED
#define USE_SKSL 1
#include "GrGpu.h"
#include "GrGpuFactory.h"
#include "vk/GrVkBackendContext.h"
@ -18,7 +20,14 @@
#include "GrVkVertexBuffer.h"
#include "GrVkUtil.h"
#if USE_SKSL
namespace SkSL {
class Compiler;
}
#else
#include "shaderc/shaderc.h"
#endif
#include "vk/GrVkDefines.h"
class GrPipeline;
@ -111,9 +120,15 @@ public:
bool byRegion,
VkImageMemoryBarrier* barrier) const;
#if USE_SKSL
SkSL::Compiler* shaderCompiler() const {
return fCompiler;
}
#else
shaderc_compiler_t shadercCompiler() const {
return fCompiler;
}
#endif
void submitSecondaryCommandBuffer(const GrVkSecondaryCommandBuffer*,
const GrVkRenderPass*,
@ -242,10 +257,13 @@ private:
VkDebugReportCallbackEXT fCallback;
#endif
#if USE_SKSL
SkSL::Compiler* fCompiler;
#else
// Shaderc compiler used for compiling glsl in spirv. We only want to create the compiler once
// since there is significant overhead to the first compile of any compiler.
shaderc_compiler_t fCompiler;
#endif
typedef GrGpu INHERITED;
};

View File

@ -9,6 +9,9 @@
#include "vk/GrVkGpu.h"
#include "vk/GrVkRenderPass.h"
#if USE_SKSL
#include "SkSLCompiler.h"
#endif
GrVkPipelineState* GrVkPipelineStateBuilder::CreatePipelineState(
GrVkGpu* gpu,
@ -72,6 +75,15 @@ VkShaderStageFlags visibility_to_vk_stage_flags(uint32_t visibility) {
return flags;
}
#if USE_SKSL
SkSL::Program::Kind vk_shader_stage_to_skiasl_kind(VkShaderStageFlagBits stage) {
if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
return SkSL::Program::kVertex_Kind;
}
SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
return SkSL::Program::kFragment_Kind;
}
#else
shaderc_shader_kind vk_shader_stage_to_shaderc_kind(VkShaderStageFlagBits stage) {
if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
return shaderc_glsl_vertex_shader;
@ -79,7 +91,10 @@ shaderc_shader_kind vk_shader_stage_to_shaderc_kind(VkShaderStageFlagBits stage)
SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
return shaderc_glsl_fragment_shader;
}
#endif
#include <fstream>
#include <sstream>
bool GrVkPipelineStateBuilder::CreateVkShaderModule(const GrVkGpu* gpu,
VkShaderStageFlagBits stage,
const GrGLSLShaderBuilder& builder,
@ -99,13 +114,28 @@ bool GrVkPipelineStateBuilder::CreateVkShaderModule(const GrVkGpu* gpu,
moduleCreateInfo.pNext = nullptr;
moduleCreateInfo.flags = 0;
#if USE_SKSL
std::string code;
#else
shaderc_compilation_result_t result = nullptr;
#endif
if (gpu->vkCaps().canUseGLSLForShaderModule()) {
moduleCreateInfo.codeSize = strlen(shaderString.c_str());
moduleCreateInfo.pCode = (const uint32_t*)shaderString.c_str();
} else {
#if USE_SKSL
bool result = gpu->shaderCompiler()->toSPIRV(vk_shader_stage_to_skiasl_kind(stage),
std::string(shaderString.c_str()),
&code);
if (!result) {
SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
return false;
}
moduleCreateInfo.codeSize = code.size();
moduleCreateInfo.pCode = (const uint32_t*) code.c_str();
#else
shaderc_compiler_t compiler = gpu->shadercCompiler();
shaderc_compile_options_t options = shaderc_compile_options_initialize();
@ -125,18 +155,22 @@ bool GrVkPipelineStateBuilder::CreateVkShaderModule(const GrVkGpu* gpu,
SkDebugf("%s\n", shaderc_result_get_error_message(result));
return false;
}
#endif
#endif // SK_DEBUG
moduleCreateInfo.codeSize = shaderc_result_get_length(result);
moduleCreateInfo.pCode = (const uint32_t*)shaderc_result_get_bytes(result);
#endif // USE_SKSL
}
VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateShaderModule(gpu->device(),
&moduleCreateInfo,
nullptr,
shaderModule));
if (!gpu->vkCaps().canUseGLSLForShaderModule()) {
#if !USE_SKSL
shaderc_result_release(result);
#endif
}
if (err) {
return false;

131
src/sksl/GLSL.std.450.h Normal file
View File

@ -0,0 +1,131 @@
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
** to deal in the Materials without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Materials, and to permit persons to whom the
** Materials are furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Materials.
**
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
** IN THE MATERIALS.
*/
#ifndef GLSLstd450_H
#define GLSLstd450_H
static const int GLSLstd450Version = 100;
static const int GLSLstd450Revision = 3;
enum GLSLstd450 {
GLSLstd450Bad = 0, // Don't use
GLSLstd450Round = 1,
GLSLstd450RoundEven = 2,
GLSLstd450Trunc = 3,
GLSLstd450FAbs = 4,
GLSLstd450SAbs = 5,
GLSLstd450FSign = 6,
GLSLstd450SSign = 7,
GLSLstd450Floor = 8,
GLSLstd450Ceil = 9,
GLSLstd450Fract = 10,
GLSLstd450Radians = 11,
GLSLstd450Degrees = 12,
GLSLstd450Sin = 13,
GLSLstd450Cos = 14,
GLSLstd450Tan = 15,
GLSLstd450Asin = 16,
GLSLstd450Acos = 17,
GLSLstd450Atan = 18,
GLSLstd450Sinh = 19,
GLSLstd450Cosh = 20,
GLSLstd450Tanh = 21,
GLSLstd450Asinh = 22,
GLSLstd450Acosh = 23,
GLSLstd450Atanh = 24,
GLSLstd450Atan2 = 25,
GLSLstd450Pow = 26,
GLSLstd450Exp = 27,
GLSLstd450Log = 28,
GLSLstd450Exp2 = 29,
GLSLstd450Log2 = 30,
GLSLstd450Sqrt = 31,
GLSLstd450InverseSqrt = 32,
GLSLstd450Determinant = 33,
GLSLstd450MatrixInverse = 34,
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
GLSLstd450ModfStruct = 36, // no OpVariable operand
GLSLstd450FMin = 37,
GLSLstd450UMin = 38,
GLSLstd450SMin = 39,
GLSLstd450FMax = 40,
GLSLstd450UMax = 41,
GLSLstd450SMax = 42,
GLSLstd450FClamp = 43,
GLSLstd450UClamp = 44,
GLSLstd450SClamp = 45,
GLSLstd450FMix = 46,
GLSLstd450IMix = 47, // Reserved
GLSLstd450Step = 48,
GLSLstd450SmoothStep = 49,
GLSLstd450Fma = 50,
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
GLSLstd450FrexpStruct = 52, // no OpVariable operand
GLSLstd450Ldexp = 53,
GLSLstd450PackSnorm4x8 = 54,
GLSLstd450PackUnorm4x8 = 55,
GLSLstd450PackSnorm2x16 = 56,
GLSLstd450PackUnorm2x16 = 57,
GLSLstd450PackHalf2x16 = 58,
GLSLstd450PackDouble2x32 = 59,
GLSLstd450UnpackSnorm2x16 = 60,
GLSLstd450UnpackUnorm2x16 = 61,
GLSLstd450UnpackHalf2x16 = 62,
GLSLstd450UnpackSnorm4x8 = 63,
GLSLstd450UnpackUnorm4x8 = 64,
GLSLstd450UnpackDouble2x32 = 65,
GLSLstd450Length = 66,
GLSLstd450Distance = 67,
GLSLstd450Cross = 68,
GLSLstd450Normalize = 69,
GLSLstd450FaceForward = 70,
GLSLstd450Reflect = 71,
GLSLstd450Refract = 72,
GLSLstd450FindILsb = 73,
GLSLstd450FindSMsb = 74,
GLSLstd450FindUMsb = 75,
GLSLstd450InterpolateAtCentroid = 76,
GLSLstd450InterpolateAtSample = 77,
GLSLstd450InterpolateAtOffset = 78,
GLSLstd450NMin = 79,
GLSLstd450NMax = 80,
GLSLstd450NClamp = 81,
GLSLstd450Count
};
#endif // #ifndef GLSLstd450_H

View File

@ -0,0 +1,30 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_CODEGENERATOR
#define SKSL_CODEGENERATOR
#include "ir/SkSLProgram.h"
#include <vector>
#include <iostream>
namespace SkSL {
/**
* Abstract superclass of all code generators, which take a Program as input and produce code as
* output.
*/
class CodeGenerator {
public:
virtual ~CodeGenerator() {}
virtual void generateCode(Program& program, std::ostream& out) = 0;
};
} // namespace
#endif

243
src/sksl/SkSLCompiler.cpp Normal file
View File

@ -0,0 +1,243 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLCompiler.h"
#include <fstream>
#include <streambuf>
#include "SkSLIRGenerator.h"
#include "SkSLParser.h"
#include "SkSLSPIRVCodeGenerator.h"
#include "ir/SkSLExpression.h"
#include "ir/SkSLIntLiteral.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLVarDeclaration.h"
#include "SkMutex.h"
#define STRINGIFY(x) #x
// include the built-in shader symbols as static strings
static std::string SKSL_INCLUDE =
#include "sksl.include"
;
static std::string SKSL_VERT_INCLUDE =
#include "sksl_vert.include"
;
static std::string SKSL_FRAG_INCLUDE =
#include "sksl_frag.include"
;
namespace SkSL {
Compiler::Compiler()
: fErrorCount(0) {
auto types = std::shared_ptr<SymbolTable>(new SymbolTable(*this));
auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, *this));
fIRGenerator = new IRGenerator(symbols, *this);
fTypes = types;
#define ADD_TYPE(t) types->add(k ## t ## _Type->fName, k ## t ## _Type)
ADD_TYPE(Void);
ADD_TYPE(Float);
ADD_TYPE(Vec2);
ADD_TYPE(Vec3);
ADD_TYPE(Vec4);
ADD_TYPE(Double);
ADD_TYPE(DVec2);
ADD_TYPE(DVec3);
ADD_TYPE(DVec4);
ADD_TYPE(Int);
ADD_TYPE(IVec2);
ADD_TYPE(IVec3);
ADD_TYPE(IVec4);
ADD_TYPE(UInt);
ADD_TYPE(UVec2);
ADD_TYPE(UVec3);
ADD_TYPE(UVec4);
ADD_TYPE(Bool);
ADD_TYPE(BVec2);
ADD_TYPE(BVec3);
ADD_TYPE(BVec4);
ADD_TYPE(Mat2x2);
ADD_TYPE(Mat2x3);
ADD_TYPE(Mat2x4);
ADD_TYPE(Mat3x2);
ADD_TYPE(Mat3x3);
ADD_TYPE(Mat3x4);
ADD_TYPE(Mat4x2);
ADD_TYPE(Mat4x3);
ADD_TYPE(Mat4x4);
ADD_TYPE(GenType);
ADD_TYPE(GenDType);
ADD_TYPE(GenIType);
ADD_TYPE(GenUType);
ADD_TYPE(GenBType);
ADD_TYPE(Mat);
ADD_TYPE(Vec);
ADD_TYPE(GVec);
ADD_TYPE(GVec2);
ADD_TYPE(GVec3);
ADD_TYPE(GVec4);
ADD_TYPE(DVec);
ADD_TYPE(IVec);
ADD_TYPE(UVec);
ADD_TYPE(BVec);
ADD_TYPE(Sampler1D);
ADD_TYPE(Sampler2D);
ADD_TYPE(Sampler3D);
ADD_TYPE(SamplerCube);
ADD_TYPE(Sampler2DRect);
ADD_TYPE(Sampler1DArray);
ADD_TYPE(Sampler2DArray);
ADD_TYPE(SamplerCubeArray);
ADD_TYPE(SamplerBuffer);
ADD_TYPE(Sampler2DMS);
ADD_TYPE(Sampler2DMSArray);
ADD_TYPE(GSampler1D);
ADD_TYPE(GSampler2D);
ADD_TYPE(GSampler3D);
ADD_TYPE(GSamplerCube);
ADD_TYPE(GSampler2DRect);
ADD_TYPE(GSampler1DArray);
ADD_TYPE(GSampler2DArray);
ADD_TYPE(GSamplerCubeArray);
ADD_TYPE(GSamplerBuffer);
ADD_TYPE(GSampler2DMS);
ADD_TYPE(GSampler2DMSArray);
ADD_TYPE(Sampler1DShadow);
ADD_TYPE(Sampler2DShadow);
ADD_TYPE(SamplerCubeShadow);
ADD_TYPE(Sampler2DRectShadow);
ADD_TYPE(Sampler1DArrayShadow);
ADD_TYPE(Sampler2DArrayShadow);
ADD_TYPE(SamplerCubeArrayShadow);
ADD_TYPE(GSampler2DArrayShadow);
ADD_TYPE(GSamplerCubeArrayShadow);
std::vector<std::unique_ptr<ProgramElement>> ignored;
this->internalConvertProgram(SKSL_INCLUDE, &ignored);
ASSERT(!fErrorCount);
}
Compiler::~Compiler() {
delete fIRGenerator;
}
void Compiler::internalConvertProgram(std::string text,
std::vector<std::unique_ptr<ProgramElement>>* result) {
Parser parser(text, *fTypes, *this);
std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
if (fErrorCount) {
return;
}
for (size_t i = 0; i < parsed.size(); i++) {
ASTDeclaration& decl = *parsed[i];
switch (decl.fKind) {
case ASTDeclaration::kVar_Kind: {
std::unique_ptr<VarDeclaration> s = fIRGenerator->convertVarDeclaration(
(ASTVarDeclaration&) decl,
Variable::kGlobal_Storage);
if (s) {
result->push_back(std::move(s));
}
break;
}
case ASTDeclaration::kFunction_Kind: {
std::unique_ptr<FunctionDefinition> f = fIRGenerator->convertFunction(
(ASTFunction&) decl);
if (f) {
result->push_back(std::move(f));
}
break;
}
case ASTDeclaration::kInterfaceBlock_Kind: {
std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock(
(ASTInterfaceBlock&) decl);
if (i) {
result->push_back(std::move(i));
}
break;
}
case ASTDeclaration::kExtension_Kind: {
std::unique_ptr<Extension> e = fIRGenerator->convertExtension((ASTExtension&) decl);
if (e) {
result->push_back(std::move(e));
}
break;
}
default:
ABORT("unsupported declaration: %s\n", decl.description().c_str());
}
}
}
std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, std::string text) {
fErrorText = "";
fErrorCount = 0;
fIRGenerator->pushSymbolTable();
std::vector<std::unique_ptr<ProgramElement>> result;
switch (kind) {
case Program::kVertex_Kind:
this->internalConvertProgram(SKSL_VERT_INCLUDE, &result);
break;
case Program::kFragment_Kind:
this->internalConvertProgram(SKSL_FRAG_INCLUDE, &result);
break;
}
this->internalConvertProgram(text, &result);
fIRGenerator->popSymbolTable();
this->writeErrorCount();
return std::unique_ptr<Program>(new Program(kind, std::move(result)));;
}
void Compiler::error(Position position, std::string msg) {
fErrorCount++;
fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
}
std::string Compiler::errorText() {
std::string result = fErrorText;
return result;
}
void Compiler::writeErrorCount() {
if (fErrorCount) {
fErrorText += to_string(fErrorCount) + " error";
if (fErrorCount > 1) {
fErrorText += "s";
}
fErrorText += "\n";
}
}
#include <fstream>
bool Compiler::toSPIRV(Program::Kind kind, std::string text, std::ostream& out) {
auto program = this->convertProgram(kind, text);
if (fErrorCount == 0) {
SkSL::SPIRVCodeGenerator cg;
cg.generateCode(*program.get(), out);
ASSERT(!out.rdstate());
}
return fErrorCount == 0;
}
bool Compiler::toSPIRV(Program::Kind kind, std::string text, std::string* out) {
std::stringstream buffer;
bool result = this->toSPIRV(kind, text, buffer);
if (result) {
*out = buffer.str();
}
return fErrorCount == 0;
}
} // namespace

59
src/sksl/SkSLCompiler.h Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_COMPILER
#define SKSL_COMPILER
#include <vector>
#include "ir/SkSLProgram.h"
#include "ir/SkSLSymbolTable.h"
#include "SkSLErrorReporter.h"
namespace SkSL {
class IRGenerator;
/**
* Main compiler entry point. This is a traditional compiler design which first parses the .sksl
* file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to
* produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce
* compiled output.
*/
class Compiler : public ErrorReporter {
public:
Compiler();
~Compiler();
std::unique_ptr<Program> convertProgram(Program::Kind kind, std::string text);
bool toSPIRV(Program::Kind kind, std::string text, std::ostream& out);
bool toSPIRV(Program::Kind kind, std::string text, std::string* out);
void error(Position position, std::string msg) override;
std::string errorText();
void writeErrorCount();
private:
void internalConvertProgram(std::string text,
std::vector<std::unique_ptr<ProgramElement>>* result);
std::shared_ptr<SymbolTable> fTypes;
IRGenerator* fIRGenerator;
std::string fSkiaVertText; // FIXME store parsed version instead
int fErrorCount;
std::string fErrorText;
};
} // namespace
#endif

View File

@ -0,0 +1,27 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ERRORREPORTER
#define SKSL_ERRORREPORTER
#include "SkSLPosition.h"
namespace SkSL {
/**
* Interface for the compiler to report errors.
*/
class ErrorReporter {
public:
virtual ~ErrorReporter() {}
virtual void error(Position position, std::string msg) = 0;
};
} // namespace
#endif

1217
src/sksl/SkSLIRGenerator.cpp Normal file

File diff suppressed because it is too large Load Diff

122
src/sksl/SkSLIRGenerator.h Normal file
View File

@ -0,0 +1,122 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_IRGENERATOR
#define SKSL_IRGENERATOR
#include "SkSLErrorReporter.h"
#include "ast/SkSLASTBinaryExpression.h"
#include "ast/SkSLASTBlock.h"
#include "ast/SkSLASTBreakStatement.h"
#include "ast/SkSLASTCallSuffix.h"
#include "ast/SkSLASTContinueStatement.h"
#include "ast/SkSLASTDiscardStatement.h"
#include "ast/SkSLASTDoStatement.h"
#include "ast/SkSLASTExpression.h"
#include "ast/SkSLASTExpressionStatement.h"
#include "ast/SkSLASTExtension.h"
#include "ast/SkSLASTForStatement.h"
#include "ast/SkSLASTFunction.h"
#include "ast/SkSLASTIdentifier.h"
#include "ast/SkSLASTIfStatement.h"
#include "ast/SkSLASTInterfaceBlock.h"
#include "ast/SkSLASTModifiers.h"
#include "ast/SkSLASTPrefixExpression.h"
#include "ast/SkSLASTReturnStatement.h"
#include "ast/SkSLASTStatement.h"
#include "ast/SkSLASTSuffixExpression.h"
#include "ast/SkSLASTTernaryExpression.h"
#include "ast/SkSLASTVarDeclaration.h"
#include "ast/SkSLASTVarDeclarationStatement.h"
#include "ast/SkSLASTWhileStatement.h"
#include "ir/SkSLBlock.h"
#include "ir/SkSLExpression.h"
#include "ir/SkSLExtension.h"
#include "ir/SkSLFunctionDefinition.h"
#include "ir/SkSLInterfaceBlock.h"
#include "ir/SkSLModifiers.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLType.h"
#include "ir/SkSLTypeReference.h"
#include "ir/SkSLVarDeclaration.h"
namespace SkSL {
/**
* Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
* (unoptimized) intermediate representation (IR).
*/
class IRGenerator {
public:
IRGenerator(std::shared_ptr<SymbolTable> root, ErrorReporter& errorReporter);
std::unique_ptr<VarDeclaration> convertVarDeclaration(const ASTVarDeclaration& decl,
Variable::Storage storage);
std::unique_ptr<FunctionDefinition> convertFunction(const ASTFunction& f);
std::unique_ptr<Statement> convertStatement(const ASTStatement& statement);
std::unique_ptr<Expression> convertExpression(const ASTExpression& expression);
private:
void pushSymbolTable();
void popSymbolTable();
std::shared_ptr<Type> convertType(const ASTType& type);
std::unique_ptr<Expression> call(Position position,
std::shared_ptr<FunctionDeclaration> function,
std::vector<std::unique_ptr<Expression>> arguments);
bool determineCallCost(std::shared_ptr<FunctionDeclaration> function,
const std::vector<std::unique_ptr<Expression>>& arguments,
int* outCost);
std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
std::vector<std::unique_ptr<Expression>> arguments);
std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr,
std::shared_ptr<Type> type);
std::unique_ptr<Block> convertBlock(const ASTBlock& block);
std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b);
std::unique_ptr<Expression> convertConstructor(Position position,
std::shared_ptr<Type> type,
std::vector<std::unique_ptr<Expression>> params);
std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
std::unique_ptr<Statement> convertDiscard(const ASTDiscardStatement& d);
std::unique_ptr<Statement> convertDo(const ASTDoStatement& d);
std::unique_ptr<Expression> convertBinaryExpression(const ASTBinaryExpression& expression);
std::unique_ptr<Extension> convertExtension(const ASTExtension& e);
std::unique_ptr<Statement> convertExpressionStatement(const ASTExpressionStatement& s);
std::unique_ptr<Statement> convertFor(const ASTForStatement& f);
std::unique_ptr<Expression> convertIdentifier(const ASTIdentifier& identifier);
std::unique_ptr<Statement> convertIf(const ASTIfStatement& s);
std::unique_ptr<Expression> convertIndex(std::unique_ptr<Expression> base,
const ASTExpression& index);
std::unique_ptr<InterfaceBlock> convertInterfaceBlock(const ASTInterfaceBlock& s);
Modifiers convertModifiers(const ASTModifiers& m);
std::unique_ptr<Expression> convertPrefixExpression(const ASTPrefixExpression& expression);
std::unique_ptr<Statement> convertReturn(const ASTReturnStatement& r);
std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression);
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
const std::string& field);
std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base,
const std::string& fields);
std::unique_ptr<Expression> convertTernaryExpression(const ASTTernaryExpression& expression);
std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTVarDeclarationStatement& s);
std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w);
void checkValid(const Expression& expr);
void markReadFrom(std::shared_ptr<Variable> var);
void markWrittenTo(const Expression& expr);
std::shared_ptr<FunctionDeclaration> fCurrentFunction;
std::shared_ptr<SymbolTable> fSymbolTable;
ErrorReporter& fErrors;
friend class AutoSymbolTable;
friend class Compiler;
};
}
#endif

48
src/sksl/SkSLMain.cpp Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "stdio.h"
#include <fstream>
#include "SkSLCompiler.h"
/**
* Very simple standalone executable to facilitate testing.
*/
int main(int argc, const char** argv) {
if (argc != 3) {
printf("usage: skslc <input> <output>\n");
exit(1);
}
SkSL::Program::Kind kind;
size_t len = strlen(argv[1]);
if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".vert")) {
kind = SkSL::Program::kVertex_Kind;
} else if (len > 5 && !strcmp(argv[1] + strlen(argv[1]) - 5, ".frag")) {
kind = SkSL::Program::kFragment_Kind;
} else {
printf("input filename must end in '.vert' or '.frag'\n");
exit(1);
}
std::ifstream in(argv[1]);
std::string text((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
if (in.rdstate()) {
printf("error reading '%s'\n", argv[1]);
exit(2);
}
std::ofstream out(argv[2], std::ofstream::binary);
SkSL::Compiler compiler;
if (!compiler.toSPIRV(kind, text, out)) {
printf("%s", compiler.errorText().c_str());
exit(3);
}
if (out.rdstate()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
}
}

1389
src/sksl/SkSLParser.cpp Normal file

File diff suppressed because it is too large Load Diff

209
src/sksl/SkSLParser.h Normal file
View File

@ -0,0 +1,209 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_PARSER
#define SKSL_PARSER
#include <string>
#include <vector>
#include <memory>
#include <unordered_set>
#include "SkSLErrorReporter.h"
#include "SkSLToken.h"
struct yy_buffer_state;
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
namespace SkSL {
struct ASTBlock;
struct ASTBreakStatement;
struct ASTContinueStatement;
struct ASTDeclaration;
struct ASTDiscardStatement;
struct ASTDoStatement;
struct ASTExpression;
struct ASTExpressionStatement;
struct ASTForStatement;
struct ASTIfStatement;
struct ASTInterfaceBlock;
struct ASTLayout;
struct ASTModifiers;
struct ASTParameter;
struct ASTReturnStatement;
struct ASTStatement;
struct ASTSuffix;
struct ASTType;
struct ASTWhileStatement;
struct ASTVarDeclaration;
class SymbolTable;
/**
* Consumes .sksl text and produces an abstract syntax tree describing the contents.
*/
class Parser {
public:
Parser(std::string text, SymbolTable& types, ErrorReporter& errors);
~Parser();
/**
* Consumes a complete .sksl file and produces a list of declarations. Errors are reported via
* the ErrorReporter; the return value may contain some declarations even when errors have
* occurred.
*/
std::vector<std::unique_ptr<ASTDeclaration>> file();
private:
/**
* Return the next token from the parse stream.
*/
Token nextToken();
/**
* Push a token back onto the parse stream, so that it is the next one read. Only a single level
* of pushback is supported (that is, it is an error to call pushback() twice in a row without
* an intervening nextToken()).
*/
void pushback(Token t);
/**
* Returns the next token without consuming it from the stream.
*/
Token peek();
/**
* Reads the next token and generates an error if it is not the expected type. The 'expected'
* string is part of the error message, which reads:
*
* "expected <expected>, but found '<actual text>'"
*
* If 'result' is non-null, it is set to point to the token that was read.
* Returns true if the read token was as expected, false otherwise.
*/
bool expect(Token::Kind kind, std::string expected, Token* result = nullptr);
void error(Position p, std::string msg);
/**
* Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
* always return true.
*/
bool isType(std::string name);
// these functions parse individual grammar rules from the current parse position; you probably
// don't need to call any of these outside of the parser. The function declarations in the .cpp
// file have comments describing the grammar rules.
void precision();
std::unique_ptr<ASTDeclaration> directive();
std::unique_ptr<ASTDeclaration> declaration();
std::unique_ptr<ASTVarDeclaration> varDeclaration();
std::unique_ptr<ASTType> structDeclaration();
std::unique_ptr<ASTVarDeclaration> structVarDeclaration(ASTModifiers modifiers);
std::unique_ptr<ASTVarDeclaration> varDeclarationEnd(ASTModifiers modifiers,
std::unique_ptr<ASTType> type,
std::string name);
std::unique_ptr<ASTParameter> parameter();
int layoutInt();
ASTLayout layout();
ASTModifiers modifiers();
ASTModifiers modifiersWithDefaults(int defaultFlags);
std::unique_ptr<ASTStatement> statement();
std::unique_ptr<ASTType> type();
std::unique_ptr<ASTDeclaration> interfaceBlock(ASTModifiers mods);
std::unique_ptr<ASTIfStatement> ifStatement();
std::unique_ptr<ASTDoStatement> doStatement();
std::unique_ptr<ASTWhileStatement> whileStatement();
std::unique_ptr<ASTForStatement> forStatement();
std::unique_ptr<ASTReturnStatement> returnStatement();
std::unique_ptr<ASTBreakStatement> breakStatement();
std::unique_ptr<ASTContinueStatement> continueStatement();
std::unique_ptr<ASTDiscardStatement> discardStatement();
std::unique_ptr<ASTBlock> block();
std::unique_ptr<ASTExpressionStatement> expressionStatement();
std::unique_ptr<ASTExpression> expression();
std::unique_ptr<ASTExpression> assignmentExpression();
std::unique_ptr<ASTExpression> ternaryExpression();
std::unique_ptr<ASTExpression> logicalOrExpression();
std::unique_ptr<ASTExpression> logicalXorExpression();
std::unique_ptr<ASTExpression> logicalAndExpression();
std::unique_ptr<ASTExpression> bitwiseOrExpression();
std::unique_ptr<ASTExpression> bitwiseXorExpression();
std::unique_ptr<ASTExpression> bitwiseAndExpression();
std::unique_ptr<ASTExpression> equalityExpression();
std::unique_ptr<ASTExpression> relationalExpression();
std::unique_ptr<ASTExpression> shiftExpression();
std::unique_ptr<ASTExpression> additiveExpression();
std::unique_ptr<ASTExpression> multiplicativeExpression();
std::unique_ptr<ASTExpression> unaryExpression();
std::unique_ptr<ASTExpression> postfixExpression();
std::unique_ptr<ASTSuffix> suffix();
std::unique_ptr<ASTExpression> term();
bool intLiteral(int64_t* dest);
bool floatLiteral(double* dest);
bool boolLiteral(bool* dest);
bool identifier(std::string* dest);
void* fScanner;
YY_BUFFER_STATE fBuffer;
Token fPushback;
SymbolTable& fTypes;
ErrorReporter& fErrors;
};
} // namespace
#endif

38
src/sksl/SkSLPosition.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_POSITION
#define SKSL_POSITION
#include "SkSLUtil.h"
namespace SkSL {
/**
* Represents a position in the source code. Both line and column are one-based. Column is currently
* ignored.
*/
struct Position {
Position()
: fLine(-1)
, fColumn(-1) {}
Position(int line, int column)
: fLine(line)
, fColumn(column) {}
std::string description() const {
return to_string(fLine);
}
int fLine;
int fColumn;
};
} // namespace
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,264 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SPIRVCODEGENERATOR
#define SKSL_SPIRVCODEGENERATOR
#include <sstream>
#include <stack>
#include <tuple>
#include <unordered_map>
#include "SkSLCodeGenerator.h"
#include "ir/SkSLBinaryExpression.h"
#include "ir/SkSLBoolLiteral.h"
#include "ir/SkSLConstructor.h"
#include "ir/SkSLFloatLiteral.h"
#include "ir/SkSLIfStatement.h"
#include "ir/SkSLIndexExpression.h"
#include "ir/SkSLInterfaceBlock.h"
#include "ir/SkSLIntLiteral.h"
#include "ir/SkSLFieldAccess.h"
#include "ir/SkSLForStatement.h"
#include "ir/SkSLFunctionCall.h"
#include "ir/SkSLFunctionDeclaration.h"
#include "ir/SkSLFunctionDefinition.h"
#include "ir/SkSLPrefixExpression.h"
#include "ir/SkSLPostfixExpression.h"
#include "ir/SkSLProgramElement.h"
#include "ir/SkSLReturnStatement.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLSwizzle.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLVarDeclaration.h"
#include "ir/SkSLVarDeclarationStatement.h"
#include "ir/SkSLVariableReference.h"
#include "spirv.h"
namespace SkSL {
#define kLast_Capability SpvCapabilityMultiViewport
/**
* Converts a Program into a SPIR-V binary.
*/
class SPIRVCodeGenerator : public CodeGenerator {
public:
class LValue {
public:
virtual ~LValue() {}
// returns a pointer to the lvalue, if possible. If the lvalue cannot be directly referenced
// by a pointer (e.g. vector swizzles), returns 0.
virtual SpvId getPointer() = 0;
virtual SpvId load(std::ostream& out) = 0;
virtual void store(SpvId value, std::ostream& out) = 0;
};
SPIRVCodeGenerator()
: fCapabilities(1 << SpvCapabilityShader)
, fIdCount(1)
, fBoolTrue(0)
, fBoolFalse(0)
, fCurrentBlock(0) {
this->setupIntrinsics();
}
void generateCode(Program& program, std::ostream& out) override;
private:
enum IntrinsicKind {
kGLSL_STD_450_IntrinsicKind,
kSPIRV_IntrinsicKind,
kSpecial_IntrinsicKind
};
enum SpecialIntrinsic {
kAtan_SpecialIntrinsic,
kTexture_SpecialIntrinsic,
kTexture2D_SpecialIntrinsic,
kTextureProj_SpecialIntrinsic
};
void setupIntrinsics();
SpvId nextId();
SpvId getType(const Type& type);
SpvId getFunctionType(std::shared_ptr<FunctionDeclaration> function);
SpvId getPointerType(std::shared_ptr<Type> type, SpvStorageClass_ storageClass);
std::vector<SpvId> getAccessChain(Expression& expr, std::ostream& out);
void writeLayout(const Layout& layout, SpvId target);
void writeLayout(const Layout& layout, SpvId target, int member);
void writeStruct(const Type& type, SpvId resultId);
void writeProgramElement(ProgramElement& pe, std::ostream& out);
SpvId writeInterfaceBlock(InterfaceBlock& intf);
SpvId writeFunctionStart(std::shared_ptr<FunctionDeclaration> f, std::ostream& out);
SpvId writeFunctionDeclaration(std::shared_ptr<FunctionDeclaration> f, std::ostream& out);
SpvId writeFunction(FunctionDefinition& f, std::ostream& out);
void writeGlobalVars(VarDeclaration& v, std::ostream& out);
void writeVarDeclaration(VarDeclaration& decl, std::ostream& out);
SpvId writeVariableReference(VariableReference& ref, std::ostream& out);
std::unique_ptr<LValue> getLValue(Expression& value, std::ostream& out);
SpvId writeExpression(Expression& expr, std::ostream& out);
SpvId writeIntrinsicCall(FunctionCall& c, std::ostream& out);
SpvId writeFunctionCall(FunctionCall& c, std::ostream& out);
SpvId writeSpecialIntrinsic(FunctionCall& c, SpecialIntrinsic kind, std::ostream& out);
SpvId writeConstantVector(Constructor& c);
SpvId writeFloatConstructor(Constructor& c, std::ostream& out);
SpvId writeIntConstructor(Constructor& c, std::ostream& out);
SpvId writeMatrixConstructor(Constructor& c, std::ostream& out);
SpvId writeVectorConstructor(Constructor& c, std::ostream& out);
SpvId writeConstructor(Constructor& c, std::ostream& out);
SpvId writeFieldAccess(FieldAccess& f, std::ostream& out);
SpvId writeSwizzle(Swizzle& swizzle, std::ostream& out);
SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs,
SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
SpvOp_ ifBool, std::ostream& out);
SpvId writeBinaryOperation(BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
std::ostream& out);
SpvId writeBinaryExpression(BinaryExpression& b, std::ostream& out);
SpvId writeTernaryExpression(TernaryExpression& t, std::ostream& out);
SpvId writeIndexExpression(IndexExpression& expr, std::ostream& out);
SpvId writeLogicalAnd(BinaryExpression& b, std::ostream& out);
SpvId writeLogicalOr(BinaryExpression& o, std::ostream& out);
SpvId writePrefixExpression(PrefixExpression& p, std::ostream& out);
SpvId writePostfixExpression(PostfixExpression& p, std::ostream& out);
SpvId writeBoolLiteral(BoolLiteral& b);
SpvId writeIntLiteral(IntLiteral& i);
SpvId writeFloatLiteral(FloatLiteral& f);
void writeStatement(Statement& s, std::ostream& out);
void writeBlock(Block& b, std::ostream& out);
void writeIfStatement(IfStatement& stmt, std::ostream& out);
void writeForStatement(ForStatement& f, std::ostream& out);
void writeReturnStatement(ReturnStatement& r, std::ostream& out);
void writeCapabilities(std::ostream& out);
void writeInstructions(Program& program, std::ostream& out);
void writeOpCode(SpvOp_ opCode, int length, std::ostream& out);
void writeWord(int32_t word, std::ostream& out);
void writeString(const char* string, std::ostream& out);
void writeLabel(SpvId id, std::ostream& out);
void writeInstruction(SpvOp_ opCode, std::ostream& out);
void writeInstruction(SpvOp_ opCode, const char* string, std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, const char* string, std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, const char* string,
std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
int32_t word5, std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
int32_t word5, int32_t word6, std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
int32_t word5, int32_t word6, int32_t word7, std::ostream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
int32_t word5, int32_t word6, int32_t word7, int32_t word8,
std::ostream& out);
uint64_t fCapabilities;
SpvId fIdCount;
SpvId fGLSLExtendedInstructions;
typedef std::tuple<IntrinsicKind, int32_t, int32_t, int32_t, int32_t> Intrinsic;
std::unordered_map<std::string, Intrinsic> fIntrinsicMap;
std::unordered_map<std::shared_ptr<FunctionDeclaration>, SpvId> fFunctionMap;
std::unordered_map<std::shared_ptr<Variable>, SpvId> fVariableMap;
std::unordered_map<std::shared_ptr<Variable>, int32_t> fInterfaceBlockMap;
std::unordered_map<std::string, SpvId> fTypeMap;
std::stringstream fCapabilitiesBuffer;
std::stringstream fGlobalInitializersBuffer;
std::stringstream fConstantBuffer;
std::stringstream fExternalFunctionsBuffer;
std::stringstream fVariableBuffer;
std::stringstream fNameBuffer;
std::stringstream fDecorationBuffer;
SpvId fBoolTrue;
SpvId fBoolFalse;
std::unordered_map<int64_t, SpvId> fIntConstants;
std::unordered_map<uint64_t, SpvId> fUIntConstants;
std::unordered_map<float, SpvId> fFloatConstants;
std::unordered_map<double, SpvId> fDoubleConstants;
// label of the current block, or 0 if we are not in a block
SpvId fCurrentBlock;
std::stack<SpvId> fBreakTarget;
std::stack<SpvId> fContinueTarget;
friend class PointerLValue;
friend class SwizzleLValue;
};
}
#endif

156
src/sksl/SkSLToken.h Normal file
View File

@ -0,0 +1,156 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_TOKEN
#define SKSL_TOKEN
#include "SkSLPosition.h"
#include "SkSLUtil.h"
namespace SkSL {
/**
* Represents a lexical analysis token. Token is generally only used during the parse process, but
* Token::Kind is also used to represent operator kinds.
*/
struct Token {
enum Kind {
END_OF_FILE,
IDENTIFIER,
INT_LITERAL,
FLOAT_LITERAL,
TRUE_LITERAL,
FALSE_LITERAL,
LPAREN,
RPAREN,
LBRACE,
RBRACE,
LBRACKET,
RBRACKET,
DOT,
COMMA,
PLUSPLUS,
MINUSMINUS,
PLUS,
MINUS,
STAR,
SLASH,
PERCENT,
SHL,
SHR,
BITWISEOR,
BITWISEXOR,
BITWISEAND,
LOGICALOR,
LOGICALXOR,
LOGICALAND,
NOT,
QUESTION,
COLON,
EQ,
EQEQ,
NEQ,
GT,
LT,
GTEQ,
LTEQ,
PLUSEQ,
MINUSEQ,
STAREQ,
SLASHEQ,
PERCENTEQ,
SHLEQ,
SHREQ,
BITWISEOREQ,
BITWISEXOREQ,
BITWISEANDEQ,
LOGICALOREQ,
LOGICALXOREQ,
LOGICALANDEQ,
SEMICOLON,
IF,
ELSE,
FOR,
WHILE,
DO,
RETURN,
BREAK,
CONTINUE,
DISCARD,
IN,
OUT,
INOUT,
CONST,
LOWP,
MEDIUMP,
HIGHP,
UNIFORM,
STRUCT,
LAYOUT,
DIRECTIVE,
PRECISION,
INVALID_TOKEN
};
static std::string OperatorName(Kind kind) {
switch (kind) {
case Token::PLUS: return "+";
case Token::MINUS: return "-";
case Token::STAR: return "*";
case Token::SLASH: return "/";
case Token::PERCENT: return "%";
case Token::SHL: return "<<";
case Token::SHR: return ">>";
case Token::LOGICALAND: return "&&";
case Token::LOGICALOR: return "||";
case Token::LOGICALXOR: return "^^";
case Token::BITWISEAND: return "&";
case Token::BITWISEOR: return "|";
case Token::BITWISEXOR: return "^";
case Token::EQ: return "=";
case Token::EQEQ: return "==";
case Token::NEQ: return "!=";
case Token::LT: return "<";
case Token::GT: return ">";
case Token::LTEQ: return "<=";
case Token::GTEQ: return ">=";
case Token::PLUSEQ: return "+=";
case Token::MINUSEQ: return "-=";
case Token::STAREQ: return "*=";
case Token::SLASHEQ: return "/=";
case Token::PERCENTEQ: return "%=";
case Token::SHLEQ: return "<<=";
case Token::SHREQ: return ">>=";
case Token::LOGICALANDEQ: return "&&=";
case Token::LOGICALOREQ: return "||=";
case Token::LOGICALXOREQ: return "^^=";
case Token::BITWISEANDEQ: return "&=";
case Token::BITWISEOREQ: return "|=";
case Token::BITWISEXOREQ: return "^=";
case Token::PLUSPLUS: return "++";
case Token::MINUSMINUS: return "--";
case Token::NOT: return "!";
default:
ABORT("unsupported operator: %d\n", kind);
}
}
Token() {
}
Token(Position position, Kind kind, std::string text)
: fPosition(position)
, fKind(kind)
, fText(std::move(text)) {}
Position fPosition;
Kind fKind;
std::string fText;
};
} // namespace
#endif

33
src/sksl/SkSLUtil.cpp Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLUtil.h"
namespace SkSL {
int stoi(std::string s) {
return atoi(s.c_str());
}
double stod(std::string s) {
return atof(s.c_str());
}
long stol(std::string s) {
return atol(s.c_str());
}
void sksl_abort() {
#ifdef SKIA
sk_abort_no_print();
exit(1);
#else
abort();
#endif
}
} // namespace

60
src/sksl/SkSLUtil.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_UTIL
#define SKSL_UTIL
#include <string>
#include <sstream>
#include "stdlib.h"
#include "assert.h"
#include "SkTypes.h"
namespace SkSL {
// our own definitions of certain std:: functions, because they are not always present on Android
template <typename T> std::string to_string(T value) {
#ifdef SK_BUILD_FOR_ANDROID
std::stringstream buffer;
buffer << value;
return buffer.str();
#else
return std::to_string(value);
#endif
}
#if _MSC_VER
#define NORETURN __declspec(noreturn)
#else
#define NORETURN __attribute__((__noreturn__))
#endif
int stoi(std::string s);
double stod(std::string s);
long stol(std::string s);
NORETURN void sksl_abort();
} // namespace
#ifdef DEBUG
#define ASSERT(x) assert(x)
#define ASSERT_RESULT(x) ASSERT(x);
#else
#define ASSERT(x)
#define ASSERT_RESULT(x) x
#endif
#ifdef SKIA
#define ABORT(...) { SkDebugf(__VA_ARGS__); sksl_abort(); }
#else
#define ABORT(...) { sksl_abort(); }
#endif
#endif

View File

@ -0,0 +1,42 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTBINARYEXPRESSION
#define SKSL_ASTBINARYEXPRESSION
#include "SkSLASTExpression.h"
#include "../SkSLToken.h"
#include <sstream>
namespace SkSL {
/**
* Represents a binary operation, with the operator represented by the token's type.
*/
struct ASTBinaryExpression : public ASTExpression {
ASTBinaryExpression(std::unique_ptr<ASTExpression> left, Token op,
std::unique_ptr<ASTExpression> right)
: INHERITED(op.fPosition, kBinary_Kind)
, fLeft(std::move(left))
, fOperator(op.fKind)
, fRight(std::move(right)) {}
std::string description() const override {
return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " +
fRight->description() + ")";
}
const std::unique_ptr<ASTExpression> fLeft;
const Token::Kind fOperator;
const std::unique_ptr<ASTExpression> fRight;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTBLOCK
#define SKSL_ASTBLOCK
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* Represents a curly-braced block of statements.
*/
struct ASTBlock : public ASTStatement {
ASTBlock(Position position, std::vector<std::unique_ptr<ASTStatement>> statements)
: INHERITED(position, kBlock_Kind)
, fStatements(std::move(statements)) {}
std::string description() const override {
std::string result("{");
for (size_t i = 0; i < fStatements.size(); i++) {
result += "\n";
result += fStatements[i]->description();
}
result += "\n}\n";
return result;
}
const std::vector<std::unique_ptr<ASTStatement>> fStatements;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTBOOLLITERAL
#define SKSL_ASTBOOLLITERAL
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* Represents "true" or "false".
*/
struct ASTBoolLiteral : public ASTExpression {
ASTBoolLiteral(Position position, bool value)
: INHERITED(position, kBool_Kind)
, fValue(value) {}
std::string description() const override {
return fValue ? "true" : "false";
}
const bool fValue;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,31 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTBREAKSTATEMENT
#define SKSL_ASTBREAKSTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A 'break' statement.
*/
struct ASTBreakStatement : public ASTStatement {
ASTBreakStatement(Position position)
: INHERITED(position, kBreak_Kind) {}
std::string description() const override {
return "break;";
}
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,44 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTCALLSUFFIX
#define SKSL_ASTCALLSUFFIX
#include <sstream>
#include <vector>
#include "SkSLASTSuffix.h"
namespace SkSL {
/**
* A parenthesized list of arguments following an expression, indicating a function call.
*/
struct ASTCallSuffix : public ASTSuffix {
ASTCallSuffix(Position position, std::vector<std::unique_ptr<ASTExpression>> arguments)
: INHERITED(position, ASTSuffix::kCall_Kind)
, fArguments(std::move(arguments)) {}
std::string description() const override {
std::string result("(");
std::string separator = "";
for (size_t i = 0; i < fArguments.size(); ++i) {
result += separator;
separator = ", ";
result += fArguments[i]->description();
}
result += ")";
return result;
}
std::vector<std::unique_ptr<ASTExpression>> fArguments;
typedef ASTSuffix INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,31 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTCONTINUESTATEMENT
#define SKSL_ASTCONTINUESTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A 'continue' statement.
*/
struct ASTContinueStatement : public ASTStatement {
ASTContinueStatement(Position position)
: INHERITED(position, kContinue_Kind) {}
std::string description() const override {
return "continue;";
}
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTDECLARATION
#define SKSL_ASTDECLARATION
#include "SkSLASTPositionNode.h"
namespace SkSL {
/**
* Abstract supertype of declarations such as variables and functions.
*/
struct ASTDeclaration : public ASTPositionNode {
enum Kind {
kVar_Kind,
kFunction_Kind,
kInterfaceBlock_Kind,
kExtension_Kind
};
ASTDeclaration(Position position, Kind kind)
: INHERITED(position)
, fKind(kind) {}
Kind fKind;
typedef ASTPositionNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,31 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTDISCARDSTATEMENT
#define SKSL_ASTDISCARDSTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A 'discard' statement.
*/
struct ASTDiscardStatement : public ASTStatement {
ASTDiscardStatement(Position position)
: INHERITED(position, kDiscard_Kind) {}
std::string description() const override {
return "discard;";
}
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTDOSTATEMENT
#define SKSL_ASTDOSTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A 'do' loop.
*/
struct ASTDoStatement : public ASTStatement {
ASTDoStatement(Position position, std::unique_ptr<ASTStatement> statement,
std::unique_ptr<ASTExpression> test)
: INHERITED(position, kDo_Kind)
, fStatement(std::move(statement))
, fTest(std::move(test)) {}
std::string description() const override {
return "do " + fStatement->description() + " while (" + fTest->description() + ");";
}
const std::unique_ptr<ASTStatement> fStatement;
const std::unique_ptr<ASTExpression> fTest;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTEXPRESSION
#define SKSL_ASTEXPRESSION
#include "SkSLASTPositionNode.h"
namespace SkSL {
/**
* Abstract supertype of all expressions.
*/
struct ASTExpression : public ASTPositionNode {
enum Kind {
kFloat_Kind,
kIdentifier_Kind,
kInt_Kind,
kBool_Kind,
kPrefix_Kind,
kSuffix_Kind,
kBinary_Kind,
kTernary_Kind
};
ASTExpression(Position position, Kind kind)
: INHERITED(position)
, fKind(kind) {}
const Kind fKind;
typedef ASTPositionNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTEXPRESSIONSTATEMENT
#define SKSL_ASTEXPRESSIONSTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A lone expression being used as a statement.
*/
struct ASTExpressionStatement : public ASTStatement {
ASTExpressionStatement(std::unique_ptr<ASTExpression> expression)
: INHERITED(expression->fPosition, kExpression_Kind)
, fExpression(std::move(expression)) {}
std::string description() const override {
return fExpression->description() + ";";
}
const std::unique_ptr<ASTExpression> fExpression;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTEXTENSION
#define SKSL_ASTEXTENSION
#include "SkSLASTDeclaration.h"
namespace SkSL {
/**
* An extension declaration.
*/
struct ASTExtension : public ASTDeclaration {
ASTExtension(Position position, std::string name)
: INHERITED(position, kExtension_Kind)
, fName(std::move(name)) {}
std::string description() const override {
return "#extension " + fName + " : enable";
}
const std::string fName;
typedef ASTDeclaration INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,35 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTFIELDSUFFIX
#define SKSL_ASTFIELDSUFFIX
#include "SkSLASTSuffix.h"
namespace SkSL {
/**
* A dotted identifier of the form ".foo". We refer to these as "fields" at parse time even if it is
* actually vector swizzle (which looks the same to the parser).
*/
struct ASTFieldSuffix : public ASTSuffix {
ASTFieldSuffix(Position position, std::string field)
: INHERITED(position, ASTSuffix::kField_Kind)
, fField(std::move(field)) {}
std::string description() const override {
return "." + fField;
}
std::string fField;
typedef ASTSuffix INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTFLOATLITERAL
#define SKSL_ASTFLOATLITERAL
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* A literal floating point number.
*/
struct ASTFloatLiteral : public ASTExpression {
ASTFloatLiteral(Position position, double value)
: INHERITED(position, kFloat_Kind)
, fValue(value) {}
std::string description() const override {
return to_string(fValue);
}
const double fValue;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,56 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTFORSTATEMENT
#define SKSL_ASTFORSTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A 'for' loop.
*/
struct ASTForStatement : public ASTStatement {
ASTForStatement(Position position, std::unique_ptr<ASTStatement> initializer,
std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTExpression> next,
std::unique_ptr<ASTStatement> statement)
: INHERITED(position, kFor_Kind)
, fInitializer(std::move(initializer))
, fTest(std::move(test))
, fNext(std::move(next))
, fStatement(std::move(statement)) {}
std::string description() const override {
std::string result = "for (";
if (fInitializer) {
result.append(fInitializer->description());
}
result += " ";
if (fTest) {
result.append(fTest->description());
}
result += "; ";
if (fNext) {
result.append(fNext->description());
}
result += ") ";
result += fStatement->description();
return result;
}
const std::unique_ptr<ASTStatement> fInitializer;
const std::unique_ptr<ASTExpression> fTest;
const std::unique_ptr<ASTExpression> fNext;
const std::unique_ptr<ASTStatement> fStatement;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,57 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTFUNCTION
#define SKSL_ASTFUNCTION
#include "SkSLASTBlock.h"
#include "SkSLASTDeclaration.h"
#include "SkSLASTParameter.h"
#include "SkSLASTType.h"
namespace SkSL {
/**
* A function declaration or definition. The fBody field will be null for declarations.
*/
struct ASTFunction : public ASTDeclaration {
ASTFunction(Position position, std::unique_ptr<ASTType> returnType, std::string name,
std::vector<std::unique_ptr<ASTParameter>> parameters,
std::unique_ptr<ASTBlock> body)
: INHERITED(position, kFunction_Kind)
, fReturnType(std::move(returnType))
, fName(std::move(name))
, fParameters(std::move(parameters))
, fBody(std::move(body)) {}
std::string description() const override {
std::string result = fReturnType->description() + " " + fName + "(";
for (size_t i = 0; i < fParameters.size(); i++) {
if (i > 0) {
result += ", ";
}
result += fParameters[i]->description();
}
if (fBody) {
result += ") " + fBody->description();
} else {
result += ");";
}
return result;
}
const std::unique_ptr<ASTType> fReturnType;
const std::string fName;
const std::vector<std::unique_ptr<ASTParameter>> fParameters;
const std::unique_ptr<ASTBlock> fBody;
typedef ASTDeclaration INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTIDENTIFIER
#define SKSL_ASTIDENTIFIER
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* An identifier in an expression context.
*/
struct ASTIdentifier : public ASTExpression {
ASTIdentifier(Position position, std::string text)
: INHERITED(position, kIdentifier_Kind)
, fText(std::move(text)) {}
std::string description() const override {
return fText;
}
const std::string fText;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,47 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTIFSTATEMENT
#define SKSL_ASTIFSTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* An 'if' statement.
*/
struct ASTIfStatement : public ASTStatement {
ASTIfStatement(Position position, std::unique_ptr<ASTExpression> test,
std::unique_ptr<ASTStatement> ifTrue, std::unique_ptr<ASTStatement> ifFalse)
: INHERITED(position, kIf_Kind)
, fTest(std::move(test))
, fIfTrue(std::move(ifTrue))
, fIfFalse(std::move(ifFalse)) {}
std::string description() const override {
std::string result("if (");
result += fTest->description();
result += ") ";
result += fIfTrue->description();
if (fIfFalse) {
result += " else ";
result += fIfFalse->description();
}
return result;
}
const std::unique_ptr<ASTExpression> fTest;
const std::unique_ptr<ASTStatement> fIfTrue;
const std::unique_ptr<ASTStatement> fIfFalse;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,35 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTINDEXSUFFIX
#define SKSL_ASTINDEXSUFFIX
#include "SkSLASTExpression.h"
#include "SkSLASTSuffix.h"
namespace SkSL {
/**
* A bracketed expression, as in '[0]', indicating an array access.
*/
struct ASTIndexSuffix : public ASTSuffix {
ASTIndexSuffix(std::unique_ptr<ASTExpression> expression)
: INHERITED(expression->fPosition, ASTSuffix::kIndex_Kind)
, fExpression(std::move(expression)) {}
std::string description() const override {
return "[" + fExpression->description() + "]";
}
std::unique_ptr<ASTExpression> fExpression;
typedef ASTSuffix INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,35 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTINTLITERAL
#define SKSL_ASTINTLITERAL
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* A literal integer. At the AST level, integer literals are always positive; a negative number will
* appear as a unary minus being applied to an integer literal.
*/
struct ASTIntLiteral : public ASTExpression {
ASTIntLiteral(Position position, uint64_t value)
: INHERITED(position, kInt_Kind)
, fValue(value) {}
std::string description() const override {
return to_string(fValue);
}
const uint64_t fValue;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,58 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTINTERFACEBLOCK
#define SKSL_ASTINTERFACEBLOCK
#include "SkSLASTVarDeclaration.h"
namespace SkSL {
/**
* An interface block, as in:
*
* out gl_PerVertex {
* layout(builtin=0) vec4 gl_Position;
* layout(builtin=1) float gl_PointSize;
* };
*/
struct ASTInterfaceBlock : public ASTDeclaration {
// valueName is empty when it was not present in the source
ASTInterfaceBlock(Position position,
ASTModifiers modifiers,
std::string interfaceName,
std::string valueName,
std::vector<std::unique_ptr<ASTVarDeclaration>> declarations)
: INHERITED(position, kInterfaceBlock_Kind)
, fModifiers(modifiers)
, fInterfaceName(std::move(interfaceName))
, fValueName(std::move(valueName))
, fDeclarations(std::move(declarations)) {}
std::string description() const override {
std::string result = fModifiers.description() + fInterfaceName + " {\n";
for (size_t i = 0; i < fDeclarations.size(); i++) {
result += fDeclarations[i]->description() + "\n";
}
result += "}";
if (fValueName.length()) {
result += " " + fValueName;
}
return result + ";";
}
const ASTModifiers fModifiers;
const std::string fInterfaceName;
const std::string fValueName;
const std::vector<std::unique_ptr<ASTVarDeclaration>> fDeclarations;
typedef ASTDeclaration INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,68 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTLAYOUT
#define SKSL_ASTLAYOUT
#include "SkSLASTNode.h"
#include "SkSLUtil.h"
namespace SkSL {
/**
* Represents a layout block appearing before a variable declaration, as in:
*
* layout (location = 0) int x;
*/
struct ASTLayout : public ASTNode {
// For all parameters, a -1 means no value
ASTLayout(int location, int binding, int index, int set, int builtin)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin) {}
std::string description() const {
std::string result;
std::string separator;
if (fLocation >= 0) {
result += separator + "location = " + to_string(fLocation);
separator = ", ";
}
if (fBinding >= 0) {
result += separator + "binding = " + to_string(fBinding);
separator = ", ";
}
if (fIndex >= 0) {
result += separator + "index = " + to_string(fIndex);
separator = ", ";
}
if (fSet >= 0) {
result += separator + "set = " + to_string(fSet);
separator = ", ";
}
if (fBuiltin >= 0) {
result += separator + "builtin = " + to_string(fBuiltin);
separator = ", ";
}
if (result.length() > 0) {
result = "layout (" + result + ")";
}
return result;
}
const int fLocation;
const int fBinding;
const int fIndex;
const int fSet;
const int fBuiltin;
};
} // namespace
#endif

View File

@ -0,0 +1,70 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTMODIFIERS
#define SKSL_ASTMODIFIERS
#include "SkSLASTLayout.h"
#include "SkSLASTNode.h"
namespace SkSL {
/**
* A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration.
*/
struct ASTModifiers : public ASTNode {
enum Flag {
kNo_Flag = 0,
kConst_Flag = 1,
kIn_Flag = 2,
kOut_Flag = 4,
kLowp_Flag = 8,
kMediump_Flag = 16,
kHighp_Flag = 32,
kUniform_Flag = 64
};
ASTModifiers(ASTLayout layout, int flags)
: fLayout(layout)
, fFlags(flags) {}
std::string description() const override {
std::string result = fLayout.description();
if (fFlags & kUniform_Flag) {
result += "uniform ";
}
if (fFlags & kConst_Flag) {
result += "const ";
}
if (fFlags & kLowp_Flag) {
result += "lowp ";
}
if (fFlags & kMediump_Flag) {
result += "mediump ";
}
if (fFlags & kHighp_Flag) {
result += "highp ";
}
if ((fFlags & kIn_Flag) && (fFlags & kOut_Flag)) {
result += "inout ";
} else if (fFlags & kIn_Flag) {
result += "in ";
} else if (fFlags & kOut_Flag) {
result += "out ";
}
return result;
}
const ASTLayout fLayout;
const int fFlags;
};
} // namespace
#endif

View File

@ -0,0 +1,28 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTNODE
#define SKSL_ASTNODE
#include <memory>
#include <string>
namespace SkSL {
/**
* Represents a node in the abstract syntax tree (AST). The AST is based directly on the parse tree;
* it is a parsed-but-not-yet-analyzed version of the program.
*/
struct ASTNode {
virtual ~ASTNode() {}
virtual std::string description() const = 0;
};
} // namespace
#endif

View File

@ -0,0 +1,48 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTPARAMETER
#define SKSL_ASTPARAMETER
#include "SkSLASTModifiers.h"
#include "SkSLASTType.h"
namespace SkSL {
/**
* A declaration of a parameter, as part of a function declaration.
*/
struct ASTParameter : public ASTPositionNode {
// 'sizes' is a list of the array sizes appearing on a parameter, in source order.
// e.g. int x[3][1] would have sizes [3, 1].
ASTParameter(Position position, ASTModifiers modifiers, std::unique_ptr<ASTType> type,
std::string name, std::vector<int> sizes)
: INHERITED(position)
, fModifiers(modifiers)
, fType(std::move(type))
, fName(std::move(name))
, fSizes(std::move(sizes)) {}
std::string description() const override {
std::string result = fModifiers.description() + fType->description() + " " + fName;
for (int size : fSizes) {
result += "[" + to_string(size) + "]";
}
return result;
}
const ASTModifiers fModifiers;
const std::unique_ptr<ASTType> fType;
const std::string fName;
const std::vector<int> fSizes;
typedef ASTPositionNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,28 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTPOSITIONNODE
#define SKSL_ASTPOSITIONNODE
#include "SkSLASTNode.h"
#include "../SkSLPosition.h"
namespace SkSL {
/**
* An AST node with an associated position in the source.
*/
struct ASTPositionNode : public ASTNode {
ASTPositionNode(Position position)
: fPosition(position) {}
const Position fPosition;
};
} // namespace
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTPREFIXEXPRESSION
#define SKSL_ASTPREFIXEXPRESSION
#include "SkSLASTExpression.h"
#include "../SkSLToken.h"
namespace SkSL {
/**
* An expression modified by a unary operator appearing in front of it, such as '-x' or '!inside'.
*/
struct ASTPrefixExpression : public ASTExpression {
ASTPrefixExpression(Token op, std::unique_ptr<ASTExpression> operand)
: INHERITED(op.fPosition, kPrefix_Kind)
, fOperator(op.fKind)
, fOperand(std::move(operand)) {}
std::string description() const override {
return Token::OperatorName(fOperator) + fOperand->description();
}
const Token::Kind fOperator;
const std::unique_ptr<ASTExpression> fOperand;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTRETURNSTATEMENT
#define SKSL_ASTRETURNSTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A 'return' statement.
*/
struct ASTReturnStatement : public ASTStatement {
// expression may be null
ASTReturnStatement(Position position, std::unique_ptr<ASTExpression> expression)
: INHERITED(position, kReturn_Kind)
, fExpression(std::move(expression)) {}
std::string description() const override {
std::string result("return");
if (fExpression) {
result += " " + fExpression->description();
}
return result + ";";
}
const std::unique_ptr<ASTExpression> fExpression;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,46 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTSTATEMENT
#define SKSL_ASTSTATEMENT
#include <vector>
#include "SkSLASTPositionNode.h"
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* Abstract supertype of all statements.
*/
struct ASTStatement : public ASTPositionNode {
enum Kind {
kBlock_Kind,
kVarDeclaration_Kind,
kExpression_Kind,
kIf_Kind,
kFor_Kind,
kWhile_Kind,
kDo_Kind,
kReturn_Kind,
kBreak_Kind,
kContinue_Kind,
kDiscard_Kind
};
ASTStatement(Position position, Kind kind)
: INHERITED(position)
, fKind(kind) {}
Kind fKind;
typedef ASTPositionNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,51 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTSUFFIX
#define SKSL_ASTSUFFIX
#include "SkSLASTPositionNode.h"
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* This and its subclasses represents expression suffixes, such as '[0]' or '.rgb'. Suffixes are not
* expressions in and of themselves; they are attached to expressions to modify them.
*/
struct ASTSuffix : public ASTPositionNode {
enum Kind {
kIndex_Kind,
kCall_Kind,
kField_Kind,
kPostIncrement_Kind,
kPostDecrement_Kind
};
ASTSuffix(Position position, Kind kind)
: INHERITED(position)
, fKind(kind) {}
std::string description() const override {
switch (fKind) {
case kPostIncrement_Kind:
return "++";
case kPostDecrement_Kind:
return "--";
default:
ABORT("unsupported suffix operator");
}
}
Kind fKind;
typedef ASTPositionNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTSUFFIXEXPRESSION
#define SKSL_ASTSUFFIXEXPRESSION
#include "SkSLASTSuffix.h"
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* An expression with an associated suffix.
*/
struct ASTSuffixExpression : public ASTExpression {
ASTSuffixExpression(std::unique_ptr<ASTExpression> base, std::unique_ptr<ASTSuffix> suffix)
: INHERITED(base->fPosition, kSuffix_Kind)
, fBase(std::move(base))
, fSuffix(std::move(suffix)) {}
std::string description() const override {
return fBase->description() + fSuffix->description();
}
const std::unique_ptr<ASTExpression> fBase;
const std::unique_ptr<ASTSuffix> fSuffix;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTTERNARYEXPRESSION
#define SKSL_ASTTERNARYEXPRESSION
#include "SkSLASTExpression.h"
namespace SkSL {
/**
* A ternary expression (test ? ifTrue : ifFalse).
*/
struct ASTTernaryExpression : public ASTExpression {
ASTTernaryExpression(std::unique_ptr<ASTExpression> test,
std::unique_ptr<ASTExpression> ifTrue,
std::unique_ptr<ASTExpression> ifFalse)
: INHERITED(test->fPosition, kTernary_Kind)
, fTest(std::move(test))
, fIfTrue(std::move(ifTrue))
, fIfFalse(std::move(ifFalse)) {}
std::string description() const override {
return "(" + fTest->description() + " ? " + fIfTrue->description() + " : " +
fIfFalse->description() + ")";
}
const std::unique_ptr<ASTExpression> fTest;
const std::unique_ptr<ASTExpression> fIfTrue;
const std::unique_ptr<ASTExpression> fIfFalse;
typedef ASTExpression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTTYPE
#define SKSL_ASTTYPE
namespace SkSL {
/**
* A type, such as 'int' or 'struct foo'.
*/
struct ASTType : public ASTPositionNode {
enum Kind {
kIdentifier_Kind,
kStruct_Kind
};
ASTType(Position position, std::string name, Kind kind)
: INHERITED(position)
, fName(std::move(name))
, fKind(kind) {}
std::string description() const override {
return fName;
}
const std::string fName;
const Kind fKind;
typedef ASTPositionNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTVARDECLARATION
#define SKSL_ASTVARDECLARATION
#include "SkSLASTDeclaration.h"
#include "SkSLASTModifiers.h"
#include "SkSLASTStatement.h"
#include "SkSLASTType.h"
#include "../SkSLUtil.h"
namespace SkSL {
/**
* A variable declaration, which may consist of multiple individual variables. For instance
* 'int x, y = 1, z[4][2]' is a single ASTVarDeclaration. This declaration would have a type of
* 'int', names ['x', 'y', 'z'], sizes of [[], [], [4, 2]], and values of [null, 1, null].
*/
struct ASTVarDeclaration : public ASTDeclaration {
ASTVarDeclaration(ASTModifiers modifiers,
std::unique_ptr<ASTType> type,
std::vector<std::string> names,
std::vector<std::vector<std::unique_ptr<ASTExpression>>> sizes,
std::vector<std::unique_ptr<ASTExpression>> values)
: INHERITED(type->fPosition, kVar_Kind)
, fModifiers(modifiers)
, fType(std::move(type))
, fNames(std::move(names))
, fSizes(std::move(sizes))
, fValues(std::move(values)) {
ASSERT(fNames.size() == fValues.size());
}
std::string description() const override {
std::string result = fModifiers.description() + fType->description() + " ";
std::string separator = "";
for (size_t i = 0; i < fNames.size(); i++) {
result += separator;
separator = ", ";
result += fNames[i];
for (size_t j = 0; j < fSizes[i].size(); j++) {
if (fSizes[i][j]) {
result += "[" + fSizes[i][j]->description() + "]";
} else {
result += "[]";
}
}
if (fValues[i]) {
result += " = " + fValues[i]->description();
}
}
return result;
}
const ASTModifiers fModifiers;
const std::unique_ptr<ASTType> fType;
const std::vector<std::string> fNames;
const std::vector<std::vector<std::unique_ptr<ASTExpression>>> fSizes;
const std::vector<std::unique_ptr<ASTExpression>> fValues;
typedef ASTDeclaration INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,35 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTVARDECLARATIONSTATEMENT
#define SKSL_ASTVARDECLARATIONSTATEMENT
#include "SkSLASTStatement.h"
#include "SkSLASTVarDeclaration.h"
namespace SkSL {
/**
* A variable declaration appearing as a statement within a function.
*/
struct ASTVarDeclarationStatement : public ASTStatement {
ASTVarDeclarationStatement(std::unique_ptr<ASTVarDeclaration> decl)
: INHERITED(decl->fPosition, kVarDeclaration_Kind)
, fDeclaration(std::move(decl)) {}
std::string description() const override {
return fDeclaration->description() + ";";
}
std::unique_ptr<ASTVarDeclaration> fDeclaration;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_ASTWHILESTATEMENT
#define SKSL_ASTWHILESTATEMENT
#include "SkSLASTStatement.h"
namespace SkSL {
/**
* A 'while' statement.
*/
struct ASTWhileStatement : public ASTStatement {
ASTWhileStatement(Position position, std::unique_ptr<ASTExpression> test,
std::unique_ptr<ASTStatement> statement)
: INHERITED(position, kWhile_Kind)
, fTest(std::move(test))
, fStatement(std::move(statement)) {}
std::string description() const override {
return "while (" + fTest->description() + ") " + fStatement->description();
}
const std::unique_ptr<ASTExpression> fTest;
const std::unique_ptr<ASTStatement> fStatement;
typedef ASTStatement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,41 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_BINARYEXPRESSION
#define SKSL_BINARYEXPRESSION
#include "SkSLExpression.h"
#include "../SkSLToken.h"
namespace SkSL {
/**
* A binary operation.
*/
struct BinaryExpression : public Expression {
BinaryExpression(Position position, std::unique_ptr<Expression> left, Token::Kind op,
std::unique_ptr<Expression> right, std::shared_ptr<Type> type)
: INHERITED(position, kBinary_Kind, type)
, fLeft(std::move(left))
, fOperator(op)
, fRight(std::move(right)) {}
virtual std::string description() const override {
return "(" + fLeft->description() + " " + Token::OperatorName(fOperator) + " " +
fRight->description() + ")";
}
const std::unique_ptr<Expression> fLeft;
const Token::Kind fOperator;
const std::unique_ptr<Expression> fRight;
typedef Expression INHERITED;
};
} // namespace
#endif

40
src/sksl/ir/SkSLBlock.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_BLOCK
#define SKSL_BLOCK
#include "SkSLStatement.h"
namespace SkSL {
/**
* A block of multiple statements functioning as a single statement.
*/
struct Block : public Statement {
Block(Position position, std::vector<std::unique_ptr<Statement>> statements)
: INHERITED(position, kBlock_Kind)
, fStatements(std::move(statements)) {}
std::string description() const override {
std::string result = "{";
for (size_t i = 0; i < fStatements.size(); i++) {
result += "\n";
result += fStatements[i]->description();
}
result += "\n}\n";
return result;
}
const std::vector<std::unique_ptr<Statement>> fStatements;
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,38 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_BOOLLITERAL
#define SKSL_BOOLLITERAL
#include "SkSLExpression.h"
namespace SkSL {
/**
* Represents 'true' or 'false'.
*/
struct BoolLiteral : public Expression {
BoolLiteral(Position position, bool value)
: INHERITED(position, kBoolLiteral_Kind, kBool_Type)
, fValue(value) {}
std::string description() const override {
return fValue ? "true" : "false";
}
bool isConstant() const override {
return true;
}
const bool fValue;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_BREAKSTATEMENT
#define SKSL_BREAKSTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* A 'break' statement.
*/
struct BreakStatement : public Statement {
BreakStatement(Position position)
: INHERITED(position, kBreak_Kind) {}
std::string description() const override {
return "break;";
}
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,52 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_CONSTRUCTOR
#define SKSL_CONSTRUCTOR
#include "SkSLExpression.h"
namespace SkSL {
/**
* Represents the construction of a compound type, such as "vec2(x, y)".
*/
struct Constructor : public Expression {
Constructor(Position position, std::shared_ptr<Type> type,
std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(position, kConstructor_Kind, std::move(type))
, fArguments(std::move(arguments)) {}
std::string description() const override {
std::string result = fType->description() + "(";
std::string separator = "";
for (size_t i = 0; i < fArguments.size(); i++) {
result += separator;
result += fArguments[i]->description();
separator = ", ";
}
result += ")";
return result;
}
bool isConstant() const override {
for (size_t i = 0; i < fArguments.size(); i++) {
if (!fArguments[i]->isConstant()) {
return false;
}
}
return true;
}
const std::vector<std::unique_ptr<Expression>> fArguments;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_CONTINUESTATEMENT
#define SKSL_CONTINUESTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* A 'continue' statement.
*/
struct ContinueStatement : public Statement {
ContinueStatement(Position position)
: INHERITED(position, kContinue_Kind) {}
std::string description() const override {
return "continue;";
}
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,32 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_DISCARDSTATEMENT
#define SKSL_DISCARDSTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* A 'discard' statement.
*/
struct DiscardStatement : public Statement {
DiscardStatement(Position position)
: INHERITED(position, kDiscard_Kind) {}
std::string description() const override {
return "discard;";
}
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,38 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_DOSTATEMENT
#define SKSL_DOSTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* A 'do' statement.
*/
struct DoStatement : public Statement {
DoStatement(Position position, std::unique_ptr<Statement> statement,
std::unique_ptr<Expression> test)
: INHERITED(position, kDo_Kind)
, fStatement(std::move(statement))
, fTest(std::move(test)) {}
std::string description() const override {
return "do " + fStatement->description() + " while (" + fTest->description() + ");";
}
const std::unique_ptr<Statement> fStatement;
const std::unique_ptr<Expression> fTest;
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,55 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_EXPRESSION
#define SKSL_EXPRESSION
#include "SkSLIRNode.h"
#include "SkSLType.h"
namespace SkSL {
/**
* Abstract supertype of all expressions.
*/
struct Expression : public IRNode {
enum Kind {
kBinary_Kind,
kBoolLiteral_Kind,
kConstructor_Kind,
kIntLiteral_Kind,
kFieldAccess_Kind,
kFloatLiteral_Kind,
kFunctionReference_Kind,
kFunctionCall_Kind,
kIndex_Kind,
kPrefix_Kind,
kPostfix_Kind,
kSwizzle_Kind,
kVariableReference_Kind,
kTernary_Kind,
kTypeReference_Kind,
};
Expression(Position position, Kind kind, std::shared_ptr<Type> type)
: INHERITED(position)
, fKind(kind)
, fType(std::move(type)) {}
virtual bool isConstant() const {
return false;
}
const Kind fKind;
const std::shared_ptr<Type> fType;
typedef IRNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,35 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_EXPRESSIONSTATEMENT
#define SKSL_EXPRESSIONSTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* A lone expression being used as a statement.
*/
struct ExpressionStatement : public Statement {
ExpressionStatement(std::unique_ptr<Expression> expression)
: INHERITED(expression->fPosition, kExpression_Kind)
, fExpression(std::move(expression)) {}
std::string description() const override {
return fExpression->description() + ";";
}
const std::unique_ptr<Expression> fExpression;
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_EXTENSION
#define SKSL_EXTENSION
#include "SkSLProgramElement.h"
namespace SkSL {
/**
* An extension declaration.
*/
struct Extension : public ProgramElement {
Extension(Position position, std::string name)
: INHERITED(position, kExtension_Kind)
, fName(std::move(name)) {}
std::string description() const override {
return "#extension " + fName + " : enable";
}
const std::string fName;
typedef ProgramElement INHERITED;
};
} // namespace
#endif

41
src/sksl/ir/SkSLField.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FIELD
#define SKSL_FIELD
#include "SkSLModifiers.h"
#include "SkSLPosition.h"
#include "SkSLSymbol.h"
#include "SkSLType.h"
namespace SkSL {
/**
* A symbol which should be interpreted as a field access. Fields are added to the symboltable
* whenever a bare reference to an identifier should refer to a struct field; in GLSL, this is the
* result of declaring anonymous interface blocks.
*/
struct Field : public Symbol {
Field(Position position, std::shared_ptr<Variable> owner, int fieldIndex)
: INHERITED(position, kField_Kind, owner->fType->fields()[fieldIndex].fName)
, fOwner(owner)
, fFieldIndex(fieldIndex) {}
virtual std::string description() const override {
return fOwner->description() + "." + fOwner->fType->fields()[fFieldIndex].fName;
}
const std::shared_ptr<Variable> fOwner;
const int fFieldIndex;
typedef Symbol INHERITED;
};
} // namespace SkSL
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FIELDACCESS
#define SKSL_FIELDACCESS
#include "SkSLExpression.h"
#include "SkSLUtil.h"
namespace SkSL {
/**
* An expression which extracts a field from a struct, as in 'foo.bar'.
*/
struct FieldAccess : public Expression {
FieldAccess(std::unique_ptr<Expression> base, int fieldIndex)
: INHERITED(base->fPosition, kFieldAccess_Kind, base->fType->fields()[fieldIndex].fType)
, fBase(std::move(base))
, fFieldIndex(fieldIndex) {}
virtual std::string description() const override {
return fBase->description() + "." + fBase->fType->fields()[fFieldIndex].fName;
}
const std::unique_ptr<Expression> fBase;
const int fFieldIndex;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,38 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FLOATLITERAL
#define SKSL_FLOATLITERAL
#include "SkSLExpression.h"
namespace SkSL {
/**
* A literal floating point number.
*/
struct FloatLiteral : public Expression {
FloatLiteral(Position position, double value)
: INHERITED(position, kFloatLiteral_Kind, kFloat_Type)
, fValue(value) {}
virtual std::string description() const override {
return to_string(fValue);
}
bool isConstant() const override {
return true;
}
const double fValue;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,56 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FORSTATEMENT
#define SKSL_FORSTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* A 'for' statement.
*/
struct ForStatement : public Statement {
ForStatement(Position position, std::unique_ptr<Statement> initializer,
std::unique_ptr<Expression> test, std::unique_ptr<Expression> next,
std::unique_ptr<Statement> statement)
: INHERITED(position, kFor_Kind)
, fInitializer(std::move(initializer))
, fTest(std::move(test))
, fNext(std::move(next))
, fStatement(std::move(statement)) {}
std::string description() const override {
std::string result = "for (";
if (fInitializer) {
result += fInitializer->description();
}
result += " ";
if (fTest) {
result += fTest->description();
}
result += "; ";
if (fNext) {
result += fNext->description();
}
result += ") " + fStatement->description();
return result;
}
const std::unique_ptr<Statement> fInitializer;
const std::unique_ptr<Expression> fTest;
const std::unique_ptr<Expression> fNext;
const std::unique_ptr<Statement> fStatement;
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,46 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FUNCTIONCALL
#define SKSL_FUNCTIONCALL
#include "SkSLExpression.h"
#include "SkSLFunctionDeclaration.h"
namespace SkSL {
/**
* A function invocation.
*/
struct FunctionCall : public Expression {
FunctionCall(Position position, std::shared_ptr<FunctionDeclaration> function,
std::vector<std::unique_ptr<Expression>> arguments)
: INHERITED(position, kFunctionCall_Kind, function->fReturnType)
, fFunction(std::move(function))
, fArguments(std::move(arguments)) {}
std::string description() const override {
std::string result = fFunction->fName + "(";
std::string separator = "";
for (size_t i = 0; i < fArguments.size(); i++) {
result += separator;
result += fArguments[i]->description();
separator = ", ";
}
result += ")";
return result;
}
const std::shared_ptr<FunctionDeclaration> fFunction;
const std::vector<std::unique_ptr<Expression>> fArguments;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,55 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FUNCTIONDECLARATION
#define SKSL_FUNCTIONDECLARATION
#include "SkSLModifiers.h"
#include "SkSLSymbol.h"
#include "SkSLType.h"
#include "SkSLVariable.h"
namespace SkSL {
/**
* A function declaration (not a definition -- does not contain a body).
*/
struct FunctionDeclaration : public Symbol {
FunctionDeclaration(Position position, std::string name,
std::vector<std::shared_ptr<Variable>> parameters,
std::shared_ptr<Type> returnType)
: INHERITED(position, kFunctionDeclaration_Kind, std::move(name))
, fDefined(false)
, fParameters(parameters)
, fReturnType(returnType) {}
std::string description() const override {
std::string result = fReturnType->description() + " " + fName + "(";
std::string separator = "";
for (auto p : fParameters) {
result += separator;
separator = ", ";
result += p->description();
}
result += ")";
return result;
}
bool matches(FunctionDeclaration& f) {
return fName == f.fName && fParameters == f.fParameters;
}
mutable bool fDefined;
const std::vector<std::shared_ptr<Variable>> fParameters;
const std::shared_ptr<Type> fReturnType;
typedef Symbol INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FUNCTIONDEFINITION
#define SKSL_FUNCTIONDEFINITION
#include "SkSLBlock.h"
#include "SkSLFunctionDeclaration.h"
#include "SkSLProgramElement.h"
namespace SkSL {
/**
* A function definition (a declaration plus an associated block of code).
*/
struct FunctionDefinition : public ProgramElement {
FunctionDefinition(Position position, std::shared_ptr<FunctionDeclaration> declaration,
std::unique_ptr<Block> body)
: INHERITED(position, kFunction_Kind)
, fDeclaration(std::move(declaration))
, fBody(std::move(body)) {}
std::string description() const override {
return fDeclaration->description() + " " + fBody->description();
}
const std::shared_ptr<FunctionDeclaration> fDeclaration;
const std::unique_ptr<Block> fBody;
typedef ProgramElement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_FUNCTIONREFERENCE
#define SKSL_FUNCTIONREFERENCE
#include "SkSLExpression.h"
namespace SkSL {
/**
* An identifier referring to a function name. This is an intermediate value: FunctionReferences are
* always eventually replaced by FunctionCalls in valid programs.
*/
struct FunctionReference : public Expression {
FunctionReference(Position position, std::vector<std::shared_ptr<FunctionDeclaration>> function)
: INHERITED(position, kFunctionReference_Kind, kInvalid_Type)
, fFunctions(function) {}
virtual std::string description() const override {
ASSERT(false);
return "<function>";
}
const std::vector<std::shared_ptr<FunctionDeclaration>> fFunctions;
typedef Expression INHERITED;
};
} // namespace
#endif

32
src/sksl/ir/SkSLIRNode.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_IRNODE
#define SKSL_IRNODE
#include "../SkSLPosition.h"
namespace SkSL {
/**
* Represents a node in the intermediate representation (IR) tree. The IR is a fully-resolved
* version of the program (all types determined, everything validated), ready for code generation.
*/
struct IRNode {
IRNode(Position position)
: fPosition(position) {}
virtual ~IRNode() {}
virtual std::string description() const = 0;
const Position fPosition;
};
} // namespace
#endif

View File

@ -0,0 +1,44 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_IFSTATEMENT
#define SKSL_IFSTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* An 'if' statement.
*/
struct IfStatement : public Statement {
IfStatement(Position position, std::unique_ptr<Expression> test,
std::unique_ptr<Statement> ifTrue, std::unique_ptr<Statement> ifFalse)
: INHERITED(position, kIf_Kind)
, fTest(std::move(test))
, fIfTrue(std::move(ifTrue))
, fIfFalse(std::move(ifFalse)) {}
std::string description() const override {
std::string result = "if (" + fTest->description() + ") " + fIfTrue->description();
if (fIfFalse) {
result += " else " + fIfFalse->description();
}
return result;
}
const std::unique_ptr<Expression> fTest;
const std::unique_ptr<Statement> fIfTrue;
const std::unique_ptr<Statement> fIfFalse;
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,64 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_INDEX
#define SKSL_INDEX
#include "SkSLExpression.h"
#include "SkSLUtil.h"
namespace SkSL {
/**
* Given a type, returns the type that will result from extracting an array value from it.
*/
static std::shared_ptr<Type> index_type(const Type& type) {
if (type.kind() == Type::kMatrix_Kind) {
if (type.componentType() == kFloat_Type) {
switch (type.columns()) {
case 2: return kVec2_Type;
case 3: return kVec3_Type;
case 4: return kVec4_Type;
default: ASSERT(false);
}
} else {
ASSERT(type.componentType() == kDouble_Type);
switch (type.columns()) {
case 2: return kDVec2_Type;
case 3: return kDVec3_Type;
case 4: return kDVec4_Type;
default: ASSERT(false);
}
}
}
return type.componentType();
}
/**
* An expression which extracts a value from an array or matrix, as in 'm[2]'.
*/
struct IndexExpression : public Expression {
IndexExpression(std::unique_ptr<Expression> base, std::unique_ptr<Expression> index)
: INHERITED(base->fPosition, kIndex_Kind, index_type(*base->fType))
, fBase(std::move(base))
, fIndex(std::move(index)) {
ASSERT(fIndex->fType == kInt_Type);
}
std::string description() const override {
return fBase->description() + "[" + fIndex->description() + "]";
}
const std::unique_ptr<Expression> fBase;
const std::unique_ptr<Expression> fIndex;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,40 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_INTLITERAL
#define SKSL_INTLITERAL
#include "SkSLExpression.h"
namespace SkSL {
/**
* A literal integer.
*/
struct IntLiteral : public Expression {
// FIXME: we will need to revisit this if/when we add full support for both signed and unsigned
// 64-bit integers, but for right now an int64_t will hold every value we care about
IntLiteral(Position position, int64_t value)
: INHERITED(position, kIntLiteral_Kind, kInt_Type)
, fValue(value) {}
virtual std::string description() const override {
return to_string(fValue);
}
bool isConstant() const override {
return true;
}
const int64_t fValue;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,49 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_INTERFACEBLOCK
#define SKSL_INTERFACEBLOCK
#include "SkSLProgramElement.h"
#include "SkSLVarDeclaration.h"
namespace SkSL {
/**
* An interface block, as in:
*
* out gl_PerVertex {
* layout(builtin=0) vec4 gl_Position;
* layout(builtin=1) float gl_PointSize;
* };
*
* At the IR level, this is represented by a single variable of struct type.
*/
struct InterfaceBlock : public ProgramElement {
InterfaceBlock(Position position, std::shared_ptr<Variable> var)
: INHERITED(position, kInterfaceBlock_Kind)
, fVariable(std::move(var)) {
ASSERT(fVariable->fType->kind() == Type::kStruct_Kind);
}
std::string description() const override {
std::string result = fVariable->fModifiers.description() + fVariable->fName + " {\n";
for (size_t i = 0; i < fVariable->fType->fields().size(); i++) {
result += fVariable->fType->fields()[i].description() + "\n";
}
result += "};";
return result;
}
const std::shared_ptr<Variable> fVariable;
typedef ProgramElement INHERITED;
};
} // namespace
#endif

83
src/sksl/ir/SkSLLayout.h Normal file
View File

@ -0,0 +1,83 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_LAYOUT
#define SKSL_LAYOUT
namespace SkSL {
/**
* Represents a layout block appearing before a variable declaration, as in:
*
* layout (location = 0) int x;
*/
struct Layout {
Layout(const ASTLayout& layout)
: fLocation(layout.fLocation)
, fBinding(layout.fBinding)
, fIndex(layout.fIndex)
, fSet(layout.fSet)
, fBuiltin(layout.fBuiltin) {}
Layout(int location, int binding, int index, int set, int builtin)
: fLocation(location)
, fBinding(binding)
, fIndex(index)
, fSet(set)
, fBuiltin(builtin) {}
std::string description() const {
std::string result;
std::string separator;
if (fLocation >= 0) {
result += separator + "location = " + to_string(fLocation);
separator = ", ";
}
if (fBinding >= 0) {
result += separator + "binding = " + to_string(fBinding);
separator = ", ";
}
if (fIndex >= 0) {
result += separator + "index = " + to_string(fIndex);
separator = ", ";
}
if (fSet >= 0) {
result += separator + "set = " + to_string(fSet);
separator = ", ";
}
if (fBuiltin >= 0) {
result += separator + "builtin = " + to_string(fBuiltin);
separator = ", ";
}
if (result.length() > 0) {
result = "layout (" + result + ")";
}
return result;
}
bool operator==(const Layout& other) const {
return fLocation == other.fLocation &&
fBinding == other.fBinding &&
fIndex == other.fIndex &&
fSet == other.fSet &&
fBuiltin == other.fBuiltin;
}
bool operator!=(const Layout& other) const {
return !(*this == other);
}
const int fLocation;
const int fBinding;
const int fIndex;
const int fSet;
const int fBuiltin;
};
} // namespace
#endif

View File

@ -0,0 +1,82 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_MODIFIERS
#define SKSL_MODIFIERS
#include "../ast/SkSLASTModifiers.h"
#include "SkSLLayout.h"
namespace SkSL {
/**
* A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration.
*/
struct Modifiers {
enum Flag {
kNo_Flag = ASTModifiers::kNo_Flag,
kConst_Flag = ASTModifiers::kConst_Flag,
kIn_Flag = ASTModifiers::kIn_Flag,
kOut_Flag = ASTModifiers::kOut_Flag,
kLowp_Flag = ASTModifiers::kLowp_Flag,
kMediump_Flag = ASTModifiers::kMediump_Flag,
kHighp_Flag = ASTModifiers::kHighp_Flag,
kUniform_Flag = ASTModifiers::kUniform_Flag
};
Modifiers(const ASTModifiers& modifiers)
: fLayout(modifiers.fLayout)
, fFlags(modifiers.fFlags) {}
Modifiers(Layout& layout, int flags)
: fLayout(layout)
, fFlags(flags) {}
std::string description() const {
std::string result = fLayout.description();
if (fFlags & kUniform_Flag) {
result += "uniform ";
}
if (fFlags & kConst_Flag) {
result += "const ";
}
if (fFlags & kLowp_Flag) {
result += "lowp ";
}
if (fFlags & kMediump_Flag) {
result += "mediump ";
}
if (fFlags & kHighp_Flag) {
result += "highp ";
}
if ((fFlags & kIn_Flag) && (fFlags & kOut_Flag)) {
result += "inout ";
} else if (fFlags & kIn_Flag) {
result += "in ";
} else if (fFlags & kOut_Flag) {
result += "out ";
}
return result;
}
bool operator==(const Modifiers& other) const {
return fLayout == other.fLayout && fFlags == other.fFlags;
}
bool operator!=(const Modifiers& other) const {
return !(*this == other);
}
const Layout fLayout;
const int fFlags;
};
} // namespace
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_POSTFIXEXPRESSION
#define SKSL_POSTFIXEXPRESSION
#include "SkSLExpression.h"
namespace SkSL {
/**
* An expression modified by a unary operator appearing after it, such as 'i++'.
*/
struct PostfixExpression : public Expression {
PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op)
: INHERITED(operand->fPosition, kPostfix_Kind, operand->fType)
, fOperand(std::move(operand))
, fOperator(op) {}
virtual std::string description() const override {
return fOperand->description() + Token::OperatorName(fOperator);
}
const std::unique_ptr<Expression> fOperand;
const Token::Kind fOperator;
typedef Expression INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,36 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_PREFIXEXPRESSION
#define SKSL_PREFIXEXPRESSION
#include "SkSLExpression.h"
namespace SkSL {
/**
* An expression modified by a unary operator appearing before it, such as '!flag'.
*/
struct PrefixExpression : public Expression {
PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand)
: INHERITED(operand->fPosition, kPrefix_Kind, operand->fType)
, fOperand(std::move(operand))
, fOperator(op) {}
virtual std::string description() const override {
return Token::OperatorName(fOperator) + fOperand->description();
}
const std::unique_ptr<Expression> fOperand;
const Token::Kind fOperator;
typedef Expression INHERITED;
};
} // namespace
#endif

38
src/sksl/ir/SkSLProgram.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_PROGRAM
#define SKSL_PROGRAM
#include <vector>
#include <memory>
#include "SkSLProgramElement.h"
namespace SkSL {
/**
* Represents a fully-digested program, ready for code generation.
*/
struct Program {
enum Kind {
kFragment_Kind,
kVertex_Kind
};
Program(Kind kind, std::vector<std::unique_ptr<ProgramElement>> elements)
: fKind(kind)
, fElements(std::move(elements)) {}
Kind fKind;
std::vector<std::unique_ptr<ProgramElement>> fElements;
};
} // namespace
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_PROGRAMELEMENT
#define SKSL_PROGRAMELEMENT
#include "SkSLIRNode.h"
namespace SkSL {
/**
* Represents a top-level element (e.g. function or global variable) in a program.
*/
struct ProgramElement : public IRNode {
enum Kind {
kVar_Kind,
kFunction_Kind,
kInterfaceBlock_Kind,
kExtension_Kind
};
ProgramElement(Position position, Kind kind)
: INHERITED(position)
, fKind(kind) {}
Kind fKind;
typedef IRNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,42 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_RETURNSTATEMENT
#define SKSL_RETURNSTATEMENT
#include "SkSLExpression.h"
#include "SkSLStatement.h"
namespace SkSL {
/**
* A 'return' statement.
*/
struct ReturnStatement : public Statement {
ReturnStatement(Position position)
: INHERITED(position, kReturn_Kind) {}
ReturnStatement(std::unique_ptr<Expression> expression)
: INHERITED(expression->fPosition, kReturn_Kind)
, fExpression(std::move(expression)) {}
std::string description() const override {
if (fExpression) {
return "return " + fExpression->description() + ";";
} else {
return "return;";
}
}
const std::unique_ptr<Expression> fExpression;
typedef Statement INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,45 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_STATEMENT
#define SKSL_STATEMENT
#include "SkSLIRNode.h"
#include "SkSLType.h"
namespace SkSL {
/**
* Abstract supertype of all statements.
*/
struct Statement : public IRNode {
enum Kind {
kBlock_Kind,
kBreak_Kind,
kContinue_Kind,
kDiscard_Kind,
kDo_Kind,
kExpression_Kind,
kFor_Kind,
kIf_Kind,
kReturn_Kind,
kVarDeclaration_Kind,
kWhile_Kind
};
Statement(Position position, Kind kind)
: INHERITED(position)
, fKind(kind) {}
const Kind fKind;
typedef IRNode INHERITED;
};
} // namespace
#endif

88
src/sksl/ir/SkSLSwizzle.h Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SWIZZLE
#define SKSL_SWIZZLE
#include "SkSLExpression.h"
#include "SkSLUtil.h"
namespace SkSL {
/**
* Given a type and a swizzle component count, returns the type that will result from swizzling. For
* instance, swizzling a vec3 with two components will result in a vec2. It is possible to swizzle
* with more components than the source vector, as in 'vec2(1).xxxx'.
*/
static std::shared_ptr<Type> get_type(Expression& value,
size_t count) {
std::shared_ptr<Type> base = value.fType->componentType();
if (count == 1) {
return base;
}
if (base == kFloat_Type) {
switch (count) {
case 2: return kVec2_Type;
case 3: return kVec3_Type;
case 4: return kVec4_Type;
}
} else if (base == kDouble_Type) {
switch (count) {
case 2: return kDVec2_Type;
case 3: return kDVec3_Type;
case 4: return kDVec4_Type;
}
} else if (base == kInt_Type) {
switch (count) {
case 2: return kIVec2_Type;
case 3: return kIVec3_Type;
case 4: return kIVec4_Type;
}
} else if (base == kUInt_Type) {
switch (count) {
case 2: return kUVec2_Type;
case 3: return kUVec3_Type;
case 4: return kUVec4_Type;
}
} else if (base == kBool_Type) {
switch (count) {
case 2: return kBVec2_Type;
case 3: return kBVec3_Type;
case 4: return kBVec4_Type;
}
}
ABORT("cannot swizzle %s\n", value.description().c_str());
}
/**
* Represents a vector swizzle operation such as 'vec2(1, 2, 3).zyx'.
*/
struct Swizzle : public Expression {
Swizzle(std::unique_ptr<Expression> base, std::vector<int> components)
: INHERITED(base->fPosition, kSwizzle_Kind, get_type(*base, components.size()))
, fBase(std::move(base))
, fComponents(std::move(components)) {
ASSERT(fComponents.size() >= 1 && fComponents.size() <= 4);
}
std::string description() const override {
std::string result = fBase->description() + ".";
for (int x : fComponents) {
result += "xyzw"[x];
}
return result;
}
const std::unique_ptr<Expression> fBase;
const std::vector<int> fComponents;
typedef Expression INHERITED;
};
} // namespace
#endif

40
src/sksl/ir/SkSLSymbol.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SYMBOL
#define SKSL_SYMBOL
#include "SkSLIRNode.h"
namespace SkSL {
/**
* Represents a symboltable entry.
*/
struct Symbol : public IRNode {
enum Kind {
kFunctionDeclaration_Kind,
kUnresolvedFunction_Kind,
kType_Kind,
kVariable_Kind,
kField_Kind
};
Symbol(Position position, Kind kind, std::string name)
: INHERITED(position)
, fKind(kind)
, fName(std::move(name)) {}
const Kind fKind;
const std::string fName;
typedef IRNode INHERITED;
};
} // namespace
#endif

View File

@ -0,0 +1,85 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLSymbolTable.h"
namespace SkSL {
std::vector<std::shared_ptr<FunctionDeclaration>> SymbolTable::GetFunctions(
const std::shared_ptr<Symbol>& s) {
switch (s->fKind) {
case Symbol::kFunctionDeclaration_Kind:
return { std::static_pointer_cast<FunctionDeclaration>(s) };
case Symbol::kUnresolvedFunction_Kind:
return ((UnresolvedFunction&) *s).fFunctions;
default:
return { };
}
}
std::shared_ptr<Symbol> SymbolTable::operator[](const std::string& name) {
const auto& entry = fSymbols.find(name);
if (entry == fSymbols.end()) {
if (fParent) {
return (*fParent)[name];
}
return nullptr;
}
if (fParent) {
auto functions = GetFunctions(entry->second);
if (functions.size() > 0) {
bool modified = false;
std::shared_ptr<Symbol> previous = (*fParent)[name];
if (previous) {
auto previousFunctions = GetFunctions(previous);
for (const std::shared_ptr<FunctionDeclaration>& prev : previousFunctions) {
bool found = false;
for (const std::shared_ptr<FunctionDeclaration>& current : functions) {
if (current->matches(*prev)) {
found = true;
break;
}
}
if (!found) {
functions.push_back(prev);
modified = true;
}
}
if (modified) {
ASSERT(functions.size() > 1);
return std::shared_ptr<Symbol>(new UnresolvedFunction(functions));
}
}
}
}
return entry->second;
}
void SymbolTable::add(const std::string& name, std::shared_ptr<Symbol> symbol) {
const auto& existing = fSymbols.find(name);
if (existing == fSymbols.end()) {
fSymbols[name] = symbol;
} else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) {
const std::shared_ptr<Symbol>& oldSymbol = existing->second;
if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) {
std::vector<std::shared_ptr<FunctionDeclaration>> functions;
functions.push_back(std::static_pointer_cast<FunctionDeclaration>(oldSymbol));
functions.push_back(std::static_pointer_cast<FunctionDeclaration>(symbol));
fSymbols[name].reset(new UnresolvedFunction(std::move(functions)));
} else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) {
std::vector<std::shared_ptr<FunctionDeclaration>> functions;
for (const auto& f : ((UnresolvedFunction&) *oldSymbol).fFunctions) {
functions.push_back(f);
}
functions.push_back(std::static_pointer_cast<FunctionDeclaration>(symbol));
fSymbols[name].reset(new UnresolvedFunction(std::move(functions)));
}
} else {
fErrorReporter.error(symbol->fPosition, "symbol '" + name + "' was already defined");
}
}
} // namespace

View File

@ -0,0 +1,49 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_SYMBOLTABLE
#define SKSL_SYMBOLTABLE
#include <memory>
#include <unordered_map>
#include "SkSLErrorReporter.h"
#include "SkSLSymbol.h"
#include "SkSLUnresolvedFunction.h"
namespace SkSL {
/**
* Maps identifiers to symbols. Functions, in particular, are mapped to either FunctionDeclaration
* or UnresolvedFunction depending on whether they are overloaded or not.
*/
class SymbolTable {
public:
SymbolTable(ErrorReporter& errorReporter)
: fErrorReporter(errorReporter) {}
SymbolTable(std::shared_ptr<SymbolTable> parent, ErrorReporter& errorReporter)
: fParent(parent)
, fErrorReporter(errorReporter) {}
std::shared_ptr<Symbol> operator[](const std::string& name);
void add(const std::string& name, std::shared_ptr<Symbol> symbol);
const std::shared_ptr<SymbolTable> fParent;
private:
static std::vector<std::shared_ptr<FunctionDeclaration>> GetFunctions(
const std::shared_ptr<Symbol>& s);
std::unordered_map<std::string, std::shared_ptr<Symbol>> fSymbols;
ErrorReporter& fErrorReporter;
};
} // namespace
#endif

View File

@ -0,0 +1,43 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_TERNARYEXPRESSION
#define SKSL_TERNARYEXPRESSION
#include "SkSLExpression.h"
#include "../SkSLPosition.h"
namespace SkSL {
/**
* A ternary expression (test ? ifTrue : ifFalse).
*/
struct TernaryExpression : public Expression {
TernaryExpression(Position position, std::unique_ptr<Expression> test,
std::unique_ptr<Expression> ifTrue, std::unique_ptr<Expression> ifFalse)
: INHERITED(position, kTernary_Kind, ifTrue->fType)
, fTest(std::move(test))
, fIfTrue(std::move(ifTrue))
, fIfFalse(std::move(ifFalse)) {
ASSERT(fIfTrue->fType == fIfFalse->fType);
}
std::string description() const override {
return "(" + fTest->description() + " ? " + fIfTrue->description() + " : " +
fIfFalse->description() + ")";
}
const std::unique_ptr<Expression> fTest;
const std::unique_ptr<Expression> fIfTrue;
const std::unique_ptr<Expression> fIfFalse;
typedef Expression INHERITED;
};
} // namespace
#endif

258
src/sksl/ir/SkSLType.cpp Normal file
View File

@ -0,0 +1,258 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLType.h"
namespace SkSL {
bool Type::determineCoercionCost(std::shared_ptr<Type> other, int* outCost) const {
if (this == other.get()) {
*outCost = 0;
return true;
}
if (this->kind() == kVector_Kind && other->kind() == kVector_Kind) {
if (this->columns() == other->columns()) {
return this->componentType()->determineCoercionCost(other->componentType(), outCost);
}
return false;
}
if (this->kind() == kMatrix_Kind) {
if (this->columns() == other->columns() &&
this->rows() == other->rows()) {
return this->componentType()->determineCoercionCost(other->componentType(), outCost);
}
return false;
}
for (size_t i = 0; i < fCoercibleTypes.size(); i++) {
if (fCoercibleTypes[i] == other) {
*outCost = (int) i + 1;
return true;
}
}
return false;
}
std::shared_ptr<Type> Type::toCompound(int columns, int rows) {
ASSERT(this->kind() == Type::kScalar_Kind);
if (columns == 1 && rows == 1) {
return std::shared_ptr<Type>(this);
}
if (*this == *kFloat_Type) {
switch (rows) {
case 1:
switch (columns) {
case 2: return kVec2_Type;
case 3: return kVec3_Type;
case 4: return kVec4_Type;
default: ABORT("unsupported vector column count (%d)", columns);
}
case 2:
switch (columns) {
case 2: return kMat2x2_Type;
case 3: return kMat3x2_Type;
case 4: return kMat4x2_Type;
default: ABORT("unsupported matrix column count (%d)", columns);
}
case 3:
switch (columns) {
case 2: return kMat2x3_Type;
case 3: return kMat3x3_Type;
case 4: return kMat4x3_Type;
default: ABORT("unsupported matrix column count (%d)", columns);
}
case 4:
switch (columns) {
case 2: return kMat2x4_Type;
case 3: return kMat3x4_Type;
case 4: return kMat4x4_Type;
default: ABORT("unsupported matrix column count (%d)", columns);
}
default: ABORT("unsupported row count (%d)", rows);
}
} else if (*this == *kDouble_Type) {
switch (rows) {
case 1:
switch (columns) {
case 2: return kDVec2_Type;
case 3: return kDVec3_Type;
case 4: return kDVec4_Type;
default: ABORT("unsupported vector column count (%d)", columns);
}
case 2:
switch (columns) {
case 2: return kDMat2x2_Type;
case 3: return kDMat3x2_Type;
case 4: return kDMat4x2_Type;
default: ABORT("unsupported matrix column count (%d)", columns);
}
case 3:
switch (columns) {
case 2: return kDMat2x3_Type;
case 3: return kDMat3x3_Type;
case 4: return kDMat4x3_Type;
default: ABORT("unsupported matrix column count (%d)", columns);
}
case 4:
switch (columns) {
case 2: return kDMat2x4_Type;
case 3: return kDMat3x4_Type;
case 4: return kDMat4x4_Type;
default: ABORT("unsupported matrix column count (%d)", columns);
}
default: ABORT("unsupported row count (%d)", rows);
}
} else if (*this == *kInt_Type) {
switch (rows) {
case 1:
switch (columns) {
case 2: return kIVec2_Type;
case 3: return kIVec3_Type;
case 4: return kIVec4_Type;
default: ABORT("unsupported vector column count (%d)", columns);
}
default: ABORT("unsupported row count (%d)", rows);
}
} else if (*this == *kUInt_Type) {
switch (rows) {
case 1:
switch (columns) {
case 2: return kUVec2_Type;
case 3: return kUVec3_Type;
case 4: return kUVec4_Type;
default: ABORT("unsupported vector column count (%d)", columns);
}
default: ABORT("unsupported row count (%d)", rows);
}
}
ABORT("unsupported scalar_to_compound type %s", this->description().c_str());
}
const std::shared_ptr<Type> kVoid_Type(new Type("void"));
const std::shared_ptr<Type> kDouble_Type(new Type("double", true));
const std::shared_ptr<Type> kDVec2_Type(new Type("dvec2", kDouble_Type, 2));
const std::shared_ptr<Type> kDVec3_Type(new Type("dvec3", kDouble_Type, 3));
const std::shared_ptr<Type> kDVec4_Type(new Type("dvec4", kDouble_Type, 4));
const std::shared_ptr<Type> kFloat_Type(new Type("float", true, { kDouble_Type }));
const std::shared_ptr<Type> kVec2_Type(new Type("vec2", kFloat_Type, 2));
const std::shared_ptr<Type> kVec3_Type(new Type("vec3", kFloat_Type, 3));
const std::shared_ptr<Type> kVec4_Type(new Type("vec4", kFloat_Type, 4));
const std::shared_ptr<Type> kUInt_Type(new Type("uint", true, { kFloat_Type, kDouble_Type }));
const std::shared_ptr<Type> kUVec2_Type(new Type("uvec2", kUInt_Type, 2));
const std::shared_ptr<Type> kUVec3_Type(new Type("uvec3", kUInt_Type, 3));
const std::shared_ptr<Type> kUVec4_Type(new Type("uvec4", kUInt_Type, 4));
const std::shared_ptr<Type> kInt_Type(new Type("int", true, { kUInt_Type, kFloat_Type,
kDouble_Type }));
const std::shared_ptr<Type> kIVec2_Type(new Type("ivec2", kInt_Type, 2));
const std::shared_ptr<Type> kIVec3_Type(new Type("ivec3", kInt_Type, 3));
const std::shared_ptr<Type> kIVec4_Type(new Type("ivec4", kInt_Type, 4));
const std::shared_ptr<Type> kBool_Type(new Type("bool", false));
const std::shared_ptr<Type> kBVec2_Type(new Type("bvec2", kBool_Type, 2));
const std::shared_ptr<Type> kBVec3_Type(new Type("bvec3", kBool_Type, 3));
const std::shared_ptr<Type> kBVec4_Type(new Type("bvec4", kBool_Type, 4));
const std::shared_ptr<Type> kMat2x2_Type(new Type("mat2", kFloat_Type, 2, 2));
const std::shared_ptr<Type> kMat2x3_Type(new Type("mat2x3", kFloat_Type, 2, 3));
const std::shared_ptr<Type> kMat2x4_Type(new Type("mat2x4", kFloat_Type, 2, 4));
const std::shared_ptr<Type> kMat3x2_Type(new Type("mat3x2", kFloat_Type, 3, 2));
const std::shared_ptr<Type> kMat3x3_Type(new Type("mat3", kFloat_Type, 3, 3));
const std::shared_ptr<Type> kMat3x4_Type(new Type("mat3x4", kFloat_Type, 3, 4));
const std::shared_ptr<Type> kMat4x2_Type(new Type("mat4x2", kFloat_Type, 4, 2));
const std::shared_ptr<Type> kMat4x3_Type(new Type("mat4x3", kFloat_Type, 4, 3));
const std::shared_ptr<Type> kMat4x4_Type(new Type("mat4", kFloat_Type, 4, 4));
const std::shared_ptr<Type> kDMat2x2_Type(new Type("dmat2", kFloat_Type, 2, 2));
const std::shared_ptr<Type> kDMat2x3_Type(new Type("dmat2x3", kFloat_Type, 2, 3));
const std::shared_ptr<Type> kDMat2x4_Type(new Type("dmat2x4", kFloat_Type, 2, 4));
const std::shared_ptr<Type> kDMat3x2_Type(new Type("dmat3x2", kFloat_Type, 3, 2));
const std::shared_ptr<Type> kDMat3x3_Type(new Type("dmat3", kFloat_Type, 3, 3));
const std::shared_ptr<Type> kDMat3x4_Type(new Type("dmat3x4", kFloat_Type, 3, 4));
const std::shared_ptr<Type> kDMat4x2_Type(new Type("dmat4x2", kFloat_Type, 4, 2));
const std::shared_ptr<Type> kDMat4x3_Type(new Type("dmat4x3", kFloat_Type, 4, 3));
const std::shared_ptr<Type> kDMat4x4_Type(new Type("dmat4", kFloat_Type, 4, 4));
const std::shared_ptr<Type> kSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true));
const std::shared_ptr<Type> kSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true));
const std::shared_ptr<Type> kSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true));
const std::shared_ptr<Type> kSamplerCube_Type(new Type("samplerCube"));
const std::shared_ptr<Type> kSampler2DRect_Type(new Type("sampler2DRect"));
const std::shared_ptr<Type> kSampler1DArray_Type(new Type("sampler1DArray"));
const std::shared_ptr<Type> kSampler2DArray_Type(new Type("sampler2DArray"));
const std::shared_ptr<Type> kSamplerCubeArray_Type(new Type("samplerCubeArray"));
const std::shared_ptr<Type> kSamplerBuffer_Type(new Type("samplerBuffer"));
const std::shared_ptr<Type> kSampler2DMS_Type(new Type("sampler2DMS"));
const std::shared_ptr<Type> kSampler2DMSArray_Type(new Type("sampler2DMSArray"));
const std::shared_ptr<Type> kSampler1DShadow_Type(new Type("sampler1DShadow"));
const std::shared_ptr<Type> kSampler2DShadow_Type(new Type("sampler2DShadow"));
const std::shared_ptr<Type> kSamplerCubeShadow_Type(new Type("samplerCubeShadow"));
const std::shared_ptr<Type> kSampler2DRectShadow_Type(new Type("sampler2DRectShadow"));
const std::shared_ptr<Type> kSampler1DArrayShadow_Type(new Type("sampler1DArrayShadow"));
const std::shared_ptr<Type> kSampler2DArrayShadow_Type(new Type("sampler2DArrayShadow"));
const std::shared_ptr<Type> kSamplerCubeArrayShadow_Type(new Type("samplerCubeArrayShadow"));
static std::vector<std::shared_ptr<Type>> type(std::shared_ptr<Type> t) {
return { t, t, t, t };
}
// FIXME figure out what we're supposed to do with the gsampler et al. types
const std::shared_ptr<Type> kGSampler1D_Type(new Type("$gsampler1D", type(kSampler1D_Type)));
const std::shared_ptr<Type> kGSampler2D_Type(new Type("$gsampler2D", type(kSampler2D_Type)));
const std::shared_ptr<Type> kGSampler3D_Type(new Type("$gsampler3D", type(kSampler3D_Type)));
const std::shared_ptr<Type> kGSamplerCube_Type(new Type("$gsamplerCube", type(kSamplerCube_Type)));
const std::shared_ptr<Type> kGSampler2DRect_Type(new Type("$gsampler2DRect",
type(kSampler2DRect_Type)));
const std::shared_ptr<Type> kGSampler1DArray_Type(new Type("$gsampler1DArray",
type(kSampler1DArray_Type)));
const std::shared_ptr<Type> kGSampler2DArray_Type(new Type("$gsampler2DArray",
type(kSampler2DArray_Type)));
const std::shared_ptr<Type> kGSamplerCubeArray_Type(new Type("$gsamplerCubeArray",
type(kSamplerCubeArray_Type)));
const std::shared_ptr<Type> kGSamplerBuffer_Type(new Type("$gsamplerBuffer",
type(kSamplerBuffer_Type)));
const std::shared_ptr<Type> kGSampler2DMS_Type(new Type("$gsampler2DMS",
type(kSampler2DMS_Type)));
const std::shared_ptr<Type> kGSampler2DMSArray_Type(new Type("$gsampler2DMSArray",
type(kSampler2DMSArray_Type)));
const std::shared_ptr<Type> kGSampler2DArrayShadow_Type(new Type("$gsampler2DArrayShadow",
type(kSampler2DArrayShadow_Type)));
const std::shared_ptr<Type> kGSamplerCubeArrayShadow_Type(new Type("$gsamplerCubeArrayShadow",
type(kSamplerCubeArrayShadow_Type)));
const std::shared_ptr<Type> kGenType_Type(new Type("$genType", { kFloat_Type, kVec2_Type,
kVec3_Type, kVec4_Type }));
const std::shared_ptr<Type> kGenDType_Type(new Type("$genDType", { kDouble_Type, kDVec2_Type,
kDVec3_Type, kDVec4_Type }));
const std::shared_ptr<Type> kGenIType_Type(new Type("$genIType", { kInt_Type, kIVec2_Type,
kIVec3_Type, kIVec4_Type }));
const std::shared_ptr<Type> kGenUType_Type(new Type("$genUType", { kUInt_Type, kUVec2_Type,
kUVec3_Type, kUVec4_Type }));
const std::shared_ptr<Type> kGenBType_Type(new Type("$genBType", { kBool_Type, kBVec2_Type,
kBVec3_Type, kBVec4_Type }));
const std::shared_ptr<Type> kMat_Type(new Type("$mat"));
const std::shared_ptr<Type> kVec_Type(new Type("$vec", { kVec2_Type, kVec2_Type, kVec3_Type,
kVec4_Type }));
const std::shared_ptr<Type> kGVec_Type(new Type("$gvec"));
const std::shared_ptr<Type> kGVec2_Type(new Type("$gvec2"));
const std::shared_ptr<Type> kGVec3_Type(new Type("$gvec3"));
const std::shared_ptr<Type> kGVec4_Type(new Type("$gvec4", type(kVec4_Type)));
const std::shared_ptr<Type> kDVec_Type(new Type("$dvec"));
const std::shared_ptr<Type> kIVec_Type(new Type("$ivec"));
const std::shared_ptr<Type> kUVec_Type(new Type("$uvec"));
const std::shared_ptr<Type> kBVec_Type(new Type("$bvec", { kBVec2_Type, kBVec2_Type,
kBVec3_Type, kBVec4_Type }));
const std::shared_ptr<Type> kInvalid_Type(new Type("<INVALID>"));
} // namespace

438
src/sksl/ir/SkSLType.h Normal file
View File

@ -0,0 +1,438 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKIASL_TYPE
#define SKIASL_TYPE
#include "SkSLModifiers.h"
#include "SkSLSymbol.h"
#include "../SkSLPosition.h"
#include "../SkSLUtil.h"
#include "../spirv.h"
#include <vector>
#include <memory>
namespace SkSL {
/**
* Represents a type, such as int or vec4.
*/
class Type : public Symbol {
public:
struct Field {
Field(Modifiers modifiers, std::string name, std::shared_ptr<Type> type)
: fModifiers(modifiers)
, fName(std::move(name))
, fType(std::move(type)) {}
const std::string description() {
return fType->description() + " " + fName + ";";
}
const Modifiers fModifiers;
const std::string fName;
const std::shared_ptr<Type> fType;
};
enum Kind {
kScalar_Kind,
kVector_Kind,
kMatrix_Kind,
kArray_Kind,
kStruct_Kind,
kGeneric_Kind,
kSampler_Kind,
kOther_Kind
};
// Create an "other" (special) type with the given name. These types cannot be directly
// referenced from user code.
Type(std::string name)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kOther_Kind) {}
// Create a generic type which maps to the listed types.
Type(std::string name, std::vector<std::shared_ptr<Type>> types)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kGeneric_Kind)
, fCoercibleTypes(std::move(types)) {
ASSERT(fCoercibleTypes.size() == 4);
}
// Create a struct type with the given fields.
Type(std::string name, std::vector<Field> fields)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kStruct_Kind)
, fFields(std::move(fields)) {}
// Create a scalar type.
Type(std::string name, bool isNumber)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kScalar_Kind)
, fIsNumber(isNumber)
, fColumns(1)
, fRows(1) {}
// Create a scalar type which can be coerced to the listed types.
Type(std::string name, bool isNumber, std::vector<std::shared_ptr<Type>> coercibleTypes)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kScalar_Kind)
, fIsNumber(isNumber)
, fCoercibleTypes(std::move(coercibleTypes))
, fColumns(1)
, fRows(1) {}
// Create a vector type.
Type(std::string name, std::shared_ptr<Type> componentType, int columns)
: Type(name, kVector_Kind, componentType, columns) {}
// Create a vector or array type.
Type(std::string name, Kind kind, std::shared_ptr<Type> componentType, int columns)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kind)
, fComponentType(std::move(componentType))
, fColumns(columns)
, fRows(1)
, fDimensions(SpvDim1D) {}
// Create a matrix type.
Type(std::string name, std::shared_ptr<Type> componentType, int columns, int rows)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kMatrix_Kind)
, fComponentType(std::move(componentType))
, fColumns(columns)
, fRows(rows)
, fDimensions(SpvDim1D) {}
// Create a sampler type.
Type(std::string name, SpvDim_ dimensions, bool isDepth, bool isArrayed, bool isMultisampled,
bool isSampled)
: INHERITED(Position(), kType_Kind, std::move(name))
, fTypeKind(kSampler_Kind)
, fDimensions(dimensions)
, fIsDepth(isDepth)
, fIsArrayed(isArrayed)
, fIsMultisampled(isMultisampled)
, fIsSampled(isSampled) {}
std::string name() const {
return fName;
}
std::string description() const override {
return fName;
}
bool operator==(const Type& other) const {
return fName == other.fName;
}
bool operator!=(const Type& other) const {
return fName != other.fName;
}
/**
* Returns the category (scalar, vector, matrix, etc.) of this type.
*/
Kind kind() const {
return fTypeKind;
}
/**
* Returns true if this is a numeric scalar type.
*/
bool isNumber() const {
return fIsNumber;
}
/**
* Returns true if an instance of this type can be freely coerced (implicitly converted) to
* another type.
*/
bool canCoerceTo(std::shared_ptr<Type> other) const {
int cost;
return determineCoercionCost(other, &cost);
}
/**
* Determines the "cost" of coercing (implicitly converting) this type to another type. The cost
* is a number with no particular meaning other than that lower costs are preferable to higher
* costs. Returns true if a conversion is possible, false otherwise. The value of the out
* parameter is undefined if false is returned.
*/
bool determineCoercionCost(std::shared_ptr<Type> other, int* outCost) const;
/**
* For matrices and vectors, returns the type of individual cells (e.g. mat2 has a component
* type of kFloat_Type). For all other types, causes an assertion failure.
*/
std::shared_ptr<Type> componentType() const {
ASSERT(fComponentType);
return fComponentType;
}
/**
* For matrices and vectors, returns the number of columns (e.g. both mat3 and vec3 return 3).
* For scalars, returns 1. For arrays, returns either the size of the array (if known) or -1.
* For all other types, causes an assertion failure.
*/
int columns() const {
ASSERT(fTypeKind == kScalar_Kind || fTypeKind == kVector_Kind ||
fTypeKind == kMatrix_Kind || fTypeKind == kArray_Kind);
return fColumns;
}
/**
* For matrices, returns the number of rows (e.g. mat2x4 returns 4). For vectors and scalars,
* returns 1. For all other types, causes an assertion failure.
*/
int rows() const {
ASSERT(fRows > 0);
return fRows;
}
std::vector<Field> fields() const {
ASSERT(fTypeKind == kStruct_Kind);
return fFields;
}
/**
* For generic types, returns the types that this generic type can substitute for. For other
* types, returns a list of other types that this type can be coerced into.
*/
std::vector<std::shared_ptr<Type>> coercibleTypes() const {
ASSERT(fCoercibleTypes.size() > 0);
return fCoercibleTypes;
}
int dimensions() const {
ASSERT(fTypeKind == kSampler_Kind);
return fDimensions;
}
bool isDepth() const {
ASSERT(fTypeKind == kSampler_Kind);
return fIsDepth;
}
bool isArrayed() const {
ASSERT(fTypeKind == kSampler_Kind);
return fIsArrayed;
}
bool isMultisampled() const {
ASSERT(fTypeKind == kSampler_Kind);
return fIsMultisampled;
}
bool isSampled() const {
ASSERT(fTypeKind == kSampler_Kind);
return fIsSampled;
}
static size_t vector_alignment(size_t componentSize, int columns) {
return componentSize * (columns + columns % 2);
}
/**
* Returns the type's required alignment (when putting this type into a struct, the offset must
* be a multiple of the alignment).
*/
size_t alignment() const {
// See OpenGL Spec 7.6.2.2 Standard Uniform Block Layout
switch (fTypeKind) {
case kScalar_Kind:
return this->size();
case kVector_Kind:
return vector_alignment(fComponentType->size(), fColumns);
case kMatrix_Kind:
return (vector_alignment(fComponentType->size(), fRows) + 15) & ~15;
case kArray_Kind:
// round up to next multiple of 16
return (fComponentType->alignment() + 15) & ~15;
case kStruct_Kind: {
size_t result = 16;
for (size_t i = 0; i < fFields.size(); i++) {
size_t alignment = fFields[i].fType->alignment();
if (alignment > result) {
result = alignment;
}
}
}
default:
ABORT(("cannot determine size of type " + fName).c_str());
}
}
/**
* For matrices and arrays, returns the number of bytes from the start of one entry (row, in
* the case of matrices) to the start of the next.
*/
size_t stride() const {
switch (fTypeKind) {
case kMatrix_Kind: // fall through
case kArray_Kind:
return this->alignment();
default:
ABORT("type does not have a stride");
}
}
/**
* Returns the size of this type in bytes.
*/
size_t size() const {
switch (fTypeKind) {
case kScalar_Kind:
// FIXME need to take precision into account, once we figure out how we want to
// handle it...
return 4;
case kVector_Kind:
return fColumns * fComponentType->size();
case kMatrix_Kind:
return vector_alignment(fComponentType->size(), fRows) * fColumns;
case kArray_Kind:
return fColumns * this->stride();
case kStruct_Kind: {
size_t total = 0;
for (size_t i = 0; i < fFields.size(); i++) {
size_t alignment = fFields[i].fType->alignment();
if (total % alignment != 0) {
total += alignment - total % alignment;
}
ASSERT(false);
ASSERT(total % alignment == 0);
total += fFields[i].fType->size();
}
return total;
}
default:
ABORT(("cannot determine size of type " + fName).c_str());
}
}
/**
* Returns the corresponding vector or matrix type with the specified number of columns and
* rows.
*/
std::shared_ptr<Type> toCompound(int columns, int rows);
private:
typedef Symbol INHERITED;
const Kind fTypeKind;
const bool fIsNumber = false;
const std::shared_ptr<Type> fComponentType = nullptr;
const std::vector<std::shared_ptr<Type>> fCoercibleTypes = { };
const int fColumns = -1;
const int fRows = -1;
const std::vector<Field> fFields = { };
const SpvDim_ fDimensions = SpvDim1D;
const bool fIsDepth = false;
const bool fIsArrayed = false;
const bool fIsMultisampled = false;
const bool fIsSampled = false;
};
extern const std::shared_ptr<Type> kVoid_Type;
extern const std::shared_ptr<Type> kFloat_Type;
extern const std::shared_ptr<Type> kVec2_Type;
extern const std::shared_ptr<Type> kVec3_Type;
extern const std::shared_ptr<Type> kVec4_Type;
extern const std::shared_ptr<Type> kDouble_Type;
extern const std::shared_ptr<Type> kDVec2_Type;
extern const std::shared_ptr<Type> kDVec3_Type;
extern const std::shared_ptr<Type> kDVec4_Type;
extern const std::shared_ptr<Type> kInt_Type;
extern const std::shared_ptr<Type> kIVec2_Type;
extern const std::shared_ptr<Type> kIVec3_Type;
extern const std::shared_ptr<Type> kIVec4_Type;
extern const std::shared_ptr<Type> kUInt_Type;
extern const std::shared_ptr<Type> kUVec2_Type;
extern const std::shared_ptr<Type> kUVec3_Type;
extern const std::shared_ptr<Type> kUVec4_Type;
extern const std::shared_ptr<Type> kBool_Type;
extern const std::shared_ptr<Type> kBVec2_Type;
extern const std::shared_ptr<Type> kBVec3_Type;
extern const std::shared_ptr<Type> kBVec4_Type;
extern const std::shared_ptr<Type> kMat2x2_Type;
extern const std::shared_ptr<Type> kMat2x3_Type;
extern const std::shared_ptr<Type> kMat2x4_Type;
extern const std::shared_ptr<Type> kMat3x2_Type;
extern const std::shared_ptr<Type> kMat3x3_Type;
extern const std::shared_ptr<Type> kMat3x4_Type;
extern const std::shared_ptr<Type> kMat4x2_Type;
extern const std::shared_ptr<Type> kMat4x3_Type;
extern const std::shared_ptr<Type> kMat4x4_Type;
extern const std::shared_ptr<Type> kDMat2x2_Type;
extern const std::shared_ptr<Type> kDMat2x3_Type;
extern const std::shared_ptr<Type> kDMat2x4_Type;
extern const std::shared_ptr<Type> kDMat3x2_Type;
extern const std::shared_ptr<Type> kDMat3x3_Type;
extern const std::shared_ptr<Type> kDMat3x4_Type;
extern const std::shared_ptr<Type> kDMat4x2_Type;
extern const std::shared_ptr<Type> kDMat4x3_Type;
extern const std::shared_ptr<Type> kDMat4x4_Type;
extern const std::shared_ptr<Type> kSampler1D_Type;
extern const std::shared_ptr<Type> kSampler2D_Type;
extern const std::shared_ptr<Type> kSampler3D_Type;
extern const std::shared_ptr<Type> kSamplerCube_Type;
extern const std::shared_ptr<Type> kSampler2DRect_Type;
extern const std::shared_ptr<Type> kSampler1DArray_Type;
extern const std::shared_ptr<Type> kSampler2DArray_Type;
extern const std::shared_ptr<Type> kSamplerCubeArray_Type;
extern const std::shared_ptr<Type> kSamplerBuffer_Type;
extern const std::shared_ptr<Type> kSampler2DMS_Type;
extern const std::shared_ptr<Type> kSampler2DMSArray_Type;
extern const std::shared_ptr<Type> kGSampler1D_Type;
extern const std::shared_ptr<Type> kGSampler2D_Type;
extern const std::shared_ptr<Type> kGSampler3D_Type;
extern const std::shared_ptr<Type> kGSamplerCube_Type;
extern const std::shared_ptr<Type> kGSampler2DRect_Type;
extern const std::shared_ptr<Type> kGSampler1DArray_Type;
extern const std::shared_ptr<Type> kGSampler2DArray_Type;
extern const std::shared_ptr<Type> kGSamplerCubeArray_Type;
extern const std::shared_ptr<Type> kGSamplerBuffer_Type;
extern const std::shared_ptr<Type> kGSampler2DMS_Type;
extern const std::shared_ptr<Type> kGSampler2DMSArray_Type;
extern const std::shared_ptr<Type> kSampler1DShadow_Type;
extern const std::shared_ptr<Type> kSampler2DShadow_Type;
extern const std::shared_ptr<Type> kSamplerCubeShadow_Type;
extern const std::shared_ptr<Type> kSampler2DRectShadow_Type;
extern const std::shared_ptr<Type> kSampler1DArrayShadow_Type;
extern const std::shared_ptr<Type> kSampler2DArrayShadow_Type;
extern const std::shared_ptr<Type> kSamplerCubeArrayShadow_Type;
extern const std::shared_ptr<Type> kGSampler2DArrayShadow_Type;
extern const std::shared_ptr<Type> kGSamplerCubeArrayShadow_Type;
extern const std::shared_ptr<Type> kGenType_Type;
extern const std::shared_ptr<Type> kGenDType_Type;
extern const std::shared_ptr<Type> kGenIType_Type;
extern const std::shared_ptr<Type> kGenUType_Type;
extern const std::shared_ptr<Type> kGenBType_Type;
extern const std::shared_ptr<Type> kMat_Type;
extern const std::shared_ptr<Type> kVec_Type;
extern const std::shared_ptr<Type> kGVec_Type;
extern const std::shared_ptr<Type> kGVec2_Type;
extern const std::shared_ptr<Type> kGVec3_Type;
extern const std::shared_ptr<Type> kGVec4_Type;
extern const std::shared_ptr<Type> kDVec_Type;
extern const std::shared_ptr<Type> kIVec_Type;
extern const std::shared_ptr<Type> kUVec_Type;
extern const std::shared_ptr<Type> kBVec_Type;
extern const std::shared_ptr<Type> kInvalid_Type;
} // namespace
#endif

Some files were not shown because too many files have changed in this diff Show More