Commit 31018486 by Austin Kinross Committed by Jamie Madill

Resubmit "Compile the D3D11 VS and PS on separate threads at GL link time"

The original change caused a Chromium build break due to "__uncaught_exception" not being defined in concrt.h. This is because Chromium defines "_HAS_EXCEPTIONS=0" in its GYP, but ANGLE doesn't do this. This change defines "_HAS_EXCEPTIONS=0" in ANGLE's GYP to match Chromium, and refines it in ProgramD3D.cpp before including <future>. Change-Id: Ic324702569bac8f4ae1381f308c4f3f11f190f9e Reviewed-on: https://chromium-review.googlesource.com/244860Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 592ab9dd
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
[ [
'_CRT_SECURE_NO_DEPRECATE', '_CRT_SECURE_NO_DEPRECATE',
'_SCL_SECURE_NO_WARNINGS', '_SCL_SECURE_NO_WARNINGS',
'_HAS_EXCEPTIONS=0',
'NOMINMAX', 'NOMINMAX',
], ],
}, },
......
...@@ -29,7 +29,8 @@ size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char> ...@@ -29,7 +29,8 @@ size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>
std::string FormatString(const char *fmt, va_list vararg) std::string FormatString(const char *fmt, va_list vararg)
{ {
static std::vector<char> buffer(512); // Note: this needs to be thread-safe, since the D3D11 renderer uses some multithreading
std::vector<char> buffer(512);
size_t len = FormatStringIntoVector(fmt, vararg, buffer); size_t len = FormatStringIntoVector(fmt, vararg, buffer);
return std::string(&buffer[0], len); return std::string(&buffer[0], len);
......
...@@ -29,6 +29,8 @@ Error::Error(GLenum errorCode, const char *msg, ...) ...@@ -29,6 +29,8 @@ Error::Error(GLenum errorCode, const char *msg, ...)
va_list vararg; va_list vararg;
va_start(vararg, msg); va_start(vararg, msg);
createMessageString(); createMessageString();
// gl::Errors can be created across multiple threads, so we must make sure they're thread safe.
*mMessage = FormatString(msg, vararg); *mMessage = FormatString(msg, vararg);
va_end(vararg); va_end(vararg);
} }
......
...@@ -6,6 +6,13 @@ ...@@ -6,6 +6,13 @@
// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. // ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
// <future> requires _HAS_EXCEPTIONS to be defined
#ifdef _HAS_EXCEPTIONS
#undef _HAS_EXCEPTIONS
#endif // _HAS_EXCEPTIONS
#define _HAS_EXCEPTIONS 1
#include <future> // For std::async
#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "common/utilities.h" #include "common/utilities.h"
...@@ -955,6 +962,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i ...@@ -955,6 +962,7 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i
} }
else if (!infoLog) else if (!infoLog)
{ {
// This isn't thread-safe, so we should ensure that we always pass in an infoLog if using multiple threads.
std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3); std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
...@@ -970,18 +978,41 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shade ...@@ -970,18 +978,41 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shade
ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS]; gl::Error vertexShaderTaskResult(GL_NO_ERROR);
GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); gl::InfoLog tempVertexShaderInfoLog;
ShaderExecutableD3D *defaultVertexExecutable = NULL;
gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); // Use an async task to begin compiling the vertex shader asynchronously on its own task.
if (error.isError()) std::future<ShaderExecutableD3D*> vertexShaderTask = std::async([this, vertexShader, &tempVertexShaderInfoLog, &vertexShaderTaskResult]()
{ {
return LinkResult(false, error); gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
} GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
ShaderExecutableD3D *defaultVertexExecutable = NULL;
vertexShaderTaskResult = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &tempVertexShaderInfoLog);
return defaultVertexExecutable;
});
// Continue to compile the pixel shader on the main thread
std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
ShaderExecutableD3D *defaultPixelExecutable = NULL; ShaderExecutableD3D *defaultPixelExecutable = NULL;
error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); gl::Error error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
// Call .get() on the vertex shader compilation. This waits until the task is complete before returning
ShaderExecutableD3D *defaultVertexExecutable = vertexShaderTask.get();
// Combine the temporary infoLog with the real one
if (tempVertexShaderInfoLog.getLength() > 0)
{
std::vector<char> tempCharBuffer(tempVertexShaderInfoLog.getLength() + 3);
tempVertexShaderInfoLog.getLog(tempVertexShaderInfoLog.getLength(), NULL, &tempCharBuffer[0]);
infoLog.append(&tempCharBuffer[0]);
}
if (vertexShaderTaskResult.isError())
{
return LinkResult(false, vertexShaderTaskResult);
}
// If the pixel shader compilation failed, then return error
if (error.isError()) if (error.isError())
{ {
return LinkResult(false, error); return LinkResult(false, error);
......
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