Commit fa449cf3 by Jamie Madill Committed by Commit Bot

Fix separable Geometry Shaders.

Was a needed fix for a new varying test. Bug: angleproject:3571 Bug: angleproject:5496 Change-Id: I49ae69967510b7a6330ea217a0e0e19e3bebe865 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2613198Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 3e33db95
...@@ -9066,7 +9066,6 @@ void StateCache::setValidDrawModes(bool pointsOK, ...@@ -9066,7 +9066,6 @@ void StateCache::setValidDrawModes(bool pointsOK,
void StateCache::updateValidDrawModes(Context *context) void StateCache::updateValidDrawModes(Context *context)
{ {
const State &state = context->getState(); const State &state = context->getState();
Program *program = state.getProgram();
if (mCachedTransformFeedbackActiveUnpaused) if (mCachedTransformFeedbackActiveUnpaused)
{ {
...@@ -9109,7 +9108,7 @@ void StateCache::updateValidDrawModes(Context *context) ...@@ -9109,7 +9108,7 @@ void StateCache::updateValidDrawModes(Context *context)
} }
ASSERT(programExecutable->hasLinkedShaderStage(ShaderType::Geometry)); ASSERT(programExecutable->hasLinkedShaderStage(ShaderType::Geometry));
PrimitiveMode gsMode = program->getGeometryShaderInputPrimitiveType(); PrimitiveMode gsMode = programExecutable->getGeometryShaderInputPrimitiveType();
bool pointsOK = gsMode == PrimitiveMode::Points; bool pointsOK = gsMode == PrimitiveMode::Points;
bool linesOK = gsMode == PrimitiveMode::Lines; bool linesOK = gsMode == PrimitiveMode::Lines;
......
...@@ -1203,11 +1203,6 @@ ProgramState::ProgramState() ...@@ -1203,11 +1203,6 @@ ProgramState::ProgramState()
mBinaryRetrieveableHint(false), mBinaryRetrieveableHint(false),
mSeparable(false), mSeparable(false),
mNumViews(-1), mNumViews(-1),
// [GL_EXT_geometry_shader] Table 20.22
mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
mGeometryShaderInvocations(1),
mGeometryShaderMaxVertices(0),
mDrawIDLocation(-1), mDrawIDLocation(-1),
mBaseVertexLocation(-1), mBaseVertexLocation(-1),
mBaseInstanceLocation(-1), mBaseInstanceLocation(-1),
...@@ -1939,17 +1934,13 @@ void Program::unlink() ...@@ -1939,17 +1934,13 @@ void Program::unlink()
mState.mYUVOutput = false; mState.mYUVOutput = false;
mState.mActiveOutputVariables.reset(); mState.mActiveOutputVariables.reset();
mState.mComputeShaderLocalSize.fill(1); mState.mComputeShaderLocalSize.fill(1);
mState.mNumViews = -1; mState.mNumViews = -1;
mState.mGeometryShaderInputPrimitiveType = PrimitiveMode::Triangles; mState.mDrawIDLocation = -1;
mState.mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip; mState.mBaseVertexLocation = -1;
mState.mGeometryShaderInvocations = 1; mState.mBaseInstanceLocation = -1;
mState.mGeometryShaderMaxVertices = 0; mState.mCachedBaseVertex = 0;
mState.mDrawIDLocation = -1; mState.mCachedBaseInstance = 0;
mState.mBaseVertexLocation = -1; mState.mEarlyFramentTestsOptimization = false;
mState.mBaseInstanceLocation = -1;
mState.mCachedBaseVertex = 0;
mState.mCachedBaseInstance = 0;
mState.mEarlyFramentTestsOptimization = false;
mState.mSpecConstUsageBits.reset(); mState.mSpecConstUsageBits.reset();
mValidated = false; mValidated = false;
...@@ -2241,23 +2232,23 @@ const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const ...@@ -2241,23 +2232,23 @@ const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
{ {
ASSERT(!mLinkingState); ASSERT(!mLinkingState && mState.mExecutable);
return mState.mGeometryShaderInputPrimitiveType; return mState.mExecutable->getGeometryShaderInputPrimitiveType();
} }
PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
{ {
ASSERT(!mLinkingState); ASSERT(!mLinkingState && mState.mExecutable);
return mState.mGeometryShaderOutputPrimitiveType; return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
} }
GLint Program::getGeometryShaderInvocations() const GLint Program::getGeometryShaderInvocations() const
{ {
ASSERT(!mLinkingState); ASSERT(!mLinkingState && mState.mExecutable);
return mState.mGeometryShaderInvocations; return mState.mExecutable->getGeometryShaderInvocations();
} }
GLint Program::getGeometryShaderMaxVertices() const GLint Program::getGeometryShaderMaxVertices() const
{ {
ASSERT(!mLinkingState); ASSERT(!mLinkingState && mState.mExecutable);
return mState.mGeometryShaderMaxVertices; return mState.mExecutable->getGeometryShaderMaxVertices();
} }
const sh::ShaderVariable &Program::getInputResource(size_t index) const const sh::ShaderVariable &Program::getInputResource(size_t index) const
...@@ -3502,10 +3493,11 @@ bool Program::linkValidateShaders(InfoLog &infoLog) ...@@ -3502,10 +3493,11 @@ bool Program::linkValidateShaders(InfoLog &infoLog)
return false; return false;
} }
mState.mGeometryShaderInputPrimitiveType = inputPrimitive.value(); mState.mExecutable->mGeometryShaderInputPrimitiveType = inputPrimitive.value();
mState.mGeometryShaderOutputPrimitiveType = outputPrimitive.value(); mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
mState.mGeometryShaderMaxVertices = maxVertices.value(); mState.mExecutable->mGeometryShaderMaxVertices = maxVertices.value();
mState.mGeometryShaderInvocations = geometryShader->getGeometryShaderInvocations(); mState.mExecutable->mGeometryShaderInvocations =
geometryShader->getGeometryShaderInvocations();
} }
} }
...@@ -5189,12 +5181,6 @@ angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *bi ...@@ -5189,12 +5181,6 @@ angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *bi
stream.writeInt(computeLocalSize[1]); stream.writeInt(computeLocalSize[1]);
stream.writeInt(computeLocalSize[2]); stream.writeInt(computeLocalSize[2]);
ASSERT(mState.mGeometryShaderInvocations >= 1 && mState.mGeometryShaderMaxVertices >= 0);
stream.writeEnum(mState.mGeometryShaderInputPrimitiveType);
stream.writeEnum(mState.mGeometryShaderOutputPrimitiveType);
stream.writeInt(mState.mGeometryShaderInvocations);
stream.writeInt(mState.mGeometryShaderMaxVertices);
stream.writeInt(mState.mNumViews); stream.writeInt(mState.mNumViews);
stream.writeBool(mState.mEarlyFramentTestsOptimization); stream.writeBool(mState.mEarlyFramentTestsOptimization);
stream.writeInt(mState.mSpecConstUsageBits.bits()); stream.writeInt(mState.mSpecConstUsageBits.bits());
...@@ -5389,11 +5375,6 @@ angle::Result Program::deserialize(const Context *context, ...@@ -5389,11 +5375,6 @@ angle::Result Program::deserialize(const Context *context,
mState.mComputeShaderLocalSize[1] = stream.readInt<int>(); mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
mState.mComputeShaderLocalSize[2] = stream.readInt<int>(); mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
mState.mGeometryShaderInputPrimitiveType = stream.readEnum<PrimitiveMode>();
mState.mGeometryShaderOutputPrimitiveType = stream.readEnum<PrimitiveMode>();
mState.mGeometryShaderInvocations = stream.readInt<int>();
mState.mGeometryShaderMaxVertices = stream.readInt<int>();
mState.mNumViews = stream.readInt<int>(); mState.mNumViews = stream.readInt<int>();
mState.mEarlyFramentTestsOptimization = stream.readBool(); mState.mEarlyFramentTestsOptimization = stream.readBool();
mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>()); mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
......
...@@ -356,20 +356,6 @@ class ProgramState final : angle::NonCopyable ...@@ -356,20 +356,6 @@ class ProgramState final : angle::NonCopyable
bool isSeparable() const { return mSeparable; } bool isSeparable() const { return mSeparable; }
PrimitiveMode getGeometryShaderInputPrimitiveType() const
{
return mGeometryShaderInputPrimitiveType;
}
PrimitiveMode getGeometryShaderOutputPrimitiveType() const
{
return mGeometryShaderOutputPrimitiveType;
}
int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
int getDrawIDLocation() const { return mDrawIDLocation; } int getDrawIDLocation() const { return mDrawIDLocation; }
int getBaseVertexLocation() const { return mBaseVertexLocation; } int getBaseVertexLocation() const { return mBaseVertexLocation; }
...@@ -428,12 +414,6 @@ class ProgramState final : angle::NonCopyable ...@@ -428,12 +414,6 @@ class ProgramState final : angle::NonCopyable
// ANGLE_multiview. // ANGLE_multiview.
int mNumViews; int mNumViews;
// GL_EXT_geometry_shader.
PrimitiveMode mGeometryShaderInputPrimitiveType;
PrimitiveMode mGeometryShaderOutputPrimitiveType;
int mGeometryShaderInvocations;
int mGeometryShaderMaxVertices;
// GL_ANGLE_multi_draw // GL_ANGLE_multi_draw
int mDrawIDLocation; int mDrawIDLocation;
......
...@@ -41,7 +41,12 @@ ProgramExecutable::ProgramExecutable() ...@@ -41,7 +41,12 @@ ProgramExecutable::ProgramExecutable()
mPipelineHasComputeTextures(false), mPipelineHasComputeTextures(false),
mPipelineHasGraphicsImages(false), mPipelineHasGraphicsImages(false),
mPipelineHasComputeImages(false), mPipelineHasComputeImages(false),
mIsCompute(false) mIsCompute(false),
// [GL_EXT_geometry_shader] Table 20.22
mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
mGeometryShaderInvocations(1),
mGeometryShaderMaxVertices(0)
{ {
reset(); reset();
} }
...@@ -136,6 +141,11 @@ void ProgramExecutable::reset() ...@@ -136,6 +141,11 @@ void ProgramExecutable::reset()
mPipelineHasComputeDefaultUniforms = false; mPipelineHasComputeDefaultUniforms = false;
mPipelineHasGraphicsTextures = false; mPipelineHasGraphicsTextures = false;
mPipelineHasComputeTextures = false; mPipelineHasComputeTextures = false;
mGeometryShaderInputPrimitiveType = PrimitiveMode::Triangles;
mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
mGeometryShaderInvocations = 1;
mGeometryShaderMaxVertices = 0;
} }
void ProgramExecutable::load(gl::BinaryInputStream *stream) void ProgramExecutable::load(gl::BinaryInputStream *stream)
...@@ -162,6 +172,11 @@ void ProgramExecutable::load(gl::BinaryInputStream *stream) ...@@ -162,6 +172,11 @@ void ProgramExecutable::load(gl::BinaryInputStream *stream)
mPipelineHasComputeDefaultUniforms = stream->readBool(); mPipelineHasComputeDefaultUniforms = stream->readBool();
mPipelineHasGraphicsTextures = stream->readBool(); mPipelineHasGraphicsTextures = stream->readBool();
mPipelineHasComputeTextures = stream->readBool(); mPipelineHasComputeTextures = stream->readBool();
mGeometryShaderInputPrimitiveType = stream->readEnum<PrimitiveMode>();
mGeometryShaderOutputPrimitiveType = stream->readEnum<PrimitiveMode>();
mGeometryShaderInvocations = stream->readInt<int>();
mGeometryShaderMaxVertices = stream->readInt<int>();
} }
void ProgramExecutable::save(gl::BinaryOutputStream *stream) const void ProgramExecutable::save(gl::BinaryOutputStream *stream) const
...@@ -187,6 +202,12 @@ void ProgramExecutable::save(gl::BinaryOutputStream *stream) const ...@@ -187,6 +202,12 @@ void ProgramExecutable::save(gl::BinaryOutputStream *stream) const
stream->writeBool(mPipelineHasComputeDefaultUniforms); stream->writeBool(mPipelineHasComputeDefaultUniforms);
stream->writeBool(mPipelineHasGraphicsTextures); stream->writeBool(mPipelineHasGraphicsTextures);
stream->writeBool(mPipelineHasComputeTextures); stream->writeBool(mPipelineHasComputeTextures);
ASSERT(mGeometryShaderInvocations >= 1 && mGeometryShaderMaxVertices >= 0);
stream->writeEnum(mGeometryShaderInputPrimitiveType);
stream->writeEnum(mGeometryShaderOutputPrimitiveType);
stream->writeInt(mGeometryShaderInvocations);
stream->writeInt(mGeometryShaderMaxVertices);
} }
int ProgramExecutable::getInfoLogLength() const int ProgramExecutable::getInfoLogLength() const
......
...@@ -310,6 +310,20 @@ class ProgramExecutable final : public angle::Subject ...@@ -310,6 +310,20 @@ class ProgramExecutable final : public angle::Subject
bool isYUVOutput() const; bool isYUVOutput() const;
PrimitiveMode getGeometryShaderInputPrimitiveType() const
{
return mGeometryShaderInputPrimitiveType;
}
PrimitiveMode getGeometryShaderOutputPrimitiveType() const
{
return mGeometryShaderOutputPrimitiveType;
}
int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
private: private:
// TODO(timvp): http://anglebug.com/3570: Investigate removing these friend // TODO(timvp): http://anglebug.com/3570: Investigate removing these friend
// class declarations and accessing the necessary members with getters/setters. // class declarations and accessing the necessary members with getters/setters.
...@@ -406,6 +420,12 @@ class ProgramExecutable final : public angle::Subject ...@@ -406,6 +420,12 @@ class ProgramExecutable final : public angle::Subject
ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings; ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings;
ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings; ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings;
ShaderMap<int> mLinkedShaderVersions; ShaderMap<int> mLinkedShaderVersions;
// GL_EXT_geometry_shader.
PrimitiveMode mGeometryShaderInputPrimitiveType;
PrimitiveMode mGeometryShaderOutputPrimitiveType;
int mGeometryShaderInvocations;
int mGeometryShaderMaxVertices;
}; };
} // namespace gl } // namespace gl
......
...@@ -766,10 +766,6 @@ void SerializeProgramState(gl::BinaryOutputStream *bos, const gl::ProgramState & ...@@ -766,10 +766,6 @@ void SerializeProgramState(gl::BinaryOutputStream *bos, const gl::ProgramState &
bos->writeBool(programState.isSeparable()); bos->writeBool(programState.isSeparable());
bos->writeBool(programState.hasEarlyFragmentTestsOptimization()); bos->writeBool(programState.hasEarlyFragmentTestsOptimization());
bos->writeInt(programState.getNumViews()); bos->writeInt(programState.getNumViews());
bos->writeEnum(programState.getGeometryShaderInputPrimitiveType());
bos->writeEnum(programState.getGeometryShaderOutputPrimitiveType());
bos->writeInt(programState.getGeometryShaderInvocations());
bos->writeInt(programState.getGeometryShaderMaxVertices());
bos->writeInt(programState.getDrawIDLocation()); bos->writeInt(programState.getDrawIDLocation());
bos->writeInt(programState.getBaseVertexLocation()); bos->writeInt(programState.getBaseVertexLocation());
bos->writeInt(programState.getBaseInstanceLocation()); bos->writeInt(programState.getBaseInstanceLocation());
......
...@@ -1697,8 +1697,14 @@ bool ValidateUseProgramStagesBase(const Context *context, ...@@ -1697,8 +1697,14 @@ bool ValidateUseProgramStagesBase(const Context *context,
{ {
// GL_INVALID_VALUE is generated if shaders contains set bits that are not recognized, and is // GL_INVALID_VALUE is generated if shaders contains set bits that are not recognized, and is
// not the reserved value GL_ALL_SHADER_BITS. // not the reserved value GL_ALL_SHADER_BITS.
const GLbitfield knownShaderBits = GLbitfield knownShaderBits =
GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT | GL_COMPUTE_SHADER_BIT; GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT | GL_COMPUTE_SHADER_BIT;
if (context->getClientVersion() == ES_3_2 || context->getExtensions().geometryShader)
{
knownShaderBits |= GL_GEOMETRY_SHADER_BIT;
}
if ((stages & ~knownShaderBits) && (stages != GL_ALL_SHADER_BITS)) if ((stages & ~knownShaderBits) && (stages != GL_ALL_SHADER_BITS))
{ {
context->validationError(GL_INVALID_VALUE, kUnrecognizedShaderStageBit); context->validationError(GL_INVALID_VALUE, kUnrecognizedShaderStageBit);
......
...@@ -1489,6 +1489,146 @@ void main() ...@@ -1489,6 +1489,146 @@ void main()
EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue); EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue);
} }
// Tests separating the VS from the GS/FS and then modifying the shader.
TEST_P(GeometryShaderTest, RecompileSeparableVSWithVaryings)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
// Errors in D3D11/GL. No plans to fix this.
ANGLE_SKIP_TEST_IF(!IsVulkan());
// http://anglebug.com/5506
ANGLE_SKIP_TEST_IF(IsVulkan());
const char *kVS = R"(#version 310 es
precision mediump float;
in vec4 position;
out vec4 vgVarying;
uniform vec4 uniVec;
void main()
{
vgVarying = uniVec;
gl_Position = position;
})";
const char *kGS = R"(#version 310 es
#extension GL_EXT_geometry_shader : require
precision mediump float;
layout (triangles) in;
layout (triangle_strip, max_vertices = 4) out;
in vec4 vgVarying[];
layout(location = 5) out vec4 gfVarying;
void main()
{
for (int n = 0; n < gl_in.length(); n++)
{
gl_Position = gl_in[n].gl_Position;
gfVarying = vgVarying[n];
EmitVertex();
}
EndPrimitive();
})";
const char *kFS = R"(#version 310 es
precision mediump float;
layout(location = 5) in vec4 gfVarying;
out vec4 fOut;
void main()
{
fOut = gfVarying;
})";
GLShader vertShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &kVS, nullptr);
glCompileShader(vertShader);
GLProgram vertProg;
glProgramParameteri(vertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(vertProg, vertShader);
glLinkProgram(vertProg);
ASSERT_GL_NO_ERROR();
GLShader geomShader(GL_GEOMETRY_SHADER);
glShaderSource(geomShader, 1, &kGS, nullptr);
glCompileShader(geomShader);
GLShader fragShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &kFS, nullptr);
glCompileShader(fragShader);
GLProgram geomFragProg;
glProgramParameteri(geomFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(geomFragProg, geomShader);
glAttachShader(geomFragProg, fragShader);
glLinkProgram(geomFragProg);
ASSERT_GL_NO_ERROR();
GLProgramPipeline pipeline;
glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertProg);
glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, geomFragProg);
glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, geomFragProg);
glBindProgramPipeline(pipeline);
glActiveShaderProgram(pipeline, vertProg);
GLint uniLoc = glGetUniformLocation(vertProg, "uniVec");
ASSERT_NE(-1, uniLoc);
glUniform4f(uniLoc, 0, 1, 0, 1);
ASSERT_GL_NO_ERROR();
drawQuadPPO(vertProg, "position", 0.5f, 1.0f);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
// Do it again with deleted shaders.
vertProg.reset();
geomFragProg.reset();
pipeline.reset();
glProgramParameteri(vertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(vertProg, vertShader);
glLinkProgram(vertProg);
// Mess up the VS.
const char *otherVS = essl1_shaders::vs::Texture2D();
glShaderSource(vertShader, 1, &otherVS, nullptr);
glCompileShader(vertShader);
ASSERT_GL_NO_ERROR();
glProgramParameteri(geomFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
glAttachShader(geomFragProg, geomShader);
glAttachShader(geomFragProg, fragShader);
glLinkProgram(geomFragProg);
// Mess up the FS.
const char *otherFS = essl1_shaders::fs::Texture2D();
glShaderSource(fragShader, 1, &otherFS, nullptr);
glCompileShader(fragShader);
ASSERT_GL_NO_ERROR();
glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertProg);
glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, geomFragProg);
glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, geomFragProg);
glBindProgramPipeline(pipeline);
glActiveShaderProgram(pipeline, vertProg);
uniLoc = glGetUniformLocation(vertProg, "uniVec");
ASSERT_NE(-1, uniLoc);
glUniform4f(uniLoc, 0, 1, 0, 1);
ASSERT_GL_NO_ERROR();
drawQuadPPO(vertProg, "position", 0.5f, 1.0f);
EXPECT_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),
......
...@@ -147,6 +147,15 @@ class GLShader : angle::NonCopyable ...@@ -147,6 +147,15 @@ class GLShader : angle::NonCopyable
operator GLuint() { return get(); } operator GLuint() { return get(); }
void reset()
{
if (mHandle)
{
glDeleteShader(mHandle);
mHandle = 0;
}
}
private: private:
GLuint mHandle; GLuint mHandle;
}; };
...@@ -157,13 +166,7 @@ class GLProgram ...@@ -157,13 +166,7 @@ class GLProgram
public: public:
GLProgram() : mHandle(0) {} GLProgram() : mHandle(0) {}
~GLProgram() ~GLProgram() { reset(); }
{
if (mHandle)
{
glDeleteProgram(mHandle);
}
}
void makeEmpty() { mHandle = glCreateProgram(); } void makeEmpty() { mHandle = glCreateProgram(); }
...@@ -202,7 +205,23 @@ class GLProgram ...@@ -202,7 +205,23 @@ class GLProgram
bool valid() const { return mHandle != 0; } bool valid() const { return mHandle != 0; }
GLuint get() { return mHandle; } GLuint get()
{
if (!mHandle)
{
makeEmpty();
}
return mHandle;
}
void reset()
{
if (mHandle)
{
glDeleteProgram(mHandle);
mHandle = 0;
}
}
operator GLuint() { return get(); } operator GLuint() { return get(); }
......
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