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