D3D11: Consolidate input layout application.
This merges all calls to IASetInputLayout to a single place in
StateManager11. This means we no longer have to invalidate the state
for D3D11, and can always lazily apply the input layout state.
Introduces a new ResourceSerial class to replace the uintptr_t and
DirtyPointer design.
BUG=angleproject:2052
Change-Id: I76b874218b754395f25a129967c769b1f8f82115
Reviewed-on: https://chromium-review.googlesource.com/523025
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
index b6adc6b..612ff80 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -951,7 +951,7 @@
{
ANGLE_TRY(mQuad2DIL.resolve(mRenderer));
ANGLE_TRY(mQuad2DVS.resolve(mRenderer));
- supportOut->inputLayout = mQuad2DIL.get();
+ supportOut->inputLayout = &mQuad2DIL.getObj();
supportOut->vertexShader = mQuad2DVS.get();
supportOut->geometryShader = nullptr;
supportOut->vertexWriteFunction = Write2DVertices;
@@ -962,7 +962,7 @@
ANGLE_TRY(mQuad3DIL.resolve(mRenderer));
ANGLE_TRY(mQuad3DVS.resolve(mRenderer));
ANGLE_TRY(mQuad3DGS.resolve(mRenderer));
- supportOut->inputLayout = mQuad2DIL.get();
+ supportOut->inputLayout = &mQuad2DIL.getObj();
supportOut->vertexShader = mQuad3DVS.get();
supportOut->geometryShader = mQuad3DGS.get();
supportOut->vertexWriteFunction = Write3DVertices;
@@ -1063,6 +1063,8 @@
deviceContext->Unmap(mSwizzleCB.get(), 0);
+ auto stateManager = mRenderer->getStateManager();
+
// Apply vertex buffer
ID3D11Buffer *vertexBuffer = mVertexBuffer.get();
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &startIdx);
@@ -1077,7 +1079,7 @@
deviceContext->RSSetState(mScissorDisabledRasterizerState.get());
// Apply shaders
- deviceContext->IASetInputLayout(support.inputLayout);
+ stateManager->setInputLayout(support.inputLayout);
deviceContext->IASetPrimitiveTopology(topology);
deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
@@ -1085,7 +1087,6 @@
deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
// Unset the currently bound shader resource to avoid conflicts
- auto stateManager = mRenderer->getStateManager();
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
// Apply render target
@@ -1183,6 +1184,8 @@
deviceContext->Unmap(mVertexBuffer.get(), 0);
+ auto stateManager = mRenderer->getStateManager();
+
// Apply vertex buffer
ID3D11Buffer *vertexBuffer = mVertexBuffer.get();
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &startIdx);
@@ -1217,7 +1220,7 @@
}
// Apply shaders
- deviceContext->IASetInputLayout(support.inputLayout);
+ stateManager->setInputLayout(support.inputLayout);
deviceContext->IASetPrimitiveTopology(topology);
deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
@@ -1225,7 +1228,6 @@
deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
// Unset the currently bound shader resource to avoid conflicts
- auto stateManager = mRenderer->getStateManager();
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
// Apply render target
@@ -1351,8 +1353,10 @@
ANGLE_TRY(mQuad2DVS.resolve(mRenderer));
ANGLE_TRY(mDepthPS.resolve(mRenderer));
+ auto stateManager = mRenderer->getStateManager();
+
// Apply shaders
- deviceContext->IASetInputLayout(mQuad2DIL.get());
+ stateManager->setInputLayout(&mQuad2DIL.getObj());
deviceContext->IASetPrimitiveTopology(topology);
deviceContext->VSSetShader(mQuad2DVS.get(), nullptr, 0);
@@ -1360,7 +1364,6 @@
deviceContext->GSSetShader(nullptr, nullptr, 0);
// Unset the currently bound shader resource to avoid conflicts
- auto stateManager = mRenderer->getStateManager();
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
// Apply render target
@@ -1984,6 +1987,7 @@
const auto &extents = depth->getExtents();
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ auto *stateManager = mRenderer->getStateManager();
ANGLE_TRY(initResolveDepthOnly(depth->getFormatSet(), extents));
@@ -1994,7 +1998,7 @@
ANGLE_TRY(mResolveDepthPS.resolve(mRenderer));
// Apply the necessary state changes to the D3D11 immediate device context.
- context->IASetInputLayout(nullptr);
+ stateManager->setInputLayout(nullptr);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->VSSetShader(mResolveDepthStencilVS.get(), nullptr, 0);
context->GSSetShader(nullptr, nullptr, 0);
@@ -2116,7 +2120,7 @@
ANGLE_TRY(initResolveDepthStencil(extents));
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
+ auto *stateManager = mRenderer->getStateManager();
ID3D11Resource *stencilResource = depthStencil->getTexture().get();
// Check if we need to re-create the stencil SRV.
@@ -2151,7 +2155,7 @@
ANGLE_TRY(mResolveDepthStencilVS.resolve(mRenderer));
// Apply the necessary state changes to the D3D11 immediate device context.
- context->IASetInputLayout(nullptr);
+ stateManager->setInputLayout(nullptr);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
context->VSSetShader(mResolveDepthStencilVS.get(), nullptr, 0);
context->GSSetShader(nullptr, nullptr, 0);
diff --git a/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/src/libANGLE/renderer/d3d/d3d11/Blit11.h
index f2fd7b5..ba783f2 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Blit11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Blit11.h
@@ -187,7 +187,7 @@
struct ShaderSupport
{
- ID3D11InputLayout *inputLayout;
+ const d3d11::InputLayout *inputLayout;
ID3D11VertexShader *vertexShader;
ID3D11GeometryShader *geometryShader;
WriteVertexFunction vertexWriteFunction;
diff --git a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
index cbfd645..d4093d9 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -98,7 +98,7 @@
gl::Error Clear11::ShaderManager::getShadersAndLayout(Renderer11 *renderer,
const INT clearType,
- ID3D11InputLayout **il,
+ const d3d11::InputLayout **il,
ID3D11VertexShader **vs,
ID3D11PixelShader **ps)
{
@@ -121,7 +121,7 @@
}
*vs = mVs9.get();
- *il = mIl9.get();
+ *il = &mIl9;
*ps = mPsFloat9.get();
return gl::NoError();
}
@@ -694,10 +694,12 @@
deviceContext->RSSetState(mScissorDisabledRasterizerState.get());
}
+ auto *stateManager = mRenderer->getStateManager();
+
// Get Shaders
- ID3D11VertexShader *vs = nullptr;
- ID3D11InputLayout *il = nullptr;
- ID3D11PixelShader *ps = nullptr;
+ ID3D11VertexShader *vs = nullptr;
+ const d3d11::InputLayout *il = nullptr;
+ ID3D11PixelShader *ps = nullptr;
ANGLE_TRY(mShaderManager.getShadersAndLayout(mRenderer, clearParams.colorType, &il, &vs, &ps));
@@ -710,7 +712,7 @@
// Bind IL & VB if needed
deviceContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
- deviceContext->IASetInputLayout(il);
+ stateManager->setInputLayout(il);
if (useVertexBuffer())
{
@@ -727,7 +729,7 @@
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Apply render targets
- mRenderer->getStateManager()->setOneTimeRenderTargets(&rtvs[0], numRtvs, dsv);
+ stateManager->setOneTimeRenderTargets(&rtvs[0], numRtvs, dsv);
// Draw the fullscreen quad
deviceContext->Draw(6, 0);
diff --git a/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/src/libANGLE/renderer/d3d/d3d11/Clear11.h
index 0b22522..78ad66f 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Clear11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Clear11.h
@@ -49,7 +49,7 @@
~ShaderManager();
gl::Error getShadersAndLayout(Renderer11 *renderer,
const INT clearType,
- ID3D11InputLayout **il,
+ const d3d11::InputLayout **il,
ID3D11VertexShader **vs,
ID3D11PixelShader **ps);
diff --git a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
index 7773806..468509b 100644
--- a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -172,10 +172,7 @@
}
InputLayoutCache::InputLayoutCache()
- : mCurrentIL(angle::DirtyPointer),
- mPointSpriteVertexBuffer(),
- mPointSpriteIndexBuffer(),
- mCacheSize(kDefaultCacheSize)
+ : mPointSpriteVertexBuffer(), mPointSpriteIndexBuffer(), mCacheSize(kDefaultCacheSize)
{
mCurrentBuffers.fill(nullptr);
mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
@@ -185,7 +182,6 @@
InputLayoutCache::~InputLayoutCache()
{
- clear();
}
void InputLayoutCache::initialize()
@@ -203,7 +199,6 @@
void InputLayoutCache::markDirty()
{
- mCurrentIL = angle::DirtyPointer;
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mCurrentBuffers[i] = nullptr;
@@ -494,13 +489,13 @@
layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType, binding.divisor);
}
- ID3D11InputLayout *inputLayout = nullptr;
+ const d3d11::InputLayout *inputLayout = nullptr;
if (layout.numAttributes > 0 || layout.flags != 0)
{
auto layoutMapIt = mLayoutMap.find(layout);
if (layoutMapIt != mLayoutMap.end())
{
- inputLayout = layoutMapIt->second.get();
+ inputLayout = &layoutMapIt->second;
}
else
{
@@ -525,18 +520,12 @@
}
}
- inputLayout = newInputLayout.get();
- mLayoutMap[layout] = std::move(newInputLayout);
+ auto result = mLayoutMap.insert(std::make_pair(layout, std::move(newInputLayout)));
+ inputLayout = &result.first->second;
}
}
- if (reinterpret_cast<uintptr_t>(inputLayout) != mCurrentIL)
- {
- ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
- deviceContext->IASetInputLayout(inputLayout);
- mCurrentIL = reinterpret_cast<uintptr_t>(inputLayout);
- }
-
+ renderer->getStateManager()->setInputLayout(inputLayout);
return gl::NoError();
}
diff --git a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
index b506cca..2a09ad2 100644
--- a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
+++ b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
@@ -105,7 +105,6 @@
std::map<PackedAttributeLayout, d3d11::InputLayout> mLayoutMap;
- uintptr_t mCurrentIL;
std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentBuffers;
std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides;
std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets;
diff --git a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
index 48d4bbd..163233e 100644
--- a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -192,7 +192,7 @@
deviceContext->GSSetShader(geometryShader, nullptr, 0);
deviceContext->PSSetShader(pixelShader, nullptr, 0);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV);
- deviceContext->IASetInputLayout(nullptr);
+ stateManager->setInputLayout(nullptr);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
diff --git a/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h b/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
index 2f684e8..6bed5ee 100644
--- a/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
@@ -16,6 +16,7 @@
#include "common/angleutils.h"
#include "common/debug.h"
#include "libANGLE/Error.h"
+#include "libANGLE/renderer/renderer_utils.h"
namespace rx
{
@@ -175,6 +176,11 @@
void reset() { mData.reset(new DataT()); }
+ ResourceSerial getSerial() const
+ {
+ return ResourceSerial(reinterpret_cast<uintptr_t>(mData->object));
+ }
+
protected:
friend class TextureHelper11;
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index 506ed87..fd6173c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -159,7 +159,8 @@
mViewportBounds(),
mRenderTargetIsDirty(false),
mDirtyCurrentValueAttribs(),
- mCurrentValueAttribs()
+ mCurrentValueAttribs(),
+ mCurrentInputLayout()
{
mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE;
@@ -819,6 +820,9 @@
// anymore. For example when a currently used SRV is used as an RTV, D3D silently
// remove it from its state.
invalidateBoundViews();
+
+ // All calls to IASetInputLayout go through the state manager, so it shouldn't be
+ // necessary to invalidate the state.
}
void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *rtv,
@@ -1137,4 +1141,22 @@
return mCurrentValueAttribs;
}
+void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ if (inputLayout == nullptr)
+ {
+ if (mCurrentInputLayout != 0)
+ {
+ deviceContext->IASetInputLayout(nullptr);
+ mCurrentInputLayout = 0;
+ }
+ }
+ else if (inputLayout->getSerial() != mCurrentInputLayout)
+ {
+ deviceContext->IASetInputLayout(inputLayout->get());
+ mCurrentInputLayout = inputLayout->getSerial();
+ }
+}
+
} // namespace rx
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
index f9dea00..76a3118 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -106,6 +106,8 @@
const std::vector<TranslatedAttribute> &getCurrentValueAttribs() const;
+ void setInputLayout(const d3d11::InputLayout *inputLayout);
+
private:
void setViewportBounds(const int width, const int height);
void unsetConflictingSRVs(gl::SamplerType shaderType,
@@ -207,6 +209,9 @@
// Current translations of "Current-Value" data - owned by Context, not VertexArray.
gl::AttributesMask mDirtyCurrentValueAttribs;
std::vector<TranslatedAttribute> mCurrentValueAttribs;
+
+ // Current applied input layout.
+ ResourceSerial mCurrentInputLayout;
};
} // namespace rx
diff --git a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
index 64f576e..857f739 100644
--- a/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -782,15 +782,15 @@
deviceContext->RSSetState(mPassThroughRS.get());
+ auto stateManager = mRenderer->getStateManager();
+
// Apply shaders
- deviceContext->IASetInputLayout(mPassThroughIL.get());
+ stateManager->setInputLayout(&mPassThroughIL);
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
deviceContext->VSSetShader(mPassThroughVS.get(), nullptr, 0);
deviceContext->PSSetShader(mPassThroughPS.get(), nullptr, 0);
deviceContext->GSSetShader(nullptr, nullptr, 0);
- auto stateManager = mRenderer->getStateManager();
-
// Apply render targets
stateManager->setOneTimeRenderTarget(mBackBufferRTView.get(), nullptr);
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
index 3c1275d..99853d6 100644
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
@@ -199,6 +199,8 @@
return mResource.get();
}
+ const Resource11<GetD3D11Type<ResourceT>> &getObj() const { return mResource; }
+
protected:
gl::Error resolveImpl(Renderer11 *renderer,
const GetDescType<ResourceT> &desc,
diff --git a/src/libANGLE/renderer/renderer_utils.h b/src/libANGLE/renderer/renderer_utils.h
index 803c8c2..a146d0f 100644
--- a/src/libANGLE/renderer/renderer_utils.h
+++ b/src/libANGLE/renderer/renderer_utils.h
@@ -12,6 +12,7 @@
#include <cstdint>
+#include <limits>
#include <map>
#include "libANGLE/angletypes.h"
@@ -30,6 +31,22 @@
namespace rx
{
+class ResourceSerial
+{
+ public:
+ constexpr ResourceSerial() : mValue(kDirty) {}
+ constexpr ResourceSerial(uintptr_t value) : mValue(value) {}
+ constexpr bool operator==(ResourceSerial other) const { return mValue == other.mValue; }
+ constexpr bool operator!=(ResourceSerial other) const { return mValue != other.mValue; }
+
+ void dirty() { mValue = kDirty; }
+
+ private:
+ constexpr static uintptr_t kDirty = std::numeric_limits<uintptr_t>::max();
+
+ uintptr_t mValue;
+};
+
using MipGenerationFunction = void (*)(size_t sourceWidth,
size_t sourceHeight,
size_t sourceDepth,