diff options
-rw-r--r-- | bench/nanobench.cpp | 17 | ||||
-rw-r--r-- | include/gpu/GrCaps.h | 19 | ||||
-rw-r--r-- | include/gpu/gl/GrGLFunctions.h | 3 | ||||
-rw-r--r-- | include/gpu/gl/GrGLInterface.h | 3 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrSurfaceProxy.cpp | 2 | ||||
-rw-r--r-- | src/gpu/SkGr.cpp | 10 | ||||
-rw-r--r-- | src/gpu/SkGr.h | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGLAssembleInterface.cpp | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 55 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 6 | ||||
-rw-r--r-- | src/gpu/gl/GrGLDefines.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 6 | ||||
-rw-r--r-- | src/gpu/gl/GrGLInterface.cpp | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTestInterface.cpp | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTestInterface.h | 1 | ||||
-rw-r--r-- | src/gpu/gl/GrGLUtil.h | 6 | ||||
-rw-r--r-- | src/gpu/mock/GrMockCaps.h | 3 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.cpp | 59 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCaps.h | 5 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 4 | ||||
-rw-r--r-- | tests/GLProgramsTest.cpp | 2 | ||||
-rw-r--r-- | tests/GpuSampleLocationsTest.cpp | 3 | ||||
-rw-r--r-- | tests/ProxyTest.cpp | 9 | ||||
-rw-r--r-- | tests/ResourceCacheTest.cpp | 38 | ||||
-rw-r--r-- | tools/skpbench/skpbench.cpp | 12 |
27 files changed, 232 insertions, 59 deletions
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index 8cbaa2339a..7148bc26fd 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -61,6 +61,7 @@ extern bool gSkForceRasterPipelineBlitter; #include "GrCaps.h" #include "GrContextFactory.h" #include "gl/GrGLUtil.h" + #include "SkGr.h" using sk_gpu_test::GrContextFactory; using sk_gpu_test::TestContext; std::unique_ptr<GrContextFactory> gGrFactory; @@ -416,12 +417,16 @@ static void create_config(const SkCommandLineConfig* config, SkTArray<Config>* c const auto ctxType = gpuConfig->getContextType(); const auto ctxOverrides = gpuConfig->getContextOverrides(); const auto sampleCount = gpuConfig->getSamples(); + const auto colorType = gpuConfig->getColorType(); + auto colorSpace = gpuConfig->getColorSpace(); if (const GrContext* ctx = gGrFactory->get(ctxType, ctxOverrides)) { - const auto maxSampleCount = ctx->caps()->maxSampleCount(); - if (sampleCount > ctx->caps()->maxSampleCount()) { - SkDebugf("Configuration sample count %d exceeds maximum %d.\n", - sampleCount, maxSampleCount); + GrPixelConfig grPixConfig = SkImageInfo2GrPixelConfig(colorType, colorSpace, + *ctx->caps()); + int supportedSampleCount = ctx->caps()->getSampleCount(sampleCount, grPixConfig); + if (sampleCount != supportedSampleCount) { + SkDebugf("Configuration sample count %d is not a supported sample count.\n", + sampleCount); return; } } else { @@ -432,9 +437,9 @@ static void create_config(const SkCommandLineConfig* config, SkTArray<Config>* c Config target = { gpuConfig->getTag(), Benchmark::kGPU_Backend, - gpuConfig->getColorType(), + colorType, kPremul_SkAlphaType, - sk_ref_sp(gpuConfig->getColorSpace()), + sk_ref_sp(colorSpace), sampleCount, ctxType, ctxOverrides, diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h index cc24846091..a1a1826676 100644 --- a/include/gpu/GrCaps.h +++ b/include/gpu/GrCaps.h @@ -132,22 +132,11 @@ public: It is usually the max texture size, unless we're overriding it for testing. */ int maxTileSize() const { SkASSERT(fMaxTileSize <= fMaxTextureSize); return fMaxTileSize; } - // Will be 0 if MSAA is not supported - int maxColorSampleCount() const { return fMaxColorSampleCount; } - // Will be 0 if MSAA is not supported - int maxStencilSampleCount() const { return fMaxStencilSampleCount; } - // Will be 0 if raster multisample is not supported. Raster multisample is a special HW mode - // where the rasterizer runs with more samples than are in the target framebuffer. int maxRasterSamples() const { return fMaxRasterSamples; } - // We require the sample count to be less than maxColorSampleCount and maxStencilSampleCount. - // If we are using mixed samples, we only care about stencil. - int maxSampleCount() const { - if (this->usesMixedSamples()) { - return this->maxStencilSampleCount(); - } else { - return SkTMin(this->maxColorSampleCount(), this->maxStencilSampleCount()); - } - } + + // Find a sample count greater than or equal to the requested count which is supported for a + // color buffer of the given config. If MSAA is not support for the config we will return 0. + virtual int getSampleCount(int requestedCount, GrPixelConfig config) const = 0; int maxWindowRectangles() const { return fMaxWindowRectangles; } diff --git a/include/gpu/gl/GrGLFunctions.h b/include/gpu/gl/GrGLFunctions.h index 930a0c1aad..5166a4b099 100644 --- a/include/gpu/gl/GrGLFunctions.h +++ b/include/gpu/gl/GrGLFunctions.h @@ -357,6 +357,9 @@ typedef GrGLenum (GR_GL_FUNCTION_TYPE* GrGLClientWaitSyncProc)(GrGLsync sync, Gr typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLWaitSyncProc)(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDeleteSyncProc)(GrGLsync sync); +/* ARB_internalformat_query */ +typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetInternalformativProc)(GrGLenum target, GrGLenum internalformat, GrGLenum pname, GrGLsizei bufSize, GrGLint *params); + /* KHR_debug */ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDebugMessageControlProc)(GrGLenum source, GrGLenum type, GrGLenum severity, GrGLsizei count, const GrGLuint* ids, GrGLboolean enabled); typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDebugMessageInsertProc)(GrGLenum source, GrGLenum type, GrGLuint id, GrGLenum severity, GrGLsizei length, const GrGLchar* buf); diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h index e5479eb466..10880471ce 100644 --- a/include/gpu/gl/GrGLInterface.h +++ b/include/gpu/gl/GrGLInterface.h @@ -460,6 +460,9 @@ public: GrGLFunction<GrGLWaitSyncProc> fWaitSync; GrGLFunction<GrGLDeleteSyncProc> fDeleteSync; + /* ARB_internalforamt_query */ + GrGLFunction<GrGLGetInternalformativProc> fGetInternalformativ; + /* KHR_debug */ GrGLFunction<GrGLDebugMessageControlProc> fDebugMessageControl; GrGLFunction<GrGLDebugMessageInsertProc> fDebugMessageInsert; diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 0c227e3f32..ecf4398288 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -636,7 +636,8 @@ int GrContext::getRecommendedSampleCount(GrPixelConfig config, chosenSampleCount = 16; } } - return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0; + int supportedSampleCount = fGpu->caps()->getSampleCount(chosenSampleCount, config); + return chosenSampleCount <= supportedSampleCount ? supportedSampleCount : 0; } sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy, diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index cab5d15458..038ffef0cd 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -143,7 +143,7 @@ sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted return nullptr; } - desc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount()); + desc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig); // Attempt to catch un- or wrongly initialized sample counts. SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64); diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp index b07366265c..f300770690 100644 --- a/src/gpu/GrSurfaceProxy.cpp +++ b/src/gpu/GrSurfaceProxy.cpp @@ -185,7 +185,7 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceP } GrSurfaceDesc copyDesc = desc; - copyDesc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount()); + copyDesc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig); if (willBeRT) { // We know anything we instantiate later from this deferred path will be diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 6d8e46ddca..af0a55a156 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -308,11 +308,11 @@ GrColor4f SkColorToUnpremulGrColor4f(SkColor c, SkColorSpace* dstColorSpace, /////////////////////////////////////////////////////////////////////////////// -GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) { +GrPixelConfig SkImageInfo2GrPixelConfig(const SkColorType type, SkColorSpace* cs, + const GrCaps& caps) { // We intentionally ignore profile type for non-8888 formats. Anything we can't support // in hardware will be expanded to sRGB 8888 in GrUploadPixmapToTexture. - SkColorSpace* cs = info.colorSpace(); - switch (info.colorType()) { + switch (type) { case kUnknown_SkColorType: return kUnknown_GrPixelConfig; case kAlpha_8_SkColorType: @@ -336,6 +336,10 @@ GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& c return kUnknown_GrPixelConfig; } +GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) { + return SkImageInfo2GrPixelConfig(info.colorType(), info.colorSpace(), caps); +} + bool GrPixelConfigToColorType(GrPixelConfig config, SkColorType* ctOut) { SkColorType ct; switch (config) { diff --git a/src/gpu/SkGr.h b/src/gpu/SkGr.h index 3ed82a8523..1f7f2ad425 100644 --- a/src/gpu/SkGr.h +++ b/src/gpu/SkGr.h @@ -151,6 +151,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context, // Misc Sk to Gr type conversions GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo&, const GrCaps&); +GrPixelConfig SkImageInfo2GrPixelConfig(const SkColorType, SkColorSpace*, const GrCaps& caps); GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps); bool GrPixelConfigToColorType(GrPixelConfig, SkColorType*); diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp index d61b38bbed..64bed32136 100644 --- a/src/gpu/gl/GrGLAssembleInterface.cpp +++ b/src/gpu/gl/GrGLAssembleInterface.cpp @@ -529,6 +529,11 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) { GET_PROC(MemoryBarrierByRegion); } + + if (glVer >= GR_GL_VER(4,2) || extensions.has("GL_ARB_internalformat_query")) { + GET_PROC(GetInternalformativ); + } + interface->fStandard = kGL_GrGLStandard; interface->fExtensions.swap(&extensions); @@ -951,6 +956,10 @@ const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) { GET_PROC(MemoryBarrierByRegion); } + if (version >= GR_GL_VER(3,0)) { + GET_PROC(GetInternalformativ); + } + interface->fStandard = kGLES_GrGLStandard; interface->fExtensions.swap(&extensions); diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index a7ec88ea87..766b438d2b 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -2109,6 +2109,46 @@ void GrGLCaps::initConfigTable(const GrContextOptions& contextOptions, } } + bool hasInternalformatFunction = gli->fFunctions.fGetInternalformativ != nullptr; + for (int i = 0; i < kGrPixelConfigCnt; ++i) { + if (ConfigInfo::kRenderableWithMSAA_Flag & fConfigTable[i].fFlags) { + if (hasInternalformatFunction && // This check is temporary until chrome is updated + ((kGL_GrGLStandard == ctxInfo.standard() && + (ctxInfo.version() >= GR_GL_VER(4,2) || + ctxInfo.hasExtension("GL_ARB_internalformat_query"))) || + (kGLES_GrGLStandard == ctxInfo.standard() && ctxInfo.version() >= GR_GL_VER(3,0)))) { + int count; + GrGLenum format = fConfigTable[i].fFormats.fInternalFormatRenderbuffer; + GR_GL_GetInternalformativ(gli, GR_GL_RENDERBUFFER, format, GR_GL_NUM_SAMPLE_COUNTS, + 1, &count); + if (count) { + int* temp = new int[count]; + GR_GL_GetInternalformativ(gli, GR_GL_RENDERBUFFER, format, GR_GL_SAMPLES, count, + temp); + fConfigTable[i].fColorSampleCounts.setCount(count+1); + // We initialize our supported values with 0 (no msaa) and reverse the order + // returned by GL so that the array is ascending. + fConfigTable[i].fColorSampleCounts[0] = 0; + for (int j = 0; j < count; ++j) { + fConfigTable[i].fColorSampleCounts[j+1] = temp[count - j - 1]; + } + delete[] temp; + } + } else { + static const int kDefaultSamples[] = {0,1,2,4,8}; + int count = SK_ARRAY_COUNT(kDefaultSamples); + for (; count > 0; --count) { + if (kDefaultSamples[count-i] <= fMaxColorSampleCount) { + break; + } + } + if (count > 0) { + fConfigTable[i].fColorSampleCounts.append(count, kDefaultSamples); + } + } + } + } + #ifdef SK_DEBUG // Make sure we initialized everything. ConfigInfo defaultEntry; @@ -2231,3 +2271,18 @@ void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) { fUseDrawInsteadOfAllRenderTargetWrites = true; } } + +int GrGLCaps::getSampleCount(int requestedCount, GrPixelConfig config) const { + int count = fConfigTable[config].fColorSampleCounts.count(); + if (!count || !this->isConfigRenderable(config, true)) { + return 0; + } + + for (int i = 0; i < count; ++i) { + if (fConfigTable[config].fColorSampleCounts[i] >= requestedCount) { + return fConfigTable[config].fColorSampleCounts[i]; + } + } + return fConfigTable[config].fColorSampleCounts[count-1]; +} + diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 43da5f86cd..707c65e13d 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -112,6 +112,8 @@ public: GrGLCaps(const GrContextOptions& contextOptions, const GrGLContextInfo& ctxInfo, const GrGLInterface* glInterface); + int getSampleCount(int requestedCount, GrPixelConfig config) const override; + bool isConfigTexturable(GrPixelConfig config) const override { return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kTextureable_Flag); } @@ -529,7 +531,9 @@ private: }; // Index fStencilFormats. - int fStencilFormatIndex; + int fStencilFormatIndex; + + SkTDArray<int> fColorSampleCounts; enum { kVerifiedColorAttachment_Flag = 0x1, diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h index a986ce80c3..b62c26bcc2 100644 --- a/src/gpu/gl/GrGLDefines.h +++ b/src/gpu/gl/GrGLDefines.h @@ -1065,6 +1065,9 @@ /* GL_EXT_geometry_shader */ #define GR_GL_LINES_ADJACENCY 0x000A +/* GL_ARB_internalformat_query */ +#define GR_GL_NUM_SAMPLE_COUNTS 0x9380 + /* EGL Defines */ #define GR_EGL_NO_DISPLAY ((GrEGLDisplay)0) #define GR_EGL_EXTENSIONS 0x3055 diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index a73f97c97f..b310df4f7a 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -572,7 +572,7 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTe surfDesc.fWidth = backendTex.width(); surfDesc.fHeight = backendTex.height(); surfDesc.fConfig = backendTex.config(); - surfDesc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount()); + surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config()); // FIXME: this should be calling resolve_origin(), but Chrome code is currently // assuming the old behaviour, which is that backend textures are always // BottomLeft, even for non-RT's. Once Chrome is fixed, change this to: @@ -616,7 +616,7 @@ sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTa desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fWidth = backendRT.width(); desc.fHeight = backendRT.height(); - desc.fSampleCnt = SkTMin(backendRT.sampleCnt(), this->caps()->maxSampleCount()); + desc.fSampleCnt = this->caps()->getSampleCount(backendRT.sampleCnt(), backendRT.config()); SkASSERT(kDefault_GrSurfaceOrigin != origin); desc.fOrigin = origin; @@ -647,7 +647,7 @@ sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBacken surfDesc.fWidth = tex.width(); surfDesc.fHeight = tex.height(); surfDesc.fConfig = tex.config(); - surfDesc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount()); + surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, tex.config()); // FIXME: this should be calling resolve_origin(), but Chrome code is currently // assuming the old behaviour, which is that backend textures are always // BottomLeft, even for non-RT's. Once Chrome is fixed, change this to: diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp index a71127f577..09d7a4fad3 100644 --- a/src/gpu/gl/GrGLInterface.cpp +++ b/src/gpu/gl/GrGLInterface.cpp @@ -808,5 +808,14 @@ bool GrGLInterface::validate() const { } } + // getInternalformativ was added in GL 4.2, ES 3.0, and with extension ARB_internalformat_query + if ((kGL_GrGLStandard == fStandard && + (glVer >= GR_GL_VER(4,2) || fExtensions.has("GL_ARB_internalformat_query"))) || + (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0))) { + if (nullptr == fFunctions.fGetInternalformativ) { + // RETURN_FALSE_INTERFACE; + } + } + return true; } diff --git a/src/gpu/gl/GrGLTestInterface.cpp b/src/gpu/gl/GrGLTestInterface.cpp index 25d66a94fc..ef86ea71b9 100644 --- a/src/gpu/gl/GrGLTestInterface.cpp +++ b/src/gpu/gl/GrGLTestInterface.cpp @@ -324,4 +324,5 @@ GrGLTestInterface::GrGLTestInterface() { fFunctions.fPushDebugGroup = bind_to_member(this, &GrGLTestInterface::pushDebugGroup); fFunctions.fPopDebugGroup = bind_to_member(this, &GrGLTestInterface::popDebugGroup); fFunctions.fObjectLabel = bind_to_member(this, &GrGLTestInterface::objectLabel); + fFunctions.fGetInternalformativ = bind_to_member(this, &GrGLTestInterface::getInternalformativ); } diff --git a/src/gpu/gl/GrGLTestInterface.h b/src/gpu/gl/GrGLTestInterface.h index 636f493037..69427f8d5a 100644 --- a/src/gpu/gl/GrGLTestInterface.h +++ b/src/gpu/gl/GrGLTestInterface.h @@ -329,6 +329,7 @@ public: virtual GrGLvoid pushDebugGroup(GrGLenum source, GrGLuint id, GrGLsizei length, const GrGLchar * message) {} virtual GrGLvoid popDebugGroup() {} virtual GrGLvoid objectLabel(GrGLenum identifier, GrGLuint name, GrGLsizei length, const GrGLchar *label) {} + virtual GrGLvoid getInternalformativ(GrGLenum target, GrGLenum internalformat, GrGLenum pname, GrGLsizei bufSize, GrGLint *params) {} protected: // This must be called by leaf class diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h index b798385cf6..834b68204b 100644 --- a/src/gpu/gl/GrGLUtil.h +++ b/src/gpu/gl/GrGLUtil.h @@ -90,6 +90,12 @@ enum GrGLDriver { GR_GL_CALL(gl, GetFramebufferAttachmentParameteriv(t, a, pname, p)); \ } while (0) +#define GR_GL_GetInternalformativ(gl, t, f, n, s, p) \ + do { \ + *(p) = GR_GL_INIT_ZERO; \ + GR_GL_CALL(gl, GetInternalformativ(t, f, n, s, p)); \ + } while (0) + #define GR_GL_GetNamedFramebufferAttachmentParameteriv(gl, fb, a, pname, p) \ do { \ *(p) = GR_GL_INIT_ZERO; \ diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h index 721ac83142..b1d9a84bcf 100644 --- a/src/gpu/mock/GrMockCaps.h +++ b/src/gpu/mock/GrMockCaps.h @@ -22,6 +22,9 @@ public: fShaderCaps.reset(new GrShaderCaps(contextOptions)); this->applyOptionsOverrides(contextOptions); } + int getSampleCount(int /*requestCount*/, GrPixelConfig /*config*/) const override { + return 0; + } bool isConfigTexturable(GrPixelConfig config) const override { return fOptions.fConfigOptions[config].fTexturable; } diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp index db926179be..909b4fbd4c 100644 --- a/src/gpu/vk/GrVkCaps.cpp +++ b/src/gpu/vk/GrVkCaps.cpp @@ -340,6 +340,47 @@ void GrVkCaps::ConfigInfo::InitConfigFlags(VkFormatFeatureFlags vkFlags, uint16_ } } +void GrVkCaps::ConfigInfo::initSampleCounts(const GrVkInterface* interface, + VkPhysicalDevice physDev, + VkFormat format) { + VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT | + VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + VkImageCreateFlags createFlags = GrVkFormatIsSRGB(format, nullptr) + ? VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT : 0; + VkImageFormatProperties properties; + GR_VK_CALL(interface, GetPhysicalDeviceImageFormatProperties(physDev, + format, + VK_IMAGE_TYPE_2D, + VK_IMAGE_TILING_OPTIMAL, + usage, + createFlags, + &properties)); + VkSampleCountFlags flags = properties.sampleCounts; + if (flags & VK_SAMPLE_COUNT_1_BIT) { + fColorSampleCounts.push(0); + } + if (flags & VK_SAMPLE_COUNT_2_BIT) { + fColorSampleCounts.push(2); + } + if (flags & VK_SAMPLE_COUNT_4_BIT) { + fColorSampleCounts.push(4); + } + if (flags & VK_SAMPLE_COUNT_8_BIT) { + fColorSampleCounts.push(8); + } + if (flags & VK_SAMPLE_COUNT_16_BIT) { + fColorSampleCounts.push(16); + } + if (flags & VK_SAMPLE_COUNT_32_BIT) { + fColorSampleCounts.push(32); + } + if (flags & VK_SAMPLE_COUNT_64_BIT) { + fColorSampleCounts.push(64); + } +} + void GrVkCaps::ConfigInfo::init(const GrVkInterface* interface, VkPhysicalDevice physDev, VkFormat format) { @@ -348,4 +389,22 @@ void GrVkCaps::ConfigInfo::init(const GrVkInterface* interface, GR_VK_CALL(interface, GetPhysicalDeviceFormatProperties(physDev, format, &props)); InitConfigFlags(props.linearTilingFeatures, &fLinearFlags); InitConfigFlags(props.optimalTilingFeatures, &fOptimalFlags); + if (fOptimalFlags & kRenderable_Flag) { + this->initSampleCounts(interface, physDev, format); + } } + +int GrVkCaps::getSampleCount(int requestedCount, GrPixelConfig config) const { + int count = fConfigTable[config].fColorSampleCounts.count(); + if (!count || !this->isConfigRenderable(config, true)) { + return 0; + } + + for (int i = 0; i < count; ++i) { + if (fConfigTable[config].fColorSampleCounts[i] >= requestedCount) { + return fConfigTable[config].fColorSampleCounts[i]; + } + } + return fConfigTable[config].fColorSampleCounts[count-1]; +} + diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h index f599d22cb5..b0854867c8 100644 --- a/src/gpu/vk/GrVkCaps.h +++ b/src/gpu/vk/GrVkCaps.h @@ -29,6 +29,8 @@ public: GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface* vkInterface, VkPhysicalDevice device, uint32_t featureFlags, uint32_t extensionFlags); + int getSampleCount(int requestedCount, GrPixelConfig config) const override; + bool isConfigTexturable(GrPixelConfig config) const override { return SkToBool(ConfigInfo::kTextureable_Flag & fConfigTable[config].fOptimalFlags); } @@ -132,6 +134,7 @@ private: void init(const GrVkInterface*, VkPhysicalDevice, VkFormat); static void InitConfigFlags(VkFormatFeatureFlags, uint16_t* flags); + void initSampleCounts(const GrVkInterface*, VkPhysicalDevice, VkFormat); enum { kTextureable_Flag = 0x1, @@ -142,6 +145,8 @@ private: uint16_t fOptimalFlags; uint16_t fLinearFlags; + + SkTDArray<int> fColorSampleCounts; }; ConfigInfo fConfigTable[kGrPixelConfigCnt]; diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 17fccfb1bb..cd0fc99b4b 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -882,7 +882,7 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTe surfDesc.fWidth = backendTex.width(); surfDesc.fHeight = backendTex.height(); surfDesc.fConfig = backendTex.config(); - surfDesc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount()); + surfDesc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, backendTex.config()); bool renderTarget = SkToBool(flags & kRenderTarget_GrBackendTextureFlag); // In GL, Chrome assumes all textures are BottomLeft // In VK, we don't have this restriction @@ -948,7 +948,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBacken desc.fConfig = tex.config(); desc.fWidth = tex.width(); desc.fHeight = tex.height(); - desc.fSampleCnt = SkTMin(sampleCnt, this->caps()->maxSampleCount()); + desc.fSampleCnt = this->caps()->getSampleCount(sampleCnt, tex.config()); desc.fOrigin = resolve_origin(origin); diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 178676431f..f8cb6efb67 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -145,7 +145,7 @@ static sk_sp<GrRenderTargetContext> random_render_target_context(GrContext* cont const GrCaps* caps) { GrSurfaceOrigin origin = random->nextBool() ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin; - int sampleCnt = random->nextBool() ? SkTMin(4, caps->maxSampleCount()) : 0; + int sampleCnt = random->nextBool() ? caps->getSampleCount(4, kRGBA_8888_GrPixelConfig) : 0; sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext( SkBackingFit::kExact, diff --git a/tests/GpuSampleLocationsTest.cpp b/tests/GpuSampleLocationsTest.cpp index ff87a33725..6c5d4a6d37 100644 --- a/tests/GpuSampleLocationsTest.cpp +++ b/tests/GpuSampleLocationsTest.cpp @@ -189,7 +189,8 @@ DEF_GPUTEST(GLSampleLocations, reporter, /*factory*/) { sk_sp<GrContext> ctx(GrContext::Create(kOpenGL_GrBackend, testInterface)); // This test relies on at least 2 samples. - if (ctx->caps()->maxSampleCount() < 2) { + int supportedSample = ctx->caps()->getSampleCount(2, kRGBA_8888_GrPixelConfig); + if (supportedSample < 2) { return; } test_sampleLocations(reporter, &testInterface, ctx.get()); diff --git a/tests/ProxyTest.cpp b/tests/ProxyTest.cpp index f9cefc5b89..c2a7734901 100644 --- a/tests/ProxyTest.cpp +++ b/tests/ProxyTest.cpp @@ -157,9 +157,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DeferredProxyTest, reporter, ctxInfo) { check_surface(reporter, proxy.get(), origin, widthHeight, widthHeight, config, kInvalidResourceID, budgeted); + int supportedSamples = caps.getSampleCount(numSamples, config); check_rendertarget(reporter, caps, provider, proxy->asRenderTargetProxy(), - SkTMin(numSamples, caps.maxSampleCount()), + supportedSamples, fit, caps.maxWindowRectangles(), false); } } @@ -214,9 +215,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) { for (auto config : { kAlpha_8_GrPixelConfig, kRGBA_8888_GrPixelConfig }) { for (auto budgeted : { SkBudgeted::kYes, SkBudgeted::kNo }) { for (auto numSamples: { 0, 4}) { - if (caps.maxSampleCount() < numSamples) { - continue; - } + int supportedNumSamples = caps.getSampleCount(numSamples, config); bool renderable = caps.isConfigRenderable(config, numSamples > 0); @@ -225,7 +224,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(WrappedProxyTest, reporter, ctxInfo) { desc.fWidth = kWidthHeight; desc.fHeight = kWidthHeight; desc.fConfig = config; - desc.fSampleCnt = numSamples; + desc.fSampleCnt = supportedNumSamples; // External on-screen render target. if (renderable && kOpenGL_GrBackend == ctxInfo.backend()) { diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index 83d316fcbc..50ddd00e8a 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -150,10 +150,11 @@ DEF_GPUTEST_FOR_CONTEXTS(ResourceCacheStencilBuffers, &is_rendering_and_not_angl resourceProvider->attachStencilAttachment(smallRT0->asRenderTarget()) != resourceProvider->attachStencilAttachment(bigRT->asRenderTarget())); - if (context->caps()->maxSampleCount() >= 4) { + int supportedSampleCount = context->caps()->getSampleCount(4, smallDesc.fConfig); + if (supportedSampleCount > 0) { // An RT with a different sample count should not share. GrSurfaceDesc smallMSAADesc = smallDesc; - smallMSAADesc.fSampleCnt = 4; + smallMSAADesc.fSampleCnt = supportedSampleCount; sk_sp<GrTexture> smallMSAART0(resourceProvider->createTexture(smallMSAADesc, SkBudgeted::kNo)); if (smallMSAART0 && smallMSAART0->asRenderTarget()) { @@ -184,10 +185,10 @@ DEF_GPUTEST_FOR_CONTEXTS(ResourceCacheStencilBuffers, &is_rendering_and_not_angl resourceProvider->attachStencilAttachment(smallMSAART1->asRenderTarget())); // But not one with a larger sample count should not. (Also check that the request for 4 // samples didn't get rounded up to >= 8 or else they could share.). - if (context->caps()->maxSampleCount() >= 8 && - smallMSAART0 && smallMSAART0->asRenderTarget() && - smallMSAART0->asRenderTarget()->numColorSamples() < 8) { - smallMSAADesc.fSampleCnt = 8; + supportedSampleCount = context->caps()->getSampleCount(8, smallDesc.fConfig); + if (supportedSampleCount != smallMSAADesc.fSampleCnt && + smallMSAART0 && smallMSAART0->asRenderTarget()) { + smallMSAADesc.fSampleCnt = supportedSampleCount; smallMSAART1 = resourceProvider->createTexture(smallMSAADesc, SkBudgeted::kNo); sk_sp<GrTexture> smallMSAART1( resourceProvider->createTexture(smallMSAADesc, SkBudgeted::kNo)); @@ -1700,12 +1701,15 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) { size_t size = tex->gpuMemorySize(); REPORTER_ASSERT(reporter, kSize*kSize*4 == size); - if (context->caps()->maxSampleCount() >= 4) { - tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 4); + size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig); + if (sampleCount >= 4) { + tex = make_normal_texture(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, + sampleCount); size = tex->gpuMemorySize(); - REPORTER_ASSERT(reporter, kSize*kSize*4 == size || // msaa4 failed - kSize*kSize*4*4 == size || // auto-resolving - kSize*kSize*4*5 == size); // explicit resolve buffer + REPORTER_ASSERT(reporter, + kSize*kSize*4 == size || // msaa4 failed + kSize*kSize*4*sampleCount == size || // auto-resolving + kSize*kSize*4*(sampleCount+1) == size); // explicit resolve buffer } tex = make_normal_texture(provider, kNone_GrSurfaceFlags, kSize, kSize, 0); @@ -1722,13 +1726,15 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GPUMemorySize, reporter, ctxInfo) { size_t size = proxy->gpuMemorySize(); REPORTER_ASSERT(reporter, kSize*kSize*4+(kSize*kSize*4)/3 == size); - if (context->caps()->maxSampleCount() >= 4) { - proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, 4); + size_t sampleCount = (size_t)context->caps()->getSampleCount(4, kRGBA_8888_GrPixelConfig); + if (sampleCount >= 4) { + proxy = make_mipmap_proxy(provider, kRenderTarget_GrSurfaceFlag, kSize, kSize, + sampleCount); size = proxy->gpuMemorySize(); REPORTER_ASSERT(reporter, - kSize*kSize*4+(kSize*kSize*4)/3 == size || // msaa4 failed - kSize*kSize*4*4+(kSize*kSize*4)/3 == size || // auto-resolving - kSize*kSize*4*5+(kSize*kSize*4)/3 == size); // explicit resolve buffer + kSize*kSize*4+(kSize*kSize*4)/3 == size || // msaa4 failed + kSize*kSize*4*sampleCount+(kSize*kSize*4)/3 == size || // auto-resolving + kSize*kSize*4*(sampleCount+1)+(kSize*kSize*4)/3 == size); // explicit resolve buffer } proxy = make_mipmap_proxy(provider, kNone_GrSurfaceFlags, kSize, kSize, 0); diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp index 8898da25d5..c0ead46155 100644 --- a/tools/skpbench/skpbench.cpp +++ b/tools/skpbench/skpbench.cpp @@ -7,6 +7,8 @@ #include "GpuTimer.h" #include "GrContextFactory.h" +#include "SkGr.h" + #include "SkCanvas.h" #include "SkCommonFlagsPathRenderer.h" #include "SkOSFile.h" @@ -287,9 +289,13 @@ int main(int argc, char** argv) { exitf(ExitErr::kUnavailable, "render target size %ix%i not supported by platform (max: %i)", width, height, ctx->caps()->maxRenderTargetSize()); } - if (ctx->caps()->maxSampleCount() < config->getSamples()) { - exitf(ExitErr::kUnavailable, "sample count %i not supported by platform (max: %i)", - config->getSamples(), ctx->caps()->maxSampleCount()); + GrPixelConfig grPixConfig = SkImageInfo2GrPixelConfig(config->getColorType(), + config->getColorSpace(), + *ctx->caps()); + int supportedSampleCount = ctx->caps()->getSampleCount(config->getSamples(), grPixConfig); + if (supportedSampleCount != config->getSamples()) { + exitf(ExitErr::kUnavailable, "sample count %i not supported by platform", + config->getSamples()); } sk_gpu_test::TestContext* testCtx = ctxInfo.testContext(); if (!testCtx) { |