1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RenderPassDesc.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Caps.h"
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
13*c8dee2aaSAndroid Build Coastguard Worker
14*c8dee2aaSAndroid Build Coastguard Worker namespace {
15*c8dee2aaSAndroid Build Coastguard Worker
to_str(LoadOp op)16*c8dee2aaSAndroid Build Coastguard Worker const char* to_str(LoadOp op) {
17*c8dee2aaSAndroid Build Coastguard Worker switch (op) {
18*c8dee2aaSAndroid Build Coastguard Worker case LoadOp::kLoad: return "load";
19*c8dee2aaSAndroid Build Coastguard Worker case LoadOp::kClear: return "clear";
20*c8dee2aaSAndroid Build Coastguard Worker case LoadOp::kDiscard: return "discard";
21*c8dee2aaSAndroid Build Coastguard Worker }
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
24*c8dee2aaSAndroid Build Coastguard Worker }
25*c8dee2aaSAndroid Build Coastguard Worker
to_str(StoreOp op)26*c8dee2aaSAndroid Build Coastguard Worker const char* to_str(StoreOp op) {
27*c8dee2aaSAndroid Build Coastguard Worker switch (op) {
28*c8dee2aaSAndroid Build Coastguard Worker case StoreOp::kStore: return "store";
29*c8dee2aaSAndroid Build Coastguard Worker case StoreOp::kDiscard: return "discard";
30*c8dee2aaSAndroid Build Coastguard Worker }
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
33*c8dee2aaSAndroid Build Coastguard Worker }
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
36*c8dee2aaSAndroid Build Coastguard Worker
Make(const Caps * caps,const TextureInfo & targetInfo,LoadOp loadOp,StoreOp storeOp,SkEnumBitMask<DepthStencilFlags> depthStencilFlags,const std::array<float,4> & clearColor,bool requiresMSAA,Swizzle writeSwizzle)37*c8dee2aaSAndroid Build Coastguard Worker RenderPassDesc RenderPassDesc::Make(const Caps* caps,
38*c8dee2aaSAndroid Build Coastguard Worker const TextureInfo& targetInfo,
39*c8dee2aaSAndroid Build Coastguard Worker LoadOp loadOp,
40*c8dee2aaSAndroid Build Coastguard Worker StoreOp storeOp,
41*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<DepthStencilFlags> depthStencilFlags,
42*c8dee2aaSAndroid Build Coastguard Worker const std::array<float, 4>& clearColor,
43*c8dee2aaSAndroid Build Coastguard Worker bool requiresMSAA,
44*c8dee2aaSAndroid Build Coastguard Worker Swizzle writeSwizzle) {
45*c8dee2aaSAndroid Build Coastguard Worker RenderPassDesc desc;
46*c8dee2aaSAndroid Build Coastguard Worker desc.fWriteSwizzle = writeSwizzle;
47*c8dee2aaSAndroid Build Coastguard Worker desc.fSampleCount = 1;
48*c8dee2aaSAndroid Build Coastguard Worker // It doesn't make sense to have a storeOp for our main target not be store. Why are we doing
49*c8dee2aaSAndroid Build Coastguard Worker // this DrawPass then
50*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(storeOp == StoreOp::kStore);
51*c8dee2aaSAndroid Build Coastguard Worker if (requiresMSAA) {
52*c8dee2aaSAndroid Build Coastguard Worker if (caps->msaaRenderToSingleSampledSupport()) {
53*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fTextureInfo = targetInfo;
54*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fLoadOp = loadOp;
55*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fStoreOp = storeOp;
56*c8dee2aaSAndroid Build Coastguard Worker desc.fSampleCount = caps->defaultMSAASamplesCount();
57*c8dee2aaSAndroid Build Coastguard Worker } else {
58*c8dee2aaSAndroid Build Coastguard Worker // TODO: If the resolve texture isn't readable, the MSAA color attachment will need to
59*c8dee2aaSAndroid Build Coastguard Worker // be persistently associated with the framebuffer, in which case it's not discardable.
60*c8dee2aaSAndroid Build Coastguard Worker auto msaaTextureInfo = caps->getDefaultMSAATextureInfo(targetInfo, Discardable::kYes);
61*c8dee2aaSAndroid Build Coastguard Worker if (msaaTextureInfo.isValid()) {
62*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fTextureInfo = msaaTextureInfo;
63*c8dee2aaSAndroid Build Coastguard Worker if (loadOp != LoadOp::kClear) {
64*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fLoadOp = LoadOp::kDiscard;
65*c8dee2aaSAndroid Build Coastguard Worker } else {
66*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fLoadOp = LoadOp::kClear;
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fStoreOp = StoreOp::kDiscard;
69*c8dee2aaSAndroid Build Coastguard Worker
70*c8dee2aaSAndroid Build Coastguard Worker desc.fColorResolveAttachment.fTextureInfo = targetInfo;
71*c8dee2aaSAndroid Build Coastguard Worker if (loadOp != LoadOp::kLoad) {
72*c8dee2aaSAndroid Build Coastguard Worker desc.fColorResolveAttachment.fLoadOp = LoadOp::kDiscard;
73*c8dee2aaSAndroid Build Coastguard Worker } else {
74*c8dee2aaSAndroid Build Coastguard Worker desc.fColorResolveAttachment.fLoadOp = LoadOp::kLoad;
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker desc.fColorResolveAttachment.fStoreOp = storeOp;
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker desc.fSampleCount = msaaTextureInfo.numSamples();
79*c8dee2aaSAndroid Build Coastguard Worker } else {
80*c8dee2aaSAndroid Build Coastguard Worker // fall back to single sampled
81*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fTextureInfo = targetInfo;
82*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fLoadOp = loadOp;
83*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fStoreOp = storeOp;
84*c8dee2aaSAndroid Build Coastguard Worker }
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker } else {
87*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fTextureInfo = targetInfo;
88*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fLoadOp = loadOp;
89*c8dee2aaSAndroid Build Coastguard Worker desc.fColorAttachment.fStoreOp = storeOp;
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker desc.fClearColor = clearColor;
92*c8dee2aaSAndroid Build Coastguard Worker
93*c8dee2aaSAndroid Build Coastguard Worker if (depthStencilFlags != DepthStencilFlags::kNone) {
94*c8dee2aaSAndroid Build Coastguard Worker desc.fDepthStencilAttachment.fTextureInfo = caps->getDefaultDepthStencilTextureInfo(
95*c8dee2aaSAndroid Build Coastguard Worker depthStencilFlags, desc.fSampleCount, targetInfo.isProtected());
96*c8dee2aaSAndroid Build Coastguard Worker // Always clear the depth and stencil to 0 at the start of a DrawPass, but discard at the
97*c8dee2aaSAndroid Build Coastguard Worker // end since their contents do not affect the next frame.
98*c8dee2aaSAndroid Build Coastguard Worker desc.fDepthStencilAttachment.fLoadOp = LoadOp::kClear;
99*c8dee2aaSAndroid Build Coastguard Worker desc.fClearDepth = 0.f;
100*c8dee2aaSAndroid Build Coastguard Worker desc.fClearStencil = 0;
101*c8dee2aaSAndroid Build Coastguard Worker desc.fDepthStencilAttachment.fStoreOp = StoreOp::kDiscard;
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker return desc;
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
toString() const107*c8dee2aaSAndroid Build Coastguard Worker SkString RenderPassDesc::toString() const {
108*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("RP(color: %s, resolve: %s, ds: %s, samples: %u, swizzle: %s, "
109*c8dee2aaSAndroid Build Coastguard Worker "clear: c(%f,%f,%f,%f), d(%f), s(0x%02x))",
110*c8dee2aaSAndroid Build Coastguard Worker fColorAttachment.toString().c_str(),
111*c8dee2aaSAndroid Build Coastguard Worker fColorResolveAttachment.toString().c_str(),
112*c8dee2aaSAndroid Build Coastguard Worker fDepthStencilAttachment.toString().c_str(),
113*c8dee2aaSAndroid Build Coastguard Worker fSampleCount,
114*c8dee2aaSAndroid Build Coastguard Worker fWriteSwizzle.asString().c_str(),
115*c8dee2aaSAndroid Build Coastguard Worker fClearColor[0], fClearColor[1], fClearColor[2], fClearColor[3],
116*c8dee2aaSAndroid Build Coastguard Worker fClearDepth,
117*c8dee2aaSAndroid Build Coastguard Worker fClearStencil);
118*c8dee2aaSAndroid Build Coastguard Worker }
119*c8dee2aaSAndroid Build Coastguard Worker
toPipelineLabel() const120*c8dee2aaSAndroid Build Coastguard Worker SkString RenderPassDesc::toPipelineLabel() const {
121*c8dee2aaSAndroid Build Coastguard Worker // This intentionally only includes the fixed state that impacts pipeline compilation.
122*c8dee2aaSAndroid Build Coastguard Worker // We include the load op of the color attachment when there is a resolve attachment because
123*c8dee2aaSAndroid Build Coastguard Worker // the load may trigger a different renderpass description.
124*c8dee2aaSAndroid Build Coastguard Worker const char* colorLoadStr = "";
125*c8dee2aaSAndroid Build Coastguard Worker if (fColorAttachment.fLoadOp == LoadOp::kLoad &&
126*c8dee2aaSAndroid Build Coastguard Worker (fColorResolveAttachment.fTextureInfo.isValid() || fSampleCount > 1)) {
127*c8dee2aaSAndroid Build Coastguard Worker colorLoadStr = " w/ msaa load";
128*c8dee2aaSAndroid Build Coastguard Worker }
129*c8dee2aaSAndroid Build Coastguard Worker // TODO: Remove `fSampleCount` in label when the Dawn backend manages its MSAA color attachments
130*c8dee2aaSAndroid Build Coastguard Worker // directly instead of relying on msaaRenderToSingleSampledSupport().
131*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("RP(color: %s%s, resolve: %s, ds: %s, samples: %u, swizzle: %s)",
132*c8dee2aaSAndroid Build Coastguard Worker fColorAttachment.fTextureInfo.toRPAttachmentString().c_str(),
133*c8dee2aaSAndroid Build Coastguard Worker colorLoadStr,
134*c8dee2aaSAndroid Build Coastguard Worker fColorResolveAttachment.fTextureInfo.toRPAttachmentString().c_str(),
135*c8dee2aaSAndroid Build Coastguard Worker fDepthStencilAttachment.fTextureInfo.toRPAttachmentString().c_str(),
136*c8dee2aaSAndroid Build Coastguard Worker fSampleCount,
137*c8dee2aaSAndroid Build Coastguard Worker fWriteSwizzle.asString().c_str());
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker
toString() const140*c8dee2aaSAndroid Build Coastguard Worker SkString AttachmentDesc::toString() const {
141*c8dee2aaSAndroid Build Coastguard Worker if (fTextureInfo.isValid()) {
142*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("info: %s loadOp: %s storeOp: %s",
143*c8dee2aaSAndroid Build Coastguard Worker fTextureInfo.toString().c_str(),
144*c8dee2aaSAndroid Build Coastguard Worker to_str(fLoadOp),
145*c8dee2aaSAndroid Build Coastguard Worker to_str(fStoreOp));
146*c8dee2aaSAndroid Build Coastguard Worker } else {
147*c8dee2aaSAndroid Build Coastguard Worker return SkString("invalid attachment");
148*c8dee2aaSAndroid Build Coastguard Worker }
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
152