blob: 4c37bdbf60c6bb01c4d034954d554c80ccb14344 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
shannon.woods@transgaming.com70c856f2013-02-28 23:07:53 +00002//
3// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// BufferStorage11.cpp Defines the BufferStorage11 class.
9
10#include "libGLESv2/renderer/BufferStorage11.h"
11#include "libGLESv2/main.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000012#include "libGLESv2/renderer/Renderer11.h"
shannon.woods@transgaming.com70c856f2013-02-28 23:07:53 +000013
14namespace rx
15{
16
17BufferStorage11::BufferStorage11(Renderer11 *renderer)
18{
19 mRenderer = renderer;
20
21 mStagingBuffer = NULL;
22 mStagingBufferSize = 0;
23
24 mBuffer = NULL;
25 mBufferSize = 0;
26
27 mSize = 0;
28
29 mResolvedData = NULL;
30 mResolvedDataSize = 0;
31 mResolvedDataValid = false;
32
33 mReadUsageCount = 0;
34 mWriteUsageCount = 0;
35}
36
37BufferStorage11::~BufferStorage11()
38{
39 if (mStagingBuffer)
40 {
41 mStagingBuffer->Release();
42 mStagingBuffer = NULL;
43 }
44
45 if (mBuffer)
46 {
47 mBuffer->Release();
48 mBuffer = NULL;
49 }
50
51 if (mResolvedData)
52 {
53 free(mResolvedData);
54 mResolvedData = NULL;
55 }
56}
57
58BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
59{
60 ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
61 return static_cast<BufferStorage11*>(bufferStorage);
62}
63
64void *BufferStorage11::getData()
65{
66 if (!mResolvedDataValid)
67 {
68 ID3D11Device *device = mRenderer->getDevice();
69 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
70 HRESULT result;
71
72 if (!mStagingBuffer || mStagingBufferSize < mBufferSize)
73 {
74 if (mStagingBuffer)
75 {
76 mStagingBuffer->Release();
77 mStagingBuffer = NULL;
78 mStagingBufferSize = 0;
79 }
80
81 D3D11_BUFFER_DESC bufferDesc;
82 bufferDesc.ByteWidth = mSize;
83 bufferDesc.Usage = D3D11_USAGE_STAGING;
84 bufferDesc.BindFlags = 0;
85 bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
86 bufferDesc.MiscFlags = 0;
87 bufferDesc.StructureByteStride = 0;
88
89 result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
90 if (FAILED(result))
91 {
92 return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
93 }
94
95 mStagingBufferSize = bufferDesc.ByteWidth;
96 }
97
98 if (!mResolvedData || mResolvedDataSize < mBufferSize)
99 {
100 free(mResolvedData);
101 mResolvedData = malloc(mSize);
102 mResolvedDataSize = mSize;
103 }
104
105 D3D11_BOX srcBox;
106 srcBox.left = 0;
107 srcBox.right = mSize;
108 srcBox.top = 0;
109 srcBox.bottom = 1;
110 srcBox.front = 0;
111 srcBox.back = 1;
112
113 context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
114
115 D3D11_MAPPED_SUBRESOURCE mappedResource;
116 result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
117 if (FAILED(result))
118 {
119 return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
120 }
121
122 memcpy(mResolvedData, mappedResource.pData, mSize);
123
124 context->Unmap(mStagingBuffer, 0);
125
126 mResolvedDataValid = true;
127 }
128
129 mReadUsageCount = 0;
130
131 return mResolvedData;
132}
133
134void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset)
135{
136 ID3D11Device *device = mRenderer->getDevice();
137 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
138 HRESULT result;
139
140 unsigned int requiredBufferSize = size + offset;
141 unsigned int requiredStagingSize = size;
142 bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset);
143
144 if (!directInitialization)
145 {
146 if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize)
147 {
148 if (mStagingBuffer)
149 {
150 mStagingBuffer->Release();
151 mStagingBuffer = NULL;
152 mStagingBufferSize = 0;
153 }
154
155 D3D11_BUFFER_DESC bufferDesc;
156 bufferDesc.ByteWidth = size;
157 bufferDesc.Usage = D3D11_USAGE_STAGING;
158 bufferDesc.BindFlags = 0;
159 bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
160 bufferDesc.MiscFlags = 0;
161 bufferDesc.StructureByteStride = 0;
162
163 D3D11_SUBRESOURCE_DATA initialData;
164 initialData.pSysMem = data;
165 initialData.SysMemPitch = size;
166 initialData.SysMemSlicePitch = 0;
167
168 result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
169 if (FAILED(result))
170 {
171 return gl::error(GL_OUT_OF_MEMORY);
172 }
173
174 mStagingBufferSize = size;
175 }
176 else
177 {
178 D3D11_MAPPED_SUBRESOURCE mappedResource;
179 result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
180 if (FAILED(result))
181 {
182 return gl::error(GL_OUT_OF_MEMORY);
183 }
184
185 memcpy(mappedResource.pData, data, size);
186
187 context->Unmap(mStagingBuffer, 0);
188 }
189 }
190
191 if (!mBuffer || mBufferSize < size + offset)
192 {
193 D3D11_BUFFER_DESC bufferDesc;
194 bufferDesc.ByteWidth = requiredBufferSize;
195 bufferDesc.Usage = D3D11_USAGE_DEFAULT;
196 bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER;
197 bufferDesc.CPUAccessFlags = 0;
198 bufferDesc.MiscFlags = 0;
199 bufferDesc.StructureByteStride = 0;
200
201 if (directInitialization)
202 {
203 // Since the data will fill the entire buffer (being larger than the initial size and having
204 // no offset), the buffer can be initialized with the data so no staging buffer is required
205
206 // No longer need the old buffer
207 if (mBuffer)
208 {
209 mBuffer->Release();
210 mBuffer = NULL;
211 mBufferSize = 0;
212 }
213
214 D3D11_SUBRESOURCE_DATA initialData;
215 initialData.pSysMem = data;
216 initialData.SysMemPitch = size;
217 initialData.SysMemSlicePitch = 0;
218
219 result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer);
220 if (FAILED(result))
221 {
222 return gl::error(GL_OUT_OF_MEMORY);
223 }
224 }
225 else if (mBuffer && offset > 0)
226 {
227 // If offset is greater than zero and the buffer is non-null, need to preserve the data from
228 // the old buffer up to offset
229 ID3D11Buffer *newBuffer = NULL;
230
231 result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
232 if (FAILED(result))
233 {
234 return gl::error(GL_OUT_OF_MEMORY);
235 }
236
237 D3D11_BOX srcBox;
238 srcBox.left = 0;
239 srcBox.right = std::min(offset, mBufferSize);
240 srcBox.top = 0;
241 srcBox.bottom = 1;
242 srcBox.front = 0;
243 srcBox.back = 1;
244
245 context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
246
247 mBuffer->Release();
248 mBuffer = newBuffer;
249 }
250 else
251 {
252 // Simple case, nothing needs to be copied from the old buffer to the new one, just create
253 // a new buffer
254
255 // No longer need the old buffer
256 if (mBuffer)
257 {
258 mBuffer->Release();
259 mBuffer = NULL;
260 mBufferSize = 0;
261 }
262
263 // Create a new buffer for data storage
264 result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
265 if (FAILED(result))
266 {
267 return gl::error(GL_OUT_OF_MEMORY);
268 }
269 }
270
271 updateSerial();
272 mBufferSize = bufferDesc.ByteWidth;
273 }
274
275 if (!directInitialization)
276 {
277 ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize);
278
279 // Data is already put into the staging buffer, copy it over to the data buffer
280 D3D11_BOX srcBox;
281 srcBox.left = 0;
282 srcBox.right = size;
283 srcBox.top = 0;
284 srcBox.bottom = 1;
285 srcBox.front = 0;
286 srcBox.back = 1;
287
288 context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox);
289 }
290
291 mSize = std::max(mSize, offset + size);
292
293 mWriteUsageCount = 0;
294
295 mResolvedDataValid = false;
296}
297
298void BufferStorage11::clear()
299{
300 mResolvedDataValid = false;
301 mSize = 0;
302}
303
304unsigned int BufferStorage11::getSize() const
305{
306 return mSize;
307}
308
309bool BufferStorage11::supportsDirectBinding() const
310{
311 return true;
312}
313
314void BufferStorage11::markBufferUsage()
315{
316 mReadUsageCount++;
317 mWriteUsageCount++;
318
319 static const unsigned int usageLimit = 5;
320
321 if (mReadUsageCount > usageLimit && mResolvedData)
322 {
323 free(mResolvedData);
324 mResolvedData = NULL;
325 mResolvedDataSize = 0;
326 mResolvedDataValid = false;
327 }
328
329 if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer)
330 {
331 mStagingBuffer->Release();
332 mStagingBuffer = NULL;
333 mStagingBufferSize = 0;
334 }
335}
336
337ID3D11Buffer *BufferStorage11::getBuffer() const
338{
339 return mBuffer;
340}
341
342}