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