Commit d654ac9b by Jamie Madill Committed by Commit Bot

Program: Support multiple varying packings.

Instead of using a single varying packing for all program stages, we switch to using a varying register packing for each pair of input/output shaders. This allows several valid use cases that use many varying to succeed. For instance Geometry Shaders have both an input and output varying packing. With tessellation shaders the upper bound of valid varying packings in one Program goes up even more. We keep multiple varying packings at once inside a new "ProgramVaryingPacking" class. Internally the class keeps a unique varying mapping for each input/output interface in the program. Separable programs with "open" interfaces are handled specially. Fixes a bug where varying counting was artificially limited for programs with more than two shaders. This CL also disables GS support when we're emulating line raster so we don't have to figure out the details on how to place the special position varying. Bug: angleproject:5496 Change-Id: I1f9a327c4750caef570c608d86953e9d0cc5eea3 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2606532 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 8943d1e2
...@@ -368,7 +368,6 @@ class ProgramState final : angle::NonCopyable ...@@ -368,7 +368,6 @@ class ProgramState final : angle::NonCopyable
friend class MemoryProgramCache; friend class MemoryProgramCache;
friend class Program; friend class Program;
void updateTransformFeedbackStrides();
void updateActiveSamplers(); void updateActiveSamplers();
void updateProgramInterfaceInputs(); void updateProgramInterfaceInputs();
void updateProgramInterfaceOutputs(); void updateProgramInterfaceOutputs();
...@@ -490,10 +489,6 @@ class Program final : public LabeledObject, public angle::Subject, public HasAtt ...@@ -490,10 +489,6 @@ class Program final : public LabeledObject, public angle::Subject, public HasAtt
void bindFragmentOutputLocation(GLuint index, const char *name); void bindFragmentOutputLocation(GLuint index, const char *name);
void bindFragmentOutputIndex(GLuint index, const char *name); void bindFragmentOutputIndex(GLuint index, const char *name);
bool linkMergedVaryings(const Context *context,
const ProgramMergedVaryings &mergedVaryings,
VaryingPacking *varyingPacking);
// KHR_parallel_shader_compile // KHR_parallel_shader_compile
// Try to link the program asynchrously. As a result, background threads may be launched to // Try to link the program asynchrously. As a result, background threads may be launched to
// execute the linking tasks concurrently. // execute the linking tasks concurrently.
...@@ -868,14 +863,6 @@ class Program final : public LabeledObject, public angle::Subject, public HasAtt ...@@ -868,14 +863,6 @@ class Program final : public LabeledObject, public angle::Subject, public HasAtt
void updateLinkedShaderStages(); void updateLinkedShaderStages();
bool linkValidateTransformFeedback(const Version &version,
InfoLog &infoLog,
const ProgramMergedVaryings &linkedVaryings,
ShaderType stage,
const Caps &caps) const;
void gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings, ShaderType stage);
int getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const; int getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const;
bool isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const; bool isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const;
bool linkOutputVariables(const Caps &caps, bool linkOutputVariables(const Caps &caps,
......
...@@ -334,6 +334,26 @@ class ProgramExecutable final : public angle::Subject ...@@ -334,6 +334,26 @@ class ProgramExecutable final : public angle::Subject
void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex, void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,
std::vector<SamplerBinding> &samplerBindings); std::vector<SamplerBinding> &samplerBindings);
bool linkMergedVaryings(const Context *context,
const HasAttachedShaders &programOrPipeline,
const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &transformFeedbackVaryingNames,
bool isSeparable,
ProgramVaryingPacking *varyingPacking);
bool linkValidateTransformFeedback(
const Context *context,
const ProgramMergedVaryings &varyings,
ShaderType stage,
const std::vector<std::string> &transformFeedbackVaryingNames);
void gatherTransformFeedbackVaryings(
const ProgramMergedVaryings &varyings,
ShaderType stage,
const std::vector<std::string> &transformFeedbackVaryingNames);
void updateTransformFeedbackStrides();
InfoLog mInfoLog; InfoLog mInfoLog;
ShaderBitSet mLinkedGraphicsShaderStages; ShaderBitSet mLinkedGraphicsShaderStages;
......
...@@ -221,7 +221,7 @@ struct ProgramLinkedResources ...@@ -221,7 +221,7 @@ struct ProgramLinkedResources
std::vector<BufferVariable> *bufferVariablesOut, std::vector<BufferVariable> *bufferVariablesOut,
std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut); std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
VaryingPacking varyingPacking; ProgramVaryingPacking varyingPacking;
UniformBlockLinker uniformBlockLinker; UniformBlockLinker uniformBlockLinker;
ShaderStorageBlockLinker shaderStorageBlockLinker; ShaderStorageBlockLinker shaderStorageBlockLinker;
AtomicCounterBufferLinker atomicCounterBufferLinker; AtomicCounterBufferLinker atomicCounterBufferLinker;
......
...@@ -420,7 +420,7 @@ angle::Result ProgramPipeline::link(const Context *context) ...@@ -420,7 +420,7 @@ angle::Result ProgramPipeline::link(const Context *context)
} }
ProgramMergedVaryings mergedVaryings; ProgramMergedVaryings mergedVaryings;
VaryingPacking varyingPacking; ProgramVaryingPacking varyingPacking;
if (!getExecutable().isCompute()) if (!getExecutable().isCompute())
{ {
...@@ -438,14 +438,22 @@ angle::Result ProgramPipeline::link(const Context *context) ...@@ -438,14 +438,22 @@ angle::Result ProgramPipeline::link(const Context *context)
} }
mergedVaryings = GetMergedVaryingsFromShaders(*this); mergedVaryings = GetMergedVaryingsFromShaders(*this);
for (ShaderType shaderType : getExecutable().getLinkedShaderStages()) // If separable program objects are in use, the set of attributes captured is taken
// from the program object active on the last vertex processing stage.
Program *tfProgram = mState.mPrograms[ShaderType::Geometry];
if (!tfProgram)
{ {
Program *program = mState.mPrograms[shaderType]; tfProgram = mState.mPrograms[ShaderType::Vertex];
ASSERT(program); }
if (!program->linkMergedVaryings(context, mergedVaryings, &varyingPacking))
{ const std::vector<std::string> &transformFeedbackVaryingNames =
return angle::Result::Stop; tfProgram->getState().getTransformFeedbackVaryingNames();
}
if (!mState.mExecutable->linkMergedVaryings(context, *this, mergedVaryings,
transformFeedbackVaryingNames, false,
&varyingPacking))
{
return angle::Result::Stop;
} }
} }
......
...@@ -109,6 +109,32 @@ bool InterfaceVariablesMatch(const sh::ShaderVariable &front, const sh::ShaderVa ...@@ -109,6 +109,32 @@ bool InterfaceVariablesMatch(const sh::ShaderVariable &front, const sh::ShaderVa
const std::string &frontName = front.isShaderIOBlock ? front.structName : front.name; const std::string &frontName = front.isShaderIOBlock ? front.structName : front.name;
return backName == frontName; return backName == frontName;
} }
GLint GetMaxShaderInputVectors(const Caps &caps, ShaderType shaderStage)
{
switch (shaderStage)
{
case ShaderType::Geometry:
return caps.maxGeometryInputComponents / 4;
case ShaderType::Fragment:
return caps.maxFragmentInputComponents / 4;
default:
return std::numeric_limits<GLint>::max();
}
}
GLint GetMaxShaderOutputVectors(const Caps &caps, ShaderType shaderStage)
{
switch (shaderStage)
{
case ShaderType::Vertex:
return caps.maxVertexOutputComponents / 4;
case ShaderType::Geometry:
return caps.maxGeometryOutputComponents / 4;
default:
return std::numeric_limits<GLint>::max();
}
}
} // anonymous namespace } // anonymous namespace
// Implementation of VaryingInShaderRef // Implementation of VaryingInShaderRef
...@@ -719,6 +745,8 @@ void VaryingPacking::collectTFVarying(const std::string &tfVarying, ...@@ -719,6 +745,8 @@ void VaryingPacking::collectTFVarying(const std::string &tfVarying,
bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog, bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
GLint maxVaryingVectors, GLint maxVaryingVectors,
PackMode packMode, PackMode packMode,
ShaderType frontShaderStage,
ShaderType backShaderStage,
const ProgramMergedVaryings &mergedVaryings, const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings, const std::vector<std::string> &tfVaryings,
const bool isSeparableProgram) const bool isSeparableProgram)
...@@ -732,6 +760,12 @@ bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog, ...@@ -732,6 +760,12 @@ bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
const sh::ShaderVariable *input = ref.frontShader; const sh::ShaderVariable *input = ref.frontShader;
const sh::ShaderVariable *output = ref.backShader; const sh::ShaderVariable *output = ref.backShader;
if ((input && ref.frontShaderStage != frontShaderStage) ||
(output && ref.backShaderStage != backShaderStage))
{
continue;
}
const bool isActiveBuiltInInput = input && input->isBuiltIn() && input->active; const bool isActiveBuiltInInput = input && input->isBuiltIn() && input->active;
const bool isActiveBuiltInOutput = output && output->isBuiltIn() && output->active; const bool isActiveBuiltInOutput = output && output->isBuiltIn() && output->active;
...@@ -834,6 +868,111 @@ bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog, ...@@ -834,6 +868,111 @@ bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
return true; return true;
} }
// ProgramVaryingPacking implementation.
ProgramVaryingPacking::ProgramVaryingPacking() = default;
ProgramVaryingPacking::~ProgramVaryingPacking() = default;
const VaryingPacking &ProgramVaryingPacking::getInputPacking(ShaderType backShaderStage) const
{
ShaderType frontShaderStage = mBackToFrontStageMap[backShaderStage];
// If there's a missing shader stage, return the compute shader packing which is always empty.
if (frontShaderStage == ShaderType::InvalidEnum)
{
ASSERT(mVaryingPackings[ShaderType::Compute].getMaxSemanticIndex() == 0);
return mVaryingPackings[ShaderType::Compute];
}
return mVaryingPackings[frontShaderStage];
}
const VaryingPacking &ProgramVaryingPacking::getOutputPacking(ShaderType frontShaderStage) const
{
return mVaryingPackings[frontShaderStage];
}
bool ProgramVaryingPacking::collectAndPackUserVaryings(InfoLog &infoLog,
const Caps &caps,
PackMode packMode,
const ShaderBitSet &attachedShadersMask,
const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings,
bool isSeparableProgram)
{
mBackToFrontStageMap.fill(ShaderType::InvalidEnum);
ShaderBitSet attachedShaders = attachedShadersMask;
ShaderType frontShaderStage = attachedShaders.first();
attachedShaders[frontShaderStage] = false;
// Special case for start-after-vertex.
if (frontShaderStage != ShaderType::Vertex)
{
ASSERT(isSeparableProgram);
ShaderType emulatedFrontShaderStage = ShaderType::Vertex;
ShaderType backShaderStage = frontShaderStage;
if (!mVaryingPackings[emulatedFrontShaderStage].collectAndPackUserVaryings(
infoLog, GetMaxShaderInputVectors(caps, backShaderStage), packMode,
ShaderType::InvalidEnum, backShaderStage, mergedVaryings, tfVaryings,
isSeparableProgram))
{
return false;
}
mBackToFrontStageMap[backShaderStage] = emulatedFrontShaderStage;
}
// Process input/output shader pairs.
for (ShaderType backShaderStage : attachedShaders)
{
GLint maxVaryingVectors;
if (frontShaderStage == ShaderType::Vertex && backShaderStage == ShaderType::Fragment)
{
maxVaryingVectors = caps.maxVaryingVectors;
}
else
{
GLint outputVaryingsMax = GetMaxShaderOutputVectors(caps, frontShaderStage);
GLint inputVaryingsMax = GetMaxShaderInputVectors(caps, backShaderStage);
maxVaryingVectors = std::min(inputVaryingsMax, outputVaryingsMax);
}
ASSERT(maxVaryingVectors > 0 && maxVaryingVectors < std::numeric_limits<GLint>::max());
if (!mVaryingPackings[frontShaderStage].collectAndPackUserVaryings(
infoLog, maxVaryingVectors, packMode, frontShaderStage, backShaderStage,
mergedVaryings, tfVaryings, isSeparableProgram))
{
return false;
}
mBackToFrontStageMap[backShaderStage] = frontShaderStage;
frontShaderStage = backShaderStage;
}
// Special case for stop-before-fragment.
if (frontShaderStage != ShaderType::Fragment)
{
ASSERT(isSeparableProgram);
if (!mVaryingPackings[frontShaderStage].collectAndPackUserVaryings(
infoLog, GetMaxShaderOutputVectors(caps, frontShaderStage), packMode,
frontShaderStage, ShaderType::InvalidEnum, mergedVaryings, tfVaryings,
isSeparableProgram))
{
return false;
}
ShaderType emulatedBackShaderStage = ShaderType::Fragment;
mBackToFrontStageMap[emulatedBackShaderStage] = frontShaderStage;
}
return true;
}
ProgramMergedVaryings GetMergedVaryingsFromShaders(const HasAttachedShaders &programOrPipeline) ProgramMergedVaryings GetMergedVaryingsFromShaders(const HasAttachedShaders &programOrPipeline)
{ {
Shader *frontShader = nullptr; Shader *frontShader = nullptr;
......
...@@ -24,6 +24,7 @@ namespace gl ...@@ -24,6 +24,7 @@ namespace gl
{ {
class HasAttachedShaders; class HasAttachedShaders;
class InfoLog; class InfoLog;
struct Caps;
struct ProgramVaryingRef; struct ProgramVaryingRef;
using ProgramMergedVaryings = std::vector<ProgramVaryingRef>; using ProgramMergedVaryings = std::vector<ProgramVaryingRef>;
...@@ -206,12 +207,14 @@ class VaryingPacking final : angle::NonCopyable ...@@ -206,12 +207,14 @@ class VaryingPacking final : angle::NonCopyable
VaryingPacking(); VaryingPacking();
~VaryingPacking(); ~VaryingPacking();
bool collectAndPackUserVaryings(InfoLog &infoLog, ANGLE_NO_DISCARD bool collectAndPackUserVaryings(InfoLog &infoLog,
GLint maxVaryingVectors, GLint maxVaryingVectors,
PackMode packMode, PackMode packMode,
const ProgramMergedVaryings &mergedVaryings, ShaderType frontShaderStage,
const std::vector<std::string> &tfVaryings, ShaderType backShaderStage,
const bool isSeparableProgram); const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings,
const bool isSeparableProgram);
struct Register struct Register
{ {
...@@ -237,7 +240,7 @@ class VaryingPacking final : angle::NonCopyable ...@@ -237,7 +240,7 @@ class VaryingPacking final : angle::NonCopyable
return mInactiveVaryingMappedNames; return mInactiveVaryingMappedNames;
} }
const ShaderMap<std::vector<std::string>> &getActiveOutputBuiltIns() const const ShaderMap<std::vector<std::string>> &getActiveOutputBuiltInNames() const
{ {
return mActiveOutputBuiltIns; return mActiveOutputBuiltIns;
} }
...@@ -288,6 +291,31 @@ class VaryingPacking final : angle::NonCopyable ...@@ -288,6 +291,31 @@ class VaryingPacking final : angle::NonCopyable
ShaderMap<std::vector<std::string>> mActiveOutputBuiltIns; ShaderMap<std::vector<std::string>> mActiveOutputBuiltIns;
}; };
class ProgramVaryingPacking final : angle::NonCopyable
{
public:
ProgramVaryingPacking();
~ProgramVaryingPacking();
const VaryingPacking &getInputPacking(ShaderType backShaderStage) const;
const VaryingPacking &getOutputPacking(ShaderType frontShaderStage) const;
ANGLE_NO_DISCARD bool collectAndPackUserVaryings(InfoLog &infoLog,
const Caps &caps,
PackMode packMode,
const ShaderBitSet &attachedShadersMask,
const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings,
bool isSeparableProgram);
private:
// Indexed by the front shader.
ShaderMap<VaryingPacking> mVaryingPackings;
// Looks up the front stage from the back stage.
ShaderMap<ShaderType> mBackToFrontStageMap;
};
// Takes an abstract handle to a program or pipeline. // Takes an abstract handle to a program or pipeline.
ProgramMergedVaryings GetMergedVaryingsFromShaders(const HasAttachedShaders &programOrPipeline); ProgramMergedVaryings GetMergedVaryingsFromShaders(const HasAttachedShaders &programOrPipeline);
} // namespace gl } // namespace gl
......
...@@ -46,7 +46,8 @@ class VaryingPackingTest : public ::testing::TestWithParam<GLuint> ...@@ -46,7 +46,8 @@ class VaryingPackingTest : public ::testing::TestWithParam<GLuint>
VaryingPacking varyingPacking; VaryingPacking varyingPacking;
return varyingPacking.collectAndPackUserVaryings( return varyingPacking.collectAndPackUserVaryings(
infoLog, maxVaryings, packMode, mergedVaryings, transformFeedbackVaryings, false); infoLog, maxVaryings, packMode, ShaderType::Vertex, ShaderType::Fragment,
mergedVaryings, transformFeedbackVaryings, false);
} }
// Uses the "relaxed" ANGLE packing mode. // Uses the "relaxed" ANGLE packing mode.
......
...@@ -13,7 +13,7 @@ namespace rx ...@@ -13,7 +13,7 @@ namespace rx
angle::Result ProgramPipelineImpl::link(const gl::Context *context, angle::Result ProgramPipelineImpl::link(const gl::Context *context,
const gl::ProgramMergedVaryings &mergedVaryings, const gl::ProgramMergedVaryings &mergedVaryings,
const gl::VaryingPacking &varyingPacking) const gl::ProgramVaryingPacking &varyingPacking)
{ {
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -25,7 +25,7 @@ class ProgramPipelineImpl : public angle::NonCopyable ...@@ -25,7 +25,7 @@ class ProgramPipelineImpl : public angle::NonCopyable
virtual angle::Result link(const gl::Context *context, virtual angle::Result link(const gl::Context *context,
const gl::ProgramMergedVaryings &mergedVaryings, const gl::ProgramMergedVaryings &mergedVaryings,
const gl::VaryingPacking &varyingPacking); const gl::ProgramVaryingPacking &varyingPacking);
const gl::ProgramPipelineState &getState() const { return mState; } const gl::ProgramPipelineState &getState() const { return mState; }
......
...@@ -2112,11 +2112,14 @@ std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context, ...@@ -2112,11 +2112,14 @@ std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
} }
} }
const gl::VaryingPacking &varyingPacking =
resources.varyingPacking.getOutputPacking(gl::ShaderType::Vertex);
ProgramD3DMetadata metadata(mRenderer, shadersD3D, context->getClientType()); ProgramD3DMetadata metadata(mRenderer, shadersD3D, context->getClientType());
BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking); BuiltinVaryingsD3D builtins(metadata, varyingPacking);
mDynamicHLSL->generateShaderLinkHLSL(context->getCaps(), mState, metadata, mDynamicHLSL->generateShaderLinkHLSL(context->getCaps(), mState, metadata, varyingPacking,
resources.varyingPacking, builtins, &mShaderHLSL); builtins, &mShaderHLSL);
const ShaderD3D *vertexShader = shadersD3D[gl::ShaderType::Vertex]; const ShaderD3D *vertexShader = shadersD3D[gl::ShaderType::Vertex];
mUsesPointSize = vertexShader && vertexShader->usesPointSize(); mUsesPointSize = vertexShader && vertexShader->usesPointSize();
...@@ -2132,7 +2135,7 @@ std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context, ...@@ -2132,7 +2135,7 @@ std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
if (mRenderer->getMajorShaderModel() >= 4) if (mRenderer->getMajorShaderModel() >= 4)
{ {
mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble( mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled, varyingPacking, builtins, mHasANGLEMultiviewEnabled,
metadata.canSelectViewInVertexShader()); metadata.canSelectViewInVertexShader());
} }
...@@ -2140,7 +2143,7 @@ std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context, ...@@ -2140,7 +2143,7 @@ std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
defineUniformsAndAssignRegisters(); defineUniformsAndAssignRegisters();
gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::ShaderType::Vertex]); gatherTransformFeedbackVaryings(varyingPacking, builtins[gl::ShaderType::Vertex]);
linkResources(resources); linkResources(resources);
......
...@@ -476,7 +476,7 @@ bool IsFirstRegisterOfVarying(const gl::PackedVaryingRegister &varyingReg, bool ...@@ -476,7 +476,7 @@ bool IsFirstRegisterOfVarying(const gl::PackedVaryingRegister &varyingReg, bool
// Calculates XFB layout qualifier arguments for each tranform feedback varying. Stores calculated // Calculates XFB layout qualifier arguments for each tranform feedback varying. Stores calculated
// values for the SPIR-V transformation. // values for the SPIR-V transformation.
void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programState, void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programState,
const gl::ProgramLinkedResources &resources, const gl::VaryingPacking &varyingPacking,
std::string *xfbShaderSource, std::string *xfbShaderSource,
uint32_t *locationsUsedForXfbExtensionOut) uint32_t *locationsUsedForXfbExtensionOut)
{ {
...@@ -500,8 +500,8 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt ...@@ -500,8 +500,8 @@ void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programSt
// clip space and prerotation), so it cannot be captured directly. // clip space and prerotation), so it cannot be captured directly.
// //
// The rest of the builtins are captured by decorating gl_PerVertex directly. // The rest of the builtins are captured by decorating gl_PerVertex directly.
uint32_t xfbVaryingLocation = resources.varyingPacking.getMaxSemanticIndex() + uint32_t xfbVaryingLocation =
++(*locationsUsedForXfbExtensionOut); varyingPacking.getMaxSemanticIndex() + ++(*locationsUsedForXfbExtensionOut);
std::string xfbVaryingName = kXfbBuiltInPrefix + tfVaryingName; std::string xfbVaryingName = kXfbBuiltInPrefix + tfVaryingName;
...@@ -664,7 +664,7 @@ void AssignVaryingLocations(const GlslangSourceOptions &options, ...@@ -664,7 +664,7 @@ void AssignVaryingLocations(const GlslangSourceOptions &options,
// Add an entry for active builtins varyings. This will allow inactive builtins, such as // Add an entry for active builtins varyings. This will allow inactive builtins, such as
// gl_PointSize, gl_ClipDistance etc to be removed. // gl_PointSize, gl_ClipDistance etc to be removed.
const gl::ShaderMap<std::vector<std::string>> &activeOutputBuiltIns = const gl::ShaderMap<std::vector<std::string>> &activeOutputBuiltIns =
varyingPacking.getActiveOutputBuiltIns(); varyingPacking.getActiveOutputBuiltInNames();
for (const std::string &builtInName : activeOutputBuiltIns[shaderType]) for (const std::string &builtInName : activeOutputBuiltIns[shaderType])
{ {
ASSERT(gl::IsBuiltInName(builtInName)); ASSERT(gl::IsBuiltInName(builtInName));
...@@ -690,7 +690,7 @@ void AssignVaryingLocations(const GlslangSourceOptions &options, ...@@ -690,7 +690,7 @@ void AssignVaryingLocations(const GlslangSourceOptions &options,
} }
// Add an entry for gl_PerVertex, for use with transform feedback capture of built-ins. // Add an entry for gl_PerVertex, for use with transform feedback capture of built-ins.
ShaderInterfaceVariableInfo &info = variableInfoMapOut->add(shaderType, "gl_PerVertex"); ShaderInterfaceVariableInfo &info = variableInfoMapOut->addOrGet(shaderType, "gl_PerVertex");
info.activeStages.set(shaderType); info.activeStages.set(shaderType);
} }
...@@ -3813,7 +3813,7 @@ void GlslangGenTransformFeedbackEmulationOutputs(const GlslangSourceOptions &opt ...@@ -3813,7 +3813,7 @@ void GlslangGenTransformFeedbackEmulationOutputs(const GlslangSourceOptions &opt
void GlslangAssignLocations(const GlslangSourceOptions &options, void GlslangAssignLocations(const GlslangSourceOptions &options,
const gl::ProgramExecutable &programExecutable, const gl::ProgramExecutable &programExecutable,
const gl::VaryingPacking &varyingPacking, const gl::ProgramVaryingPacking &varyingPacking,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
const gl::ShaderType frontShaderType, const gl::ShaderType frontShaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
...@@ -3835,16 +3835,27 @@ void GlslangAssignLocations(const GlslangSourceOptions &options, ...@@ -3835,16 +3835,27 @@ void GlslangAssignLocations(const GlslangSourceOptions &options,
if (!programExecutable.hasLinkedShaderStage(gl::ShaderType::Compute)) if (!programExecutable.hasLinkedShaderStage(gl::ShaderType::Compute))
{ {
const gl::VaryingPacking &inputPacking = varyingPacking.getInputPacking(shaderType);
const gl::VaryingPacking &outputPacking = varyingPacking.getOutputPacking(shaderType);
// Assign varying locations. // Assign varying locations.
AssignVaryingLocations(options, varyingPacking, shaderType, frontShaderType, if (shaderType != gl::ShaderType::Vertex)
programInterfaceInfo, variableInfoMapOut); {
AssignVaryingLocations(options, inputPacking, shaderType, frontShaderType,
programInterfaceInfo, variableInfoMapOut);
}
if (shaderType != gl::ShaderType::Fragment)
{
AssignVaryingLocations(options, outputPacking, shaderType, frontShaderType,
programInterfaceInfo, variableInfoMapOut);
}
if (!programExecutable.getLinkedTransformFeedbackVaryings().empty() && if (!programExecutable.getLinkedTransformFeedbackVaryings().empty() &&
options.supportsTransformFeedbackExtension && options.supportsTransformFeedbackExtension &&
(shaderType == programExecutable.getLinkedTransformFeedbackStage())) (shaderType == programExecutable.getLinkedTransformFeedbackStage()))
{ {
AssignTransformFeedbackExtensionQualifiers( AssignTransformFeedbackExtensionQualifiers(
programExecutable, varyingPacking, programExecutable, outputPacking,
programInterfaceInfo->locationsUsedForXfbExtension, shaderType, variableInfoMapOut); programInterfaceInfo->locationsUsedForXfbExtension, shaderType, variableInfoMapOut);
} }
} }
...@@ -3881,7 +3892,7 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options, ...@@ -3881,7 +3892,7 @@ void GlslangGetShaderSource(const GlslangSourceOptions &options,
if (options.supportsTransformFeedbackExtension) if (options.supportsTransformFeedbackExtension)
{ {
GenerateTransformFeedbackExtensionOutputs( GenerateTransformFeedbackExtensionOutputs(
programState, resources, xfbSource, programState, resources.varyingPacking.getOutputPacking(xfbStage), xfbSource,
&programInterfaceInfo->locationsUsedForXfbExtension); &programInterfaceInfo->locationsUsedForXfbExtension);
} }
else if (options.emulateTransformFeedback) else if (options.emulateTransformFeedback)
......
...@@ -173,7 +173,7 @@ void GlslangGenTransformFeedbackEmulationOutputs( ...@@ -173,7 +173,7 @@ void GlslangGenTransformFeedbackEmulationOutputs(
void GlslangAssignLocations(const GlslangSourceOptions &options, void GlslangAssignLocations(const GlslangSourceOptions &options,
const gl::ProgramExecutable &programExecutable, const gl::ProgramExecutable &programExecutable,
const gl::VaryingPacking &varyingPacking, const gl::ProgramVaryingPacking &varyingPacking,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
const gl::ShaderType frontShaderType, const gl::ShaderType frontShaderType,
GlslangProgramInterfaceInfo *programInterfaceInfo, GlslangProgramInterfaceInfo *programInterfaceInfo,
......
...@@ -54,7 +54,7 @@ void ProgramPipelineVk::fillProgramStateMap( ...@@ -54,7 +54,7 @@ void ProgramPipelineVk::fillProgramStateMap(
angle::Result ProgramPipelineVk::link(const gl::Context *glContext, angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
const gl::ProgramMergedVaryings &mergedVaryings, const gl::ProgramMergedVaryings &mergedVaryings,
const gl::VaryingPacking &varyingPacking) const gl::ProgramVaryingPacking &varyingPacking)
{ {
ContextVk *contextVk = vk::GetImpl(glContext); ContextVk *contextVk = vk::GetImpl(glContext);
const gl::State &glState = glContext->getState(); const gl::State &glState = glContext->getState();
...@@ -78,7 +78,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext, ...@@ -78,7 +78,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
// The program interface info must survive across shaders, except // The program interface info must survive across shaders, except
// for some program-specific values. // for some program-specific values.
ProgramVk *programVk = vk::GetImpl(glProgram); ProgramVk *programVk = vk::GetImpl(glProgram);
GlslangProgramInterfaceInfo &programProgramInterfaceInfo = const GlslangProgramInterfaceInfo &programProgramInterfaceInfo =
programVk->getGlslangProgramInterfaceInfo(); programVk->getGlslangProgramInterfaceInfo();
glslangProgramInterfaceInfo.locationsUsedForXfbExtension = glslangProgramInterfaceInfo.locationsUsedForXfbExtension =
programProgramInterfaceInfo.locationsUsedForXfbExtension; programProgramInterfaceInfo.locationsUsedForXfbExtension;
......
...@@ -47,7 +47,7 @@ class ProgramPipelineVk : public ProgramPipelineImpl ...@@ -47,7 +47,7 @@ class ProgramPipelineVk : public ProgramPipelineImpl
angle::Result link(const gl::Context *glContext, angle::Result link(const gl::Context *glContext,
const gl::ProgramMergedVaryings &mergedVaryings, const gl::ProgramMergedVaryings &mergedVaryings,
const gl::VaryingPacking &varyingPacking) override; const gl::ProgramVaryingPacking &varyingPacking) override;
angle::Result updateUniforms(ContextVk *contextVk); angle::Result updateUniforms(ContextVk *contextVk);
......
...@@ -165,7 +165,7 @@ class ProgramVk : public ProgramImpl ...@@ -165,7 +165,7 @@ class ProgramVk : public ProgramImpl
variableInfoMap); variableInfoMap);
} }
GlslangProgramInterfaceInfo &getGlslangProgramInterfaceInfo() const GlslangProgramInterfaceInfo &getGlslangProgramInterfaceInfo()
{ {
return mGlslangProgramInterfaceInfo; return mGlslangProgramInterfaceInfo;
} }
......
...@@ -915,12 +915,13 @@ void RendererVk::ensureCapsInitialized() const ...@@ -915,12 +915,13 @@ void RendererVk::ensureCapsInitialized() const
vk::HasShaderImageAtomicsSupport(this, mNativeExtensions) || vk::HasShaderImageAtomicsSupport(this, mNativeExtensions) ||
getFeatures().exposeNonConformantExtensionsAndVersions.enabled; getFeatures().exposeNonConformantExtensionsAndVersions.enabled;
// Geometry shader is optional. // Geometry shaders are required for ES 3.2.
if (mPhysicalDeviceFeatures.geometryShader) // We can't support GS when we are emulating line raster due to the tricky position varying.
if (mPhysicalDeviceFeatures.geometryShader && !mFeatures.basicGLLineRasterization.enabled)
{ {
// TODO: geometry shader support is incomplete. http://anglebug.com/3571 // TODO: geometry shader support is incomplete. http://anglebug.com/3571
mNativeExtensions.geometryShader = mNativeExtensions.geometryShader =
getFeatures().exposeNonConformantExtensionsAndVersions.enabled; mFeatures.exposeNonConformantExtensionsAndVersions.enabled;
mNativeCaps.maxFramebufferLayers = LimitToInt(limitsVk.maxFramebufferLayers); mNativeCaps.maxFramebufferLayers = LimitToInt(limitsVk.maxFramebufferLayers);
mNativeCaps.layerProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT; mNativeCaps.layerProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
......
...@@ -1632,6 +1632,144 @@ void main() ...@@ -1632,6 +1632,144 @@ void main()
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
// Tests that varying limits work as expected with geometry shaders.
TEST_P(GeometryShaderTest, MaxVaryings)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
// Get appropriate limitations.
GLint maxVertexOutputComponents = 0;
glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &maxVertexOutputComponents);
ASSERT_GT(maxVertexOutputComponents, 0);
GLint maxGeometryInputComponents = 0;
glGetIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &maxGeometryInputComponents);
ASSERT_GT(maxGeometryInputComponents, 0);
GLint maxGeometryOutputComponents = 0;
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &maxGeometryOutputComponents);
ASSERT_GT(maxGeometryOutputComponents, 0);
GLint maxFragmentInputComponents = 0;
glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &maxFragmentInputComponents);
ASSERT_GT(maxFragmentInputComponents, 0);
GLint vertexToGeometryVaryings =
std::min(maxVertexOutputComponents, maxGeometryInputComponents) / 4;
GLint geometryToFragmentVaryings =
std::min(maxGeometryOutputComponents, maxFragmentInputComponents) / 4;
GLint varyingCount = std::min(vertexToGeometryVaryings, geometryToFragmentVaryings);
// Reserve gl_Position;
varyingCount--;
// Create a vertex shader with "varyingCount" outputs.
std::stringstream vsStream;
vsStream << R"(#version 310 es
uniform vec4 uniOne;
in vec4 position;
)";
for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
{
vsStream << "out vec4 v" << varyingIndex << ";\n";
}
vsStream << R"(
void main()
{
gl_Position = position;
)";
for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
{
vsStream << " v" << varyingIndex << " = uniOne * " << varyingIndex << ".0;\n";
}
vsStream << "}";
// Create a GS with "varyingCount" inputs and "varyingCount" outputs.
std::stringstream gsStream;
gsStream << R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (triangles) in;
layout (triangle_strip, max_vertices = 4) out;
)";
for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
{
gsStream << "in vec4 v" << varyingIndex << "[];\n";
}
for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
{
gsStream << "out vec4 o" << varyingIndex << ";\n";
}
gsStream << R"(
void main()
{
for (int n = 0; n < gl_in.length(); n++)
{
gl_Position = gl_in[n].gl_Position;
)";
for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
{
gsStream << " o" << varyingIndex << " = v" << varyingIndex << "[n];\n";
}
gsStream << R"(
EmitVertex();
}
EndPrimitive();
}
)";
// Create a FS with "varyingCount" inputs.
std::stringstream fsStream;
fsStream << R"(#version 310 es
precision mediump float;
out vec4 color;
)";
for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
{
fsStream << "in vec4 o" << varyingIndex << ";\n";
}
fsStream << R"(
void main()
{
color = vec4(0, 1, 0, 1);
)";
for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
{
fsStream << " if (o" << varyingIndex << " != vec4(" << varyingIndex << ".0))\n"
<< " color = vec4(1, 0, 0, 1);\n";
}
fsStream << "}";
const std::string vs = vsStream.str();
const std::string gs = gsStream.str();
const std::string fs = fsStream.str();
ANGLE_GL_PROGRAM_WITH_GS(program, vs.c_str(), gs.c_str(), fs.c_str());
glUseProgram(program);
GLint uniLoc = glGetUniformLocation(program, "uniOne");
ASSERT_NE(-1, uniLoc);
glUniform4f(uniLoc, 1.0f, 1.0f, 1.0f, 1.0f);
drawQuad(program, "position", 0.5f, 1.0f, true);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
ANGLE_INSTANTIATE_TEST_ES3(GeometryShaderTestES3); ANGLE_INSTANTIATE_TEST_ES3(GeometryShaderTestES3);
ANGLE_INSTANTIATE_TEST_ES31_AND(GeometryShaderTest, ANGLE_INSTANTIATE_TEST_ES31_AND(GeometryShaderTest,
WithEmulatedPrerotation(ES31_VULKAN(), 90), WithEmulatedPrerotation(ES31_VULKAN(), 90),
......
...@@ -2657,6 +2657,9 @@ TEST_P(TransformFeedbackTestES32, PrimitivesWrittenAndGenerated) ...@@ -2657,6 +2657,9 @@ TEST_P(TransformFeedbackTestES32, PrimitivesWrittenAndGenerated)
ANGLE_SKIP_TEST_IF(IsVulkan() && IsAMD() && IsWindows()); ANGLE_SKIP_TEST_IF(IsVulkan() && IsAMD() && IsWindows());
ANGLE_SKIP_TEST_IF(IsVulkan() && IsNVIDIA() && IsWindows7()); ANGLE_SKIP_TEST_IF(IsVulkan() && IsNVIDIA() && IsWindows7());
// http://anglebug.com/5539
ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux());
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
......
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