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(
}
}
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)
{
return var.isRowMajorLayout;
......@@ -1221,14 +1196,11 @@ void ProgramD3D::setSeparable(bool /* separable */)
gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog)
{
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
if (mCachedPixelExecutableIndex.valid())
{
if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
{
*outExecutable = mPixelExecutables[executableIndex]->shaderExecutable();
*outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
return gl::NoError();
}
}
std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
mPixelHLSL, mPixelShaderKey, mUsesFragDepth, mPixelShaderOutputLayoutCache);
......@@ -1248,6 +1220,7 @@ gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3
{
mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
}
else if (!infoLog)
{
......@@ -1262,14 +1235,12 @@ gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3
gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
gl::InfoLog *infoLog)
{
for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
{
if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
if (mCachedVertexExecutableIndex.valid())
{
*outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
*outExectuable =
mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
return gl::NoError();
}
}
// Generate new dynamic layout with attribute conversions
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
......@@ -1290,6 +1261,7 @@ gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3
{
mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
}
else if (!infoLog)
{
......@@ -1407,6 +1379,7 @@ void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
{
GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout);
VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
updateCachedVertexExecutableIndex();
}
class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
......@@ -1426,6 +1399,7 @@ class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
void ProgramD3D::updateCachedOutputLayoutFromShader()
{
GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
updateCachedPixelExecutableIndex();
}
class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
......@@ -2465,6 +2439,9 @@ void ProgramD3D::reset()
mGeometryShaderPreamble.clear();
mUniformsDirty = true;
mCachedPixelExecutableIndex.reset();
mCachedVertexExecutableIndex.reset();
}
unsigned int ProgramD3D::getSerial() const
......@@ -2506,6 +2483,7 @@ void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::Stat
mCurrentVertexArrayStateSerial = associatedSerial;
mCachedInputLayout.clear();
const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
for (size_t locationIndex : mState.getActiveAttribLocationsMask())
......@@ -2525,12 +2503,35 @@ void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::Stat
}
VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
updateCachedVertexExecutableIndex();
}
void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
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,
......@@ -2653,17 +2654,7 @@ void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
{
VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
{
if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
{
return true;
}
}
return false;
return mCachedVertexExecutableIndex.valid();
}
bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
......@@ -2680,15 +2671,7 @@ bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
{
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
{
if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
{
return true;
}
}
return false;
return mCachedPixelExecutableIndex.valid();
}
template <typename DestT>
......@@ -2726,4 +2709,30 @@ void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuin
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
......@@ -434,6 +434,8 @@ class ProgramD3D : public ProgramImpl
void updateCachedInputLayoutFromShader(const gl::Context *context);
void updateCachedOutputLayoutFromShader();
void updateCachedVertexExecutableIndex();
void updateCachedPixelExecutableIndex();
RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL;
......@@ -475,6 +477,7 @@ class ProgramD3D : public ProgramImpl
// Cache for pixel shader output layout to save reallocations.
std::vector<GLenum> mPixelShaderOutputLayoutCache;
Optional<size_t> mCachedPixelExecutableIndex;
AttribIndexArray mAttribLocationToD3DSemantic;
......@@ -484,6 +487,7 @@ class ProgramD3D : public ProgramImpl
std::vector<GLint> mFragmentUBOCache;
VertexExecutable::Signature mCachedVertexSignature;
gl::InputLayout mCachedInputLayout;
Optional<size_t> mCachedVertexExecutableIndex;
std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms;
......
......@@ -58,12 +58,18 @@ class SerialFactory;
class Serial final
{
public:
constexpr Serial() : mValue(0) {}
constexpr Serial() : mValue(kInvalid) {}
constexpr Serial(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 { return 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 == 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; }
......@@ -73,6 +79,7 @@ class Serial final
friend class SerialFactory;
constexpr explicit Serial(uint64_t value) : mValue(value) {}
uint64_t mValue;
static constexpr uint64_t kInvalid = 0;
};
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