daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 1 | // |
shannon.woods@transgaming.com | 0776550 | 2013-02-28 23:06:43 +0000 | [diff] [blame] | 2 | // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 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 | |
Brandon Jones | c7a4104 | 2014-06-23 12:03:25 -0700 | [diff] [blame] | 9 | #include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" |
Brandon Jones | d38f926 | 2014-06-18 16:26:45 -0700 | [diff] [blame] | 10 | #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" |
Brandon Jones | c7a4104 | 2014-06-23 12:03:25 -0700 | [diff] [blame] | 11 | #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" |
Brandon Jones | c7a4104 | 2014-06-23 12:03:25 -0700 | [diff] [blame] | 12 | #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" |
Geoff Lang | 0b7eef7 | 2014-06-12 14:10:47 -0400 | [diff] [blame] | 13 | #include "libGLESv2/Buffer.h" |
| 14 | #include "libGLESv2/VertexAttribute.h" |
Jamie Madill | a857c36 | 2013-07-02 11:57:02 -0400 | [diff] [blame] | 15 | |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 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 | { |
Geoff Lang | ea22863 | 2013-07-30 15:17:12 -0400 | [diff] [blame] | 28 | SafeRelease(mBuffer); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 29 | } |
| 30 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 31 | gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 32 | { |
Geoff Lang | ea22863 | 2013-07-30 15:17:12 -0400 | [diff] [blame] | 33 | SafeRelease(mBuffer); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 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 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 52 | return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 53 | } |
| 54 | } |
| 55 | |
| 56 | mBufferSize = size; |
| 57 | mDynamicUsage = dynamicUsage; |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 58 | |
| 59 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) |
| 63 | { |
apatrick@chromium.org | 8b400b1 | 2013-01-30 21:53:40 +0000 | [diff] [blame] | 64 | ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 65 | return static_cast<VertexBuffer11*>(vetexBuffer); |
| 66 | } |
| 67 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 68 | gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, |
| 69 | GLint start, GLsizei count, GLsizei instances, unsigned int offset) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 70 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 71 | if (!mBuffer) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 72 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 73 | return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); |
| 74 | } |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 75 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 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) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 93 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 94 | Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); |
| 95 | input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 96 | } |
| 97 | else |
| 98 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 99 | input = static_cast<const uint8_t*>(attrib.pointer); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 100 | } |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 101 | } |
| 102 | else |
| 103 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 104 | input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 105 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 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); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 120 | } |
| 121 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 122 | gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, |
| 123 | GLsizei instances, unsigned int *outSpaceRequired) const |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 124 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 125 | unsigned int elementCount = 0; |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame] | 126 | if (attrib.enabled) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 127 | { |
Brandon Jones | 5bf9829 | 2014-06-06 17:19:38 -0700 | [diff] [blame] | 128 | if (instances == 0 || attrib.divisor == 0) |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 129 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 130 | elementCount = count; |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 131 | } |
| 132 | else |
| 133 | { |
Jamie Madill | aff8084 | 2014-08-04 10:47:56 -0400 | [diff] [blame] | 134 | // Round up to divisor, if possible |
| 135 | elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor); |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 136 | } |
| 137 | |
Jamie Madill | 7ab02fa | 2014-02-04 16:04:08 -0500 | [diff] [blame] | 138 | gl::VertexFormat vertexFormat(attrib); |
Geoff Lang | 9aa00bb | 2014-07-07 12:33:25 -0400 | [diff] [blame] | 139 | const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); |
| 140 | const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); |
| 141 | unsigned int elementSize = dxgiFormatInfo.pixelBytes; |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 142 | if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) |
| 143 | { |
| 144 | if (outSpaceRequired) |
| 145 | { |
| 146 | *outSpaceRequired = elementSize * elementCount; |
| 147 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 148 | return gl::Error(GL_NO_ERROR); |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 149 | } |
| 150 | else |
| 151 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 152 | return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); |
shannon.woods%transgaming.com@gtempaccount.com | cf8d2f8 | 2013-04-13 03:37:34 +0000 | [diff] [blame] | 153 | } |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 154 | } |
| 155 | else |
| 156 | { |
Geoff Lang | a36ead4 | 2013-08-02 11:54:08 -0400 | [diff] [blame] | 157 | const unsigned int elementSize = 4; |
| 158 | if (outSpaceRequired) |
| 159 | { |
| 160 | *outSpaceRequired = elementSize * 4; |
| 161 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 162 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 163 | } |
| 164 | } |
| 165 | |
| 166 | unsigned int VertexBuffer11::getBufferSize() const |
| 167 | { |
| 168 | return mBufferSize; |
| 169 | } |
| 170 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 171 | gl::Error VertexBuffer11::setBufferSize(unsigned int size) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 172 | { |
| 173 | if (size > mBufferSize) |
| 174 | { |
| 175 | return initialize(size, mDynamicUsage); |
| 176 | } |
| 177 | else |
| 178 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 179 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 180 | } |
| 181 | } |
| 182 | |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 183 | gl::Error VertexBuffer11::discard() |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 184 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 185 | if (!mBuffer) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 186 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 187 | return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 188 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 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)) |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 195 | { |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 196 | return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 197 | } |
Geoff Lang | f7100b9 | 2014-09-08 16:17:08 -0400 | [diff] [blame] | 198 | |
| 199 | dxContext->Unmap(mBuffer, 0); |
| 200 | |
| 201 | return gl::Error(GL_NO_ERROR); |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 202 | } |
| 203 | |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 204 | ID3D11Buffer *VertexBuffer11::getBuffer() const |
| 205 | { |
| 206 | return mBuffer; |
| 207 | } |
| 208 | |
daniel@transgaming.com | 2c4d070 | 2012-12-20 21:08:51 +0000 | [diff] [blame] | 209 | } |