diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni index 37abe97bd8..7694114d73 100644 --- a/gn/sksl_tests.gni +++ b/gn/sksl_tests.gni @@ -362,9 +362,7 @@ sksl_shared_tests = [ "/sksl/shared/Enum.sksl", "/sksl/shared/ForLoopControlFlow.sksl", "/sksl/shared/ForLoopMultipleInit.sksl", - "/sksl/shared/FragCoordsFlipY.sksl", - "/sksl/shared/FragCoordsNew.sksl", - "/sksl/shared/FragCoordsOld.sksl", + "/sksl/shared/FragCoords.sksl", "/sksl/shared/FunctionArgTypeMatch.sksl", "/sksl/shared/FunctionReturnTypeMatch.sksl", "/sksl/shared/FunctionPrototype.sksl", @@ -556,7 +554,6 @@ sksl_settings_tests = [ "/sksl/inliner/ExponentialGrowth.sksl", "/sksl/inliner/InlinerCanBeDisabled.sksl", "/sksl/shared/Derivatives.sksl", - "/sksl/shared/DerivativesFlipY.sksl", "/sksl/workarounds/AbsInt.sksl", "/sksl/workarounds/BlendGuardedDivide.sksl", "/sksl/workarounds/BlendModesAllZeroVec.sksl", diff --git a/include/sksl/DSLVar.h b/include/sksl/DSLVar.h index e7aa38d880..f23d4bcfa3 100644 --- a/include/sksl/DSLVar.h +++ b/include/sksl/DSLVar.h @@ -15,6 +15,7 @@ namespace SkSL { class IRGenerator; +class SPIRVCodeGenerator; class Variable; enum class VariableStorage : int8_t; @@ -165,6 +166,7 @@ private: friend class DSLFunction; friend class DSLWriter; friend class ::SkSL::IRGenerator; + friend class ::SkSL::SPIRVCodeGenerator; }; } // namespace dsl diff --git a/resources/sksl/shared/DerivativesFlipY.sksl b/resources/sksl/shared/DerivativesFlipY.sksl deleted file mode 100644 index 38c0e319e0..0000000000 --- a/resources/sksl/shared/DerivativesFlipY.sksl +++ /dev/null @@ -1,6 +0,0 @@ -/*#pragma settings FlipY*/ - -void main() { - sk_FragColor.r = half(dFdx(1)), - sk_FragColor.g = half(dFdy(1)); -} diff --git a/resources/sksl/shared/FragCoordsFlipY.sksl b/resources/sksl/shared/FragCoords.sksl similarity index 61% rename from resources/sksl/shared/FragCoordsFlipY.sksl rename to resources/sksl/shared/FragCoords.sksl index 24ab6daeb1..96bf1cf26d 100644 --- a/resources/sksl/shared/FragCoordsFlipY.sksl +++ b/resources/sksl/shared/FragCoords.sksl @@ -1,3 +1 @@ -/*#pragma settings Default FlipY*/ - void main() { sk_FragColor.xy = half2(sk_FragCoord.xy); } diff --git a/resources/sksl/shared/FragCoordsNew.sksl b/resources/sksl/shared/FragCoordsNew.sksl deleted file mode 100644 index fe091550cb..0000000000 --- a/resources/sksl/shared/FragCoordsNew.sksl +++ /dev/null @@ -1,3 +0,0 @@ -/*#pragma settings FragCoordsNew FlipY*/ - -void main() { sk_FragColor.xy = half2(sk_FragCoord.xy); } diff --git a/resources/sksl/shared/FragCoordsOld.sksl b/resources/sksl/shared/FragCoordsOld.sksl deleted file mode 100644 index 3793f1114d..0000000000 --- a/resources/sksl/shared/FragCoordsOld.sksl +++ /dev/null @@ -1,3 +0,0 @@ -/*#pragma settings FragCoordsOld FlipY*/ - -void main() { sk_FragColor.xy = half2(sk_FragCoord.xy); } diff --git a/src/gpu/GrPersistentCacheUtils.cpp b/src/gpu/GrPersistentCacheUtils.cpp index 19569b6d49..71443e66cd 100644 --- a/src/gpu/GrPersistentCacheUtils.cpp +++ b/src/gpu/GrPersistentCacheUtils.cpp @@ -13,14 +13,14 @@ namespace GrPersistentCacheUtils { -static constexpr int kCurrentVersion = 6; +static constexpr int kCurrentVersion = 7; int GetCurrentVersion() { // The persistent cache stores a copy of the SkSL::Program::Inputs struct. If you alter the // Program::Inputs struct in any way, you must increment kCurrentVersion to invalidate the // outdated persistent cache files. The KnownSkSLProgramInputs struct must also be updated to // match the new contents of Program::Inputs. - struct KnownSkSLProgramInputs { bool height, flipY, usesYDeriv; }; + struct KnownSkSLProgramInputs { bool useRTFlipUniform; }; static_assert(sizeof(SkSL::Program::Inputs) == sizeof(KnownSkSLProgramInputs)); return kCurrentVersion; @@ -46,7 +46,6 @@ sk_sp PackCachedShaders(SkFourByteTag shaderType, if (meta) { writer.writeBool(SkToBool(meta->fSettings)); if (meta->fSettings) { - writer.writeBool(meta->fSettings->fFlipY); writer.writeBool(meta->fSettings->fFragColorIsInOut); writer.writeBool(meta->fSettings->fForceHighPrecision); writer.writeBool(meta->fSettings->fUsePushConstants); @@ -97,7 +96,6 @@ bool UnpackCachedShaders(SkReadBuffer* reader, SkASSERT(meta->fSettings != nullptr); if (reader->readBool()) { - meta->fSettings->fFlipY = reader->readBool(); meta->fSettings->fFragColorIsInOut = reader->readBool(); meta->fSettings->fForceHighPrecision = reader->readBool(); meta->fSettings->fUsePushConstants = reader->readBool(); diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp index 3da48a18e3..528fe63384 100644 --- a/src/gpu/GrProgramDesc.cpp +++ b/src/gpu/GrProgramDesc.cpp @@ -154,9 +154,6 @@ static void gen_key(GrProcessorKeyBuilder* b, gen_xp_key(pipeline.getXferProcessor(), caps, pipeline, b); b->addBits(16, pipeline.writeSwizzle().asKey(), "writeSwizzle"); - // If we knew the shader won't depend on origin, we could skip this (and use the same program - // for both origins). Instrumenting all fragment processors would be difficult and error prone. - b->addBits(2, GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(programInfo.origin()), "origin"); b->addBits(1, static_cast(programInfo.requestedFeatures()), "requestedFeatures"); b->addBool(pipeline.snapVerticesToPixelCenters(), "snapVertices"); // The base descriptor only stores whether or not the primitiveType is kPoints. Backend- diff --git a/src/gpu/GrSPIRVUniformHandler.cpp b/src/gpu/GrSPIRVUniformHandler.cpp index 50e1c2e670..f073496c71 100644 --- a/src/gpu/GrSPIRVUniformHandler.cpp +++ b/src/gpu/GrSPIRVUniformHandler.cpp @@ -318,7 +318,7 @@ void GrSPIRVUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkStrin } } -uint32_t GrSPIRVUniformHandler::getRTHeightOffset() const { +uint32_t GrSPIRVUniformHandler::getRTFlipOffset() const { uint32_t currentOffset = fCurrentUBOOffset; - return get_ubo_offset(¤tOffset, kFloat_GrSLType, 0); + return get_ubo_offset(¤tOffset, kFloat2_GrSLType, 0); } diff --git a/src/gpu/GrSPIRVUniformHandler.h b/src/gpu/GrSPIRVUniformHandler.h index 4a41b0a78c..7ba8468f40 100644 --- a/src/gpu/GrSPIRVUniformHandler.h +++ b/src/gpu/GrSPIRVUniformHandler.h @@ -33,7 +33,7 @@ public: kUniformDescriptorSet = 0, kSamplerTextureDescriptorSet = 1, }; - uint32_t getRTHeightOffset() const; + uint32_t getRTFlipOffset() const; int numUniforms() const override { return fUniforms.count(); @@ -69,7 +69,7 @@ private: SkTArray fSamplerReferences; uint32_t fCurrentUBOOffset = 0; - uint32_t fRTHeightOffset = 0; + uint32_t fRTFlipOffset = 0; friend class GrD3DPipelineStateBuilder; friend class GrDawnProgramBuilder; diff --git a/src/gpu/d3d/GrD3DPipelineState.cpp b/src/gpu/d3d/GrD3DPipelineState.cpp index 515884aec4..49f4990fb6 100644 --- a/src/gpu/d3d/GrD3DPipelineState.cpp +++ b/src/gpu/d3d/GrD3DPipelineState.cpp @@ -65,13 +65,7 @@ void GrD3DPipelineState::setAndBindConstants(GrD3DGpu* gpu, } void GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) { - // Load the RT height uniform if it is needed to y-flip gl_FragCoord. - if (fBuiltinUniformHandles.fRTHeightUni.isValid() && - fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) { - fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height())); - } - - // set RT adjustment + // Set RT adjustment and RT flip SkISize dimensions = rt->dimensions(); SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); if (fRenderTargetState.fRenderTargetOrigin != origin || @@ -85,6 +79,11 @@ void GrD3DPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfac bool flip = (origin == kTopLeft_GrSurfaceOrigin); std::array v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip); fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data()); + if (fBuiltinUniformHandles.fRTFlipUni.isValid()) { + // Note above that framebuffer space has origin top left. So we need !flip here. + std::array d = SkSL::Compiler::GetRTFlipVector(rt->height(), !flip); + fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data()); + } } } diff --git a/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp b/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp index 2c1c220b4f..f971665fe4 100644 --- a/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp +++ b/src/gpu/d3d/GrD3DPipelineStateBuilder.cpp @@ -125,8 +125,8 @@ bool GrD3DPipelineStateBuilder::loadHLSLFromCache(SkReadBuffer* reader, gr_cpaddRTHeightUniform(SKSL_RTHEIGHT_NAME); + if (inputs[shaderType].fUseFlipRTUniform) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } shaders[shaderType] = GrCompileHLSLShader(fGpu, hlsl[shaderType], kind); return shaders[shaderType].get(); @@ -172,8 +172,8 @@ gr_cp GrD3DPipelineStateBuilder::compileD3DProgram( } } - if (program->fInputs.fRTHeight) { - this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + if (program->fInputs.fUseFlipRTUniform) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } return GrCompileHLSLShader(fGpu, *outHLSL, kind); @@ -578,12 +578,11 @@ std::unique_ptr GrD3DPipelineStateBuilder::finalize() { this->finalizeShaders(); SkSL::Program::Settings settings; - settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin; settings.fSharpenTextures = this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures; - settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset(); - settings.fRTHeightBinding = 0; - settings.fRTHeightSet = 0; + settings.fRTFlipOffset = fUniformHandler.getRTFlipOffset(); + settings.fRTFlipBinding = 0; + settings.fRTFlipSet = 0; sk_sp cached; SkReadBuffer reader; diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp index 7e9bf25f8d..f371930880 100644 --- a/src/gpu/dawn/GrDawnGpu.cpp +++ b/src/gpu/dawn/GrDawnGpu.cpp @@ -706,8 +706,10 @@ bool GrDawnGpu::onRegenerateMipMapLevels(GrTexture* tex) { " sk_Position = float4(positions[sk_VertexID], 0.0, 1.0);\n" " texCoord = texCoords[sk_VertexID];\n" "}\n"; - SkSL::String vsSPIRV = - this->SkSLToSPIRV(vs, SkSL::ProgramKind::kVertex, false, 0, nullptr); + SkSL::String vsSPIRV = this->SkSLToSPIRV(vs, + SkSL::ProgramKind::kVertex, + /*rtFlipOffset*/ 0, + nullptr); const char* fs = "layout(set = 0, binding = 0) uniform sampler samp;\n" @@ -716,8 +718,10 @@ bool GrDawnGpu::onRegenerateMipMapLevels(GrTexture* tex) { "void main() {\n" " sk_FragColor = sample(makeSampler2D(tex, samp), texCoord);\n" "}\n"; - SkSL::String fsSPIRV = - this->SkSLToSPIRV(fs, SkSL::ProgramKind::kFragment, false, 0, nullptr); + SkSL::String fsSPIRV = this->SkSLToSPIRV(fs, + SkSL::ProgramKind::kFragment, + /*rtFlipOffset=*/ 0, + nullptr); wgpu::VertexState vertexState; vertexState.module = this->createShaderModule(vsSPIRV); @@ -923,14 +927,15 @@ void GrDawnGpu::moveStagingBuffersToBusyAndMapAsync() { fSubmittedStagingBuffers.clear(); } -SkSL::String GrDawnGpu::SkSLToSPIRV(const char* shaderString, SkSL::ProgramKind kind, bool flipY, - uint32_t rtHeightOffset, SkSL::Program::Inputs* inputs) { +SkSL::String GrDawnGpu::SkSLToSPIRV(const char* shaderString, + SkSL::ProgramKind kind, + uint32_t rtFlipOffset, + SkSL::Program::Inputs* inputs) { auto errorHandler = this->getContext()->priv().getShaderErrorHandler(); SkSL::Program::Settings settings; - settings.fFlipY = flipY; - settings.fRTHeightOffset = rtHeightOffset; - settings.fRTHeightBinding = 0; - settings.fRTHeightSet = 0; + settings.fRTFlipOffset = rtFlipOffset; + settings.fRTFlipBinding = 0; + settings.fRTFlipSet = 0; std::unique_ptr program = this->shaderCompiler()->convertProgram( kind, shaderString, diff --git a/src/gpu/dawn/GrDawnGpu.h b/src/gpu/dawn/GrDawnGpu.h index df3a8fadf8..c79f5bd06d 100644 --- a/src/gpu/dawn/GrDawnGpu.h +++ b/src/gpu/dawn/GrDawnGpu.h @@ -100,8 +100,10 @@ public: void appendCommandBuffer(wgpu::CommandBuffer commandBuffer); void waitOnAllBusyStagingBuffers(); - SkSL::String SkSLToSPIRV(const char* shaderString, SkSL::ProgramKind, bool flipY, - uint32_t rtHeightOffset, SkSL::Program::Inputs*); + SkSL::String SkSLToSPIRV(const char* shaderString, + SkSL::ProgramKind, + uint32_t rtFlipOffset, + SkSL::Program::Inputs*); wgpu::ShaderModule createShaderModule(const SkSL::String& spirvSource); private: diff --git a/src/gpu/dawn/GrDawnProgramBuilder.cpp b/src/gpu/dawn/GrDawnProgramBuilder.cpp index dbf68161c7..62f92365fb 100644 --- a/src/gpu/dawn/GrDawnProgramBuilder.cpp +++ b/src/gpu/dawn/GrDawnProgramBuilder.cpp @@ -439,10 +439,12 @@ wgpu::ShaderModule GrDawnProgramBuilder::createShaderModule(const GrGLSLShaderBu printf("converting program:\n%s\n", sksl.c_str()); #endif - SkSL::String spirvSource = fGpu->SkSLToSPIRV(source.c_str(), kind, flipY, - fUniformHandler.getRTHeightOffset(), inputs); - if (inputs->fRTHeight) { - this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + SkSL::String spirvSource = fGpu->SkSLToSPIRV(source.c_str(), + kind, + fUniformHandler.getRTFlipOffset(), + inputs); + if (inputs->fUseFlipRTUniform) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } return fGpu->createShaderModule(spirvSource); @@ -457,13 +459,7 @@ SkSL::Compiler* GrDawnProgramBuilder::shaderCompiler() const { } void GrDawnProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) { - // Load the RT height uniform if it is needed to y-flip gl_FragCoord. - if (fBuiltinUniformHandles.fRTHeightUni.isValid() && - fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) { - fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height())); - } - - // set RT adjustment + // Set RT adjustment and RT flip SkISize dimensions = rt->dimensions(); SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); if (fRenderTargetState.fRenderTargetOrigin != origin || @@ -477,6 +473,11 @@ void GrDawnProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrig bool flip = (origin == kTopLeft_GrSurfaceOrigin); std::array v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip); fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data()); + if (fBuiltinUniformHandles.fRTFlipUni.isValid()) { + // Note above that framebuffer space has origin top left. So we need !flip here. + std::array d = SkSL::Compiler::GetRTFlipVector(rt->height(), !flip); + fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data()); + } } } diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index a9152aa4b3..559517c87a 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -3147,7 +3147,7 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) { GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram, GR_GL_VERTEX_SHADER, glsl, fProgramCache->stats(), errorHandler); - SkASSERT(program->fInputs.isEmpty()); + SkASSERT(program->fInputs == SkSL::Program::Inputs()); sksl.assign(fshaderTxt.c_str(), fshaderTxt.size()); program = GrSkSLtoGLSL(this, SkSL::ProgramKind::kFragment, sksl, settings, &glsl, @@ -3155,7 +3155,7 @@ bool GrGLGpu::createCopyProgram(GrTexture* srcTex) { GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[progIdx].fProgram, GR_GL_FRAGMENT_SHADER, glsl, fProgramCache->stats(), errorHandler); - SkASSERT(program->fInputs.isEmpty()); + SkASSERT(program->fInputs == SkSL::Program::Inputs()); GL_CALL(LinkProgram(fCopyPrograms[progIdx].fProgram)); @@ -3301,7 +3301,7 @@ bool GrGLGpu::createMipmapProgram(int progIdx) { GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram, GR_GL_VERTEX_SHADER, glsl, fProgramCache->stats(), errorHandler); - SkASSERT(program->fInputs.isEmpty()); + SkASSERT(program->fInputs == SkSL::Program::Inputs()); sksl.assign(fshaderTxt.c_str(), fshaderTxt.size()); program = GrSkSLtoGLSL(this, SkSL::ProgramKind::kFragment, sksl, settings, &glsl, @@ -3309,7 +3309,7 @@ bool GrGLGpu::createMipmapProgram(int progIdx) { GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fMipmapPrograms[progIdx].fProgram, GR_GL_FRAGMENT_SHADER, glsl, fProgramCache->stats(), errorHandler); - SkASSERT(program->fInputs.isEmpty()); + SkASSERT(program->fInputs == SkSL::Program::Inputs()); GL_CALL(LinkProgram(fMipmapPrograms[progIdx].fProgram)); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 425be17adc..d725a6b816 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -154,13 +154,7 @@ void GrGLProgram::bindTextures(const GrGeometryProcessor& geomProc, void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin, const GrGeometryProcessor& geomProc) { - // Load the RT height uniform if it is needed - if (fBuiltinUniformHandles.fRTHeightUni.isValid() && - fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) { - fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height())); - } - - // set RT adjustment + // Set RT adjustment and RT flip SkISize dimensions = rt->dimensions(); if (fRenderTargetState.fRenderTargetOrigin != origin || fRenderTargetState.fRenderTargetSize != dimensions) { @@ -174,5 +168,9 @@ void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt, bool flip = (origin == kBottomLeft_GrSurfaceOrigin); std::array v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip); fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data()); + if (fBuiltinUniformHandles.fRTFlipUni.isValid()) { + std::array d = SkSL::Compiler::GetRTFlipVector(dimensions.height(), flip); + fProgramDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data()); + } } } diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 210faaa234..5c628a358c 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -147,8 +147,8 @@ void GrGLProgramBuilder::computeCountsAndStrides(GrGLuint programID, } void GrGLProgramBuilder::addInputVars(const SkSL::Program::Inputs& inputs) { - if (inputs.fRTHeight) { - this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + if (inputs.fUseFlipRTUniform) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } } @@ -232,7 +232,6 @@ sk_sp GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr auto errorHandler = this->gpu()->getContext()->priv().getShaderErrorHandler(); const GrGeometryProcessor& geomProc = this->geometryProcessor(); SkSL::Program::Settings settings; - settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin; settings.fSharpenTextures = this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures; settings.fFragColorIsInOut = this->fragColorIsInOut(); diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp index 4017c814a9..0f284d47e5 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp @@ -13,14 +13,6 @@ #include "src/gpu/glsl/GrGLSLUniformHandler.h" #include "src/gpu/glsl/GrGLSLVarying.h" -uint8_t GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(GrSurfaceOrigin origin) { - SkASSERT(kTopLeft_GrSurfaceOrigin == origin || kBottomLeft_GrSurfaceOrigin == origin); - return origin + 1; - - static_assert(0 == kTopLeft_GrSurfaceOrigin); - static_assert(1 == kBottomLeft_GrSurfaceOrigin); -} - GrGLSLFragmentShaderBuilder::GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program) : GrGLSLShaderBuilder(program) { fSubstageIndices.push_back(0); diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h index 50fdeeb89c..f8cc417c60 100644 --- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h @@ -92,10 +92,6 @@ public: */ class GrGLSLFragmentShaderBuilder : public GrGLSLFPFragmentBuilder, public GrGLSLXPFragmentBuilder { public: - /** Returns a nonzero key for a surface's origin. This should only be called if a processor will - use the fragment position and/or sample locations. */ - static uint8_t KeyForSurfaceOrigin(GrSurfaceOrigin); - GrGLSLFragmentShaderBuilder(GrGLSLProgramBuilder* program); // Shared FP/XP interface. diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp index 348d1930f4..9f295ec42a 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp +++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp @@ -382,12 +382,17 @@ void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString this->uniformHandler()->appendUniformDecls(visibility, out); } -void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) { - SkASSERT(!fUniformHandles.fRTHeightUni.isValid()); +void GrGLSLProgramBuilder::addRTFlipUniform(const char* name) { + SkASSERT(!fUniformHandles.fRTFlipUni.isValid()); GrGLSLUniformHandler* uniformHandler = this->uniformHandler(); - fUniformHandles.fRTHeightUni = - uniformHandler->internalAddUniformArray(nullptr, kFragment_GrShaderFlag, kHalf_GrSLType, - name, false, 0, nullptr); + fUniformHandles.fRTFlipUni = + uniformHandler->internalAddUniformArray(nullptr, + kFragment_GrShaderFlag, + kHalf2_GrSLType, + name, + false, + 0, + nullptr); } void GrGLSLProgramBuilder::finalizeShaders() { diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h index 00cd1dc8d5..7ddb3fca47 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.h +++ b/src/gpu/glsl/GrGLSLProgramBuilder.h @@ -71,9 +71,9 @@ public: return this->uniformHandler()->inputSamplerSwizzle(handle); } - // Used to add a uniform for the RenderTarget height (used for u_skRTHeight and frag position) + // Used to add a uniform for render target flip (used for dFdy, sk_Clockwise, and sk_FragCoord) // without mangling the name of the uniform inside of a stage. - void addRTHeightUniform(const char* name); + void addRTFlipUniform(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/glsl/GrGLSLUniformHandler.h b/src/gpu/glsl/GrGLSLUniformHandler.h index 115511941f..af0a9304ef 100644 --- a/src/gpu/glsl/GrGLSLUniformHandler.h +++ b/src/gpu/glsl/GrGLSLUniformHandler.h @@ -23,9 +23,8 @@ class GrSurfaceProxy; // Handles for program uniforms (other than per-effect uniforms) struct GrGLSLBuiltinUniformHandles { GrGLSLProgramDataManager::UniformHandle fRTAdjustmentUni; - // Render target height, used to implement u_skRTHeight and to calculate sk_FragCoord when - // origin_upper_left is not supported. - GrGLSLProgramDataManager::UniformHandle fRTHeightUni; + // Render target flip uniform (used for dFdy, sk_Clockwise, and sk_FragCoord) + GrGLSLProgramDataManager::UniformHandle fRTFlipUni; // Destination texture origin and scale, used when dest-texture readback is enabled. GrGLSLProgramDataManager::UniformHandle fDstTextureCoordsUni; }; diff --git a/src/gpu/mtl/GrMtlPipelineState.mm b/src/gpu/mtl/GrMtlPipelineState.mm index eebe018548..df7128c9ac 100644 --- a/src/gpu/mtl/GrMtlPipelineState.mm +++ b/src/gpu/mtl/GrMtlPipelineState.mm @@ -128,13 +128,7 @@ void GrMtlPipelineState::bindTextures(GrMtlRenderCommandEncoder* renderCmdEncode } void GrMtlPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) { - // Load the RT height uniform if it is needed to y-flip gl_FragCoord. - if (fBuiltinUniformHandles.fRTHeightUni.isValid() && - fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) { - fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height())); - } - - // set RT adjustment + // Set RT adjustment and RT flip SkISize dimensions = rt->dimensions(); SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); if (fRenderTargetState.fRenderTargetOrigin != origin || @@ -148,6 +142,11 @@ void GrMtlPipelineState::setRenderTargetState(const GrRenderTarget* rt, GrSurfac bool flip = (origin == kTopLeft_GrSurfaceOrigin); std::array v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip); fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data()); + if (fBuiltinUniformHandles.fRTFlipUni.isValid()) { + // Note above that framebuffer space has origin top left. So we need !flip here. + std::array d = SkSL::Compiler::GetRTFlipVector(rt->height(), !flip); + fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data()); + } } } diff --git a/src/gpu/mtl/GrMtlPipelineStateBuilder.h b/src/gpu/mtl/GrMtlPipelineStateBuilder.h index 27c0f9e32f..b5e0453611 100644 --- a/src/gpu/mtl/GrMtlPipelineStateBuilder.h +++ b/src/gpu/mtl/GrMtlPipelineStateBuilder.h @@ -27,7 +27,7 @@ struct GrMtlPrecompiledLibraries { // TODO: wrap these in sk_cfp<> or unique_ptr<> when we remove ARC id fVertexLibrary; id fFragmentLibrary; - bool fRTHeight = false; + bool fRTFlip = false; }; class GrMtlPipelineStateBuilder : public GrGLSLProgramBuilder { diff --git a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm index 3949d4166b..f7aea42822 100644 --- a/src/gpu/mtl/GrMtlPipelineStateBuilder.mm +++ b/src/gpu/mtl/GrMtlPipelineStateBuilder.mm @@ -91,8 +91,8 @@ id GrMtlPipelineStateBuilder::compileMtlShaderLibrary( const SkSL::String& shader, SkSL::Program::Inputs inputs, GrContextOptions::ShaderErrorHandler* errorHandler) { id shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shader, errorHandler); - if (shaderLibrary != nil && inputs.fRTHeight) { - this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + if (shaderLibrary != nil && inputs.fUseFlipRTUniform) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } return shaderLibrary; } @@ -524,8 +524,8 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize( [precompiledLibs->fFragmentLibrary newFunctionWithName: @"fragmentMain"]; SkASSERT(pipelineDescriptor.vertexFunction); SkASSERT(pipelineDescriptor.fragmentFunction); - if (precompiledLibs->fRTHeight) { - this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + if (precompiledLibs->fRTFlip) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } } else { id shaderLibraries[kGrShaderTypeCount]; @@ -538,7 +538,6 @@ GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize( this->finalizeShaders(); SkSL::Program::Settings settings; - settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin; settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures; SkASSERT(!this->fragColorIsInOut()); @@ -832,7 +831,7 @@ bool GrMtlPipelineStateBuilder::PrecompileShaders(GrMtlGpu* gpu, const SkData& c completionHandler: completionHandler]; } - precompiledLibs->fRTHeight = inputs[kFragment_GrShaderType].fRTHeight; + precompiledLibs->fRTFlip = inputs[kFragment_GrShaderType].fUseFlipRTUniform; return true; } diff --git a/src/gpu/vk/GrVkMSAALoadManager.cpp b/src/gpu/vk/GrVkMSAALoadManager.cpp index 6f3d773b60..f0268d831f 100644 --- a/src/gpu/vk/GrVkMSAALoadManager.cpp +++ b/src/gpu/vk/GrVkMSAALoadManager.cpp @@ -68,7 +68,7 @@ bool GrVkMSAALoadManager::createMSAALoadProgram(GrVkGpu* gpu) { this->destroyResources(gpu); return false; } - SkASSERT(inputs.isEmpty()); + SkASSERT(inputs == SkSL::Program::Inputs()); if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, &fFragShaderModule, &fShaderStageInfo[1], settings, &spirv, @@ -76,7 +76,7 @@ bool GrVkMSAALoadManager::createMSAALoadProgram(GrVkGpu* gpu) { this->destroyResources(gpu); return false; } - SkASSERT(inputs.isEmpty()); + SkASSERT(inputs == SkSL::Program::Inputs()); VkDescriptorSetLayout dsLayout[GrVkUniformHandler::kDescSetCount]; diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp index 9d76026250..208cf94d1a 100644 --- a/src/gpu/vk/GrVkPipelineState.cpp +++ b/src/gpu/vk/GrVkPipelineState.cpp @@ -246,15 +246,7 @@ bool GrVkPipelineState::setAndBindInputAttachment(GrVkGpu* gpu, void GrVkPipelineState::setRenderTargetState(SkISize colorAttachmentDimensions, GrSurfaceOrigin origin) { - - // Load the RT height uniform if it is needed to y-flip gl_FragCoord. - if (fBuiltinUniformHandles.fRTHeightUni.isValid() && - fRenderTargetState.fRenderTargetSize.fHeight != colorAttachmentDimensions.height()) { - fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, - SkIntToScalar(colorAttachmentDimensions.height())); - } - - // set RT adjustment + // Set RT adjustment and RT flip SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); if (fRenderTargetState.fRenderTargetOrigin != origin || fRenderTargetState.fRenderTargetSize != colorAttachmentDimensions) { @@ -268,6 +260,11 @@ void GrVkPipelineState::setRenderTargetState(SkISize colorAttachmentDimensions, bool flip = (origin == kBottomLeft_GrSurfaceOrigin); std::array v = SkSL::Compiler::GetRTAdjustVector(colorAttachmentDimensions, flip); fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data()); + if (fBuiltinUniformHandles.fRTFlipUni.isValid()) { + std::array d = + SkSL::Compiler::GetRTFlipVector(colorAttachmentDimensions.height(), flip); + fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data()); + } } } diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp index adc609d188..fbabc4d219 100644 --- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp +++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp @@ -82,8 +82,8 @@ bool GrVkPipelineStateBuilder::createVkShaderModule(VkShaderStageFlagBits stage, stageInfo, settings, outSPIRV, outInputs)) { return false; } - if (outInputs->fRTHeight) { - this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + if (outInputs->fUseFlipRTUniform) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } return true; } @@ -97,8 +97,8 @@ bool GrVkPipelineStateBuilder::installVkShaderModule(VkShaderStageFlagBits stage if (!GrInstallVkShaderModule(fGpu, spirv, stage, shaderModule, stageInfo)) { return false; } - if (inputs.fRTHeight) { - this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); + if (inputs.fUseFlipRTUniform) { + this->addRTFlipUniform(SKSL_RTFLIP_NAME); } return true; } @@ -204,12 +204,11 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrProgramDesc& desc, bool usePushConstants = fUniformHandler.usePushConstants(); VkPipelineShaderStageCreateInfo shaderStageInfo[3]; SkSL::Program::Settings settings; - settings.fRTHeightBinding = this->gpu()->vkCaps().getFragmentUniformBinding(); - settings.fRTHeightSet = this->gpu()->vkCaps().getFragmentUniformSet(); - settings.fFlipY = fUniformHandler.getFlipY(); + settings.fRTFlipBinding = this->gpu()->vkCaps().getFragmentUniformBinding(); + settings.fRTFlipSet = this->gpu()->vkCaps().getFragmentUniformSet(); settings.fSharpenTextures = this->gpu()->getContext()->priv().options().fSharpenMipmappedTextures; - settings.fRTHeightOffset = fUniformHandler.getRTHeightOffset(); + settings.fRTFlipOffset = fUniformHandler.getRTFlipOffset(); settings.fUsePushConstants = usePushConstants; if (fFS.fForceHighPrecision) { settings.fForceHighPrecision = true; diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp index 195be3a1aa..a0a5fd4978 100644 --- a/src/gpu/vk/GrVkUniformHandler.cpp +++ b/src/gpu/vk/GrVkUniformHandler.cpp @@ -382,17 +382,18 @@ void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* } } -uint32_t GrVkUniformHandler::getRTHeightOffset() const { +uint32_t GrVkUniformHandler::getRTFlipOffset() const { Layout layout = fUsePushConstants ? kStd430Layout : kStd140Layout; uint32_t currentOffset = fCurrentOffsets[layout]; - return get_aligned_offset(¤tOffset, kFloat_GrSLType, 0, layout); + return get_aligned_offset(¤tOffset, kFloat2_GrSLType, 0, layout); } void GrVkUniformHandler::determineIfUsePushConstants() const { - // If flipY is enabled we may be adding the RTHeight uniform during compilation. + // We may insert a uniform for flipping origin-sensitive language features (e.g. sk_FragCoord). // We won't know that for sure until then but we need to make this determination now, // so assume we will need it. - uint32_t pad = fFlipY ? sizeof(float) : 0; - fUsePushConstants = fCurrentOffsets[kStd430Layout] > 0 && - fCurrentOffsets[kStd430Layout] + pad <= fProgramBuilder->caps()->maxPushConstantsSize(); + static constexpr uint32_t kPad = 2*sizeof(float); + fUsePushConstants = + fCurrentOffsets[kStd430Layout] > 0 && + fCurrentOffsets[kStd430Layout] + kPad <= fProgramBuilder->caps()->maxPushConstantsSize(); } diff --git a/src/gpu/vk/GrVkUniformHandler.h b/src/gpu/vk/GrVkUniformHandler.h index 0a4151c36b..738db57654 100644 --- a/src/gpu/vk/GrVkUniformHandler.h +++ b/src/gpu/vk/GrVkUniformHandler.h @@ -73,9 +73,9 @@ public: } /** - * Returns the offset that the RTHeight synthetic uniform should use if it needs to be created. + * Returns the offset that the RTFlip synthetic uniform should use if it needs to be created. */ - uint32_t getRTHeightOffset() const; + uint32_t getRTFlipOffset() const; int numUniforms() const override { return fUniforms.count(); @@ -88,8 +88,6 @@ public: return fUniforms.item(idx); } - bool getFlipY() const { return fFlipY; } - bool usePushConstants() const { return fUsePushConstants; } uint32_t currentOffset() const { return fUsePushConstants ? fCurrentOffsets[kStd430Layout] : fCurrentOffsets[kStd140Layout]; @@ -100,7 +98,6 @@ private: : INHERITED(program) , fUniforms(kUniformsPerBlock) , fSamplers(kUniformsPerBlock) - , fFlipY(program->origin() != kTopLeft_GrSurfaceOrigin) , fUsePushConstants(false) , fCurrentOffsets{0, 0} { } @@ -161,7 +158,6 @@ private: SkTArray fSamplerSwizzles; UniformInfo fInputUniform; GrSwizzle fInputSwizzle; - bool fFlipY; mutable bool fUsePushConstants; uint32_t fCurrentOffsets[kLayoutCount]; diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index b8533cceb2..72d60d2e67 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -895,6 +895,10 @@ bool Compiler::optimize(Program& program) { bool Compiler::toSPIRV(Program& program, OutputStream& out) { TRACE_EVENT0("skia.shaders", "SkSL::Compiler::toSPIRV"); AutoSource as(this, program.fSource.get()); + ProgramSettings settings; + settings.fDSLUseMemoryPool = false; + dsl::Start(this, program.fConfig->fKind, settings); + dsl::DSLWriter::IRGenerator().fSymbolTable = program.fSymbols; #ifdef SK_ENABLE_SPIRV_VALIDATION StringStream buffer; SPIRVCodeGenerator cg(fContext.get(), &program, this, &buffer); @@ -933,6 +937,7 @@ bool Compiler::toSPIRV(Program& program, OutputStream& out) { SPIRVCodeGenerator cg(fContext.get(), &program, this, &out); bool result = cg.generateCode(); #endif + dsl::End(); return result; } diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index ec21906aed..20432c18f9 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -94,6 +94,17 @@ public: return result; } + /** + * Uniform values by the compiler to implement origin-neutral dFdy, sk_Clockwise, and + * sk_FragCoord. + */ + static std::array GetRTFlipVector(int rtHeight, bool flipY) { + std::array result; + result[0] = flipY ? rtHeight : 0.f; + result[1] = flipY ? -1.f : 1.f; + return result; + } + struct OptimizationContext { // nodes we have already reported errors for and should not error on again std::unordered_set fSilences; diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 381eb7a740..3f3eb892c0 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -1268,14 +1268,14 @@ std::unique_ptr IRGenerator::convertIdentifier(int offset, skstd::st const Variable* var = &result->as(); const Modifiers& modifiers = var->modifiers(); switch (modifiers.fLayout.fBuiltin) { -#ifndef SKSL_STANDALONE case SK_FRAGCOORD_BUILTIN: - fInputs.fFlipY = true; - if (this->settings().fFlipY && - !this->caps().fragCoordConventionsExtensionString()) { - fInputs.fRTHeight = true; + if (caps().canUseFragCoord()) { + fInputs.fUseFlipRTUniform = true; } -#endif + break; + case SK_CLOCKWISE_BUILTIN: + fInputs.fUseFlipRTUniform = true; + break; } if (this->programKind() == ProgramKind::kFragmentProcessor && (modifiers.fFlags & Modifiers::kIn_Flag) && @@ -1411,7 +1411,7 @@ std::unique_ptr IRGenerator::call(int offset, ExpressionArray arguments) { if (function.isBuiltin()) { if (function.intrinsicKind() == k_dFdy_IntrinsicKind) { - fInputs.fUsesYDerivative = true; + fInputs.fUseFlipRTUniform = true; } if (function.definition()) { fReferencedIntrinsics.insert(&function); @@ -1841,7 +1841,7 @@ void IRGenerator::start(const ParsedModule& base, } fIsBuiltinCode = isBuiltinCode; - fInputs.reset(); + fInputs = {}; fInvocations = -1; fRTAdjust = nullptr; fRTAdjustInterfaceBlock = nullptr; diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp index 258ac17017..d5919bc3dd 100644 --- a/src/sksl/SkSLMain.cpp +++ b/src/sksl/SkSLMain.cpp @@ -140,14 +140,6 @@ static bool detect_shader_settings(const SkSL::String& text, static auto s_emulateAbsIntCaps = Factory::EmulateAbsIntFunction(); *caps = s_emulateAbsIntCaps.get(); } - if (settingsText.consumeSuffix(" FragCoordsOld")) { - static auto s_fragCoordsOld = Factory::FragCoordsOld(); - *caps = s_fragCoordsOld.get(); - } - if (settingsText.consumeSuffix(" FragCoordsNew")) { - static auto s_fragCoordsNew = Factory::FragCoordsNew(); - *caps = s_fragCoordsNew.get(); - } if (settingsText.consumeSuffix(" GeometryShaderExtensionString")) { static auto s_geometryExtCaps = Factory::GeometryShaderExtensionString(); *caps = s_geometryExtCaps.get(); @@ -217,9 +209,6 @@ static bool detect_shader_settings(const SkSL::String& text, static auto s_version450CoreCaps = Factory::Version450Core(); *caps = s_version450CoreCaps.get(); } - if (settingsText.consumeSuffix(" FlipY")) { - settings->fFlipY = true; - } if (settingsText.consumeSuffix(" ForceHighPrecision")) { settings->fForceHighPrecision = true; } @@ -319,6 +308,13 @@ ResultCode processCommand(std::vector& args) { } } + // This tells the compiler where the rt-flip uniform will live should it be required. For + // testing purposes we don't care where that is, but the compiler will report an error if we + // leave them at their default invalid values. + settings.fRTFlipOffset = 32; + settings.fRTFlipSet = 0; + settings.fRTFlipBinding = 0; + const SkSL::String& outputPath = args[2]; auto emitCompileError = [&](SkSL::FileOutputStream& out, const char* errorText) { // Overwrite the compiler output, if any, with an error message. diff --git a/src/sksl/SkSLProgramSettings.h b/src/sksl/SkSLProgramSettings.h index ddd9e10705..e477dfb521 100644 --- a/src/sksl/SkSLProgramSettings.h +++ b/src/sksl/SkSLProgramSettings.h @@ -21,9 +21,6 @@ class ExternalFunction; * Holds the compiler settings for a program. */ struct ProgramSettings { - // if false, sk_FragCoord is exactly the same as gl_FragCoord. If true, the y coordinate - // must be flipped. - bool fFlipY = false; // If true the destination fragment color is read sk_FragColor. It must be declared inout. bool fFragColorIsInOut = false; // if true, Setting objects (e.g. sk_Caps.fbFetchSupport) should be replaced with their @@ -33,13 +30,13 @@ struct ProgramSettings { bool fForceHighPrecision = false; // if true, add -0.5 bias to LOD of all texture lookups bool fSharpenTextures = false; - // if the program needs to create an RTHeight uniform, this is its offset in the uniform + // if the program needs to create an RTFlip uniform, this is its offset in the uniform // buffer - int fRTHeightOffset = -1; - // if the program needs to create an RTHeight uniform and is creating spriv, this is the + int fRTFlipOffset = -1; + // if the program needs to create an RTFlip uniform and is creating spriv, this is the // binding and set number of the uniform buffer. - int fRTHeightBinding = -1; - int fRTHeightSet = -1; + int fRTFlipBinding = -1; + int fRTFlipSet = -1; // If layout(set=S, binding=B) is not specified for a uniform, these values will be used. // At present, zero is always used by our backends. int fDefaultUniformSet = 0; @@ -75,6 +72,8 @@ struct ProgramSettings { bool fDSLMangling = true; // If true, the DSL should automatically mark variables declared upon creation. bool fDSLMarkVarsDeclared = false; + // If true, the DSL should install a memory pool when possible. + bool fDSLUseMemoryPool = true; // External functions available for use in runtime effects. These values are registered in the // symbol table of the Program, but ownership is *not* transferred. It is up to the caller to // keep them alive. diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index da9fc43524..f53061ff29 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -361,20 +361,6 @@ public: return result; } - static ShaderCapsPointer FragCoordsNew() { - ShaderCapsPointer result = MakeShaderCaps(); - result->fVersionDeclString = "#version 400"; - result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; - return result; - } - static ShaderCapsPointer FragCoordsOld() { - ShaderCapsPointer result = MakeShaderCaps(); - result->fVersionDeclString = "#version 110"; - result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration; - result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions"; - return result; - } - static ShaderCapsPointer GeometryShaderExtensionString() { ShaderCapsPointer result = MakeShaderCaps(); result->fVersionDeclString = "#version 310es"; diff --git a/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp b/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp index d042a94d48..9f009baa69 100644 --- a/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp @@ -483,11 +483,9 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { } break; case k_dFdy_IntrinsicKind: - if (fProgram.fConfig->fSettings.fFlipY) { - // Flipping Y also negates the Y derivatives. - this->write("-dFdy"); - nameWritten = true; - } + // Flipping Y also negates the Y derivatives. + this->write(SKSL_RTFLIP_NAME ".y * dFdy"); + nameWritten = true; [[fallthrough]]; case k_dFdx_IntrinsicKind: case k_fwidth_IntrinsicKind: @@ -743,29 +741,16 @@ void GLSLCodeGenerator::writeFragCoord() { return; } - // 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.fConfig->fSettings.fFlipY) { - this->write("gl_FragCoord"); - } else if (const char* extension = this->caps().fragCoordConventionsExtensionString()) { - if (!fSetupFragPositionGlobal) { - if (this->caps().generation() < k150_GrGLSLGeneration) { - this->writeExtension(extension); - } - fGlobals.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n"); - fSetupFragPositionGlobal = true; - } - this->write("gl_FragCoord"); - } else { - if (!fSetupFragPositionLocal) { - fFunctionHeader += usesPrecisionModifiers() ? "highp " : ""; - fFunctionHeader += " vec4 sk_FragCoord = vec4(gl_FragCoord.x, " SKSL_RTHEIGHT_NAME - " - gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w);\n"; - fSetupFragPositionLocal = true; - } - this->write("sk_FragCoord"); + if (!fSetupFragPosition) { + fFunctionHeader += usesPrecisionModifiers() ? "highp " : ""; + fFunctionHeader += " vec4 sk_FragCoord = vec4(" + "gl_FragCoord.x, " + SKSL_RTFLIP_NAME ".x + " SKSL_RTFLIP_NAME ".y * gl_FragCoord.y, " + "gl_FragCoord.z, " + "gl_FragCoord.w);\n"; + fSetupFragPosition = true; } + this->write("sk_FragCoord"); } void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { @@ -781,7 +766,15 @@ void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { this->writeFragCoord(); break; case SK_CLOCKWISE_BUILTIN: - this->write(fProgram.fConfig->fSettings.fFlipY ? "(!gl_FrontFacing)" : "gl_FrontFacing"); + if (!fSetupClockwise) { + fFunctionHeader += + " bool sk_Clockwise = gl_FrontFacing;\n" + " if (" SKSL_RTFLIP_NAME ".y < 0.0) {\n" + " sk_Clockwise = !sk_Clockwise;\n" + " }\n"; + fSetupClockwise = true; + } + this->write("sk_Clockwise"); break; case SK_VERTEXID_BUILTIN: this->write("gl_VertexID"); @@ -1035,7 +1028,7 @@ void GLSLCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f) { } void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { - fSetupFragPositionLocal = false; + fSetupFragPosition = false; fSetupFragCoordWorkaround = false; this->writeFunctionDeclaration(f.declaration()); @@ -1475,11 +1468,11 @@ void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { } void GLSLCodeGenerator::writeInputVars() { - if (fProgram.fInputs.fRTHeight) { + if (fProgram.fInputs.fUseFlipRTUniform) { const char* precision = usesPrecisionModifiers() ? "highp " : ""; fGlobals.writeText("uniform "); fGlobals.writeText(precision); - fGlobals.writeText("float " SKSL_RTHEIGHT_NAME ";\n"); + fGlobals.writeText("vec2 " SKSL_RTFLIP_NAME ";\n"); } } diff --git a/src/sksl/codegen/SkSLGLSLCodeGenerator.h b/src/sksl/codegen/SkSLGLSLCodeGenerator.h index 9340620594..a249a5d553 100644 --- a/src/sksl/codegen/SkSLGLSLCodeGenerator.h +++ b/src/sksl/codegen/SkSLGLSLCodeGenerator.h @@ -193,8 +193,8 @@ protected: bool fFoundExternalSamplerDecl = false; bool fFoundRectSamplerDecl = false; bool fFoundGSInvocations = false; - bool fSetupFragPositionGlobal = false; - bool fSetupFragPositionLocal = false; + bool fSetupClockwise = false; + bool fSetupFragPosition = false; bool fSetupFragCoordWorkaround = false; // if non-empty, replace all texture / texture2D / textureProj / etc. calls with this name String fTextureFunctionOverride; diff --git a/src/sksl/codegen/SkSLMetalCodeGenerator.cpp b/src/sksl/codegen/SkSLMetalCodeGenerator.cpp index 99ccb1b38d..8614d79c34 100644 --- a/src/sksl/codegen/SkSLMetalCodeGenerator.cpp +++ b/src/sksl/codegen/SkSLMetalCodeGenerator.cpp @@ -618,11 +618,7 @@ bool MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind return true; } case k_dFdy_IntrinsicKind: { - // Flipping Y also negates the Y derivatives. - if (fProgram.fConfig->fSettings.fFlipY) { - this->write("-"); - } - this->write("dfdy"); + this->write(fRTFlipName + ".y*dfdy"); this->writeArgumentList(c.arguments()); return true; } @@ -1107,13 +1103,12 @@ void MetalCodeGenerator::writeCastConstructor(const AnyConstructor& c, } void MetalCodeGenerator::writeFragCoord() { - if (fRTHeightName.length()) { - this->write("float4(_fragCoord.x, "); - this->write(fRTHeightName.c_str()); - this->write(" - _fragCoord.y, 0.0, _fragCoord.w)"); - } else { - this->write("float4(_fragCoord.x, _fragCoord.y, 0.0, _fragCoord.w)"); - } + SkASSERT(fRTFlipName.length()); + this->write("float4(_fragCoord.x, "); + this->write(fRTFlipName.c_str()); + this->write(".x + "); + this->write(fRTFlipName.c_str()); + this->write(".y * _fragCoord.y, 0.0, _fragCoord.w)"); } void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) { @@ -1141,7 +1136,7 @@ void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) { case SK_CLOCKWISE_BUILTIN: // We'd set the front facing winding in the MTLRenderCommandEncoder to be counter // clockwise to match Skia convention. - this->write(fProgram.fConfig->fSettings.fFlipY ? "_frontFacing" : "(!_frontFacing)"); + this->write("(" + fRTFlipName + ".y < 0 ? _frontFacing : !_frontFacing)"); break; default: const Variable& var = *ref.variable(); @@ -1596,7 +1591,9 @@ int MetalCodeGenerator::getUniformSet(const Modifiers& m) { } bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f) { - fRTHeightName = fProgram.fInputs.fRTHeight ? "_globals._anonInterface0->u_skRTHeight" : ""; + fRTFlipName = fProgram.fInputs.fUseFlipRTUniform + ? "_globals._anonInterface0->" SKSL_RTFLIP_NAME + : ""; const char* separator = ""; if (f.isMain()) { switch (fProgram.fConfig->fKind) { @@ -1657,9 +1654,9 @@ bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f) } } if (fProgram.fConfig->fKind == ProgramKind::kFragment) { - if (fProgram.fInputs.fRTHeight && fInterfaceBlockNameMap.empty()) { + if (fProgram.fInputs.fUseFlipRTUniform && fInterfaceBlockNameMap.empty()) { this->write(", constant sksl_synthetic_uniforms& _anonInterface0 [[buffer(1)]]"); - fRTHeightName = "_anonInterface0.u_skRTHeight"; + fRTFlipName = "_anonInterface0." SKSL_RTFLIP_NAME; } this->write(", bool _frontFacing [[front_facing]]"); this->write(", float4 _fragCoord [[position]]"); @@ -1784,8 +1781,8 @@ void MetalCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { } fIndentation++; this->writeFields(structType->fields(), structType->fOffset, &intf); - if (fProgram.fInputs.fRTHeight) { - this->writeLine("float u_skRTHeight;"); + if (fProgram.fInputs.fUseFlipRTUniform) { + this->writeLine("float2 " SKSL_RTFLIP_NAME ";"); } fIndentation--; this->write("}"); @@ -2165,9 +2162,9 @@ void MetalCodeGenerator::writeInterfaceBlocks() { wroteInterfaceBlock = true; } } - if (!wroteInterfaceBlock && fProgram.fInputs.fRTHeight) { + if (!wroteInterfaceBlock && fProgram.fInputs.fUseFlipRTUniform) { this->writeLine("struct sksl_synthetic_uniforms {"); - this->writeLine(" float u_skRTHeight;"); + this->writeLine(" float2 " SKSL_RTFLIP_NAME ";"); this->writeLine("};"); } } diff --git a/src/sksl/codegen/SkSLMetalCodeGenerator.h b/src/sksl/codegen/SkSLMetalCodeGenerator.h index 40071d30f1..b5695be269 100644 --- a/src/sksl/codegen/SkSLMetalCodeGenerator.h +++ b/src/sksl/codegen/SkSLMetalCodeGenerator.h @@ -286,7 +286,7 @@ protected: bool fSetupFragPositionLocal = false; std::unordered_set fHelpers; int fUniformBuffer = -1; - String fRTHeightName; + String fRTFlipName; const FunctionDeclaration* fCurrentFunction = nullptr; int fSwizzleHelperCount = 0; bool fIgnoreVariableReferenceModifiers = false; diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp index 1775f301f7..8d9c074057 100644 --- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp @@ -9,11 +9,14 @@ #include "src/sksl/GLSL.std.450.h" +#include "include/sksl/DSLCore.h" #include "src/sksl/SkSLCompiler.h" #include "src/sksl/SkSLOperators.h" +#include "src/sksl/dsl/priv/DSLWriter.h" #include "src/sksl/ir/SkSLBlock.h" #include "src/sksl/ir/SkSLExpressionStatement.h" #include "src/sksl/ir/SkSLExtension.h" +#include "src/sksl/ir/SkSLField.h" #include "src/sksl/ir/SkSLIndexExpression.h" #include "src/sksl/ir/SkSLVariableReference.h" @@ -23,6 +26,9 @@ #define kLast_Capability SpvCapabilityMultiViewport +constexpr int DEVICE_FRAGCOORDS_BUILTIN = -1000; +constexpr int DEVICE_CLOCKWISE_BUILTIN = -1001; + namespace SkSL { static const int32_t SKSL_MAGIC = 0x0; // FIXME: we should probably register a magic number @@ -844,14 +850,35 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream } } +SpvId SPIRVCodeGenerator::vectorize(const Expression& arg, int vectorSize, OutputStream& out) { + SkASSERT(vectorSize >= 1 && vectorSize <= 4); + const Type& argType = arg.type(); + SpvId raw = this->writeExpression(arg, out); + if (argType.isScalar()) { + if (vectorSize == 1) { + return raw; + } + SpvId vector = this->nextId(&argType); + this->writeOpCode(SpvOpCompositeConstruct, 3 + vectorSize, out); + this->writeWord(this->getType(argType.toCompound(fContext, vectorSize, 1)), out); + this->writeWord(vector, out); + for (int i = 0; i < vectorSize; i++) { + this->writeWord(raw, out); + } + return vector; + } else { + SkASSERT(vectorSize == argType.columns()); + return raw; + } +} + std::vector SPIRVCodeGenerator::vectorize(const ExpressionArray& args, OutputStream& out) { - int vectorSize = 0; + int vectorSize = 1; for (const auto& a : args) { if (a->type().isVector()) { - if (vectorSize) { + if (vectorSize > 1) { SkASSERT(a->type().columns() == vectorSize); - } - else { + } else { vectorSize = a->type().columns(); } } @@ -859,20 +886,7 @@ std::vector SPIRVCodeGenerator::vectorize(const ExpressionArray& args, Ou std::vector result; result.reserve(args.size()); for (const auto& arg : args) { - const Type& argType = arg->type(); - SpvId raw = this->writeExpression(*arg, out); - if (vectorSize && argType.isScalar()) { - SpvId vector = this->nextId(&arg->type()); - this->writeOpCode(SpvOpCompositeConstruct, 3 + vectorSize, out); - this->writeWord(this->getType(argType.toCompound(fContext, vectorSize, 1)), out); - this->writeWord(vector, out); - for (int i = 0; i < vectorSize; i++) { - this->writeWord(raw, out); - } - result.push_back(vector); - } else { - result.push_back(raw); - } + result.push_back(this->vectorize(*arg, vectorSize, out)); } return result; } @@ -1045,13 +1059,15 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn this->writeWord(this->getType(callType), out); this->writeWord(result, out); this->writeWord(fn, out); - if (fProgram.fConfig->fSettings.fFlipY) { - // Flipping Y also negates the Y derivatives. - SpvId flipped = this->nextId(&callType); - this->writeInstruction(SpvOpFNegate, this->getType(callType), flipped, result, - out); - result = flipped; - } + this->addRTFlipUniform(c.fOffset); + using namespace dsl; + DSLExpression rtFlip(DSLWriter::IRGenerator().convertIdentifier(/*offset=*/-1, + SKSL_RTFLIP_NAME)); + SpvId rtFlipY = this->vectorize(*rtFlip.y().release(), callType.columns(), out); + SpvId flipped = this->nextId(&callType); + this->writeInstruction(SpvOpFMul, this->getType(callType), flipped, result, rtFlipY, + out); + result = flipped; break; } case kClamp_SpecialIntrinsic: { @@ -2032,137 +2048,98 @@ std::unique_ptr SPIRVCodeGenerator::getLValue(const } SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, OutputStream& out) { - SpvId result = this->getLValue(ref, out)->load(out); + if (ref.variable()->modifiers().fLayout.fBuiltin == DEVICE_FRAGCOORDS_BUILTIN) { + // Down below, we rewrite raw references to sk_FragCoord with expressions that reference + // DEVICE_FRAGCOORDS_BUILTIN. This is a fake variable that means we need to directly access + // the fragcoord; do so now. + dsl::DSLVar fragCoord("sk_FragCoord"); + return this->getLValue(*dsl::DSLExpression(fragCoord).release(), out)->load(out); + } + if (ref.variable()->modifiers().fLayout.fBuiltin == DEVICE_CLOCKWISE_BUILTIN) { + // Down below, we rewrite raw references to sk_Clockwise with expressions that reference + // DEVICE_CLOCKWISE_BUILTIN. This is a fake variable that means we need to directly + // access front facing; do so now. + dsl::DSLVar clockwise("sk_Clockwise"); + return this->getLValue(*dsl::DSLExpression(clockwise).release(), out)->load(out); + } - // Handle the "flipY" setting when reading sk_FragCoord. + // Handle inserting use of uniform to flip y when referencing sk_FragCoord. const Variable* variable = ref.variable(); - if (variable->modifiers().fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN && - fProgram.fConfig->fSettings.fFlipY) { - // The x component never changes, so just grab it - SpvId xId = this->nextId(Precision::kDefault); - this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fTypes.fFloat), xId, - result, 0, out); - - // Calculate the y component which may need to be flipped - SpvId rawYId = this->nextId(nullptr); - this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fTypes.fFloat), - rawYId, result, 1, out); - SpvId flippedYId = 0; - if (fProgram.fConfig->fSettings.fFlipY) { - // need to remap to a top-left coordinate system - if (fRTHeightStructId == (SpvId)-1) { - // height variable hasn't been written yet - SkASSERT(fRTHeightFieldIndex == (SpvId)-1); - std::vector fields; - if (fProgram.fConfig->fSettings.fRTHeightOffset < 0) { - fErrors.error(ref.fOffset, "RTHeightOffset is negative"); - } - fields.emplace_back( - Modifiers(Layout(/*flags=*/0, /*location=*/-1, - fProgram.fConfig->fSettings.fRTHeightOffset, - /*binding=*/-1, /*index=*/-1, /*set=*/-1, /*builtin=*/-1, - /*inputAttachmentIndex=*/-1, - Layout::kUnspecified_Primitive, /*maxVertices=*/1, - /*invocations=*/-1, /*when=*/"", Layout::CType::kDefault), - /*flags=*/0), - SKSL_RTHEIGHT_NAME, fContext.fTypes.fFloat.get()); - String name("sksl_synthetic_uniforms"); - std::unique_ptr intfStruct = Type::MakeStructType(/*offset=*/-1, name, - fields); - int binding = fProgram.fConfig->fSettings.fRTHeightBinding; - if (binding == -1) { - fErrors.error(ref.fOffset, "layout(binding=...) is required in SPIR-V"); - } - int set = fProgram.fConfig->fSettings.fRTHeightSet; - if (set == -1) { - fErrors.error(ref.fOffset, "layout(set=...) is required in SPIR-V"); - } - bool usePushConstants = fProgram.fConfig->fSettings.fUsePushConstants; - int flags = usePushConstants ? Layout::Flag::kPushConstant_Flag : 0; - Modifiers modifiers( - Layout(flags, /*location=*/-1, /*offset=*/-1, binding, /*index=*/-1, - set, /*builtin=*/-1, /*inputAttachmentIndex=*/-1, - Layout::kUnspecified_Primitive, - /*maxVertices=*/-1, /*invocations=*/-1, /*when=*/"", - Layout::CType::kDefault), - Modifiers::kUniform_Flag); - const Variable* intfVar = fSynthetics.takeOwnershipOfSymbol( - std::make_unique(/*offset=*/-1, - fProgram.fModifiers->add(modifiers), - name, - intfStruct.get(), - /*builtin=*/false, - Variable::Storage::kGlobal)); - InterfaceBlock intf(/*offset=*/-1, - intfVar, - name, - /*instanceName=*/"", - /*arraySize=*/0, - std::make_shared(&fErrors, /*builtin=*/false)); - - fRTHeightStructId = this->writeInterfaceBlock(intf, false); - fRTHeightFieldIndex = 0; - fRTHeightStorageClass = usePushConstants ? SpvStorageClassPushConstant - : SpvStorageClassUniform; + if (variable->modifiers().fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) { + this->addRTFlipUniform(ref.fOffset); + // Use sk_RTAdjust to compute the flipped coordinate + using namespace dsl; + const char* DEVICE_COORDS_NAME = "__device_FragCoords"; + SymbolTable& symbols = *dsl::DSLWriter::SymbolTable(); + // Use a uniform to flip the Y coordinate. The new expression will be written in + // terms of __device_FragCoords, which is a fake variable that means "access the + // underlying fragcoords directly without flipping it". + DSLExpression rtFlip(DSLWriter::IRGenerator().convertIdentifier(/*offset=*/-1, + SKSL_RTFLIP_NAME)); + if (!symbols[DEVICE_COORDS_NAME]) { + Modifiers modifiers; + modifiers.fLayout.fBuiltin = DEVICE_FRAGCOORDS_BUILTIN; + if (fProgram.fPool) { + fProgram.fPool->attachToThread(); + } + symbols.add(std::make_unique(/*offset=*/-1, + fContext.fModifiersPool->add(modifiers), + DEVICE_COORDS_NAME, + fContext.fTypes.fFloat4.get(), + true, + Variable::Storage::kGlobal)); + if (fProgram.fPool) { + fProgram.fPool->detachFromThread(); } - SkASSERT(fRTHeightFieldIndex != (SpvId)-1); - - IntLiteral fieldIndex(/*offset=*/-1, fRTHeightFieldIndex, fContext.fTypes.fInt.get()); - SpvId fieldIndexId = this->writeIntLiteral(fieldIndex); - SpvId heightPtr = this->nextId(nullptr); - this->writeOpCode(SpvOpAccessChain, 5, out); - this->writeWord(this->getPointerType(*fContext.fTypes.fFloat, fRTHeightStorageClass), - out); - this->writeWord(heightPtr, out); - this->writeWord(fRTHeightStructId, out); - this->writeWord(fieldIndexId, out); - SpvId heightRead = this->nextId(nullptr); - this->writeInstruction(SpvOpLoad, this->getType(*fContext.fTypes.fFloat), heightRead, - heightPtr, out); - - flippedYId = this->nextId(nullptr); - this->writeInstruction(SpvOpFSub, this->getType(*fContext.fTypes.fFloat), flippedYId, - heightRead, rawYId, out); } - - // The z component will always be zero so we just get an id to the 0 literal - FloatLiteral zero(/*offset=*/-1, /*value=*/0.0, fContext.fTypes.fFloat.get()); - SpvId zeroId = writeFloatLiteral(zero); - - // Calculate the w component - SpvId rawWId = this->nextId(nullptr); - this->writeInstruction(SpvOpCompositeExtract, this->getType(*fContext.fTypes.fFloat), - rawWId, result, 3, out); - - // Fill in the new fragcoord with the components from above - SpvId adjusted = this->nextId(nullptr); - this->writeOpCode(SpvOpCompositeConstruct, 7, out); - this->writeWord(this->getType(*fContext.fTypes.fFloat4), out); - this->writeWord(adjusted, out); - this->writeWord(xId, out); - if (fProgram.fConfig->fSettings.fFlipY) { - this->writeWord(flippedYId, out); - } else { - this->writeWord(rawYId, out); - } - this->writeWord(zeroId, out); - this->writeWord(rawWId, out); - - return adjusted; + DSLVar deviceCoord(DEVICE_COORDS_NAME); + std::unique_ptr rtFlipSkSLExpr = rtFlip.release(); + DSLExpression x = DSLExpression(rtFlipSkSLExpr->clone()).x(); + DSLExpression y = DSLExpression(std::move(rtFlipSkSLExpr)).y(); + return this->writeExpression(*dsl::Float4(deviceCoord.x(), + std::move(x) + std::move(y) * deviceCoord.y(), + deviceCoord.z(), + deviceCoord.w()).release(), + out); } - // Handle the "flipY" setting when reading sk_Clockwise. - if (variable->modifiers().fLayout.fBuiltin == SK_CLOCKWISE_BUILTIN && - !fProgram.fConfig->fSettings.fFlipY) { - // FrontFacing in Vulkan is defined in terms of a top-down render target. In skia, we use - // the default convention of "counter-clockwise face is front". - SpvId inverse = this->nextId(nullptr); - this->writeInstruction(SpvOpLogicalNot, this->getType(*fContext.fTypes.fBool), inverse, - result, out); - return inverse; + // Handle flipping sk_Clockwise. + if (variable->modifiers().fLayout.fBuiltin == SK_CLOCKWISE_BUILTIN) { + this->addRTFlipUniform(ref.fOffset); + using namespace dsl; + const char* DEVICE_CLOCKWISE_NAME = "__device_Clockwise"; + SymbolTable& symbols = *dsl::DSLWriter::SymbolTable(); + // Use a uniform to flip the Y coordinate. The new expression will be written in + // terms of __device_Clockwise, which is a fake variable that means "access the + // underlying FrontFacing directly". + DSLExpression rtFlip(DSLWriter::IRGenerator().convertIdentifier(/*offset=*/-1, + SKSL_RTFLIP_NAME)); + if (!symbols[DEVICE_CLOCKWISE_NAME]) { + Modifiers modifiers; + modifiers.fLayout.fBuiltin = DEVICE_CLOCKWISE_BUILTIN; + if (fProgram.fPool) { + fProgram.fPool->attachToThread(); + } + symbols.add(std::make_unique(/*offset=*/-1, + fContext.fModifiersPool->add(modifiers), + DEVICE_CLOCKWISE_NAME, + fContext.fTypes.fBool.get(), + true, + Variable::Storage::kGlobal)); + if (fProgram.fPool) { + fProgram.fPool->detachFromThread(); + } + } + DSLVar deviceClockwise(DEVICE_CLOCKWISE_NAME); + // FrontFacing in Vulkan is defined in terms of a top-down render target. In skia, + // we use the default convention of "counter-clockwise face is front". + return this->writeExpression(*dsl::Bool(Select(rtFlip.y() > 0, + !deviceClockwise, + deviceClockwise)).release(), + out); } - return result; + return this->getLValue(ref, out)->load(out); } SpvId SPIRVCodeGenerator::writeIndexExpression(const IndexExpression& expr, OutputStream& out) { @@ -3048,31 +3025,68 @@ static void update_sk_in_count(const Modifiers& m, int* outSkInCount) { } } -SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTHeight) { +SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTFlip) { MemoryLayout memoryLayout = this->memoryLayoutForVariable(intf.variable()); SpvId result = this->nextId(nullptr); - std::unique_ptr rtHeightStructType; - const Type* type = &intf.variable().type(); - if (!MemoryLayout::LayoutIsSupported(*type)) { - fErrors.error(type->fOffset, "type '" + type->name() + "' is not permitted here"); + const Variable& intfVar = intf.variable(); + const Type& type = intfVar.type(); + if (!MemoryLayout::LayoutIsSupported(type)) { + fErrors.error(type.fOffset, "type '" + type.name() + "' is not permitted here"); return this->nextId(nullptr); } SpvStorageClass_ storageClass = get_storage_class(intf.variable(), SpvStorageClassFunction); - if (fProgram.fInputs.fRTHeight && appendRTHeight) { - SkASSERT(fRTHeightStructId == (SpvId) -1); - SkASSERT(fRTHeightFieldIndex == (SpvId) -1); - std::vector fields = type->fields(); - fRTHeightStructId = result; - fRTHeightFieldIndex = fields.size(); - fRTHeightStorageClass = storageClass; - fields.emplace_back(Modifiers(), skstd::string_view(SKSL_RTHEIGHT_NAME), - fContext.fTypes.fFloat.get()); - rtHeightStructType = Type::MakeStructType(type->fOffset, String(type->name()), - std::move(fields)); - type = rtHeightStructType.get(); + if (fProgram.fInputs.fUseFlipRTUniform && appendRTFlip) { + // We can only have one interface block (because we use push_constant and that is limited + // to one per program), so we need to append rtflip to this one rather than synthesize an + // entirely new block when the variable is referenced. And we can't modify the existing + // block, so we instead create a modified copy of it and write that. + std::vector fields = type.fields(); + fields.emplace_back(Modifiers(Layout(/*flags=*/0, + /*location=*/-1, + fProgram.fConfig->fSettings.fRTFlipOffset, + /*binding=*/-1, + /*index=*/-1, + /*set=*/-1, + /*builtin=*/-1, + /*inputAttachmentIndex=*/-1, + Layout::kUnspecified_Primitive, + /*maxVertices=*/1, + /*invocations=*/-1, + /*when=*/"", + Layout::CType::kDefault), + /*flags=*/0), + SKSL_RTFLIP_NAME, + fContext.fTypes.fFloat2.get()); + if (fProgram.fPool) { + fProgram.fPool->attachToThread(); + } + const Type* rtFlipStructType = fProgram.fSymbols->takeOwnershipOfSymbol( + Type::MakeStructType(type.fOffset, String(type.name()), std::move(fields))); + const Variable* modifiedVar = fProgram.fSymbols->takeOwnershipOfSymbol( + std::make_unique(intfVar.fOffset, + &intfVar.modifiers(), + intfVar.name(), + rtFlipStructType, + intfVar.isBuiltin(), + intfVar.storage())); + InterfaceBlock modifiedCopy(intf.fOffset, + modifiedVar, + intf.typeName(), + intf.instanceName(), + intf.arraySize(), + intf.typeOwner()); + SpvId result = this->writeInterfaceBlock(modifiedCopy, false); + fProgram.fSymbols->add(std::make_unique( + /*offset=*/-1, modifiedVar, rtFlipStructType->fields().size() - 1)); + if (fProgram.fPool) { + fProgram.fPool->detachFromThread(); + } + fVariableMap[&intfVar] = result; + fWroteRTFlip = true; + return result; } SpvId typeId; - const Modifiers& intfModifiers = intf.variable().modifiers(); + const Modifiers& intfModifiers = intfVar.modifiers(); if (intfModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) { for (const ProgramElement* e : fProgram.elements()) { if (e->is()) { @@ -3080,11 +3094,10 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a update_sk_in_count(m, &fSkInCount); } } - typeId = this->getType( - *Type::MakeArrayType("sk_in", intf.variable().type().componentType(), fSkInCount), - memoryLayout); + typeId = this->getType(*Type::MakeArrayType("sk_in", type.componentType(), fSkInCount), + memoryLayout); } else { - typeId = this->getType(*type, memoryLayout); + typeId = this->getType(type, memoryLayout); } if (intfModifiers.fLayout.fBuiltin == -1) { this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBlock, fDecorationBuffer); @@ -3097,7 +3110,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a layout.fSet = 0; } this->writeLayout(layout, result); - fVariableMap[&intf.variable()] = result; + fVariableMap[&intfVar] = result; return result; } @@ -3556,6 +3569,91 @@ void SPIRVCodeGenerator::writeUniformBuffer(std::shared_ptr topLeve fUniformBufferId = this->writeInterfaceBlock(*fUniformBuffer.fInterfaceBlock); } +void SPIRVCodeGenerator::addRTFlipUniform(int offset) { + if (fWroteRTFlip) { + return; + } + // Flip variable hasn't been written yet. This means we don't have an existing + // interface block, so we're free to just synthesize one. + fWroteRTFlip = true; + std::vector fields; + if (fProgram.fConfig->fSettings.fRTFlipOffset < 0) { + fErrors.error(offset, "RTFlipOffset is negative"); + } + fields.emplace_back(Modifiers(Layout(/*flags=*/0, + /*location=*/-1, + fProgram.fConfig->fSettings.fRTFlipOffset, + /*binding=*/-1, + /*index=*/-1, + /*set=*/-1, + /*builtin=*/-1, + /*inputAttachmentIndex=*/-1, + Layout::kUnspecified_Primitive, + /*maxVertices=*/1, + /*invocations=*/-1, + /*when=*/"", + Layout::CType::kDefault), + /*flags=*/0), + SKSL_RTFLIP_NAME, + fContext.fTypes.fFloat2.get()); + String name("sksl_synthetic_uniforms"); + const Type* intfStruct = + fSynthetics.takeOwnershipOfSymbol(Type::MakeStructType(/*offset=*/-1, name, fields)); + int binding = fProgram.fConfig->fSettings.fRTFlipBinding; + if (binding == -1) { + fErrors.error(offset, "layout(binding=...) is required in SPIR-V"); + } + int set = fProgram.fConfig->fSettings.fRTFlipSet; + if (set == -1) { + fErrors.error(offset, "layout(set=...) is required in SPIR-V"); + } + bool usePushConstants = fProgram.fConfig->fSettings.fUsePushConstants; + int flags = usePushConstants ? Layout::Flag::kPushConstant_Flag : 0; + if (fProgram.fPool) { + fProgram.fPool->attachToThread(); + } + Modifiers modifiers(Layout(flags, + /*location=*/-1, + /*offset=*/-1, + binding, + /*index=*/-1, + set, + /*builtin=*/-1, + /*inputAttachmentIndex=*/-1, + Layout::kUnspecified_Primitive, + /*maxVertices=*/-1, + /*invocations=*/-1, + /*when=*/"", + Layout::CType::kDefault), + Modifiers::kUniform_Flag); + const Modifiers* modsPtr = fProgram.fModifiers->add(modifiers); + if (fProgram.fPool) { + fProgram.fPool->detachFromThread(); + } + const Variable* intfVar = fSynthetics.takeOwnershipOfSymbol( + std::make_unique(/*offset=*/-1, + modsPtr, + name, + intfStruct, + /*builtin=*/false, + Variable::Storage::kGlobal)); + if (fProgram.fPool) { + fProgram.fPool->attachToThread(); + } + fProgram.fSymbols->add(std::make_unique(/*offset=*/-1, intfVar, /*field=*/0)); + if (fProgram.fPool) { + fProgram.fPool->detachFromThread(); + } + InterfaceBlock intf(/*offset=*/-1, + intfVar, + name, + /*instanceName=*/"", + /*arraySize=*/0, + std::make_shared(&fErrors, /*builtin=*/false)); + + this->writeInterfaceBlock(intf, false); +} + void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& out) { fGLSLExtendedInstructions = this->nextId(nullptr); StringStream body; diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h index cefdfca10e..68e3d315fb 100644 --- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h @@ -208,7 +208,7 @@ private: void writeProgramElement(const ProgramElement& pe, OutputStream& out); - SpvId writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTHeight = true); + SpvId writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTFlip = true); SpvId writeFunctionStart(const FunctionDeclaration& f, OutputStream& out); @@ -237,6 +237,14 @@ private: SpvId signedInst, SpvId unsignedInst, const std::vector& args, OutputStream& out); + /** + * Promotes an expression to a vector. If the expression is already a vector with vectorSize + * columns, returns it unmodified. If the expression is a scalar, either promotes it to a + * vector (if vectorSize > 1) or returns it unmodified (if vectorSize == 1). Asserts if the + * expression is already a vector and it does not have vectorSize columns. + */ + SpvId vectorize(const Expression& expr, int vectorSize, OutputStream& out); + /** * Given a list of potentially mixed scalars and vectors, promotes the scalars to match the * size of the vectors and returns the ids of the written expressions. e.g. given (float, vec2), @@ -455,6 +463,8 @@ private: void writeUniformBuffer(std::shared_ptr topLevelSymbolTable); + void addRTFlipUniform(int offset); + const Context& fContext; const MemoryLayout fDefaultLayout; @@ -485,9 +495,7 @@ private: SpvId fCurrentBlock; std::stack fBreakTarget; std::stack fContinueTarget; - SpvId fRTHeightStructId = (SpvId) -1; - SpvId fRTHeightFieldIndex = (SpvId) -1; - SpvStorageClass_ fRTHeightStorageClass; + bool fWroteRTFlip = false; // holds variables synthesized during output, for lifetime purposes SymbolTable fSynthetics; int fSkInCount = 1; diff --git a/src/sksl/dsl/priv/DSLWriter.cpp b/src/sksl/dsl/priv/DSLWriter.cpp index abbb734b49..16ea8eb56a 100644 --- a/src/sksl/dsl/priv/DSLWriter.cpp +++ b/src/sksl/dsl/priv/DSLWriter.cpp @@ -42,7 +42,7 @@ DSLWriter::DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind, fOldConfig = fCompiler->fContext->fConfig; if (!isModule) { - if (compiler->context().fCaps.useNodePools()) { + if (compiler->context().fCaps.useNodePools() && settings.fDSLUseMemoryPool) { fPool = Pool::Create(); fPool->attachToThread(); } @@ -231,7 +231,7 @@ const SkSL::Variable* DSLWriter::Var(DSLVar& var) { var.fStorage); SkSL::Variable* varPtr = skslvar.get(); // We can't call VarDeclaration::Convert directly here, because the IRGenerator has special - // treatment for sk_FragColor and sk_RTHeight that we want to preserve in DSL. + // treatment for sk_FragColor that we want to preserve in DSL. var.fDeclaration = DSLWriter::IRGenerator().convertVarDeclaration( std::move(skslvar), var.fInitialValue.releaseIfValid()); diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index 774ffb2edf..78dd112fdb 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -27,8 +27,8 @@ #include "src/gpu/vk/GrVkCaps.h" #endif -// name of the render target height uniform -#define SKSL_RTHEIGHT_NAME "u_skRTHeight" +// name of the uniform used to handle features that are sensitive to whether Y is flipped. +#define SKSL_RTFLIP_NAME "u_skRTFlip" namespace SkSL { @@ -67,25 +67,11 @@ struct Program { using Settings = ProgramSettings; struct Inputs { - // if true, this program requires the render target height uniform to be defined - bool fRTHeight; - - // if true, this program must be recompiled if the flipY setting changes. If false, the - // program will compile to the same code regardless of the flipY setting. - bool fFlipY; - - // If true, this program includes a call to `dFdy`. - bool fUsesYDerivative; - - void reset() { - fRTHeight = false; - fFlipY = false; - fUsesYDerivative = false; - } - - bool isEmpty() { - return !fRTHeight && !fFlipY && !fUsesYDerivative; + bool fUseFlipRTUniform = false; + bool operator==(const Inputs& that) const { + return fUseFlipRTUniform == that.fUseFlipRTUniform; } + bool operator!=(const Inputs& that) const { return !(*this == that); } }; Program(std::unique_ptr source, diff --git a/tests/sksl/intrinsics/DFdy.asm.frag b/tests/sksl/intrinsics/DFdy.asm.frag index 661f8e25cb..14a2568653 100644 --- a/tests/sksl/intrinsics/DFdy.asm.frag +++ b/tests/sksl/intrinsics/DFdy.asm.frag @@ -7,6 +7,7 @@ OpName %sk_FragColor "sk_FragColor" OpName %sk_Clockwise "sk_Clockwise" OpName %_UniformBuffer "_UniformBuffer" OpMemberName %_UniformBuffer 0 "a" +OpMemberName %_UniformBuffer 1 "u_skRTFlip" OpName %main "main" OpDecorate %sk_FragColor RelaxedPrecision OpDecorate %sk_FragColor Location 0 @@ -14,10 +15,12 @@ OpDecorate %sk_FragColor Index 0 OpDecorate %sk_Clockwise BuiltIn FrontFacing OpMemberDecorate %_UniformBuffer 0 Offset 0 OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision +OpMemberDecorate %_UniformBuffer 1 Offset 32 OpDecorate %_UniformBuffer Block -OpDecorate %10 Binding 0 -OpDecorate %10 DescriptorSet 0 -OpDecorate %21 RelaxedPrecision +OpDecorate %11 Binding 0 +OpDecorate %11 DescriptorSet 0 +OpDecorate %23 RelaxedPrecision +OpDecorate %29 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -25,21 +28,28 @@ OpDecorate %21 RelaxedPrecision %bool = OpTypeBool %_ptr_Input_bool = OpTypePointer Input %bool %sk_Clockwise = OpVariable %_ptr_Input_bool Input -%_UniformBuffer = OpTypeStruct %float +%v2float = OpTypeVector %float 2 +%_UniformBuffer = OpTypeStruct %float %v2float %_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer -%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform +%11 = OpVariable %_ptr_Uniform__UniformBuffer Uniform %void = OpTypeVoid -%14 = OpTypeFunction %void +%16 = OpTypeFunction %void %_ptr_Uniform_float = OpTypePointer Uniform %float %int = OpTypeInt 32 1 %int_0 = OpConstant %int 0 +%int_1 = OpConstant %int 1 +%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float %_ptr_Output_float = OpTypePointer Output %float -%main = OpFunction %void None %14 -%15 = OpLabel -%17 = OpAccessChain %_ptr_Uniform_float %10 %int_0 -%21 = OpLoad %float %17 -%16 = OpDPdy %float %21 -%22 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0 -OpStore %22 %16 +%main = OpFunction %void None %16 +%17 = OpLabel +%19 = OpAccessChain %_ptr_Uniform_float %11 %int_0 +%23 = OpLoad %float %19 +%18 = OpDPdy %float %23 +%25 = OpAccessChain %_ptr_Uniform_v2float %11 %int_1 +%27 = OpLoad %v2float %25 +%28 = OpCompositeExtract %float %27 1 +%29 = OpFMul %float %18 %28 +%30 = OpAccessChain %_ptr_Output_float %sk_FragColor %int_0 +OpStore %30 %29 OpReturn OpFunctionEnd diff --git a/tests/sksl/intrinsics/DFdy.glsl b/tests/sksl/intrinsics/DFdy.glsl index 49aef35c16..4f7617b17f 100644 --- a/tests/sksl/intrinsics/DFdy.glsl +++ b/tests/sksl/intrinsics/DFdy.glsl @@ -1,6 +1,7 @@ +uniform vec2 u_skRTFlip; out vec4 sk_FragColor; uniform float a; void main() { - sk_FragColor.x = dFdy(a); + sk_FragColor.x = u_skRTFlip.y * dFdy(a); } diff --git a/tests/sksl/intrinsics/DFdy.metal b/tests/sksl/intrinsics/DFdy.metal index c2cd105a5c..5f2a91b097 100644 --- a/tests/sksl/intrinsics/DFdy.metal +++ b/tests/sksl/intrinsics/DFdy.metal @@ -9,9 +9,12 @@ struct Inputs { struct Outputs { float4 sk_FragColor [[color(0)]]; }; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { +struct sksl_synthetic_uniforms { + float2 u_skRTFlip; +}; +fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], constant sksl_synthetic_uniforms& _anonInterface0 [[buffer(1)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { Outputs _out; (void)_out; - _out.sk_FragColor.x = dfdy(_uniforms.a); + _out.sk_FragColor.x = _anonInterface0.u_skRTFlip.y*dfdy(_uniforms.a); return _out; } diff --git a/tests/sksl/shared/Clockwise.asm.frag b/tests/sksl/shared/Clockwise.asm.frag index 3d848c4ecb..11bba530be 100644 --- a/tests/sksl/shared/Clockwise.asm.frag +++ b/tests/sksl/shared/Clockwise.asm.frag @@ -6,13 +6,20 @@ OpExecutionMode %main OriginUpperLeft OpName %sk_FragColor "sk_FragColor" OpName %sk_Clockwise "sk_Clockwise" OpName %main "main" +OpName %sksl_synthetic_uniforms "sksl_synthetic_uniforms" +OpMemberName %sksl_synthetic_uniforms 0 "u_skRTFlip" OpDecorate %sk_FragColor RelaxedPrecision OpDecorate %sk_FragColor Location 0 OpDecorate %sk_FragColor Index 0 OpDecorate %sk_Clockwise BuiltIn FrontFacing -OpDecorate %13 RelaxedPrecision -OpDecorate %19 RelaxedPrecision -OpDecorate %20 RelaxedPrecision +OpMemberDecorate %sksl_synthetic_uniforms 0 Offset 32 +OpDecorate %sksl_synthetic_uniforms Block +OpDecorate %13 Binding 0 +OpDecorate %13 DescriptorSet 0 +OpDecorate %31 RelaxedPrecision +OpDecorate %32 RelaxedPrecision +OpDecorate %37 RelaxedPrecision +OpDecorate %38 RelaxedPrecision %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float @@ -22,16 +29,40 @@ OpDecorate %20 RelaxedPrecision %sk_Clockwise = OpVariable %_ptr_Input_bool Input %void = OpTypeVoid %11 = OpTypeFunction %void +%v2float = OpTypeVector %float 2 +%sksl_synthetic_uniforms = OpTypeStruct %v2float +%_ptr_Uniform_sksl_synthetic_uniforms = OpTypePointer Uniform %sksl_synthetic_uniforms +%13 = OpVariable %_ptr_Uniform_sksl_synthetic_uniforms Uniform %int = OpTypeInt 32 1 +%int_0 = OpConstant %int 0 +%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float +%float_0 = OpConstant %float 0 +%_ptr_Function_bool = OpTypePointer Function %bool %int_1 = OpConstant %int 1 %int_n1 = OpConstant %int -1 %main = OpFunction %void None %11 %12 = OpLabel -%13 = OpLoad %bool %sk_Clockwise -%14 = OpLogicalNot %bool %13 -%15 = OpSelect %int %14 %int_1 %int_n1 -%19 = OpConvertSToF %float %15 -%20 = OpCompositeConstruct %v4float %19 %19 %19 %19 -OpStore %sk_FragColor %20 +%25 = OpVariable %_ptr_Function_bool Function +%19 = OpAccessChain %_ptr_Uniform_v2float %13 %int_0 +%21 = OpLoad %v2float %19 +%22 = OpCompositeExtract %float %21 1 +%24 = OpFOrdGreaterThan %bool %22 %float_0 +OpSelectionMerge %29 None +OpBranchConditional %24 %27 %28 +%27 = OpLabel +%31 = OpLoad %bool %sk_Clockwise +%30 = OpLogicalNot %bool %31 +OpStore %25 %30 +OpBranch %29 +%28 = OpLabel +%32 = OpLoad %bool %sk_Clockwise +OpStore %25 %32 +OpBranch %29 +%29 = OpLabel +%33 = OpLoad %bool %25 +%34 = OpSelect %int %33 %int_1 %int_n1 +%37 = OpConvertSToF %float %34 +%38 = OpCompositeConstruct %v4float %37 %37 %37 %37 +OpStore %sk_FragColor %38 OpReturn OpFunctionEnd diff --git a/tests/sksl/shared/Clockwise.glsl b/tests/sksl/shared/Clockwise.glsl index 08224131db..ae0886ef74 100644 --- a/tests/sksl/shared/Clockwise.glsl +++ b/tests/sksl/shared/Clockwise.glsl @@ -1,5 +1,10 @@ +uniform vec2 u_skRTFlip; out vec4 sk_FragColor; void main() { - sk_FragColor = vec4(float(gl_FrontFacing ? 1 : -1)); + bool sk_Clockwise = gl_FrontFacing; + if (u_skRTFlip.y < 0.0) { + sk_Clockwise = !sk_Clockwise; + } + sk_FragColor = vec4(float(sk_Clockwise ? 1 : -1)); } diff --git a/tests/sksl/shared/Clockwise.metal b/tests/sksl/shared/Clockwise.metal index 12c43042a7..5d352c524e 100644 --- a/tests/sksl/shared/Clockwise.metal +++ b/tests/sksl/shared/Clockwise.metal @@ -6,9 +6,12 @@ struct Inputs { struct Outputs { float4 sk_FragColor [[color(0)]]; }; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { +struct sksl_synthetic_uniforms { + float2 u_skRTFlip; +}; +fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant sksl_synthetic_uniforms& _anonInterface0 [[buffer(1)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { Outputs _out; (void)_out; - _out.sk_FragColor = float4(float((!_frontFacing) ? 1 : -1)); + _out.sk_FragColor = float4(float((_anonInterface0.u_skRTFlip.y < 0 ? _frontFacing : !_frontFacing) ? 1 : -1)); return _out; } diff --git a/tests/sksl/shared/DerivativesFlipY.glsl b/tests/sksl/shared/DerivativesFlipY.glsl deleted file mode 100644 index 3a2e5570ed..0000000000 --- a/tests/sksl/shared/DerivativesFlipY.glsl +++ /dev/null @@ -1,5 +0,0 @@ - -out vec4 sk_FragColor; -void main() { - (sk_FragColor.x = dFdx(1.0) , sk_FragColor.y = -dFdy(1.0)); -} diff --git a/tests/sksl/shared/DerivativesFlipYStandaloneSettings.glsl b/tests/sksl/shared/DerivativesFlipYStandaloneSettings.glsl deleted file mode 100644 index 5557f6aa50..0000000000 --- a/tests/sksl/shared/DerivativesFlipYStandaloneSettings.glsl +++ /dev/null @@ -1,5 +0,0 @@ - -out vec4 sk_FragColor; -void main() { - (sk_FragColor.x = dFdx(1.0) , sk_FragColor.y = dFdy(1.0)); -} diff --git a/tests/sksl/shared/FragCoords.asm.frag b/tests/sksl/shared/FragCoords.asm.frag new file mode 100644 index 0000000000..7c140a9080 --- /dev/null +++ b/tests/sksl/shared/FragCoords.asm.frag @@ -0,0 +1,65 @@ +OpCapability Shader +%1 = OpExtInstImport "GLSL.std.450" +OpMemoryModel Logical GLSL450 +OpEntryPoint Fragment %main "main" %sk_FragColor %sk_FragCoord %sk_Clockwise +OpExecutionMode %main OriginUpperLeft +OpName %sk_FragColor "sk_FragColor" +OpName %sk_FragCoord "sk_FragCoord" +OpName %sk_Clockwise "sk_Clockwise" +OpName %main "main" +OpName %sksl_synthetic_uniforms "sksl_synthetic_uniforms" +OpMemberName %sksl_synthetic_uniforms 0 "u_skRTFlip" +OpDecorate %sk_FragColor RelaxedPrecision +OpDecorate %sk_FragColor Location 0 +OpDecorate %sk_FragColor Index 0 +OpDecorate %sk_FragCoord BuiltIn FragCoord +OpDecorate %sk_Clockwise BuiltIn FrontFacing +OpMemberDecorate %sksl_synthetic_uniforms 0 Offset 32 +OpDecorate %sksl_synthetic_uniforms Block +OpDecorate %15 Binding 0 +OpDecorate %15 DescriptorSet 0 +OpDecorate %40 RelaxedPrecision +OpDecorate %41 RelaxedPrecision +%float = OpTypeFloat 32 +%v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float +%sk_FragColor = OpVariable %_ptr_Output_v4float Output +%_ptr_Input_v4float = OpTypePointer Input %v4float +%sk_FragCoord = OpVariable %_ptr_Input_v4float Input +%bool = OpTypeBool +%_ptr_Input_bool = OpTypePointer Input %bool +%sk_Clockwise = OpVariable %_ptr_Input_bool Input +%void = OpTypeVoid +%13 = OpTypeFunction %void +%v2float = OpTypeVector %float 2 +%sksl_synthetic_uniforms = OpTypeStruct %v2float +%_ptr_Uniform_sksl_synthetic_uniforms = OpTypePointer Uniform %sksl_synthetic_uniforms +%15 = OpVariable %_ptr_Uniform_sksl_synthetic_uniforms Uniform +%int = OpTypeInt 32 1 +%int_0 = OpConstant %int 0 +%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float +%main = OpFunction %void None %13 +%14 = OpLabel +%19 = OpLoad %v4float %sk_FragCoord +%20 = OpCompositeExtract %float %19 0 +%23 = OpAccessChain %_ptr_Uniform_v2float %15 %int_0 +%25 = OpLoad %v2float %23 +%26 = OpCompositeExtract %float %25 0 +%27 = OpAccessChain %_ptr_Uniform_v2float %15 %int_0 +%28 = OpLoad %v2float %27 +%29 = OpCompositeExtract %float %28 1 +%30 = OpLoad %v4float %sk_FragCoord +%31 = OpCompositeExtract %float %30 1 +%32 = OpFMul %float %29 %31 +%33 = OpFAdd %float %26 %32 +%34 = OpLoad %v4float %sk_FragCoord +%35 = OpCompositeExtract %float %34 2 +%36 = OpLoad %v4float %sk_FragCoord +%37 = OpCompositeExtract %float %36 3 +%38 = OpCompositeConstruct %v4float %20 %33 %35 %37 +%39 = OpVectorShuffle %v2float %38 %38 0 1 +%40 = OpLoad %v4float %sk_FragColor +%41 = OpVectorShuffle %v4float %40 %39 4 5 2 3 +OpStore %sk_FragColor %41 +OpReturn +OpFunctionEnd diff --git a/tests/sksl/shared/FragCoords.glsl b/tests/sksl/shared/FragCoords.glsl new file mode 100644 index 0000000000..f0f836924a --- /dev/null +++ b/tests/sksl/shared/FragCoords.glsl @@ -0,0 +1,7 @@ + +uniform vec2 u_skRTFlip; +out vec4 sk_FragColor; +void main() { + vec4 sk_FragCoord = vec4(gl_FragCoord.x, u_skRTFlip.x + u_skRTFlip.y * gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w); + sk_FragColor.xy = sk_FragCoord.xy; +} diff --git a/tests/sksl/shared/FragCoords.metal b/tests/sksl/shared/FragCoords.metal new file mode 100644 index 0000000000..dbb7ae0397 --- /dev/null +++ b/tests/sksl/shared/FragCoords.metal @@ -0,0 +1,17 @@ +#include +#include +using namespace metal; +struct Inputs { +}; +struct Outputs { + float4 sk_FragColor [[color(0)]]; +}; +struct sksl_synthetic_uniforms { + float2 u_skRTFlip; +}; +fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant sksl_synthetic_uniforms& _anonInterface0 [[buffer(1)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { + Outputs _out; + (void)_out; + _out.sk_FragColor.xy = float4(_fragCoord.x, _anonInterface0.u_skRTFlip.x + _anonInterface0.u_skRTFlip.y * _fragCoord.y, 0.0, _fragCoord.w).xy; + return _out; +} diff --git a/tests/sksl/shared/FragCoordsFlipY.asm.frag b/tests/sksl/shared/FragCoordsFlipY.asm.frag deleted file mode 100644 index d42ded1a9b..0000000000 --- a/tests/sksl/shared/FragCoordsFlipY.asm.frag +++ /dev/null @@ -1,6 +0,0 @@ -### Compilation failed: - -error: 3: RTHeightOffset is negative -error: 3: layout(binding=...) is required in SPIR-V -error: 3: layout(set=...) is required in SPIR-V -3 errors diff --git a/tests/sksl/shared/FragCoordsFlipY.glsl b/tests/sksl/shared/FragCoordsFlipY.glsl deleted file mode 100644 index 26fe7a2de8..0000000000 --- a/tests/sksl/shared/FragCoordsFlipY.glsl +++ /dev/null @@ -1,6 +0,0 @@ -#version 400 -out vec4 sk_FragColor; -void main() { - vec4 sk_FragCoord = vec4(gl_FragCoord.x, u_skRTHeight - gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w); - sk_FragColor.xy = sk_FragCoord.xy; -} diff --git a/tests/sksl/shared/FragCoordsFlipY.metal b/tests/sksl/shared/FragCoordsFlipY.metal deleted file mode 100644 index aa981bdfca..0000000000 --- a/tests/sksl/shared/FragCoordsFlipY.metal +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -using namespace metal; -struct Inputs { -}; -struct Outputs { - float4 sk_FragColor [[color(0)]]; -}; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { - Outputs _out; - (void)_out; - _out.sk_FragColor.xy = float4(_fragCoord.x, _fragCoord.y, 0.0, _fragCoord.w).xy; - return _out; -} diff --git a/tests/sksl/shared/FragCoordsNew.asm.frag b/tests/sksl/shared/FragCoordsNew.asm.frag deleted file mode 100644 index d42ded1a9b..0000000000 --- a/tests/sksl/shared/FragCoordsNew.asm.frag +++ /dev/null @@ -1,6 +0,0 @@ -### Compilation failed: - -error: 3: RTHeightOffset is negative -error: 3: layout(binding=...) is required in SPIR-V -error: 3: layout(set=...) is required in SPIR-V -3 errors diff --git a/tests/sksl/shared/FragCoordsNew.glsl b/tests/sksl/shared/FragCoordsNew.glsl deleted file mode 100644 index a8651284eb..0000000000 --- a/tests/sksl/shared/FragCoordsNew.glsl +++ /dev/null @@ -1,6 +0,0 @@ -#version 400 -layout(origin_upper_left) in vec4 gl_FragCoord; -out vec4 sk_FragColor; -void main() { - sk_FragColor.xy = gl_FragCoord.xy; -} diff --git a/tests/sksl/shared/FragCoordsNew.metal b/tests/sksl/shared/FragCoordsNew.metal deleted file mode 100644 index aa981bdfca..0000000000 --- a/tests/sksl/shared/FragCoordsNew.metal +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -using namespace metal; -struct Inputs { -}; -struct Outputs { - float4 sk_FragColor [[color(0)]]; -}; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { - Outputs _out; - (void)_out; - _out.sk_FragColor.xy = float4(_fragCoord.x, _fragCoord.y, 0.0, _fragCoord.w).xy; - return _out; -} diff --git a/tests/sksl/shared/FragCoordsOld.asm.frag b/tests/sksl/shared/FragCoordsOld.asm.frag deleted file mode 100644 index d42ded1a9b..0000000000 --- a/tests/sksl/shared/FragCoordsOld.asm.frag +++ /dev/null @@ -1,6 +0,0 @@ -### Compilation failed: - -error: 3: RTHeightOffset is negative -error: 3: layout(binding=...) is required in SPIR-V -error: 3: layout(set=...) is required in SPIR-V -3 errors diff --git a/tests/sksl/shared/FragCoordsOld.glsl b/tests/sksl/shared/FragCoordsOld.glsl deleted file mode 100644 index fc64b1e3e5..0000000000 --- a/tests/sksl/shared/FragCoordsOld.glsl +++ /dev/null @@ -1,6 +0,0 @@ -#version 110 -#extension GL_ARB_fragment_coord_conventions : require -layout(origin_upper_left) in vec4 gl_FragCoord; -void main() { - gl_FragColor.xy = gl_FragCoord.xy; -} diff --git a/tests/sksl/shared/FragCoordsOld.metal b/tests/sksl/shared/FragCoordsOld.metal deleted file mode 100644 index aa981bdfca..0000000000 --- a/tests/sksl/shared/FragCoordsOld.metal +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -using namespace metal; -struct Inputs { -}; -struct Outputs { - float4 sk_FragColor [[color(0)]]; -}; -fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) { - Outputs _out; - (void)_out; - _out.sk_FragColor.xy = float4(_fragCoord.x, _fragCoord.y, 0.0, _fragCoord.w).xy; - return _out; -} diff --git a/tests/sksl/workarounds/FragCoordsStandaloneSettings.glsl b/tests/sksl/workarounds/FragCoordsStandaloneSettings.glsl index 2247f331a8..f0f836924a 100644 --- a/tests/sksl/workarounds/FragCoordsStandaloneSettings.glsl +++ b/tests/sksl/workarounds/FragCoordsStandaloneSettings.glsl @@ -1,5 +1,7 @@ +uniform vec2 u_skRTFlip; out vec4 sk_FragColor; void main() { - sk_FragColor.xy = gl_FragCoord.xy; + vec4 sk_FragCoord = vec4(gl_FragCoord.x, u_skRTFlip.x + u_skRTFlip.y * gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w); + sk_FragColor.xy = sk_FragCoord.xy; }