Add half-float vertex attribute caps bit and benchmark

Updates the existing vertex color bench with a half-float mode.
Vanilla GL2/ES2 don't have half-float attributes. The extension
(OES_vertex_half_float) uses a different enum value for the type
parameter. For now, just support GL3/ES3. Otherwise, we could
add a check in GrGLGpu::setupGeometry to re-map GL_HALF_FLOAT
to GL_HALF_FLOAT_OES, based on caps?

Bug: skia:
Change-Id: I1325087db4e615023cceffe1c5b051232769d0ac
Reviewed-on: https://skia-review.googlesource.com/154822
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2018-09-17 11:32:42 -04:00 committed by Skia Commit-Bot
parent 4c709a2fab
commit 499bf1a599
6 changed files with 72 additions and 10 deletions

View File

@ -15,6 +15,7 @@
#include "GrRenderTargetContextPriv.h"
#include "SkColorSpacePriv.h"
#include "SkGr.h"
#include "SkHalf.h"
#include "SkString.h"
#include "glsl/GrGLSLColorSpaceXformHelper.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
@ -28,6 +29,7 @@ namespace {
enum Mode {
kBaseline_Mode, // Do the wrong thing, but quickly.
kFloat_Mode, // Transform colors on CPU, use float4 attributes.
kHalf_Mode, // Transform colors on CPU, use half4 attributes.
kShader_Mode, // Use ubyte4 attributes, transform colors on GPU (vertex shader).
};
@ -38,10 +40,17 @@ public:
, fMode(mode)
, fColorSpaceXform(std::move(colorSpaceXform)) {
fInPosition = {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
if (kFloat_Mode == fMode) {
fInColor = {"inColor", kFloat4_GrVertexAttribType, kFloat4_GrSLType};
} else {
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
switch (fMode) {
case kBaseline_Mode:
case kShader_Mode:
fInColor = {"inColor", kUByte4_norm_GrVertexAttribType, kHalf4_GrSLType};
break;
case kFloat_Mode:
fInColor = {"inColor", kFloat4_GrVertexAttribType, kHalf4_GrSLType};
break;
case kHalf_Mode:
fInColor = {"inColor", kHalf4_GrVertexAttribType, kHalf4_GrSLType};
break;
}
this->setVertexAttributeCnt(2);
}
@ -126,10 +135,11 @@ public:
this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
}
Op(GrColor4f color4f)
Op(GrColor4f color4f, Mode mode)
: INHERITED(ClassID())
, fMode(kFloat_Mode)
, fMode(mode)
, fColor4f(color4f) {
SkASSERT(kFloat_Mode == fMode || kHalf_Mode == mode);
this->setBounds(SkRect::MakeWH(100.f, 100.f), HasAABloat::kNo, IsZeroArea::kNo);
}
@ -155,8 +165,17 @@ private:
void onPrepareDraws(Target* target) override {
sk_sp<GrGeometryProcessor> gp(new GP(fMode, fColorSpaceXform));
size_t vertexStride = sizeof(SkPoint) +
((kFloat_Mode == fMode) ? sizeof(GrColor4f) : sizeof(uint32_t));
size_t vertexStride = sizeof(SkPoint);
switch (fMode) {
case kFloat_Mode:
vertexStride += sizeof(GrColor4f);
break;
case kHalf_Mode:
vertexStride += sizeof(uint64_t);
break;
default:
vertexStride += sizeof(uint32_t);
}
SkASSERT(vertexStride == gp->debugOnly_vertexStride());
const int kVertexCount = 1024;
@ -182,6 +201,25 @@ private:
v[i + 1].fPos.set(dx * i, 100.0f);
v[i + 1].fColor = fColor4f;
}
} else if (kHalf_Mode == fMode) {
struct V {
SkPoint fPos;
uint64_t fColor;
};
SkASSERT(sizeof(V) == vertexStride);
uint64_t color;
Sk4h halfColor = SkFloatToHalf_finite_ftz(Sk4f::Load(&fColor));
color = (uint64_t)halfColor[0] << 48 |
(uint64_t)halfColor[1] << 32 |
(uint64_t)halfColor[2] << 16 |
(uint64_t)halfColor[3] << 0;
V* v = (V*)verts;
for (int i = 0; i < kVertexCount; i += 2) {
v[i + 0].fPos.set(dx * i, 0.0f);
v[i + 0].fColor = color;
v[i + 1].fPos.set(dx * i, 100.0f);
v[i + 1].fColor = color;
}
} else {
struct V {
SkPoint fPos;
@ -226,9 +264,15 @@ public:
void onDraw(int loops, SkCanvas* canvas) override {
GrContext* context = canvas->getGrContext();
SkASSERT(context);
if (kHalf_Mode == fMode &&
!context->contextPriv().caps()->halfFloatVertexAttributeSupport()) {
return;
}
GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
SkASSERT(context);
auto p3 = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
SkColorSpace::kDCIP3_D65_Gamut);
auto xform = GrColorSpaceXform::Make(sk_srgb_singleton(), kUnpremul_SkAlphaType,
@ -254,10 +298,11 @@ public:
case kShader_Mode:
op = pool->allocate<Op>(SkColorToUnpremulGrColor(c), xform);
break;
case kHalf_Mode:
case kFloat_Mode: {
GrColor4f c4f = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(c));
c4f = xform->apply(c4f);
op = pool->allocate<Op>(c4f);
op = pool->allocate<Op>(c4f, fMode);
}
}
rtc->priv().testingOnly_addDrawOp(std::move(op));
@ -276,4 +321,5 @@ private:
DEF_BENCH(return new VertexColorSpaceBench(kBaseline_Mode, "baseline"));
DEF_BENCH(return new VertexColorSpaceBench(kFloat_Mode, "float"));
DEF_BENCH(return new VertexColorSpaceBench(kHalf_Mode, "half"));
DEF_BENCH(return new VertexColorSpaceBench(kShader_Mode, "shader"));

View File

@ -62,6 +62,7 @@ GrCaps::GrCaps(const GrContextOptions& options) {
fSampleShadingSupport = false;
fFenceSyncSupport = false;
fCrossContextTextureSupport = false;
fHalfFloatVertexAttributeSupport = false;
fBlendEquationSupport = kBasic_BlendEquationSupport;
fAdvBlendEqBlacklist = 0;
@ -174,6 +175,7 @@ void GrCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Sample shading support", fSampleShadingSupport);
writer->appendBool("Fence sync support", fFenceSyncSupport);
writer->appendBool("Cross context texture support", fCrossContextTextureSupport);
writer->appendBool("Half float vertex attribute support", fHalfFloatVertexAttributeSupport);
writer->appendBool("Blacklist Coverage Counting Path Renderer [workaround]",
fBlacklistCoverageCounting);

View File

@ -58,6 +58,7 @@ public:
bool multisampleDisableSupport() const { return fMultisampleDisableSupport; }
bool instanceAttribSupport() const { return fInstanceAttribSupport; }
bool usesMixedSamples() const { return fUsesMixedSamples; }
bool halfFloatVertexAttributeSupport() const { return fHalfFloatVertexAttributeSupport; }
// Primitive restart functionality is core in ES 3.0, but using it will cause slowdowns on some
// systems. This cap is only set if primitive restart will improve performance.
@ -322,6 +323,7 @@ protected:
bool fPreferFullscreenClears : 1;
bool fMustClearUploadedBufferData : 1;
bool fSupportsAHardwareBufferImages : 1;
bool fHalfFloatVertexAttributeSupport : 1;
// Driver workaround
bool fBlacklistCoverageCounting : 1;

View File

@ -576,6 +576,16 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
// Safely moving textures between contexts requires fences.
fCrossContextTextureSupport = fFenceSyncSupport;
// Half float vertex attributes requires GL3 or ES3
// It can also work with OES_VERTEX_HALF_FLOAT, but that requires a different enum.
if (kGL_GrGLStandard == standard) {
if (version >= GR_GL_VER(3, 0)) {
fHalfFloatVertexAttributeSupport = true;
}
} else if (version >= GR_GL_VER(3, 0)) {
fHalfFloatVertexAttributeSupport = true;
}
if (kGL_GrGLStandard == standard) {
if (version >= GR_GL_VER(4, 1)) {
fProgramBinarySupport = true;

View File

@ -255,6 +255,7 @@ void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
fFenceSyncSupport = true; // always available in Metal
fCrossContextTextureSupport = false;
fHalfFloatVertexAttributeSupport = true;
}

View File

@ -35,6 +35,7 @@ GrVkCaps::GrVkCaps(const GrContextOptions& contextOptions, const GrVkInterface*
fBlacklistCoverageCounting = true; // blacklisting ccpr until we work through a few issues.
fFenceSyncSupport = true; // always available in Vulkan
fCrossContextTextureSupport = true;
fHalfFloatVertexAttributeSupport = true;
fMapBufferFlags = kNone_MapFlags; //TODO: figure this out
fBufferMapThreshold = SK_MaxS32; //TODO: figure this out