1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/BufferStorage11.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,358 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// BufferStorage11.cpp Defines the BufferStorage11 class. 1.12 + 1.13 +#include "libGLESv2/renderer/BufferStorage11.h" 1.14 +#include "libGLESv2/main.h" 1.15 +#include "libGLESv2/renderer/Renderer11.h" 1.16 + 1.17 +namespace rx 1.18 +{ 1.19 + 1.20 +BufferStorage11::BufferStorage11(Renderer11 *renderer) 1.21 +{ 1.22 + mRenderer = renderer; 1.23 + 1.24 + mStagingBuffer = NULL; 1.25 + mStagingBufferSize = 0; 1.26 + 1.27 + mBuffer = NULL; 1.28 + mBufferSize = 0; 1.29 + 1.30 + mSize = 0; 1.31 + 1.32 + mResolvedData = NULL; 1.33 + mResolvedDataSize = 0; 1.34 + mResolvedDataValid = false; 1.35 + 1.36 + mReadUsageCount = 0; 1.37 + mWriteUsageCount = 0; 1.38 +} 1.39 + 1.40 +BufferStorage11::~BufferStorage11() 1.41 +{ 1.42 + if (mStagingBuffer) 1.43 + { 1.44 + mStagingBuffer->Release(); 1.45 + mStagingBuffer = NULL; 1.46 + } 1.47 + 1.48 + if (mBuffer) 1.49 + { 1.50 + mBuffer->Release(); 1.51 + mBuffer = NULL; 1.52 + } 1.53 + 1.54 + if (mResolvedData) 1.55 + { 1.56 + free(mResolvedData); 1.57 + mResolvedData = NULL; 1.58 + } 1.59 +} 1.60 + 1.61 +BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) 1.62 +{ 1.63 + ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); 1.64 + return static_cast<BufferStorage11*>(bufferStorage); 1.65 +} 1.66 + 1.67 +void *BufferStorage11::getData() 1.68 +{ 1.69 + if (!mResolvedDataValid) 1.70 + { 1.71 + ID3D11Device *device = mRenderer->getDevice(); 1.72 + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); 1.73 + HRESULT result; 1.74 + 1.75 + if (!mStagingBuffer || mStagingBufferSize < mBufferSize) 1.76 + { 1.77 + if (mStagingBuffer) 1.78 + { 1.79 + mStagingBuffer->Release(); 1.80 + mStagingBuffer = NULL; 1.81 + mStagingBufferSize = 0; 1.82 + } 1.83 + 1.84 + D3D11_BUFFER_DESC bufferDesc; 1.85 + bufferDesc.ByteWidth = mSize; 1.86 + bufferDesc.Usage = D3D11_USAGE_STAGING; 1.87 + bufferDesc.BindFlags = 0; 1.88 + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 1.89 + bufferDesc.MiscFlags = 0; 1.90 + bufferDesc.StructureByteStride = 0; 1.91 + 1.92 + result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); 1.93 + if (FAILED(result)) 1.94 + { 1.95 + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); 1.96 + } 1.97 + 1.98 + mStagingBufferSize = bufferDesc.ByteWidth; 1.99 + } 1.100 + 1.101 + if (!mResolvedData || mResolvedDataSize < mBufferSize) 1.102 + { 1.103 + free(mResolvedData); 1.104 + mResolvedData = malloc(mSize); 1.105 + mResolvedDataSize = mSize; 1.106 + } 1.107 + 1.108 + D3D11_BOX srcBox; 1.109 + srcBox.left = 0; 1.110 + srcBox.right = mSize; 1.111 + srcBox.top = 0; 1.112 + srcBox.bottom = 1; 1.113 + srcBox.front = 0; 1.114 + srcBox.back = 1; 1.115 + 1.116 + context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); 1.117 + 1.118 + D3D11_MAPPED_SUBRESOURCE mappedResource; 1.119 + result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); 1.120 + if (FAILED(result)) 1.121 + { 1.122 + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); 1.123 + } 1.124 + 1.125 + memcpy(mResolvedData, mappedResource.pData, mSize); 1.126 + 1.127 + context->Unmap(mStagingBuffer, 0); 1.128 + 1.129 + mResolvedDataValid = true; 1.130 + } 1.131 + 1.132 + mReadUsageCount = 0; 1.133 + 1.134 + return mResolvedData; 1.135 +} 1.136 + 1.137 +void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset) 1.138 +{ 1.139 + ID3D11Device *device = mRenderer->getDevice(); 1.140 + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); 1.141 + HRESULT result; 1.142 + 1.143 + unsigned int requiredBufferSize = size + offset; 1.144 + unsigned int requiredStagingSize = size; 1.145 + bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset); 1.146 + 1.147 + if (!directInitialization) 1.148 + { 1.149 + if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize) 1.150 + { 1.151 + if (mStagingBuffer) 1.152 + { 1.153 + mStagingBuffer->Release(); 1.154 + mStagingBuffer = NULL; 1.155 + mStagingBufferSize = 0; 1.156 + } 1.157 + 1.158 + D3D11_BUFFER_DESC bufferDesc; 1.159 + bufferDesc.ByteWidth = size; 1.160 + bufferDesc.Usage = D3D11_USAGE_STAGING; 1.161 + bufferDesc.BindFlags = 0; 1.162 + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 1.163 + bufferDesc.MiscFlags = 0; 1.164 + bufferDesc.StructureByteStride = 0; 1.165 + 1.166 + if (data) 1.167 + { 1.168 + D3D11_SUBRESOURCE_DATA initialData; 1.169 + initialData.pSysMem = data; 1.170 + initialData.SysMemPitch = size; 1.171 + initialData.SysMemSlicePitch = 0; 1.172 + 1.173 + result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer); 1.174 + } 1.175 + else 1.176 + { 1.177 + result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer); 1.178 + } 1.179 + 1.180 + if (FAILED(result)) 1.181 + { 1.182 + return gl::error(GL_OUT_OF_MEMORY); 1.183 + } 1.184 + 1.185 + mStagingBufferSize = size; 1.186 + } 1.187 + else if (data) 1.188 + { 1.189 + D3D11_MAPPED_SUBRESOURCE mappedResource; 1.190 + result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); 1.191 + if (FAILED(result)) 1.192 + { 1.193 + return gl::error(GL_OUT_OF_MEMORY); 1.194 + } 1.195 + 1.196 + memcpy(mappedResource.pData, data, size); 1.197 + 1.198 + context->Unmap(mStagingBuffer, 0); 1.199 + } 1.200 + } 1.201 + 1.202 + if (!mBuffer || mBufferSize < size + offset) 1.203 + { 1.204 + D3D11_BUFFER_DESC bufferDesc; 1.205 + bufferDesc.ByteWidth = requiredBufferSize; 1.206 + bufferDesc.Usage = D3D11_USAGE_DEFAULT; 1.207 + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER; 1.208 + bufferDesc.CPUAccessFlags = 0; 1.209 + bufferDesc.MiscFlags = 0; 1.210 + bufferDesc.StructureByteStride = 0; 1.211 + 1.212 + if (directInitialization) 1.213 + { 1.214 + // Since the data will fill the entire buffer (being larger than the initial size and having 1.215 + // no offset), the buffer can be initialized with the data so no staging buffer is required 1.216 + 1.217 + // No longer need the old buffer 1.218 + if (mBuffer) 1.219 + { 1.220 + mBuffer->Release(); 1.221 + mBuffer = NULL; 1.222 + mBufferSize = 0; 1.223 + } 1.224 + 1.225 + if (data) 1.226 + { 1.227 + D3D11_SUBRESOURCE_DATA initialData; 1.228 + initialData.pSysMem = data; 1.229 + initialData.SysMemPitch = size; 1.230 + initialData.SysMemSlicePitch = 0; 1.231 + 1.232 + result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); 1.233 + } 1.234 + else 1.235 + { 1.236 + result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); 1.237 + } 1.238 + 1.239 + if (FAILED(result)) 1.240 + { 1.241 + return gl::error(GL_OUT_OF_MEMORY); 1.242 + } 1.243 + } 1.244 + else if (mBuffer && offset > 0) 1.245 + { 1.246 + // If offset is greater than zero and the buffer is non-null, need to preserve the data from 1.247 + // the old buffer up to offset 1.248 + ID3D11Buffer *newBuffer = NULL; 1.249 + 1.250 + result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); 1.251 + if (FAILED(result)) 1.252 + { 1.253 + return gl::error(GL_OUT_OF_MEMORY); 1.254 + } 1.255 + 1.256 + D3D11_BOX srcBox; 1.257 + srcBox.left = 0; 1.258 + srcBox.right = std::min(offset, mBufferSize); 1.259 + srcBox.top = 0; 1.260 + srcBox.bottom = 1; 1.261 + srcBox.front = 0; 1.262 + srcBox.back = 1; 1.263 + 1.264 + context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); 1.265 + 1.266 + mBuffer->Release(); 1.267 + mBuffer = newBuffer; 1.268 + } 1.269 + else 1.270 + { 1.271 + // Simple case, nothing needs to be copied from the old buffer to the new one, just create 1.272 + // a new buffer 1.273 + 1.274 + // No longer need the old buffer 1.275 + if (mBuffer) 1.276 + { 1.277 + mBuffer->Release(); 1.278 + mBuffer = NULL; 1.279 + mBufferSize = 0; 1.280 + } 1.281 + 1.282 + // Create a new buffer for data storage 1.283 + result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); 1.284 + if (FAILED(result)) 1.285 + { 1.286 + return gl::error(GL_OUT_OF_MEMORY); 1.287 + } 1.288 + } 1.289 + 1.290 + updateSerial(); 1.291 + mBufferSize = bufferDesc.ByteWidth; 1.292 + } 1.293 + 1.294 + if (!directInitialization) 1.295 + { 1.296 + ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize); 1.297 + 1.298 + // Data is already put into the staging buffer, copy it over to the data buffer 1.299 + D3D11_BOX srcBox; 1.300 + srcBox.left = 0; 1.301 + srcBox.right = size; 1.302 + srcBox.top = 0; 1.303 + srcBox.bottom = 1; 1.304 + srcBox.front = 0; 1.305 + srcBox.back = 1; 1.306 + 1.307 + context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox); 1.308 + } 1.309 + 1.310 + mSize = std::max(mSize, offset + size); 1.311 + 1.312 + mWriteUsageCount = 0; 1.313 + 1.314 + mResolvedDataValid = false; 1.315 +} 1.316 + 1.317 +void BufferStorage11::clear() 1.318 +{ 1.319 + mResolvedDataValid = false; 1.320 + mSize = 0; 1.321 +} 1.322 + 1.323 +unsigned int BufferStorage11::getSize() const 1.324 +{ 1.325 + return mSize; 1.326 +} 1.327 + 1.328 +bool BufferStorage11::supportsDirectBinding() const 1.329 +{ 1.330 + return true; 1.331 +} 1.332 + 1.333 +void BufferStorage11::markBufferUsage() 1.334 +{ 1.335 + mReadUsageCount++; 1.336 + mWriteUsageCount++; 1.337 + 1.338 + static const unsigned int usageLimit = 5; 1.339 + 1.340 + if (mReadUsageCount > usageLimit && mResolvedData) 1.341 + { 1.342 + free(mResolvedData); 1.343 + mResolvedData = NULL; 1.344 + mResolvedDataSize = 0; 1.345 + mResolvedDataValid = false; 1.346 + } 1.347 + 1.348 + if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer) 1.349 + { 1.350 + mStagingBuffer->Release(); 1.351 + mStagingBuffer = NULL; 1.352 + mStagingBufferSize = 0; 1.353 + } 1.354 +} 1.355 + 1.356 +ID3D11Buffer *BufferStorage11::getBuffer() const 1.357 +{ 1.358 + return mBuffer; 1.359 +} 1.360 + 1.361 +}