1// 2// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6 7// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. 8 9#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" 10#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" 11#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" 12#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" 13#include "libGLESv2/Buffer.h" 14#include "libGLESv2/VertexAttribute.h" 15 16namespace rx 17{ 18 19VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) 20{ 21 mBuffer = NULL; 22 mBufferSize = 0; 23 mDynamicUsage = false; 24} 25 26VertexBuffer11::~VertexBuffer11() 27{ 28 SafeRelease(mBuffer); 29} 30 31gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) 32{ 33 SafeRelease(mBuffer); 34 35 updateSerial(); 36 37 if (size > 0) 38 { 39 ID3D11Device* dxDevice = mRenderer->getDevice(); 40 41 D3D11_BUFFER_DESC bufferDesc; 42 bufferDesc.ByteWidth = size; 43 bufferDesc.Usage = D3D11_USAGE_DYNAMIC; 44 bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 45 bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 46 bufferDesc.MiscFlags = 0; 47 bufferDesc.StructureByteStride = 0; 48 49 HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); 50 if (FAILED(result)) 51 { 52 return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); 53 } 54 } 55 56 mBufferSize = size; 57 mDynamicUsage = dynamicUsage; 58 59 return gl::Error(GL_NO_ERROR); 60} 61 62VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) 63{ 64 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); 65 return static_cast<VertexBuffer11*>(vetexBuffer); 66} 67 68gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, 69 GLint start, GLsizei count, GLsizei instances, unsigned int offset) 70{ 71 if (!mBuffer) 72 { 73 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); 74 } 75 76 gl::Buffer *buffer = attrib.buffer.get(); 77 int inputStride = ComputeVertexAttributeStride(attrib); 78 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); 79 80 D3D11_MAPPED_SUBRESOURCE mappedResource; 81 HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); 82 if (FAILED(result)) 83 { 84 return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result); 85 } 86 87 uint8_t *output = reinterpret_cast<uint8_t*>(mappedResource.pData) + offset; 88 89 const uint8_t *input = NULL; 90 if (attrib.enabled) 91 { 92 if (buffer) 93 { 94 Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); 95 input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset); 96 } 97 else 98 { 99 input = static_cast<const uint8_t*>(attrib.pointer); 100 } 101 } 102 else 103 { 104 input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues); 105 } 106 107 if (instances == 0 || attrib.divisor == 0) 108 { 109 input += inputStride * start; 110 } 111 112 gl::VertexFormat vertexFormat(attrib, currentValue.Type); 113 const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); 114 ASSERT(vertexFormatInfo.copyFunction != NULL); 115 vertexFormatInfo.copyFunction(input, inputStride, count, output); 116 117 dxContext->Unmap(mBuffer, 0); 118 119 return gl::Error(GL_NO_ERROR); 120} 121 122gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, 123 GLsizei instances, unsigned int *outSpaceRequired) const 124{ 125 unsigned int elementCount = 0; 126 if (attrib.enabled) 127 { 128 if (instances == 0 || attrib.divisor == 0) 129 { 130 elementCount = count; 131 } 132 else 133 { 134 // Round up to divisor, if possible 135 elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor); 136 } 137 138 gl::VertexFormat vertexFormat(attrib); 139 const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); 140 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); 141 unsigned int elementSize = dxgiFormatInfo.pixelBytes; 142 if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) 143 { 144 if (outSpaceRequired) 145 { 146 *outSpaceRequired = elementSize * elementCount; 147 } 148 return gl::Error(GL_NO_ERROR); 149 } 150 else 151 { 152 return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); 153 } 154 } 155 else 156 { 157 const unsigned int elementSize = 4; 158 if (outSpaceRequired) 159 { 160 *outSpaceRequired = elementSize * 4; 161 } 162 return gl::Error(GL_NO_ERROR); 163 } 164} 165 166unsigned int VertexBuffer11::getBufferSize() const 167{ 168 return mBufferSize; 169} 170 171gl::Error VertexBuffer11::setBufferSize(unsigned int size) 172{ 173 if (size > mBufferSize) 174 { 175 return initialize(size, mDynamicUsage); 176 } 177 else 178 { 179 return gl::Error(GL_NO_ERROR); 180 } 181} 182 183gl::Error VertexBuffer11::discard() 184{ 185 if (!mBuffer) 186 { 187 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); 188 } 189 190 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); 191 192 D3D11_MAPPED_SUBRESOURCE mappedResource; 193 HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); 194 if (FAILED(result)) 195 { 196 return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result); 197 } 198 199 dxContext->Unmap(mBuffer, 0); 200 201 return gl::Error(GL_NO_ERROR); 202} 203 204ID3D11Buffer *VertexBuffer11::getBuffer() const 205{ 206 return mBuffer; 207} 208 209} 210