mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-03 14:09:33 +03:00
Group all ProgramExecutable basic data type members into a struct
So that we can load/save with a simple memcpy. Bug: b/275102061 Change-Id: I178404fd72b615174a7a0412ea5482ae2bea2f80 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4785567 Reviewed-by: Roman Lavrov <romanl@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Charlie Lao <cclao@google.com>
This commit is contained in:
committed by
Angle LUCI CQ
parent
cf2c9c5607
commit
c34f83d9a3
@@ -787,6 +787,8 @@ class Range
|
||||
|
||||
typedef Range<int> RangeI;
|
||||
typedef Range<unsigned int> RangeUI;
|
||||
static_assert(std::is_trivially_copyable<RangeUI>(),
|
||||
"RangeUI should be trivial copyable so that we can memcpy");
|
||||
|
||||
struct IndexRange
|
||||
{
|
||||
|
||||
@@ -997,13 +997,13 @@ Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
|
||||
|
||||
bool ProgramState::isSamplerUniformIndex(GLuint index) const
|
||||
{
|
||||
return mExecutable->mSamplerUniformRange.contains(index);
|
||||
return mExecutable->mPODStruct.samplerUniformRange.contains(index);
|
||||
}
|
||||
|
||||
GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
|
||||
{
|
||||
ASSERT(isSamplerUniformIndex(uniformIndex));
|
||||
return uniformIndex - mExecutable->mSamplerUniformRange.low();
|
||||
return uniformIndex - mExecutable->mPODStruct.samplerUniformRange.low();
|
||||
}
|
||||
|
||||
GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
|
||||
@@ -1013,13 +1013,13 @@ GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
|
||||
|
||||
bool ProgramState::isImageUniformIndex(GLuint index) const
|
||||
{
|
||||
return mExecutable->mImageUniformRange.contains(index);
|
||||
return mExecutable->mPODStruct.imageUniformRange.contains(index);
|
||||
}
|
||||
|
||||
GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
|
||||
{
|
||||
ASSERT(isImageUniformIndex(uniformIndex));
|
||||
return uniformIndex - mExecutable->mImageUniformRange.low();
|
||||
return uniformIndex - mExecutable->mPODStruct.imageUniformRange.low();
|
||||
}
|
||||
|
||||
GLuint ProgramState::getAttributeLocation(const std::string &name) const
|
||||
@@ -1364,8 +1364,8 @@ angle::Result Program::linkImpl(const Context *context)
|
||||
gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
|
||||
if (vertexShader)
|
||||
{
|
||||
mState.mNumViews = vertexShader->getNumViews(context);
|
||||
mState.mExecutable->mHasClipDistance = vertexShader->hasClipDistance();
|
||||
mState.mNumViews = vertexShader->getNumViews(context);
|
||||
mState.mExecutable->mPODStruct.hasClipDistance = vertexShader->hasClipDistance();
|
||||
mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
|
||||
}
|
||||
|
||||
@@ -1382,10 +1382,10 @@ angle::Result Program::linkImpl(const Context *context)
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
mState.mExecutable->mHasDiscard = fragmentShader->hasDiscard();
|
||||
mState.mExecutable->mEnablesPerSampleShading =
|
||||
mState.mExecutable->mPODStruct.hasDiscard = fragmentShader->hasDiscard();
|
||||
mState.mExecutable->mPODStruct.enablesPerSampleShading =
|
||||
fragmentShader->enablesPerSampleShading();
|
||||
mState.mExecutable->mAdvancedBlendEquations =
|
||||
mState.mExecutable->mPODStruct.advancedBlendEquations =
|
||||
fragmentShader->getAdvancedBlendEquations();
|
||||
mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
|
||||
}
|
||||
@@ -1884,31 +1884,31 @@ GLint Program::getGeometryShaderMaxVertices() const
|
||||
GLint Program::getTessControlShaderVertices() const
|
||||
{
|
||||
ASSERT(!mLinkingState && mState.mExecutable);
|
||||
return mState.mExecutable->mTessControlShaderVertices;
|
||||
return mState.mExecutable->mPODStruct.tessControlShaderVertices;
|
||||
}
|
||||
|
||||
GLenum Program::getTessGenMode() const
|
||||
{
|
||||
ASSERT(!mLinkingState && mState.mExecutable);
|
||||
return mState.mExecutable->mTessGenMode;
|
||||
return mState.mExecutable->mPODStruct.tessGenMode;
|
||||
}
|
||||
|
||||
GLenum Program::getTessGenPointMode() const
|
||||
{
|
||||
ASSERT(!mLinkingState && mState.mExecutable);
|
||||
return mState.mExecutable->mTessGenPointMode;
|
||||
return mState.mExecutable->mPODStruct.tessGenPointMode;
|
||||
}
|
||||
|
||||
GLenum Program::getTessGenSpacing() const
|
||||
{
|
||||
ASSERT(!mLinkingState && mState.mExecutable);
|
||||
return mState.mExecutable->mTessGenSpacing;
|
||||
return mState.mExecutable->mPODStruct.tessGenSpacing;
|
||||
}
|
||||
|
||||
GLenum Program::getTessGenVertexOrder() const
|
||||
{
|
||||
ASSERT(!mLinkingState && mState.mExecutable);
|
||||
return mState.mExecutable->mTessGenVertexOrder;
|
||||
return mState.mExecutable->mPODStruct.tessGenVertexOrder;
|
||||
}
|
||||
|
||||
const ProgramInput &Program::getInputResource(size_t index) const
|
||||
@@ -2769,7 +2769,7 @@ void Program::setTransformFeedbackVaryings(GLsizei count,
|
||||
mState.mTransformFeedbackVaryingNames[i] = varyings[i];
|
||||
}
|
||||
|
||||
mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
|
||||
mState.mExecutable->mPODStruct.transformFeedbackBufferMode = bufferMode;
|
||||
}
|
||||
|
||||
void Program::getTransformFeedbackVarying(GLuint index,
|
||||
@@ -2968,10 +2968,12 @@ bool Program::linkValidateShaders(const Context *context, InfoLog &infoLog)
|
||||
return false;
|
||||
}
|
||||
|
||||
mState.mExecutable->mGeometryShaderInputPrimitiveType = inputPrimitive.value();
|
||||
mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
|
||||
mState.mExecutable->mGeometryShaderMaxVertices = maxVertices.value();
|
||||
mState.mExecutable->mGeometryShaderInvocations =
|
||||
mState.mExecutable->mPODStruct.geometryShaderInputPrimitiveType =
|
||||
inputPrimitive.value();
|
||||
mState.mExecutable->mPODStruct.geometryShaderOutputPrimitiveType =
|
||||
outputPrimitive.value();
|
||||
mState.mExecutable->mPODStruct.geometryShaderMaxVertices = maxVertices.value();
|
||||
mState.mExecutable->mPODStruct.geometryShaderInvocations =
|
||||
geometryShader->getGeometryShaderInvocations(context);
|
||||
}
|
||||
|
||||
@@ -2994,7 +2996,7 @@ bool Program::linkValidateShaders(const Context *context, InfoLog &infoLog)
|
||||
return false;
|
||||
}
|
||||
|
||||
mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
|
||||
mState.mExecutable->mPODStruct.tessControlShaderVertices = tcsShaderVertices;
|
||||
}
|
||||
|
||||
Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
|
||||
@@ -3017,11 +3019,12 @@ bool Program::linkValidateShaders(const Context *context, InfoLog &infoLog)
|
||||
return false;
|
||||
}
|
||||
|
||||
mState.mExecutable->mTessGenMode = tesPrimitiveMode;
|
||||
mState.mExecutable->mTessGenSpacing = tessEvaluationShader->getTessGenSpacing(context);
|
||||
mState.mExecutable->mTessGenVertexOrder =
|
||||
mState.mExecutable->mPODStruct.tessGenMode = tesPrimitiveMode;
|
||||
mState.mExecutable->mPODStruct.tessGenSpacing =
|
||||
tessEvaluationShader->getTessGenSpacing(context);
|
||||
mState.mExecutable->mPODStruct.tessGenVertexOrder =
|
||||
tessEvaluationShader->getTessGenVertexOrder(context);
|
||||
mState.mExecutable->mTessGenPointMode =
|
||||
mState.mExecutable->mPODStruct.tessGenPointMode =
|
||||
tessEvaluationShader->getTessGenPointMode(context);
|
||||
}
|
||||
}
|
||||
@@ -3295,8 +3298,8 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(mState.mExecutable->mAttributesTypeMask.none());
|
||||
ASSERT(mState.mExecutable->mAttributesMask.none());
|
||||
ASSERT(mState.mExecutable->mPODStruct.attributesTypeMask.none());
|
||||
ASSERT(mState.mExecutable->mPODStruct.attributesMask.none());
|
||||
|
||||
// Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
|
||||
// shader versions we're only processing active attributes to begin with.
|
||||
@@ -3328,16 +3331,16 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
// Built-in active program inputs don't have a bound attribute.
|
||||
if (!attribute.isBuiltIn())
|
||||
{
|
||||
mState.mExecutable->mActiveAttribLocationsMask.set(location);
|
||||
mState.mExecutable->mMaxActiveAttribLocation =
|
||||
std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
|
||||
mState.mExecutable->mPODStruct.activeAttribLocationsMask.set(location);
|
||||
mState.mExecutable->mPODStruct.maxActiveAttribLocation =
|
||||
std::max(mState.mExecutable->mPODStruct.maxActiveAttribLocation, location + 1);
|
||||
|
||||
ComponentType componentType =
|
||||
GLenumToComponentType(VariableComponentType(attribute.getType()));
|
||||
|
||||
SetComponentTypeMask(componentType, location,
|
||||
&mState.mExecutable->mAttributesTypeMask);
|
||||
mState.mExecutable->mAttributesMask.set(location);
|
||||
&mState.mExecutable->mPODStruct.attributesTypeMask);
|
||||
mState.mExecutable->mPODStruct.attributesMask.set(location);
|
||||
|
||||
location++;
|
||||
}
|
||||
|
||||
@@ -273,42 +273,22 @@ void LoadUniforms(BinaryInputStream *stream,
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
ProgramExecutable::ProgramExecutable()
|
||||
: mMaxActiveAttribLocation(0),
|
||||
mAttributesTypeMask(0),
|
||||
mAttributesMask(0),
|
||||
mActiveSamplerRefCounts{},
|
||||
mCanDrawWith(false),
|
||||
mYUVOutput(false),
|
||||
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
|
||||
mDefaultUniformRange(0, 0),
|
||||
mSamplerUniformRange(0, 0),
|
||||
mImageUniformRange(0, 0),
|
||||
mAtomicCounterUniformRange(0, 0),
|
||||
mFragmentInoutRange(0, 0),
|
||||
mHasClipDistance(false),
|
||||
mHasDiscard(false),
|
||||
mEnablesPerSampleShading(false),
|
||||
// [GL_EXT_geometry_shader] Table 20.22
|
||||
mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
|
||||
mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
|
||||
mGeometryShaderInvocations(1),
|
||||
mGeometryShaderMaxVertices(0),
|
||||
mTessControlShaderVertices(0),
|
||||
mTessGenMode(GL_NONE),
|
||||
mTessGenSpacing(GL_NONE),
|
||||
mTessGenVertexOrder(GL_NONE),
|
||||
mTessGenPointMode(GL_NONE)
|
||||
ProgramExecutable::PODStruct::PODStruct() = default;
|
||||
ProgramExecutable::PODStruct::PODStruct(const PODStruct &other) = default;
|
||||
|
||||
ProgramExecutable::ProgramExecutable() : mActiveSamplerRefCounts{}, mCanDrawWith(false)
|
||||
{
|
||||
memset(&mPODStruct, 0, sizeof(mPODStruct));
|
||||
mPODStruct.geometryShaderInputPrimitiveType = PrimitiveMode::Triangles;
|
||||
mPODStruct.geometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
|
||||
mPODStruct.geometryShaderInvocations = 1;
|
||||
mPODStruct.transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS;
|
||||
|
||||
reset(true);
|
||||
}
|
||||
|
||||
ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
|
||||
: mLinkedShaderStages(other.mLinkedShaderStages),
|
||||
mActiveAttribLocationsMask(other.mActiveAttribLocationsMask),
|
||||
mMaxActiveAttribLocation(other.mMaxActiveAttribLocation),
|
||||
mAttributesTypeMask(other.mAttributesTypeMask),
|
||||
mAttributesMask(other.mAttributesMask),
|
||||
: mPODStruct(other.mPODStruct),
|
||||
mActiveSamplersMask(other.mActiveSamplersMask),
|
||||
mActiveSamplerRefCounts(other.mActiveSamplerRefCounts),
|
||||
mActiveSamplerTypes(other.mActiveSamplerTypes),
|
||||
@@ -321,27 +301,16 @@ ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
|
||||
mOutputVariables(other.mOutputVariables),
|
||||
mOutputLocations(other.mOutputLocations),
|
||||
mSecondaryOutputLocations(other.mSecondaryOutputLocations),
|
||||
mYUVOutput(other.mYUVOutput),
|
||||
mProgramInputs(other.mProgramInputs),
|
||||
mLinkedTransformFeedbackVaryings(other.mLinkedTransformFeedbackVaryings),
|
||||
mTransformFeedbackStrides(other.mTransformFeedbackStrides),
|
||||
mTransformFeedbackBufferMode(other.mTransformFeedbackBufferMode),
|
||||
mUniforms(other.mUniforms),
|
||||
mUniformNames(other.mUniformNames),
|
||||
mUniformMappedNames(other.mUniformMappedNames),
|
||||
mDefaultUniformRange(other.mDefaultUniformRange),
|
||||
mSamplerUniformRange(other.mSamplerUniformRange),
|
||||
mImageUniformRange(other.mImageUniformRange),
|
||||
mAtomicCounterUniformRange(other.mAtomicCounterUniformRange),
|
||||
mUniformBlocks(other.mUniformBlocks),
|
||||
mActiveUniformBlockBindings(other.mActiveUniformBlockBindings),
|
||||
mAtomicCounterBuffers(other.mAtomicCounterBuffers),
|
||||
mShaderStorageBlocks(other.mShaderStorageBlocks),
|
||||
mFragmentInoutRange(other.mFragmentInoutRange),
|
||||
mHasClipDistance(other.mHasClipDistance),
|
||||
mHasDiscard(other.mHasDiscard),
|
||||
mEnablesPerSampleShading(other.mEnablesPerSampleShading),
|
||||
mAdvancedBlendEquations(other.mAdvancedBlendEquations)
|
||||
mShaderStorageBlocks(other.mShaderStorageBlocks)
|
||||
{
|
||||
reset(true);
|
||||
}
|
||||
@@ -354,10 +323,37 @@ void ProgramExecutable::reset(bool clearInfoLog)
|
||||
{
|
||||
resetInfoLog();
|
||||
}
|
||||
mActiveAttribLocationsMask.reset();
|
||||
mAttributesTypeMask.reset();
|
||||
mAttributesMask.reset();
|
||||
mMaxActiveAttribLocation = 0;
|
||||
|
||||
mPODStruct.activeAttribLocationsMask.reset();
|
||||
mPODStruct.attributesTypeMask.reset();
|
||||
mPODStruct.attributesMask.reset();
|
||||
mPODStruct.maxActiveAttribLocation = 0;
|
||||
mPODStruct.activeOutputVariablesMask.reset();
|
||||
|
||||
mPODStruct.defaultUniformRange = RangeUI(0, 0);
|
||||
mPODStruct.samplerUniformRange = RangeUI(0, 0);
|
||||
mPODStruct.imageUniformRange = RangeUI(0, 0);
|
||||
mPODStruct.atomicCounterUniformRange = RangeUI(0, 0);
|
||||
mPODStruct.fragmentInoutRange = RangeUI(0, 0);
|
||||
|
||||
mPODStruct.hasClipDistance = false;
|
||||
mPODStruct.hasDiscard = false;
|
||||
mPODStruct.enablesPerSampleShading = false;
|
||||
mPODStruct.hasYUVOutput = false;
|
||||
|
||||
mPODStruct.advancedBlendEquations.reset();
|
||||
|
||||
mPODStruct.geometryShaderInputPrimitiveType = PrimitiveMode::Triangles;
|
||||
mPODStruct.geometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
|
||||
mPODStruct.geometryShaderInvocations = 1;
|
||||
mPODStruct.geometryShaderMaxVertices = 0;
|
||||
|
||||
mPODStruct.tessControlShaderVertices = 0;
|
||||
mPODStruct.tessGenMode = GL_NONE;
|
||||
mPODStruct.tessGenSpacing = GL_NONE;
|
||||
mPODStruct.tessGenVertexOrder = GL_NONE;
|
||||
mPODStruct.tessGenPointMode = GL_NONE;
|
||||
mPODStruct.drawBufferTypeMask.reset();
|
||||
|
||||
mActiveSamplersMask.reset();
|
||||
mActiveSamplerRefCounts = {};
|
||||
@@ -379,36 +375,11 @@ void ProgramExecutable::reset(bool clearInfoLog)
|
||||
mAtomicCounterBuffers.clear();
|
||||
mOutputVariables.clear();
|
||||
mOutputLocations.clear();
|
||||
mActiveOutputVariablesMask.reset();
|
||||
mSecondaryOutputLocations.clear();
|
||||
mYUVOutput = false;
|
||||
mSamplerBindings.clear();
|
||||
mImageBindings.clear();
|
||||
|
||||
mDefaultUniformRange = RangeUI(0, 0);
|
||||
mSamplerUniformRange = RangeUI(0, 0);
|
||||
mImageUniformRange = RangeUI(0, 0);
|
||||
mAtomicCounterUniformRange = RangeUI(0, 0);
|
||||
|
||||
mFragmentInoutRange = RangeUI(0, 0);
|
||||
mHasClipDistance = false;
|
||||
mHasDiscard = false;
|
||||
mEnablesPerSampleShading = false;
|
||||
mAdvancedBlendEquations.reset();
|
||||
|
||||
mGeometryShaderInputPrimitiveType = PrimitiveMode::Triangles;
|
||||
mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
|
||||
mGeometryShaderInvocations = 1;
|
||||
mGeometryShaderMaxVertices = 0;
|
||||
|
||||
mTessControlShaderVertices = 0;
|
||||
mTessGenMode = GL_NONE;
|
||||
mTessGenSpacing = GL_NONE;
|
||||
mTessGenVertexOrder = GL_NONE;
|
||||
mTessGenPointMode = GL_NONE;
|
||||
|
||||
mOutputVariableTypes.clear();
|
||||
mDrawBufferTypeMask.reset();
|
||||
}
|
||||
|
||||
void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
@@ -416,35 +387,11 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
|
||||
"Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
|
||||
"mask fit into 32 bits each");
|
||||
mAttributesTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
|
||||
mAttributesMask = gl::AttributesMask(stream->readInt<uint32_t>());
|
||||
mActiveAttribLocationsMask = gl::AttributesMask(stream->readInt<uint32_t>());
|
||||
mMaxActiveAttribLocation = stream->readInt<unsigned int>();
|
||||
static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
|
||||
"All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
|
||||
"into 32 bits each");
|
||||
|
||||
unsigned int fragmentInoutRangeLow = stream->readInt<uint32_t>();
|
||||
unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>();
|
||||
mFragmentInoutRange = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh);
|
||||
|
||||
mHasClipDistance = stream->readBool();
|
||||
|
||||
mHasDiscard = stream->readBool();
|
||||
mEnablesPerSampleShading = stream->readBool();
|
||||
|
||||
static_assert(sizeof(mAdvancedBlendEquations.bits()) == sizeof(uint32_t));
|
||||
mAdvancedBlendEquations = BlendEquationBitSet(stream->readInt<uint32_t>());
|
||||
|
||||
mLinkedShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
|
||||
|
||||
mGeometryShaderInputPrimitiveType = stream->readEnum<PrimitiveMode>();
|
||||
mGeometryShaderOutputPrimitiveType = stream->readEnum<PrimitiveMode>();
|
||||
mGeometryShaderInvocations = stream->readInt<int>();
|
||||
mGeometryShaderMaxVertices = stream->readInt<int>();
|
||||
|
||||
mTessControlShaderVertices = stream->readInt<int>();
|
||||
mTessGenMode = stream->readInt<GLenum>();
|
||||
mTessGenSpacing = stream->readInt<GLenum>();
|
||||
mTessGenVertexOrder = stream->readInt<GLenum>();
|
||||
mTessGenPointMode = stream->readInt<GLenum>();
|
||||
stream->readBytes(reinterpret_cast<unsigned char *>(&mPODStruct), sizeof(mPODStruct));
|
||||
|
||||
LoadProgramInputs(stream, &mProgramInputs);
|
||||
LoadUniforms(stream, &mUniforms, &mUniformNames, &mUniformMappedNames);
|
||||
@@ -494,8 +441,6 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
varying.arrayIndex = stream->readInt<GLuint>();
|
||||
}
|
||||
|
||||
mTransformFeedbackBufferMode = stream->readInt<GLint>();
|
||||
|
||||
size_t outputCount = stream->readInt<size_t>();
|
||||
ASSERT(getOutputVariables().empty());
|
||||
mOutputVariables.resize(outputCount);
|
||||
@@ -518,9 +463,6 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
stream->readBool(&locationData.ignored);
|
||||
}
|
||||
|
||||
mActiveOutputVariablesMask =
|
||||
gl::DrawBufferMask(stream->readInt<gl::DrawBufferMask::value_type>());
|
||||
|
||||
size_t outputTypeCount = stream->readInt<size_t>();
|
||||
mOutputVariableTypes.resize(outputTypeCount);
|
||||
for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
|
||||
@@ -528,13 +470,6 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
mOutputVariableTypes[outputIndex] = stream->readInt<GLenum>();
|
||||
}
|
||||
|
||||
static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
|
||||
"All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
|
||||
"into 32 bits each");
|
||||
mDrawBufferTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
|
||||
|
||||
stream->readBool(&mYUVOutput);
|
||||
|
||||
size_t secondaryOutputVarCount = stream->readInt<size_t>();
|
||||
ASSERT(mSecondaryOutputLocations.empty());
|
||||
mSecondaryOutputLocations.resize(secondaryOutputVarCount);
|
||||
@@ -546,14 +481,6 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
stream->readBool(&locationData.ignored);
|
||||
}
|
||||
|
||||
unsigned int defaultUniformRangeLow = stream->readInt<unsigned int>();
|
||||
unsigned int defaultUniformRangeHigh = stream->readInt<unsigned int>();
|
||||
mDefaultUniformRange = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh);
|
||||
|
||||
unsigned int samplerRangeLow = stream->readInt<unsigned int>();
|
||||
unsigned int samplerRangeHigh = stream->readInt<unsigned int>();
|
||||
mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh);
|
||||
|
||||
size_t samplerCount = stream->readInt<size_t>();
|
||||
ASSERT(mSamplerBindings.empty());
|
||||
mSamplerBindings.resize(samplerCount);
|
||||
@@ -567,10 +494,6 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
samplerBinding.boundTextureUnits.resize(bindingCount, 0);
|
||||
}
|
||||
|
||||
unsigned int imageRangeLow = stream->readInt<unsigned int>();
|
||||
unsigned int imageRangeHigh = stream->readInt<unsigned int>();
|
||||
mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh);
|
||||
|
||||
size_t imageBindingCount = stream->readInt<size_t>();
|
||||
ASSERT(mImageBindings.empty());
|
||||
mImageBindings.resize(imageBindingCount);
|
||||
@@ -586,15 +509,11 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int atomicCounterRangeLow = stream->readInt<unsigned int>();
|
||||
unsigned int atomicCounterRangeHigh = stream->readInt<unsigned int>();
|
||||
mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
|
||||
|
||||
// These values are currently only used by PPOs, so only load them when the program is marked
|
||||
// separable to save memory.
|
||||
if (isSeparable)
|
||||
{
|
||||
for (ShaderType shaderType : mLinkedShaderStages)
|
||||
for (ShaderType shaderType : getLinkedShaderStages())
|
||||
{
|
||||
mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
|
||||
for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
|
||||
@@ -625,33 +544,12 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
||||
{
|
||||
static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
|
||||
"All bits of mAttributesTypeMask types and mask fit into 32 bits each");
|
||||
stream->writeInt(static_cast<uint32_t>(mAttributesTypeMask.to_ulong()));
|
||||
stream->writeInt(static_cast<uint32_t>(mAttributesMask.to_ulong()));
|
||||
stream->writeInt(static_cast<uint32_t>(mActiveAttribLocationsMask.to_ulong()));
|
||||
stream->writeInt(mMaxActiveAttribLocation);
|
||||
static_assert(
|
||||
IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
|
||||
"All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
|
||||
|
||||
stream->writeInt(mFragmentInoutRange.low());
|
||||
stream->writeInt(mFragmentInoutRange.high());
|
||||
|
||||
stream->writeBool(mHasClipDistance);
|
||||
|
||||
stream->writeBool(mHasDiscard);
|
||||
stream->writeBool(mEnablesPerSampleShading);
|
||||
stream->writeInt(mAdvancedBlendEquations.bits());
|
||||
|
||||
stream->writeInt(mLinkedShaderStages.bits());
|
||||
|
||||
ASSERT(mGeometryShaderInvocations >= 1 && mGeometryShaderMaxVertices >= 0);
|
||||
stream->writeEnum(mGeometryShaderInputPrimitiveType);
|
||||
stream->writeEnum(mGeometryShaderOutputPrimitiveType);
|
||||
stream->writeInt(mGeometryShaderInvocations);
|
||||
stream->writeInt(mGeometryShaderMaxVertices);
|
||||
|
||||
stream->writeInt(mTessControlShaderVertices);
|
||||
stream->writeInt(mTessGenMode);
|
||||
stream->writeInt(mTessGenSpacing);
|
||||
stream->writeInt(mTessGenVertexOrder);
|
||||
stream->writeInt(mTessGenPointMode);
|
||||
ASSERT(mPODStruct.geometryShaderInvocations >= 1 && mPODStruct.geometryShaderMaxVertices >= 0);
|
||||
stream->writeBytes(reinterpret_cast<const unsigned char *>(&mPODStruct), sizeof(mPODStruct));
|
||||
|
||||
SaveProgramInputs(stream, mProgramInputs);
|
||||
SaveUniforms(stream, mUniforms, mUniformNames, mUniformMappedNames);
|
||||
@@ -684,8 +582,6 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
||||
stream->writeIntOrNegOne(var.arrayIndex);
|
||||
}
|
||||
|
||||
stream->writeInt(getTransformFeedbackBufferMode());
|
||||
|
||||
stream->writeInt(getOutputVariables().size());
|
||||
for (const sh::ShaderVariable &output : getOutputVariables())
|
||||
{
|
||||
@@ -702,21 +598,12 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
||||
stream->writeBool(outputVar.ignored);
|
||||
}
|
||||
|
||||
stream->writeInt(static_cast<int>(mActiveOutputVariablesMask.to_ulong()));
|
||||
|
||||
stream->writeInt(mOutputVariableTypes.size());
|
||||
for (const auto &outputVariableType : mOutputVariableTypes)
|
||||
{
|
||||
stream->writeInt(outputVariableType);
|
||||
}
|
||||
|
||||
static_assert(
|
||||
IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
|
||||
"All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
|
||||
stream->writeInt(static_cast<int>(mDrawBufferTypeMask.to_ulong()));
|
||||
|
||||
stream->writeBool(mYUVOutput);
|
||||
|
||||
stream->writeInt(getSecondaryOutputLocations().size());
|
||||
for (const auto &outputVar : getSecondaryOutputLocations())
|
||||
{
|
||||
@@ -725,12 +612,6 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
||||
stream->writeBool(outputVar.ignored);
|
||||
}
|
||||
|
||||
stream->writeInt(getDefaultUniformRange().low());
|
||||
stream->writeInt(getDefaultUniformRange().high());
|
||||
|
||||
stream->writeInt(getSamplerUniformRange().low());
|
||||
stream->writeInt(getSamplerUniformRange().high());
|
||||
|
||||
stream->writeInt(getSamplerBindings().size());
|
||||
for (const auto &samplerBinding : getSamplerBindings())
|
||||
{
|
||||
@@ -740,9 +621,6 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
||||
stream->writeInt(samplerBinding.boundTextureUnits.size());
|
||||
}
|
||||
|
||||
stream->writeInt(getImageUniformRange().low());
|
||||
stream->writeInt(getImageUniformRange().high());
|
||||
|
||||
stream->writeInt(getImageBindings().size());
|
||||
for (const auto &imageBinding : getImageBindings())
|
||||
{
|
||||
@@ -754,14 +632,11 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
||||
}
|
||||
}
|
||||
|
||||
stream->writeInt(getAtomicCounterUniformRange().low());
|
||||
stream->writeInt(getAtomicCounterUniformRange().high());
|
||||
|
||||
// These values are currently only used by PPOs, so only save them when the program is marked
|
||||
// separable to save memory.
|
||||
if (isSeparable)
|
||||
{
|
||||
for (ShaderType shaderType : mLinkedShaderStages)
|
||||
for (ShaderType shaderType : getLinkedShaderStages())
|
||||
{
|
||||
stream->writeInt(mLinkedOutputVaryings[shaderType].size());
|
||||
for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
|
||||
@@ -803,64 +678,6 @@ std::string ProgramExecutable::getInfoLogString() const
|
||||
return mInfoLog.str();
|
||||
}
|
||||
|
||||
bool ProgramExecutable::isAttribLocationActive(size_t attribLocation) const
|
||||
{
|
||||
ASSERT(attribLocation < mActiveAttribLocationsMask.size());
|
||||
return mActiveAttribLocationsMask[attribLocation];
|
||||
}
|
||||
|
||||
AttributesMask ProgramExecutable::getAttributesMask() const
|
||||
{
|
||||
return mAttributesMask;
|
||||
}
|
||||
|
||||
bool ProgramExecutable::hasDefaultUniforms() const
|
||||
{
|
||||
return !getDefaultUniformRange().empty();
|
||||
}
|
||||
|
||||
bool ProgramExecutable::hasTextures() const
|
||||
{
|
||||
return !getSamplerBindings().empty();
|
||||
}
|
||||
|
||||
bool ProgramExecutable::hasUniformBuffers() const
|
||||
{
|
||||
return !mUniformBlocks.empty();
|
||||
}
|
||||
|
||||
bool ProgramExecutable::hasStorageBuffers() const
|
||||
{
|
||||
return !mShaderStorageBlocks.empty();
|
||||
}
|
||||
|
||||
bool ProgramExecutable::hasAtomicCounterBuffers() const
|
||||
{
|
||||
return !mAtomicCounterBuffers.empty();
|
||||
}
|
||||
|
||||
bool ProgramExecutable::hasImages() const
|
||||
{
|
||||
return !mImageBindings.empty();
|
||||
}
|
||||
|
||||
bool ProgramExecutable::usesFramebufferFetch() const
|
||||
{
|
||||
return (mFragmentInoutRange.length() > 0);
|
||||
}
|
||||
|
||||
GLuint ProgramExecutable::getUniformIndexFromImageIndex(GLuint imageIndex) const
|
||||
{
|
||||
ASSERT(imageIndex < mImageUniformRange.length());
|
||||
return imageIndex + mImageUniformRange.low();
|
||||
}
|
||||
|
||||
GLuint ProgramExecutable::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
|
||||
{
|
||||
ASSERT(samplerIndex < mSamplerUniformRange.length());
|
||||
return samplerIndex + mSamplerUniformRange.low();
|
||||
}
|
||||
|
||||
void ProgramExecutable::setActive(size_t textureUnit,
|
||||
const SamplerBinding &samplerBinding,
|
||||
const gl::LinkedUniform &samplerUniform)
|
||||
@@ -1016,16 +833,6 @@ void ProgramExecutable::saveLinkedStateInfo(const Context *context, const Progra
|
||||
}
|
||||
}
|
||||
|
||||
bool ProgramExecutable::isYUVOutput() const
|
||||
{
|
||||
return mYUVOutput;
|
||||
}
|
||||
|
||||
ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const
|
||||
{
|
||||
return GetLastPreFragmentStage(mLinkedShaderStages);
|
||||
}
|
||||
|
||||
bool ProgramExecutable::linkMergedVaryings(
|
||||
const Context *context,
|
||||
const ProgramMergedVaryings &mergedVaryings,
|
||||
@@ -1190,7 +997,7 @@ bool ProgramExecutable::linkValidateTransformFeedback(
|
||||
|
||||
// TODO(jmadill): Investigate implementation limits on D3D11
|
||||
componentCount = VariableComponentCount(var->type) * elementCount;
|
||||
if (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
|
||||
if (mPODStruct.transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
|
||||
componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
|
||||
{
|
||||
mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
|
||||
@@ -1200,7 +1007,7 @@ bool ProgramExecutable::linkValidateTransformFeedback(
|
||||
}
|
||||
|
||||
totalComponents += componentCount;
|
||||
if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
|
||||
if (mPODStruct.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
|
||||
totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
|
||||
{
|
||||
mInfoLog << "Transform feedback varying total components (" << totalComponents
|
||||
@@ -1263,7 +1070,7 @@ void ProgramExecutable::updateTransformFeedbackStrides()
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
|
||||
if (mPODStruct.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
|
||||
{
|
||||
mTransformFeedbackStrides.resize(1);
|
||||
size_t totalSize = 0;
|
||||
@@ -1335,9 +1142,9 @@ bool ProgramExecutable::linkValidateOutputVariables(
|
||||
const ProgramAliasedBindings &fragmentOutputIndices)
|
||||
{
|
||||
ASSERT(mOutputVariableTypes.empty());
|
||||
ASSERT(mActiveOutputVariablesMask.none());
|
||||
ASSERT(mDrawBufferTypeMask.none());
|
||||
ASSERT(!mYUVOutput);
|
||||
ASSERT(mPODStruct.activeOutputVariablesMask.none());
|
||||
ASSERT(mPODStruct.drawBufferTypeMask.none());
|
||||
ASSERT(!mPODStruct.hasYUVOutput);
|
||||
|
||||
// Gather output variable types
|
||||
for (const sh::ShaderVariable &outputVariable : outputVariables)
|
||||
@@ -1362,17 +1169,17 @@ bool ProgramExecutable::linkValidateOutputVariables(
|
||||
{
|
||||
mOutputVariableTypes.resize(location + 1, GL_NONE);
|
||||
}
|
||||
ASSERT(location < mActiveOutputVariablesMask.size());
|
||||
mActiveOutputVariablesMask.set(location);
|
||||
ASSERT(location < mPODStruct.activeOutputVariablesMask.size());
|
||||
mPODStruct.activeOutputVariablesMask.set(location);
|
||||
mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
|
||||
ComponentType componentType = GLenumToComponentType(mOutputVariableTypes[location]);
|
||||
SetComponentTypeMask(componentType, location, &mDrawBufferTypeMask);
|
||||
SetComponentTypeMask(componentType, location, &mPODStruct.drawBufferTypeMask);
|
||||
}
|
||||
|
||||
if (outputVariable.yuv)
|
||||
{
|
||||
ASSERT(outputVariables.size() == 1);
|
||||
mYUVOutput = true;
|
||||
mPODStruct.hasYUVOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,7 +1191,7 @@ bool ProgramExecutable::linkValidateOutputVariables(
|
||||
// fragment shader outputs exceeds the implementation-dependent value of
|
||||
// MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
|
||||
if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
|
||||
mActiveOutputVariablesMask.count() >
|
||||
mPODStruct.activeOutputVariablesMask.count() >
|
||||
static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
|
||||
{
|
||||
mInfoLog
|
||||
@@ -1590,7 +1397,7 @@ bool ProgramExecutable::linkUniforms(
|
||||
std::vector<UnusedUniform> *unusedUniformsOutOrNull,
|
||||
std::vector<VariableLocation> *uniformLocationsOutOrNull)
|
||||
{
|
||||
UniformLinker linker(mLinkedShaderStages, shaderUniforms);
|
||||
UniformLinker linker(mPODStruct.linkedShaderStages, shaderUniforms);
|
||||
if (!linker.link(context->getCaps(), infoLog, uniformLocationBindings))
|
||||
{
|
||||
return false;
|
||||
@@ -1630,7 +1437,7 @@ void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniform
|
||||
--low;
|
||||
}
|
||||
|
||||
mFragmentInoutRange = RangeUI(low, high);
|
||||
mPODStruct.fragmentInoutRange = RangeUI(low, high);
|
||||
|
||||
highIter = lowIter;
|
||||
high = low;
|
||||
@@ -1640,7 +1447,7 @@ void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniform
|
||||
--low;
|
||||
}
|
||||
|
||||
mAtomicCounterUniformRange = RangeUI(low, high);
|
||||
mPODStruct.atomicCounterUniformRange = RangeUI(low, high);
|
||||
|
||||
highIter = lowIter;
|
||||
high = low;
|
||||
@@ -1650,10 +1457,10 @@ void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniform
|
||||
--low;
|
||||
}
|
||||
|
||||
mImageUniformRange = RangeUI(low, high);
|
||||
*combinedImageUniforms = 0u;
|
||||
mPODStruct.imageUniformRange = RangeUI(low, high);
|
||||
*combinedImageUniforms = 0u;
|
||||
// If uniform is a image type, insert it into the mImageBindings array.
|
||||
for (unsigned int imageIndex : mImageUniformRange)
|
||||
for (unsigned int imageIndex : mPODStruct.imageUniformRange)
|
||||
{
|
||||
// ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
|
||||
// cannot load values into a uniform defined as an image. if declare without a
|
||||
@@ -1688,10 +1495,10 @@ void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniform
|
||||
--low;
|
||||
}
|
||||
|
||||
mSamplerUniformRange = RangeUI(low, high);
|
||||
mPODStruct.samplerUniformRange = RangeUI(low, high);
|
||||
|
||||
// If uniform is a sampler type, insert it into the mSamplerBindings array.
|
||||
for (unsigned int samplerIndex : mSamplerUniformRange)
|
||||
for (unsigned int samplerIndex : mPODStruct.samplerUniformRange)
|
||||
{
|
||||
const auto &samplerUniform = mUniforms[samplerIndex];
|
||||
TextureType textureType = SamplerTypeToTextureType(samplerUniform.getType());
|
||||
@@ -1702,12 +1509,12 @@ void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniform
|
||||
}
|
||||
|
||||
// Whatever is left constitutes the default uniforms.
|
||||
mDefaultUniformRange = RangeUI(0, low);
|
||||
mPODStruct.defaultUniformRange = RangeUI(0, low);
|
||||
}
|
||||
|
||||
bool ProgramExecutable::linkAtomicCounterBuffers(const Context *context, InfoLog &infoLog)
|
||||
{
|
||||
for (unsigned int index : mAtomicCounterUniformRange)
|
||||
for (unsigned int index : mPODStruct.atomicCounterUniformRange)
|
||||
{
|
||||
auto &uniform = mUniforms[index];
|
||||
|
||||
@@ -1816,29 +1623,33 @@ void ProgramExecutable::copyUniformsFromProgramMap(const ShaderMap<Program *> &p
|
||||
{
|
||||
// Merge default uniforms.
|
||||
auto getDefaultRange = [](const ProgramState &state) { return state.getDefaultUniformRange(); };
|
||||
mDefaultUniformRange = AddUniforms(programs, mLinkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getDefaultRange);
|
||||
mPODStruct.defaultUniformRange =
|
||||
AddUniforms(programs, mPODStruct.linkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getDefaultRange);
|
||||
|
||||
// Merge sampler uniforms.
|
||||
auto getSamplerRange = [](const ProgramState &state) { return state.getSamplerUniformRange(); };
|
||||
mSamplerUniformRange = AddUniforms(programs, mLinkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getSamplerRange);
|
||||
mPODStruct.samplerUniformRange =
|
||||
AddUniforms(programs, mPODStruct.linkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getSamplerRange);
|
||||
|
||||
// Merge image uniforms.
|
||||
auto getImageRange = [](const ProgramState &state) { return state.getImageUniformRange(); };
|
||||
mImageUniformRange = AddUniforms(programs, mLinkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getImageRange);
|
||||
mPODStruct.imageUniformRange = AddUniforms(programs, mPODStruct.linkedShaderStages, &mUniforms,
|
||||
&mUniformNames, &mUniformMappedNames, getImageRange);
|
||||
|
||||
// Merge atomic counter uniforms.
|
||||
auto getAtomicRange = [](const ProgramState &state) {
|
||||
return state.getAtomicCounterUniformRange();
|
||||
};
|
||||
mAtomicCounterUniformRange = AddUniforms(programs, mLinkedShaderStages, &mUniforms,
|
||||
&mUniformNames, &mUniformMappedNames, getAtomicRange);
|
||||
mPODStruct.atomicCounterUniformRange =
|
||||
AddUniforms(programs, mPODStruct.linkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getAtomicRange);
|
||||
|
||||
// Merge fragment in/out uniforms.
|
||||
auto getInoutRange = [](const ProgramState &state) { return state.getFragmentInoutRange(); };
|
||||
mFragmentInoutRange = AddUniforms(programs, mLinkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getInoutRange);
|
||||
auto getInoutRange = [](const ProgramState &state) { return state.getFragmentInoutRange(); };
|
||||
mPODStruct.fragmentInoutRange =
|
||||
AddUniforms(programs, mPODStruct.linkedShaderStages, &mUniforms, &mUniformNames,
|
||||
&mUniformMappedNames, getInoutRange);
|
||||
}
|
||||
} // namespace gl
|
||||
|
||||
@@ -194,40 +194,48 @@ class ProgramExecutable final : public angle::Subject
|
||||
std::string getInfoLogString() const;
|
||||
void resetInfoLog() { mInfoLog.reset(); }
|
||||
|
||||
void resetLinkedShaderStages() { mLinkedShaderStages.reset(); }
|
||||
const ShaderBitSet getLinkedShaderStages() const { return mLinkedShaderStages; }
|
||||
void resetLinkedShaderStages() { mPODStruct.linkedShaderStages.reset(); }
|
||||
const ShaderBitSet getLinkedShaderStages() const { return mPODStruct.linkedShaderStages; }
|
||||
void setLinkedShaderStages(ShaderType shaderType)
|
||||
{
|
||||
mLinkedShaderStages.set(shaderType);
|
||||
mPODStruct.linkedShaderStages.set(shaderType);
|
||||
updateCanDrawWith();
|
||||
}
|
||||
bool hasLinkedShaderStage(ShaderType shaderType) const
|
||||
{
|
||||
ASSERT(shaderType != ShaderType::InvalidEnum);
|
||||
return mLinkedShaderStages[shaderType];
|
||||
return mPODStruct.linkedShaderStages[shaderType];
|
||||
}
|
||||
size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
|
||||
size_t getLinkedShaderStageCount() const { return mPODStruct.linkedShaderStages.count(); }
|
||||
bool hasLinkedGraphicsShader() const
|
||||
{
|
||||
return mLinkedShaderStages.any() &&
|
||||
mLinkedShaderStages != gl::ShaderBitSet{gl::ShaderType::Compute};
|
||||
return mPODStruct.linkedShaderStages.any() &&
|
||||
mPODStruct.linkedShaderStages != gl::ShaderBitSet{gl::ShaderType::Compute};
|
||||
}
|
||||
bool hasLinkedTessellationShader() const
|
||||
{
|
||||
return mLinkedShaderStages[ShaderType::TessEvaluation];
|
||||
return mPODStruct.linkedShaderStages[ShaderType::TessEvaluation];
|
||||
}
|
||||
|
||||
ShaderType getLinkedTransformFeedbackStage() const;
|
||||
ShaderType getLinkedTransformFeedbackStage() const
|
||||
{
|
||||
return GetLastPreFragmentStage(mPODStruct.linkedShaderStages);
|
||||
}
|
||||
|
||||
const AttributesMask &getActiveAttribLocationsMask() const
|
||||
{
|
||||
return mActiveAttribLocationsMask;
|
||||
return mPODStruct.activeAttribLocationsMask;
|
||||
}
|
||||
bool isAttribLocationActive(size_t attribLocation) const;
|
||||
AttributesMask getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
|
||||
unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
|
||||
ComponentTypeMask getAttributesTypeMask() const { return mAttributesTypeMask; }
|
||||
AttributesMask getAttributesMask() const;
|
||||
bool isAttribLocationActive(size_t attribLocation) const
|
||||
{
|
||||
ASSERT(attribLocation < mPODStruct.activeAttribLocationsMask.size());
|
||||
return mPODStruct.activeAttribLocationsMask[attribLocation];
|
||||
}
|
||||
|
||||
AttributesMask getNonBuiltinAttribLocationsMask() const { return mPODStruct.attributesMask; }
|
||||
unsigned int getMaxActiveAttribLocation() const { return mPODStruct.maxActiveAttribLocation; }
|
||||
ComponentTypeMask getAttributesTypeMask() const { return mPODStruct.attributesTypeMask; }
|
||||
AttributesMask getAttributesMask() const { return mPODStruct.attributesMask; }
|
||||
|
||||
const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
|
||||
void setActiveTextureMask(ActiveTextureMask mask) { mActiveSamplersMask = mask; }
|
||||
@@ -262,17 +270,17 @@ class ProgramExecutable final : public angle::Subject
|
||||
|
||||
void updateActiveSamplers(const ProgramState &programState);
|
||||
|
||||
bool hasDefaultUniforms() const;
|
||||
bool hasTextures() const;
|
||||
bool hasUniformBuffers() const;
|
||||
bool hasStorageBuffers() const;
|
||||
bool hasAtomicCounterBuffers() const;
|
||||
bool hasImages() const;
|
||||
bool hasDefaultUniforms() const { return !getDefaultUniformRange().empty(); }
|
||||
bool hasTextures() const { return !getSamplerBindings().empty(); }
|
||||
bool hasUniformBuffers() const { return !mUniformBlocks.empty(); }
|
||||
bool hasStorageBuffers() const { return !mShaderStorageBlocks.empty(); }
|
||||
bool hasAtomicCounterBuffers() const { return !mAtomicCounterBuffers.empty(); }
|
||||
bool hasImages() const { return !mImageBindings.empty(); }
|
||||
bool hasTransformFeedbackOutput() const
|
||||
{
|
||||
return !getLinkedTransformFeedbackVaryings().empty();
|
||||
}
|
||||
bool usesFramebufferFetch() const;
|
||||
bool usesFramebufferFetch() const { return (mPODStruct.fragmentInoutRange.length() > 0); }
|
||||
|
||||
// Count the number of uniform and storage buffer declarations, counting arrays as one.
|
||||
size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
|
||||
@@ -298,20 +306,26 @@ class ProgramExecutable final : public angle::Subject
|
||||
const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
|
||||
const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
|
||||
std::vector<ImageBinding> *getImageBindings() { return &mImageBindings; }
|
||||
const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; }
|
||||
const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
|
||||
const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
|
||||
const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
|
||||
const RangeUI &getFragmentInoutRange() const { return mFragmentInoutRange; }
|
||||
bool hasClipDistance() const { return mHasClipDistance; }
|
||||
bool hasDiscard() const { return mHasDiscard; }
|
||||
bool enablesPerSampleShading() const { return mEnablesPerSampleShading; }
|
||||
BlendEquationBitSet getAdvancedBlendEquations() const { return mAdvancedBlendEquations; }
|
||||
const RangeUI &getDefaultUniformRange() const { return mPODStruct.defaultUniformRange; }
|
||||
const RangeUI &getSamplerUniformRange() const { return mPODStruct.samplerUniformRange; }
|
||||
const RangeUI &getImageUniformRange() const { return mPODStruct.imageUniformRange; }
|
||||
const RangeUI &getAtomicCounterUniformRange() const
|
||||
{
|
||||
return mPODStruct.atomicCounterUniformRange;
|
||||
}
|
||||
const RangeUI &getFragmentInoutRange() const { return mPODStruct.fragmentInoutRange; }
|
||||
bool hasClipDistance() const { return mPODStruct.hasClipDistance; }
|
||||
bool hasDiscard() const { return mPODStruct.hasDiscard; }
|
||||
bool enablesPerSampleShading() const { return mPODStruct.enablesPerSampleShading; }
|
||||
BlendEquationBitSet getAdvancedBlendEquations() const
|
||||
{
|
||||
return mPODStruct.advancedBlendEquations;
|
||||
}
|
||||
const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
|
||||
{
|
||||
return mLinkedTransformFeedbackVaryings;
|
||||
}
|
||||
GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
|
||||
GLint getTransformFeedbackBufferMode() const { return mPODStruct.transformFeedbackBufferMode; }
|
||||
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
|
||||
{
|
||||
ASSERT(uniformBlockIndex < mUniformBlocks.size());
|
||||
@@ -361,9 +375,17 @@ class ProgramExecutable final : public angle::Subject
|
||||
return static_cast<GLuint>(shaderStorageBlocksSize);
|
||||
}
|
||||
|
||||
GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const;
|
||||
GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const
|
||||
{
|
||||
ASSERT(imageIndex < mPODStruct.imageUniformRange.length());
|
||||
return imageIndex + mPODStruct.imageUniformRange.low();
|
||||
}
|
||||
|
||||
GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
|
||||
GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
|
||||
{
|
||||
ASSERT(samplerIndex < mPODStruct.samplerUniformRange.length());
|
||||
return samplerIndex + mPODStruct.samplerUniformRange.low();
|
||||
}
|
||||
|
||||
void saveLinkedStateInfo(const Context *context, const ProgramState &state);
|
||||
const std::vector<sh::ShaderVariable> &getLinkedOutputVaryings(ShaderType shaderType) const
|
||||
@@ -390,23 +412,23 @@ class ProgramExecutable final : public angle::Subject
|
||||
return mLinkedShaderVersions[shaderType];
|
||||
}
|
||||
|
||||
bool isYUVOutput() const;
|
||||
bool isYUVOutput() const { return mPODStruct.hasYUVOutput; }
|
||||
|
||||
PrimitiveMode getGeometryShaderInputPrimitiveType() const
|
||||
{
|
||||
return mGeometryShaderInputPrimitiveType;
|
||||
return mPODStruct.geometryShaderInputPrimitiveType;
|
||||
}
|
||||
|
||||
PrimitiveMode getGeometryShaderOutputPrimitiveType() const
|
||||
{
|
||||
return mGeometryShaderOutputPrimitiveType;
|
||||
return mPODStruct.geometryShaderOutputPrimitiveType;
|
||||
}
|
||||
|
||||
int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
|
||||
int getGeometryShaderInvocations() const { return mPODStruct.geometryShaderInvocations; }
|
||||
|
||||
int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
|
||||
int getGeometryShaderMaxVertices() const { return mPODStruct.geometryShaderMaxVertices; }
|
||||
|
||||
GLenum getTessGenMode() const { return mTessGenMode; }
|
||||
GLenum getTessGenMode() const { return mPODStruct.tessGenMode; }
|
||||
|
||||
void resetCachedValidateSamplersResult() { mCachedValidateSamplersResult.reset(); }
|
||||
bool validateSamplers(InfoLog *infoLog, const Caps &caps) const
|
||||
@@ -422,8 +444,11 @@ class ProgramExecutable final : public angle::Subject
|
||||
return validateSamplersImpl(infoLog, caps);
|
||||
}
|
||||
|
||||
ComponentTypeMask getFragmentOutputsTypeMask() const { return mDrawBufferTypeMask; }
|
||||
DrawBufferMask getActiveOutputVariablesMask() const { return mActiveOutputVariablesMask; }
|
||||
ComponentTypeMask getFragmentOutputsTypeMask() const { return mPODStruct.drawBufferTypeMask; }
|
||||
DrawBufferMask getActiveOutputVariablesMask() const
|
||||
{
|
||||
return mPODStruct.activeOutputVariablesMask;
|
||||
}
|
||||
|
||||
bool linkUniforms(const Context *context,
|
||||
const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
|
||||
@@ -489,13 +514,53 @@ class ProgramExecutable final : public angle::Subject
|
||||
|
||||
InfoLog mInfoLog;
|
||||
|
||||
ShaderBitSet mLinkedShaderStages;
|
||||
// This struct must only contains basic data types so that entire struct can be memcpy.
|
||||
struct PODStruct
|
||||
{
|
||||
PODStruct();
|
||||
PODStruct(const PODStruct &other);
|
||||
|
||||
angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
|
||||
unsigned int mMaxActiveAttribLocation;
|
||||
ComponentTypeMask mAttributesTypeMask;
|
||||
// mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
|
||||
AttributesMask mAttributesMask;
|
||||
ShaderBitSet linkedShaderStages;
|
||||
angle::BitSet<MAX_VERTEX_ATTRIBS> activeAttribLocationsMask;
|
||||
unsigned int maxActiveAttribLocation;
|
||||
ComponentTypeMask attributesTypeMask;
|
||||
// attributesMask is identical to mActiveAttribLocationsMask with built-in attributes
|
||||
// removed.
|
||||
AttributesMask attributesMask;
|
||||
DrawBufferMask activeOutputVariablesMask;
|
||||
ComponentTypeMask drawBufferTypeMask;
|
||||
|
||||
RangeUI defaultUniformRange;
|
||||
RangeUI samplerUniformRange;
|
||||
RangeUI imageUniformRange;
|
||||
RangeUI atomicCounterUniformRange;
|
||||
RangeUI fragmentInoutRange;
|
||||
|
||||
bool hasClipDistance;
|
||||
bool hasDiscard;
|
||||
bool hasYUVOutput;
|
||||
bool enablesPerSampleShading;
|
||||
|
||||
// KHR_blend_equation_advanced supported equation list
|
||||
BlendEquationBitSet advancedBlendEquations;
|
||||
|
||||
// GL_EXT_geometry_shader.
|
||||
PrimitiveMode geometryShaderInputPrimitiveType;
|
||||
PrimitiveMode geometryShaderOutputPrimitiveType;
|
||||
int geometryShaderInvocations;
|
||||
int geometryShaderMaxVertices;
|
||||
|
||||
// GL_EXT_tessellation_shader
|
||||
int tessControlShaderVertices;
|
||||
GLenum tessGenMode;
|
||||
GLenum tessGenSpacing;
|
||||
GLenum tessGenVertexOrder;
|
||||
GLenum tessGenPointMode;
|
||||
|
||||
GLenum transformFeedbackBufferMode;
|
||||
} mPODStruct;
|
||||
static_assert(std::is_standard_layout<PODStruct>(),
|
||||
"PODStruct must be a standard layout struct so that we can memcpy");
|
||||
|
||||
// Cached mask of active samplers and sampler types.
|
||||
ActiveTextureMask mActiveSamplersMask;
|
||||
@@ -515,16 +580,13 @@ class ProgramExecutable final : public angle::Subject
|
||||
// to uniforms.
|
||||
std::vector<sh::ShaderVariable> mOutputVariables;
|
||||
std::vector<VariableLocation> mOutputLocations;
|
||||
DrawBufferMask mActiveOutputVariablesMask;
|
||||
// EXT_blend_func_extended secondary outputs (ones with index 1)
|
||||
std::vector<VariableLocation> mSecondaryOutputLocations;
|
||||
bool mYUVOutput;
|
||||
// Vertex attributes, Fragment input varyings, etc.
|
||||
std::vector<ProgramInput> mProgramInputs;
|
||||
std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
|
||||
// The size of the data written to each transform feedback buffer per vertex.
|
||||
std::vector<GLsizei> mTransformFeedbackStrides;
|
||||
GLenum mTransformFeedbackBufferMode;
|
||||
// Uniforms are sorted in order:
|
||||
// 1. Non-opaque uniforms
|
||||
// 2. Sampler uniforms
|
||||
@@ -541,10 +603,6 @@ class ProgramExecutable final : public angle::Subject
|
||||
std::vector<std::string> mUniformNames;
|
||||
// Only used by GL and D3D backend
|
||||
std::vector<std::string> mUniformMappedNames;
|
||||
RangeUI mDefaultUniformRange;
|
||||
RangeUI mSamplerUniformRange;
|
||||
RangeUI mImageUniformRange;
|
||||
RangeUI mAtomicCounterUniformRange;
|
||||
std::vector<InterfaceBlock> mUniformBlocks;
|
||||
|
||||
// For faster iteration on the blocks currently being bound.
|
||||
@@ -553,14 +611,6 @@ class ProgramExecutable final : public angle::Subject
|
||||
std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
|
||||
std::vector<InterfaceBlock> mShaderStorageBlocks;
|
||||
|
||||
RangeUI mFragmentInoutRange;
|
||||
bool mHasClipDistance;
|
||||
bool mHasDiscard;
|
||||
bool mEnablesPerSampleShading;
|
||||
|
||||
// KHR_blend_equation_advanced supported equation list
|
||||
BlendEquationBitSet mAdvancedBlendEquations;
|
||||
|
||||
// An array of the samplers that are used by the program
|
||||
std::vector<SamplerBinding> mSamplerBindings;
|
||||
|
||||
@@ -574,22 +624,8 @@ class ProgramExecutable final : public angle::Subject
|
||||
|
||||
ShaderMap<int> mLinkedShaderVersions;
|
||||
|
||||
// GL_EXT_geometry_shader.
|
||||
PrimitiveMode mGeometryShaderInputPrimitiveType;
|
||||
PrimitiveMode mGeometryShaderOutputPrimitiveType;
|
||||
int mGeometryShaderInvocations;
|
||||
int mGeometryShaderMaxVertices;
|
||||
|
||||
// GL_EXT_tessellation_shader
|
||||
int mTessControlShaderVertices;
|
||||
GLenum mTessGenMode;
|
||||
GLenum mTessGenSpacing;
|
||||
GLenum mTessGenVertexOrder;
|
||||
GLenum mTessGenPointMode;
|
||||
|
||||
// Fragment output variable base types: FLOAT, INT, or UINT. Ordered by location.
|
||||
std::vector<GLenum> mOutputVariableTypes;
|
||||
ComponentTypeMask mDrawBufferTypeMask;
|
||||
|
||||
// Cache for sampler validation
|
||||
mutable Optional<bool> mCachedValidateSamplersResult;
|
||||
|
||||
@@ -270,12 +270,15 @@ void ProgramPipeline::updateExecutableAttributes()
|
||||
return;
|
||||
}
|
||||
|
||||
const ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
|
||||
mState.mExecutable->mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
|
||||
mState.mExecutable->mMaxActiveAttribLocation = vertexExecutable.mMaxActiveAttribLocation;
|
||||
mState.mExecutable->mAttributesTypeMask = vertexExecutable.mAttributesTypeMask;
|
||||
mState.mExecutable->mAttributesMask = vertexExecutable.mAttributesMask;
|
||||
mState.mExecutable->mProgramInputs = vertexExecutable.mProgramInputs;
|
||||
const ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
|
||||
mState.mExecutable->mPODStruct.activeAttribLocationsMask =
|
||||
vertexExecutable.mPODStruct.activeAttribLocationsMask;
|
||||
mState.mExecutable->mPODStruct.maxActiveAttribLocation =
|
||||
vertexExecutable.mPODStruct.maxActiveAttribLocation;
|
||||
mState.mExecutable->mPODStruct.attributesTypeMask =
|
||||
vertexExecutable.mPODStruct.attributesTypeMask;
|
||||
mState.mExecutable->mPODStruct.attributesMask = vertexExecutable.mPODStruct.attributesMask;
|
||||
mState.mExecutable->mProgramInputs = vertexExecutable.mProgramInputs;
|
||||
}
|
||||
|
||||
void ProgramPipeline::updateTransformFeedbackMembers()
|
||||
@@ -359,12 +362,14 @@ void ProgramPipeline::updateExecutableGeometryProperties()
|
||||
}
|
||||
|
||||
const ProgramExecutable &geometryExecutable = geometryProgram->getExecutable();
|
||||
mState.mExecutable->mGeometryShaderInputPrimitiveType =
|
||||
geometryExecutable.mGeometryShaderInputPrimitiveType;
|
||||
mState.mExecutable->mGeometryShaderOutputPrimitiveType =
|
||||
geometryExecutable.mGeometryShaderOutputPrimitiveType;
|
||||
mState.mExecutable->mGeometryShaderInvocations = geometryExecutable.mGeometryShaderInvocations;
|
||||
mState.mExecutable->mGeometryShaderMaxVertices = geometryExecutable.mGeometryShaderMaxVertices;
|
||||
mState.mExecutable->mPODStruct.geometryShaderInputPrimitiveType =
|
||||
geometryExecutable.mPODStruct.geometryShaderInputPrimitiveType;
|
||||
mState.mExecutable->mPODStruct.geometryShaderOutputPrimitiveType =
|
||||
geometryExecutable.mPODStruct.geometryShaderOutputPrimitiveType;
|
||||
mState.mExecutable->mPODStruct.geometryShaderInvocations =
|
||||
geometryExecutable.mPODStruct.geometryShaderInvocations;
|
||||
mState.mExecutable->mPODStruct.geometryShaderMaxVertices =
|
||||
geometryExecutable.mPODStruct.geometryShaderMaxVertices;
|
||||
}
|
||||
|
||||
void ProgramPipeline::updateExecutableTessellationProperties()
|
||||
@@ -375,17 +380,20 @@ void ProgramPipeline::updateExecutableTessellationProperties()
|
||||
if (tessControlProgram)
|
||||
{
|
||||
const ProgramExecutable &tessControlExecutable = tessControlProgram->getExecutable();
|
||||
mState.mExecutable->mTessControlShaderVertices =
|
||||
tessControlExecutable.mTessControlShaderVertices;
|
||||
mState.mExecutable->mPODStruct.tessControlShaderVertices =
|
||||
tessControlExecutable.mPODStruct.tessControlShaderVertices;
|
||||
}
|
||||
|
||||
if (tessEvalProgram)
|
||||
{
|
||||
const ProgramExecutable &tessEvalExecutable = tessEvalProgram->getExecutable();
|
||||
mState.mExecutable->mTessGenMode = tessEvalExecutable.mTessGenMode;
|
||||
mState.mExecutable->mTessGenSpacing = tessEvalExecutable.mTessGenSpacing;
|
||||
mState.mExecutable->mTessGenVertexOrder = tessEvalExecutable.mTessGenVertexOrder;
|
||||
mState.mExecutable->mTessGenPointMode = tessEvalExecutable.mTessGenPointMode;
|
||||
mState.mExecutable->mPODStruct.tessGenMode = tessEvalExecutable.mPODStruct.tessGenMode;
|
||||
mState.mExecutable->mPODStruct.tessGenSpacing =
|
||||
tessEvalExecutable.mPODStruct.tessGenSpacing;
|
||||
mState.mExecutable->mPODStruct.tessGenVertexOrder =
|
||||
tessEvalExecutable.mPODStruct.tessGenVertexOrder;
|
||||
mState.mExecutable->mPODStruct.tessGenPointMode =
|
||||
tessEvalExecutable.mPODStruct.tessGenPointMode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,10 +406,12 @@ void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
|
||||
return;
|
||||
}
|
||||
|
||||
const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
|
||||
mState.mExecutable->mFragmentInoutRange = fragmentExecutable.mFragmentInoutRange;
|
||||
mState.mExecutable->mHasDiscard = fragmentExecutable.mHasDiscard;
|
||||
mState.mExecutable->mEnablesPerSampleShading = fragmentExecutable.mEnablesPerSampleShading;
|
||||
const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
|
||||
mState.mExecutable->mPODStruct.fragmentInoutRange =
|
||||
fragmentExecutable.mPODStruct.fragmentInoutRange;
|
||||
mState.mExecutable->mPODStruct.hasDiscard = fragmentExecutable.mPODStruct.hasDiscard;
|
||||
mState.mExecutable->mPODStruct.enablesPerSampleShading =
|
||||
fragmentExecutable.mPODStruct.enablesPerSampleShading;
|
||||
}
|
||||
|
||||
void ProgramPipeline::updateLinkedVaryings()
|
||||
|
||||
Reference in New Issue
Block a user