[graphite] Add Combination to GraphicsPipelineDesc
Change-Id: I7fa9b4da48f993143ade3b8030e2c67831cf0ffd Reviewed-on: https://skia-review.googlesource.com/c/skia/+/475257 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
a0ad6db141
commit
0814e7fb6a
@ -11,9 +11,10 @@
|
||||
#include "experimental/graphite/src/CommandBuffer.h"
|
||||
#include "experimental/graphite/src/ContextUtils.h"
|
||||
#include "experimental/graphite/src/Gpu.h"
|
||||
#include "experimental/graphite/src/ProgramCache.h"
|
||||
#include "experimental/graphite/src/GraphicsPipelineDesc.h"
|
||||
#include "experimental/graphite/src/Recorder.h"
|
||||
#include "experimental/graphite/src/Recording.h"
|
||||
#include "experimental/graphite/src/Renderer.h"
|
||||
|
||||
#ifdef SK_METAL
|
||||
#include "experimental/graphite/src/mtl/MtlTrampoline.h"
|
||||
@ -55,21 +56,23 @@ void Context::submit(SyncToCpu syncToCpu) {
|
||||
}
|
||||
|
||||
void Context::preCompile(const PaintCombo& paintCombo) {
|
||||
ProgramCache cache;
|
||||
|
||||
for (auto bm: paintCombo.fBlendModes) {
|
||||
for (auto& shaderCombo: paintCombo.fShaders) {
|
||||
for (auto shaderType: shaderCombo.fTypes) {
|
||||
for (auto tm: shaderCombo.fTileModes) {
|
||||
Combination c {shaderType, tm, bm};
|
||||
|
||||
sk_sp<ProgramCache::ProgramInfo> pi = cache.findOrCreateProgram(c);
|
||||
// TODO: this should be getSkSL
|
||||
// TODO: it should also return the uniform information
|
||||
std::string msl = pi->getMSL();
|
||||
// TODO: compile the MSL and store the result back into the ProgramInfo
|
||||
// To do this we will need the path rendering options from Chris and
|
||||
// a stock set of RenderPasses.
|
||||
GraphicsPipelineDesc desc;
|
||||
|
||||
for (const Renderer* r : {&Renderer::StencilAndFillPath()}) {
|
||||
for (auto&& s : r->steps()) {
|
||||
desc.setProgram(s, c);
|
||||
// TODO: Combine with renderpass description set to generate full
|
||||
// GraphicsPipeline and MSL program. Cache that compiled pipeline on
|
||||
// the resource provider in a map from desc -> pipeline so that any
|
||||
// later desc created from equivalent RenderStep + Combination get it.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,30 @@ static constexpr Uniform kSolidUniforms[kNumSolidUniforms] {
|
||||
{"color", SLType::kFloat4 }
|
||||
};
|
||||
|
||||
static const char* kLinearGradientMSL =
|
||||
// TODO: This should use local coords
|
||||
"float2 pos = interpolated.position.xy;\n"
|
||||
"float2 delta = uniforms.point1 - uniforms.point0;\n"
|
||||
"float2 pt = pos - uniforms.point0;\n"
|
||||
"float t = dot(pt, delta) / dot(delta, delta);\n"
|
||||
"float4 result = uniforms.colors[0];\n"
|
||||
"result = mix(result, uniforms.colors[1],\n"
|
||||
" clamp((t-uniforms.offsets[0])/(uniforms.offsets[1]-uniforms.offsets[0]),\n"
|
||||
" 0, 1));\n"
|
||||
"result = mix(result, uniforms.colors[2],\n"
|
||||
" clamp((t-uniforms.offsets[1])/(uniforms.offsets[2]-uniforms.offsets[1]),\n"
|
||||
" 0, 1));\n"
|
||||
"result = mix(result, uniforms.colors[3],\n"
|
||||
" clamp((t-uniforms.offsets[2])/(uniforms.offsets[3]-uniforms.offsets[2]),\n"
|
||||
" 0, 1));\n"
|
||||
"out.color = result;\n";
|
||||
|
||||
static const char* kSolidColorMSL = "out.color = float4(uniforms.color);\n";
|
||||
|
||||
// TODO: kNone is for depth-only draws, so should actually have a fragment output type
|
||||
// that only defines a [[depth]] attribute but no color calculation.
|
||||
static const char* kNoneMSL = "out.color float4(0.0, 0.0, 1.0, 1.0);\n";
|
||||
|
||||
sk_sp<UniformData> make_gradient_uniform_data_common(void* srcs[kNumGradientUniforms]) {
|
||||
UniformManager mgr(Layout::kMetal);
|
||||
|
||||
@ -268,60 +292,33 @@ std::tuple<Combination, sk_sp<UniformData>> ExtractCombo(const PaintParams& p) {
|
||||
return { result, std::move(uniforms) };
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO: use a SkSpan for the parameters
|
||||
std::string emit_MSL_uniform_struct(const Uniform *uniforms, int numUniforms) {
|
||||
std::string result;
|
||||
|
||||
result.append("struct FragmentUniforms {\n");
|
||||
for (int i = 0; i < numUniforms; ++i) {
|
||||
// TODO: this is sufficient for the sprint but should be changed to use SkSL's
|
||||
// machinery
|
||||
switch (uniforms[i].type()) {
|
||||
case SLType::kFloat4:
|
||||
result.append("vector_float4");
|
||||
break;
|
||||
case SLType::kFloat2:
|
||||
result.append("vector_float2");
|
||||
break;
|
||||
case SLType::kFloat:
|
||||
result.append("float");
|
||||
break;
|
||||
case SLType::kHalf4:
|
||||
result.append("vector_half4");
|
||||
break;
|
||||
default:
|
||||
SkASSERT(0);
|
||||
}
|
||||
|
||||
result.append(" ");
|
||||
result.append(uniforms[i].name());
|
||||
if (uniforms[i].count()) {
|
||||
result.append("[");
|
||||
result.append(std::to_string(uniforms[i].count()));
|
||||
result.append("]");
|
||||
}
|
||||
result.append(";\n");
|
||||
}
|
||||
result.append("};\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::string GetMSLUniformStruct(ShaderCombo::ShaderType shaderType) {
|
||||
SkSpan<const Uniform> GetUniforms(ShaderCombo::ShaderType shaderType) {
|
||||
switch (shaderType) {
|
||||
case ShaderCombo::ShaderType::kLinearGradient:
|
||||
case ShaderCombo::ShaderType::kRadialGradient:
|
||||
case ShaderCombo::ShaderType::kSweepGradient:
|
||||
case ShaderCombo::ShaderType::kConicalGradient:
|
||||
return emit_MSL_uniform_struct(kGradientUniforms, kNumGradientUniforms);
|
||||
return SkMakeSpan(kGradientUniforms, kNumGradientUniforms);
|
||||
case ShaderCombo::ShaderType::kNone:
|
||||
return "";
|
||||
return {nullptr, 0};
|
||||
case ShaderCombo::ShaderType::kSolidColor:
|
||||
default:
|
||||
return emit_MSL_uniform_struct(kSolidUniforms, kNumSolidUniforms);
|
||||
return SkMakeSpan(kSolidUniforms, kNumSolidUniforms);
|
||||
}
|
||||
}
|
||||
|
||||
const char* GetShaderMSL(ShaderCombo::ShaderType shaderType) {
|
||||
switch (shaderType) {
|
||||
case ShaderCombo::ShaderType::kLinearGradient:
|
||||
return kLinearGradientMSL;
|
||||
case ShaderCombo::ShaderType::kNone:
|
||||
return kNoneMSL;
|
||||
case ShaderCombo::ShaderType::kRadialGradient:
|
||||
case ShaderCombo::ShaderType::kSweepGradient:
|
||||
case ShaderCombo::ShaderType::kConicalGradient:
|
||||
case ShaderCombo::ShaderType::kSolidColor:
|
||||
default:
|
||||
return kSolidColorMSL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "experimental/graphite/include/Context.h"
|
||||
#include "include/core/SkBlendMode.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSpan.h"
|
||||
#include "include/core/SkTileMode.h"
|
||||
|
||||
namespace skgpu {
|
||||
@ -86,7 +87,13 @@ private:
|
||||
};
|
||||
|
||||
std::tuple<Combination, sk_sp<UniformData>> ExtractCombo(const PaintParams&);
|
||||
std::string GetMSLUniformStruct(ShaderCombo::ShaderType);
|
||||
SkSpan<const Uniform> GetUniforms(ShaderCombo::ShaderType);
|
||||
|
||||
// TODO: Temporary way to get at MSL snippet for handling the given shader type, which will be
|
||||
// embedded in the fragment function's body. It has access to the vertex output via a "interpolated"
|
||||
// variable, and must have a statement that writes to a float4 "out.color". Its uniforms (as defined
|
||||
// by GetUniforms(type)) are available as a variable named "uniforms".
|
||||
const char* GetShaderMSL(ShaderCombo::ShaderType);
|
||||
|
||||
} // namespace skgpu
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "experimental/graphite/src/DrawContext.h"
|
||||
#include "experimental/graphite/src/DrawList.h"
|
||||
#include "experimental/graphite/src/DrawWriter.h"
|
||||
#include "experimental/graphite/src/ProgramCache.h"
|
||||
#include "experimental/graphite/src/GraphicsPipelineDesc.h"
|
||||
#include "experimental/graphite/src/Recorder.h"
|
||||
#include "experimental/graphite/src/Renderer.h"
|
||||
#include "experimental/graphite/src/TextureProxy.h"
|
||||
@ -28,20 +28,7 @@
|
||||
#include "src/gpu/BufferWriter.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
// Retrieve the program ID and uniformData ID
|
||||
std::tuple<uint32_t, uint32_t> get_ids_from_paint(skgpu::Recorder* recorder,
|
||||
skgpu::PaintParams params) {
|
||||
// TODO: perhaps just return the ids here rather than the sk_sps?
|
||||
auto [ combo, uniformData] = ExtractCombo(params);
|
||||
auto programInfo = recorder->programCache()->findOrCreateProgram(combo);
|
||||
auto uniformID = recorder->uniformCache()->insert(std::move(uniformData));
|
||||
return { programInfo->id(), uniformID };
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
#include <unordered_map>
|
||||
|
||||
namespace skgpu {
|
||||
|
||||
@ -226,19 +213,24 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
// If we have two different descriptors, such that the uniforms from the PaintParams can be
|
||||
// bound independently of those used by the rest of the RenderStep, then we can upload now
|
||||
// and remember the location for re-use on any RenderStep that does shading.
|
||||
uint32_t programID = ProgramCache::kInvalidProgramID;
|
||||
uint32_t shadingUniformID = UniformCache::kInvalidUniformID;
|
||||
Combination shader;
|
||||
sk_sp<UniformData> shadingUniforms = nullptr;
|
||||
uint32_t shadingIndex = UniformCache::kInvalidUniformID;
|
||||
if (draw.fPaintParams.has_value()) {
|
||||
std::tie(programID, shadingUniformID) = get_ids_from_paint(recorder,
|
||||
draw.fPaintParams.value());
|
||||
}
|
||||
std::tie(shader, shadingUniforms) = ExtractCombo(draw.fPaintParams.value());
|
||||
shadingIndex = recorder->uniformCache()->insert(shadingUniforms);
|
||||
} // else depth-only
|
||||
|
||||
for (int stepIndex = 0; stepIndex < draw.fRenderer.numRenderSteps(); ++stepIndex) {
|
||||
const RenderStep* const step = draw.fRenderer.steps()[stepIndex];
|
||||
const bool performsShading = draw.fPaintParams.has_value() && step->performsShading();
|
||||
|
||||
// TODO ask step to generate a pipeline description based on the above shading code, and
|
||||
// have pipelineIndex point to that description in the accumulated list of descs
|
||||
uint32_t pipelineIndex = 0;
|
||||
Combination stepShader;
|
||||
uint32_t stepShadingIndex = UniformCache::kInvalidUniformID;
|
||||
if (performsShading) {
|
||||
stepShader = shader;
|
||||
stepShadingIndex = shadingIndex;
|
||||
} // else depth-only draw or stencil-only step of renderer so no shading is needed
|
||||
|
||||
uint32_t geometryIndex = UniformCache::kInvalidUniformID;
|
||||
if (step->numUniforms() > 0) {
|
||||
@ -254,19 +246,13 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t shadingIndex = UniformCache::kInvalidUniformID;
|
||||
GraphicsPipelineDesc desc;
|
||||
desc.setProgram(step, stepShader);
|
||||
uint32_t pipelineIndex = 0;
|
||||
|
||||
const bool performsShading = draw.fPaintParams.has_value() && step->performsShading();
|
||||
if (performsShading) {
|
||||
// TODO: we need to combine the 'programID' with the RenderPass info and the
|
||||
// geometric rendering method to get the true 'pipelineIndex'
|
||||
pipelineIndex = programID;
|
||||
shadingIndex = shadingUniformID;
|
||||
} else {
|
||||
// TODO: fill in 'pipelineIndex' for Chris' stencil/depth draws
|
||||
}
|
||||
// TODO: Have a map from descriptions to uint32_ts for the SortKey
|
||||
|
||||
keys.push_back({&draw, stepIndex, pipelineIndex, geometryIndex, shadingIndex});
|
||||
keys.push_back({&draw, stepIndex, pipelineIndex, geometryIndex, stepShadingIndex});
|
||||
}
|
||||
|
||||
passBounds.join(draw.fClip.drawBounds());
|
||||
@ -287,8 +273,9 @@ std::unique_ptr<DrawPass> DrawPass::Make(Recorder* recorder,
|
||||
Drawer drawer;
|
||||
DrawWriter drawWriter(&drawer, bufferMgr);
|
||||
|
||||
// Used to track when a new pipeline or dynamic state needs recording between draw steps
|
||||
uint32_t lastPipeline = 0;
|
||||
// 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.
|
||||
uint32_t lastPipeline = draws->renderStepCount();
|
||||
uint32_t lastShadingUniforms = UniformCache::kInvalidUniformID;
|
||||
uint32_t lastGeometryUniforms = UniformCache::kInvalidUniformID;
|
||||
SkIRect lastScissor = SkIRect::MakeSize(target->dimensions());
|
||||
|
@ -11,9 +11,11 @@
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include "experimental/graphite/src/Attribute.h"
|
||||
#include "experimental/graphite/src/ContextUtils.h"
|
||||
#include "experimental/graphite/src/DrawTypes.h"
|
||||
#include "include/private/SkTArray.h"
|
||||
|
||||
#include <array>
|
||||
namespace skgpu {
|
||||
|
||||
class RenderStep;
|
||||
@ -45,32 +47,32 @@ public:
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// Describes the geometric portion of the pipeline's program and the pipeline's fixed state
|
||||
// (except for renderpass-level state that will never change between draws).
|
||||
const RenderStep* renderStep() const { return fRenderStep; }
|
||||
void setRenderStep(const RenderStep* step) {
|
||||
// Key describing the color shading tree of the pipeline's program
|
||||
Combination shaderCombo() const { return fCombination; }
|
||||
|
||||
void setProgram(const RenderStep* step, const Combination& shaderCombo) {
|
||||
SkASSERT(step);
|
||||
fRenderStep = step;
|
||||
|
||||
static constexpr int kWords = sizeof(uintptr_t) / sizeof(uint32_t);
|
||||
static_assert(sizeof(uintptr_t) % sizeof(uint32_t) == 0);
|
||||
|
||||
if (fKey.count() < kWords) {
|
||||
fKey.push_back_n(kWords - fKey.count());
|
||||
}
|
||||
fCombination = shaderCombo;
|
||||
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(fRenderStep);
|
||||
memcpy(fKey.data(), &addr, sizeof(uintptr_t));
|
||||
fKey[kWords - 1] = shaderCombo.key();
|
||||
}
|
||||
|
||||
private:
|
||||
// Estimate of max expected key size
|
||||
// TODO: flesh this out
|
||||
inline static constexpr int kPreAllocSize = 1;
|
||||
// The key is the RenderStep address and the uint32_t key from Combination
|
||||
static constexpr int kWords = sizeof(uintptr_t) / sizeof(uint32_t) + 1;
|
||||
static_assert(sizeof(uintptr_t) % sizeof(uint32_t) == 0);
|
||||
|
||||
// TODO: I wonder if we could expose the "key" as just a char[] union over the renderstep and
|
||||
// paint combination? That would avoid extra size, but definitely locks GraphicsPipelineDesc
|
||||
// keys to the current process, which is probably okay since we can have something a with a more
|
||||
// stable hash used for the pre-compilation combos.
|
||||
SkSTArray<kPreAllocSize, uint32_t, true> fKey;
|
||||
std::array<uint32_t, kWords> fKey;
|
||||
|
||||
// Each RenderStep defines a fixed set of attributes and rasterization state, as well as the
|
||||
// shader fragments that control the geometry and coverage calculations. The RenderStep's shader
|
||||
@ -78,6 +80,12 @@ private:
|
||||
// RenderStep is fixed, its pointer can be used as a proxy for everything that it specifies in
|
||||
// the GraphicsPipeline.
|
||||
const RenderStep* fRenderStep = nullptr;
|
||||
|
||||
// TODO: Right now the Combination is roughly the equivalent of the PaintBlob description, so
|
||||
// eventually it won't be a fixed size, as it can eventually represent arbitrary shader trees.
|
||||
// However, in that world, each PaintBlob structure will have a unique ID and a map from ID to
|
||||
// blob, so the GraphicsPipelineDesc can be reduced to just storing RenderStep + unique ID int.
|
||||
Combination fCombination;
|
||||
};
|
||||
|
||||
} // namespace skgpu
|
||||
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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_ProgramCache_DEFINED
|
||||
#define skgpu_ProgramCache_DEFINED
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "experimental/graphite/src/ContextUtils.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
|
||||
namespace skgpu {
|
||||
|
||||
class ProgramCache {
|
||||
public:
|
||||
ProgramCache();
|
||||
|
||||
static constexpr uint32_t kInvalidProgramID = 0;
|
||||
|
||||
// TODO: this is a bit underspecified. It still needs the rendering technique info.
|
||||
// Additionally, it still needs an entry point to generate the text of the program.
|
||||
class ProgramInfo : public SkRefCnt {
|
||||
public:
|
||||
ProgramInfo(uint32_t uniqueID, Combination c);
|
||||
~ProgramInfo() override;
|
||||
|
||||
uint32_t id() const { return fID; }
|
||||
Combination combo() const { return fCombination; }
|
||||
|
||||
std::string getMSL() const;
|
||||
|
||||
private:
|
||||
const uint32_t fID;
|
||||
const Combination fCombination;
|
||||
// TODO: store the rendering technique info from Chris here
|
||||
};
|
||||
|
||||
// TODO: we need the rendering technique info from Chris for this look up
|
||||
sk_sp<ProgramInfo> findOrCreateProgram(Combination);
|
||||
|
||||
sk_sp<ProgramInfo> lookup(uint32_t uniqueID);
|
||||
|
||||
// The number of unique programs in the cache
|
||||
size_t count() const {
|
||||
SkASSERT(fProgramHash.size()+1 == fProgramVector.size());
|
||||
return fProgramHash.size();
|
||||
}
|
||||
|
||||
private:
|
||||
struct Hash {
|
||||
size_t operator()(Combination) const;
|
||||
};
|
||||
|
||||
std::unordered_map<Combination, sk_sp<ProgramInfo>, Hash> fProgramHash;
|
||||
std::vector<sk_sp<ProgramInfo>> fProgramVector;
|
||||
// The ProgramInfo's unique ID is only unique w/in a Recorder _not_ globally
|
||||
uint32_t fNextUniqueID = 1;
|
||||
};
|
||||
|
||||
} // namespace skgpu
|
||||
|
||||
#endif // skgpu_ProgramCache_DEFINED
|
@ -12,7 +12,6 @@
|
||||
#include "experimental/graphite/src/ContextPriv.h"
|
||||
#include "experimental/graphite/src/DrawBufferManager.h"
|
||||
#include "experimental/graphite/src/Gpu.h"
|
||||
#include "experimental/graphite/src/ProgramCache.h"
|
||||
#include "experimental/graphite/src/Recording.h"
|
||||
#include "experimental/graphite/src/ResourceProvider.h"
|
||||
#include "experimental/graphite/src/UniformCache.h"
|
||||
@ -21,7 +20,6 @@ namespace skgpu {
|
||||
|
||||
Recorder::Recorder(sk_sp<Context> context)
|
||||
: fContext(std::move(context))
|
||||
, fProgramCache(new ProgramCache)
|
||||
, fUniformCache(new UniformCache)
|
||||
// TODO: Is '4' the correct initial alignment?
|
||||
, fDrawBufferManager(new DrawBufferManager(fContext->priv().gpu()->resourceProvider(), 4)) {
|
||||
@ -33,10 +31,6 @@ Context* Recorder::context() const {
|
||||
return fContext.get();
|
||||
}
|
||||
|
||||
ProgramCache* Recorder::programCache() {
|
||||
return fProgramCache.get();
|
||||
}
|
||||
|
||||
UniformCache* Recorder::uniformCache() {
|
||||
return fUniformCache.get();
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ namespace skgpu {
|
||||
|
||||
class Context;
|
||||
class DrawBufferManager;
|
||||
class ProgramCache;
|
||||
class Recording;
|
||||
class UniformCache;
|
||||
|
||||
@ -27,7 +26,6 @@ public:
|
||||
void add(sk_sp<Task>);
|
||||
|
||||
Context* context() const;
|
||||
ProgramCache* programCache();
|
||||
UniformCache* uniformCache();
|
||||
DrawBufferManager* drawBufferManager();
|
||||
|
||||
@ -37,7 +35,6 @@ protected:
|
||||
private:
|
||||
sk_sp<Context> fContext;
|
||||
TaskGraph fGraph;
|
||||
std::unique_ptr<ProgramCache> fProgramCache;
|
||||
std::unique_ptr<UniformCache> fUniformCache;
|
||||
std::unique_ptr<DrawBufferManager> fDrawBufferManager;
|
||||
};
|
||||
|
@ -121,6 +121,9 @@ SkSL::String get_msl(const GraphicsPipelineDesc& desc) {
|
||||
"typedef struct {\n"
|
||||
" float4 position [[position]];\n"
|
||||
"} VertexOutput;\n"
|
||||
"typedef struct {\n"
|
||||
" float4 color [[color(0)]];\n"
|
||||
"} FragmentOutput;\n"
|
||||
"\n";
|
||||
|
||||
// Typedefs needed by RenderStep
|
||||
@ -151,14 +154,16 @@ SkSL::String get_msl(const GraphicsPipelineDesc& desc) {
|
||||
"}\n";
|
||||
|
||||
// Typedefs needed for painting
|
||||
// TODO: Right now hardcoded float4 color uniform but will come from Combination once that is
|
||||
// stored on the GraphicsPipelineDesc.
|
||||
msl += "struct PaintUniforms {\n"
|
||||
" float4 color;\n"
|
||||
"};\n";
|
||||
msl += "fragment float4 fragmentMain(VertexOutput in [[stage_in]],\n"
|
||||
" constant PaintUniforms& uniforms [[buffer(1)]]) {\n"
|
||||
" return uniforms.color;\n"
|
||||
auto paintUniforms = GetUniforms(desc.shaderCombo().fShaderType);
|
||||
if (!paintUniforms.empty()) {
|
||||
msl += emit_MSL_uniform_struct("FragUniforms", paintUniforms);
|
||||
}
|
||||
|
||||
msl += "fragment FragmentOutput fragmentMain(VertexOutput interpolated [[stage_in]],\n"
|
||||
" constant FragUniforms& uniforms [[buffer(1)]]) {\n"
|
||||
" FragmentOutput out;\n";
|
||||
msl += GetShaderMSL(desc.shaderCombo().fShaderType);
|
||||
msl += " return out;\n"
|
||||
"}\n";
|
||||
|
||||
return msl;
|
||||
|
@ -56,8 +56,6 @@ skia_graphite_sources = [
|
||||
"$_src/GraphicsPipelineDesc.h",
|
||||
"$_src/Image_Graphite.cpp",
|
||||
"$_src/Image_Graphite.h",
|
||||
"$_src/ProgramCache.cpp",
|
||||
"$_src/ProgramCache.h",
|
||||
"$_src/Recorder.cpp",
|
||||
"$_src/Recorder.h",
|
||||
"$_src/Recording.cpp",
|
||||
|
@ -333,7 +333,6 @@ graphite_tests_sources = [
|
||||
"$_tests/graphite/CommandBufferTest.cpp",
|
||||
"$_tests/graphite/IntersectionTreeTest.cpp",
|
||||
"$_tests/graphite/MaskTest.cpp",
|
||||
"$_tests/graphite/ProgramCacheTest.cpp",
|
||||
"$_tests/graphite/RectTest.cpp",
|
||||
"$_tests/graphite/ShapeTest.cpp",
|
||||
"$_tests/graphite/TransformTest.cpp",
|
||||
|
@ -257,6 +257,7 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
DrawBufferManager bufferMgr(gpu->resourceProvider(), 4);
|
||||
|
||||
commandBuffer->beginRenderPass(renderPassDesc);
|
||||
|
||||
DrawWriter drawWriter(commandBuffer->asDrawDispatcher(), &bufferMgr);
|
||||
|
||||
struct RectAndColor {
|
||||
@ -265,8 +266,9 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
};
|
||||
|
||||
auto draw = [&](const RenderStep* step, std::vector<RectAndColor> draws) {
|
||||
Combination shader{ShaderCombo::ShaderType::kSolidColor};
|
||||
GraphicsPipelineDesc pipelineDesc;
|
||||
pipelineDesc.setRenderStep(step);
|
||||
pipelineDesc.setProgram(step, shader);
|
||||
drawWriter.newPipelineState(step->primitiveType(),
|
||||
step->vertexStride(),
|
||||
step->instanceStride());
|
||||
@ -283,17 +285,16 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
bufferMgr.getUniformWriter(renderStepUniforms->dataSize());
|
||||
writer.write(renderStepUniforms->data(), renderStepUniforms->dataSize());
|
||||
commandBuffer->bindUniformBuffer(UniformSlot::kRenderStep,
|
||||
sk_ref_sp(bindInfo.fBuffer),
|
||||
bindInfo.fOffset);
|
||||
sk_ref_sp(bindInfo.fBuffer),
|
||||
bindInfo.fOffset);
|
||||
}
|
||||
|
||||
// TODO: Hard-coded solid color uniform for the fragment shader is always combined
|
||||
// with the RenderStep's vertex shader.
|
||||
// TODO: Rely on uniform writer and GetUniforms(kSolidColor).
|
||||
auto [writer, bindInfo] = bufferMgr.getUniformWriter(sizeof(SkColor4f));
|
||||
writer.write(&d.fColor, sizeof(SkColor4f));
|
||||
commandBuffer->bindUniformBuffer(UniformSlot::kPaint,
|
||||
sk_ref_sp(bindInfo.fBuffer),
|
||||
bindInfo.fOffset);
|
||||
sk_ref_sp(bindInfo.fBuffer),
|
||||
bindInfo.fOffset);
|
||||
|
||||
step->writeVertices(&drawWriter, shape);
|
||||
}
|
||||
@ -309,8 +310,8 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(CommandBufferTest, reporter, context) {
|
||||
draw(TriangleRectDraw::Singleton(), {{{-.5f, -.5f, .5f, .5f}, SkColors::kMagenta}});
|
||||
|
||||
// Draw green and cyan rects using instance buffer
|
||||
draw(InstanceRectDraw::Singleton(), { {{0.4f, -0.4f, 0.4f, 0.4f}, SkColors::kGreen},
|
||||
{{0.f, 0.f, 0.25f, 0.25f}, SkColors::kCyan} });
|
||||
draw(InstanceRectDraw::Singleton(), { {{-0.4f, -0.4f, 0.0f, 0.0f}, SkColors::kGreen},
|
||||
{{0.f, 0.f, 0.25f, 0.25f}, SkColors::kCyan} });
|
||||
|
||||
drawWriter.flush();
|
||||
bufferMgr.transferToCommandBuffer(commandBuffer.get());
|
||||
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "tests/Test.h"
|
||||
|
||||
#include "experimental/graphite/include/Context.h"
|
||||
#include "experimental/graphite/src/ProgramCache.h"
|
||||
#include "experimental/graphite/src/Recorder.h"
|
||||
|
||||
using namespace skgpu;
|
||||
|
||||
DEF_GRAPHITE_TEST_FOR_CONTEXTS(ProgramCacheTest, reporter, context) {
|
||||
Recorder recorder(sk_ref_sp(context));
|
||||
|
||||
auto cache = recorder.programCache();
|
||||
|
||||
REPORTER_ASSERT(reporter, cache->count() == 0);
|
||||
|
||||
// Add an initial unique program
|
||||
sk_sp<ProgramCache::ProgramInfo> pi1;
|
||||
{
|
||||
Combination c1 { ShaderCombo::ShaderType::kSolidColor,
|
||||
SkTileMode::kRepeat,
|
||||
SkBlendMode::kSrc };
|
||||
pi1 = cache->findOrCreateProgram(c1);
|
||||
REPORTER_ASSERT(reporter, pi1->id() != ProgramCache::kInvalidProgramID);
|
||||
REPORTER_ASSERT(reporter, pi1->combo() == c1);
|
||||
sk_sp<ProgramCache::ProgramInfo> lookup = cache->lookup(pi1->id());
|
||||
REPORTER_ASSERT(reporter, lookup->id() == pi1->id());
|
||||
|
||||
REPORTER_ASSERT(reporter, cache->count() == 1);
|
||||
}
|
||||
|
||||
// Try to add a duplicate program
|
||||
{
|
||||
Combination c2 { ShaderCombo::ShaderType::kSolidColor,
|
||||
SkTileMode::kRepeat,
|
||||
SkBlendMode::kSrc };
|
||||
sk_sp<ProgramCache::ProgramInfo> pi2 = cache->findOrCreateProgram(c2);
|
||||
REPORTER_ASSERT(reporter, pi2->id() != ProgramCache::kInvalidProgramID);
|
||||
REPORTER_ASSERT(reporter, pi2->id() == pi1->id());
|
||||
REPORTER_ASSERT(reporter, pi2->combo() == c2);
|
||||
sk_sp<ProgramCache::ProgramInfo> lookup = cache->lookup(pi2->id());
|
||||
REPORTER_ASSERT(reporter, lookup->id() == pi2->id());
|
||||
|
||||
REPORTER_ASSERT(reporter, cache->count() == 1);
|
||||
}
|
||||
|
||||
// Add a second unique program
|
||||
{
|
||||
Combination c3 { ShaderCombo::ShaderType::kLinearGradient,
|
||||
SkTileMode::kRepeat,
|
||||
SkBlendMode::kSrc };
|
||||
|
||||
sk_sp<ProgramCache::ProgramInfo> pi3 = cache->findOrCreateProgram(c3);
|
||||
REPORTER_ASSERT(reporter, pi3->id() != ProgramCache::kInvalidProgramID);
|
||||
REPORTER_ASSERT(reporter, pi3->id() != pi1->id());
|
||||
REPORTER_ASSERT(reporter, pi3->combo() == c3);
|
||||
sk_sp<ProgramCache::ProgramInfo> lookup = cache->lookup(pi3->id());
|
||||
REPORTER_ASSERT(reporter, lookup->id() == pi3->id());
|
||||
|
||||
REPORTER_ASSERT(reporter, cache->count() == 2);
|
||||
}
|
||||
|
||||
// TODO(robertphillips): expand this test to exercise more program variations
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user