Commit 04fb89ad by Geoff Lang

Generate pixel shader output to match the bound framebuffer.

Only generate pixel shader output variables for render targets that are currently bound. Fixes some performance issues with D3D10 cards that were slow to discard unused outputs. Fixed memory leaks in ProgramBinary by refactoring the freeing of the current state into a reset function. BUG=angle:670 Change-Id: I40f83e15724fb9a1a9ae61363a056999f1fa26d2 Reviewed-on: https://chromium-review.googlesource.com/202977Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 16004fca
......@@ -54,6 +54,16 @@ void SafeDelete(T*& resource)
}
template <typename T>
void SafeDeleteContainer(T& resource)
{
for (T::iterator i = resource.begin(); i != resource.end(); i++)
{
SafeDelete(*i);
}
resource.clear();
}
template <typename T>
void SafeDeleteArray(T*& resource)
{
delete[] resource;
......
......@@ -2404,7 +2404,9 @@ void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackA
VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.vertexAttribCurrentValues);
mRenderer->applyShaders(programBinary, mState.rasterizer.rasterizerDiscard, transformFeedbackActive, inputLayout);
const Framebuffer *fbo = getDrawFramebuffer();
mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.rasterizer.rasterizerDiscard, transformFeedbackActive);
programBinary->applyUniforms();
}
......
......@@ -82,7 +82,8 @@ std::string ArrayString(unsigned int i)
return (i == GL_INVALID_INDEX ? "" : "[" + Str(i) + "]");
}
const std::string DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
DynamicHLSL::DynamicHLSL(rx::Renderer *const renderer)
: mRenderer(renderer)
......@@ -339,7 +340,7 @@ std::string DynamicHLSL::generateVaryingHLSL(VertexShader *shader, const std::st
return varyingHLSL;
}
std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[], const Attribute shaderAttributes[]) const
std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader, const VertexFormat inputLayout[], const Attribute shaderAttributes[]) const
{
std::string structHLSL, initHLSL;
......@@ -392,15 +393,70 @@ std::string DynamicHLSL::generateInputLayoutHLSL(const VertexFormat inputLayout[
}
}
return "struct VS_INPUT\n"
"{\n" +
structHLSL +
"};\n"
"\n"
"void initAttributes(VS_INPUT input)\n"
"{\n" +
initHLSL +
"}\n";
std::string replacementHLSL = "struct VS_INPUT\n"
"{\n" +
structHLSL +
"};\n"
"\n"
"void initAttributes(VS_INPUT input)\n"
"{\n" +
initHLSL +
"}\n";
std::string vertexHLSL(sourceShader);
size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL);
return vertexHLSL;
}
std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOuputVariable> &outputVariables,
bool usesFragDepth, const std::vector<GLenum> &outputLayout) const
{
const int shaderModel = mRenderer->getMajorShaderModel();
std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
std::string declarationHLSL;
std::string copyHLSL;
for (size_t i = 0; i < outputVariables.size(); i++)
{
const PixelShaderOuputVariable& outputVariable = outputVariables[i];
ASSERT(outputLayout.size() > outputVariable.outputIndex);
if (outputLayout[outputVariable.outputIndex] != GL_NONE)
{
declarationHLSL += " " + gl_d3d::HLSLTypeString(outputVariable.type) + " " + outputVariable.name +
" : " + targetSemantic + Str(outputVariable.outputIndex) + ";\n";
copyHLSL += " output." + outputVariable.name + " = " + outputVariable.source + ";\n";
}
}
if (usesFragDepth)
{
declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n";
copyHLSL += " output.gl_Depth = gl_Depth; \n";
}
std::string replacementHLSL = "struct PS_OUTPUT\n"
"{\n" +
declarationHLSL +
"};\n"
"\n"
"PS_OUTPUT generateOutput()\n"
"{\n"
" PS_OUTPUT output;\n" +
copyHLSL +
" return output;\n"
"}\n";
std::string pixelHLSL(sourceShader);
size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL);
return pixelHLSL;
}
bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing,
......@@ -408,7 +464,9 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
FragmentShader *fragmentShader, VertexShader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings,
std::vector<LinkedVarying> *linkedVaryings,
std::map<int, VariableLocation> *programOutputVars) const
std::map<int, VariableLocation> *programOutputVars,
std::vector<PixelShaderOuputVariable> *outPixelShaderKey,
bool *outUsesFragDepth) const
{
if (pixelHLSL.empty() || vertexHLSL.empty())
{
......@@ -448,7 +506,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
std::string varyingSemantic = (vertexShader->mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD";
std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR";
std::string dxPositionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION";
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
std::string varyingHLSL = generateVaryingHLSL(vertexShader, varyingSemantic, linkedVaryings);
......@@ -660,22 +717,22 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
}
}
pixelHLSL += "};\n"
"\n"
"struct PS_OUTPUT\n"
"{\n";
pixelHLSL += "};\n";
if (shaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
pixelHLSL += " float4 gl_Color" + Str(renderTargetIndex) + " : " + targetSemantic + Str(renderTargetIndex) + ";\n";
}
PixelShaderOuputVariable outputKeyVariable;
outputKeyVariable.type = GL_FLOAT_VEC4;
outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
outputKeyVariable.source = broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
outputKeyVariable.outputIndex = renderTargetIndex;
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n";
outPixelShaderKey->push_back(outputKeyVariable);
}
*outUsesFragDepth = fragmentShader->mUsesFragDepth;
}
else
{
......@@ -686,16 +743,22 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
{
const VariableLocation &outputLocation = locationIt->second;
const ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
const std::string &variableName = "out_" + outputLocation.name;
const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
pixelHLSL += " " + gl_d3d::HLSLTypeString(outputVariable.type) +
" out_" + outputLocation.name + elementString +
" : " + targetSemantic + Str(locationIt->first) + ";\n";
PixelShaderOuputVariable outputKeyVariable;
outputKeyVariable.type = outputVariable.type;
outputKeyVariable.name = variableName + elementString;
outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
outputKeyVariable.outputIndex = locationIt->first;
outPixelShaderKey->push_back(outputKeyVariable);
}
*outUsesFragDepth = false;
}
pixelHLSL += "};\n"
"\n";
pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n";
if (fragmentShader->mUsesFrontFacing)
{
......@@ -807,37 +870,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(InfoLog &infoLog, int registers, const
pixelHLSL += "\n"
" gl_main();\n"
"\n"
" PS_OUTPUT output;\n";
if (shaderVersion < 300)
{
for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++)
{
unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex;
pixelHLSL += " output.gl_Color" + Str(renderTargetIndex) + " = gl_Color[" + Str(sourceColorIndex) + "];\n";
}
if (fragmentShader->mUsesFragDepth)
{
pixelHLSL += " output.gl_Depth = gl_Depth;\n";
}
}
else
{
for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
{
const VariableLocation &outputLocation = locationIt->second;
const std::string &variableName = "out_" + outputLocation.name;
const std::string &outVariableName = variableName + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
const std::string &staticVariableName = variableName + ArrayString(outputLocation.element);
pixelHLSL += " output." + outVariableName + " = " + staticVariableName + ";\n";
}
}
pixelHLSL += "\n"
" return output;\n"
" return generateOutput();\n"
"}\n";
return true;
......
......@@ -34,6 +34,14 @@ struct PackedVarying;
typedef const PackedVarying *VaryingPacking[IMPLEMENTATION_MAX_VARYING_VECTORS][4];
struct PixelShaderOuputVariable
{
GLenum type;
std::string name;
std::string source;
size_t outputIndex;
};
class DynamicHLSL
{
public:
......@@ -41,19 +49,21 @@ class DynamicHLSL
int packVaryings(InfoLog &infoLog, VaryingPacking packing, FragmentShader *fragmentShader,
VertexShader *vertexShader, const std::vector<std::string>& transformFeedbackVaryings);
std::string generateInputLayoutHLSL(const VertexFormat inputLayout[], const Attribute shaderAttributes[]) const;
std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const VertexFormat inputLayout[], const Attribute shaderAttributes[]) const;
std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOuputVariable> &outputVariables,
bool usesFragDepth, const std::vector<GLenum> &outputLayout) const;
bool generateShaderLinkHLSL(InfoLog &infoLog, int registers, const VaryingPacking packing,
std::string& pixelHLSL, std::string& vertexHLSL,
FragmentShader *fragmentShader, VertexShader *vertexShader,
const std::vector<std::string>& transformFeedbackVaryings,
std::vector<LinkedVarying> *linkedVaryings,
std::map<int, VariableLocation> *programOutputVars) const;
std::map<int, VariableLocation> *programOutputVars,
std::vector<PixelShaderOuputVariable> *outPixelShaderKey,
bool *outUsesFragDepth) const;
std::string generateGeometryShaderHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const;
void getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const;
static const std::string VERTEX_ATTRIBUTE_STUB_STRING;
private:
DISALLOW_COPY_AND_ASSIGN(DynamicHLSL);
......
......@@ -25,6 +25,7 @@
#include "libGLESv2/Shader.h"
#include "libGLESv2/Constants.h"
#include "libGLESv2/renderer/VertexDataManager.h"
#include "libGLESv2/DynamicHLSL.h"
namespace rx
{
......@@ -32,7 +33,6 @@ class ShaderExecutable;
class Renderer;
struct TranslatedAttribute;
class UniformStorage;
class DynamicHLSL;
}
namespace gl
......@@ -42,6 +42,7 @@ class VertexShader;
class InfoLog;
class AttributeBindings;
class Buffer;
class Framebuffer;
// Struct used for correlating uniforms/elements of uniform arrays to handles
struct VariableLocation
......@@ -82,7 +83,8 @@ class ProgramBinary : public RefCountObject
explicit ProgramBinary(rx::Renderer *renderer);
~ProgramBinary();
rx::ShaderExecutable *getPixelExecutable() const;
rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo);
rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout);
rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]);
rx::ShaderExecutable *getGeometryExecutable() const;
......@@ -177,6 +179,8 @@ class ProgramBinary : public RefCountObject
private:
DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
void reset();
bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader);
bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader);
......@@ -217,8 +221,7 @@ class ProgramBinary : public RefCountObject
class VertexExecutable
{
public:
VertexExecutable(rx::Renderer *const renderer,
const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS],
const GLenum signature[MAX_VERTEX_ATTRIBS],
rx::ShaderExecutable *shaderExecutable);
~VertexExecutable();
......@@ -235,14 +238,35 @@ class ProgramBinary : public RefCountObject
rx::ShaderExecutable *mShaderExecutable;
};
class PixelExecutable
{
public:
PixelExecutable(const std::vector<GLenum> &outputSignature, rx::ShaderExecutable *shaderExecutable);
~PixelExecutable();
bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
private:
std::vector<GLenum> mOutputSignature;
rx::ShaderExecutable *mShaderExecutable;
};
rx::Renderer *const mRenderer;
DynamicHLSL *mDynamicHLSL;
std::string mVertexHLSL;
rx::D3DWorkaroundType mVertexWorkarounds;
std::vector<VertexExecutable *> mVertexExecutables;
std::string mPixelHLSL;
rx::D3DWorkaroundType mPixelWorkarounds;
bool mUsesFragDepth;
std::vector<PixelShaderOuputVariable> mPixelShaderKey;
std::vector<PixelExecutable *> mPixelExecutables;
rx::ShaderExecutable *mGeometryExecutable;
rx::ShaderExecutable *mPixelExecutable;
Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS];
......
......@@ -118,7 +118,8 @@ class Renderer
bool ignoreViewport) = 0;
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0;
virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]) = 0;
virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive) = 0;
virtual void applyUniforms(const gl::ProgramBinary &programBinary) = 0;
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
......
......@@ -1349,10 +1349,11 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
}
}
void Renderer11::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[])
void Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive)
{
ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer);
ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL);
......
......@@ -77,7 +77,8 @@ class Renderer11 : public Renderer
virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]);
virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive);
virtual void applyUniforms(const gl::ProgramBinary &programBinary);
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
GLint first, GLsizei count, GLsizei instances);
......
......@@ -1601,13 +1601,14 @@ void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indi
}
}
void Renderer9::applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[])
void Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive)
{
ASSERT(!transformFeedbackActive);
ASSERT(!rasterizerDiscard);
ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer);
IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL);
IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL);
......
......@@ -76,7 +76,8 @@ class Renderer9 : public Renderer
bool ignoreViewport);
virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
virtual void applyShaders(gl::ProgramBinary *programBinary, bool rasterizerDiscard, bool transformFeedbackActive, const gl::VertexFormat inputLayout[]);
virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive);
virtual void applyUniforms(const gl::ProgramBinary &programBinary);
virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], gl::VertexAttribCurrentValueData currentValues[],
......
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