blob: 9bc5b1d2d16cc345b9ec7d7f178501d9902c1555 [file] [log] [blame]
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +00001//
shannon.woods@transgaming.com07765502013-02-28 23:06:43 +00002// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +00003// 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 Jonesc7a41042014-06-23 12:03:25 -07009#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
Brandon Jonesd38f9262014-06-18 16:26:45 -070010#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
Brandon Jonesc7a41042014-06-23 12:03:25 -070011#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
Brandon Jonesc7a41042014-06-23 12:03:25 -070012#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040013#include "libGLESv2/Buffer.h"
14#include "libGLESv2/VertexAttribute.h"
Jamie Madilla857c362013-07-02 11:57:02 -040015
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000016namespace 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{
Geoff Langea228632013-07-30 15:17:12 -040028 SafeRelease(mBuffer);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000029}
30
Geoff Langf7100b92014-09-08 16:17:08 -040031gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000032{
Geoff Langea228632013-07-30 15:17:12 -040033 SafeRelease(mBuffer);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000034
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 Langf7100b92014-09-08 16:17:08 -040052 return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000053 }
54 }
55
56 mBufferSize = size;
57 mDynamicUsage = dynamicUsage;
Geoff Langf7100b92014-09-08 16:17:08 -040058
59 return gl::Error(GL_NO_ERROR);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000060}
61
62VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
63{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +000064 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000065 return static_cast<VertexBuffer11*>(vetexBuffer);
66}
67
Geoff Langf7100b92014-09-08 16:17:08 -040068gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
69 GLint start, GLsizei count, GLsizei instances, unsigned int offset)
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000070{
Geoff Langf7100b92014-09-08 16:17:08 -040071 if (!mBuffer)
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000072 {
Geoff Langf7100b92014-09-08 16:17:08 -040073 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
74 }
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000075
Geoff Langf7100b92014-09-08 16:17:08 -040076 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.com2c4d0702012-12-20 21:08:51 +000093 {
Geoff Langf7100b92014-09-08 16:17:08 -040094 Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation());
95 input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +000096 }
97 else
98 {
Geoff Langf7100b92014-09-08 16:17:08 -040099 input = static_cast<const uint8_t*>(attrib.pointer);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000100 }
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000101 }
102 else
103 {
Geoff Langf7100b92014-09-08 16:17:08 -0400104 input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000105 }
Geoff Langf7100b92014-09-08 16:17:08 -0400106
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.com2c4d0702012-12-20 21:08:51 +0000120}
121
Geoff Langf7100b92014-09-08 16:17:08 -0400122gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
123 GLsizei instances, unsigned int *outSpaceRequired) const
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000124{
Geoff Langa36ead42013-08-02 11:54:08 -0400125 unsigned int elementCount = 0;
Brandon Jones5bf98292014-06-06 17:19:38 -0700126 if (attrib.enabled)
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000127 {
Brandon Jones5bf98292014-06-06 17:19:38 -0700128 if (instances == 0 || attrib.divisor == 0)
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000129 {
Geoff Langa36ead42013-08-02 11:54:08 -0400130 elementCount = count;
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000131 }
132 else
133 {
Jamie Madillaff80842014-08-04 10:47:56 -0400134 // Round up to divisor, if possible
135 elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
Geoff Langa36ead42013-08-02 11:54:08 -0400136 }
137
Jamie Madill7ab02fa2014-02-04 16:04:08 -0500138 gl::VertexFormat vertexFormat(attrib);
Geoff Lang9aa00bb2014-07-07 12:33:25 -0400139 const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
140 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat);
141 unsigned int elementSize = dxgiFormatInfo.pixelBytes;
Geoff Langa36ead42013-08-02 11:54:08 -0400142 if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
143 {
144 if (outSpaceRequired)
145 {
146 *outSpaceRequired = elementSize * elementCount;
147 }
Geoff Langf7100b92014-09-08 16:17:08 -0400148 return gl::Error(GL_NO_ERROR);
Geoff Langa36ead42013-08-02 11:54:08 -0400149 }
150 else
151 {
Geoff Langf7100b92014-09-08 16:17:08 -0400152 return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
shannon.woods%transgaming.com@gtempaccount.comcf8d2f82013-04-13 03:37:34 +0000153 }
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000154 }
155 else
156 {
Geoff Langa36ead42013-08-02 11:54:08 -0400157 const unsigned int elementSize = 4;
158 if (outSpaceRequired)
159 {
160 *outSpaceRequired = elementSize * 4;
161 }
Geoff Langf7100b92014-09-08 16:17:08 -0400162 return gl::Error(GL_NO_ERROR);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000163 }
164}
165
166unsigned int VertexBuffer11::getBufferSize() const
167{
168 return mBufferSize;
169}
170
Geoff Langf7100b92014-09-08 16:17:08 -0400171gl::Error VertexBuffer11::setBufferSize(unsigned int size)
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000172{
173 if (size > mBufferSize)
174 {
175 return initialize(size, mDynamicUsage);
176 }
177 else
178 {
Geoff Langf7100b92014-09-08 16:17:08 -0400179 return gl::Error(GL_NO_ERROR);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000180 }
181}
182
Geoff Langf7100b92014-09-08 16:17:08 -0400183gl::Error VertexBuffer11::discard()
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000184{
Geoff Langf7100b92014-09-08 16:17:08 -0400185 if (!mBuffer)
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000186 {
Geoff Langf7100b92014-09-08 16:17:08 -0400187 return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000188 }
Geoff Langf7100b92014-09-08 16:17:08 -0400189
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.com2c4d0702012-12-20 21:08:51 +0000195 {
Geoff Langf7100b92014-09-08 16:17:08 -0400196 return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000197 }
Geoff Langf7100b92014-09-08 16:17:08 -0400198
199 dxContext->Unmap(mBuffer, 0);
200
201 return gl::Error(GL_NO_ERROR);
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000202}
203
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000204ID3D11Buffer *VertexBuffer11::getBuffer() const
205{
206 return mBuffer;
207}
208
daniel@transgaming.com2c4d0702012-12-20 21:08:51 +0000209}