D3D11: Update cached dynamically recompiled programs.
This change makes it so that when we need to recompile a program on a
draw call, we also update the cache. It also streamlines the internal
queries of the dynamic vertex and fragment shaders such that we only
update the input and output signatures a single time per draw. This
should also facilitate dirty bit implementations for the D3D11 back-
end.
BUG=angleproject:2116
Change-Id: Iccb0501b700bc894f40a8c68d7f297ff0c8f46bd
Reviewed-on: https://chromium-review.googlesource.com/531798
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 38f7cf9..b7bb3d1 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -34,10 +34,12 @@
namespace
{
-gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Context *context,
- gl::Shader *vertexShader)
+void GetDefaultInputLayoutFromShader(const gl::Context *context,
+ gl::Shader *vertexShader,
+ gl::InputLayout *inputLayoutOut)
{
- gl::InputLayout defaultLayout;
+ inputLayoutOut->clear();
+
for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes(context))
{
if (shaderAttr.type != GL_NONE)
@@ -53,26 +55,48 @@
gl::VertexFormatType defaultType =
gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
- defaultLayout.push_back(defaultType);
+ inputLayoutOut->push_back(defaultType);
}
}
}
-
- return defaultLayout;
}
-std::vector<GLenum> GetDefaultOutputLayoutFromShader(
- const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
+void GetDefaultOutputLayoutFromShader(
+ const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
+ std::vector<GLenum> *outputLayoutOut)
{
- std::vector<GLenum> defaultPixelOutput;
+ outputLayoutOut->clear();
if (!shaderOutputVars.empty())
{
- defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
- static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
+ outputLayoutOut->push_back(GL_COLOR_ATTACHMENT0 +
+ static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
}
+}
- return defaultPixelOutput;
+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)
@@ -1133,49 +1157,20 @@
{
}
-gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Context *context,
- const gl::Framebuffer *fbo,
- ShaderExecutableD3D **outExecutable)
-{
- mPixelShaderOutputFormatCache.clear();
-
- FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
- const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
-
- for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
- {
- const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
-
- if (colorbuffer)
- {
- mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
- ? GL_COLOR_ATTACHMENT0
- : colorbuffer->getBinding());
- }
- else
- {
- mPixelShaderOutputFormatCache.push_back(GL_NONE);
- }
- }
-
- return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
-}
-
-gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
- ShaderExecutableD3D **outExectuable,
- gl::InfoLog *infoLog)
+gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog)
{
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
{
- if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
+ if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
{
- *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
+ *outExecutable = mPixelExecutables[executableIndex]->shaderExecutable();
return gl::NoError();
}
}
std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
- mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
+ mPixelHLSL, mPixelShaderKey, mUsesFragDepth, mPixelShaderOutputLayoutCache);
// Generate new pixel executable
ShaderExecutableD3D *pixelExecutable = nullptr;
@@ -1191,7 +1186,7 @@
if (pixelExecutable)
{
mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
- new PixelExecutable(outputSignature, pixelExecutable)));
+ new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
}
else if (!infoLog)
{
@@ -1199,16 +1194,13 @@
<< tempInfoLog.str() << std::endl;
}
- *outExectuable = pixelExecutable;
+ *outExecutable = pixelExecutable;
return gl::NoError();
}
-gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
- ShaderExecutableD3D **outExectuable,
- gl::InfoLog *infoLog)
+gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog)
{
- VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
-
for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
{
if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
@@ -1220,7 +1212,7 @@
// Generate new dynamic layout with attribute conversions
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
- mVertexHLSL, inputLayout, mState.getAttributes());
+ mVertexHLSL, mCachedInputLayout, mState.getAttributes());
// Generate new vertex executable
ShaderExecutableD3D *vertexExecutable = nullptr;
@@ -1236,7 +1228,7 @@
if (vertexExecutable)
{
mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
- new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable)));
+ new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
}
else if (!infoLog)
{
@@ -1338,11 +1330,9 @@
}
gl::Error run() override
{
- const auto &defaultInputLayout =
- GetDefaultInputLayoutFromShader(mContext, mProgram->mState.getAttachedVertexShader());
+ mProgram->updateCachedInputLayoutFromShader(mContext);
- ANGLE_TRY(
- mProgram->getVertexExecutableForInputLayout(defaultInputLayout, &mResult, &mInfoLog));
+ ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(&mResult, &mInfoLog));
return gl::NoError();
}
@@ -1351,22 +1341,31 @@
const gl::Context *mContext;
};
+void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
+{
+ GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout);
+ VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
+}
+
class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
{
public:
GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
gl::Error run() override
{
- const auto &defaultPixelOutput =
- GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey());
+ mProgram->updateCachedOutputLayoutFromShader();
- ANGLE_TRY(
- mProgram->getPixelExecutableForOutputLayout(defaultPixelOutput, &mResult, &mInfoLog));
+ ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(&mResult, &mInfoLog));
return gl::NoError();
}
};
+void ProgramD3D::updateCachedOutputLayoutFromShader()
+{
+ GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
+}
+
class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
{
public:
@@ -2415,6 +2414,14 @@
state.getVertexAttribCurrentValue(locationIndex).Type);
}
}
+
+ VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
+}
+
+void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
+ const gl::Framebuffer *framebuffer)
+{
+ GetPixelOutputLayoutFromFramebuffer(context, framebuffer, &mPixelShaderOutputLayoutCache);
}
void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
@@ -2527,4 +2534,44 @@
UNREACHABLE();
}
+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;
+}
+
+bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
+{
+ if (!usesGeometryShader(drawMode))
+ {
+ // No shader necessary mean we have the required (null) executable.
+ return true;
+ }
+
+ gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
+ return mGeometryExecutables[geometryShaderType].get() != nullptr;
+}
+
+bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
+{
+ for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+ {
+ if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace rx