Commit 2cd45629 by Jamie Madill Committed by Commit Bot

D3D11: Consolidate Vertex Buffer application.

With this change, IASetVertexBuffers is only called from a single code site in StateManager11. All other classes call through to here. This will make adopting the dirty bits for InputLayouts and VBs much simpler. BUG=angleproject:2052 Change-Id: I6e7b6146deb7f80f5f0e75dd0aff18eb4cc2bfc2 Reviewed-on: https://chromium-review.googlesource.com/524232Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 863b6236
......@@ -1038,7 +1038,6 @@ gl::Error Blit11::swizzleTexture(const d3d11::SharedSRV &source,
ANGLE_TRY(getShaderSupport(*shader, &support));
UINT stride = 0;
UINT startIdx = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
......@@ -1067,8 +1066,7 @@ gl::Error Blit11::swizzleTexture(const d3d11::SharedSRV &source,
auto stateManager = mRenderer->getStateManager();
// Apply vertex buffer
ID3D11Buffer *vertexBuffer = mVertexBuffer.get();
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &startIdx);
stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply constant buffer
ID3D11Buffer *constantBuffer = mSwizzleCB.get();
......@@ -1113,13 +1111,8 @@ gl::Error Blit11::swizzleTexture(const d3d11::SharedSRV &source,
// Draw the quad
deviceContext->Draw(drawCount, 0);
// Unbind textures and render targets and vertex buffer
// Unbind shader resources and dirty state.
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
UINT zero = 0;
ID3D11Buffer *const nullBuffer = nullptr;
deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
mRenderer->markAllStateDirty();
return gl::NoError();
......@@ -1176,7 +1169,6 @@ gl::Error Blit11::copyTexture(const d3d11::SharedSRV &source,
}
UINT stride = 0;
UINT startIdx = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
......@@ -1188,8 +1180,7 @@ gl::Error Blit11::copyTexture(const d3d11::SharedSRV &source,
auto stateManager = mRenderer->getStateManager();
// Apply vertex buffer
ID3D11Buffer *vertexBuffer = mVertexBuffer.get();
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &startIdx);
stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply state
if (maskOffAlpha)
......@@ -1267,13 +1258,9 @@ gl::Error Blit11::copyTexture(const d3d11::SharedSRV &source,
// Draw the quad
deviceContext->Draw(drawCount, 0);
// Unbind textures and render targets and vertex buffer
// Unbind shader resource and invalidate state.
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
UINT zero = 0;
ID3D11Buffer *const nullBuffer = nullptr;
deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
mRenderer->markAllStateDirty();
return gl::NoError();
......@@ -1317,7 +1304,6 @@ gl::Error Blit11::copyDepth(const d3d11::SharedSRV &source,
}
UINT stride = 0;
UINT startIdx = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
......@@ -1326,9 +1312,10 @@ gl::Error Blit11::copyDepth(const d3d11::SharedSRV &source,
deviceContext->Unmap(mVertexBuffer.get(), 0);
auto stateManager = mRenderer->getStateManager();
// Apply vertex buffer
ID3D11Buffer *vertexBuffer = mVertexBuffer.get();
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &startIdx);
stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply state
deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
......@@ -1354,8 +1341,6 @@ gl::Error Blit11::copyDepth(const d3d11::SharedSRV &source,
ANGLE_TRY(mQuad2DVS.resolve(mRenderer));
ANGLE_TRY(mDepthPS.resolve(mRenderer));
auto stateManager = mRenderer->getStateManager();
// Apply shaders
stateManager->setInputLayout(&mQuad2DIL.getObj());
deviceContext->IASetPrimitiveTopology(topology);
......@@ -1390,13 +1375,9 @@ gl::Error Blit11::copyDepth(const d3d11::SharedSRV &source,
// Draw the quad
deviceContext->Draw(drawCount, 0);
// Unbind textures and render targets and vertex buffer
// Unbind shader resources and invalidate all state.
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
UINT zero = 0;
ID3D11Buffer *const nullBuffer = nullptr;
deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
mRenderer->markAllStateDirty();
return gl::NoError();
......
......@@ -717,13 +717,11 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams,
if (useVertexBuffer())
{
ANGLE_TRY(ensureVertexBufferCreated());
const UINT offset = 0;
ID3D11Buffer *vertexBuffer = mVertexBuffer.get();
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &g_VertexSize, &offset);
stateManager->setSingleVertexBuffer(&mVertexBuffer, g_VertexSize, 0);
}
else
{
deviceContext->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr);
stateManager->setSingleVertexBuffer(nullptr, 0, 0);
}
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
......
......@@ -174,9 +174,6 @@ bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLay
InputLayoutCache::InputLayoutCache()
: mPointSpriteVertexBuffer(), mPointSpriteIndexBuffer(), mCacheSize(kDefaultCacheSize)
{
mCurrentBuffers.fill(nullptr);
mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
}
......@@ -184,27 +181,11 @@ InputLayoutCache::~InputLayoutCache()
{
}
void InputLayoutCache::initialize()
{
clear();
}
void InputLayoutCache::clear()
{
mLayoutMap.clear();
mPointSpriteVertexBuffer.reset();
mPointSpriteIndexBuffer.reset();
markDirty();
}
void InputLayoutCache::markDirty()
{
for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mCurrentBuffers[i] = nullptr;
mCurrentVertexStrides[i] = static_cast<UINT>(-1);
mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
}
}
gl::Error InputLayoutCache::applyVertexBuffers(
......@@ -218,6 +199,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(
GLsizei numIndicesPerInstance)
{
ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
auto *stateManager = renderer->getStateManager();
gl::Program *program = state.getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
......@@ -249,10 +231,6 @@ gl::Error InputLayoutCache::applyVertexBuffers(
ANGLE_TRY(
updateInputLayout(renderer, state, mode, sortedSemanticIndices, numIndicesPerInstance));
bool dirtyBuffers = false;
size_t minDiff = gl::MAX_VERTEX_ATTRIBS;
size_t maxDiff = 0;
// Note that if we use instance emulation, we reserve the first buffer slot.
size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);
......@@ -307,18 +285,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(
size_t bufferIndex = reservedBuffers + attribIndex;
if (buffer != mCurrentBuffers[bufferIndex] ||
vertexStride != mCurrentVertexStrides[bufferIndex] ||
vertexOffset != mCurrentVertexOffsets[bufferIndex])
{
dirtyBuffers = true;
minDiff = std::min(minDiff, bufferIndex);
maxDiff = std::max(maxDiff, bufferIndex);
mCurrentBuffers[bufferIndex] = buffer;
mCurrentVertexStrides[bufferIndex] = vertexStride;
mCurrentVertexOffsets[bufferIndex] = vertexOffset;
}
stateManager->queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset);
}
// Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs
......@@ -358,16 +325,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(
&mPointSpriteVertexBuffer));
}
mCurrentBuffers[0] = mPointSpriteVertexBuffer.get();
// Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid
// indexing into the vertex buffer.
mCurrentVertexStrides[0] = instancedPointSpritesActive ? pointSpriteVertexStride : 0;
mCurrentVertexOffsets[0] = 0;
// Update maxDiff to include the additional point sprite vertex buffer
// to ensure that IASetVertexBuffers uses the correct buffer count.
minDiff = 0;
maxDiff = std::max(maxDiff, static_cast<size_t>(0));
UINT stride = instancedPointSpritesActive ? pointSpriteVertexStride : 0;
stateManager->queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0);
if (!mPointSpriteIndexBuffer.valid())
{
......@@ -400,15 +361,7 @@ gl::Error InputLayoutCache::applyVertexBuffers(
}
}
if (dirtyBuffers)
{
ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS);
deviceContext->IASetVertexBuffers(
static_cast<UINT>(minDiff), static_cast<UINT>(maxDiff - minDiff + 1),
&mCurrentBuffers[minDiff], &mCurrentVertexStrides[minDiff],
&mCurrentVertexOffsets[minDiff]);
}
stateManager->applyVertexBufferChanges();
return gl::NoError();
}
......@@ -416,6 +369,8 @@ gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(Renderer
GLint startVertex,
GLsizei emulatedInstanceId)
{
auto *stateManager = renderer->getStateManager();
size_t reservedBuffers = GetReservedBufferCount(true);
for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
{
......@@ -426,15 +381,12 @@ gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(Renderer
{
unsigned int offset = 0;
ANGLE_TRY_RESULT(attrib.computeOffset(startVertex), offset);
mCurrentVertexOffsets[bufferIndex] =
offset + (attrib.stride * (emulatedInstanceId / attrib.divisor));
offset += (attrib.stride * (emulatedInstanceId / attrib.divisor));
stateManager->queueVertexOffsetChange(bufferIndex, offset);
}
}
ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
deviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers.data(),
mCurrentVertexStrides.data(), mCurrentVertexOffsets.data());
stateManager->applyVertexBufferChanges();
return gl::NoError();
}
......
......@@ -41,11 +41,9 @@ class InputLayoutCache : angle::NonCopyable
{
public:
InputLayoutCache();
virtual ~InputLayoutCache();
~InputLayoutCache();
void initialize();
void clear();
void markDirty();
gl::Error applyVertexBuffers(Renderer11 *renderer,
const gl::State &state,
......@@ -105,9 +103,6 @@ class InputLayoutCache : angle::NonCopyable
std::map<PackedAttributeLayout, d3d11::InputLayout> mLayoutMap;
std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentBuffers;
std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides;
std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets;
std::vector<const TranslatedAttribute *> mCurrentAttributes;
d3d11::Buffer mPointSpriteVertexBuffer;
......
......@@ -180,9 +180,6 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
ID3D11Buffer *nullBuffer = nullptr;
UINT zero = 0;
// Are we doing a 2D or 3D copy?
ID3D11GeometryShader *geometryShader =
((destSize.depth > 1) ? mBufferToTextureGS.get() : nullptr);
......@@ -195,7 +192,7 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac
stateManager->setInputLayout(nullptr);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
stateManager->setSingleVertexBuffer(nullptr, 0, 0);
deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
deviceContext->OMSetDepthStencilState(mCopyDepthStencilState.get(), 0xFFFFFFFF);
deviceContext->RSSetState(mCopyRasterizerState.get());
......@@ -224,8 +221,10 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac
UINT numPixels = (destArea.width * destArea.height * destArea.depth);
deviceContext->Draw(numPixels, 0);
// Unbind textures and render targets and vertex buffer
// Unbind shader resources and invalidate state.
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
ID3D11Buffer *nullBuffer = nullptr;
deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
mRenderer->markAllStateDirty();
......
......@@ -789,7 +789,6 @@ void Renderer11::initializeDevice()
populateRenderer11DeviceCaps();
mStateCache.clear();
mInputLayoutCache.initialize();
ASSERT(!mVertexDataManager && !mIndexDataManager);
mVertexDataManager = new VertexDataManager(this);
......@@ -2813,8 +2812,6 @@ void Renderer11::markAllStateDirty()
memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11));
memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11));
mInputLayoutCache.markDirty();
for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++)
{
mCurrentConstantBufferVS[i] = static_cast<unsigned int>(-1);
......
......@@ -160,7 +160,8 @@ StateManager11::StateManager11(Renderer11 *renderer)
mRenderTargetIsDirty(false),
mDirtyCurrentValueAttribs(),
mCurrentValueAttribs(),
mCurrentInputLayout()
mCurrentInputLayout(),
mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0)
{
mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE;
......@@ -204,6 +205,10 @@ StateManager11::StateManager11(Renderer11 *renderer)
// Initially all current value attributes must be updated on first use.
mDirtyCurrentValueAttribs.flip();
mCurrentVertexBuffers.fill(nullptr);
mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
}
StateManager11::~StateManager11()
......@@ -491,6 +496,8 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
break;
}
}
// TODO(jmadill): Input layout and vertex buffer state.
}
gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
......@@ -823,6 +830,16 @@ void StateManager11::invalidateEverything()
// All calls to IASetInputLayout go through the state manager, so it shouldn't be
// necessary to invalidate the state.
// Invalidate the vertex buffer state.
invalidateVertexBuffer();
}
void StateManager11::invalidateVertexBuffer()
{
unsigned int limit = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes,
gl::MAX_VERTEX_ATTRIBS);
mDirtyVertexBufferRange = gl::RangeUI(0, limit);
}
void StateManager11::setOneTimeRenderTarget(ID3D11RenderTargetView *rtv,
......@@ -1157,4 +1174,63 @@ void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
}
}
bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
ID3D11Buffer *buffer,
UINT stride,
UINT offset)
{
if (buffer != mCurrentVertexBuffers[bufferIndex] ||
stride != mCurrentVertexStrides[bufferIndex] ||
offset != mCurrentVertexOffsets[bufferIndex])
{
mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
mCurrentVertexBuffers[bufferIndex] = buffer;
mCurrentVertexStrides[bufferIndex] = stride;
mCurrentVertexOffsets[bufferIndex] = offset;
return true;
}
return false;
}
bool StateManager11::queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly)
{
if (offsetOnly != mCurrentVertexOffsets[bufferIndex])
{
mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
mCurrentVertexOffsets[bufferIndex] = offsetOnly;
return true;
}
return false;
}
void StateManager11::applyVertexBufferChanges()
{
if (mDirtyVertexBufferRange.empty())
{
return;
}
ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);
UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
&mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
&mCurrentVertexOffsets[start]);
mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
}
void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
{
ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
if (queueVertexBufferChange(0, native, stride, offset))
{
applyVertexBufferChanges();
}
}
} // namespace rx
......@@ -90,6 +90,7 @@ class StateManager11 final : angle::NonCopyable
void invalidateRenderTarget();
void invalidateBoundViews();
void invalidateVertexBuffer();
void invalidateEverything();
void setOneTimeRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
......@@ -108,6 +109,16 @@ class StateManager11 final : angle::NonCopyable
void setInputLayout(const d3d11::InputLayout *inputLayout);
// TODO(jmadill): Migrate to d3d11::Buffer.
bool queueVertexBufferChange(size_t bufferIndex,
ID3D11Buffer *buffer,
UINT stride,
UINT offset);
bool queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly);
void applyVertexBufferChanges();
void setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset);
private:
void setViewportBounds(const int width, const int height);
void unsetConflictingSRVs(gl::SamplerType shaderType,
......@@ -212,6 +223,13 @@ class StateManager11 final : angle::NonCopyable
// Current applied input layout.
ResourceSerial mCurrentInputLayout;
// Current applied vertex states.
// TODO(jmadill): Figure out how to use ResourceSerial here.
std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexBuffers;
std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides;
std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets;
gl::RangeUI mDirtyVertexBufferRange;
};
} // namespace rx
......
......@@ -769,10 +769,10 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
deviceContext->Unmap(mQuadVB.get(), 0);
static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
static UINT startIdx = 0;
ID3D11Buffer *vertexBuffer = mQuadVB.get();
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &startIdx);
auto stateManager = mRenderer->getStateManager();
constexpr UINT stride = sizeof(d3d11::PositionTexCoordVertex);
stateManager->setSingleVertexBuffer(&mQuadVB, stride, 0);
// Apply state
deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
......@@ -782,8 +782,6 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
deviceContext->RSSetState(mPassThroughRS.get());
auto stateManager = mRenderer->getStateManager();
// Apply shaders
stateManager->setInputLayout(&mPassThroughIL);
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
......
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