bool GrGLProgramBuilder::compileAndAttachShaders(const char* glsl, int length, GrGLuint programId, GrGLenum type, SkTDArray<GrGLuint>* shaderIds, const SkSL::Program::Settings& settings, const SkSL::Program::Inputs& inputs) { GrGLGpu* gpu = this->gpu(); GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId, type, glsl, length, gpu->stats(), settings); if (!shaderId) { return false; } *shaderIds->append() = shaderId; if (inputs.fFlipY) { GrProgramDesc* d = this->desc(); d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin( this->pipeline().proxy()->origin())); d->finalize(); } return true; }
static int get_glprograms_max_stages(const sk_gpu_test::ContextInfo& ctxInfo) { GrContext* context = ctxInfo.grContext(); GrGLGpu* gpu = static_cast<GrGLGpu*>(context->contextPriv().getGpu()); int maxStages = 6; if (kGLES_GrGLStandard == gpu->glStandard()) { // We've had issues with driver crashes and HW limits being exceeded with many effects on // Android devices. We have passes on ARM devices with the default number of stages. // TODO When we run ES 3.00 GLSL in more places, test again #ifdef SK_BUILD_FOR_ANDROID if (kARM_GrGLVendor != gpu->ctxInfo().vendor()) { maxStages = 1; } #endif // On iOS we can exceed the maximum number of varyings. http://skbug.com/6627. #ifdef SK_BUILD_FOR_IOS maxStages = 3; #endif } if (ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D9_ES2_ContextType || ctxInfo.type() == sk_gpu_test::GrContextFactory::kANGLE_D3D11_ES2_ContextType) { // On Angle D3D we will hit a limit of out variables if we use too many stages. maxStages = 3; } return maxStages; }
const char* GrGLFragmentShaderBuilder::fragmentPosition() { fHasReadFragmentPosition = true; GrGLGpu* gpu = fProgramBuilder->gpu(); // 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 (fTopLeftFragPosRead) { fSetupFragPosition = true; return "gl_FragCoord"; } else if (gpu->glCaps().fragCoordConventionsSupport()) { if (!fSetupFragPosition) { if (gpu->glslGeneration() < k150_GrGLSLGeneration) { this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, "GL_ARB_fragment_coord_conventions"); } fInputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kIn_TypeModifier, "gl_FragCoord", kDefault_GrSLPrecision, GrGLShaderVar::kUpperLeft_Origin); fSetupFragPosition = true; } return "gl_FragCoord"; } else { static const char* kTempName = "tmpXYFragCoord"; static const char* kCoordName = "fragCoordYDown"; if (!fSetupFragPosition) { // temporarily change the stage index because we're inserting non-stage code. GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder); SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); const char* rtHeightName; fProgramBuilder->fUniformHandles.fRTHeightUni = fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "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("\tvec4 %s = vec4(%s.x, %s - %s.y, 1.0, 1.0);\n", kCoordName, kTempName, rtHeightName, kTempName); this->codePrependf("vec2 %s = gl_FragCoord.xy;", kTempName); fSetupFragPosition = true; } SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); return kCoordName; } }
DEF_GPUTEST(GLPrograms, reporter, factory) { // Set a locale that would cause shader compilation to fail because of , as decimal separator. // skbug 3330 #ifdef SK_BUILD_FOR_WIN GrAutoLocaleSetter als("sv-SE"); #else GrAutoLocaleSetter als("sv_SE.UTF-8"); #endif // We suppress prints to avoid spew GrContextOptions opts; opts.fSuppressPrints = true; GrContextFactory debugFactory(opts); for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) { GrContext* context = debugFactory.get(static_cast<GrContextFactory::GLContextType>(type)); if (context) { GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu()); /* * For the time being, we only support the test with desktop GL or for android on * ARM platforms * TODO When we run ES 3.00 GLSL in more places, test again */ int maxStages; if (kGL_GrGLStandard == gpu->glStandard() || kARM_GrGLVendor == gpu->ctxInfo().vendor()) { maxStages = 6; } else if (kTegra3_GrGLRenderer == gpu->ctxInfo().renderer() || kOther_GrGLRenderer == gpu->ctxInfo().renderer()) { maxStages = 1; } else { return; } #if SK_ANGLE // Some long shaders run out of temporary registers in the D3D compiler on ANGLE. if (type == GrContextFactory::kANGLE_GLContextType) { maxStages = 2; } #endif #if SK_COMMAND_BUFFER // Some long shaders run out of temporary registers in the D3D compiler on ANGLE. // TODO(hendrikw): This only needs to happen with the ANGLE comand buffer backend. if (type == GrContextFactory::kCommandBuffer_GLContextType) { maxStages = 2; } #endif GrTestTarget testTarget; context->getTestTarget(&testTarget); REPORTER_ASSERT(reporter, GrDrawingManager::ProgramUnitTest( context, testTarget.target(), maxStages)); } } }
const char* GrGLFragmentShaderBuilder::fragmentPosition() { fHasReadFragmentPosition = true; GrGLGpu* gpu = fProgramBuilder->gpu(); // 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 (fTopLeftFragPosRead) { fSetupFragPosition = true; return "gl_FragCoord"; } else if (gpu->glCaps().fragCoordConventionsSupport()) { if (!fSetupFragPosition) { if (gpu->glslGeneration() < k150_GrGLSLGeneration) { this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature, "GL_ARB_fragment_coord_conventions"); } fInputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kIn_TypeModifier, "gl_FragCoord", kDefault_GrSLPrecision, GrGLShaderVar::kUpperLeft_Origin); fSetupFragPosition = true; } return "gl_FragCoord"; } else { static const char* kCoordName = "fragCoordYDown"; if (!fSetupFragPosition) { // temporarily change the stage index because we're inserting non-stage code. GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder); SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); const char* rtHeightName; fProgramBuilder->fUniformHandles.fRTHeightUni = fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "RTHeight", &rtHeightName); // Using glFragCoord.zw for the last two components tickles an Adreno driver bug that // causes programs to fail to link. Making this function return a vec2() didn't fix the // problem but using 1.0 for the last two components does. this->codePrependf("\tvec4 %s = vec4(gl_FragCoord.x, %s - gl_FragCoord.y, 1.0, " "1.0);\n", kCoordName, rtHeightName); fSetupFragPosition = true; } SkASSERT(fProgramBuilder->fUniformHandles.fRTHeightUni.isValid()); return kCoordName; } }
static int get_glprograms_max_stages(GrContext* context) { GrGLGpu* gpu = static_cast<GrGLGpu*>(context->getGpu()); /* * For the time being, we only support the test with desktop GL or for android on * ARM platforms * TODO When we run ES 3.00 GLSL in more places, test again */ if (kGL_GrGLStandard == gpu->glStandard() || kARM_GrGLVendor == gpu->ctxInfo().vendor()) { return 6; } else if (kTegra3_GrGLRenderer == gpu->ctxInfo().renderer() || kOther_GrGLRenderer == gpu->ctxInfo().renderer()) { return 1; } return 0; }
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) { GrGLGpu* gpu = fProgramBuilder->gpu(); this->versionDecl() = GrGLGetGLSLVersionDecl(gpu->ctxInfo()); GrGLAppendGLSLDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, gpu->glStandard(), &this->precisionQualifier()); this->compileAndAppendLayoutQualifiers(); fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &this->uniforms()); this->appendDecls(fInputs, &this->inputs()); // We shouldn't have declared outputs on 1.10 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); this->appendDecls(fOutputs, &this->outputs()); return this->finalize(programId, GR_GL_FRAGMENT_SHADER, shaderIds); }
void GrGLPathRange::onInitPath(int index, const SkPath& skPath) const { GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu()); if (NULL == gpu) { return; } // Make sure the path at this index hasn't been initted already. SkDEBUGCODE( GrGLboolean isPath; GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index))); SkASSERT(GR_GL_FALSE == isPath); GrGLPath::InitPathObject(gpu, fBasePathID + index, skPath, this->getStroke()); // TODO: Use a better approximation for the individual path sizes. fGpuMemorySize += 100; }
void GrGLPathRendering::onStencilPath(const StencilPathArgs& args, const GrPath* path) { GrGLGpu* gpu = this->gpu(); SkASSERT(gpu->caps()->shaderCaps()->pathRenderingSupport()); gpu->flushColorWrite(false); gpu->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace); GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(args.fRenderTarget); SkISize size = SkISize::Make(rt->width(), rt->height()); this->setProjectionMatrix(*args.fViewMatrix, size, rt->origin()); gpu->flushScissor(*args.fScissor, rt->getViewport(), rt->origin()); gpu->flushHWAAState(rt, args.fUseHWAA); gpu->flushRenderTarget(rt, NULL); const GrGLPath* glPath = static_cast<const GrGLPath*>(path); this->flushPathStencilSettings(*args.fStencil); SkASSERT(!fHWPathStencilSettings.isTwoSided()); GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode( fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face)); GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face); if (glPath->shouldFill()) { GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask)); } if (glPath->shouldStroke()) { GL_CALL(StencilStrokePath(glPath->pathID(), 0xffff, writeMask)); } }
bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) { switch (feature) { case kStandardDerivatives_GLSLFeature: { GrGLGpu* gpu = fProgramBuilder->gpu(); if (!gpu->glCaps().shaderCaps()->shaderDerivativeSupport()) { return false; } if (kGLES_GrGLStandard == gpu->glStandard() && k110_GrGLSLGeneration == gpu->glslGeneration()) { this->addFeature(1 << kStandardDerivatives_GLSLFeature, "GL_OES_standard_derivatives"); } return true; } default: SkFAIL("Unexpected GLSLFeature requested."); return false; } }
const char* GrGLFragmentShaderBuilder::dstColor() { fHasReadDstColor = true; GrGLGpu* gpu = fProgramBuilder->gpu(); if (gpu->glCaps().glslCaps()->fbFetchSupport()) { this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), gpu->glCaps().glslCaps()->fbFetchExtensionString()); // Some versions of this extension string require declaring custom color output on ES 3.0+ const char* fbFetchColorName = gpu->glCaps().glslCaps()->fbFetchColorName(); if (gpu->glCaps().glslCaps()->fbFetchNeedsCustomOutput()) { this->enableCustomOutput(); fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier); fbFetchColorName = declared_color_output_name(); } return fbFetchColorName; } else { return kDstTextureColorName; } }
void GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const { GrGLGpu* gpu = static_cast<GrGLGpu*>(this->getGpu()); if (NULL == gpu) { return; } // Make sure the path at this index hasn't been initted already. SkDEBUGCODE( GrGLboolean isPath; GR_GL_CALL_RET(gpu->glInterface(), isPath, IsPath(fBasePathID + index))); SkASSERT(GR_GL_FALSE == isPath); const SkPath* skPath = &origSkPath; SkTLazy<SkPath> tmpPath; const GrStrokeInfo* stroke = &fStroke; GrStrokeInfo tmpStroke(SkStrokeRec::kFill_InitStyle); // Dashing must be applied to the path. However, if dashing is present, // we must convert all the paths to fills. The GrStrokeInfo::applyDash leaves // simple paths as strokes but converts other paths to fills. // Thus we must stroke the strokes here, so that all paths in the // path range are using the same style. if (fStroke.isDashed()) { if (!stroke->applyDashToPath(tmpPath.init(), &tmpStroke, *skPath)) { return; } skPath = tmpPath.get(); stroke = &tmpStroke; if (tmpStroke.needToApply()) { if (!tmpStroke.applyToPath(tmpPath.get(), *tmpPath.get())) { return; } tmpStroke.setFillStyle(); } } GrGLPath::InitPathObject(gpu, fBasePathID + index, *skPath, *stroke); // TODO: Use a better approximation for the individual path sizes. fGpuMemorySize += 100; }
bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader, GrGLuint programId, GrGLenum type, SkTDArray<GrGLuint>* shaderIds) { GrGLGpu* gpu = this->gpu(); GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId, type, shader.fCompilerStrings.begin(), shader.fCompilerStringLengths.begin(), shader.fCompilerStrings.count(), gpu->stats()); if (!shaderId) { return false; } *shaderIds->append() = shaderId; return true; }
bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const { GrGLGpu* gpu = fProgramBuilder->gpu(); const GrGLContext& glCtx = gpu->glContext(); const GrGLContextInfo& ctxInfo = gpu->ctxInfo(); SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo)); fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc); this->appendDecls(fInputs, &vertShaderSrc); this->appendDecls(fOutputs, &vertShaderSrc); vertShaderSrc.append("void main() {"); vertShaderSrc.append(fCode); vertShaderSrc.append("}\n"); GrGLuint vertShaderId = GrGLCompileAndAttachShader(glCtx, programId, GR_GL_VERTEX_SHADER, vertShaderSrc, gpu->gpuStats()); if (!vertShaderId) { return false; } *shaderIds->append() = vertShaderId; return true; }
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const { GrGLGpu* gpu = fProgramBuilder->gpu(); SkString fragShaderSrc(GrGetGLSLVersionDecl(gpu->ctxInfo())); fragShaderSrc.append(fExtensions); append_default_precision_qualifier(kDefault_GrSLPrecision, gpu->glStandard(), &fragShaderSrc); fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc); this->appendDecls(fInputs, &fragShaderSrc); // We shouldn't have declared outputs on 1.10 SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty()); this->appendDecls(fOutputs, &fragShaderSrc); fragShaderSrc.append(fFunctions); fragShaderSrc.append("void main() {\n"); fragShaderSrc.append(fCode); fragShaderSrc.append("}\n"); GrGLuint fragShaderId = GrGLCompileAndAttachShader(gpu->glContext(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc, gpu->gpuStats()); if (!fragShaderId) { return false; } *shaderIds->append() = fragShaderId; return true; }
const char* GrGLFragmentShaderBuilder::dstColor() { fHasReadDstColor = true; GrGLGpu* gpu = fProgramBuilder->gpu(); if (gpu->glCaps().fbFetchSupport()) { this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1), gpu->glCaps().fbFetchExtensionString()); // On ES 3.0 we have to declare this, and use the custom color output name const char* fbFetchColorName = gpu->glCaps().fbFetchColorName(); if (gpu->glslGeneration() >= k330_GrGLSLGeneration) { this->enableCustomOutput(); fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier); fbFetchColorName = declared_color_output_name(); } return fbFetchColorName; } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) { return kDstCopyColorName; } else { return ""; } }
bool GrGLRenderTarget::completeStencilAttachment() { GrGLGpu* gpu = this->getGLGpu(); const GrGLInterface* interface = gpu->glInterface(); GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); if (nullptr == stencil) { GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT, GR_GL_RENDERBUFFER, 0)); GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT, GR_GL_RENDERBUFFER, 0)); #ifdef SK_DEBUG if (kChromium_GrGLDriver != gpu->glContext().driver()) { // This check can cause problems in Chromium if the context has been asynchronously // abandoned (see skbug.com/5200) GrGLenum status; GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status); } #endif return true; } else { const GrGLStencilAttachment* glStencil = static_cast<const GrGLStencilAttachment*>(stencil); GrGLuint rb = glStencil->renderbufferID(); gpu->invalidateBoundRenderTarget(); gpu->stats()->incRenderTargetBinds(); GR_GL_CALL(interface, BindFramebuffer(GR_GL_FRAMEBUFFER, this->renderFBOID())); GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT, GR_GL_RENDERBUFFER, rb)); if (glStencil->format().fPacked) { GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT, GR_GL_RENDERBUFFER, rb)); } else { GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_DEPTH_ATTACHMENT, GR_GL_RENDERBUFFER, 0)); } #ifdef SK_DEBUG if (kChromium_GrGLDriver != gpu->glContext().driver()) { // This check can cause problems in Chromium if the context has been asynchronously // abandoned (see skbug.com/5200) GrGLenum status; GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); SkASSERT(GR_GL_FRAMEBUFFER_COMPLETE == status); } #endif return true; } }
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo) { GrContext* ctx = ctxInfo.grContext(); if (!ctx->caps()->fenceSyncSupport()) { return; } const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType, kPremul_SkAlphaType); sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, ii, 0, kTopLeft_GrSurfaceOrigin, nullptr)); // Flush surface once without semaphores to make sure there is no peneding IO for it. mainSurface->flush(); GrBackendSemaphore semaphore; GrSemaphoresSubmitted submitted = mainSurface->flushAndSignalSemaphores(1, &semaphore); REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted); if (kOpenGL_GrBackend == ctxInfo.backend()) { GrGLGpu* gpu = static_cast<GrGLGpu*>(ctx->contextPriv().getGpu()); const GrGLInterface* interface = gpu->glInterface(); GrGLsync sync = semaphore.glSync(); REPORTER_ASSERT(reporter, sync); bool result; GR_GL_CALL_RET(interface, result, IsSync(sync)); REPORTER_ASSERT(reporter, result); } #ifdef SK_VULKAN if (kVulkan_GrBackend == ctxInfo.backend()) { GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->contextPriv().getGpu()); const GrVkInterface* interface = gpu->vkInterface(); VkDevice device = gpu->device(); VkQueue queue = gpu->queue(); VkCommandPool cmdPool = gpu->cmdPool(); VkCommandBuffer cmdBuffer; // Create Command Buffer const VkCommandBufferAllocateInfo cmdInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType nullptr, // pNext cmdPool, // commandPool VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 1 // bufferCount }; VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer)); if (err) { return; } VkCommandBufferBeginInfo cmdBufferBeginInfo; memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo)); cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufferBeginInfo.pNext = nullptr; cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; cmdBufferBeginInfo.pInheritanceInfo = nullptr; GR_VK_CALL_ERRCHECK(interface, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo)); GR_VK_CALL_ERRCHECK(interface, EndCommandBuffer(cmdBuffer)); VkFenceCreateInfo fenceInfo; VkFence fence; memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo)); fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence)); SkASSERT(!err); VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; VkSubmitInfo submitInfo; memset(&submitInfo, 0, sizeof(VkSubmitInfo)); submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.pNext = nullptr; submitInfo.waitSemaphoreCount = 1; VkSemaphore vkSem = semaphore.vkSemaphore(); submitInfo.pWaitSemaphores = &vkSem; submitInfo.pWaitDstStageMask = &waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cmdBuffer; submitInfo.signalSemaphoreCount = 0; submitInfo.pSignalSemaphores = nullptr; GR_VK_CALL_ERRCHECK(interface, QueueSubmit(queue, 1, &submitInfo, fence)); err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000)); REPORTER_ASSERT(reporter, err != VK_TIMEOUT); GR_VK_CALL(interface, DestroyFence(device, fence, nullptr)); GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr)); // If the above test fails the wait semaphore will never be signaled which can cause the // device to hang when tearing down (even if just tearing down GL). So we Fail here to // kill things. if (err == VK_TIMEOUT) { SK_ABORT("Waiting on semaphore indefinitely"); } } #endif }
GrContext* GrContextFactory::get(GLContextType type, GrGLStandard forcedGpuAPI) { for (int i = 0; i < fContexts.count(); ++i) { if (forcedGpuAPI != kNone_GrGLStandard && forcedGpuAPI != fContexts[i].fGLContext->gl()->fStandard) continue; if (fContexts[i].fType == type) { fContexts[i].fGLContext->makeCurrent(); return fContexts[i].fGrContext; } } SkAutoTUnref<SkGLContext> glCtx; SkAutoTUnref<GrContext> grCtx; switch (type) { case kNVPR_GLContextType: // fallthru case kNative_GLContextType: glCtx.reset(SkCreatePlatformGLContext(forcedGpuAPI)); break; #ifdef SK_ANGLE case kANGLE_GLContextType: glCtx.reset(SkANGLEGLContext::Create(forcedGpuAPI)); break; #endif #ifdef SK_MESA case kMESA_GLContextType: glCtx.reset(SkMesaGLContext::Create(forcedGpuAPI)); break; #endif case kNull_GLContextType: glCtx.reset(SkNullGLContext::Create(forcedGpuAPI)); break; case kDebug_GLContextType: glCtx.reset(SkDebugGLContext::Create(forcedGpuAPI)); break; } if (NULL == glCtx.get()) { return NULL; } SkASSERT(glCtx->isValid()); // Block NVPR from non-NVPR types. SkAutoTUnref<const GrGLInterface> glInterface(SkRef(glCtx->gl())); if (kNVPR_GLContextType != type) { glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface)); if (!glInterface) { return NULL; } } else { if (!glInterface->hasExtension("GL_NV_path_rendering")) { return NULL; } } glCtx->makeCurrent(); GrBackendContext p3dctx = reinterpret_cast<GrBackendContext>(glInterface.get()); grCtx.reset(GrContext::Create(kOpenGL_GrBackend, p3dctx, fGlobalOptions)); if (!grCtx.get()) { return NULL; } // Warn if path rendering support is not available for the NVPR type. if (kNVPR_GLContextType == type) { if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) { GrGLGpu* gpu = static_cast<GrGLGpu*>(grCtx->getGpu()); const GrGLubyte* verUByte; GR_GL_CALL_RET(gpu->glInterface(), verUByte, GetString(GR_GL_VERSION)); const char* ver = reinterpret_cast<const char*>(verUByte); SkDebugf("\nWARNING: nvprmsaa config requested, but driver path rendering support not" " available. Maybe update the driver? Your driver version string: \"%s\"\n", ver); } } GPUContext& ctx = fContexts.push_back(); ctx.fGLContext = glCtx.get(); ctx.fGLContext->ref(); ctx.fGrContext = grCtx.get(); ctx.fGrContext->ref(); ctx.fType = type; return ctx.fGrContext; }