Commit c9fed8dd by Jamie Madill Committed by Commit Bot

D3D11: Move TF state management to StateManager11.

This also changes the dirty TF object to use a Serial, which is more secure for very edge-care reallocation issues. It also moves the StateManager11::updateState call to be the very first thing that happens in a draw call. This prepares the back-end for making the state sync actually happen in Context11::syncState, instead of inside the draw call. Also moves a bit more TF management code out of RendererD3D and Renderer9. BUG=angleproject:2052 Change-Id: I93d033a07be2049023111975a31637c53893e8c8 Reviewed-on: https://chromium-review.googlesource.com/659229Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent cd8e9729
......@@ -1006,8 +1006,8 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va
return preambleStream.str();
}
std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::ContextState &data,
std::string DynamicHLSL::generateGeometryShaderHLSL(const gl::Context *context,
gl::PrimitiveType primitiveType,
const gl::ProgramState &programData,
const bool useViewScale,
const bool hasANGLEMultiviewEnabled,
......@@ -1114,10 +1114,10 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
"};\n"
"\n"
"static float minPointSize = "
<< static_cast<int>(data.getCaps().minAliasedPointSize)
<< static_cast<int>(context->getCaps().minAliasedPointSize)
<< ".0f;\n"
"static float maxPointSize = "
<< static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n"
<< static_cast<int>(context->getCaps().maxAliasedPointSize) << ".0f;\n"
<< "\n";
}
......
......@@ -135,8 +135,8 @@ class DynamicHLSL : angle::NonCopyable
const bool hasANGLEMultiviewEnabled,
const bool selectViewInVS) const;
std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
const gl::ContextState &data,
std::string generateGeometryShaderHLSL(const gl::Context *context,
gl::PrimitiveType primitiveType,
const gl::ProgramState &programData,
const bool useViewScale,
const bool hasANGLEMultiviewEnabled,
......
......@@ -1272,7 +1272,7 @@ gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3
return gl::NoError();
}
gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::ContextState &data,
gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Context *context,
GLenum drawMode,
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog)
......@@ -1300,7 +1300,7 @@ gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::ContextSta
}
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
geometryShaderType, data, mState, mRenderer->presentPathFastEnabled(),
context, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
......@@ -1404,8 +1404,8 @@ void ProgramD3D::updateCachedOutputLayoutFromShader()
class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
{
public:
GetGeometryExecutableTask(ProgramD3D *program, const gl::ContextState &contextState)
: GetExecutableTask(program), mContextState(contextState)
GetGeometryExecutableTask(ProgramD3D *program, const gl::Context *context)
: GetExecutableTask(program), mContext(context)
{
}
......@@ -1415,15 +1415,15 @@ class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTa
// D3D11.
if (mProgram->usesGeometryShader(GL_POINTS))
{
ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(mContextState, GL_POINTS,
&mResult, &mInfoLog));
ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(mContext, GL_POINTS, &mResult,
&mInfoLog));
}
return gl::NoError();
}
private:
const gl::ContextState &mContextState;
const gl::Context *mContext;
};
gl::Error ProgramD3D::getComputeExecutable(ShaderExecutableD3D **outExecutable)
......@@ -1446,7 +1446,7 @@ gl::LinkResult ProgramD3D::compileProgramExecutables(const gl::Context *context,
GetVertexExecutableTask vertexTask(this, context);
GetPixelExecutableTask pixelTask(this);
GetGeometryExecutableTask geometryTask(this, context->getContextState());
GetGeometryExecutableTask geometryTask(this, context);
std::array<WaitableEvent, 3> waitEvents = {{workerPool->postWorkerTask(&vertexTask),
workerPool->postWorkerTask(&pixelTask),
......
......@@ -184,7 +184,7 @@ class ProgramD3D : public ProgramImpl
gl::Error getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
gl::InfoLog *infoLog);
gl::Error getGeometryExecutableForPrimitiveType(const gl::ContextState &data,
gl::Error getGeometryExecutableForPrimitiveType(const gl::Context *context,
GLenum drawMode,
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog);
......
......@@ -59,18 +59,16 @@ void RendererD3D::cleanup()
mIncompleteTextures.clear();
}
bool RendererD3D::skipDraw(const gl::ContextState &data, GLenum drawMode)
bool RendererD3D::skipDraw(const gl::State &glState, GLenum drawMode)
{
const gl::State &state = data.getState();
if (drawMode == GL_POINTS)
{
bool usesPointSize = GetImplAs<ProgramD3D>(state.getProgram())->usesPointSize();
bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
// ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
// which affects varying interpolation. Since the value of gl_PointSize is
// undefined when not written, just skip drawing to avoid unexpected results.
if (!usesPointSize && !state.isTransformFeedbackActiveUnpaused())
if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
{
// Notify developers of risking undefined behavior.
WARN() << "Point rendering without writing to gl_PointSize.";
......@@ -79,8 +77,8 @@ bool RendererD3D::skipDraw(const gl::ContextState &data, GLenum drawMode)
}
else if (gl::IsTriangleMode(drawMode))
{
if (state.getRasterizerState().cullFace &&
state.getRasterizerState().cullMode == GL_FRONT_AND_BACK)
if (glState.getRasterizerState().cullFace &&
glState.getRasterizerState().cullMode == GL_FRONT_AND_BACK)
{
return true;
}
......@@ -89,23 +87,6 @@ bool RendererD3D::skipDraw(const gl::ContextState &data, GLenum drawMode)
return false;
}
gl::Error RendererD3D::markTransformFeedbackUsage(const gl::ContextState &data)
{
const gl::TransformFeedback *transformFeedback = data.getState().getCurrentTransformFeedback();
for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
{
const gl::OffsetBindingPointer<gl::Buffer> &binding =
transformFeedback->getIndexedBuffer(i);
if (binding.get() != nullptr)
{
BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
ANGLE_TRY(bufferD3D->markTransformFeedbackUsage());
}
}
return gl::NoError();
}
size_t RendererD3D::getBoundFramebufferTextures(const gl::ContextState &data,
FramebufferTextureArray *outTextureArray)
{
......
......@@ -331,8 +331,7 @@ class RendererD3D : public BufferFactoryD3D
// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
bool skipDraw(const gl::ContextState &data, GLenum drawMode);
gl::Error markTransformFeedbackUsage(const gl::ContextState &data);
bool skipDraw(const gl::State &glState, GLenum drawMode);
egl::Display *mDisplay;
......
......@@ -153,6 +153,9 @@ gl::Error Context11::finish()
gl::Error Context11::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count)
{
// TODO(jmadill): Update state in syncState before the draw call.
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode));
return mRenderer->genericDrawArrays(context, mode, first, count, 0);
}
......@@ -162,6 +165,9 @@ gl::Error Context11::drawArraysInstanced(const gl::Context *context,
GLsizei count,
GLsizei instanceCount)
{
// TODO(jmadill): Update state in syncState before the draw call.
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode));
return mRenderer->genericDrawArrays(context, mode, first, count, instanceCount);
}
......@@ -171,6 +177,9 @@ gl::Error Context11::drawElements(const gl::Context *context,
GLenum type,
const void *indices)
{
// TODO(jmadill): Update state in syncState before the draw call.
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode));
return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
}
......@@ -181,6 +190,9 @@ gl::Error Context11::drawElementsInstanced(const gl::Context *context,
const void *indices,
GLsizei instances)
{
// TODO(jmadill): Update state in syncState before the draw call.
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode));
return mRenderer->genericDrawElements(context, mode, count, type, indices, instances);
}
......@@ -192,6 +204,9 @@ gl::Error Context11::drawRangeElements(const gl::Context *context,
GLenum type,
const void *indices)
{
// TODO(jmadill): Update state in syncState before the draw call.
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode));
return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
}
......@@ -199,6 +214,9 @@ gl::Error Context11::drawArraysIndirect(const gl::Context *context,
GLenum mode,
const void *indirect)
{
// TODO(jmadill): Update state in syncState before the draw call.
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode));
return mRenderer->genericDrawIndirect(context, mode, GL_NONE, indirect);
}
......@@ -207,6 +225,9 @@ gl::Error Context11::drawElementsIndirect(const gl::Context *context,
GLenum type,
const void *indirect)
{
// TODO(jmadill): Update state in syncState before the draw call.
ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode));
return mRenderer->genericDrawIndirect(context, mode, type, indirect);
}
......@@ -335,8 +356,8 @@ gl::Error Context11::triggerDrawCallProgramRecompilation(const gl::Context *cont
if (recompileGS)
{
ShaderExecutableD3D *geometryExe = nullptr;
ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(
context->getContextState(), drawMode, &geometryExe, infoLog));
ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe,
infoLog));
if (!programD3D->hasGeometryExecutableForPrimitiveType(drawMode))
{
return gl::InternalError() << "Error compiling dynamic geometry executable.";
......
......@@ -147,7 +147,6 @@ class Renderer11 : public RendererD3D
const egl::AttributeMap &attribs) const override;
bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
gl::Error applyTransformFeedbackBuffers(const gl::ContextState &data);
// lost device
bool testDeviceLost() override;
......@@ -485,13 +484,13 @@ class Renderer11 : public RendererD3D
angle::WorkaroundsD3D generateWorkarounds() const override;
gl::Error drawLineLoop(const gl::ContextState &data,
gl::Error drawLineLoop(const gl::State &glState,
GLsizei count,
GLenum type,
const void *indices,
int baseVertex,
int instances);
gl::Error drawTriangleFan(const gl::ContextState &data,
gl::Error drawTriangleFan(const gl::State &glState,
GLsizei count,
GLenum type,
const void *indices,
......@@ -525,6 +524,8 @@ class Renderer11 : public RendererD3D
d3d11::ANGLED3D11DeviceType getDeviceType() const;
gl::Error markTransformFeedbackUsage(const gl::State &glState);
HMODULE mD3d11Module;
HMODULE mDxgiModule;
HMODULE mDCompModule;
......@@ -540,9 +541,6 @@ class Renderer11 : public RendererD3D
StateManager11 mStateManager;
// Currently applied transform feedback buffers
uintptr_t mAppliedTFObject;
StreamingIndexBufferInterface *mLineLoopIB;
StreamingIndexBufferInterface *mTriangleFanIB;
......
......@@ -21,6 +21,7 @@
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
namespace rx
......@@ -541,7 +542,8 @@ StateManager11::StateManager11(Renderer11 *renderer)
mAppliedIBChanged(false),
mVertexDataManager(renderer),
mIndexDataManager(renderer, RENDERER_D3D11),
mIsMultiviewEnabled(false)
mIsMultiviewEnabled(false),
mEmptySerial(mRenderer->generateSerial())
{
mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE;
......@@ -1343,6 +1345,8 @@ void StateManager11::invalidateEverything(const gl::Context *context)
// As long as all calls to *SSetConstantBuffes go through the StateManager11, it should not be
// necessary to invalidate constant buffer state.
mAppliedTFSerial = Serial();
}
void StateManager11::invalidateVertexBuffer()
......@@ -1899,6 +1903,8 @@ gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMod
}
}
ANGLE_TRY(syncTransformFeedbackBuffers(context));
// Check that we haven't set any dirty bits in the flushing of the dirty bits loop.
ASSERT(mInternalDirtyBits.none());
......@@ -2253,8 +2259,8 @@ gl::Error StateManager11::syncProgram(const gl::Context *context, GLenum drawMod
ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
ShaderExecutableD3D *geometryExe = nullptr;
ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context->getContextState(),
drawMode, &geometryExe, nullptr));
ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe,
nullptr));
const d3d11::VertexShader *vertexShader =
(vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
......@@ -2371,13 +2377,13 @@ gl::Error StateManager11::applyVertexBuffer(const gl::Context *context,
return gl::NoError();
}
gl::Error StateManager11::applyIndexBuffer(const gl::ContextState &data,
gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
const void *indices,
GLsizei count,
GLenum type,
TranslatedIndexData *indexInfo)
{
const auto &glState = data.getState();
const auto &glState = context->getGLState();
gl::VertexArray *vao = glState.getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
ANGLE_TRY(mIndexDataManager.prepareIndexData(type, count, elementArrayBuffer, indices,
......@@ -2792,4 +2798,40 @@ gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, Program
return gl::NoError();
}
gl::Error StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
{
const auto &glState = context->getGLState();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
// If transform feedback is not active, unbind all buffers
if (!glState.isTransformFeedbackActiveUnpaused())
{
if (mAppliedTFSerial != mEmptySerial)
{
deviceContext->SOSetTargets(0, nullptr, nullptr);
mAppliedTFSerial = mEmptySerial;
}
return gl::NoError();
}
gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
TransformFeedback11 *tf11 = GetImplAs<TransformFeedback11>(transformFeedback);
if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
{
return gl::NoError();
}
const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
ANGLE_TRY_RESULT(tf11->getSOBuffers(), soBuffers);
const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();
deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());
mAppliedTFSerial = tf11->getSerial();
tf11->onApply();
return gl::NoError();
}
} // namespace rx
......@@ -225,7 +225,7 @@ class StateManager11 final : angle::NonCopyable
GLsizei instances,
TranslatedIndexData *indexInfo);
gl::Error applyIndexBuffer(const gl::ContextState &data,
gl::Error applyIndexBuffer(const gl::Context *context,
const void *indices,
GLsizei count,
GLenum type,
......@@ -301,6 +301,7 @@ class StateManager11 final : angle::NonCopyable
gl::Error applyUniforms(ProgramD3D *programD3D);
gl::Error syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D);
gl::Error syncTransformFeedbackBuffers(const gl::Context *context);
enum DirtyBitType
{
......@@ -481,6 +482,11 @@ class StateManager11 final : angle::NonCopyable
FragmentConstantBufferArray<ResourceSerial> mCurrentConstantBufferPS;
FragmentConstantBufferArray<GLintptr> mCurrentConstantBufferPSOffset;
FragmentConstantBufferArray<GLsizeiptr> mCurrentConstantBufferPSSize;
// Currently applied transform feedback buffers
Serial mAppliedTFSerial;
Serial mEmptySerial;
};
} // namespace rx
......
......@@ -21,7 +21,8 @@ TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state
mRenderer(renderer),
mIsDirty(true),
mBuffers(state.getIndexedBuffers().size(), nullptr),
mBufferOffsets(state.getIndexedBuffers().size(), 0)
mBufferOffsets(state.getIndexedBuffers().size(), 0),
mSerial(mRenderer->generateSerial())
{
}
......@@ -113,4 +114,10 @@ const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const
{
return mBufferOffsets;
}
Serial TransformFeedback11::getSerial() const
{
return mSerial;
}
} // namespace rx
......@@ -11,9 +11,10 @@
#include "common/platform.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h"
#include "libANGLE/renderer/renderer_utils.h"
namespace rx
{
......@@ -43,12 +44,16 @@ class TransformFeedback11 : public TransformFeedbackImpl
gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> getSOBuffers();
const std::vector<UINT> &getSOBufferOffsets() const;
Serial getSerial() const;
private:
Renderer11 *mRenderer;
bool mIsDirty;
std::vector<ID3D11Buffer *> mBuffers;
std::vector<UINT> mBufferOffsets;
Serial mSerial;
};
} // namespace rx
......
......@@ -1360,12 +1360,6 @@ gl::Error Renderer9::applyIndexBuffer(const gl::ContextState &data,
return gl::NoError();
}
gl::Error Renderer9::applyTransformFeedbackBuffers(const gl::State &state)
{
ASSERT(!state.isTransformFeedbackActiveUnpaused());
return gl::NoError();
}
gl::Error Renderer9::drawArraysImpl(const gl::ContextState &data,
GLenum mode,
GLint startVertex,
......@@ -3140,19 +3134,10 @@ gl::Error Renderer9::genericDrawElements(const gl::Context *context,
}
ANGLE_TRY(updateState(context, mode));
applyTransformFeedbackBuffers(data.getState());
// Transform feedback is not allowed for DrawElements, this error should have been caught at the
// API validation
// layer.
ASSERT(!data.getState().isTransformFeedbackActiveUnpaused());
ANGLE_TRY(applyTextures(context));
ANGLE_TRY(applyShaders(context, mode));
if (!skipDraw(data, mode))
if (!skipDraw(data.getState(), mode))
{
ANGLE_TRY(drawElementsImpl(context, mode, count, type, indices, instances));
}
......@@ -3180,19 +3165,13 @@ gl::Error Renderer9::genericDrawArrays(const gl::Context *context,
}
ANGLE_TRY(updateState(context, mode));
ANGLE_TRY(applyTransformFeedbackBuffers(data.getState()));
ANGLE_TRY(applyVertexBuffer(data.getState(), mode, first, count, instances, nullptr));
ANGLE_TRY(applyTextures(context));
ANGLE_TRY(applyShaders(context, mode));
if (!skipDraw(data, mode))
if (!skipDraw(data.getState(), mode))
{
ANGLE_TRY(drawArraysImpl(data, mode, first, count, instances));
if (data.getState().isTransformFeedbackActiveUnpaused())
{
ANGLE_TRY(markTransformFeedbackUsage(data));
}
}
return gl::NoError();
......
......@@ -158,8 +158,6 @@ class Renderer9 : public RendererD3D
GLenum type,
TranslatedIndexData *indexInfo);
gl::Error applyTransformFeedbackBuffers(const gl::State &state);
gl::Error clear(const gl::Context *context,
const ClearParameters &clearParams,
const gl::FramebufferAttachment *colorBuffer,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment