Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
82GrD3DBuffer::GrD3DBuffer(GrD3DGpu* gpu, size_t size, GrGpuBufferType intendedType,
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
144 fMapPtr = this->internalMap(type, 0, this->size());
145}
146
148 this->internalUnmap(type, 0, this->size());
149}
150
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
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)
#define VALIDATE()
std::wstring GrD3DMultiByteToWide(const std::string &str)
Definition GrD3DUtil.cpp:25
GrGpuBufferType
GrAccessPattern
@ kStatic_GrAccessPattern
#define SkASSERT(cond)
Definition SkAssert.h:116
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
void onMap(MapType) override
void onSetLabel() override
void onAbandon() override
void onUnmap(MapType) override
ID3D12Resource * d3dResource() const
Definition GrD3DBuffer.h:24
void setResourceState(const GrD3DGpu *gpu, D3D12_RESOURCE_STATES newResourceState)
void onRelease() override
D3D12_RESOURCE_STATES fResourceState
Definition GrD3DBuffer.h:38
static sk_sp< GrD3DBuffer > Make(GrD3DGpu *, size_t size, GrGpuBufferType, GrAccessPattern)
bool onClearToZero() override
GrD3DBuffer(GrD3DGpu *, size_t size, GrGpuBufferType, GrAccessPattern, gr_cp< ID3D12Resource >, sk_sp< GrD3DAlloc >, D3D12_RESOURCE_STATES, std::string_view label)
bool onUpdateData(const void *src, size_t offset, size_t size, bool preserve) override
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
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
void * fMapPtr
GrAccessPattern accessPattern() const
Definition GrGpuBuffer.h:32
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
Definition ref_ptr.h:256
Point offset