Commit 561ed3ae by Jamie Madill Committed by Commit Bot

D3D: Keep a single dirty bit for uniforms.

This simplifies uniform management in D3D11. It will also facilitate further optimizations. Improves performance in a uniforms stress test by ~13% on a test machine. (UniformsBenchmark.Run/d3d11_null_400_vec4) BUG=angleproject:1390 Change-Id: Iba2c15d420396aa8fb4e8c451cba2b4dde7b4b77 Reviewed-on: https://chromium-review.googlesource.com/623930Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 851edac7
......@@ -283,7 +283,6 @@ D3DUniform::D3DUniform(GLenum typeIn,
vsData(nullptr),
psData(nullptr),
csData(nullptr),
dirty(true),
vsRegisterIndex(GL_INVALID_INDEX),
psRegisterIndex(GL_INVALID_INDEX),
csRegisterIndex(GL_INVALID_INDEX),
......@@ -578,7 +577,8 @@ ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
mUsedPixelSamplerRange(0),
mUsedComputeSamplerRange(0),
mDirtySamplerMapping(true),
mSerial(issueSerial())
mSerial(issueSerial()),
mUniformsDirty(true)
{
mDynamicHLSL = new DynamicHLSL(renderer);
}
......@@ -712,9 +712,6 @@ void ProgramD3D::updateSamplerMapping()
// Retrieve sampler uniform values
for (const D3DUniform *d3dUniform : mD3DUniforms)
{
if (!d3dUniform->dirty)
continue;
if (!d3dUniform->isSampler())
continue;
......@@ -1786,17 +1783,11 @@ void ProgramD3D::initializeUniformStorage()
}
}
gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
gl::Error ProgramD3D::applyUniforms()
{
ASSERT(!mDirtySamplerMapping);
ANGLE_TRY(mRenderer->applyUniforms(*this, drawMode, mD3DUniforms));
for (D3DUniform *d3dUniform : mD3DUniforms)
{
d3dUniform->dirty = false;
}
ANGLE_TRY(mRenderer->applyUniforms(*this, mD3DUniforms));
mUniformsDirty = false;
return gl::NoError();
}
......@@ -1804,12 +1795,7 @@ gl::Error ProgramD3D::applyComputeUniforms()
{
ASSERT(!mDirtySamplerMapping);
ANGLE_TRY(mRenderer->applyComputeUniforms(*this, mD3DUniforms));
for (D3DUniform *d3dUniform : mD3DUniforms)
{
d3dUniform->dirty = false;
}
mUniformsDirty = false;
return gl::NoError();
}
......@@ -1874,10 +1860,7 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::ContextState &data)
void ProgramD3D::dirtyAllUniforms()
{
for (D3DUniform *d3dUniform : mD3DUniforms)
{
d3dUniform->dirty = true;
}
mUniformsDirty = true;
}
void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
......@@ -2173,18 +2156,15 @@ void ProgramD3D::defineUniform(GLenum shaderType,
if (shaderType == GL_FRAGMENT_SHADER)
{
d3dUniform->psRegisterIndex = reg;
d3dUniform->dirty = true;
}
else if (shaderType == GL_VERTEX_SHADER)
{
d3dUniform->vsRegisterIndex = reg;
d3dUniform->dirty = true;
}
else
{
ASSERT(shaderType == GL_COMPUTE_SHADER);
d3dUniform->csRegisterIndex = reg;
d3dUniform->dirty = true;
}
// Arrays are treated as aggregate types
......@@ -2220,7 +2200,6 @@ void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
T *dest = target + (i * 4);
const T *source = v + (i * components);
memcpy(dest, source, components * sizeof(T));
targetUniform->dirty = true;
}
}
else if (targetUniform->type == targetBoolType)
......@@ -2236,7 +2215,6 @@ void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
{
dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
}
targetUniform->dirty = true;
}
}
else
......@@ -2252,12 +2230,13 @@ void ProgramD3D::setUniformInternal(GLint location,
const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
mUniformsDirty = true;
if (!targetUniform->mSamplerData.empty())
{
ASSERT(targetUniformType == GL_INT);
memcpy(&targetUniform->mSamplerData[locationInfo.element], v, count * sizeof(T));
mDirtySamplerMapping = true;
targetUniform->dirty = true;
return;
}
......@@ -2300,17 +2279,17 @@ void ProgramD3D::setUniformMatrixfvImpl(GLint location,
// Internally store matrices as transposed versions to accomodate HLSL matrix indexing
if (transpose == GL_FALSE)
{
targetUniform->dirty =
TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || targetUniform->dirty;
TransposeExpandMatrix<GLfloat, cols, rows>(target, value);
}
else
{
targetUniform->dirty =
ExpandMatrix<GLfloat, cols, rows>(target, value) || targetUniform->dirty;
ExpandMatrix<GLfloat, cols, rows>(target, value);
}
target += targetMatrixStride;
value += cols * rows;
}
mUniformsDirty = true;
}
template <int cols, int rows>
......@@ -2479,6 +2458,8 @@ void ProgramD3D::reset()
mStreamOutVaryings.clear();
mGeometryShaderPreamble.clear();
mUniformsDirty = true;
}
unsigned int ProgramD3D::getSerial() const
......
......@@ -61,9 +61,6 @@ struct D3DUniform : private angle::NonCopyable
uint8_t *psData;
uint8_t *csData;
// Has the data been updated since the last sync?
bool dirty;
// Register information.
unsigned int vsRegisterIndex;
unsigned int psRegisterIndex;
......@@ -205,7 +202,7 @@ class ProgramD3D : public ProgramImpl
const GLfloat *coeffs) override;
void initializeUniformStorage();
gl::Error applyUniforms(GLenum drawMode);
gl::Error applyUniforms();
gl::Error applyComputeUniforms();
gl::Error applyUniformBuffers(const gl::ContextState &data);
void dirtyAllUniforms();
......@@ -286,6 +283,8 @@ class ProgramD3D : public ProgramImpl
bool hasGeometryExecutableForPrimitiveType(GLenum drawMode);
bool hasPixelExecutableForCachedOutputLayout();
bool areUniformsDirty() const { return mUniformsDirty; }
private:
// These forward-declared tasks are used for multi-thread shader compiles.
class GetExecutableTask;
......@@ -478,6 +477,8 @@ class ProgramD3D : public ProgramImpl
std::vector<D3DUniform *> mD3DUniforms;
std::vector<D3DUniformBlock> mD3DUniformBlocks;
bool mUniformsDirty;
std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
std::map<std::string, size_t> mBlockDataSizes;
......
......@@ -155,7 +155,6 @@ class RendererD3D : public BufferFactoryD3D
const std::vector<GLint> &fragmentUniformBuffers) = 0;
virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) = 0;
virtual unsigned int getReservedVertexUniformBuffers() const = 0;
......
......@@ -1548,8 +1548,17 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
switch (mode)
{
case GL_POINTS:
primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
minCount = 1;
// If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
// must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
{
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
else
{
primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
}
minCount = 1;
break;
case GL_LINES:
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
......@@ -1581,15 +1590,6 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi
return false;
}
// If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader,
// GL_POINTS mode is expected to render pointsprites.
// Instanced PointSprite emulation requires that the topology to be
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
{
primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
mStateManager.setPrimitiveTopology(primitiveTopology);
return count >= minCount;
......@@ -2135,30 +2135,8 @@ gl::Error Renderer11::drawTriangleFan(const gl::ContextState &data,
// TODO(jmadill): Move to StateManager11.
gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray)
{
unsigned int totalRegisterCountVS = 0;
unsigned int totalRegisterCountPS = 0;
bool vertexUniformsDirty = false;
bool pixelUniformsDirty = false;
for (const D3DUniform *uniform : uniformArray)
{
if (uniform->isReferencedByVertexShader() && !uniform->isSampler())
{
totalRegisterCountVS += uniform->registerCount;
vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
}
if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
{
totalRegisterCountPS += uniform->registerCount;
pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
}
}
UniformStorage11 *vertexUniformStorage =
GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
UniformStorage11 *fragmentUniformStorage =
......@@ -2171,7 +2149,9 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
const d3d11::Buffer *pixelConstantBuffer = nullptr;
ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(this, &pixelConstantBuffer));
if (totalRegisterCountVS > 0 && vertexUniformsDirty)
bool uniformsDirty = programD3D.areUniformsDirty();
if (vertexUniformStorage->size() > 0 && uniformsDirty)
{
D3D11_MAPPED_SUBRESOURCE map = {0};
HRESULT result =
......@@ -2181,7 +2161,7 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
mDeviceContext->Unmap(vertexConstantBuffer->get(), 0);
}
if (totalRegisterCountPS > 0 && pixelUniformsDirty)
if (fragmentUniformStorage->size() > 0 && uniformsDirty)
{
D3D11_MAPPED_SUBRESOURCE map = {0};
HRESULT result =
......@@ -2208,6 +2188,11 @@ gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
mCurrentPixelConstantBuffer = reinterpret_cast<uintptr_t>(appliedPixelConstants);
}
return gl::NoError();
}
gl::Error Renderer11::applyDriverUniforms(const ProgramD3D &programD3D, GLenum drawMode)
{
auto *samplerMetadataVS = mStateManager.getVertexSamplerMetadata();
auto *samplerMetadataPS = mStateManager.getPixelSamplerMetadata();
......@@ -4306,21 +4291,6 @@ gl::Error Renderer11::dispatchCompute(const gl::Context *context,
gl::Error Renderer11::applyComputeUniforms(const ProgramD3D &programD3D,
const std::vector<D3DUniform *> &uniformArray)
{
unsigned int totalRegisterCountCS = 0;
bool computeUniformsDirty = false;
for (const D3DUniform *uniform : uniformArray)
{
ASSERT(uniform->isReferencedByComputeShader());
// TODO(Xinghua): add isImage() and isAtomicCounter().
if (uniform->isSampler())
{
totalRegisterCountCS += uniform->registerCount;
computeUniformsDirty = (computeUniformsDirty || uniform->dirty);
}
}
UniformStorage11 *computeUniformStorage =
GetAs<UniformStorage11>(&programD3D.getComputeUniformStorage());
ASSERT(computeUniformStorage);
......@@ -4330,7 +4300,7 @@ gl::Error Renderer11::applyComputeUniforms(const ProgramD3D &programD3D,
ID3D11Buffer *computeConstantBuffer = computeConstantBufferObj->get();
if (totalRegisterCountCS > 0 && computeUniformsDirty)
if (computeUniformStorage->size() > 0)
{
D3D11_MAPPED_SUBRESOURCE map = {0};
HRESULT result =
......
......@@ -142,9 +142,11 @@ class Renderer11 : public RendererD3D
const std::vector<GLint> &fragmentUniformBuffers) override;
bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
gl::Error applyUniforms(const ProgramD3D &programD3D,
GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) override;
gl::Error applyDriverUniforms(const ProgramD3D &programD3D, GLenum drawMode);
gl::Error applyTransformFeedbackBuffers(const gl::ContextState &data);
// lost device
......
......@@ -1621,7 +1621,8 @@ gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMod
// This must happen after viewport sync, because the viewport affects builtin uniforms.
// TODO(jmadill): Use dirty bits.
auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
ANGLE_TRY(programD3D->applyUniforms(drawMode));
ANGLE_TRY(programD3D->applyUniforms());
ANGLE_TRY(mRenderer->applyDriverUniforms(*programD3D, drawMode));
// Check that we haven't set any dirty bits in the flushing of the dirty bits loop.
ASSERT(mInternalDirtyBits.none());
......
......@@ -1842,16 +1842,22 @@ gl::Error Renderer9::applyShaders(const gl::Context *context, GLenum drawMode)
mAppliedProgramSerial = programSerial;
}
return programD3D->applyUniforms(drawMode);
ANGLE_TRY(programD3D->applyUniforms());
// Driver uniforms
mStateManager.setShaderConstants();
return gl::NoError();
}
gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
GLenum /*drawMode*/,
const std::vector<D3DUniform *> &uniformArray)
{
for (const D3DUniform *targetUniform : uniformArray)
{
if (!targetUniform->dirty)
// Built-in uniforms must be skipped.
if (!targetUniform->isReferencedByFragmentShader() &&
!targetUniform->isReferencedByVertexShader())
continue;
// Built-in uniforms must be skipped.
......@@ -1894,9 +1900,6 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
}
}
// Driver uniforms
mStateManager.setShaderConstants();
return gl::NoError();
}
......
......@@ -148,7 +148,6 @@ class Renderer9 : public RendererD3D
const gl::FramebufferAttachment *colorAttachment,
const gl::FramebufferAttachment *depthStencilAttachment);
gl::Error applyUniforms(const ProgramD3D &programD3D,
GLenum drawMode,
const std::vector<D3DUniform *> &uniformArray) override;
bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
gl::Error applyVertexBuffer(const gl::State &state,
......
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