Commit 80a6fc03 by Jamie Madill

Make output variables part of Program's shared data.

Also initialize this structure within Program instead of DynamicHLSL. This should have benefits for other back-ends. Also these variables weren't being serialized and de-serialized with the program binary, which could mess up WebGL apps that use MRT. BUG=angleproject:1123 Change-Id: Ic0dd4840f26441a1bee8527dfa178b24daf82f8a Reviewed-on: https://chromium-review.googlesource.com/294571Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 63805b47
......@@ -11,6 +11,7 @@
#include <algorithm>
#include "common/BitSetIterator.h"
#include "common/debug.h"
#include "common/platform.h"
#include "common/utilities.h"
......@@ -309,8 +310,10 @@ Error Program::link(const gl::Data &data)
return Error(GL_NO_ERROR);
}
rx::LinkResult result = mProgram->link(data, mInfoLog, mData.mAttachedFragmentShader,
mData.mAttachedVertexShader, &mOutputVariables);
linkOutputVariables();
rx::LinkResult result =
mProgram->link(data, mInfoLog, mData.mAttachedFragmentShader, mData.mAttachedVertexShader);
if (result.error.isError() || !result.linkSuccess)
{
......@@ -357,6 +360,7 @@ void Program::unlink(bool destroy)
mData.mAttributes.clear();
mData.mActiveAttribLocationsMask.reset();
mData.mTransformFeedbackVaryingVars.clear();
mData.mOutputVariables.clear();
mProgram->reset();
......@@ -424,6 +428,17 @@ Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei lengt
stream.readInt(&mData.mTransformFeedbackBufferMode);
unsigned int outputVarCount = stream.readInt<unsigned int>();
for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
{
int locationIndex = stream.readInt<int>();
VariableLocation locationData;
locationData.element = stream.readInt<unsigned int>();
locationData.index = stream.readInt<unsigned int>();
locationData.name = stream.readString();
mData.mOutputVariables[locationIndex] = locationData;
}
rx::LinkResult result = mProgram->load(mInfoLog, &stream);
if (result.error.isError() || !result.linkSuccess)
{
......@@ -464,6 +479,15 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
stream.writeInt(mData.mTransformFeedbackBufferMode);
stream.writeInt(mData.mOutputVariables.size());
for (const auto &outputPair : mData.mOutputVariables)
{
stream.writeInt(outputPair.first);
stream.writeInt(outputPair.second.element);
stream.writeInt(outputPair.second.index);
stream.writeString(outputPair.second.name);
}
gl::Error error = mProgram->save(&stream);
if (error.isError())
{
......@@ -692,7 +716,7 @@ GLint Program::getFragDataLocation(const std::string &name) const
{
std::string baseName(name);
unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName);
for (auto outputPair : mOutputVariables)
for (auto outputPair : mData.mOutputVariables)
{
const VariableLocation &outputVariable = outputPair.second;
if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
......@@ -1663,4 +1687,43 @@ std::vector<const sh::Varying *> Program::getMergedVaryings() const
return varyings;
}
void Program::linkOutputVariables()
{
const Shader *fragmentShader = mData.mAttachedFragmentShader;
ASSERT(fragmentShader != nullptr);
// Skip this step for GLES2 shaders.
if (fragmentShader->getShaderVersion() == 100)
return;
const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
// TODO(jmadill): any caps validation here?
for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size();
outputVariableIndex++)
{
const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
// Don't store outputs for gl_FragDepth, gl_FragColor, etc.
if (outputVariable.isBuiltIn())
continue;
// Since multiple output locations must be specified, use 0 for non-specified locations.
int baseLocation = (outputVariable.location == -1 ? 0 : outputVariable.location);
ASSERT(outputVariable.staticUse);
for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount();
elementIndex++)
{
const int location = baseLocation + elementIndex;
ASSERT(mData.mOutputVariables.count(location) == 0);
unsigned int element = outputVariable.isArray() ? elementIndex : GL_INVALID_INDEX;
mData.mOutputVariables[location] =
VariableLocation(outputVariable.name, element, outputVariableIndex);
}
}
}
}
......@@ -185,6 +185,10 @@ class Program : angle::NonCopyable
{
return mActiveAttribLocationsMask;
}
const std::map<int, VariableLocation> &getOutputVariables() const
{
return mOutputVariables;
}
private:
friend class Program;
......@@ -201,6 +205,9 @@ class Program : angle::NonCopyable
std::vector<sh::Attribute> mAttributes;
std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
// TODO(jmadill): use unordered/hash map when available
std::map<int, VariableLocation> mOutputVariables;
// TODO(jmadill): move more state into Data.
};
......@@ -343,12 +350,11 @@ class Program : angle::NonCopyable
void defineOutputVariables(Shader *fragmentShader);
std::vector<const sh::Varying *> getMergedVaryings() const;
void linkOutputVariables();
Data mData;
rx::ProgramImpl *mProgram;
std::map<int, VariableLocation> mOutputVariables;
bool mValidated;
AttributeBindings mAttributeBindings;
......
......@@ -169,6 +169,11 @@ void Shader::flagForDeletion()
mDeleteStatus = true;
}
int Shader::getShaderVersion() const
{
return mShader->getShaderVersion();
}
const std::vector<gl::PackedVarying> &Shader::getVaryings() const
{
return mShader->getVaryings();
......
......@@ -85,6 +85,8 @@ class Shader : angle::NonCopyable
bool isFlaggedForDeletion() const;
void flagForDeletion();
int getShaderVersion() const;
const std::vector<gl::PackedVarying> &getVaryings() const;
const std::vector<sh::Uniform> &getUniforms() const;
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
......
......@@ -43,8 +43,7 @@ class ProgramImpl : angle::NonCopyable
virtual LinkResult link(const gl::Data &data,
gl::InfoLog &infoLog,
gl::Shader *fragmentShader,
gl::Shader *vertexShader,
std::map<int, gl::VariableLocation> *outputVariables) = 0;
gl::Shader *vertexShader) = 0;
virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
......
......@@ -20,7 +20,7 @@ namespace rx
class ShaderImpl : angle::NonCopyable
{
public:
ShaderImpl() { }
ShaderImpl() : mShaderVersion(100) {}
virtual ~ShaderImpl() { }
virtual bool compile(gl::Compiler *compiler, const std::string &source) = 0;
......@@ -29,6 +29,8 @@ class ShaderImpl : angle::NonCopyable
virtual const std::string &getInfoLog() const { return mInfoLog; }
virtual const std::string &getTranslatedSource() const { return mTranslatedSource; }
int getShaderVersion() const { return mShaderVersion; }
const std::vector<gl::PackedVarying> &getVaryings() const { return mVaryings; }
const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; }
......@@ -45,6 +47,9 @@ class ShaderImpl : angle::NonCopyable
std::string mInfoLog;
std::string mTranslatedSource;
// TODO(jmadill): make part of shared non-Impl state
int mShaderVersion;
std::vector<gl::PackedVarying> mVaryings;
std::vector<sh::Uniform> mUniforms;
std::vector<sh::InterfaceBlock> mInterfaceBlocks;
......
......@@ -10,11 +10,11 @@
#include "common/utilities.h"
#include "compiler/translator/blocklayoutHLSL.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/Program.h"
#include "libANGLE/Shader.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
// For use with ArrayString, see angleutils.h
static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int.");
......@@ -737,16 +737,13 @@ void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader,
}
bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData,
InfoLog &infoLog,
int registers,
const VaryingPacking packing,
std::string &pixelHLSL,
std::string &vertexHLSL,
const ShaderD3D *fragmentShader,
const ShaderD3D *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings,
std::vector<LinkedVarying> *linkedVaryings,
std::map<int, VariableLocation> *programOutputVars,
std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
bool *outUsesFragDepth) const
{
......@@ -755,6 +752,9 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
return false;
}
const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(programData.getAttachedVertexShader());
const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(programData.getAttachedFragmentShader());
bool usesMRT = fragmentShader->mUsesMultipleRenderTargets;
bool usesFragCoord = fragmentShader->mUsesFragCoord;
bool usesPointCoord = fragmentShader->mUsesPointCoord;
......@@ -935,12 +935,12 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
}
else
{
defineOutputVariables(fragmentShader, programOutputVars);
const auto &programOutputVars = programData.getOutputVariables();
const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++)
for (auto outputPair : programOutputVars)
{
const VariableLocation &outputLocation = locationIt->second;
const VariableLocation &outputLocation = outputPair.second;
const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
const std::string &variableName = "out_" + outputLocation.name;
const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
......@@ -951,7 +951,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
outputKeyVariable.type = outputVariable.type;
outputKeyVariable.name = variableName + elementString;
outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
outputKeyVariable.outputIndex = locationIt->first;
outputKeyVariable.outputIndex = outputPair.first;
outPixelShaderKey->push_back(outputKeyVariable);
}
......@@ -1090,35 +1090,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
return true;
}
void DynamicHLSL::defineOutputVariables(const ShaderD3D *fragmentShader,
std::map<int, VariableLocation> *programOutputVars) const
{
const std::vector<sh::Attribute> &shaderOutputVars = fragmentShader->getActiveOutputVariables();
for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++)
{
const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex];
const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location;
ASSERT(outputVariable.staticUse);
if (outputVariable.arraySize > 0)
{
for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++)
{
const int location = baseLocation + elementIndex;
ASSERT(programOutputVars->count(location) == 0);
(*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex);
}
}
else
{
ASSERT(programOutputVars->count(baseLocation) == 0);
(*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex);
}
}
}
std::string DynamicHLSL::generateGeometryShaderHLSL(int registers,
const ShaderD3D *fragmentShader,
const ShaderD3D *vertexShader) const
......
......@@ -15,6 +15,7 @@
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Program.h"
#include "libANGLE/formatutils.h"
namespace sh
......@@ -61,16 +62,13 @@ class DynamicHLSL : angle::NonCopyable
std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector<PixelShaderOutputVariable> &outputVariables,
bool usesFragDepth, const std::vector<GLenum> &outputLayout) const;
bool generateShaderLinkHLSL(const gl::Data &data,
const gl::Program::Data &programData,
gl::InfoLog &infoLog,
int registers,
const VaryingPacking packing,
std::string &pixelHLSL,
std::string &vertexHLSL,
const ShaderD3D *fragmentShader,
const ShaderD3D *vertexShader,
const std::vector<std::string> &transformFeedbackVaryings,
std::vector<gl::LinkedVarying> *linkedVaryings,
std::map<int, gl::VariableLocation> *programOutputVars,
std::vector<PixelShaderOutputVariable> *outPixelShaderKey,
bool *outUsesFragDepth) const;
......@@ -90,8 +88,6 @@ class DynamicHLSL : angle::NonCopyable
std::string generateVaryingHLSL(const ShaderD3D *shader) const;
void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector<gl::LinkedVarying> *linkedVaryings) const;
void defineOutputVariables(const ShaderD3D *fragmentShader,
std::map<int, gl::VariableLocation> *programOutputVars) const;
std::string generatePointSpriteHLSL(int registers,
const ShaderD3D *fragmentShader,
const ShaderD3D *vertexShader) const;
......
......@@ -1112,8 +1112,7 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, int regis
LinkResult ProgramD3D::link(const gl::Data &data,
gl::InfoLog &infoLog,
gl::Shader *fragmentShader,
gl::Shader *vertexShader,
std::map<int, gl::VariableLocation> *outputVariables)
gl::Shader *vertexShader)
{
ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
......@@ -1150,10 +1149,9 @@ LinkResult ProgramD3D::link(const gl::Data &data,
LinkVaryingRegisters(infoLog, vertexShaderD3D, fragmentShaderD3D);
std::vector<gl::LinkedVarying> linkedVaryings;
if (!mDynamicHLSL->generateShaderLinkHLSL(
data, infoLog, registers, packing, mPixelHLSL, mVertexHLSL, fragmentShaderD3D,
vertexShaderD3D, mData.getTransformFeedbackVaryingNames(), &linkedVaryings,
outputVariables, &mPixelShaderKey, &mUsesFragDepth))
if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, infoLog, registers, packing, mPixelHLSL,
mVertexHLSL, &linkedVaryings, &mPixelShaderKey,
&mUsesFragDepth))
{
return LinkResult(false, gl::Error(GL_NO_ERROR));
}
......
......@@ -73,8 +73,7 @@ class ProgramD3D : public ProgramImpl
LinkResult link(const gl::Data &data,
gl::InfoLog &infoLog,
gl::Shader *fragmentShader,
gl::Shader *vertexShader,
std::map<int, gl::VariableLocation> *outputVariables) override;
gl::Shader *vertexShader) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
......
......@@ -65,8 +65,7 @@ const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableLis
return variableList;
}
ShaderD3D::ShaderD3D(GLenum type, RendererD3D *renderer)
: mShaderType(type), mShaderVersion(100), mRenderer(renderer)
ShaderD3D::ShaderD3D(GLenum type, RendererD3D *renderer) : mShaderType(type), mRenderer(renderer)
{
uncompile();
}
......
......@@ -60,8 +60,6 @@ class ShaderD3D : public ShaderImpl
GLenum mShaderType;
int mShaderVersion;
bool mUsesMultipleRenderTargets;
bool mUsesFragColor;
bool mUsesFragData;
......
......@@ -61,8 +61,7 @@ gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
LinkResult ProgramGL::link(const gl::Data &data,
gl::InfoLog &infoLog,
gl::Shader *fragmentShader,
gl::Shader *vertexShader,
std::map<int, gl::VariableLocation> *outputVariables)
gl::Shader *vertexShader)
{
// Reset the program state, delete the current program if one exists
reset();
......
......@@ -40,8 +40,7 @@ class ProgramGL : public ProgramImpl
LinkResult link(const gl::Data &data,
gl::InfoLog &infoLog,
gl::Shader *fragmentShader,
gl::Shader *vertexShader,
std::map<int, gl::VariableLocation> *outputVariables) override;
gl::Shader *vertexShader) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
......
......@@ -114,6 +114,8 @@ bool ShaderGL::compile(gl::Compiler *compiler, const std::string &source)
}
// Gather the shader information
mShaderVersion = ShGetShaderVersion(compilerHandle);
// TODO: refactor this out, gathering of the attributes, varyings and outputs should be done
// at the gl::Shader level
if (mType == GL_VERTEX_SHADER)
......
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