Revert "Revert "Reland "Add ability to specify different GP textures for each mesh in a draw."""
This reverts commit cd7907b57d7624c9bb60cd914d175ed72d9b1365.
Readds optimization to draw single texture quads using GrPrimitiveType::kTriangles, non-indexed.
Removes disable on NVIDIA/VK as bounds issue was fixed here:
https://skia.googlesource.com/skia/+/c525d4f7101715d728fca1b7fd7f170115994646
Change-Id: Icbea3de0382c68318db8ecffb2244bc4c5fe84ad
Reviewed-on: https://skia-review.googlesource.com/155500
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index f8546c9..2fa332f 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -586,6 +586,8 @@
fHalfFloatVertexAttributeSupport = true;
}
+ fDynamicStateArrayGeometryProcessorTextureSupport = true;
+
if (kGL_GrGLStandard == standard) {
if (version >= GR_GL_VER(4, 1)) {
fProgramBinarySupport = true;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index fda222a..b5ee46e 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1672,9 +1672,11 @@
}
}
-void GrGLGpu::generateMipmapsForProcessorTextures(const GrPrimitiveProcessor& primProc,
- const GrPipeline& pipeline,
- const GrTextureProxy* const primProcTextures[]) {
+void GrGLGpu::resolveAndGenerateMipMapsForProcessorTextures(
+ const GrPrimitiveProcessor& primProc,
+ const GrPipeline& pipeline,
+ const GrTextureProxy* const primProcTextures[],
+ int numPrimitiveProcessorTextureSets) {
auto genLevelsIfNeeded = [this](GrTexture* tex, const GrSamplerState& sampler) {
SkASSERT(tex);
if (sampler.filter() == GrSamplerState::Filter::kMipMap &&
@@ -1682,12 +1684,19 @@
tex->texturePriv().mipMapsAreDirty()) {
SkASSERT(this->caps()->mipMapSupport());
this->regenerateMipMapLevels(static_cast<GrGLTexture*>(tex));
+ SkASSERT(!tex->asRenderTarget() || !tex->asRenderTarget()->needsResolve());
+ } else if (auto* rt = tex->asRenderTarget()) {
+ if (rt->needsResolve()) {
+ this->resolveRenderTarget(rt);
+ }
}
};
- for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
- GrTexture* tex = primProcTextures[i]->peekTexture();
- genLevelsIfNeeded(tex, primProc.textureSampler(i).samplerState());
+ for (int set = 0, tex = 0; set < numPrimitiveProcessorTextureSets; ++set) {
+ for (int sampler = 0; sampler < primProc.numTextureSamplers(); ++sampler, ++tex) {
+ GrTexture* texture = primProcTextures[tex]->peekTexture();
+ genLevelsIfNeeded(texture, primProc.textureSampler(sampler).samplerState());
+ }
}
GrFragmentProcessor::Iter iter(pipeline);
@@ -1702,17 +1711,26 @@
bool GrGLGpu::flushGLState(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
const GrPipeline::FixedDynamicState* fixedDynamicState,
+ const GrPipeline::DynamicStateArrays* dynamicStateArrays,
+ int dynamicStateArraysLength,
bool willDrawPoints) {
sk_sp<GrGLProgram> program(fProgramCache->refProgram(this, primProc, pipeline, willDrawPoints));
if (!program) {
GrCapsDebugf(this->caps(), "Failed to create program!\n");
return false;
}
- const GrTextureProxy* const* primProcProxies = nullptr;
- if (fixedDynamicState) {
- primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures;
+ const GrTextureProxy* const* primProcProxiesForMipRegen = nullptr;
+ const GrTextureProxy* const* primProcProxiesToBind = nullptr;
+ int numPrimProcTextureSets = 1; // number of texture per prim proc sampler.
+ if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
+ primProcProxiesForMipRegen = dynamicStateArrays->fPrimitiveProcessorTextures;
+ numPrimProcTextureSets = dynamicStateArraysLength;
+ } else if (fixedDynamicState && fixedDynamicState->fPrimitiveProcessorTextures) {
+ primProcProxiesForMipRegen = fixedDynamicState->fPrimitiveProcessorTextures;
+ primProcProxiesToBind = fixedDynamicState->fPrimitiveProcessorTextures;
}
- this->generateMipmapsForProcessorTextures(primProc, pipeline, primProcProxies);
+ this->resolveAndGenerateMipMapsForProcessorTextures(
+ primProc, pipeline, primProcProxiesForMipRegen, numPrimProcTextureSets);
GrXferProcessor::BlendInfo blendInfo;
pipeline.getXferProcessor().getBlendInfo(&blendInfo);
@@ -1729,7 +1747,7 @@
this->flushBlend(blendInfo, swizzle);
}
- fHWProgram->updateUniformsAndTextureBindings(primProc, pipeline, primProcProxies);
+ fHWProgram->updateUniformsAndTextureBindings(primProc, pipeline, primProcProxiesToBind);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.renderTarget());
GrStencilSettings stencil;
@@ -2271,30 +2289,40 @@
break;
}
}
- if (!this->flushGLState(primProc, pipeline, fixedDynamicState, hasPoints)) {
+ if (!this->flushGLState(primProc, pipeline, fixedDynamicState, dynamicStateArrays, meshCount,
+ hasPoints)) {
return;
}
- bool dynamicScissor =
- pipeline.isScissorEnabled() && dynamicStateArrays && dynamicStateArrays->fScissorRects;
- for (int i = 0; i < meshCount; ++i) {
+ bool dynamicScissor = false;
+ bool dynamicPrimProcTextures = false;
+ if (dynamicStateArrays) {
+ dynamicScissor = pipeline.isScissorEnabled() && dynamicStateArrays->fScissorRects;
+ dynamicPrimProcTextures = dynamicStateArrays->fPrimitiveProcessorTextures;
+ }
+ for (int m = 0; m < meshCount; ++m) {
if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
this->xferBarrier(pipeline.renderTarget(), barrierType);
}
if (dynamicScissor) {
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.renderTarget());
- this->flushScissor(GrScissorState(dynamicStateArrays->fScissorRects[i]),
+ this->flushScissor(GrScissorState(dynamicStateArrays->fScissorRects[m]),
glRT->getViewport(), pipeline.proxy()->origin());
}
+ if (dynamicPrimProcTextures) {
+ auto texProxyArray = dynamicStateArrays->fPrimitiveProcessorTextures +
+ m * primProc.numTextureSamplers();
+ fHWProgram->updatePrimitiveProcessorTextureBindings(primProc, texProxyArray);
+ }
if (this->glCaps().requiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines() &&
- GrIsPrimTypeLines(meshes[i].primitiveType()) &&
+ GrIsPrimTypeLines(meshes[m].primitiveType()) &&
!GrIsPrimTypeLines(fLastPrimitiveType)) {
GL_CALL(Enable(GR_GL_CULL_FACE));
GL_CALL(Disable(GR_GL_CULL_FACE));
}
- meshes[i].sendToGpu(this);
- fLastPrimitiveType = meshes[i].primitiveType();
+ meshes[m].sendToGpu(this);
+ fLastPrimitiveType = meshes[m].primitiveType();
}
#if SWAP_PER_DRAW
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 6b01d65..295ca42 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -251,14 +251,22 @@
void setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]);
- void generateMipmapsForProcessorTextures(
+ /**
+ * primitiveProcessorTextures must contain GrPrimitiveProcessor::numTextureSamplers() *
+ * numPrimitiveProcessorTextureSets entries.
+ */
+ void resolveAndGenerateMipMapsForProcessorTextures(
const GrPrimitiveProcessor&, const GrPipeline&,
- const GrTextureProxy* const primitiveProcessorTextures[]);
+ const GrTextureProxy* const primitiveProcessorTextures[],
+ int numPrimitiveProcessorTextureSets);
// Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
// willDrawPoints must be true if point primitives will be rendered after setting the GL state.
+ // If DynamicStateArrays is not null then dynamicStateArraysLength is the number of dynamic
+ // state entries in each array.
bool flushGLState(const GrPrimitiveProcessor&, const GrPipeline&,
- const GrPipeline::FixedDynamicState*, bool willDrawPoints);
+ const GrPipeline::FixedDynamicState*, const GrPipeline::DynamicStateArrays*,
+ int dynamicStateArraysLength, bool willDrawPoints);
void flushProgram(sk_sp<GrGLProgram>);
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 8bd4c9c..1b3cfbd 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -116,7 +116,7 @@
const GrPipeline::FixedDynamicState& fixedDynamicState,
const GrStencilSettings& stencilPassSettings,
const GrPath* path) {
- if (!this->gpu()->flushGLState(primProc, pipeline, &fixedDynamicState, false)) {
+ if (!this->gpu()->flushGLState(primProc, pipeline, &fixedDynamicState, nullptr, 1, false)) {
return;
}
const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 06aaade..8a5308f 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -75,7 +75,6 @@
void GrGLProgram::updateUniformsAndTextureBindings(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
const GrTextureProxy* const primProcTextures[]) {
- SkASSERT(primProcTextures || !primProc.numTextureSamplers());
this->setRenderTargetState(primProc, pipeline.proxy());
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
@@ -84,13 +83,12 @@
// We must bind to texture units in the same order in which we set the uniforms in
// GrGLProgramDataManager. That is, we bind textures for processors in this order:
// primProc, fragProcs, XP.
- int nextTexSamplerIdx = 0;
fPrimitiveProcessor->setData(fProgramDataManager, primProc,
GrFragmentProcessor::CoordTransformIter(pipeline));
- for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
- auto* tex = static_cast<GrGLTexture*>(primProcTextures[i]->peekTexture());
- fGpu->bindTexture(nextTexSamplerIdx++, primProc.textureSampler(i).samplerState(), tex);
+ if (primProcTextures) {
+ this->updatePrimitiveProcessorTextureBindings(primProc, primProcTextures);
}
+ int nextTexSamplerIdx = primProc.numTextureSamplers();
this->setFragmentData(pipeline, &nextTexSamplerIdx);
@@ -106,6 +104,14 @@
SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
}
+void GrGLProgram::updatePrimitiveProcessorTextureBindings(const GrPrimitiveProcessor& primProc,
+ const GrTextureProxy* const proxies[]) {
+ for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
+ auto* tex = static_cast<GrGLTexture*>(proxies[i]->peekTexture());
+ fGpu->bindTexture(i, primProc.textureSampler(i).samplerState(), tex);
+ }
+}
+
void GrGLProgram::setFragmentData(const GrPipeline& pipeline, int* nextTexSamplerIdx) {
GrFragmentProcessor::Iter iter(pipeline);
GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index ca9253c..1a2ef20 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -112,13 +112,17 @@
/**
* This function uploads uniforms, calls each GrGLSL*Processor's setData. It binds all fragment
- * processor textures. Primitive process textures are also bound here but are passed separately.
+ * processor textures. Primitive process textures can be bound using this function or by
+ * calling updatePrimitiveProcessorTextureBindings.
*
* It is the caller's responsibility to ensure the program is bound before calling.
*/
void updateUniformsAndTextureBindings(const GrPrimitiveProcessor&, const GrPipeline&,
const GrTextureProxy* const primitiveProcessorTextures[]);
+ void updatePrimitiveProcessorTextureBindings(const GrPrimitiveProcessor&,
+ const GrTextureProxy* const[]);
+
int vertexStride() const { return fVertexStride; }
int instanceStride() const { return fInstanceStride; }