1 //
2 // Copyright 2014 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 // TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
8 
9 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
10 
11 #include "libANGLE/Buffer.h"
12 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
13 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
14 
15 namespace rx
16 {
17 
TransformFeedback11(const gl::TransformFeedbackState & state,Renderer11 * renderer)18 TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state,
19                                          Renderer11 *renderer)
20     : TransformFeedbackImpl(state),
21       mRenderer(renderer),
22       mIsDirty(true),
23       mBuffers(state.getIndexedBuffers().size(), nullptr),
24       mBufferOffsets(state.getIndexedBuffers().size(), 0),
25       mSerial(mRenderer->generateSerial())
26 {}
27 
~TransformFeedback11()28 TransformFeedback11::~TransformFeedback11() {}
29 
begin(const gl::Context * context,gl::PrimitiveMode primitiveMode)30 angle::Result TransformFeedback11::begin(const gl::Context *context,
31                                          gl::PrimitiveMode primitiveMode)
32 {
33     // Reset all the cached offsets to the binding offsets
34     mIsDirty = true;
35     for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
36     {
37         const auto &binding = mState.getIndexedBuffer(bindingIdx);
38         if (binding.get() != nullptr)
39         {
40             mBufferOffsets[bindingIdx] = static_cast<UINT>(binding.getOffset());
41         }
42         else
43         {
44             mBufferOffsets[bindingIdx] = 0;
45         }
46     }
47     mRenderer->getStateManager()->invalidateTransformFeedback();
48     return angle::Result::Continue;
49 }
50 
end(const gl::Context * context)51 angle::Result TransformFeedback11::end(const gl::Context *context)
52 {
53     mRenderer->getStateManager()->invalidateTransformFeedback();
54     if (mRenderer->getFeatures().flushAfterEndingTransformFeedback.enabled)
55     {
56         mRenderer->getDeviceContext()->Flush();
57     }
58     return angle::Result::Continue;
59 }
60 
pause(const gl::Context * context)61 angle::Result TransformFeedback11::pause(const gl::Context *context)
62 {
63     mRenderer->getStateManager()->invalidateTransformFeedback();
64     return angle::Result::Continue;
65 }
66 
resume(const gl::Context * context)67 angle::Result TransformFeedback11::resume(const gl::Context *context)
68 {
69     mRenderer->getStateManager()->invalidateTransformFeedback();
70     return angle::Result::Continue;
71 }
72 
bindIndexedBuffer(const gl::Context * context,size_t index,const gl::OffsetBindingPointer<gl::Buffer> & binding)73 angle::Result TransformFeedback11::bindIndexedBuffer(
74     const gl::Context *context,
75     size_t index,
76     const gl::OffsetBindingPointer<gl::Buffer> &binding)
77 {
78     mIsDirty              = true;
79     mBufferOffsets[index] = static_cast<UINT>(binding.getOffset());
80     mRenderer->getStateManager()->invalidateTransformFeedback();
81     return angle::Result::Continue;
82 }
83 
onApply()84 void TransformFeedback11::onApply()
85 {
86     mIsDirty = false;
87 
88     // Change all buffer offsets to -1 so that if any of them need to be re-applied, the are set to
89     // append
90     std::fill(mBufferOffsets.begin(), mBufferOffsets.end(), -1);
91 }
92 
isDirty() const93 bool TransformFeedback11::isDirty() const
94 {
95     return mIsDirty;
96 }
97 
getNumSOBuffers() const98 UINT TransformFeedback11::getNumSOBuffers() const
99 {
100     return static_cast<UINT>(mBuffers.size());
101 }
102 
getSOBuffers(const gl::Context * context,const std::vector<ID3D11Buffer * > ** buffersOut)103 angle::Result TransformFeedback11::getSOBuffers(const gl::Context *context,
104                                                 const std::vector<ID3D11Buffer *> **buffersOut)
105 {
106     for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
107     {
108         const auto &binding = mState.getIndexedBuffer(bindingIdx);
109         if (binding.get() != nullptr)
110         {
111             Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
112             ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
113                                          &mBuffers[bindingIdx]));
114         }
115     }
116 
117     *buffersOut = &mBuffers;
118     return angle::Result::Continue;
119 }
120 
getSOBufferOffsets() const121 const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const
122 {
123     return mBufferOffsets;
124 }
125 
getSerial() const126 Serial TransformFeedback11::getSerial() const
127 {
128     return mSerial;
129 }
130 
131 }  // namespace rx
132