Commit 0e7f1736 by Jamie Madill Committed by Commit Bot

D3D: Only scan cached shader executable lists once.

Any time we would query ProgramD3D for a particular vertex or pixel shader, we would iterate over all the cached shaders of the program looking for the matching input or output layout signature. This change makes it so we only compute the index of the matching shader once, and subsequent calls will re-use the shader index. This should speed up the draw call benchmarks. Also include a fix to the Serial class that initializes a Serial value to an invalid sentinel value. This ensures that comparing any other Serial (including another invalid serial) to the invalid serial will return not-equals. BUG=angleproject:1155 Change-Id: I7d913bf08d0bedf6155eae0661b2a5fa94565cc9 Reviewed-on: https://chromium-review.googlesource.com/648730 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent eb335950
...@@ -75,31 +75,6 @@ void GetDefaultOutputLayoutFromShader( ...@@ -75,31 +75,6 @@ void GetDefaultOutputLayoutFromShader(
} }
} }
void GetPixelOutputLayoutFromFramebuffer(const gl::Context *context,
const gl::Framebuffer *framebuffer,
std::vector<GLenum> *signature)
{
signature->clear();
FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
if (colorbuffer)
{
signature->push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
: colorbuffer->getBinding());
}
else
{
signature->push_back(GL_NONE);
}
}
}
bool IsRowMajorLayout(const sh::InterfaceBlockField &var) bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
{ {
return var.isRowMajorLayout; return var.isRowMajorLayout;
...@@ -1221,13 +1196,10 @@ void ProgramD3D::setSeparable(bool /* separable */) ...@@ -1221,13 +1196,10 @@ void ProgramD3D::setSeparable(bool /* separable */)
gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable, gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog) gl::InfoLog *infoLog)
{ {
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) if (mCachedPixelExecutableIndex.valid())
{ {
if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache)) *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
{ return gl::NoError();
*outExecutable = mPixelExecutables[executableIndex]->shaderExecutable();
return gl::NoError();
}
} }
std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature( std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
...@@ -1248,6 +1220,7 @@ gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3 ...@@ -1248,6 +1220,7 @@ gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3
{ {
mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>( mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable))); new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
} }
else if (!infoLog) else if (!infoLog)
{ {
...@@ -1262,13 +1235,11 @@ gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3 ...@@ -1262,13 +1235,11 @@ gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3
gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable, gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
gl::InfoLog *infoLog) gl::InfoLog *infoLog)
{ {
for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) if (mCachedVertexExecutableIndex.valid())
{ {
if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature)) *outExectuable =
{ mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
*outExectuable = mVertexExecutables[executableIndex]->shaderExecutable(); return gl::NoError();
return gl::NoError();
}
} }
// Generate new dynamic layout with attribute conversions // Generate new dynamic layout with attribute conversions
...@@ -1290,6 +1261,7 @@ gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3 ...@@ -1290,6 +1261,7 @@ gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3
{ {
mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>( mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable))); new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
} }
else if (!infoLog) else if (!infoLog)
{ {
...@@ -1407,6 +1379,7 @@ void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context) ...@@ -1407,6 +1379,7 @@ void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
{ {
GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout); GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout);
VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature); VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
updateCachedVertexExecutableIndex();
} }
class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
...@@ -1426,6 +1399,7 @@ class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask ...@@ -1426,6 +1399,7 @@ class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
void ProgramD3D::updateCachedOutputLayoutFromShader() void ProgramD3D::updateCachedOutputLayoutFromShader()
{ {
GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache); GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
updateCachedPixelExecutableIndex();
} }
class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
...@@ -2465,6 +2439,9 @@ void ProgramD3D::reset() ...@@ -2465,6 +2439,9 @@ void ProgramD3D::reset()
mGeometryShaderPreamble.clear(); mGeometryShaderPreamble.clear();
mUniformsDirty = true; mUniformsDirty = true;
mCachedPixelExecutableIndex.reset();
mCachedVertexExecutableIndex.reset();
} }
unsigned int ProgramD3D::getSerial() const unsigned int ProgramD3D::getSerial() const
...@@ -2506,6 +2483,7 @@ void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::Stat ...@@ -2506,6 +2483,7 @@ void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::Stat
mCurrentVertexArrayStateSerial = associatedSerial; mCurrentVertexArrayStateSerial = associatedSerial;
mCachedInputLayout.clear(); mCachedInputLayout.clear();
const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
for (size_t locationIndex : mState.getActiveAttribLocationsMask()) for (size_t locationIndex : mState.getActiveAttribLocationsMask())
...@@ -2525,12 +2503,35 @@ void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::Stat ...@@ -2525,12 +2503,35 @@ void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::Stat
} }
VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature); VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
updateCachedVertexExecutableIndex();
} }
void ProgramD3D::updateCachedOutputLayout(const gl::Context *context, void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
const gl::Framebuffer *framebuffer) const gl::Framebuffer *framebuffer)
{ {
GetPixelOutputLayoutFromFramebuffer(context, framebuffer, &mPixelShaderOutputLayoutCache); mPixelShaderOutputLayoutCache.clear();
FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
if (colorbuffer)
{
auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
: colorbuffer->getBinding();
mPixelShaderOutputLayoutCache.push_back(binding);
}
else
{
mPixelShaderOutputLayoutCache.push_back(GL_NONE);
}
}
updateCachedPixelExecutableIndex();
} }
void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking, void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
...@@ -2653,17 +2654,7 @@ void ProgramD3D::setPathFragmentInputGen(const std::string &inputName, ...@@ -2653,17 +2654,7 @@ void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
bool ProgramD3D::hasVertexExecutableForCachedInputLayout() bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
{ {
VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature); return mCachedVertexExecutableIndex.valid();
for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
{
if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
{
return true;
}
}
return false;
} }
bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode) bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
...@@ -2680,15 +2671,7 @@ bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode) ...@@ -2680,15 +2671,7 @@ bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
bool ProgramD3D::hasPixelExecutableForCachedOutputLayout() bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
{ {
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) return mCachedPixelExecutableIndex.valid();
{
if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
{
return true;
}
}
return false;
} }
template <typename DestT> template <typename DestT>
...@@ -2726,4 +2709,30 @@ void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuin ...@@ -2726,4 +2709,30 @@ void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuin
getUniformInternal(location, params); getUniformInternal(location, params);
} }
void ProgramD3D::updateCachedVertexExecutableIndex()
{
mCachedVertexExecutableIndex.reset();
for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
{
if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
{
mCachedVertexExecutableIndex = executableIndex;
break;
}
}
}
void ProgramD3D::updateCachedPixelExecutableIndex()
{
mCachedPixelExecutableIndex.reset();
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
{
if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
{
mCachedPixelExecutableIndex = executableIndex;
break;
}
}
}
} // namespace rx } // namespace rx
...@@ -434,6 +434,8 @@ class ProgramD3D : public ProgramImpl ...@@ -434,6 +434,8 @@ class ProgramD3D : public ProgramImpl
void updateCachedInputLayoutFromShader(const gl::Context *context); void updateCachedInputLayoutFromShader(const gl::Context *context);
void updateCachedOutputLayoutFromShader(); void updateCachedOutputLayoutFromShader();
void updateCachedVertexExecutableIndex();
void updateCachedPixelExecutableIndex();
RendererD3D *mRenderer; RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL; DynamicHLSL *mDynamicHLSL;
...@@ -475,6 +477,7 @@ class ProgramD3D : public ProgramImpl ...@@ -475,6 +477,7 @@ class ProgramD3D : public ProgramImpl
// Cache for pixel shader output layout to save reallocations. // Cache for pixel shader output layout to save reallocations.
std::vector<GLenum> mPixelShaderOutputLayoutCache; std::vector<GLenum> mPixelShaderOutputLayoutCache;
Optional<size_t> mCachedPixelExecutableIndex;
AttribIndexArray mAttribLocationToD3DSemantic; AttribIndexArray mAttribLocationToD3DSemantic;
...@@ -484,6 +487,7 @@ class ProgramD3D : public ProgramImpl ...@@ -484,6 +487,7 @@ class ProgramD3D : public ProgramImpl
std::vector<GLint> mFragmentUBOCache; std::vector<GLint> mFragmentUBOCache;
VertexExecutable::Signature mCachedVertexSignature; VertexExecutable::Signature mCachedVertexSignature;
gl::InputLayout mCachedInputLayout; gl::InputLayout mCachedInputLayout;
Optional<size_t> mCachedVertexExecutableIndex;
std::vector<D3DVarying> mStreamOutVaryings; std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms; std::vector<D3DUniform *> mD3DUniforms;
......
...@@ -58,12 +58,18 @@ class SerialFactory; ...@@ -58,12 +58,18 @@ class SerialFactory;
class Serial final class Serial final
{ {
public: public:
constexpr Serial() : mValue(0) {} constexpr Serial() : mValue(kInvalid) {}
constexpr Serial(const Serial &other) = default; constexpr Serial(const Serial &other) = default;
Serial &operator=(const Serial &other) = default; Serial &operator=(const Serial &other) = default;
constexpr bool operator==(const Serial &other) const { return mValue == other.mValue; } constexpr bool operator==(const Serial &other) const
constexpr bool operator!=(const Serial &other) const { return mValue != other.mValue; } {
return mValue != kInvalid && mValue == other.mValue;
}
constexpr bool operator!=(const Serial &other) const
{
return mValue == kInvalid || mValue != other.mValue;
}
constexpr bool operator>(const Serial &other) const { return mValue > other.mValue; } constexpr bool operator>(const Serial &other) const { return mValue > other.mValue; }
constexpr bool operator>=(const Serial &other) const { return mValue >= other.mValue; } constexpr bool operator>=(const Serial &other) const { return mValue >= other.mValue; }
constexpr bool operator<(const Serial &other) const { return mValue < other.mValue; } constexpr bool operator<(const Serial &other) const { return mValue < other.mValue; }
...@@ -73,6 +79,7 @@ class Serial final ...@@ -73,6 +79,7 @@ class Serial final
friend class SerialFactory; friend class SerialFactory;
constexpr explicit Serial(uint64_t value) : mValue(value) {} constexpr explicit Serial(uint64_t value) : mValue(value) {}
uint64_t mValue; uint64_t mValue;
static constexpr uint64_t kInvalid = 0;
}; };
class SerialFactory final : angle::NonCopyable class SerialFactory final : angle::NonCopyable
......
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