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 "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
10
11 #include "libANGLE/Buffer.h"
12 #include "libANGLE/VertexAttribute.h"
13 #include "libANGLE/formatutils.h"
14 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
15 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
16 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
17 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
18
19 namespace rx
20 {
21
VertexBuffer11(Renderer11 * const renderer)22 VertexBuffer11::VertexBuffer11(Renderer11 *const renderer)
23 : mRenderer(renderer),
24 mBuffer(),
25 mBufferSize(0),
26 mDynamicUsage(false),
27 mMappedResourceData(nullptr)
28 {
29 }
30
~VertexBuffer11()31 VertexBuffer11::~VertexBuffer11()
32 {
33 ASSERT(mMappedResourceData == nullptr);
34 }
35
initialize(unsigned int size,bool dynamicUsage)36 gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
37 {
38 mBuffer.reset();
39 updateSerial();
40
41 if (size > 0)
42 {
43 D3D11_BUFFER_DESC bufferDesc;
44 bufferDesc.ByteWidth = size;
45 bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
46 bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
47 bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
48 bufferDesc.MiscFlags = 0;
49 bufferDesc.StructureByteStride = 0;
50
51 ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer));
52
53 if (dynamicUsage)
54 {
55 mBuffer.setDebugName("VertexBuffer11 (dynamic)");
56 }
57 else
58 {
59 mBuffer.setDebugName("VertexBuffer11 (static)");
60 }
61 }
62
63 mBufferSize = size;
64 mDynamicUsage = dynamicUsage;
65
66 return gl::NoError();
67 }
68
mapResource()69 gl::Error VertexBuffer11::mapResource()
70 {
71 if (mMappedResourceData == nullptr)
72 {
73 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
74
75 D3D11_MAPPED_SUBRESOURCE mappedResource;
76
77 HRESULT result =
78 dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
79 if (FAILED(result))
80 {
81 return gl::OutOfMemory()
82 << "Failed to map internal vertex buffer, " << gl::FmtHR(result);
83 }
84
85 mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData);
86 }
87
88 return gl::NoError();
89 }
90
hintUnmapResource()91 void VertexBuffer11::hintUnmapResource()
92 {
93 if (mMappedResourceData != nullptr)
94 {
95 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
96 dxContext->Unmap(mBuffer.get(), 0);
97
98 mMappedResourceData = nullptr;
99 }
100 }
101
storeVertexAttributes(const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,GLenum currentValueType,GLint start,GLsizei count,GLsizei instances,unsigned int offset,const uint8_t * sourceData)102 gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib,
103 const gl::VertexBinding &binding,
104 GLenum currentValueType,
105 GLint start,
106 GLsizei count,
107 GLsizei instances,
108 unsigned int offset,
109 const uint8_t *sourceData)
110 {
111 if (!mBuffer.valid())
112 {
113 return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
114 }
115
116 int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
117
118 // This will map the resource if it isn't already mapped.
119 ANGLE_TRY(mapResource());
120
121 uint8_t *output = mMappedResourceData + offset;
122
123 const uint8_t *input = sourceData;
124
125 if (instances == 0 || binding.getDivisor() == 0)
126 {
127 input += inputStride * start;
128 }
129
130 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
131 const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
132 const d3d11::VertexFormat &vertexFormatInfo =
133 d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
134 ASSERT(vertexFormatInfo.copyFunction != nullptr);
135 vertexFormatInfo.copyFunction(input, inputStride, count, output);
136
137 return gl::NoError();
138 }
139
getBufferSize() const140 unsigned int VertexBuffer11::getBufferSize() const
141 {
142 return mBufferSize;
143 }
144
setBufferSize(unsigned int size)145 gl::Error VertexBuffer11::setBufferSize(unsigned int size)
146 {
147 if (size > mBufferSize)
148 {
149 return initialize(size, mDynamicUsage);
150 }
151 else
152 {
153 return gl::NoError();
154 }
155 }
156
discard()157 gl::Error VertexBuffer11::discard()
158 {
159 if (!mBuffer.valid())
160 {
161 return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
162 }
163
164 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
165
166 D3D11_MAPPED_SUBRESOURCE mappedResource;
167 HRESULT result = dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
168 if (FAILED(result))
169 {
170 return gl::OutOfMemory() << "Failed to map internal buffer for discarding, "
171 << gl::FmtHR(result);
172 }
173
174 dxContext->Unmap(mBuffer.get(), 0);
175
176 return gl::NoError();
177 }
178
getBuffer() const179 const d3d11::Buffer &VertexBuffer11::getBuffer() const
180 {
181 return mBuffer;
182 }
183
184 } // namespace rx
185