Flutter Engine
The Flutter Engine
GrD3DBuffer.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
12
13#ifdef SK_DEBUG
14#define VALIDATE() this->validate()
15#else
16#define VALIDATE() do {} while(false)
17#endif
18
20 size_t size,
21 GrGpuBufferType intendedType,
22 GrAccessPattern accessPattern,
23 D3D12_RESOURCE_STATES* resourceState,
24 sk_sp<GrD3DAlloc>* alloc) {
25 D3D12_HEAP_TYPE heapType;
26 if (accessPattern == kStatic_GrAccessPattern) {
28 intendedType != GrGpuBufferType::kXferGpuToCpu);
29 heapType = D3D12_HEAP_TYPE_DEFAULT;
30 // Needs to be transitioned to appropriate state to be read in shader
31 *resourceState = D3D12_RESOURCE_STATE_COPY_DEST;
32 } else {
33 if (intendedType == GrGpuBufferType::kXferGpuToCpu) {
34 heapType = D3D12_HEAP_TYPE_READBACK;
35 // Cannot be changed
36 *resourceState = D3D12_RESOURCE_STATE_COPY_DEST;
37 } else {
38 heapType = D3D12_HEAP_TYPE_UPLOAD;
39 // Cannot be changed
40 // Includes VERTEX_AND_CONSTANT_BUFFER, INDEX_BUFFER, INDIRECT_ARGUMENT, and COPY_SOURCE
41 *resourceState = D3D12_RESOURCE_STATE_GENERIC_READ;
42 }
43 }
44
45 D3D12_RESOURCE_DESC bufferDesc = {};
46 bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
47 bufferDesc.Alignment = 0; // default alignment
48 bufferDesc.Width = size;
49 bufferDesc.Height = 1;
50 bufferDesc.DepthOrArraySize = 1;
51 bufferDesc.MipLevels = 1;
52 bufferDesc.Format = DXGI_FORMAT_UNKNOWN;
53 bufferDesc.SampleDesc.Count = 1;
54 bufferDesc.SampleDesc.Quality = 0; // Doesn't apply to buffers
55 bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
56 bufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
57
59 heapType, &bufferDesc, *resourceState, alloc, nullptr);
60
61 return resource;
62}
63
65 GrAccessPattern accessPattern) {
67 D3D12_RESOURCE_STATES resourceState;
68
71 &resourceState, &alloc);
72 if (!resource) {
73 return nullptr;
74 }
75
77 std::move(resource), std::move(alloc),
78 resourceState,
79 /*label=*/"MakeD3DBuffer"));
80}
81
83 GrAccessPattern accessPattern, gr_cp<ID3D12Resource> bufferResource,
85 D3D12_RESOURCE_STATES resourceState,
86 std::string_view label)
87 : INHERITED(gpu, size, intendedType, accessPattern, label)
88 , fResourceState(resourceState)
89 , fD3DResource(std::move(bufferResource))
90 , fAlloc(std::move(alloc)) {
92
93 // TODO: persistently map UPLOAD resources?
94
95 VALIDATE();
96}
97
99 D3D12_RESOURCE_STATES newResourceState) {
100 if (newResourceState == fResourceState ||
101 // GENERIC_READ encapsulates a lot of different read states
102 (fResourceState == D3D12_RESOURCE_STATE_GENERIC_READ &&
103 SkToBool(newResourceState | fResourceState))) {
104 return;
105 }
106
107 D3D12_RESOURCE_TRANSITION_BARRIER barrier = {};
108 barrier.pResource = this->d3dResource();
109 barrier.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
110 barrier.StateBefore = fResourceState;
111 barrier.StateAfter = newResourceState;
112
113 gpu->addBufferResourceBarriers(this, 1, &barrier);
114
115 fResourceState = newResourceState;
116}
117
118void GrD3DBuffer::releaseResource() {
119 if (this->wasDestroyed()) {
120 return;
121 }
122
123 if (fMapPtr) {
124 this->unmap();
125 }
126
127 SkASSERT(fD3DResource);
128 SkASSERT(fAlloc);
129 fD3DResource.reset();
130 fAlloc.reset();
131}
132
134 this->releaseResource();
135 this->INHERITED::onRelease();
136}
137
139 this->releaseResource();
140 this->INHERITED::onAbandon();
141}
142
143void GrD3DBuffer::onMap(MapType type) {
144 fMapPtr = this->internalMap(type, 0, this->size());
145}
146
147void GrD3DBuffer::onUnmap(MapType type) {
148 this->internalUnmap(type, 0, this->size());
149}
150
151bool GrD3DBuffer::onClearToZero() {
152 if (!fD3DResource) {
153 return false;
154 }
155
156 if (this->accessPattern() == kStatic_GrAccessPattern) {
158 this->getD3DGpu()->stagingBufferManager()->allocateStagingBufferSlice(this->size());
159 if (!slice.fBuffer) {
160 return false;
161 }
162 std::memset(slice.fOffsetMapPtr, 0, this->size());
163 this->setResourceState(this->getD3DGpu(), D3D12_RESOURCE_STATE_COPY_DEST);
164 this->getD3DGpu()->currentCommandList()->copyBufferToBuffer(
165 sk_ref_sp<GrD3DBuffer>(this),
166 0,
167 static_cast<const GrD3DBuffer*>(slice.fBuffer)->d3dResource(),
168 slice.fOffset,
169 this->size());
170 return true;
171 }
172
173 void* ptr = this->internalMap(MapType::kWriteDiscard, 0, this->size());
174 if (!ptr) {
175 return false;
176 }
177 std::memset(ptr, 0, this->size());
178 this->internalUnmap(MapType::kWriteDiscard, 0, this->size());
179
180 return true;
181}
182
183bool GrD3DBuffer::onUpdateData(const void* src, size_t offset, size_t size, bool /*preserve*/) {
184 if (!fD3DResource) {
185 return false;
186 }
187
188 void* ptr = this->internalMap(MapType::kWriteDiscard, offset, size);
189 if (!ptr) {
190 return false;
191 }
192 if (this->accessPattern() == kStatic_GrAccessPattern) {
193 // We should never call this method on static buffers in protected contexts.
194 SkASSERT(!this->getD3DGpu()->protectedContext());
195 //*** any alignment restrictions?
196 }
197 memcpy(ptr, src, size);
198 this->internalUnmap(MapType::kWriteDiscard, offset, size);
199
200 return true;
201}
202
203void* GrD3DBuffer::internalMap(MapType type, size_t offset, size_t size) {
204 // TODO: if UPLOAD heap type, could be persistently mapped (i.e., this would be a no-op)
205 SkASSERT(fD3DResource);
206 SkASSERT(!this->isMapped());
207 SkASSERT(offset + size <= this->size());
208
209 VALIDATE();
210
211 if (this->accessPattern() == kStatic_GrAccessPattern) {
212 if (type == MapType::kRead) {
213 return nullptr;
214 }
215 SkASSERT(!fStagingBuffer);
218 if (!slice.fBuffer) {
219 return nullptr;
220 }
221 fStagingBuffer = static_cast<const GrD3DBuffer*>(slice.fBuffer)->d3dResource();
222 fStagingOffset = slice.fOffset;
223 VALIDATE();
224 return slice.fOffsetMapPtr;
225 }
226
227 D3D12_RANGE range;
228 range.Begin = offset;
229 // The range passed here indicates the portion of the resource that may be
230 // read. If we're only writing then pass an empty range.
231 range.End = type == MapType::kRead ? offset + size : offset;
232 void* result;
233 if (fD3DResource->Map(0, &range, &result) != S_OK) {
234 return nullptr;
235 }
236 if (result) {
237 result = SkTAddOffset<void>(result, offset);
238 }
239 VALIDATE();
240 return result;
241}
242
243void GrD3DBuffer::internalUnmap(MapType type, size_t offset, size_t size) {
244 // TODO: if UPLOAD heap type, could be persistently mapped (i.e., this would be a no-op)
245 SkASSERT(fD3DResource);
246 SkASSERT(offset + size <= this->size());
247 VALIDATE();
248
249 if (this->accessPattern() == kStatic_GrAccessPattern) {
251 SkASSERT(fStagingBuffer);
252 this->setResourceState(this->getD3DGpu(), D3D12_RESOURCE_STATE_COPY_DEST);
253 this->getD3DGpu()->currentCommandList()->copyBufferToBuffer(
254 sk_ref_sp<GrD3DBuffer>(this),
255 offset,
256 fStagingBuffer,
257 fStagingOffset,
258 size);
259 fStagingBuffer = nullptr;
260 } else {
261 D3D12_RANGE range;
262 range.Begin = offset;
263 range.End = type == MapType::kWriteDiscard ? offset + size : offset;
264 // For READBACK heaps, unmap requires an empty range
265 SkASSERT(fResourceState != D3D12_RESOURCE_STATE_COPY_DEST || range.Begin == range.End);
266 fD3DResource->Unmap(0, &range);
267 }
268
269 VALIDATE();
270}
271
272void GrD3DBuffer::onSetLabel() {
273 SkASSERT(fD3DResource);
274 if (!this->getLabel().empty()) {
275 const std::wstring label = L"_Skia_" + GrD3DMultiByteToWide(this->getLabel());
276 this->d3dResource()->SetName(label.c_str());
277 }
278}
279
280#ifdef SK_DEBUG
281void GrD3DBuffer::validate() const {
287}
288#endif
static gr_cp< ID3D12Resource > make_d3d_buffer(GrD3DGpu *gpu, size_t size, GrGpuBufferType intendedType, GrAccessPattern accessPattern, D3D12_RESOURCE_STATES *resourceState, sk_sp< GrD3DAlloc > *alloc)
Definition: GrD3DBuffer.cpp:19
#define VALIDATE()
Definition: GrD3DBuffer.cpp:16
std::wstring GrD3DMultiByteToWide(const std::string &str)
Definition: GrD3DUtil.cpp:25
GrGpuBufferType
Definition: GrTypesPriv.h:411
GrAccessPattern
Definition: GrTypesPriv.h:424
@ kStatic_GrAccessPattern
Definition: GrTypesPriv.h:428
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkString resource(SkPDFResourceType type, int index)
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
GLenum type
void onAbandon() override
ID3D12Resource * d3dResource() const
Definition: GrD3DBuffer.h:24
void setResourceState(const GrD3DGpu *gpu, D3D12_RESOURCE_STATES newResourceState)
Definition: GrD3DBuffer.cpp:98
void onRelease() override
D3D12_RESOURCE_STATES fResourceState
Definition: GrD3DBuffer.h:38
static sk_sp< GrD3DBuffer > Make(GrD3DGpu *, size_t size, GrGpuBufferType, GrAccessPattern)
Definition: GrD3DBuffer.cpp:64
GrD3DBuffer(GrD3DGpu *, size_t size, GrGpuBufferType, GrAccessPattern, gr_cp< ID3D12Resource >, sk_sp< GrD3DAlloc >, D3D12_RESOURCE_STATES, std::string_view label)
Definition: GrD3DBuffer.cpp:82
void copyBufferToBuffer(sk_sp< GrD3DBuffer > dstBuffer, uint64_t dstOffset, ID3D12Resource *srcBuffer, uint64_t srcOffset, uint64_t numBytes)
void addBufferResourceBarriers(GrD3DBuffer *buffer, int numBarriers, D3D12_RESOURCE_TRANSITION_BARRIER *barriers) const
Definition: GrD3DGpu.cpp:1729
GrD3DDirectCommandList * currentCommandList() const
Definition: GrD3DGpu.h:48
GrD3DMemoryAllocator * memoryAllocator() const
Definition: GrD3DGpu.h:46
bool protectedContext() const
Definition: GrD3DGpu.h:55
GrStagingBufferManager * stagingBufferManager() override
Definition: GrD3DGpu.h:50
virtual gr_cp< ID3D12Resource > createResource(D3D12_HEAP_TYPE, const D3D12_RESOURCE_DESC *, D3D12_RESOURCE_STATES initialResourceState, sk_sp< GrD3DAlloc > *allocation, const D3D12_CLEAR_VALUE *)=0
size_t size() const final
Definition: GrGpuBuffer.h:34
GrGpuBufferType intendedType() const
Definition: GrGpuBuffer.h:99
bool isMapped() const
Definition: GrGpuBuffer.cpp:47
void * fMapPtr
Definition: GrGpuBuffer.h:119
GrAccessPattern accessPattern() const
Definition: GrGpuBuffer.h:32
void unmap()
Definition: GrGpuBuffer.cpp:38
virtual void onAbandon()
std::string getLabel() const
bool wasDestroyed() const
void registerWithCache(skgpu::Budgeted)
virtual void onRelease()
Slice allocateStagingBufferSlice(size_t size, size_t requiredAlignment=1)
void reset(T *object=nullptr)
Definition: GrD3DTypes.h:116
void reset(T *ptr=nullptr)
Definition: SkRefCnt.h:310
EMSCRIPTEN_KEEPALIVE void empty()
GAsyncResult * result
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: ref_ptr.h:256
SeparatedVector2 offset