Implement stencil clipping in mixed sampled render targets
This change enables multisampled clipping for mixed sampled render targets. Previously clipping in mixed samples config behaved the same as in the gpu config. In order to retrofit non-MSAA draw methods, programmable sample locations are used in order to colocate all samples at (0.5, 0.5). Requires support for NV_sample_locations. BUG=skia:4399 Review URL: https://codereview.chromium.org/1232103002
This commit is contained in:
parent
6634cbb427
commit
3e77ba96d5
@ -63,6 +63,7 @@ public:
|
||||
bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
|
||||
bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
|
||||
bool mixedSamplesSupport() const { return fMixedSamplesSupport; }
|
||||
bool programmableSampleLocationsSupport() const { return fProgrammableSampleLocationsSupport; }
|
||||
|
||||
/**
|
||||
* Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
|
||||
@ -93,6 +94,7 @@ protected:
|
||||
bool fDstReadInShaderSupport : 1;
|
||||
bool fDualSourceBlendingSupport : 1;
|
||||
bool fMixedSamplesSupport : 1;
|
||||
bool fProgrammableSampleLocationsSupport : 1;
|
||||
|
||||
bool fShaderPrecisionVaries;
|
||||
PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
|
||||
|
@ -390,6 +390,8 @@ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetVertexArrayIntegeri_vProc)(GrGLuin
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLGetVertexArrayPointeri_vProc)(GrGLuint vaobj, GrGLuint index, GrGLenum pname, GrGLvoid **param);
|
||||
typedef GrGLvoid* (GR_GL_FUNCTION_TYPE* GrGLMapNamedBufferRangeProc)(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr length, GrGLbitfield access);
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLFlushMappedNamedBufferRangeProc)(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr length);
|
||||
// OpenGL 4.5
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLNamedFramebufferParameteriProc)(GrGLuint framebuffer, GrGLenum pname, GrGLint param);
|
||||
|
||||
/* KHR_debug */
|
||||
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDebugMessageControlProc)(GrGLenum source, GrGLenum type, GrGLenum severity, GrGLsizei count, const GrGLuint* ids, GrGLboolean enabled);
|
||||
|
@ -490,6 +490,8 @@ public:
|
||||
GLPtr<GrGLGetVertexArrayPointeri_vProc> fGetVertexArrayPointeri_v;
|
||||
GLPtr<GrGLMapNamedBufferRangeProc> fMapNamedBufferRange;
|
||||
GLPtr<GrGLFlushMappedNamedBufferRangeProc> fFlushMappedNamedBufferRange;
|
||||
// OpenGL 4.5
|
||||
GLPtr<GrGLNamedFramebufferParameteriProc> fNamedFramebufferParameteri;
|
||||
|
||||
/* KHR_debug */
|
||||
GLPtr<GrGLDebugMessageControlProc> fDebugMessageControl;
|
||||
|
@ -16,6 +16,7 @@ GrShaderCaps::GrShaderCaps() {
|
||||
fDstReadInShaderSupport = false;
|
||||
fDualSourceBlendingSupport = false;
|
||||
fMixedSamplesSupport = false;
|
||||
fProgrammableSampleLocationsSupport = false;
|
||||
fShaderPrecisionVaries = false;
|
||||
}
|
||||
|
||||
@ -46,14 +47,15 @@ static const char* precision_to_string(GrSLPrecision p) {
|
||||
SkString GrShaderCaps::dump() const {
|
||||
SkString r;
|
||||
static const char* gNY[] = { "NO", "YES" };
|
||||
r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
|
||||
r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
|
||||
r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
|
||||
r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
|
||||
r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
|
||||
r.appendf("Mixed Samples Support : %s\n", gNY[fMixedSamplesSupport]);
|
||||
r.appendf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
|
||||
r.appendf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
|
||||
r.appendf("Path Rendering Support : %s\n", gNY[fPathRenderingSupport]);
|
||||
r.appendf("Dst Read In Shader Support : %s\n", gNY[fDstReadInShaderSupport]);
|
||||
r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
|
||||
r.appendf("Mixed Samples Support : %s\n", gNY[fMixedSamplesSupport]);
|
||||
r.appendf("Programmable Sample Locations Support : %s\n", gNY[fProgrammableSampleLocationsSupport]);
|
||||
|
||||
r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]);
|
||||
r.appendf("Shader Float Precisions (varies: %s) :\n", gNY[fShaderPrecisionVaries]);
|
||||
|
||||
for (int s = 0; s < kGrShaderTypeCount; ++s) {
|
||||
GrShaderType shaderType = static_cast<GrShaderType>(s);
|
||||
|
@ -306,7 +306,7 @@ bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
|
||||
}
|
||||
|
||||
// If MSAA is enabled we can do everything in the stencil buffer.
|
||||
if (0 == rt->numColorSamples() && requiresAA) {
|
||||
if (0 == rt->numStencilSamples() && requiresAA) {
|
||||
GrTexture* result = nullptr;
|
||||
|
||||
// The top-left of the mask corresponds to the top-left corner of the bounds.
|
||||
@ -757,7 +757,7 @@ bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
|
||||
pipelineBuilder.setDisableColorXPFactory();
|
||||
|
||||
// if the target is MSAA then we want MSAA enabled when the clip is soft
|
||||
if (rt->isUnifiedMultisampled()) {
|
||||
if (rt->isStencilBufferMultisampled()) {
|
||||
pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, element->isAA());
|
||||
}
|
||||
|
||||
|
@ -450,6 +450,10 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
|
||||
}
|
||||
}
|
||||
|
||||
if (glVer >= GR_GL_VER(4,5)) {
|
||||
GET_PROC(NamedFramebufferParameteri);
|
||||
}
|
||||
|
||||
if (glVer >= GR_GL_VER(4,3) || extensions.has("GL_KHR_debug")) {
|
||||
// KHR_debug defines these methods to have no suffix in an OpenGL (not ES) context.
|
||||
GET_PROC(DebugMessageControl);
|
||||
|
@ -355,6 +355,10 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
|
||||
fDiscardRenderTargetSupport = false;
|
||||
fInvalidateFBType = kNone_InvalidateFBType;
|
||||
}
|
||||
glslCaps->fProgrammableSampleLocationsSupport =
|
||||
ctxInfo.hasExtension("GL_NV_sample_locations") ||
|
||||
ctxInfo.hasExtension("GL_ARB_sample_locations");
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* GrCaps fields
|
||||
|
@ -889,6 +889,9 @@
|
||||
#define GR_GL_MULTISAMPLE_RASTERIZATION_ALLOWED 0x932B
|
||||
#define GR_GL_EFFECTIVE_RASTER_SAMPLES 0x932C
|
||||
|
||||
/* GL_NV_sample_locations and GL_ARB_sample_locations */
|
||||
#define GR_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS 0x9342
|
||||
|
||||
/* GL_KHR_debug */
|
||||
#define GR_GL_DEBUG_OUTPUT 0x92E0
|
||||
#define GR_GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
|
||||
|
@ -1476,7 +1476,7 @@ bool GrGLGpu::flushGLState(const DrawArgs& args) {
|
||||
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
|
||||
this->flushStencil(pipeline.getStencil());
|
||||
this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin());
|
||||
this->flushHWAAState(glRT, pipeline.isHWAntialiasState());
|
||||
this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled());
|
||||
|
||||
// This must come after textures are flushed because a texture may need
|
||||
// to be msaa-resolved (which will modify bound FBO state).
|
||||
@ -1899,6 +1899,22 @@ bool GrGLGpu::onReadPixels(GrSurface* surface,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLGpu::setColocatedSampleLocations(GrRenderTarget* rt, bool useColocatedSampleLocations) {
|
||||
GrGLRenderTarget* target = static_cast<GrGLRenderTarget*>(rt->asRenderTarget());
|
||||
SkASSERT(0 != target->renderFBOID());
|
||||
|
||||
if (!rt->isStencilBufferMultisampled() ||
|
||||
useColocatedSampleLocations == target->usesColocatedSampleLocations()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CALL(NamedFramebufferParameteri(target->renderFBOID(),
|
||||
GR_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS,
|
||||
useColocatedSampleLocations));
|
||||
|
||||
target->flagAsUsingColocatedSampleLocations(useColocatedSampleLocations);
|
||||
}
|
||||
|
||||
void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bound) {
|
||||
|
||||
SkASSERT(target);
|
||||
@ -2146,9 +2162,19 @@ void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) {
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA) {
|
||||
void GrGLGpu::flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled) {
|
||||
SkASSERT(!useHWAA || rt->isStencilBufferMultisampled());
|
||||
|
||||
if (rt->hasMixedSamples() && stencilEnabled &&
|
||||
this->glCaps().glslCaps()->programmableSampleLocationsSupport()) {
|
||||
if (useHWAA) {
|
||||
this->setColocatedSampleLocations(rt, false);
|
||||
} else {
|
||||
this->setColocatedSampleLocations(rt, true);
|
||||
}
|
||||
useHWAA = true;
|
||||
}
|
||||
|
||||
if (this->glCaps().multisampleDisableSupport()) {
|
||||
if (useHWAA) {
|
||||
if (kYes_TriState != fMSAAEnabled) {
|
||||
@ -2928,7 +2954,7 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
|
||||
this->flushBlend(blendInfo);
|
||||
this->flushColorWrite(true);
|
||||
this->flushDrawFace(GrPipelineBuilder::kBoth_DrawFace);
|
||||
this->flushHWAAState(dstRT, false);
|
||||
this->flushHWAAState(dstRT, false, false);
|
||||
this->disableScissor();
|
||||
GrStencilSettings stencil;
|
||||
stencil.setDisabled();
|
||||
|
@ -255,12 +255,16 @@ private:
|
||||
// ensures that such operations don't negatively interact with tracking bound textures.
|
||||
void setScratchTextureUnit();
|
||||
|
||||
// colocates all samples at pixel center for render target, if MSAA.
|
||||
// allows drawing coverage based AA shapes in MSAA mode.
|
||||
void setColocatedSampleLocations(GrRenderTarget* rt, bool useColocatedSampleLocations);
|
||||
|
||||
// bounds is region that may be modified and therefore has to be resolved.
|
||||
// nullptr means whole target. Can be an empty rect.
|
||||
void flushRenderTarget(GrGLRenderTarget*, const SkIRect* bounds);
|
||||
|
||||
void flushStencil(const GrStencilSettings&);
|
||||
void flushHWAAState(GrRenderTarget* rt, bool useHWAA);
|
||||
void flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled);
|
||||
|
||||
bool configToGLFormats(GrPixelConfig config,
|
||||
bool getSizedInternal,
|
||||
|
@ -701,6 +701,12 @@ bool GrGLInterface::validate() const {
|
||||
}
|
||||
}
|
||||
|
||||
if (kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,5)) {
|
||||
if (nullptr == fFunctions.fNamedFramebufferParameteri) {
|
||||
RETURN_FALSE_INTERFACE
|
||||
}
|
||||
}
|
||||
|
||||
if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
|
||||
fExtensions.has("GL_KHR_debug")) {
|
||||
if (nullptr == fFunctions.fDebugMessageControl ||
|
||||
|
@ -100,7 +100,7 @@ void GrGLPathRendering::onStencilPath(const StencilPathArgs& args, const GrPath*
|
||||
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->flushHWAAState(rt, args.fUseHWAA, true);
|
||||
gpu->flushRenderTarget(rt, nullptr);
|
||||
|
||||
const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
|
||||
|
@ -70,6 +70,21 @@ public:
|
||||
// components seperately.
|
||||
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
|
||||
|
||||
/**
|
||||
* @return true if sample locations colocated at pixel center have been set for this
|
||||
* render target. Requires support for NV_sample_locations.
|
||||
*/
|
||||
bool usesColocatedSampleLocations() const {
|
||||
return fUsesColocatedSampleLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag render target as using or not using sample locations colocated at pixel center.
|
||||
*/
|
||||
void flagAsUsingColocatedSampleLocations(bool useColocatedSampleLocations) {
|
||||
fUsesColocatedSampleLocations = useColocatedSampleLocations;
|
||||
}
|
||||
|
||||
protected:
|
||||
// The public constructor registers this object with the cache. However, only the most derived
|
||||
// class should register with the cache. This constructor does not do the registration and
|
||||
@ -116,6 +131,10 @@ private:
|
||||
// release zero out the IDs and the cache needs to know the size even after those actions.
|
||||
size_t fGpuMemorySize;
|
||||
|
||||
// True if sample locations colocated at pixel center are currently in use, false if default
|
||||
// sample locations are currently in use.
|
||||
bool fUsesColocatedSampleLocations;
|
||||
|
||||
typedef GrRenderTarget INHERITED;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user