blob: 72b0302348904ba093ba085e3c3b281c8d7ea2df [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef skgpu_graphite_GraphiteTypes_DEFINED
#define skgpu_graphite_GraphiteTypes_DEFINED
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GpuTypes.h"
#include <memory>
class SkSurface;
namespace skgpu {
class MutableTextureState;
}
namespace skgpu::graphite {
class BackendSemaphore;
class Recording;
class Task;
using GpuFinishedContext = void*;
using GpuFinishedProc = void (*)(GpuFinishedContext finishedContext, CallbackResult);
using GpuFinishedWithStatsProc = void (*)(GpuFinishedContext finishedContext,
CallbackResult,
const GpuStats&);
// NOTE: This can be converted to just an `enum class InsertStatus {}` once clients are migrated
// off of assuming `Context::insertRecording()` returns a boolean.
class InsertStatus {
public:
// Do not refer to V directly; use these constants as if InsertStatus were a class enum, e.g.
// InsertStatus::kSuccess.
enum V {
// Everything successfully added to underlying CommandBuffer
kSuccess,
// Recording or InsertRecordingInfo invalid, no CB changes
kInvalidRecording,
// Promise image instantiation failed, no CB changes
kPromiseImageInstantiationFailed,
// Internal failure, CB partially modified, state unrecoverable or unknown (e.g. dependent
// texture uploads for future Recordings may or may not get executed)
kAddCommandsFailed,
// Internal failure, shader pipeline compilation failed (driver issue, or disk corruption),
// state unrecoverable.
kAsyncShaderCompilesFailed
};
constexpr InsertStatus() : fValue(kSuccess) {}
/*implicit*/ constexpr InsertStatus(V v) : fValue(v) {}
operator InsertStatus::V() const {
return fValue;
}
// Assist migration from old bool return value of insertRecording; kSuccess is true,
// all other error statuses are false.
// NOTE: This is intentionally not explicit so that InsertStatus can be assigned correctly to
// a bool or returned as a bool, since these are not boolean contexts that automatically apply
// explicit bool operators (e.g. inside an if condition).
operator bool() const {
return fValue == kSuccess;
}
private:
V fValue;
};
/**
* The fFinishedProc is called when the Recording has been submitted and finished on the GPU, or
* when there is a failure that caused it not to be submitted. The callback will always be called
* and the caller can use the callback to know it is safe to free any resources associated with
* the Recording that they may be holding onto. If the Recording is successfully submitted to the
* GPU the callback will be called with CallbackResult::kSuccess once the GPU has finished. All
* other cases where some failure occurred it will be called with CallbackResult::kFailed.
*
* Alternatively, the client can provide fFinishedProcWithStats. This provides additional
* information about execution of the recording on the GPU. Only the stats requested using
* fStatsFlags will be valid and only if CallbackResult is kSuccess. If both fFinishedProc
* and fFinishedProcWithStats are provided the latter is preferred and the former won't be
* called.
*
* The fTargetSurface, if provided, is used as a target for any draws recorded onto a deferred
* canvas returned from Recorder::makeDeferredCanvas. This target surface must be provided iff
* the Recording contains any such draws. It must be Graphite-backed and its backing texture's
* TextureInfo must match the info provided to the Recorder when making the deferred canvas.
*
* fTargetTranslation is an additional translation applied to draws targeting fTargetSurface.
*
* fTargetClip is an additional clip applied to draws targeting fTargetSurface. It is defined in the
* local replay space, that is, with fTargetTranslation applied. An empty clip will not be applied.
*
* The client may pass in two arrays of initialized BackendSemaphores to be included in the
* command stream. At some time before issuing commands in the Recording, the fWaitSemaphores will
* be waited on by the gpu. We only guarantee these wait semaphores block transfer and fragment
* shader work. Similarly, at some time after issuing the Recording's commands, the
* fSignalSemaphores will be signaled by the gpu. Depending on the platform, the timing of the wait
* and signal operations will either be immediately before or after the given Recording's command
* stream, respectively, or before and after the entire CommandBuffer's command stream. The
* semaphores are not sent to the GPU until the next Context::submit call is made.
*
* The client will own and be responsible for deleting the underlying semaphore objects after the
* submission completes, however the BackendSemaphore objects themselves can be deleted as soon
* as this function returns.
*/
struct InsertRecordingInfo {
Recording* fRecording = nullptr;
SkSurface* fTargetSurface = nullptr;
SkIVector fTargetTranslation = {0, 0};
SkIRect fTargetClip = {0, 0, 0, 0};
MutableTextureState* fTargetTextureState = nullptr;
size_t fNumWaitSemaphores = 0;
BackendSemaphore* fWaitSemaphores = nullptr;
size_t fNumSignalSemaphores = 0;
BackendSemaphore* fSignalSemaphores = nullptr;
GpuStatsFlags fGpuStatsFlags = GpuStatsFlags::kNone;
GpuFinishedContext fFinishedContext = nullptr;
GpuFinishedProc fFinishedProc = nullptr;
GpuFinishedWithStatsProc fFinishedWithStatsProc = nullptr;
// For unit testing purposes, this can be used to induce a known failure status from
// Context::insertRecording(). When this set to anything other than kSuccess, insertRecording()
// will operate as normal until the first condition that would normally return the simulated
// status is encountered. At that point, operations are treated as if that condition had failed.
// This leaves the Context in a state consistent with encountering the InsertStatus in a normal
// application.
//
// NOTE: If the simulated failure status is one of the later error codes but the inserted
// Recording would fail with an earlier error code normally, that error is still returned.
InsertStatus fSimulatedStatus = InsertStatus::kSuccess;
};
/**
* The fFinishedProc is called when the Recording has been submitted and finished on the GPU, or
* when there is a failure that caused it not to be submitted. The callback will always be called
* and the caller can use the callback to know it is safe to free any resources associated with
* the Recording that they may be holding onto. If the Recording is successfully submitted to the
* GPU the callback will be called with CallbackResult::kSuccess once the GPU has finished. All
* other cases where some failure occured it will be called with CallbackResult::kFailed.
*/
struct InsertFinishInfo {
InsertFinishInfo() = default;
InsertFinishInfo(GpuFinishedContext context, GpuFinishedProc proc)
: fFinishedContext{context}, fFinishedProc{proc} {}
InsertFinishInfo(GpuFinishedContext context, GpuFinishedWithStatsProc proc)
: fFinishedContext{context}, fFinishedWithStatsProc{proc} {}
GpuFinishedContext fFinishedContext = nullptr;
GpuFinishedProc fFinishedProc = nullptr;
GpuFinishedWithStatsProc fFinishedWithStatsProc = nullptr;
GpuStatsFlags fGpuStatsFlags = GpuStatsFlags::kNone;
};
/**
* Actually submit work to the GPU and track its completion
*/
enum class SyncToCpu : bool {
kYes = true,
kNo = false
};
enum class MarkFrameBoundary : bool {
kYes = true,
kNo = false
};
struct SubmitInfo {
SyncToCpu fSync = SyncToCpu::kNo;
MarkFrameBoundary fMarkBoundary = MarkFrameBoundary::kNo;
uint64_t fFrameID = 0;
constexpr SubmitInfo() = default;
constexpr SubmitInfo(SyncToCpu sync)
: fSync(sync)
, fMarkBoundary(MarkFrameBoundary::kNo)
, fFrameID(0) {}
constexpr SubmitInfo(SyncToCpu sync, uint64_t frameID)
: fSync(sync)
, fMarkBoundary(MarkFrameBoundary::kYes)
, fFrameID(frameID) {}
};
/*
* For Promise Images - should the Promise Image be fulfilled every time a Recording that references
* it is inserted into the Context.
*/
enum class Volatile : bool {
kNo = false, // only fulfilled once
kYes = true // fulfilled on every insertion call
};
enum class DepthStencilFlags : int {
kNone = 0b000,
kDepth = 0b001,
kStencil = 0b010,
kDepthStencil = kDepth | kStencil,
};
// NOTE: This can be converted to just an `enum class SampleCount {}` once clients are migrated
// off of writing integer values into backend TextureInfo fields or ContextOptions.
class SampleCount {
public:
// Do not refer to V directly; use these constants as if SampleCount were a class enum, e.g.
// SampleCount::k4.
enum V : uint8_t {
k1 = 1,
k2 = 2,
k4 = 4,
k8 = 8,
k16 = 16
};
constexpr SampleCount() : fValue(k1) {}
/*implicit*/ constexpr SampleCount(V v) : fValue(v) {}
// Behave like an enum
constexpr bool operator ==(const SampleCount& o) const { return fValue == o.fValue; }
constexpr bool operator <(const SampleCount& o) const { return fValue < o.fValue; }
constexpr bool operator <=(const SampleCount& o) const { return fValue <= o.fValue; }
constexpr bool operator >(const SampleCount& o) const { return fValue > o.fValue; }
constexpr bool operator >=(const SampleCount& o) const { return fValue >= o.fValue; }
// This needs to be explicit so that ternaries that return constants mixed with variables aren't
// ambiguous; internal code can cast for switch statements.
explicit constexpr operator SampleCount::V() const { return fValue; }
explicit constexpr operator uint8_t() const { return (uint8_t) fValue; }
explicit constexpr operator unsigned int() const { return (unsigned int) fValue; }
// Assist migration from old code that would assign integers to sample count fields that used
// to be uint8_t and are now more strictly typed to SampleCount. Asserts if the value doesn't
// match a SampleCount value.
/*implicit*/ constexpr SampleCount(uint8_t v) : fValue((V) v) {
SkASSERT(v == 1 || v == 2 || v == 4 || v == 8 || v == 16);
}
constexpr SampleCount& operator=(uint8_t sampleCount) {
return (*this = SampleCount(sampleCount));
}
private:
V fValue;
};
/**
* Convert an integer value to a strictly typed SampleCount value, rounding down to the lowest
* valid sample count if needed if `sampleCount` is not already equivalent.
*/
constexpr SampleCount ToSampleCount(uint32_t sampleCount) {
return sampleCount >= 16 ? SampleCount::k16 :
sampleCount >= 8 ? SampleCount::k8 :
sampleCount >= 4 ? SampleCount::k4 :
sampleCount >= 2 ? SampleCount::k2 :
SampleCount::k1;
}
/*
* This enum allows mapping from a set of observed RenderSteps (e.g., from a GraphicsPipeline
* printout) to the correct 'drawTypes' parameter needed by the Precompilation API.
*/
enum DrawTypeFlags : uint16_t {
kNone = 0,
// kBitmapText_Mask should be used for the BitmapTextRenderStep[mask] RenderStep
kBitmapText_Mask = 1 << 0,
// kBitmapText_LCD should be used for the BitmapTextRenderStep[LCD] RenderStep
kBitmapText_LCD = 1 << 1,
// kBitmapText_Color should be used for the BitmapTextRenderStep[color] RenderStep
kBitmapText_Color = 1 << 2,
// kSDFText should be used for the SDFTextRenderStep RenderStep
kSDFText = 1 << 3,
// kSDFText_LCD should be used for the SDFTextLCDRenderStep RenderStep
kSDFText_LCD = 1 << 4,
// kDrawVertices should be used to generate Pipelines that use the following RenderSteps:
// VerticesRenderStep[*] for:
// [Tris], [TrisTexCoords], [TrisColor], [TrisColorTexCoords],
// [Tristrips], [TristripsTexCoords], [TristripsColor], [TristripsColorTexCoords]
kDrawVertices = 1 << 5,
// kCircularArc renders filled circular arcs, with or without the center included, and
// stroked circular arcs with butt or round caps that don't include the center point.
// It corresponds to the CircularArcRenderStep.
kCircularArc = 1 << 6,
// kSimpleShape should be used to generate Pipelines that use the following RenderSteps:
// AnalyticRRectRenderStep
// PerEdgeAAQuadRenderStep
// CoverBoundsRenderStep[NonAAFill]
kAnalyticRRect = 1 << 7,
kPerEdgeAAQuad = 1 << 8,
kNonAAFillRect = 1 << 9,
kSimpleShape = kAnalyticRRect | kPerEdgeAAQuad | kNonAAFillRect,
// kNonSimpleShape should be used to generate Pipelines that use the following RenderSteps:
// CoverageMaskRenderStep
// CoverBoundsRenderStep[*] for [InverseCover], [RegularCover]
// TessellateStrokeRenderStep
// TessellateWedgesRenderStep[*] for [Convex], [EvenOdd], [Winding]
// TessellateCurvesRenderStep[*] for [EvenOdd], [Winding]
// MiddleOutFanRenderStep[*] for [EvenOdd], [Winding]
kNonSimpleShape = 1 << 10,
// This draw type covers all the methods Skia uses to draw drop shadows. It can be used to
// generate Pipelines which, as part of their labels, have:
// the AnalyticBlurRenderStep
// VerticesRenderStep[TrisColor] with a GaussianColorFilter
// For this draw type the PaintOptions parameter to Precompile() will be ignored.
kDropShadows = 1 << 11,
// kAnalyticClip should be combined with the primary drawType for Pipelines that contain
// either of the following sub-strings:
// AnalyticClip
// AnalyticAndAtlasClip
kAnalyticClip = 1 << 12,
kLast = kAnalyticClip,
};
} // namespace skgpu::graphite
#endif // skgpu_graphite_GraphiteTypes_DEFINED