re-land of added sk_FragCoord support to skslc
BUG=skia:
Change-Id: Ifac1aa39839058787ad1794200c3dbb93c147a69
Reviewed-on: https://skia-review.googlesource.com/5850
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 20609af..bbbcf4c 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -27,6 +27,7 @@
#include "SkMipMap.h"
#include "SkPixmap.h"
#include "SkStrokeRec.h"
+#include "SkSLCompiler.h"
#include "SkTemplates.h"
#include "SkTypes.h"
#include "../private/GrGLSL.h"
@@ -399,13 +400,20 @@
str = vshaderTxt.c_str();
length = SkToInt(vshaderTxt.size());
+ SkSL::Program::Settings settings;
+ settings.fCaps = shaderCaps;
+ SkSL::Program::Inputs inputs;
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fPLSSetupProgram.fProgram,
- GR_GL_VERTEX_SHADER, &str, &length, 1, &fStats);
+ GR_GL_VERTEX_SHADER, &str, &length, 1, &fStats,
+ settings, &inputs);
+ SkASSERT(inputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fPLSSetupProgram.fProgram,
- GR_GL_FRAGMENT_SHADER, &str, &length, 1, &fStats);
+ GR_GL_FRAGMENT_SHADER, &str, &length, 1, &fStats,
+ settings, &inputs);
+ SkASSERT(inputs.isEmpty());
GL_CALL(LinkProgram(fPLSSetupProgram.fProgram));
@@ -3855,15 +3863,20 @@
str = vshaderTxt.c_str();
length = SkToInt(vshaderTxt.size());
+ SkSL::Program::Settings settings;
+ settings.fCaps = shaderCaps;
+ SkSL::Program::Inputs inputs;
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
GR_GL_VERTEX_SHADER, &str, &length, 1,
- &fStats);
+ &fStats, settings, &inputs);
+ SkASSERT(inputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram,
GR_GL_FRAGMENT_SHADER, &str, &length, 1,
- &fStats);
+ &fStats, settings, &inputs);
+ SkASSERT(inputs.isEmpty());
GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram));
@@ -4008,15 +4021,20 @@
str = vshaderTxt.c_str();
length = SkToInt(vshaderTxt.size());
+ SkSL::Program::Settings settings;
+ settings.fCaps = shaderCaps;
+ SkSL::Program::Inputs inputs;
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
GR_GL_VERTEX_SHADER, &str, &length, 1,
- &fStats);
+ &fStats, settings, &inputs);
+ SkASSERT(inputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram,
GR_GL_FRAGMENT_SHADER, &str, &length, 1,
- &fStats);
+ &fStats, settings, &inputs);
+ SkASSERT(inputs.isEmpty());
GL_CALL(LinkProgram(fMipmapPrograms[progIdx].fProgram));
@@ -4097,15 +4115,20 @@
str = vshaderTxt.c_str();
length = SkToInt(vshaderTxt.size());
+ SkSL::Program::Settings settings;
+ settings.fCaps = this->caps()->shaderCaps();
+ SkSL::Program::Inputs inputs;
GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram,
GR_GL_VERTEX_SHADER, &str, &length, 1,
- &fStats);
+ &fStats, settings, &inputs);
+ SkASSERT(inputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram,
GR_GL_FRAGMENT_SHADER, &str, &length, 1,
- &fStats);
+ &fStats, settings, &inputs);
+ SkASSERT(inputs.isEmpty());
GL_CALL(LinkProgram(fWireRectProgram.fProgram));
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index cc29022..045593f 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -69,7 +69,9 @@
bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
GrGLuint programId,
GrGLenum type,
- SkTDArray<GrGLuint>* shaderIds) {
+ SkTDArray<GrGLuint>* shaderIds,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs) {
GrGLGpu* gpu = this->gpu();
GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
programId,
@@ -77,7 +79,9 @@
shader.fCompilerStrings.begin(),
shader.fCompilerStringLengths.begin(),
shader.fCompilerStrings.count(),
- gpu->stats());
+ gpu->stats(),
+ settings,
+ outInputs);
if (!shaderId) {
return false;
@@ -100,8 +104,13 @@
this->finalizeShaders();
// compile shaders and bind attributes / uniforms
+ SkSL::Program::Settings settings;
+ settings.fCaps = this->gpu()->glCaps().shaderCaps();
+ settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin;
+ SkSL::Program::Inputs inputs;
SkTDArray<GrGLuint> shadersToDelete;
- if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) {
+ if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete,
+ settings, &inputs)) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
@@ -117,16 +126,22 @@
}
if (primProc.willUseGeoShader() &&
- !this->compileAndAttachShaders(fGS, programID, GR_GL_GEOMETRY_SHADER, &shadersToDelete)) {
+ !this->compileAndAttachShaders(fGS, programID, GR_GL_GEOMETRY_SHADER, &shadersToDelete,
+ settings, &inputs)) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
- if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) {
+ if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete,
+ settings, &inputs)) {
this->cleanupProgram(programID, shadersToDelete);
return nullptr;
}
+ if (inputs.fRTHeight) {
+ this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
+ }
+
this->bindProgramResourceLocations(programID);
GL_CALL(LinkProgram(programID));
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index a88f278..84d6d91 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -14,6 +14,7 @@
#include "gl/GrGLVaryingHandler.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"
+#include "ir/SkSLProgram.h"
class GrFragmentProcessor;
class GrGLContextInfo;
@@ -46,7 +47,9 @@
bool compileAndAttachShaders(GrGLSLShaderBuilder& shader,
GrGLuint programId,
GrGLenum type,
- SkTDArray<GrGLuint>* shaderIds);
+ SkTDArray<GrGLuint>* shaderIds,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs);
GrGLProgram* finalize();
void bindProgramResourceLocations(GrGLuint programID);
bool checkLinkStatus(GrGLuint programID);
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
index bd4921b..df44edd 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
@@ -44,7 +44,9 @@
const char** strings,
int* lengths,
int count,
- GrGpu::Stats* stats) {
+ GrGpu::Stats* stats,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs) {
const GrGLInterface* gli = glCtx.interface();
GrGLuint shaderId;
@@ -65,21 +67,20 @@
SkString glsl;
if (type == GR_GL_VERTEX_SHADER || type == GR_GL_FRAGMENT_SHADER) {
SkSL::Compiler& compiler = *glCtx.compiler();
- SkDEBUGCODE(bool result = )compiler.toGLSL(type == GR_GL_VERTEX_SHADER
- ? SkSL::Program::kVertex_Kind
+ std::unique_ptr<SkSL::Program> program;
+ program = compiler.convertProgram(
+ type == GR_GL_VERTEX_SHADER ? SkSL::Program::kVertex_Kind
: SkSL::Program::kFragment_Kind,
- sksl,
- *glCtx.caps()->shaderCaps(),
- &glsl);
-#ifdef SK_DEBUG
- if (!result) {
+ sksl,
+ settings);
+ if (!program || !compiler.toGLSL(*program, &glsl)) {
SkDebugf("SKSL compilation error\n----------------------\n");
SkDebugf("SKSL:\n");
dump_string(sksl);
SkDebugf("\nErrors:\n%s\n", compiler.errorText().c_str());
SkDEBUGFAIL("SKSL compilation failed!\n");
}
-#endif
+ *outInputs = program->fInputs;
} else {
// TODO: geometry shader support in sksl.
SkASSERT(type == GR_GL_GEOMETRY_SHADER);
diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.h b/src/gpu/gl/builders/GrGLShaderStringBuilder.h
index 71fce6a..242fe61 100644
--- a/src/gpu/gl/builders/GrGLShaderStringBuilder.h
+++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.h
@@ -20,6 +20,8 @@
const char** strings,
int* lengths,
int count,
- GrGpu::Stats*);
+ GrGpu::Stats*,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* inputs);
#endif
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index 8355f1d..7ef7348 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -132,49 +132,7 @@
const char* GrGLSLFragmentShaderBuilder::fragmentPosition() {
SkDEBUGCODE(fUsedProcessorFeatures |= GrProcessor::kFragmentPosition_RequiredFeature;)
-
- const GrShaderCaps* shaderCaps = fProgramBuilder->shaderCaps();
- // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
- // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
- // declaration varies in earlier GLSL specs. So it is simpler to omit it.
- if (kTopLeft_GrSurfaceOrigin == this->getSurfaceOrigin()) {
- fSetupFragPosition = true;
- return "gl_FragCoord";
- } else if (const char* extension = shaderCaps->fragCoordConventionsExtensionString()) {
- if (!fSetupFragPosition) {
- if (shaderCaps->generation() < k150_GrGLSLGeneration) {
- this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
- extension);
- }
- fInputs.push_back().set(kVec4f_GrSLType,
- "gl_FragCoord",
- GrShaderVar::kIn_TypeModifier,
- kDefault_GrSLPrecision,
- "origin_upper_left");
- fSetupFragPosition = true;
- }
- return "gl_FragCoord";
- } else {
- static const char* kTempName = "tmpXYFragCoord";
- static const char* kCoordName = "fragCoordYDown";
- if (!fSetupFragPosition) {
- const char* rtHeightName;
-
- fProgramBuilder->addRTHeightUniform("RTHeight", &rtHeightName);
-
- // The Adreno compiler seems to be very touchy about access to "gl_FragCoord".
- // Accessing glFragCoord.zw can cause a program to fail to link. Additionally,
- // depending on the surrounding code, accessing .xy with a uniform involved can
- // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand
- // (and only accessing .xy) seems to "fix" things.
- this->codePrependf("\thighp vec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n", kCoordName,
- kTempName, rtHeightName, kTempName);
- this->codePrependf("highp vec2 %s = gl_FragCoord.xy;", kTempName);
- fSetupFragPosition = true;
- }
- SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
- return kCoordName;
- }
+ return "sk_FragCoord";
}
const char* GrGLSLFragmentShaderBuilder::distanceVectorName() const {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 590439d..1182996 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -470,13 +470,13 @@
outName);
}
-void GrGLSLProgramBuilder::addRTHeightUniform(const char* name, const char** outName) {
+void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
fUniformHandles.fRTHeightUni =
uniformHandler->internalAddUniformArray(kFragment_GrShaderFlag,
kFloat_GrSLType, kDefault_GrSLPrecision,
- name, false, 0, outName);
+ name, false, 0, nullptr);
}
void GrGLSLProgramBuilder::cleanupFragmentProcessors() {
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index fdb6e11..bfd9f7a 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -72,7 +72,7 @@
// Used to add a uniform for the RenderTarget height (used for frag position) without mangling
// the name of the uniform inside of a stage.
- void addRTHeightUniform(const char* name, const char** outName);
+ void addRTHeightUniform(const char* name);
// Generates a name for a variable. The generated string will be name prefixed by the prefix
// char (unless the prefix is '\0'). It also will mangle the name to be stage-specific unless
diff --git a/src/gpu/vk/GrVkCopyManager.cpp b/src/gpu/vk/GrVkCopyManager.cpp
index 78194fc..7b2c734 100644
--- a/src/gpu/vk/GrVkCopyManager.cpp
+++ b/src/gpu/vk/GrVkCopyManager.cpp
@@ -65,19 +65,21 @@
"}"
);
- if (!GrCompileVkShaderModule(gpu, vertShaderText.c_str(),
- VK_SHADER_STAGE_VERTEX_BIT,
- &fVertShaderModule, &fShaderStageInfo[0])) {
+ SkSL::Program::Settings settings;
+ SkSL::Program::Inputs inputs;
+ if (!GrCompileVkShaderModule(gpu, vertShaderText.c_str(), VK_SHADER_STAGE_VERTEX_BIT,
+ &fVertShaderModule, &fShaderStageInfo[0], settings, &inputs)) {
this->destroyResources(gpu);
return false;
}
+ SkASSERT(inputs.isEmpty());
- if (!GrCompileVkShaderModule(gpu, fragShaderText.c_str(),
- VK_SHADER_STAGE_FRAGMENT_BIT,
- &fFragShaderModule, &fShaderStageInfo[1])) {
+ if (!GrCompileVkShaderModule(gpu, fragShaderText.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT,
+ &fFragShaderModule, &fShaderStageInfo[1], settings, &inputs)) {
this->destroyResources(gpu);
return false;
}
+ SkASSERT(inputs.isEmpty());
VkDescriptorSetLayout dsLayout[2];
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index a742c4b..f31c743 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -36,9 +36,7 @@
#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)
@@ -119,11 +117,7 @@
}
#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));
@@ -193,11 +187,7 @@
VK_CALL(DestroyCommandPool(fDevice, fCmdPool, nullptr));
-#if USE_SKSL
delete fCompiler;
-#else
- shaderc_compiler_release(fCompiler);
-#endif
#ifdef SK_ENABLE_VK_LAYERS
if (fCallback) {
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 0e5f228..5dddb93 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -8,8 +8,6 @@
#ifndef GrVkGpu_DEFINED
#define GrVkGpu_DEFINED
-#define USE_SKSL 1
-
#include "GrGpu.h"
#include "GrGpuFactory.h"
#include "vk/GrVkBackendContext.h"
@@ -20,15 +18,6 @@
#include "GrVkResourceProvider.h"
#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;
@@ -43,6 +32,10 @@
class GrVkTexture;
struct GrVkInterface;
+namespace SkSL {
+ class Compiler;
+}
+
class GrVkGpu : public GrGpu {
public:
static GrGpu* Create(GrBackendContext backendContext, const GrContextOptions& options,
@@ -120,15 +113,9 @@
bool byRegion,
VkImageMemoryBarrier* barrier) const;
-#if USE_SKSL
SkSL::Compiler* shaderCompiler() const {
return fCompiler;
}
-#else
- shaderc_compiler_t shadercCompiler() const {
- return fCompiler;
- }
-#endif
void onResolveRenderTarget(GrRenderTarget* target) override;
@@ -272,13 +259,9 @@
VkDebugReportCallbackEXT fCallback;
#endif
-#if USE_SKSL
+ // compiler used for compiling sksl into spirv. We only want to create the compiler once since
+ // there is significant overhead to the first compile of any compiler.
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;
};
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index 49f5cf8..4125938 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -58,11 +58,11 @@
outputColor.addLayoutQualifier("location = 0, index = 1");
}
-bool GrVkPipelineStateBuilder::CreateVkShaderModule(const GrVkGpu* gpu,
- VkShaderStageFlagBits stage,
+bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage,
const GrGLSLShaderBuilder& builder,
VkShaderModule* shaderModule,
- VkPipelineShaderStageCreateInfo* stageInfo) {
+ VkPipelineShaderStageCreateInfo* stageInfo,
+ const SkSL::Program::Settings& settings) {
SkString shaderString;
for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
if (builder.fCompilerStrings[i]) {
@@ -70,7 +70,17 @@
shaderString.append("\n");
}
}
- return GrCompileVkShaderModule(gpu, shaderString.c_str(), stage, shaderModule, stageInfo);
+
+ SkSL::Program::Inputs inputs;
+ bool result = GrCompileVkShaderModule(fGpu, shaderString.c_str(), stage, shaderModule,
+ stageInfo, settings, &inputs);
+ if (!result) {
+ return false;
+ }
+ if (inputs.fRTHeight) {
+ this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
+ }
+ return result;
}
GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& stencil,
@@ -117,20 +127,22 @@
this->finalizeShaders();
VkPipelineShaderStageCreateInfo shaderStageInfo[2];
- SkAssertResult(CreateVkShaderModule(fGpu,
- VK_SHADER_STAGE_VERTEX_BIT,
- fVS,
- &vertShaderModule,
- &shaderStageInfo[0]));
+ SkSL::Program::Settings settings;
+ settings.fFlipY = this->pipeline().getRenderTarget()->origin() != kTopLeft_GrSurfaceOrigin;
+ SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
+ fVS,
+ &vertShaderModule,
+ &shaderStageInfo[0],
+ settings));
// TODO: geometry shader support.
SkASSERT(!this->primitiveProcessor().willUseGeoShader());
- SkAssertResult(CreateVkShaderModule(fGpu,
- VK_SHADER_STAGE_FRAGMENT_BIT,
- fFS,
- &fragShaderModule,
- &shaderStageInfo[1]));
+ SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_FRAGMENT_BIT,
+ fFS,
+ &fragShaderModule,
+ &shaderStageInfo[1],
+ settings));
GrVkPipeline* pipeline = resourceProvider.createPipeline(fPipeline,
stencil,
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.h b/src/gpu/vk/GrVkPipelineStateBuilder.h
index c36f9ac..cf4a983 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.h
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.h
@@ -14,6 +14,7 @@
#include "GrVkPipelineState.h"
#include "GrVkUniformHandler.h"
#include "GrVkVaryingHandler.h"
+#include "SkSLCompiler.h"
#include "vk/GrVkDefines.h"
@@ -55,11 +56,11 @@
const GrVkRenderPass& renderPass,
const GrVkPipelineState::Desc&);
- static bool CreateVkShaderModule(const GrVkGpu* gpu,
- VkShaderStageFlagBits stage,
- const GrGLSLShaderBuilder& builder,
- VkShaderModule* shaderModule,
- VkPipelineShaderStageCreateInfo* stageInfo);
+ bool createVkShaderModule(VkShaderStageFlagBits stage,
+ const GrGLSLShaderBuilder& builder,
+ VkShaderModule* shaderModule,
+ VkPipelineShaderStageCreateInfo* stageInfo,
+ const SkSL::Program::Settings& settings);
GrGLSLUniformHandler* uniformHandler() override { return &fUniformHandler; }
const GrGLSLUniformHandler* uniformHandler() const override { return &fUniformHandler; }
diff --git a/src/gpu/vk/GrVkUtil.cpp b/src/gpu/vk/GrVkUtil.cpp
index 4446dfe..3071fc8 100644
--- a/src/gpu/vk/GrVkUtil.cpp
+++ b/src/gpu/vk/GrVkUtil.cpp
@@ -8,9 +8,7 @@
#include "GrVkUtil.h"
#include "vk/GrVkGpu.h"
-#if USE_SKSL
#include "SkSLCompiler.h"
-#endif
bool GrPixelConfigToVkFormat(GrPixelConfig config, VkFormat* format) {
VkFormat dontCare;
@@ -262,7 +260,6 @@
}
}
-#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;
@@ -270,85 +267,49 @@
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;
+
+VkShaderStageFlagBits skiasl_kind_to_vk_shader_stage(SkSL::Program::Kind kind) {
+ if (SkSL::Program::kVertex_Kind == kind) {
+ return VK_SHADER_STAGE_VERTEX_BIT;
}
- SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
- return shaderc_glsl_fragment_shader;
+ SkASSERT(SkSL::Program::kFragment_Kind == kind);
+ return VK_SHADER_STAGE_FRAGMENT_BIT;
}
-#endif
bool GrCompileVkShaderModule(const GrVkGpu* gpu,
const char* shaderString,
VkShaderStageFlagBits stage,
VkShaderModule* shaderModule,
- VkPipelineShaderStageCreateInfo* stageInfo) {
+ VkPipelineShaderStageCreateInfo* stageInfo,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs) {
+ std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
+ vk_shader_stage_to_skiasl_kind(stage),
+ SkString(shaderString),
+ settings);
+ if (!program) {
+ SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
+ SkASSERT(false);
+ }
+ *outInputs = program->fInputs;
+ SkString code;
+ if (!gpu->shaderCompiler()->toSPIRV(*program, &code)) {
+ SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
+ return false;
+ }
+
VkShaderModuleCreateInfo moduleCreateInfo;
memset(&moduleCreateInfo, 0, sizeof(VkShaderModuleCreateInfo));
moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
moduleCreateInfo.pNext = nullptr;
moduleCreateInfo.flags = 0;
-
-#if USE_SKSL
- SkString code;
-#else
- shaderc_compilation_result_t result = nullptr;
-#endif
-
- if (gpu->vkCaps().canUseGLSLForShaderModule()) {
- moduleCreateInfo.codeSize = strlen(shaderString);
- moduleCreateInfo.pCode = (const uint32_t*)shaderString;
- } else {
-
-#if USE_SKSL
- bool result = gpu->shaderCompiler()->toSPIRV(vk_shader_stage_to_skiasl_kind(stage),
- SkString(shaderString),
- &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();
-
- shaderc_shader_kind shadercStage = vk_shader_stage_to_shaderc_kind(stage);
- result = shaderc_compile_into_spv(compiler,
- shaderString,
- strlen(shaderString),
- shadercStage,
- "shader",
- "main",
- options);
- shaderc_compile_options_release(options);
-#ifdef SK_DEBUG
- if (shaderc_result_get_num_errors(result)) {
- SkDebugf("%s\n", shaderString);
- SkDebugf("%s\n", shaderc_result_get_error_message(result));
- return false;
- }
-#endif // SK_DEBUG
-
- moduleCreateInfo.codeSize = shaderc_result_get_length(result);
- moduleCreateInfo.pCode = (const uint32_t*)shaderc_result_get_bytes(result);
-#endif // USE_SKSL
- }
+ moduleCreateInfo.codeSize = code.size();
+ moduleCreateInfo.pCode = (const uint32_t*)code.c_str();
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;
}
@@ -357,7 +318,7 @@
stageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stageInfo->pNext = nullptr;
stageInfo->flags = 0;
- stageInfo->stage = stage;
+ stageInfo->stage = skiasl_kind_to_vk_shader_stage(program->fKind);
stageInfo->module = *shaderModule;
stageInfo->pName = "main";
stageInfo->pSpecializationInfo = nullptr;
diff --git a/src/gpu/vk/GrVkUtil.h b/src/gpu/vk/GrVkUtil.h
index fae3c20..ba07bca 100644
--- a/src/gpu/vk/GrVkUtil.h
+++ b/src/gpu/vk/GrVkUtil.h
@@ -12,6 +12,7 @@
#include "GrTypes.h"
#include "vk/GrVkDefines.h"
#include "vk/GrVkInterface.h"
+#include "ir/SkSLProgram.h"
class GrVkGpu;
@@ -48,6 +49,8 @@
const char* shaderString,
VkShaderStageFlagBits stage,
VkShaderModule* shaderModule,
- VkPipelineShaderStageCreateInfo* stageInfo);
+ VkPipelineShaderStageCreateInfo* stageInfo,
+ const SkSL::Program::Settings& settings,
+ SkSL::Program::Inputs* outInputs);
#endif
diff --git a/src/sksl/SkSLCodeGenerator.h b/src/sksl/SkSLCodeGenerator.h
index ed93778..111e73a 100644
--- a/src/sksl/SkSLCodeGenerator.h
+++ b/src/sksl/SkSLCodeGenerator.h
@@ -18,9 +18,20 @@
*/
class CodeGenerator {
public:
+ CodeGenerator(const Program* program, ErrorReporter* errors, SkWStream* out)
+ : fProgram(*program)
+ , fErrors(*errors)
+ , fOut(out) {}
+
virtual ~CodeGenerator() {}
- virtual void generateCode(const Program& program, ErrorReporter& errors, SkWStream& out) = 0;
+ virtual bool generateCode() = 0;
+
+protected:
+
+ const Program& fProgram;
+ ErrorReporter& fErrors;
+ SkWStream* fOut;
};
} // namespace
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 1be0ba9..9faf836 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -9,6 +9,7 @@
#include "ast/SkSLASTPrecision.h"
#include "SkSLCFGGenerator.h"
+#include "SkSLGLSLCodeGenerator.h"
#include "SkSLIRGenerator.h"
#include "SkSLParser.h"
#include "SkSLSPIRVCodeGenerator.h"
@@ -392,10 +393,10 @@
}
std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
- std::unordered_map<SkString, CapValue> caps) {
+ const Program::Settings& settings) {
fErrorText = "";
fErrorCount = 0;
- fIRGenerator->start(&caps);
+ fIRGenerator->start(&settings);
std::vector<std::unique_ptr<ProgramElement>> elements;
Modifiers::Flag ignored;
switch (kind) {
@@ -409,13 +410,54 @@
fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Modifiers::Flag defaultPrecision;
this->internalConvertProgram(text, &defaultPrecision, &elements);
- auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements),
- fIRGenerator->fSymbolTable));
+ auto result = std::unique_ptr<Program>(new Program(kind, settings, defaultPrecision, &fContext,
+ std::move(elements),
+ fIRGenerator->fSymbolTable,
+ fIRGenerator->fInputs));
fIRGenerator->finish();
this->writeErrorCount();
+ if (fErrorCount) {
+ return nullptr;
+ }
+ return result;
+}
+
+
+bool Compiler::toSPIRV(const Program& program, SkWStream& out) {
+ SPIRVCodeGenerator cg(&fContext, &program, this, &out);
+ bool result = cg.generateCode();
+ this->writeErrorCount();
return result;
}
+bool Compiler::toSPIRV(const Program& program, SkString* out) {
+ SkDynamicMemoryWStream buffer;
+ bool result = this->toSPIRV(program, buffer);
+ if (result) {
+ sk_sp<SkData> data(buffer.detachAsData());
+ *out = SkString((const char*) data->data(), data->size());
+ }
+ return result;
+}
+
+bool Compiler::toGLSL(const Program& program, SkWStream& out) {
+ GLSLCodeGenerator cg(&fContext, &program, this, &out);
+ bool result = cg.generateCode();
+ this->writeErrorCount();
+ return result;
+}
+
+bool Compiler::toGLSL(const Program& program, SkString* out) {
+ SkDynamicMemoryWStream buffer;
+ bool result = this->toGLSL(program, buffer);
+ if (result) {
+ sk_sp<SkData> data(buffer.detachAsData());
+ *out = SkString((const char*) data->data(), data->size());
+ }
+ return result;
+}
+
+
void Compiler::error(Position position, SkString msg) {
fErrorCount++;
fErrorText += "error: " + position.description() + ": " + msg.c_str() + "\n";
@@ -436,70 +478,4 @@
}
}
-bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkWStream& out) {
- std::unordered_map<SkString, CapValue> capsMap;
- auto program = this->convertProgram(kind, text, capsMap);
- if (fErrorCount == 0) {
- SkSL::SPIRVCodeGenerator cg(&fContext);
- cg.generateCode(*program.get(), *this, out);
- this->writeErrorCount();
- }
- return fErrorCount == 0;
-}
-
-bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkString* out) {
- SkDynamicMemoryWStream buffer;
- bool result = this->toSPIRV(kind, text, buffer);
- if (result) {
- sk_sp<SkData> data(buffer.detachAsData());
- *out = SkString((const char*) data->data(), data->size());
- }
- return result;
-}
-
-static void fill_caps(const GrShaderCaps& caps, std::unordered_map<SkString, CapValue>* capsMap) {
-#define CAP(name) capsMap->insert(std::make_pair(SkString(#name), CapValue(caps.name())));
- CAP(fbFetchSupport);
- CAP(fbFetchNeedsCustomOutput);
- CAP(bindlessTextureSupport);
- CAP(dropsTileOnZeroDivide);
- CAP(flatInterpolationSupport);
- CAP(noperspectiveInterpolationSupport);
- CAP(multisampleInterpolationSupport);
- CAP(sampleVariablesSupport);
- CAP(sampleMaskOverrideCoverageSupport);
- CAP(externalTextureSupport);
- CAP(texelFetchSupport);
- CAP(imageLoadStoreSupport);
- CAP(mustEnableAdvBlendEqs);
- CAP(mustEnableSpecificAdvBlendEqs);
- CAP(mustDeclareFragmentShaderOutput);
- CAP(canUseAnyFunctionInShader);
-#undef CAP
-}
-
-bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps,
- SkWStream& out) {
- std::unordered_map<SkString, CapValue> capsMap;
- fill_caps(caps, &capsMap);
- auto program = this->convertProgram(kind, text, capsMap);
- if (fErrorCount == 0) {
- SkSL::GLSLCodeGenerator cg(&fContext, &caps);
- cg.generateCode(*program.get(), *this, out);
- this->writeErrorCount();
- }
- return fErrorCount == 0;
-}
-
-bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps,
- SkString* out) {
- SkDynamicMemoryWStream buffer;
- bool result = this->toGLSL(kind, text, caps, buffer);
- if (result) {
- sk_sp<SkData> data(buffer.detachAsData());
- *out = SkString((const char*) data->data(), data->size());
- }
- return result;
-}
-
} // namespace
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 114f8ef..0f893f7 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -16,9 +16,9 @@
#include "SkSLContext.h"
#include "SkSLErrorReporter.h"
#include "SkSLIRGenerator.h"
-#include "SkSLGLSLCodeGenerator.h"
#define SK_FRAGCOLOR_BUILTIN 10001
+#define SK_FRAGCOORD_BUILTIN 15
namespace SkSL {
@@ -26,7 +26,7 @@
/**
* 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
+ * 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.
*
@@ -38,18 +38,16 @@
~Compiler();
- std::unique_ptr<Program> convertProgram(Program::Kind kind, SkString text,
- std::unordered_map<SkString, CapValue> caps);
+ std::unique_ptr<Program> convertProgram(Program::Kind kind, SkString text,
+ const Program::Settings& settings);
- bool toSPIRV(Program::Kind kind, const SkString& text, SkWStream& out);
-
- bool toSPIRV(Program::Kind kind, const SkString& text, SkString* out);
+ bool toSPIRV(const Program& program, SkWStream& out);
- bool toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps,
- SkWStream& out);
-
- bool toGLSL(Program::Kind kind, const SkString& text, const GrShaderCaps& caps,
- SkString* out);
+ bool toSPIRV(const Program& program, SkString* out);
+
+ bool toGLSL(const Program& program, SkWStream& out);
+
+ bool toGLSL(const Program& program, SkString* out);
void error(Position position, SkString msg) override;
@@ -57,11 +55,15 @@
void writeErrorCount();
+ int errorCount() override {
+ return fErrorCount;
+ }
+
private:
void addDefinition(const Expression* lvalue, const Expression* expr,
std::unordered_map<const Variable*, const Expression*>* definitions);
-
- void addDefinitions(const BasicBlock::Node& node,
+
+ void addDefinitions(const BasicBlock::Node& node,
std::unordered_map<const Variable*, const Expression*>* definitions);
void scanCFG(CFG* cfg, BlockId block, std::set<BlockId>* workList);
diff --git a/src/sksl/SkSLErrorReporter.h b/src/sksl/SkSLErrorReporter.h
index 585a97c..85d386d 100644
--- a/src/sksl/SkSLErrorReporter.h
+++ b/src/sksl/SkSLErrorReporter.h
@@ -24,6 +24,8 @@
}
virtual void error(Position position, SkString msg) = 0;
+
+ virtual int errorCount() = 0;
};
} // namespace
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 5b74724..dd8c0cf 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -11,14 +11,13 @@
#include "GLSL.std.450.h"
+#include "SkSLCompiler.h"
#include "ir/SkSLExpressionStatement.h"
#include "ir/SkSLExtension.h"
#include "ir/SkSLIndexExpression.h"
#include "ir/SkSLModifiersDeclaration.h"
#include "ir/SkSLVariableReference.h"
-#define SK_FRAGCOLOR_BUILTIN 10001
-
namespace SkSL {
void GLSLCodeGenerator::write(const char* s) {
@@ -134,10 +133,10 @@
return ((FunctionCall&) expr).fFunction.fName == "abs";
}
-// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
+// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
// Tegra3 compiler bug.
void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
- ASSERT(!fCaps.canUseMinAndAbsTogether());
+ ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
SkString tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
SkString tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n";
@@ -150,7 +149,8 @@
}
void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
- if (!fCaps.canUseMinAndAbsTogether() && c.fFunction.fName == "min" && c.fFunction.fBuiltin) {
+ if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" &&
+ c.fFunction.fBuiltin) {
ASSERT(c.fArguments.size() == 2);
if (is_abs(*c.fArguments[0])) {
this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
@@ -163,8 +163,9 @@
return;
}
}
- if (fCaps.mustForceNegatedAtanParamToFloat() && c.fFunction.fName == "atan" &&
- c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
+ if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
+ c.fFunction.fName == "atan" &&
+ c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
if (p.fOperator == Token::MINUS) {
@@ -176,11 +177,11 @@
return;
}
}
- if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") &&
- c.fFunction.fBuiltin && fCaps.shaderDerivativeExtensionString()) {
- ASSERT(fCaps.shaderDerivativeSupport());
+ if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") &&
+ c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) {
+ ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport());
fHeader.writeText("#extension ");
- fHeader.writeText(fCaps.shaderDerivativeExtensionString());
+ fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString());
fHeader.writeText(" : require\n");
fFoundDerivatives = true;
}
@@ -235,7 +236,7 @@
break;
}
this->write("texture");
- if (fCaps.generation() < k130_GrGLSLGeneration) {
+ if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
this->write(dim);
}
if (proj) {
@@ -266,15 +267,67 @@
this->write(")");
}
-void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
- if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) {
- if (fCaps.mustDeclareFragmentShaderOutput()) {
- this->write("sk_FragColor");
- } else {
- this->write("gl_FragColor");
+void GLSLCodeGenerator::writeFragCoord() {
+ // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
+ // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
+ // declaration varies in earlier GLSL specs. So it is simpler to omit it.
+ if (!fProgram.fSettings.fFlipY) {
+ this->write("gl_FragCoord");
+ } else if (const char* extension =
+ fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) {
+ if (!fSetupFragPositionGlobal) {
+ if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
+ fHeader.writeText("#extension ");
+ fHeader.writeText(extension);
+ fHeader.writeText(" : require\n");
+ }
+ fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n");
+ fSetupFragPositionGlobal = true;
}
+ this->write("gl_FragCoord");
} else {
- this->write(ref.fVariable.fName);
+ if (!fSetupFragPositionGlobal) {
+ // The Adreno compiler seems to be very touchy about access to "gl_FragCoord".
+ // Accessing glFragCoord.zw can cause a program to fail to link. Additionally,
+ // depending on the surrounding code, accessing .xy with a uniform involved can
+ // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand
+ // (and only accessing .xy) seems to "fix" things.
+ const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
+ : "";
+ fHeader.writeText("uniform ");
+ fHeader.writeText(precision);
+ fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n");
+ fSetupFragPositionGlobal = true;
+ }
+ if (!fSetupFragPositionLocal) {
+ const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
+ : "";
+ fFunctionHeader += precision;
+ fFunctionHeader += " vec2 _sktmpCoord = gl_FragCoord.xy;\n";
+ fFunctionHeader += precision;
+ fFunctionHeader += " vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME
+ " - _sktmpCoord.y, 1.0, 1.0);\n";
+ fSetupFragPositionLocal = true;
+ }
+ this->write("sk_FragCoord");
+ }
+}
+
+
+void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
+ switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
+ case SK_FRAGCOLOR_BUILTIN:
+ if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
+ this->write("sk_FragColor");
+ } else {
+ this->write("gl_FragColor");
+ }
+ break;
+ case SK_FRAGCOORD_BUILTIN:
+ this->writeFragCoord();
+ break;
+ default:
+ this->write(ref.fVariable.fName);
}
}
@@ -484,14 +537,16 @@
(modifiers.fFlags & Modifiers::kOut_Flag)) {
this->write("inout ");
} else if (modifiers.fFlags & Modifiers::kIn_Flag) {
- if (globalContext && fCaps.generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
+ if (globalContext &&
+ fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
: "varying ");
} else {
this->write("in ");
}
} else if (modifiers.fFlags & Modifiers::kOut_Flag) {
- if (globalContext && fCaps.generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
+ if (globalContext &&
+ fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
this->write("varying ");
} else {
this->write("out ");
@@ -503,7 +558,7 @@
if (modifiers.fFlags & Modifiers::kConst_Flag) {
this->write("const ");
}
- if (fCaps.usesPrecisionModifiers()) {
+ if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
if (modifiers.fFlags & Modifiers::kLowp_Flag) {
this->write("lowp ");
}
@@ -554,9 +609,9 @@
this->writeExpression(*var.fValue, kTopLevel_Precedence);
}
if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) {
- if (fCaps.imageLoadStoreExtensionString()) {
+ if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) {
fHeader.writeText("#extension ");
- fHeader.writeText(fCaps.imageLoadStoreExtensionString());
+ fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString());
fHeader.writeText(" : require\n");
}
fFoundImageDecl = true;
@@ -670,23 +725,22 @@
this->write(";");
}
-void GLSLCodeGenerator::generateCode(const Program& program, ErrorReporter& errors,
- SkWStream& out) {
- ASSERT(fOut == nullptr);
+bool GLSLCodeGenerator::generateCode() {
+ SkWStream* rawOut = fOut;
fOut = &fHeader;
- fProgramKind = program.fKind;
- this->write(fCaps.versionDeclString());
+ fProgramKind = fProgram.fKind;
+ this->write(fProgram.fSettings.fCaps->versionDeclString());
this->writeLine();
- for (const auto& e : program.fElements) {
+ for (const auto& e : fProgram.fElements) {
if (e->fKind == ProgramElement::kExtension_Kind) {
this->writeExtension((Extension&) *e);
}
}
SkDynamicMemoryWStream body;
fOut = &body;
- if (fCaps.usesPrecisionModifiers()) {
+ if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
this->write("precision ");
- switch (program.fDefaultPrecision) {
+ switch (fProgram.fDefaultPrecision) {
case Modifiers::kLowp_Flag:
this->write("lowp");
break;
@@ -702,7 +756,7 @@
}
this->writeLine(" float;");
}
- for (const auto& e : program.fElements) {
+ for (const auto& e : fProgram.fElements) {
switch (e->fKind) {
case ProgramElement::kExtension_Kind:
break;
@@ -715,9 +769,9 @@
this->writeVarDeclarations(decl, true);
this->writeLine();
} else if (builtin == SK_FRAGCOLOR_BUILTIN &&
- fCaps.mustDeclareFragmentShaderOutput()) {
+ fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
this->write("out ");
- if (fCaps.usesPrecisionModifiers()) {
+ if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
this->write("mediump ");
}
this->writeLine("vec4 sk_FragColor;");
@@ -742,8 +796,9 @@
}
fOut = nullptr;
- write_data(*fHeader.detachAsData(), out);
- write_data(*body.detachAsData(), out);
+ write_data(*fHeader.detachAsData(), *rawOut);
+ write_data(*body.detachAsData(), *rawOut);
+ return true;
}
}
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index ffc5a4d..0ae2c5c 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -4,7 +4,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-
+
#ifndef SKSL_GLSLCODEGENERATOR
#define SKSL_GLSLCODEGENERATOR
@@ -12,7 +12,6 @@
#include <tuple>
#include <unordered_map>
-#include "GrShaderCaps.h"
#include "SkStream.h"
#include "SkSLCodeGenerator.h"
#include "ir/SkSLBinaryExpression.h"
@@ -72,11 +71,12 @@
kTopLevel_Precedence = 18
};
- GLSLCodeGenerator(const Context* context, const GrShaderCaps* caps)
- : fContext(*context)
- , fCaps(*caps) {}
+ GLSLCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
+ SkWStream* out)
+ : INHERITED(program, errors, out)
+ , fContext(*context) {}
- void generateCode(const Program& program, ErrorReporter& errors, SkWStream& out) override;
+ virtual bool generateCode() override;
private:
void write(const char* s);
@@ -104,15 +104,17 @@
void writeLayout(const Layout& layout);
void writeModifiers(const Modifiers& modifiers, bool globalContext);
-
+
void writeGlobalVars(const VarDeclaration& vs);
void writeVarDeclarations(const VarDeclarations& decl, bool global);
+ void writeFragCoord();
+
void writeVariableReference(const VariableReference& ref);
void writeExpression(const Expression& expr, Precedence parentPrecedence);
-
+
void writeIntrinsicCall(const FunctionCall& c);
void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
@@ -156,21 +158,23 @@
void writeReturnStatement(const ReturnStatement& r);
const Context& fContext;
- const GrShaderCaps& fCaps;
- SkWStream* fOut = nullptr;
SkDynamicMemoryWStream fHeader;
SkString fFunctionHeader;
Program::Kind fProgramKind;
int fVarCount = 0;
int fIndentation = 0;
bool fAtLineStart = false;
- // Keeps track of which struct types we have written. Given that we are unlikely to ever write
- // more than one or two structs per shader, a simple linear search will be faster than anything
+ // Keeps track of which struct types we have written. Given that we are unlikely to ever write
+ // more than one or two structs per shader, a simple linear search will be faster than anything
// fancier.
std::vector<const Type*> fWrittenStructs;
// true if we have run into usages of dFdx / dFdy
bool fFoundDerivatives = false;
bool fFoundImageDecl = false;
+ bool fSetupFragPositionGlobal = false;
+ bool fSetupFragPositionLocal = false;
+
+ typedef CodeGenerator INHERITED;
};
}
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 023f191..0698817 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -9,6 +9,7 @@
#include "limits.h"
+#include "SkSLCompiler.h"
#include "ast/SkSLASTBoolLiteral.h"
#include "ast/SkSLASTFieldSuffix.h"
#include "ast/SkSLASTFloatLiteral.h"
@@ -84,7 +85,6 @@
ErrorReporter& errorReporter)
: fContext(*context)
, fCurrentFunction(nullptr)
-, fCapsMap(nullptr)
, fSymbolTable(std::move(symbolTable))
, fLoopLevel(0)
, fErrors(errorReporter) {}
@@ -97,14 +97,40 @@
fSymbolTable = fSymbolTable->fParent;
}
-void IRGenerator::start(std::unordered_map<SkString, CapValue>* caps) {
- this->fCapsMap = caps;
+static void fill_caps(const GrShaderCaps& caps, std::unordered_map<SkString, CapValue>* capsMap) {
+#define CAP(name) capsMap->insert(std::make_pair(SkString(#name), CapValue(caps.name())));
+ CAP(fbFetchSupport);
+ CAP(fbFetchNeedsCustomOutput);
+ CAP(bindlessTextureSupport);
+ CAP(dropsTileOnZeroDivide);
+ CAP(flatInterpolationSupport);
+ CAP(noperspectiveInterpolationSupport);
+ CAP(multisampleInterpolationSupport);
+ CAP(sampleVariablesSupport);
+ CAP(sampleMaskOverrideCoverageSupport);
+ CAP(externalTextureSupport);
+ CAP(texelFetchSupport);
+ CAP(imageLoadStoreSupport);
+ CAP(mustEnableAdvBlendEqs);
+ CAP(mustEnableSpecificAdvBlendEqs);
+ CAP(mustDeclareFragmentShaderOutput);
+ CAP(canUseAnyFunctionInShader);
+#undef CAP
+}
+
+void IRGenerator::start(const Program::Settings* settings) {
+ fSettings = settings;
+ fCapsMap.clear();
+ if (settings->fCaps) {
+ fill_caps(*settings->fCaps, &fCapsMap);
+ }
this->pushSymbolTable();
+ fInputs.reset();
}
void IRGenerator::finish() {
this->popSymbolTable();
- this->fCapsMap = nullptr;
+ fSettings = nullptr;
}
std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
@@ -600,6 +626,11 @@
case Symbol::kVariable_Kind: {
const Variable* var = (const Variable*) result;
this->markReadFrom(*var);
+ if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
+ fSettings->fFlipY &&
+ (!fSettings->fCaps || !fSettings->fCaps->fragCoordConventionsExtensionString())) {
+ fInputs.fRTHeight = true;
+ }
return std::unique_ptr<VariableReference>(new VariableReference(identifier.fPosition,
*var));
}
@@ -1336,9 +1367,8 @@
}
std::unique_ptr<Expression> IRGenerator::getCap(Position position, SkString name) {
- ASSERT(fCapsMap);
- auto found = fCapsMap->find(name);
- if (found == fCapsMap->end()) {
+ auto found = fCapsMap.find(name);
+ if (found == fCapsMap.end()) {
fErrors.error(position, "unknown capability flag '" + name + "'");
return nullptr;
}
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index ade6150..13b20fb 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -40,6 +40,7 @@
#include "ir/SkSLInterfaceBlock.h"
#include "ir/SkSLModifiers.h"
#include "ir/SkSLModifiersDeclaration.h"
+#include "ir/SkSLProgram.h"
#include "ir/SkSLSymbolTable.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLType.h"
@@ -87,12 +88,14 @@
std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration(
const ASTModifiersDeclaration& m);
+ Program::Inputs fInputs;
+
private:
/**
- * Prepare to compile a program. Pushes a new symbol table and installs the caps so that
- * references to sk_Caps.<cap> can be resolved.
+ * Prepare to compile a program. Resets state, pushes a new symbol table, and installs the
+ * settings.
*/
- void start(std::unordered_map<SkString, CapValue>* caps);
+ void start(const Program::Settings* settings);
/**
* Performs cleanup after compilation is complete.
@@ -153,7 +156,8 @@
const Context& fContext;
const FunctionDeclaration* fCurrentFunction;
- const std::unordered_map<SkString, CapValue>* fCapsMap;
+ const Program::Settings* fSettings;
+ std::unordered_map<SkString, CapValue> fCapsMap;
std::shared_ptr<SymbolTable> fSymbolTable;
int fLoopLevel;
ErrorReporter& fErrors;
diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp
index 381fcf0..f493b05 100644
--- a/src/sksl/SkSLMain.cpp
+++ b/src/sksl/SkSLMain.cpp
@@ -37,6 +37,9 @@
printf("error reading '%s'\n", argv[1]);
exit(2);
}
+ SkSL::Program::Settings settings;
+ sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
+ settings.fCaps = caps.get();
SkString name(argv[2]);
if (name.endsWith(".spirv")) {
SkFILEWStream out(argv[2]);
@@ -45,7 +48,8 @@
printf("error writing '%s'\n", argv[2]);
exit(4);
}
- if (!compiler.toSPIRV(kind, text, out)) {
+ std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings);
+ if (!program || !compiler.toSPIRV(*program, out)) {
printf("%s", compiler.errorText().c_str());
exit(3);
}
@@ -56,7 +60,8 @@
printf("error writing '%s'\n", argv[2]);
exit(4);
}
- if (!compiler.toGLSL(kind, text, *SkSL::ShaderCapsFactory::Default(), out)) {
+ std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, text, settings);
+ if (!program || !compiler.toGLSL(*program, out)) {
printf("%s", compiler.errorText().c_str());
exit(3);
}
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index b2857f4..63fe020 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -994,14 +994,14 @@
const Layout& fieldLayout = type.fields()[i].fModifiers.fLayout;
if (fieldLayout.fOffset >= 0) {
if (fieldLayout.fOffset <= (int) offset) {
- fErrors->error(type.fPosition,
- "offset of field '" + type.fields()[i].fName + "' must be at "
- "least " + to_string((int) offset));
+ fErrors.error(type.fPosition,
+ "offset of field '" + type.fields()[i].fName + "' must be at "
+ "least " + to_string((int) offset));
}
if (fieldLayout.fOffset % alignment) {
- fErrors->error(type.fPosition,
- "offset of field '" + type.fields()[i].fName + "' must be a multiple"
- " of " + to_string((int) alignment));
+ fErrors.error(type.fPosition,
+ "offset of field '" + type.fields()[i].fName + "' must be a multiple"
+ " of " + to_string((int) alignment));
}
offset = fieldLayout.fOffset;
} else {
@@ -1847,11 +1847,64 @@
}
SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, SkWStream& out) {
+ SpvId result = this->nextId();
auto entry = fVariableMap.find(&ref.fVariable);
ASSERT(entry != fVariableMap.end());
SpvId var = entry->second;
- SpvId result = this->nextId();
this->writeInstruction(SpvOpLoad, this->getType(ref.fVariable.fType), result, var, out);
+ if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
+ fProgram.fSettings.fFlipY) {
+ // need to remap to a top-left coordinate system
+ if (fRTHeightStructId == (SpvId) -1) {
+ // height variable hasn't been written yet
+ std::shared_ptr<SymbolTable> st(new SymbolTable(fErrors));
+ ASSERT(fRTHeightFieldIndex == (SpvId) -1);
+ std::vector<Type::Field> fields;
+ fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME),
+ fContext.fFloat_Type.get());
+ SkString name("sksl_synthetic_uniforms");
+ Type intfStruct(Position(), name, fields);
+ Layout layout(-1, -1, 1, -1, -1, -1, -1, false, false, false, Layout::Format::kUnspecified,
+ false);
+ Variable intfVar(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name,
+ intfStruct, Variable::kGlobal_Storage);
+ InterfaceBlock intf(Position(), intfVar, st);
+ fRTHeightStructId = this->writeInterfaceBlock(intf);
+ fRTHeightFieldIndex = 0;
+ }
+ ASSERT(fRTHeightFieldIndex != (SpvId) -1);
+ // write vec4(gl_FragCoord.x, u_skRTHeight - gl_FragCoord.y, 0.0, 1.0)
+ SpvId xId = this->nextId();
+ this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), xId,
+ result, 0, out);
+ IntLiteral fieldIndex(fContext, Position(), fRTHeightFieldIndex);
+ SpvId fieldIndexId = this->writeIntLiteral(fieldIndex);
+ SpvId heightRead = this->nextId();
+ this->writeOpCode(SpvOpAccessChain, 5, out);
+ this->writeWord(this->getPointerType(*fContext.fFloat_Type, SpvStorageClassUniform), out);
+ this->writeWord(heightRead, out);
+ this->writeWord(fRTHeightStructId, out);
+ this->writeWord(fieldIndexId, out);
+ SpvId rawYId = this->nextId();
+ this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fFloat_Type), rawYId,
+ result, 1, out);
+ SpvId flippedYId = this->nextId();
+ this->writeInstruction(SpvOpFSub, this->getType(*fContext.fFloat_Type), flippedYId,
+ heightRead, rawYId, out);
+ FloatLiteral zero(fContext, Position(), 0.0);
+ SpvId zeroId = writeFloatLiteral(zero);
+ FloatLiteral one(fContext, Position(), 1.0);
+ SpvId oneId = writeFloatLiteral(one);
+ SpvId flipped = this->nextId();
+ this->writeOpCode(SpvOpCompositeConstruct, 7, out);
+ this->writeWord(this->getType(*fContext.fVec4_Type), out);
+ this->writeWord(flipped, out);
+ this->writeWord(xId, out);
+ this->writeWord(flippedYId, out);
+ this->writeWord(zeroId, out);
+ this->writeWord(oneId, out);
+ return flipped;
+ }
return result;
}
@@ -2442,12 +2495,22 @@
MemoryLayout layout = intf.fVariable.fModifiers.fLayout.fPushConstant ?
MemoryLayout(MemoryLayout::k430_Standard) :
fDefaultLayout;
- SpvId type = this->getType(intf.fVariable.fType, layout);
SpvId result = this->nextId();
- this->writeInstruction(SpvOpDecorate, type, SpvDecorationBlock, fDecorationBuffer);
+ const Type* type = &intf.fVariable.fType;
+ if (fProgram.fInputs.fRTHeight) {
+ ASSERT(fRTHeightStructId == (SpvId) -1);
+ ASSERT(fRTHeightFieldIndex == (SpvId) -1);
+ std::vector<Type::Field> fields = type->fields();
+ fRTHeightStructId = result;
+ fRTHeightFieldIndex = fields.size();
+ fields.emplace_back(Modifiers(), SkString(SKSL_RTHEIGHT_NAME), fContext.fFloat_Type.get());
+ type = new Type(type->fPosition, type->name(), fields);
+ }
+ SpvId typeId = this->getType(*type, layout);
+ this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBlock, fDecorationBuffer);
SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers);
SpvId ptrType = this->nextId();
- this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, type, fConstantBuffer);
+ this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, typeId, fConstantBuffer);
this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConstantBuffer);
this->writeLayout(intf.fVariable.fModifiers.fLayout, result);
fVariableMap[&intf.fVariable] = result;
@@ -2734,6 +2797,7 @@
}
}
+ write_data(*fExtraGlobalsBuffer.detachAsData(), out);
write_data(*fNameBuffer.detachAsData(), out);
write_data(*fDecorationBuffer.detachAsData(), out);
write_data(*fConstantBuffer.detachAsData(), out);
@@ -2741,18 +2805,17 @@
write_data(*body.detachAsData(), out);
}
-void SPIRVCodeGenerator::generateCode(const Program& program, ErrorReporter& errors,
- SkWStream& out) {
- fErrors = &errors;
- this->writeWord(SpvMagicNumber, out);
- this->writeWord(SpvVersion, out);
- this->writeWord(SKSL_MAGIC, out);
+bool SPIRVCodeGenerator::generateCode() {
+ ASSERT(!fErrors.errorCount());
+ this->writeWord(SpvMagicNumber, *fOut);
+ this->writeWord(SpvVersion, *fOut);
+ this->writeWord(SKSL_MAGIC, *fOut);
SkDynamicMemoryWStream buffer;
- this->writeInstructions(program, buffer);
- this->writeWord(fIdCount, out);
- this->writeWord(0, out); // reserved, always zero
- write_data(*buffer.detachAsData(), out);
- fErrors = nullptr;
+ this->writeInstructions(fProgram, buffer);
+ this->writeWord(fIdCount, *fOut);
+ this->writeWord(0, *fOut); // reserved, always zero
+ write_data(*buffer.detachAsData(), *fOut);
+ return 0 == fErrors.errorCount();
}
}
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index 5567ec5..96ff187 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -62,18 +62,21 @@
virtual void store(SpvId value, SkWStream& out) = 0;
};
- SPIRVCodeGenerator(const Context* context)
- : fContext(*context)
+ SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
+ SkWStream* out)
+ : INHERITED(program, errors, out)
+ , fContext(*context)
, fDefaultLayout(MemoryLayout::k140_Standard)
, fCapabilities(1 << SpvCapabilityShader)
, fIdCount(1)
, fBoolTrue(0)
, fBoolFalse(0)
+ , fSetupFragPosition(false)
, fCurrentBlock(0) {
this->setupIntrinsics();
}
- void generateCode(const Program& program, ErrorReporter& errors, SkWStream& out) override;
+ bool generateCode() override;
private:
enum IntrinsicKind {
@@ -100,7 +103,7 @@
SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass);
- SpvId getPointerType(const Type& type, const MemoryLayout& layout,
+ SpvId getPointerType(const Type& type, const MemoryLayout& layout,
SpvStorageClass_ storageClass);
std::vector<SpvId> getAccessChain(const Expression& expr, SkWStream& out);
@@ -153,11 +156,11 @@
SpvId writeSwizzle(const Swizzle& swizzle, SkWStream& out);
- SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs,
- SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
+ SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs,
+ SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt,
SpvOp_ ifBool, SkWStream& out);
- SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
+ SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
SpvOp_ ifUInt, SkWStream& out);
SpvId writeBinaryExpression(const BinaryExpression& b, SkWStream& out);
@@ -215,7 +218,7 @@
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, SkWStream& out);
- void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
+ void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3,
SkWStream& out);
void writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2, int32_t word3, int32_t word4,
@@ -231,12 +234,11 @@
int32_t word5, int32_t word6, int32_t word7, SkWStream& 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,
+ int32_t word5, int32_t word6, int32_t word7, int32_t word8,
SkWStream& out);
const Context& fContext;
const MemoryLayout fDefaultLayout;
- ErrorReporter* fErrors;
uint64_t fCapabilities;
SpvId fIdCount;
@@ -250,6 +252,7 @@
SkDynamicMemoryWStream fCapabilitiesBuffer;
SkDynamicMemoryWStream fGlobalInitializersBuffer;
SkDynamicMemoryWStream fConstantBuffer;
+ SkDynamicMemoryWStream fExtraGlobalsBuffer;
SkDynamicMemoryWStream fExternalFunctionsBuffer;
SkDynamicMemoryWStream fVariableBuffer;
SkDynamicMemoryWStream fNameBuffer;
@@ -261,13 +264,18 @@
std::unordered_map<uint64_t, SpvId> fUIntConstants;
std::unordered_map<float, SpvId> fFloatConstants;
std::unordered_map<double, SpvId> fDoubleConstants;
+ bool fSetupFragPosition;
// label of the current block, or 0 if we are not in a block
SpvId fCurrentBlock;
std::stack<SpvId> fBreakTarget;
std::stack<SpvId> fContinueTarget;
+ SpvId fRTHeightStructId = (SpvId) -1;
+ SpvId fRTHeightFieldIndex = (SpvId) -1;
friend class PointerLValue;
friend class SwizzleLValue;
+
+ typedef CodeGenerator INHERITED;
};
}
diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h
index 95b2529..678241d 100644
--- a/src/sksl/SkSLUtil.h
+++ b/src/sksl/SkSLUtil.h
@@ -72,6 +72,21 @@
return result;
}
+ static sk_sp<GrShaderCaps> FragCoordsOld() {
+ sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
+ result->fVersionDeclString = "#version 110";
+ result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
+ result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
+ return result;
+ }
+
+ static sk_sp<GrShaderCaps> FragCoordsNew() {
+ sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
+ result->fVersionDeclString = "#version 400";
+ result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
+ return result;
+ }
+
static sk_sp<GrShaderCaps> VariousCaps() {
sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
result->fVersionDeclString = "#version 400";
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index 8393341..ac49d6d 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -4,42 +4,73 @@
* 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 "SkSLContext.h"
#include "SkSLModifiers.h"
#include "SkSLProgramElement.h"
#include "SkSLSymbolTable.h"
+// name of the render target height uniform
+#define SKSL_RTHEIGHT_NAME "u_skRTHeight"
+
namespace SkSL {
/**
* Represents a fully-digested program, ready for code generation.
*/
struct Program {
+ struct Settings {
+ const GrShaderCaps* fCaps = nullptr;
+ bool fFlipY = false;
+ };
+
+ struct Inputs {
+ // if true, this program requires the render target height uniform to be defined
+ bool fRTHeight;
+
+ void reset() {
+ fRTHeight = false;
+ }
+
+ bool isEmpty() {
+ return !fRTHeight;
+ }
+ };
+
enum Kind {
kFragment_Kind,
kVertex_Kind
};
- Program(Kind kind,
+ Program(Kind kind,
+ Settings settings,
Modifiers::Flag defaultPrecision,
- std::vector<std::unique_ptr<ProgramElement>> elements,
- std::shared_ptr<SymbolTable> symbols)
- : fKind(kind)
+ Context* context,
+ std::vector<std::unique_ptr<ProgramElement>> elements,
+ std::shared_ptr<SymbolTable> symbols,
+ Inputs inputs)
+ : fKind(kind)
+ , fSettings(settings)
, fDefaultPrecision(defaultPrecision)
+ , fContext(context)
, fElements(std::move(elements))
- , fSymbols(symbols) {}
+ , fSymbols(symbols)
+ , fInputs(inputs) {}
Kind fKind;
+ Settings fSettings;
// FIXME handle different types; currently it assumes this is for floats
Modifiers::Flag fDefaultPrecision;
+ Context* fContext;
std::vector<std::unique_ptr<ProgramElement>> fElements;
std::shared_ptr<SymbolTable> fSymbols;
+ Inputs fInputs;
};
} // namespace
diff --git a/src/sksl/sksl_frag.include b/src/sksl/sksl_frag.include
index 62f06e8..2184986 100644
--- a/src/sksl/sksl_frag.include
+++ b/src/sksl/sksl_frag.include
@@ -2,7 +2,7 @@
// defines built-in interfaces supported by SkiaSL fragment shaders
-layout(builtin=15) in vec4 gl_FragCoord;
+layout(builtin=15) in vec4 sk_FragCoord;
// 9999 is a temporary value that causes us to ignore these declarations beyond
// adding them to the symbol table. This works fine in GLSL (where they do not