Commit fbfecbe2 by Tim Van Patten Committed by Commit Bot

Capture/Replay: Add PPO/glProgramUniform support

Command and Conquer: Rivals requires additional frame capture API support: - Program Pipeline Objects - glProgramUniform* Bug: angleproject:5830 Change-Id: I159086f92d2dfead0a513cd17fadeda7df92f408 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2809891 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 4f68a4ee
......@@ -1151,6 +1151,28 @@ ShaderType GetShaderTypeFromBitfield(size_t singleShaderType)
}
}
GLbitfield GetBitfieldFromShaderType(ShaderType shaderType)
{
switch (shaderType)
{
case ShaderType::Vertex:
return GL_VERTEX_SHADER_BIT;
case ShaderType::Fragment:
return GL_FRAGMENT_SHADER_BIT;
case ShaderType::Compute:
return GL_COMPUTE_SHADER_BIT;
case ShaderType::Geometry:
return GL_GEOMETRY_SHADER_BIT;
case ShaderType::TessControl:
return GL_TESS_CONTROL_SHADER_BIT;
case ShaderType::TessEvaluation:
return GL_TESS_EVALUATION_SHADER_BIT;
default:
UNREACHABLE();
return GL_ZERO;
}
}
bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType)
{
switch (shaderType)
......
......@@ -252,6 +252,7 @@ enum class SrgbWriteControlMode
};
ShaderType GetShaderTypeFromBitfield(size_t singleShaderType);
GLbitfield GetBitfieldFromShaderType(ShaderType shaderType);
bool ShaderTypeSupportsTransformFeedback(ShaderType shaderType);
// Given a set of shader stages, returns the last vertex processing stage. This is the stage that
// interfaces the fragment shader.
......
......@@ -863,7 +863,14 @@ GLuint Context::createShaderProgramv(ShaderType type, GLsizei count, const GLcha
return 0u;
}
programObject->detachShader(this, shaderObject);
// If frame capture is enabled, don't detach the shader since we need the following
// to recreate the Shader and Program during MEC setup:
// 1.) Shader ID
// 2.) Shader source
if (!getFrameCapture()->enabled())
{
programObject->detachShader(this, shaderObject);
}
}
InfoLog &programInfoLog = programObject->getExecutable().getInfoLog();
......
......@@ -890,6 +890,11 @@ class State : angle::NonCopyable
const std::vector<ImageUnit> &getImageUnits() const { return mImageUnits; }
const ProgramPipelineManager *getProgramPipelineManagerForCapture() const
{
return mProgramPipelineManager;
}
private:
friend class Context;
......
......@@ -527,7 +527,8 @@ void WriteCppReplayForCall(const CallCapture &call,
std::ostringstream callOut;
if (call.entryPoint == EntryPoint::GLCreateShader ||
call.entryPoint == EntryPoint::GLCreateProgram)
call.entryPoint == EntryPoint::GLCreateProgram ||
call.entryPoint == EntryPoint::GLCreateShaderProgramv)
{
GLuint id = call.params.getReturnValue().value.GLuintVal;
callOut << "gShaderProgramMap[" << id << "] = ";
......@@ -1623,10 +1624,9 @@ void CaptureUpdateUniformValues(const gl::State &replayState,
const std::vector<gl::LinkedUniform> &uniforms = program->getState().getUniforms();
for (size_t i = 0; i < uniforms.size(); i++)
for (const gl::LinkedUniform &uniform : uniforms)
{
const gl::LinkedUniform &uniform = uniforms[i];
std::string uniformName = uniform.name;
std::string uniformName = uniform.name;
int uniformCount = 1;
if (uniform.isArray())
......@@ -1651,11 +1651,15 @@ void CaptureUpdateUniformValues(const gl::State &replayState,
// If the uniform is unused, just continue
if (readLoc.value == -1)
{
continue;
}
// Image uniforms are special and cannot be set this way
if (typeInfo->isImageType)
{
continue;
}
// Samplers should be populated with GL_INT, regardless of return type
if (typeInfo->isSampler)
......@@ -2704,6 +2708,8 @@ void CaptureMidExecutionSetup(const gl::Context *context,
shadersAndPrograms.getShadersForCapture();
const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programs =
shadersAndPrograms.getProgramsForCaptureAndPerf();
const gl::ProgramPipelineManager *programPipelineManager =
apiState.getProgramPipelineManagerForCapture();
// Capture Program binary state. Use max ID as a temporary shader ID.
gl::ShaderProgramID tempShaderID = {resourceTracker->getMaxShaderPrograms()};
......@@ -2770,10 +2776,21 @@ void CaptureMidExecutionSetup(const gl::Context *context,
continue;
}
ASSERT(attrib.location != -1);
// Separable programs may not have a VS, meaning it may not have attributes.
if (program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Vertex))
{
ASSERT(attrib.location != -1);
cap(CaptureBindAttribLocation(replayState, true, id,
static_cast<GLuint>(attrib.location),
attrib.name.c_str()));
}
}
cap(CaptureBindAttribLocation(
replayState, true, id, static_cast<GLuint>(attrib.location), attrib.name.c_str()));
if (program->isSeparable())
{
// MEC manually recreates separable programs, rather than attempting to recreate a call
// to glCreateShaderProgramv(), so insert a call to mark it separable.
cap(CaptureProgramParameteri(replayState, true, id, GL_PROGRAM_SEPARABLE, GL_TRUE));
}
cap(CaptureLinkProgram(replayState, true, id));
......@@ -2793,6 +2810,36 @@ void CaptureMidExecutionSetup(const gl::Context *context,
resourceTracker->onShaderProgramAccess(id);
}
for (const auto &ppoIterator : *programPipelineManager)
{
gl::ProgramPipeline *pipeline = ppoIterator.second;
gl::ProgramPipelineID id = {ppoIterator.first};
cap(CaptureGenProgramPipelines(replayState, true, 1, &id));
MaybeCaptureUpdateResourceIDs(setupCalls);
// PPOs can contain graphics and compute programs, so loop through all shader types rather
// than just the linked ones since getLinkedShaderStages() will return either only graphics
// or compute stages.
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
gl::Program *program = pipeline->getShaderProgram(shaderType);
if (!program)
{
continue;
}
ASSERT(program->isLinked());
GLbitfield gLbitfield = GetBitfieldFromShaderType(shaderType);
cap(CaptureUseProgramStages(replayState, true, pipeline->id(), gLbitfield,
program->id()));
}
gl::Program *program = pipeline->getActiveShaderProgram();
if (program)
{
cap(CaptureActiveShaderProgram(replayState, true, id, program->id()));
}
}
// Handle shaders.
for (const auto &shaderIter : shaders)
{
......@@ -2840,6 +2887,20 @@ void CaptureMidExecutionSetup(const gl::Context *context,
cap(CaptureUseProgram(replayState, true, apiState.getProgram()->id()));
CaptureUpdateCurrentProgram(setupCalls->back(), setupCalls);
}
else if (apiState.getProgramPipeline())
{
// glUseProgram() is called above to update the necessary uniform values for each program
// that's being recreated. If there is no program currently bound, then we need to unbind
// the last bound program so the PPO will be used instead:
// 7.4 Program Pipeline Objects
// If no current program object has been established by UseProgram, the program objects used
// for each shader stage and for uniform updates are taken from the bound program pipeline
// object, if any. If there is a current program object established by UseProgram, the bound
// program pipeline object has no effect on rendering or uniform updates.
cap(CaptureUseProgram(replayState, true, {0}));
CaptureUpdateCurrentProgram(setupCalls->back(), setupCalls);
cap(CaptureBindProgramPipeline(replayState, true, apiState.getProgramPipeline()->id()));
}
// TODO(http://anglebug.com/3662): ES 3.x objects.
......@@ -4040,6 +4101,27 @@ void FrameCapture::maybeCapturePreCallUpdates(const gl::Context *context, CallCa
break;
}
case EntryPoint::GLCreateShaderProgramv:
{
// Refresh the cached shader sources.
// The command CreateShaderProgramv() creates a stand-alone program from an array of
// null-terminated source code strings for a single shader type, so we need update the
// Shader and Program sources, similar to GLCompileShader + GLLinkProgram handling.
gl::ShaderProgramID programID = {call.params.getReturnValue().value.GLuintVal};
const ParamCapture &paramCapture =
call.params.getParam("typePacked", ParamType::TShaderType, 0);
gl::ShaderType shaderType = paramCapture.value.ShaderTypeVal;
gl::Program *program = context->getProgramResolveLink(programID);
ASSERT(program);
const gl::Shader *shader = program->getAttachedShader(shaderType);
ASSERT(shader);
FrameCaptureShared *frameCaptureShared =
context->getShareGroup()->getFrameCaptureShared();
frameCaptureShared->setShaderSource(shader->getHandle(), shader->getSourceString());
frameCaptureShared->setProgramSources(programID, GetAttachedProgramSources(program));
break;
}
case EntryPoint::GLCompileShader:
{
// Refresh the cached shader sources.
......@@ -4243,6 +4325,15 @@ void FrameCapture::maybeCapturePostCallUpdates(const gl::Context *context)
const CallCapture &lastCall = mFrameCalls.back();
switch (lastCall.entryPoint)
{
case EntryPoint::GLCreateShaderProgramv:
{
gl::ShaderProgramID programId;
programId.value = lastCall.params.getReturnValue().value.GLuintVal;
const gl::Program *program = context->getProgramResolveLink(programId);
CaptureUpdateUniformLocations(program, &mFrameCalls);
CaptureUpdateUniformBlockIndexes(program, &mFrameCalls);
break;
}
case EntryPoint::GLLinkProgram:
{
const ParamCapture &param =
......@@ -4935,6 +5026,21 @@ void CaptureGenHandlesImpl(GLsizei n, GLuint *handles, ParamCapture *paramCaptur
CaptureMemory(handles, paramCapture->readBufferSizeBytes, paramCapture);
}
void CaptureShaderStrings(GLsizei count,
const GLchar *const *strings,
const GLint *length,
ParamCapture *paramCapture)
{
for (GLsizei index = 0; index < count; ++index)
{
size_t len = ((length && length[index] >= 0) ? length[index] : strlen(strings[index]));
// includes the '\0' suffix
std::vector<uint8_t> data(len + 1, 0);
memcpy(data.data(), strings[index], len);
paramCapture->data.emplace_back(std::move(data));
}
}
template <>
void WriteParamValueReplay<ParamType::TGLboolean>(std::ostream &os,
const CallCapture &call,
......
......@@ -516,6 +516,11 @@ void CaptureGenHandles(GLsizei n, T *handles, ParamCapture *paramCapture)
CaptureGenHandlesImpl(n, reinterpret_cast<GLuint *>(handles), paramCapture);
}
void CaptureShaderStrings(GLsizei count,
const GLchar *const *strings,
const GLint *length,
ParamCapture *paramCapture);
template <ParamType ParamT, typename T>
void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value);
......
......@@ -649,14 +649,7 @@ void CaptureShaderSource_string(const State &glState,
const GLint *length,
ParamCapture *paramCapture)
{
for (GLsizei index = 0; index < count; ++index)
{
size_t len = ((length && length[index] >= 0) ? length[index] : strlen(string[index]));
// includes the '\0' suffix
std::vector<uint8_t> data(len + 1, 0);
memcpy(data.data(), string[index], len);
paramCapture->data.emplace_back(std::move(data));
}
CaptureShaderStrings(count, string, length, paramCapture);
}
void CaptureShaderSource_length(const State &glState,
......
......@@ -20,7 +20,7 @@ void CaptureCreateShaderProgramv_strings(const State &glState,
const GLchar *const *strings,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureShaderStrings(count, strings, nullptr, paramCapture);
}
void CaptureDeleteProgramPipelines_pipelinesPacked(const State &glState,
......@@ -273,7 +273,7 @@ void CaptureProgramUniform1fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * count, paramCapture);
}
void CaptureProgramUniform1iv_value(const State &glState,
......@@ -284,7 +284,7 @@ void CaptureProgramUniform1iv_value(const State &glState,
const GLint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLint) * count, paramCapture);
}
void CaptureProgramUniform1uiv_value(const State &glState,
......@@ -295,7 +295,7 @@ void CaptureProgramUniform1uiv_value(const State &glState,
const GLuint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLuint) * count, paramCapture);
}
void CaptureProgramUniform2fv_value(const State &glState,
......@@ -306,7 +306,7 @@ void CaptureProgramUniform2fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 2 * count, paramCapture);
}
void CaptureProgramUniform2iv_value(const State &glState,
......@@ -317,7 +317,7 @@ void CaptureProgramUniform2iv_value(const State &glState,
const GLint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLint) * 2 * count, paramCapture);
}
void CaptureProgramUniform2uiv_value(const State &glState,
......@@ -328,7 +328,7 @@ void CaptureProgramUniform2uiv_value(const State &glState,
const GLuint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLuint) * 2 * count, paramCapture);
}
void CaptureProgramUniform3fv_value(const State &glState,
......@@ -339,7 +339,7 @@ void CaptureProgramUniform3fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 3 * count, paramCapture);
}
void CaptureProgramUniform3iv_value(const State &glState,
......@@ -350,7 +350,7 @@ void CaptureProgramUniform3iv_value(const State &glState,
const GLint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLint) * 3 * count, paramCapture);
}
void CaptureProgramUniform3uiv_value(const State &glState,
......@@ -361,7 +361,7 @@ void CaptureProgramUniform3uiv_value(const State &glState,
const GLuint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLuint) * 3 * count, paramCapture);
}
void CaptureProgramUniform4fv_value(const State &glState,
......@@ -372,7 +372,7 @@ void CaptureProgramUniform4fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 4 * count, paramCapture);
}
void CaptureProgramUniform4iv_value(const State &glState,
......@@ -383,7 +383,7 @@ void CaptureProgramUniform4iv_value(const State &glState,
const GLint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLint) * 4 * count, paramCapture);
}
void CaptureProgramUniform4uiv_value(const State &glState,
......@@ -394,7 +394,7 @@ void CaptureProgramUniform4uiv_value(const State &glState,
const GLuint *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLuint) * 4 * count, paramCapture);
}
void CaptureProgramUniformMatrix2fv_value(const State &glState,
......@@ -406,7 +406,7 @@ void CaptureProgramUniformMatrix2fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 2 * 2 * count, paramCapture);
}
void CaptureProgramUniformMatrix2x3fv_value(const State &glState,
......@@ -418,7 +418,7 @@ void CaptureProgramUniformMatrix2x3fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 2 * 3 * count, paramCapture);
}
void CaptureProgramUniformMatrix2x4fv_value(const State &glState,
......@@ -430,7 +430,7 @@ void CaptureProgramUniformMatrix2x4fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 2 * 4 * count, paramCapture);
}
void CaptureProgramUniformMatrix3fv_value(const State &glState,
......@@ -442,7 +442,7 @@ void CaptureProgramUniformMatrix3fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 3 * 3 * count, paramCapture);
}
void CaptureProgramUniformMatrix3x2fv_value(const State &glState,
......@@ -454,7 +454,7 @@ void CaptureProgramUniformMatrix3x2fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 3 * 2 * count, paramCapture);
}
void CaptureProgramUniformMatrix3x4fv_value(const State &glState,
......@@ -466,7 +466,7 @@ void CaptureProgramUniformMatrix3x4fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 3 * 4 * count, paramCapture);
}
void CaptureProgramUniformMatrix4fv_value(const State &glState,
......@@ -478,7 +478,7 @@ void CaptureProgramUniformMatrix4fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 4 * 4 * count, paramCapture);
}
void CaptureProgramUniformMatrix4x2fv_value(const State &glState,
......@@ -490,7 +490,7 @@ void CaptureProgramUniformMatrix4x2fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 4 * 2 * count, paramCapture);
}
void CaptureProgramUniformMatrix4x3fv_value(const State &glState,
......@@ -502,7 +502,7 @@ void CaptureProgramUniformMatrix4x3fv_value(const State &glState,
const GLfloat *value,
ParamCapture *paramCapture)
{
UNIMPLEMENTED();
CaptureMemory(value, sizeof(GLfloat) * 4 * 3 * count, paramCapture);
}
} // namespace gl
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