Commit 24268826 by Tim Van Patten Committed by Commit Bot

Vulkan: Pass Input/Output Varying lists during linking

When linking program varyings, the necessary functions need the following: - Lists of Input and Output varyings - Shader versions - Shader types Rather than the full Shader itself, just this information will be passed around to the functions. This allows us to limit how much data is saved for each Program when linkProgram() succeeds, so PPos can link the attached Programs at draw time. Bug: angleproject:4514 Test: CQ Change-Id: I27b639cae9a153d0d3f5efab3b38550f09f4f49b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2181449 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 11f9c56c
...@@ -3431,7 +3431,7 @@ void Program::setBaseInstanceUniform(GLuint baseInstance) ...@@ -3431,7 +3431,7 @@ void Program::setBaseInstanceUniform(GLuint baseInstance)
bool Program::linkVaryings(InfoLog &infoLog) const bool Program::linkVaryings(InfoLog &infoLog) const
{ {
Shader *previousShader = nullptr; ShaderType previousShaderType = ShaderType::InvalidEnum;
for (ShaderType shaderType : kAllGraphicsShaderTypes) for (ShaderType shaderType : kAllGraphicsShaderTypes)
{ {
Shader *currentShader = mState.mAttachedShaders[shaderType]; Shader *currentShader = mState.mAttachedShaders[shaderType];
...@@ -3440,20 +3440,29 @@ bool Program::linkVaryings(InfoLog &infoLog) const ...@@ -3440,20 +3440,29 @@ bool Program::linkVaryings(InfoLog &infoLog) const
continue; continue;
} }
if (previousShader) if (previousShaderType != ShaderType::InvalidEnum)
{ {
if (!linkValidateShaderInterfaceMatching(previousShader, currentShader, isSeparable(), Shader *previousShader = mState.mAttachedShaders[previousShaderType];
infoLog)) const std::vector<sh::ShaderVariable> &outputVaryings =
previousShader->getOutputVaryings();
if (!linkValidateShaderInterfaceMatching(
outputVaryings, currentShader->getInputVaryings(), previousShaderType,
currentShader->getType(), previousShader->getShaderVersion(),
currentShader->getShaderVersion(), isSeparable(), infoLog))
{ {
return false; return false;
} }
} }
previousShader = currentShader; previousShaderType = currentShader->getType();
} }
Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex]; Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment]; Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
if (!linkValidateBuiltInVaryings(vertexShader, fragmentShader, infoLog)) if (vertexShader && fragmentShader &&
!linkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
fragmentShader->getInputVaryings(),
vertexShader->getShaderVersion(), infoLog))
{ {
return false; return false;
} }
...@@ -3476,8 +3485,9 @@ void Program::getFilteredVaryings(const std::vector<sh::ShaderVariable> &varying ...@@ -3476,8 +3485,9 @@ void Program::getFilteredVaryings(const std::vector<sh::ShaderVariable> &varying
} }
} }
bool Program::doShaderVariablesMatch(gl::Shader *generatingShader, bool Program::doShaderVariablesMatch(int outputShaderVersion,
gl::Shader *consumingShader, ShaderType outputShaderType,
ShaderType inputShaderType,
const sh::ShaderVariable &input, const sh::ShaderVariable &input,
const sh::ShaderVariable &output, const sh::ShaderVariable &output,
bool validateGeometryShaderInputs, bool validateGeometryShaderInputs,
...@@ -3496,13 +3506,13 @@ bool Program::doShaderVariablesMatch(gl::Shader *generatingShader, ...@@ -3496,13 +3506,13 @@ bool Program::doShaderVariablesMatch(gl::Shader *generatingShader,
if (namesMatch || locationsMatch) if (namesMatch || locationsMatch)
{ {
std::string mismatchedStructFieldName; std::string mismatchedStructFieldName;
LinkMismatchError linkError = LinkValidateVaryings( LinkMismatchError linkError =
output, input, generatingShader->getShaderVersion(), validateGeometryShaderInputs, LinkValidateVaryings(output, input, outputShaderVersion, validateGeometryShaderInputs,
isSeparable, &mismatchedStructFieldName); isSeparable, &mismatchedStructFieldName);
if (linkError != LinkMismatchError::NO_MISMATCH) if (linkError != LinkMismatchError::NO_MISMATCH)
{ {
LogLinkMismatch(infoLog, input.name, "varying", linkError, mismatchedStructFieldName, LogLinkMismatch(infoLog, input.name, "varying", linkError, mismatchedStructFieldName,
generatingShader->getType(), consumingShader->getType()); outputShaderType, inputShaderType);
return false; return false;
} }
...@@ -3514,18 +3524,21 @@ bool Program::doShaderVariablesMatch(gl::Shader *generatingShader, ...@@ -3514,18 +3524,21 @@ bool Program::doShaderVariablesMatch(gl::Shader *generatingShader,
// [OpenGL ES 3.1] Chapter 7.4.1 "Shader Interface Matching" Page 91 // [OpenGL ES 3.1] Chapter 7.4.1 "Shader Interface Matching" Page 91
// TODO(jiawei.shao@intel.com): add validation on input/output blocks matching // TODO(jiawei.shao@intel.com): add validation on input/output blocks matching
bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader, bool Program::linkValidateShaderInterfaceMatching(
gl::Shader *consumingShader, const std::vector<sh::ShaderVariable> &outputVaryings,
bool isSeparable, const std::vector<sh::ShaderVariable> &inputVaryings,
gl::InfoLog &infoLog) ShaderType outputShaderType,
{ ShaderType inputShaderType,
ASSERT(generatingShader->getShaderVersion() == consumingShader->getShaderVersion()); int outputShaderVersion,
int inputShaderVersion,
bool isSeparable,
gl::InfoLog &infoLog)
{
ASSERT(outputShaderVersion == inputShaderVersion);
const std::vector<sh::ShaderVariable> &outputVaryings = generatingShader->getOutputVaryings();
const std::vector<sh::ShaderVariable> &inputVaryings = consumingShader->getInputVaryings();
std::vector<const sh::ShaderVariable *> filteredInputVaryings; std::vector<const sh::ShaderVariable *> filteredInputVaryings;
std::vector<const sh::ShaderVariable *> filteredOutputVaryings; std::vector<const sh::ShaderVariable *> filteredOutputVaryings;
bool validateGeometryShaderInputs = consumingShader->getType() == ShaderType::Geometry; bool validateGeometryShaderInputs = inputShaderType == ShaderType::Geometry;
getFilteredVaryings(inputVaryings, &filteredInputVaryings); getFilteredVaryings(inputVaryings, &filteredInputVaryings);
getFilteredVaryings(outputVaryings, &filteredOutputVaryings); getFilteredVaryings(outputVaryings, &filteredOutputVaryings);
...@@ -3533,16 +3546,16 @@ bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader, ...@@ -3533,16 +3546,16 @@ bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader,
// Separable programs require the number of inputs and outputs match // Separable programs require the number of inputs and outputs match
if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size()) if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size())
{ {
infoLog << GetShaderTypeString(consumingShader->getType()) infoLog << GetShaderTypeString(inputShaderType)
<< " does not consume all varyings generated by " << " does not consume all varyings generated by "
<< GetShaderTypeString(generatingShader->getType()); << GetShaderTypeString(outputShaderType);
return false; return false;
} }
if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size()) if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size())
{ {
infoLog << GetShaderTypeString(generatingShader->getType()) infoLog << GetShaderTypeString(outputShaderType)
<< " does not generate all varyings consumed by " << " does not generate all varyings consumed by "
<< GetShaderTypeString(consumingShader->getType()); << GetShaderTypeString(inputShaderType);
return false; return false;
} }
...@@ -3552,8 +3565,9 @@ bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader, ...@@ -3552,8 +3565,9 @@ bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader,
bool match = false; bool match = false;
for (const sh::ShaderVariable *output : filteredOutputVaryings) for (const sh::ShaderVariable *output : filteredOutputVaryings)
{ {
if (doShaderVariablesMatch(generatingShader, consumingShader, *input, *output, if (doShaderVariablesMatch(outputShaderVersion, outputShaderType, inputShaderType,
validateGeometryShaderInputs, isSeparable, infoLog)) *input, *output, validateGeometryShaderInputs, isSeparable,
infoLog))
{ {
match = true; match = true;
break; break;
...@@ -3565,8 +3579,8 @@ bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader, ...@@ -3565,8 +3579,8 @@ bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader,
// if it is not active. GLSL ES 3.00.6 section 4.3.10. // if it is not active. GLSL ES 3.00.6 section 4.3.10.
if (!match && input->staticUse) if (!match && input->staticUse)
{ {
infoLog << GetShaderTypeString(consumingShader->getType()) << " varying " << input->name infoLog << GetShaderTypeString(inputShaderType) << " varying " << input->name
<< " does not match any " << GetShaderTypeString(generatingShader->getType()) << " does not match any " << GetShaderTypeString(outputShaderType)
<< " varying"; << " varying";
return false; return false;
} }
...@@ -4102,21 +4116,12 @@ LinkMismatchError Program::LinkValidateVaryings(const sh::ShaderVariable &output ...@@ -4102,21 +4116,12 @@ LinkMismatchError Program::LinkValidateVaryings(const sh::ShaderVariable &output
return LinkMismatchError::NO_MISMATCH; return LinkMismatchError::NO_MISMATCH;
} }
bool Program::linkValidateBuiltInVaryings(Shader *vertexShader, bool Program::linkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &vertexVaryings,
Shader *fragmentShader, const std::vector<sh::ShaderVariable> &fragmentVaryings,
int vertexShaderVersion,
InfoLog &infoLog) InfoLog &infoLog)
{ {
if (!vertexShader || !fragmentShader) if (vertexShaderVersion != 100)
{
// We can't validate an interface if we don't have both a producer and a consumer
return true;
}
const auto &vertexVaryings = vertexShader->getOutputVaryings();
const auto &fragmentVaryings = fragmentShader->getInputVaryings();
int shaderVersion = vertexShader->getShaderVersion();
if (shaderVersion != 100)
{ {
// Only ESSL 1.0 has restrictions on matching input and output invariance // Only ESSL 1.0 has restrictions on matching input and output invariance
return true; return true;
......
...@@ -816,19 +816,26 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -816,19 +816,26 @@ class Program final : angle::NonCopyable, public LabeledObject
static void getFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings, static void getFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings,
std::vector<const sh::ShaderVariable *> *filteredVaryingsOut); std::vector<const sh::ShaderVariable *> *filteredVaryingsOut);
static bool doShaderVariablesMatch(gl::Shader *generatingShader, static bool doShaderVariablesMatch(int outputShaderVersion,
gl::Shader *consumingShader, ShaderType outputShaderType,
ShaderType inputShaderType,
const sh::ShaderVariable &input, const sh::ShaderVariable &input,
const sh::ShaderVariable &output, const sh::ShaderVariable &output,
bool validateGeometryShaderInputs, bool validateGeometryShaderInputs,
bool isSeparable, bool isSeparable,
gl::InfoLog &infoLog); gl::InfoLog &infoLog);
static bool linkValidateShaderInterfaceMatching(Shader *generatingShader, static bool linkValidateShaderInterfaceMatching(
Shader *consumingShader, const std::vector<sh::ShaderVariable> &outputVaryings,
bool isSeparable, const std::vector<sh::ShaderVariable> &inputVaryings,
InfoLog &infoLog); ShaderType outputShaderType,
static bool linkValidateBuiltInVaryings(Shader *vertexShader, ShaderType inputShaderType,
Shader *fragmentShader, int outputShaderVersion,
int inputShaderVersion,
bool isSeparable,
InfoLog &infoLog);
static bool linkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &vertexVaryings,
const std::vector<sh::ShaderVariable> &fragmentVaryings,
int vertexShaderVersion,
InfoLog &infoLog); InfoLog &infoLog);
private: private:
......
...@@ -511,28 +511,34 @@ angle::Result ProgramPipeline::link(const Context *context) ...@@ -511,28 +511,34 @@ angle::Result ProgramPipeline::link(const Context *context)
bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
{ {
Shader *previousShader = nullptr; ShaderType previousShaderType = ShaderType::InvalidEnum;
for (ShaderType shaderType : getExecutable().getLinkedShaderStages()) for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
{ {
Program *currentProgram = mState.mPrograms[shaderType]; Program *currentProgram = mState.mPrograms[shaderType];
ASSERT(currentProgram); ASSERT(currentProgram);
Shader *currentShader = Shader *currentShader =
const_cast<Shader *>(currentProgram->getState().getAttachedShader(shaderType)); const_cast<Shader *>(currentProgram->getState().getAttachedShader(shaderType));
if (!currentShader) ASSERT(currentShader);
{
continue;
}
if (previousShader) if (previousShaderType != ShaderType::InvalidEnum)
{ {
const Program *previousProgram = mState.mPrograms[previousShaderType];
ASSERT(previousProgram);
Shader *previousShader = const_cast<Shader *>(
previousProgram->getState().getAttachedShader(previousShaderType));
ASSERT(previousShader);
const std::vector<sh::ShaderVariable> &outputVaryings =
previousShader->getOutputVaryings();
if (!Program::linkValidateShaderInterfaceMatching( if (!Program::linkValidateShaderInterfaceMatching(
previousShader, currentShader, currentProgram->isSeparable(), infoLog)) outputVaryings, currentShader->getInputVaryings(), previousShaderType,
currentShader->getType(), previousShader->getShaderVersion(),
currentShader->getShaderVersion(), true, infoLog))
{ {
return false; return false;
} }
} }
previousShader = currentShader; previousShaderType = currentShader->getType();
} }
Program *vertexProgram = mState.mPrograms[ShaderType::Vertex]; Program *vertexProgram = mState.mPrograms[ShaderType::Vertex];
...@@ -541,12 +547,15 @@ bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const ...@@ -541,12 +547,15 @@ bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
{ {
return false; return false;
} }
Shader *vertexShader = Shader *vertexShader =
const_cast<Shader *>(vertexProgram->getState().getAttachedShader(ShaderType::Vertex)); const_cast<Shader *>(vertexProgram->getState().getAttachedShader(ShaderType::Vertex));
Shader *fragmentShader = Shader *fragmentShader =
const_cast<Shader *>(fragmentProgram->getState().getAttachedShader(ShaderType::Fragment)); const_cast<Shader *>(fragmentProgram->getState().getAttachedShader(ShaderType::Fragment));
return Program::linkValidateBuiltInVaryings(vertexShader, fragmentShader, infoLog); ASSERT(vertexShader);
ASSERT(fragmentShader);
return Program::linkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
fragmentShader->getInputVaryings(),
vertexShader->getShaderVersion(), infoLog);
} }
void ProgramPipeline::validate(const gl::Context *context) void ProgramPipeline::validate(const gl::Context *context)
......
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