1 #include "precompiled.h" 2 // 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" 12 #include "libGLESv2/renderer/Renderer11.h" 13 14 namespace rx 15 { 16 17 BufferStorage11::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 37 BufferStorage11::~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 58 BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) 59 { 60 ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); 61 return static_cast<BufferStorage11*>(bufferStorage); 62 } 63 64 void *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 134 void 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 if (data) 164 { 165 D3D11_SUBRESOURCE_DATA initialData; 166 initialData.pSysMem = data; 167 initialData.SysMemPitch = size; 168 initialData.SysMemSlicePitch = 0; 169 170 result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer); 171 } 172 else 173 { 174 result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); 175 } 176 177 if (FAILED(result)) 178 { 179 return gl::error(GL_OUT_OF_MEMORY); 180 } 181 182 mStagingBufferSize = size; 183 } 184 else if (data) 185 { 186 D3D11_MAPPED_SUBRESOURCE mappedResource; 187 result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); 188 if (FAILED(result)) 189 { 190 return gl::error(GL_OUT_OF_MEMORY); 191 } 192 193 memcpy(mappedResource.pData, data, size); 194 195 context->Unmap(mStagingBuffer, 0); 196 } 197 } 198 199 if (!mBuffer || mBufferSize < size + offset) 200 { 201 D3D11_BUFFER_DESC bufferDesc; 202 bufferDesc.ByteWidth = requiredBufferSize; 203 bufferDesc.Usage = D3D11_USAGE_DEFAULT; 204 bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER; 205 bufferDesc.CPUAccessFlags = 0; 206 bufferDesc.MiscFlags = 0; 207 bufferDesc.StructureByteStride = 0; 208 209 if (directInitialization) 210 { 211 // Since the data will fill the entire buffer (being larger than the initial size and having 212 // no offset), the buffer can be initialized with the data so no staging buffer is required 213 214 // No longer need the old buffer 215 if (mBuffer) 216 { 217 mBuffer->Release(); 218 mBuffer = NULL; 219 mBufferSize = 0; 220 } 221 222 if (data) 223 { 224 D3D11_SUBRESOURCE_DATA initialData; 225 initialData.pSysMem = data; 226 initialData.SysMemPitch = size; 227 initialData.SysMemSlicePitch = 0; 228 229 result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); 230 } 231 else 232 { 233 result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); 234 } 235 236 if (FAILED(result)) 237 { 238 return gl::error(GL_OUT_OF_MEMORY); 239 } 240 } 241 else if (mBuffer && offset > 0) 242 { 243 // If offset is greater than zero and the buffer is non-null, need to preserve the data from 244 // the old buffer up to offset 245 ID3D11Buffer *newBuffer = NULL; 246 247 result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); 248 if (FAILED(result)) 249 { 250 return gl::error(GL_OUT_OF_MEMORY); 251 } 252 253 D3D11_BOX srcBox; 254 srcBox.left = 0; 255 srcBox.right = std::min(offset, mBufferSize); 256 srcBox.top = 0; 257 srcBox.bottom = 1; 258 srcBox.front = 0; 259 srcBox.back = 1; 260 261 context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); 262 263 mBuffer->Release(); 264 mBuffer = newBuffer; 265 } 266 else 267 { 268 // Simple case, nothing needs to be copied from the old buffer to the new one, just create 269 // a new buffer 270 271 // No longer need the old buffer 272 if (mBuffer) 273 { 274 mBuffer->Release(); 275 mBuffer = NULL; 276 mBufferSize = 0; 277 } 278 279 // Create a new buffer for data storage 280 result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); 281 if (FAILED(result)) 282 { 283 return gl::error(GL_OUT_OF_MEMORY); 284 } 285 } 286 287 updateSerial(); 288 mBufferSize = bufferDesc.ByteWidth; 289 } 290 291 if (!directInitialization) 292 { 293 ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize); 294 295 // Data is already put into the staging buffer, copy it over to the data buffer 296 D3D11_BOX srcBox; 297 srcBox.left = 0; 298 srcBox.right = size; 299 srcBox.top = 0; 300 srcBox.bottom = 1; 301 srcBox.front = 0; 302 srcBox.back = 1; 303 304 context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox); 305 } 306 307 mSize = std::max(mSize, offset + size); 308 309 mWriteUsageCount = 0; 310 311 mResolvedDataValid = false; 312 } 313 314 void BufferStorage11::clear() 315 { 316 mResolvedDataValid = false; 317 mSize = 0; 318 } 319 320 unsigned int BufferStorage11::getSize() const 321 { 322 return mSize; 323 } 324 325 bool BufferStorage11::supportsDirectBinding() const 326 { 327 return true; 328 } 329 330 void BufferStorage11::markBufferUsage() 331 { 332 mReadUsageCount++; 333 mWriteUsageCount++; 334 335 static const unsigned int usageLimit = 5; 336 337 if (mReadUsageCount > usageLimit && mResolvedData) 338 { 339 free(mResolvedData); 340 mResolvedData = NULL; 341 mResolvedDataSize = 0; 342 mResolvedDataValid = false; 343 } 344 345 if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer) 346 { 347 mStagingBuffer->Release(); 348 mStagingBuffer = NULL; 349 mStagingBufferSize = 0; 350 } 351 } 352 353 ID3D11Buffer *BufferStorage11::getBuffer() const 354 { 355 return mBuffer; 356 } 357 358 } 359