[Graphite] Use more flexible system for storing commands in DrawPass.
Bug: skia:13357 Change-Id: I845872fd70771f273b339becc2064ec732884988 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/557390 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
92c162532e
commit
23df8d2d73
@ -45,6 +45,7 @@ skia_graphite_sources = [
|
||||
"$_src/DrawAtlas.h",
|
||||
"$_src/DrawBufferManager.cpp",
|
||||
"$_src/DrawBufferManager.h",
|
||||
"$_src/DrawCommands.h",
|
||||
"$_src/DrawContext.cpp",
|
||||
"$_src/DrawContext.h",
|
||||
"$_src/DrawList.cpp",
|
||||
|
@ -46,12 +46,16 @@ void CommandBuffer::callFinishedProcs(bool success) {
|
||||
fFinishedProcs.reset();
|
||||
}
|
||||
|
||||
bool CommandBuffer::beginRenderPass(const RenderPassDesc& renderPassDesc,
|
||||
sk_sp<Texture> colorTexture,
|
||||
sk_sp<Texture> resolveTexture,
|
||||
sk_sp<Texture> depthStencilTexture) {
|
||||
if (!this->onBeginRenderPass(renderPassDesc, colorTexture.get(), resolveTexture.get(),
|
||||
depthStencilTexture.get())) {
|
||||
bool CommandBuffer::addRenderPass(const RenderPassDesc& renderPassDesc,
|
||||
sk_sp<Texture> colorTexture,
|
||||
sk_sp<Texture> resolveTexture,
|
||||
sk_sp<Texture> depthStencilTexture,
|
||||
const std::vector<std::unique_ptr<DrawPass>>& drawPasses) {
|
||||
if (!this->onAddRenderPass(renderPassDesc,
|
||||
colorTexture.get(),
|
||||
resolveTexture.get(),
|
||||
depthStencilTexture.get(),
|
||||
drawPasses)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -64,64 +68,14 @@ bool CommandBuffer::beginRenderPass(const RenderPassDesc& renderPassDesc,
|
||||
if (depthStencilTexture) {
|
||||
this->trackResource(std::move(depthStencilTexture));
|
||||
}
|
||||
#ifdef SK_DEBUG
|
||||
if (renderPassDesc.fColorAttachment.fLoadOp == LoadOp::kClear &&
|
||||
(renderPassDesc.fColorAttachment.fStoreOp == StoreOp::kStore ||
|
||||
renderPassDesc.fColorResolveAttachment.fStoreOp == StoreOp::kStore)) {
|
||||
fHasWork = true;
|
||||
}
|
||||
#endif
|
||||
// We just assume if you are adding a render pass that the render pass will actually do work. In
|
||||
// theory we could have a discard load that doesn't submit any draws, clears, etc. But hopefully
|
||||
// something so trivial would be caught before getting here.
|
||||
SkDEBUGCODE(fHasWork = true;)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandBuffer::bindGraphicsPipeline(sk_sp<GraphicsPipeline> graphicsPipeline) {
|
||||
this->onBindGraphicsPipeline(graphicsPipeline.get());
|
||||
this->trackResource(std::move(graphicsPipeline));
|
||||
}
|
||||
|
||||
void CommandBuffer::bindUniformBuffer(UniformSlot slot,
|
||||
sk_sp<Buffer> uniformBuffer,
|
||||
size_t offset) {
|
||||
this->onBindUniformBuffer(slot, uniformBuffer.get(), offset);
|
||||
this->trackResource(std::move(uniformBuffer));
|
||||
}
|
||||
|
||||
void CommandBuffer::bindVertexBuffers(sk_sp<Buffer> vertexBuffer, size_t vertexOffset,
|
||||
sk_sp<Buffer> instanceBuffer, size_t instanceOffset) {
|
||||
this->onBindVertexBuffers(vertexBuffer.get(), vertexOffset,
|
||||
instanceBuffer.get(), instanceOffset);
|
||||
if (vertexBuffer) {
|
||||
this->trackResource(std::move(vertexBuffer));
|
||||
}
|
||||
if (instanceBuffer) {
|
||||
this->trackResource(std::move(instanceBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
void CommandBuffer::bindIndexBuffer(sk_sp<Buffer> indexBuffer, size_t bufferOffset) {
|
||||
this->onBindIndexBuffer(indexBuffer.get(), bufferOffset);
|
||||
if (indexBuffer) {
|
||||
this->trackResource(std::move(indexBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
void CommandBuffer::bindDrawBuffers(BindBufferInfo vertices,
|
||||
BindBufferInfo instances,
|
||||
BindBufferInfo indices) {
|
||||
this->bindVertexBuffers(sk_ref_sp(vertices.fBuffer), vertices.fOffset,
|
||||
sk_ref_sp(instances.fBuffer), instances.fOffset);
|
||||
this->bindIndexBuffer(sk_ref_sp(indices.fBuffer), indices.fOffset);
|
||||
}
|
||||
|
||||
void CommandBuffer::bindTextureAndSampler(sk_sp<Texture> texture,
|
||||
sk_sp<Sampler> sampler,
|
||||
int bindIndex) {
|
||||
this->onBindTextureAndSampler(texture, sampler, bindIndex);
|
||||
this->trackResource(std::move(texture));
|
||||
this->trackResource(std::move(sampler));
|
||||
}
|
||||
|
||||
bool CommandBuffer::copyTextureToBuffer(sk_sp<Texture> texture,
|
||||
SkIRect srcRect,
|
||||
sk_sp<Buffer> buffer,
|
||||
|
@ -23,6 +23,7 @@ class RefCntedCallback;
|
||||
|
||||
namespace skgpu::graphite {
|
||||
class Buffer;
|
||||
class DrawPass;
|
||||
class Gpu;
|
||||
class GraphicsPipeline;
|
||||
class Resource;
|
||||
@ -46,59 +47,11 @@ public:
|
||||
void addFinishedProc(sk_sp<RefCntedCallback> finishedProc);
|
||||
void callFinishedProcs(bool success);
|
||||
|
||||
bool beginRenderPass(const RenderPassDesc&,
|
||||
sk_sp<Texture> colorTexture,
|
||||
sk_sp<Texture> resolveTexture,
|
||||
sk_sp<Texture> depthStencilTexture);
|
||||
virtual void endRenderPass() = 0;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Can only be used within renderpasses
|
||||
//---------------------------------------------------------------
|
||||
void bindGraphicsPipeline(sk_sp<GraphicsPipeline> graphicsPipeline);
|
||||
void bindUniformBuffer(UniformSlot, sk_sp<Buffer>, size_t bufferOffset);
|
||||
|
||||
void bindDrawBuffers(BindBufferInfo vertices,
|
||||
BindBufferInfo instances,
|
||||
BindBufferInfo indices);
|
||||
|
||||
void bindTextureAndSampler(sk_sp<Texture>, sk_sp<Sampler>, int bindIndex);
|
||||
|
||||
// TODO: do we want to handle multiple scissor rects and viewports?
|
||||
void setScissor(unsigned int left, unsigned int top, unsigned int width, unsigned int height) {
|
||||
this->onSetScissor(left, top, width, height);
|
||||
}
|
||||
|
||||
void setViewport(float x, float y, float width, float height,
|
||||
float minDepth = 0, float maxDepth = 1) {
|
||||
this->onSetViewport(x, y, width, height, minDepth, maxDepth);
|
||||
}
|
||||
|
||||
void setBlendConstants(std::array<float, 4> blendConstants) {
|
||||
this->onSetBlendConstants(blendConstants);
|
||||
}
|
||||
|
||||
void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) {
|
||||
this->onDraw(type, baseVertex, vertexCount);
|
||||
SkDEBUGCODE(fHasWork = true;)
|
||||
}
|
||||
void drawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
|
||||
unsigned int baseVertex) {
|
||||
this->onDrawIndexed(type, baseIndex, indexCount, baseVertex);
|
||||
SkDEBUGCODE(fHasWork = true;)
|
||||
}
|
||||
void drawInstanced(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount,
|
||||
unsigned int baseInstance, unsigned int instanceCount) {
|
||||
this->onDrawInstanced(type, baseVertex, vertexCount, baseInstance, instanceCount);
|
||||
SkDEBUGCODE(fHasWork = true;)
|
||||
}
|
||||
void drawIndexedInstanced(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
|
||||
unsigned int baseVertex, unsigned int baseInstance,
|
||||
unsigned int instanceCount) {
|
||||
this->onDrawIndexedInstanced(type, baseIndex, indexCount, baseVertex, baseInstance,
|
||||
instanceCount);
|
||||
SkDEBUGCODE(fHasWork = true;)
|
||||
}
|
||||
bool addRenderPass(const RenderPassDesc&,
|
||||
sk_sp<Texture> colorTexture,
|
||||
sk_sp<Texture> resolveTexture,
|
||||
sk_sp<Texture> depthStencilTexture,
|
||||
const std::vector<std::unique_ptr<DrawPass>>& drawPasses);
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Can only be used outside renderpasses
|
||||
@ -117,43 +70,11 @@ protected:
|
||||
CommandBuffer();
|
||||
|
||||
private:
|
||||
// TODO: Once all buffer use goes through the DrawBufferManager, we likely do not need to track
|
||||
// refs every time a buffer is bound, since the DBM will transfer ownership for any used buffer
|
||||
// to the CommandBuffer.
|
||||
void bindVertexBuffers(sk_sp<Buffer> vertexBuffer, size_t vertexOffset,
|
||||
sk_sp<Buffer> instanceBuffer, size_t instanceOffset);
|
||||
void bindIndexBuffer(sk_sp<Buffer> indexBuffer, size_t bufferOffset);
|
||||
|
||||
virtual bool onBeginRenderPass(const RenderPassDesc&,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture) = 0;
|
||||
|
||||
virtual void onBindGraphicsPipeline(const GraphicsPipeline*) = 0;
|
||||
virtual void onBindUniformBuffer(UniformSlot, const Buffer*, size_t bufferOffset) = 0;
|
||||
virtual void onBindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset,
|
||||
const Buffer* instanceBuffer, size_t instanceOffset) = 0;
|
||||
virtual void onBindIndexBuffer(const Buffer* indexBuffer, size_t bufferOffset) = 0;
|
||||
|
||||
virtual void onBindTextureAndSampler(sk_sp<Texture>,
|
||||
sk_sp<Sampler>,
|
||||
unsigned int bindIndex) = 0;
|
||||
|
||||
virtual void onSetScissor(unsigned int left, unsigned int top,
|
||||
unsigned int width, unsigned int height) = 0;
|
||||
virtual void onSetViewport(float x, float y, float width, float height,
|
||||
float minDepth, float maxDepth) = 0;
|
||||
virtual void onSetBlendConstants(std::array<float, 4> blendConstants) = 0;
|
||||
|
||||
virtual void onDraw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) = 0;
|
||||
virtual void onDrawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
|
||||
unsigned int baseVertex) = 0;
|
||||
virtual void onDrawInstanced(PrimitiveType type,
|
||||
unsigned int baseVertex, unsigned int vertexCount,
|
||||
unsigned int baseInstance, unsigned int instanceCount) = 0;
|
||||
virtual void onDrawIndexedInstanced(PrimitiveType type, unsigned int baseIndex,
|
||||
unsigned int indexCount, unsigned int baseVertex,
|
||||
unsigned int baseInstance, unsigned int instanceCount) = 0;
|
||||
virtual bool onAddRenderPass(const RenderPassDesc&,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture,
|
||||
const std::vector<std::unique_ptr<DrawPass>>& drawPasses) = 0;
|
||||
|
||||
virtual bool onCopyTextureToBuffer(const Texture*,
|
||||
SkIRect srcRect,
|
||||
|
229
src/gpu/graphite/DrawCommands.h
Normal file
229
src/gpu/graphite/DrawCommands.h
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2022 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_DrawPassCommands_DEFINED
|
||||
#define skgpu_graphite_DrawPassCommands_DEFINED
|
||||
|
||||
#include "include/core/SkRect.h"
|
||||
#include "src/core/SkArenaAlloc.h"
|
||||
#include "src/core/SkTBlockList.h"
|
||||
#include "src/gpu/graphite/DrawTypes.h"
|
||||
#include "src/gpu/graphite/DrawWriter.h"
|
||||
|
||||
namespace skgpu::graphite {
|
||||
|
||||
namespace DrawPassCommands {
|
||||
|
||||
// A list of all the commands types used by a DrawPass.
|
||||
// Each of these is reified into a struct below.
|
||||
//
|
||||
// The design of this systems is based on SkRecords.
|
||||
|
||||
// (We're using the macro-of-macro trick here to do several different things with the same list.)
|
||||
//
|
||||
// We leave this SKGPU_DRAW_COMMAND_TYPES macro defined for use by code that wants to operate on
|
||||
// DrawPassCommands types polymorphically.
|
||||
#define SKGPU_DRAW_PASS_COMMAND_TYPES(M) \
|
||||
M(BindGraphicsPipeline) \
|
||||
M(SetBlendConstants) \
|
||||
M(BindUniformBuffer) \
|
||||
M(BindDrawBuffers) \
|
||||
M(BindTexturesAndSamplers) \
|
||||
M(SetViewport) \
|
||||
M(SetScissor) \
|
||||
M(Draw) \
|
||||
M(DrawIndexed) \
|
||||
M(DrawInstanced) \
|
||||
M(DrawIndexedInstanced)
|
||||
|
||||
// Defines DrawPassCommands::Type, an enum of all draw command types.
|
||||
#define ENUM(T) k##T,
|
||||
enum class Type { SKGPU_DRAW_PASS_COMMAND_TYPES(ENUM) };
|
||||
#undef ENUM
|
||||
|
||||
#define ACT_AS_PTR(ptr) \
|
||||
operator T*() const { return ptr; } \
|
||||
T* operator->() const { return ptr; }
|
||||
|
||||
// PODArray doesn't own the pointer's memory, and we assume the data is POD.
|
||||
template <typename T>
|
||||
class PODArray {
|
||||
public:
|
||||
PODArray() {}
|
||||
PODArray(T* ptr) : fPtr(ptr) {}
|
||||
// Default copy and assign.
|
||||
|
||||
ACT_AS_PTR(fPtr)
|
||||
private:
|
||||
T* fPtr;
|
||||
};
|
||||
|
||||
#undef ACT_AS_PTR
|
||||
|
||||
// A macro to make it a little easier to define a struct that can be stored in DrawPass.
|
||||
#define COMMAND(T, ...) \
|
||||
struct T { \
|
||||
static constexpr Type kType = Type::k##T; \
|
||||
__VA_ARGS__; \
|
||||
};
|
||||
|
||||
COMMAND(BindGraphicsPipeline,
|
||||
uint32_t fPipelineIndex);
|
||||
COMMAND(SetBlendConstants,
|
||||
PODArray<float> fBlendConstants);
|
||||
COMMAND(BindUniformBuffer,
|
||||
BindBufferInfo fInfo;
|
||||
UniformSlot fSlot);
|
||||
COMMAND(BindDrawBuffers,
|
||||
BindBufferInfo fVertices;
|
||||
BindBufferInfo fInstances;
|
||||
BindBufferInfo fIndices);
|
||||
COMMAND(BindTexturesAndSamplers,
|
||||
int fNumTexSamplers;
|
||||
PODArray<int> fTextureIndices;
|
||||
PODArray<int> fSamplerIndices);
|
||||
COMMAND(SetViewport,
|
||||
SkRect fViewport;
|
||||
float fMinDepth;
|
||||
float fMaxDepth);
|
||||
COMMAND(SetScissor,
|
||||
SkIRect fScissor);
|
||||
COMMAND(Draw,
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseVertex;
|
||||
uint32_t fVertexCount);
|
||||
COMMAND(DrawIndexed,
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseIndex;
|
||||
uint32_t fIndexCount;
|
||||
uint32_t fBaseVertex);
|
||||
COMMAND(DrawInstanced,
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseVertex;
|
||||
uint32_t fVertexCount;
|
||||
uint32_t fBaseInstance;
|
||||
uint32_t fInstanceCount);
|
||||
COMMAND(DrawIndexedInstanced,
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseIndex;
|
||||
uint32_t fIndexCount;
|
||||
uint32_t fBaseVertex;
|
||||
uint32_t fBaseInstance;
|
||||
uint32_t fInstanceCount);
|
||||
|
||||
#undef COMMAND
|
||||
|
||||
#define ASSERT_TRIV_DES(T) static_assert(std::is_trivially_destructible<T>::value);
|
||||
SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_DES)
|
||||
#undef ASSERT_TRIV_DES
|
||||
#define ASSERT_TRIV_CPY(T) static_assert(std::is_trivially_copyable<T>::value);
|
||||
SKGPU_DRAW_PASS_COMMAND_TYPES(ASSERT_TRIV_CPY)
|
||||
#undef ASSERT_TRIV_CPY
|
||||
|
||||
class List final : public DrawDispatcher {
|
||||
public:
|
||||
List() = default;
|
||||
~List() override = default;
|
||||
|
||||
void bindGraphicsPipeline(uint32_t pipelineIndex) {
|
||||
this->add<BindGraphicsPipeline>(pipelineIndex);
|
||||
}
|
||||
|
||||
void setBlendConstants(std::array<float, 4> blendConstants) {
|
||||
this->add<SetBlendConstants>(this->copy(blendConstants.data(), 4));
|
||||
}
|
||||
|
||||
void bindUniformBuffer(BindBufferInfo info, UniformSlot slot) {
|
||||
this->add<BindUniformBuffer>(info, slot);
|
||||
}
|
||||
|
||||
void bindTexturesAndSamplers(int numTexSamplers,
|
||||
int* textureIndices,
|
||||
int* samplerIndices) {
|
||||
this->add<BindTexturesAndSamplers>(numTexSamplers,
|
||||
this->copy(textureIndices, numTexSamplers),
|
||||
this->copy(samplerIndices, numTexSamplers));
|
||||
}
|
||||
|
||||
void setViewport(const SkRect& viewport,
|
||||
float minDepth = 0,
|
||||
float maxDepth = 1) {
|
||||
this->add<SetViewport>(viewport, minDepth, maxDepth);
|
||||
}
|
||||
|
||||
void setScissor(SkIRect scissor) {
|
||||
this->add<SetScissor>(scissor);
|
||||
}
|
||||
|
||||
// DrawDispatcher overrides
|
||||
void bindDrawBuffers(BindBufferInfo vertexAttribs,
|
||||
BindBufferInfo instanceAttribs,
|
||||
BindBufferInfo indices) override {
|
||||
this->add<BindDrawBuffers>(vertexAttribs, instanceAttribs, indices);
|
||||
}
|
||||
|
||||
void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) override {
|
||||
this->add<Draw>(type, baseVertex, vertexCount);
|
||||
}
|
||||
|
||||
void drawIndexed(PrimitiveType type, unsigned int baseIndex,
|
||||
unsigned int indexCount, unsigned int baseVertex) override {
|
||||
this->add<DrawIndexed>(type, baseIndex, indexCount, baseVertex);
|
||||
}
|
||||
|
||||
void drawInstanced(PrimitiveType type,
|
||||
unsigned int baseVertex, unsigned int vertexCount,
|
||||
unsigned int baseInstance, unsigned int instanceCount) override {
|
||||
this->add<DrawInstanced>(type, baseVertex, vertexCount, baseInstance, instanceCount);
|
||||
}
|
||||
|
||||
void drawIndexedInstanced(PrimitiveType type,
|
||||
unsigned int baseIndex, unsigned int indexCount,
|
||||
unsigned int baseVertex, unsigned int baseInstance,
|
||||
unsigned int instanceCount) override {
|
||||
this->add<DrawIndexedInstanced>(type,
|
||||
baseIndex,
|
||||
indexCount,
|
||||
baseVertex,
|
||||
baseInstance,
|
||||
instanceCount);
|
||||
}
|
||||
|
||||
using Command = std::pair<Type, void*>;
|
||||
using Iter = SkTBlockList<Command>::CIter;
|
||||
Iter commands() const { return fCommands.items(); }
|
||||
|
||||
private:
|
||||
template <typename T, typename... Args>
|
||||
void add(Args&&... args) {
|
||||
T* cmd = fAlloc.make<T>(T{std::forward<Args>(args)...});
|
||||
fCommands.push_back(std::make_pair(T::kType, cmd));
|
||||
}
|
||||
|
||||
// This copy() is for arrays.
|
||||
// It will work with POD only arrays.
|
||||
template <typename T>
|
||||
T* copy(const T src[], size_t count) {
|
||||
static_assert(std::is_trivially_copyable<T>::value);
|
||||
T* dst = fAlloc.makeArrayDefault<T>(count);
|
||||
memcpy(dst, src, count*sizeof(T));
|
||||
return dst;
|
||||
}
|
||||
|
||||
SkTBlockList<Command> fCommands;
|
||||
|
||||
// fAlloc needs to be a data structure which can append variable length data in contiguous
|
||||
// chunks, returning a stable handle to that data for later retrieval.
|
||||
SkArenaAlloc fAlloc{256};
|
||||
};
|
||||
|
||||
} // namespace DrawPassCommands
|
||||
|
||||
} // namespace skgpu::graphite
|
||||
|
||||
#endif // skgpu_graphite_DrawPassCommands_DEFINED
|
||||
|
@ -146,45 +146,6 @@ private:
|
||||
SkNextLog2_portable(Renderer::kMaxRenderSteps * DrawList::kMaxDraws));
|
||||
};
|
||||
|
||||
class DrawPass::Drawer final : public DrawDispatcher {
|
||||
public:
|
||||
Drawer(DrawPass* drawPass) : fPass(drawPass) {}
|
||||
~Drawer() override = default;
|
||||
|
||||
void bindDrawBuffers(BindBufferInfo vertexAttribs,
|
||||
BindBufferInfo instanceAttribs,
|
||||
BindBufferInfo indices) override {
|
||||
fPass->fCommands.emplace_back(BindDrawBuffers{vertexAttribs, instanceAttribs, indices});
|
||||
}
|
||||
|
||||
void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) override {
|
||||
fPass->fCommands.emplace_back(Draw{type, baseVertex, vertexCount});
|
||||
}
|
||||
|
||||
void drawIndexed(PrimitiveType type, unsigned int baseIndex,
|
||||
unsigned int indexCount, unsigned int baseVertex) override {
|
||||
fPass->fCommands.emplace_back(DrawIndexed{type, baseIndex, indexCount, baseVertex});
|
||||
}
|
||||
|
||||
void drawInstanced(PrimitiveType type,
|
||||
unsigned int baseVertex, unsigned int vertexCount,
|
||||
unsigned int baseInstance, unsigned int instanceCount) override {
|
||||
fPass->fCommands.emplace_back(DrawInstanced{type, baseVertex, vertexCount,
|
||||
baseInstance, instanceCount});
|
||||
}
|
||||
|
||||
void drawIndexedInstanced(PrimitiveType type,
|
||||
unsigned int baseIndex, unsigned int indexCount,
|
||||
unsigned int baseVertex, unsigned int baseInstance,
|
||||
unsigned int instanceCount) override {
|
||||
fPass->fCommands.emplace_back(DrawIndexedInstanced{type, baseIndex, indexCount, baseVertex,
|
||||
baseInstance, instanceCount});
|
||||
}
|
||||
|
||||
private:
|
||||
DrawPass* fPass;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
@ -249,8 +210,7 @@ DrawPass::DrawPass(sk_sp<TextureProxy> target,
|
||||
std::pair<LoadOp, StoreOp> ops,
|
||||
std::array<float, 4> clearColor,
|
||||
int renderStepCount)
|
||||
: fCommands(std::max(1, renderStepCount / 4), SkBlockAllocator::GrowthPolicy::kFibonacci)
|
||||
, fTarget(std::move(target))
|
||||
: fTarget(std::move(target))
|
||||
, fBounds(SkIRect::MakeEmpty())
|
||||
, fOps(ops)
|
||||
, fClearColor(clearColor) {
|
||||
@ -261,7 +221,6 @@ DrawPass::DrawPass(sk_sp<TextureProxy> target,
|
||||
// many draws should be using a similar small set of samplers.
|
||||
static constexpr int kReserveSamplerCnt = 8;
|
||||
fSamplerDescs.reserve(kReserveSamplerCnt);
|
||||
fCommands.reserve(renderStepCount);
|
||||
}
|
||||
|
||||
DrawPass::~DrawPass() = default;
|
||||
@ -433,8 +392,7 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
std::sort(keys.begin(), keys.end());
|
||||
|
||||
// Used to record vertex/instance data, buffer binds, and draw calls
|
||||
Drawer drawer(drawPass.get());
|
||||
DrawWriter drawWriter(&drawer, bufferMgr);
|
||||
DrawWriter drawWriter(&drawPass->fCommandList, bufferMgr);
|
||||
|
||||
// Used to track when a new pipeline or dynamic state needs recording between draw steps.
|
||||
// Setting to # render steps ensures the very first time through the loop will bind a pipeline.
|
||||
@ -444,6 +402,11 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
UniformDataCache::Index lastGeometryUniforms;
|
||||
SkIRect lastScissor = SkIRect::MakeSize(drawPass->fTarget->dimensions());
|
||||
|
||||
// Set viewport to the entire texture for now (eventually, we may have logically smaller bounds
|
||||
// within an approx-sized texture). It is assumed that this also configures the sk_rtAdjust
|
||||
// intrinsic for programs (however the backend chooses to do so).
|
||||
drawPass->fCommandList.setViewport(SkRect::Make(drawPass->fTarget->dimensions()));
|
||||
|
||||
for (const SortKey& key : keys) {
|
||||
const DrawList::Draw& draw = *key.draw();
|
||||
const RenderStep& renderStep = key.renderStep();
|
||||
@ -473,42 +436,41 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
|
||||
// Make state changes before accumulating new draw data
|
||||
if (pipelineChange) {
|
||||
drawPass->fCommands.emplace_back(BindGraphicsPipeline{key.pipeline()});
|
||||
drawPass->fCommandList.bindGraphicsPipeline(key.pipeline());
|
||||
lastPipeline = key.pipeline();
|
||||
}
|
||||
if (stateChange) {
|
||||
if (geometryUniformChange) {
|
||||
auto binding = geometryUniformBindings.getBinding(key.geometryUniforms());
|
||||
drawPass->fCommands.emplace_back(
|
||||
BindUniformBuffer{binding, UniformSlot::kRenderStep});
|
||||
drawPass->fCommandList.bindUniformBuffer(binding, UniformSlot::kRenderStep);
|
||||
lastGeometryUniforms = key.geometryUniforms();
|
||||
}
|
||||
if (shadingUniformChange) {
|
||||
auto binding = shadingUniformBindings.getBinding(key.shadingUniforms());
|
||||
drawPass->fCommands.emplace_back(
|
||||
BindUniformBuffer{binding, UniformSlot::kPaint});
|
||||
drawPass->fCommandList.bindUniformBuffer(binding, UniformSlot::kPaint);
|
||||
lastShadingUniforms = key.shadingUniforms();
|
||||
}
|
||||
if (textureBindingsChange) {
|
||||
auto textureDataBlock = textureDataCache->lookup(key.textureBindings());
|
||||
BindTexturesAndSamplers bts;
|
||||
bts.fNumTexSamplers = textureDataBlock->numTextures();
|
||||
// TODO: Remove this assert once BindTexturesAndSamplers doesn't have a fixed size
|
||||
// of textures and samplers arrays.
|
||||
SkASSERT(bts.fNumTexSamplers <= 32);
|
||||
for (int i = 0; i < bts.fNumTexSamplers; ++i) {
|
||||
|
||||
int numTextures = textureDataBlock->numTextures();
|
||||
std::vector<int> textureIndices(numTextures);
|
||||
std::vector<int> samplerIndices(numTextures);
|
||||
for (int i = 0; i < numTextures; ++i) {
|
||||
auto& info = textureDataBlock->texture(i);
|
||||
std::tie(bts.fTextureIndices[i], bts.fSamplerIndices[i]) =
|
||||
std::tie(textureIndices[i], samplerIndices[i]) =
|
||||
get_unique_texture_sampler_indices(drawPass->fSampledTextures,
|
||||
drawPass->fSamplerDescs,
|
||||
info);
|
||||
}
|
||||
drawPass->fCommandList.bindTexturesAndSamplers(numTextures,
|
||||
textureIndices.data(),
|
||||
samplerIndices.data());
|
||||
|
||||
drawPass->fCommands.push_back(Command(bts));
|
||||
lastTextureBindings = key.textureBindings();
|
||||
}
|
||||
if (draw.fDrawParams.clip().scissor() != lastScissor) {
|
||||
drawPass->fCommands.emplace_back(SetScissor{draw.fDrawParams.clip().scissor()});
|
||||
drawPass->fCommandList.setScissor(draw.fDrawParams.clip().scissor());
|
||||
lastScissor = draw.fDrawParams.clip().scissor();
|
||||
}
|
||||
}
|
||||
@ -571,72 +533,28 @@ bool DrawPass::prepareResources(ResourceProvider* resourceProvider,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrawPass::addCommands(CommandBuffer* buffer) const {
|
||||
// TODO: Validate RenderPass state against DrawPass's target and requirements?
|
||||
// Generate actual GraphicsPipeline objects combining the target-level properties and each of
|
||||
// the GraphicsPipelineDesc's referenced in this DrawPass.
|
||||
|
||||
// Set viewport to the entire texture for now (eventually, we may have logically smaller bounds
|
||||
// within an approx-sized texture). It is assumed that this also configures the sk_rtAdjust
|
||||
// intrinsic for programs (however the backend chooses to do so).
|
||||
buffer->setViewport(0, 0, fTarget->dimensions().width(), fTarget->dimensions().height());
|
||||
|
||||
for (const Command& c : fCommands.items()) {
|
||||
switch(c.fType) {
|
||||
case CommandType::kBindGraphicsPipeline: {
|
||||
auto& d = c.fBindGraphicsPipeline;
|
||||
buffer->bindGraphicsPipeline(fFullPipelines[d.fPipelineIndex]);
|
||||
} break;
|
||||
case CommandType::kBindUniformBuffer: {
|
||||
auto& d = c.fBindUniformBuffer;
|
||||
buffer->bindUniformBuffer(d.fSlot, sk_ref_sp(d.fInfo.fBuffer), d.fInfo.fOffset);
|
||||
} break;
|
||||
case CommandType::kBindTexturesAndSamplers: {
|
||||
auto& d = c.fBindTexturesAndSamplers;
|
||||
|
||||
for (int i = 0; i < d.fNumTexSamplers; ++i) {
|
||||
SkASSERT(fSampledTextures[d.fTextureIndices[i]]);
|
||||
SkASSERT(fSampledTextures[d.fTextureIndices[i]]->texture());
|
||||
SkASSERT(fSamplers[d.fSamplerIndices[i]]);
|
||||
buffer->bindTextureAndSampler(
|
||||
fSampledTextures[d.fTextureIndices[i]]->refTexture(),
|
||||
fSamplers[d.fSamplerIndices[i]],
|
||||
i);
|
||||
}
|
||||
|
||||
} break;
|
||||
case CommandType::kBindDrawBuffers: {
|
||||
auto& d = c.fBindDrawBuffers;
|
||||
buffer->bindDrawBuffers(d.fVertices, d.fInstances, d.fIndices);
|
||||
break; }
|
||||
case CommandType::kDraw: {
|
||||
auto& d = c.fDraw;
|
||||
buffer->draw(d.fType, d.fBaseVertex, d.fVertexCount);
|
||||
break; }
|
||||
case CommandType::kDrawIndexed: {
|
||||
auto& d = c.fDrawIndexed;
|
||||
buffer->drawIndexed(d.fType, d.fBaseIndex, d.fIndexCount, d.fBaseVertex);
|
||||
break; }
|
||||
case CommandType::kDrawInstanced: {
|
||||
auto& d = c.fDrawInstanced;
|
||||
buffer->drawInstanced(d.fType, d.fBaseVertex, d.fVertexCount,
|
||||
d.fBaseInstance, d.fInstanceCount);
|
||||
break; }
|
||||
case CommandType::kDrawIndexedInstanced: {
|
||||
auto& d = c.fDrawIndexedInstanced;
|
||||
buffer->drawIndexedInstanced(d.fType, d.fBaseIndex, d.fIndexCount, d.fBaseVertex,
|
||||
d.fBaseInstance, d.fInstanceCount);
|
||||
break; }
|
||||
case CommandType::kSetScissor: {
|
||||
auto& d = c.fSetScissor;
|
||||
buffer->setScissor(d.fScissor.fLeft, d.fScissor.fTop,
|
||||
d.fScissor.width(), d.fScissor.height());
|
||||
break;
|
||||
}
|
||||
}
|
||||
void DrawPass::addResourceRefs(CommandBuffer* commandBuffer) const {
|
||||
for (size_t i = 0; i < fFullPipelines.size(); ++i) {
|
||||
commandBuffer->trackResource(fFullPipelines[i]);
|
||||
}
|
||||
for (size_t i = 0; i < fSampledTextures.size(); ++i) {
|
||||
commandBuffer->trackResource(fSampledTextures[i]->refTexture());
|
||||
}
|
||||
for (size_t i = 0; i < fSamplers.size(); ++i) {
|
||||
commandBuffer->trackResource(fSamplers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
const Texture* DrawPass::getTexture(size_t index) const {
|
||||
SkASSERT(index < fSampledTextures.size());
|
||||
SkASSERT(fSampledTextures[index]);
|
||||
SkASSERT(fSampledTextures[index]->texture());
|
||||
return fSampledTextures[index]->texture();
|
||||
}
|
||||
const Sampler* DrawPass::getSampler(size_t index) const {
|
||||
SkASSERT(index < fSamplers.size());
|
||||
SkASSERT(fSamplers[index]);
|
||||
return fSamplers[index].get();
|
||||
}
|
||||
|
||||
} // namespace skgpu::graphite
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "src/core/SkEnumBitMask.h"
|
||||
#include "src/core/SkTBlockList.h"
|
||||
#include "src/gpu/graphite/AttachmentTypes.h"
|
||||
#include "src/gpu/graphite/DrawCommands.h"
|
||||
#include "src/gpu/graphite/DrawTypes.h"
|
||||
#include "src/gpu/graphite/GraphicsPipelineDesc.h"
|
||||
#include "src/gpu/graphite/ResourceTypes.h"
|
||||
@ -35,6 +36,7 @@ class ResourceProvider;
|
||||
class Sampler;
|
||||
struct SamplerDesc;
|
||||
class TextureProxy;
|
||||
class Texture;
|
||||
enum class UniformSlot;
|
||||
|
||||
/**
|
||||
@ -75,140 +77,34 @@ public:
|
||||
size_t vertexBufferSize() const { return 0; }
|
||||
size_t uniformBufferSize() const { return 0; }
|
||||
|
||||
// TODO: Real return types, but it seems useful for DrawPass to report these as sets so that
|
||||
// task execution can compile necessary programs and track resources within a render pass.
|
||||
// Maybe these won't need to be exposed and RenderPassTask can do it per command as needed when
|
||||
// it iterates over the DrawPass contents.
|
||||
void samplers() const {}
|
||||
void programs() const {}
|
||||
|
||||
// Instantiate and prepare any resources used by the DrawPass that require the Recorder's
|
||||
// ResourceProvider. This includes things likes GraphicsPipelines, sampled Textures, Samplers,
|
||||
// etc.
|
||||
bool prepareResources(ResourceProvider*, const RenderPassDesc&);
|
||||
|
||||
// Transform this DrawPass into commands issued to the CommandBuffer. Assumes that the buffer
|
||||
// has already begun a correctly configured render pass matching this pass's target.
|
||||
// Returns true on success; false on failure
|
||||
bool addCommands(CommandBuffer*) const;
|
||||
DrawPassCommands::List::Iter commands() const {
|
||||
return fCommandList.commands();
|
||||
}
|
||||
|
||||
const GraphicsPipeline* getPipeline(size_t index) const {
|
||||
return fFullPipelines[index].get();
|
||||
}
|
||||
const Texture* getTexture(size_t index) const;
|
||||
const Sampler* getSampler(size_t index) const;
|
||||
|
||||
void addResourceRefs(CommandBuffer*) const;
|
||||
|
||||
private:
|
||||
class SortKey;
|
||||
class Drawer;
|
||||
|
||||
struct BindGraphicsPipeline {
|
||||
// Points to a GraphicsPipelineDesc in DrawPass's fPipelineDescs array. It will also
|
||||
// index into a parallel array of full GraphicsPipelines when commands are added to the CB.
|
||||
uint32_t fPipelineIndex;
|
||||
};
|
||||
struct BindUniformBuffer {
|
||||
BindBufferInfo fInfo;
|
||||
UniformSlot fSlot;
|
||||
};
|
||||
struct BindTexturesAndSamplers {
|
||||
int fNumTexSamplers;
|
||||
// TODO: Right now we are hardcoding these arrays to be 32. However, when we rewrite the
|
||||
// command system here to be more flexible and not require fixed sized structs, we will
|
||||
// remove this hardcode size.
|
||||
int fTextureIndices[32];
|
||||
int fSamplerIndices[32];
|
||||
};
|
||||
struct BindDrawBuffers {
|
||||
BindBufferInfo fVertices;
|
||||
BindBufferInfo fInstances;
|
||||
BindBufferInfo fIndices;
|
||||
};
|
||||
struct Draw {
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseVertex;
|
||||
uint32_t fVertexCount;
|
||||
};
|
||||
struct DrawIndexed {
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseIndex;
|
||||
uint32_t fIndexCount;
|
||||
uint32_t fBaseVertex;
|
||||
};
|
||||
struct DrawInstanced {
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseVertex;
|
||||
uint32_t fVertexCount;
|
||||
uint32_t fBaseInstance;
|
||||
uint32_t fInstanceCount;
|
||||
};
|
||||
struct DrawIndexedInstanced {
|
||||
PrimitiveType fType;
|
||||
uint32_t fBaseIndex;
|
||||
uint32_t fIndexCount;
|
||||
uint32_t fBaseVertex;
|
||||
uint32_t fBaseInstance;
|
||||
uint32_t fInstanceCount;
|
||||
};
|
||||
struct SetScissor {
|
||||
SkIRect fScissor;
|
||||
};
|
||||
|
||||
// TODO: BindSampler
|
||||
|
||||
enum class CommandType {
|
||||
kBindGraphicsPipeline,
|
||||
kBindUniformBuffer,
|
||||
kBindTexturesAndSamplers,
|
||||
kBindDrawBuffers,
|
||||
kDraw,
|
||||
kDrawIndexed,
|
||||
kDrawInstanced,
|
||||
kDrawIndexedInstanced,
|
||||
kSetScissor,
|
||||
// kBindSampler
|
||||
};
|
||||
// TODO: The goal is keep all command data in line, vs. type + void* to another data array, but
|
||||
// the current union is memory inefficient. It would be better to have a byte buffer with per
|
||||
// type advances, but then we need to work out alignment etc. so that will be easier to add
|
||||
// once we have something up and running.
|
||||
struct Command {
|
||||
CommandType fType;
|
||||
union {
|
||||
BindGraphicsPipeline fBindGraphicsPipeline;
|
||||
BindUniformBuffer fBindUniformBuffer;
|
||||
BindTexturesAndSamplers fBindTexturesAndSamplers;
|
||||
BindDrawBuffers fBindDrawBuffers;
|
||||
Draw fDraw;
|
||||
DrawIndexed fDrawIndexed;
|
||||
DrawInstanced fDrawInstanced;
|
||||
DrawIndexedInstanced fDrawIndexedInstanced;
|
||||
SetScissor fSetScissor;
|
||||
};
|
||||
|
||||
explicit Command(BindGraphicsPipeline d)
|
||||
: fType(CommandType::kBindGraphicsPipeline), fBindGraphicsPipeline(d) {}
|
||||
explicit Command(BindUniformBuffer d)
|
||||
: fType(CommandType::kBindUniformBuffer), fBindUniformBuffer(d) {}
|
||||
explicit Command(BindTexturesAndSamplers d)
|
||||
: fType(CommandType::kBindTexturesAndSamplers), fBindTexturesAndSamplers(d) {}
|
||||
explicit Command(BindDrawBuffers d)
|
||||
: fType(CommandType::kBindDrawBuffers), fBindDrawBuffers(d) {}
|
||||
explicit Command(Draw d)
|
||||
: fType(CommandType::kDraw), fDraw(d) {}
|
||||
explicit Command(DrawIndexed d)
|
||||
: fType(CommandType::kDrawIndexed), fDrawIndexed(d) {}
|
||||
explicit Command(DrawInstanced d)
|
||||
: fType(CommandType::kDrawInstanced), fDrawInstanced(d) {}
|
||||
explicit Command(DrawIndexedInstanced d)
|
||||
: fType(CommandType::kDrawIndexedInstanced), fDrawIndexedInstanced(d) {}
|
||||
explicit Command(SetScissor d)
|
||||
: fType(CommandType::kSetScissor), fSetScissor(d) {}
|
||||
};
|
||||
// Not strictly necessary, but keeping Command trivially destructible means the command list
|
||||
// can be cleaned up efficiently once it's converted to a command buffer.
|
||||
static_assert(std::is_trivially_destructible<Command>::value);
|
||||
|
||||
DrawPass(sk_sp<TextureProxy> target,
|
||||
std::pair<LoadOp, StoreOp> ops,
|
||||
std::array<float, 4> clearColor,
|
||||
int renderStepCount);
|
||||
|
||||
SkTBlockList<Command, 32> fCommands;
|
||||
DrawPassCommands::List fCommandList;
|
||||
|
||||
// The pipelines are referenced by index in BindGraphicsPipeline, but that will index into a
|
||||
// an array of actual GraphicsPipelines. fPipelineDescs only needs to accumulate encountered
|
||||
// GraphicsPipelineDescs and provide stable pointers, hence SkTBlockList.
|
||||
|
@ -103,23 +103,11 @@ bool RenderPassTask::addCommands(ResourceProvider* resourceProvider, CommandBuff
|
||||
// single sample resolve as an input attachment in that subpass, and then do a draw. The big
|
||||
// thing with Vulkan is that this input attachment and subpass means we also need to update
|
||||
// the fRenderPassDesc here.
|
||||
if (commandBuffer->beginRenderPass(fRenderPassDesc,
|
||||
std::move(colorAttachment),
|
||||
std::move(resolveAttachment),
|
||||
std::move(depthStencilAttachment))) {
|
||||
// Assuming one draw pass per renderpasstask for now
|
||||
SkASSERT(fDrawPasses.size() == 1);
|
||||
for (const auto& drawPass: fDrawPasses) {
|
||||
if (!drawPass->addCommands(commandBuffer)) {
|
||||
commandBuffer->endRenderPass();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
commandBuffer->endRenderPass();
|
||||
}
|
||||
|
||||
return true;
|
||||
return commandBuffer->addRenderPass(fRenderPassDesc,
|
||||
std::move(colorAttachment),
|
||||
std::move(resolveAttachment),
|
||||
std::move(depthStencilAttachment),
|
||||
fDrawPasses);
|
||||
}
|
||||
|
||||
} // namespace skgpu::graphite
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define skgpu_graphite_MtlCommandBuffer_DEFINED
|
||||
|
||||
#include "src/gpu/graphite/CommandBuffer.h"
|
||||
#include "src/gpu/graphite/DrawPass.h"
|
||||
#include "src/gpu/graphite/GpuWorkSubmission.h"
|
||||
#include "src/gpu/graphite/Log.h"
|
||||
|
||||
@ -51,38 +52,47 @@ public:
|
||||
private:
|
||||
MtlCommandBuffer(sk_cfp<id<MTLCommandBuffer>> cmdBuffer, const MtlGpu* gpu);
|
||||
|
||||
bool onBeginRenderPass(const RenderPassDesc&,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture) override;
|
||||
void endRenderPass() override;
|
||||
bool onAddRenderPass(const RenderPassDesc&,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture,
|
||||
const std::vector<std::unique_ptr<DrawPass>>& drawPasses) override;
|
||||
|
||||
void onBindGraphicsPipeline(const GraphicsPipeline*) override;
|
||||
void onBindUniformBuffer(UniformSlot, const Buffer*, size_t offset) override;
|
||||
void onBindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset,
|
||||
const Buffer* instanceBuffer, size_t instanceOffset) override;
|
||||
void onBindIndexBuffer(const Buffer* indexBuffer, size_t offset) override;
|
||||
bool beginRenderPass(const RenderPassDesc&,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture);
|
||||
void endRenderPass();
|
||||
|
||||
void addDrawPass(const DrawPass*);
|
||||
|
||||
void onBindTextureAndSampler(sk_sp<Texture>,
|
||||
sk_sp<Sampler>,
|
||||
unsigned int bindIndex) override;
|
||||
void bindGraphicsPipeline(const GraphicsPipeline*);
|
||||
void setBlendConstants(float* blendConstants);
|
||||
|
||||
void onSetScissor(unsigned int left, unsigned int top,
|
||||
unsigned int width, unsigned int height) override;
|
||||
void onSetViewport(float x, float y, float width, float height,
|
||||
float minDepth, float maxDepth) override;
|
||||
void onSetBlendConstants(std::array<float, 4> blendConstants) override;
|
||||
void bindUniformBuffer(const BindBufferInfo& info, UniformSlot);
|
||||
void bindDrawBuffers(const BindBufferInfo& vertices,
|
||||
const BindBufferInfo& instances,
|
||||
const BindBufferInfo& indices);
|
||||
void bindVertexBuffers(const Buffer* vertexBuffer, size_t vertexOffset,
|
||||
const Buffer* instanceBuffer, size_t instanceOffset);
|
||||
void bindIndexBuffer(const Buffer* indexBuffer, size_t offset);
|
||||
|
||||
void onDraw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount) override;
|
||||
void onDrawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
|
||||
unsigned int baseVertex) override;
|
||||
void onDrawInstanced(PrimitiveType type,
|
||||
unsigned int baseVertex, unsigned int vertexCount,
|
||||
unsigned int baseInstance, unsigned int instanceCount) override;
|
||||
void onDrawIndexedInstanced(PrimitiveType type, unsigned int baseIndex,
|
||||
unsigned int indexCount, unsigned int baseVertex,
|
||||
unsigned int baseInstance, unsigned int instanceCount) override;
|
||||
void bindTextureAndSampler(const Texture*, const Sampler*, unsigned int bindIndex);
|
||||
|
||||
void setScissor(unsigned int left, unsigned int top,
|
||||
unsigned int width, unsigned int height);
|
||||
void setViewport(float x, float y, float width, float height,
|
||||
float minDepth, float maxDepth);
|
||||
|
||||
void draw(PrimitiveType type, unsigned int baseVertex, unsigned int vertexCount);
|
||||
void drawIndexed(PrimitiveType type, unsigned int baseIndex, unsigned int indexCount,
|
||||
unsigned int baseVertex);
|
||||
void drawInstanced(PrimitiveType type,
|
||||
unsigned int baseVertex, unsigned int vertexCount,
|
||||
unsigned int baseInstance, unsigned int instanceCount);
|
||||
void drawIndexedInstanced(PrimitiveType type, unsigned int baseIndex,
|
||||
unsigned int indexCount, unsigned int baseVertex,
|
||||
unsigned int baseInstance, unsigned int instanceCount);
|
||||
|
||||
bool onCopyTextureToBuffer(const Texture*,
|
||||
SkIRect srcRect,
|
||||
|
@ -72,10 +72,27 @@ bool MtlCommandBuffer::commit() {
|
||||
return ((*fCommandBuffer).status != MTLCommandBufferStatusError);
|
||||
}
|
||||
|
||||
bool MtlCommandBuffer::onBeginRenderPass(const RenderPassDesc& renderPassDesc,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture) {
|
||||
bool MtlCommandBuffer::onAddRenderPass(const RenderPassDesc& renderPassDesc,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture,
|
||||
const std::vector<std::unique_ptr<DrawPass>>& drawPasses) {
|
||||
if (!this->beginRenderPass(renderPassDesc, colorTexture, resolveTexture, depthStencilTexture)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < drawPasses.size(); ++i) {
|
||||
this->addDrawPass(drawPasses[i].get());
|
||||
}
|
||||
|
||||
this->endRenderPass();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MtlCommandBuffer::beginRenderPass(const RenderPassDesc& renderPassDesc,
|
||||
const Texture* colorTexture,
|
||||
const Texture* resolveTexture,
|
||||
const Texture* depthStencilTexture) {
|
||||
SkASSERT(!fActiveRenderCommandEncoder);
|
||||
this->endBlitCommandEncoder();
|
||||
#ifdef SK_BUILD_FOR_IOS
|
||||
@ -175,6 +192,92 @@ void MtlCommandBuffer::endRenderPass() {
|
||||
fActiveRenderCommandEncoder.reset();
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::addDrawPass(const DrawPass* drawPass) {
|
||||
drawPass->addResourceRefs(this);
|
||||
|
||||
for (auto[type, cmdPtr] : drawPass->commands()) {
|
||||
switch (type) {
|
||||
case DrawPassCommands::Type::kBindGraphicsPipeline: {
|
||||
auto bgp = static_cast<DrawPassCommands::BindGraphicsPipeline*>(cmdPtr);
|
||||
this->bindGraphicsPipeline(drawPass->getPipeline(bgp->fPipelineIndex));
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kSetBlendConstants: {
|
||||
auto sbc = static_cast<DrawPassCommands::SetBlendConstants*>(cmdPtr);
|
||||
this->setBlendConstants(sbc->fBlendConstants);
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kBindUniformBuffer: {
|
||||
auto bub = static_cast<DrawPassCommands::BindUniformBuffer*>(cmdPtr);
|
||||
this->bindUniformBuffer(bub->fInfo, bub->fSlot);
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kBindDrawBuffers: {
|
||||
auto bdb = static_cast<DrawPassCommands::BindDrawBuffers*>(cmdPtr);
|
||||
this->bindDrawBuffers(bdb->fVertices, bdb->fInstances, bdb->fIndices);
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kBindTexturesAndSamplers: {
|
||||
auto bts = static_cast<DrawPassCommands::BindTexturesAndSamplers*>(cmdPtr);
|
||||
for (int j = 0; j < bts->fNumTexSamplers; ++j) {
|
||||
this->bindTextureAndSampler(drawPass->getTexture(bts->fTextureIndices[j]),
|
||||
drawPass->getSampler(bts->fSamplerIndices[j]),
|
||||
j);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kSetViewport: {
|
||||
auto sv = static_cast<DrawPassCommands::SetViewport*>(cmdPtr);
|
||||
this->setViewport(sv->fViewport.fLeft,
|
||||
sv->fViewport.fTop,
|
||||
sv->fViewport.width(),
|
||||
sv->fViewport.height(),
|
||||
sv->fMinDepth,
|
||||
sv->fMaxDepth);
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kSetScissor: {
|
||||
auto ss = static_cast<DrawPassCommands::SetScissor*>(cmdPtr);
|
||||
const SkIRect& rect = ss->fScissor;
|
||||
this->setScissor(rect.fLeft, rect.fTop, rect.width(), rect.height());
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kDraw: {
|
||||
auto draw = static_cast<DrawPassCommands::Draw*>(cmdPtr);
|
||||
this->draw(draw->fType, draw->fBaseVertex, draw->fVertexCount);
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kDrawIndexed: {
|
||||
auto draw = static_cast<DrawPassCommands::DrawIndexed*>(cmdPtr);
|
||||
this->drawIndexed(draw->fType,
|
||||
draw->fBaseIndex,
|
||||
draw->fIndexCount,
|
||||
draw->fBaseVertex);
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kDrawInstanced: {
|
||||
auto draw = static_cast<DrawPassCommands::DrawInstanced*>(cmdPtr);
|
||||
this->drawInstanced(draw->fType,
|
||||
draw->fBaseVertex,
|
||||
draw->fVertexCount,
|
||||
draw->fBaseInstance,
|
||||
draw->fInstanceCount);
|
||||
break;
|
||||
}
|
||||
case DrawPassCommands::Type::kDrawIndexedInstanced: {
|
||||
auto draw = static_cast<DrawPassCommands::DrawIndexedInstanced*>(cmdPtr);
|
||||
this->drawIndexedInstanced(draw->fType,
|
||||
draw->fBaseIndex,
|
||||
draw->fIndexCount,
|
||||
draw->fBaseVertex,
|
||||
draw->fBaseInstance,
|
||||
draw->fInstanceCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MtlBlitCommandEncoder* MtlCommandBuffer::getBlitCommandEncoder() {
|
||||
if (fActiveBlitCommandEncoder) {
|
||||
return fActiveBlitCommandEncoder.get();
|
||||
@ -205,7 +308,7 @@ void MtlCommandBuffer::endBlitCommandEncoder() {
|
||||
}
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onBindGraphicsPipeline(const GraphicsPipeline* graphicsPipeline) {
|
||||
void MtlCommandBuffer::bindGraphicsPipeline(const GraphicsPipeline* graphicsPipeline) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
auto mtlPipeline = static_cast<const MtlGraphicsPipeline*>(graphicsPipeline);
|
||||
@ -220,13 +323,11 @@ void MtlCommandBuffer::onBindGraphicsPipeline(const GraphicsPipeline* graphicsPi
|
||||
fCurrentInstanceStride = mtlPipeline->instanceStride();
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onBindUniformBuffer(UniformSlot slot,
|
||||
const Buffer* uniformBuffer,
|
||||
size_t uniformOffset) {
|
||||
void MtlCommandBuffer::bindUniformBuffer(const BindBufferInfo& info, UniformSlot slot) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
id<MTLBuffer> mtlBuffer = uniformBuffer ?
|
||||
static_cast<const MtlBuffer*>(uniformBuffer)->mtlBuffer() : nullptr;
|
||||
id<MTLBuffer> mtlBuffer = info.fBuffer ?
|
||||
static_cast<const MtlBuffer*>(info.fBuffer)->mtlBuffer() : nullptr;
|
||||
|
||||
unsigned int bufferIndex;
|
||||
switch(slot) {
|
||||
@ -238,14 +339,24 @@ void MtlCommandBuffer::onBindUniformBuffer(UniformSlot slot,
|
||||
break;
|
||||
}
|
||||
|
||||
fActiveRenderCommandEncoder->setVertexBuffer(mtlBuffer, uniformOffset, bufferIndex);
|
||||
fActiveRenderCommandEncoder->setFragmentBuffer(mtlBuffer, uniformOffset, bufferIndex);
|
||||
fActiveRenderCommandEncoder->setVertexBuffer(mtlBuffer, info.fOffset, bufferIndex);
|
||||
fActiveRenderCommandEncoder->setFragmentBuffer(mtlBuffer, info.fOffset, bufferIndex);
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onBindVertexBuffers(const Buffer* vertexBuffer,
|
||||
size_t vertexOffset,
|
||||
const Buffer* instanceBuffer,
|
||||
size_t instanceOffset) {
|
||||
void MtlCommandBuffer::bindDrawBuffers(const BindBufferInfo& vertices,
|
||||
const BindBufferInfo& instances,
|
||||
const BindBufferInfo& indices) {
|
||||
this->bindVertexBuffers(vertices.fBuffer,
|
||||
vertices.fOffset,
|
||||
instances.fBuffer,
|
||||
instances.fOffset);
|
||||
this->bindIndexBuffer(indices.fBuffer, indices.fOffset);
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::bindVertexBuffers(const Buffer* vertexBuffer,
|
||||
size_t vertexOffset,
|
||||
const Buffer* instanceBuffer,
|
||||
size_t instanceOffset) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
if (vertexBuffer) {
|
||||
@ -264,7 +375,7 @@ void MtlCommandBuffer::onBindVertexBuffers(const Buffer* vertexBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onBindIndexBuffer(const Buffer* indexBuffer, size_t offset) {
|
||||
void MtlCommandBuffer::bindIndexBuffer(const Buffer* indexBuffer, size_t offset) {
|
||||
if (indexBuffer) {
|
||||
fCurrentIndexBuffer = static_cast<const MtlBuffer*>(indexBuffer)->mtlBuffer();
|
||||
fCurrentIndexBufferOffset = offset;
|
||||
@ -274,26 +385,26 @@ void MtlCommandBuffer::onBindIndexBuffer(const Buffer* indexBuffer, size_t offse
|
||||
}
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onBindTextureAndSampler(sk_sp<Texture> texture,
|
||||
sk_sp<Sampler> sampler,
|
||||
unsigned int bindIndex) {
|
||||
void MtlCommandBuffer::bindTextureAndSampler(const Texture* texture,
|
||||
const Sampler* sampler,
|
||||
unsigned int bindIndex) {
|
||||
SkASSERT(texture && sampler);
|
||||
|
||||
id<MTLTexture> mtlTexture = ((MtlTexture*)texture.get())->mtlTexture();
|
||||
id<MTLSamplerState> mtlSamplerState = ((MtlSampler*)sampler.get())->mtlSamplerState();
|
||||
id<MTLTexture> mtlTexture = ((const MtlTexture*)texture)->mtlTexture();
|
||||
id<MTLSamplerState> mtlSamplerState = ((const MtlSampler*)sampler)->mtlSamplerState();
|
||||
fActiveRenderCommandEncoder->setFragmentTexture(mtlTexture, bindIndex);
|
||||
fActiveRenderCommandEncoder->setFragmentSamplerState(mtlSamplerState, bindIndex);
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onSetScissor(unsigned int left, unsigned int top,
|
||||
unsigned int width, unsigned int height) {
|
||||
void MtlCommandBuffer::setScissor(unsigned int left, unsigned int top,
|
||||
unsigned int width, unsigned int height) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
MTLScissorRect scissorRect = { left, top, width, height };
|
||||
fActiveRenderCommandEncoder->setScissorRect(scissorRect);
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onSetViewport(float x, float y, float width, float height,
|
||||
float minDepth, float maxDepth) {
|
||||
void MtlCommandBuffer::setViewport(float x, float y, float width, float height,
|
||||
float minDepth, float maxDepth) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
MTLViewport viewport = { x, y, width, height, minDepth, maxDepth };
|
||||
fActiveRenderCommandEncoder->setViewport(viewport);
|
||||
@ -308,10 +419,10 @@ void MtlCommandBuffer::onSetViewport(float x, float y, float width, float height
|
||||
MtlGraphicsPipeline::kIntrinsicUniformBufferIndex);
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onSetBlendConstants(std::array<float, 4> blendConstants) {
|
||||
void MtlCommandBuffer::setBlendConstants(float* blendConstants) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
fActiveRenderCommandEncoder->setBlendColor(blendConstants.data());
|
||||
fActiveRenderCommandEncoder->setBlendColor(blendConstants);
|
||||
}
|
||||
|
||||
static MTLPrimitiveType graphite_to_mtl_primitive(PrimitiveType primitiveType) {
|
||||
@ -328,9 +439,9 @@ static MTLPrimitiveType graphite_to_mtl_primitive(PrimitiveType primitiveType) {
|
||||
return mtlPrimitiveType[static_cast<int>(primitiveType)];
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onDraw(PrimitiveType type,
|
||||
unsigned int baseVertex,
|
||||
unsigned int vertexCount) {
|
||||
void MtlCommandBuffer::draw(PrimitiveType type,
|
||||
unsigned int baseVertex,
|
||||
unsigned int vertexCount) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
auto mtlPrimitiveType = graphite_to_mtl_primitive(type);
|
||||
@ -338,8 +449,8 @@ void MtlCommandBuffer::onDraw(PrimitiveType type,
|
||||
fActiveRenderCommandEncoder->drawPrimitives(mtlPrimitiveType, baseVertex, vertexCount);
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onDrawIndexed(PrimitiveType type, unsigned int baseIndex,
|
||||
unsigned int indexCount, unsigned int baseVertex) {
|
||||
void MtlCommandBuffer::drawIndexed(PrimitiveType type, unsigned int baseIndex,
|
||||
unsigned int indexCount, unsigned int baseVertex) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
@ -357,9 +468,9 @@ void MtlCommandBuffer::onDrawIndexed(PrimitiveType type, unsigned int baseIndex,
|
||||
}
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onDrawInstanced(PrimitiveType type, unsigned int baseVertex,
|
||||
unsigned int vertexCount, unsigned int baseInstance,
|
||||
unsigned int instanceCount) {
|
||||
void MtlCommandBuffer::drawInstanced(PrimitiveType type, unsigned int baseVertex,
|
||||
unsigned int vertexCount, unsigned int baseInstance,
|
||||
unsigned int instanceCount) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
auto mtlPrimitiveType = graphite_to_mtl_primitive(type);
|
||||
@ -369,12 +480,12 @@ void MtlCommandBuffer::onDrawInstanced(PrimitiveType type, unsigned int baseVert
|
||||
instanceCount, baseInstance);
|
||||
}
|
||||
|
||||
void MtlCommandBuffer::onDrawIndexedInstanced(PrimitiveType type,
|
||||
unsigned int baseIndex,
|
||||
unsigned int indexCount,
|
||||
unsigned int baseVertex,
|
||||
unsigned int baseInstance,
|
||||
unsigned int instanceCount) {
|
||||
void MtlCommandBuffer::drawIndexedInstanced(PrimitiveType type,
|
||||
unsigned int baseIndex,
|
||||
unsigned int indexCount,
|
||||
unsigned int baseVertex,
|
||||
unsigned int baseInstance,
|
||||
unsigned int instanceCount) {
|
||||
SkASSERT(fActiveRenderCommandEncoder);
|
||||
|
||||
if (@available(macOS 10.11, iOS 9.0, *)) {
|
||||
|
Loading…
Reference in New Issue
Block a user