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