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 16 namespace rx 17 { 18 19 VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) 20 { 21 mBuffer = NULL; 22 mBufferSize = 0; 23 mDynamicUsage = false; 24 } 25 26 VertexBuffer11::~VertexBuffer11() 27 { 28 SafeRelease(mBuffer); 29 } 30 31 gl::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 62 VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) 63 { 64 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); 65 return static_cast<VertexBuffer11*>(vetexBuffer); 66 } 67 68 gl::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 122 gl::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 166 unsigned int VertexBuffer11::getBufferSize() const 167 { 168 return mBufferSize; 169 } 170 171 gl::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 183 gl::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 204 ID3D11Buffer *VertexBuffer11::getBuffer() const 205 { 206 return mBuffer; 207 } 208 209 } 210