Add detachShader capture calls in MEC

This change adds a capture call to detach shader
object before deleting the shader object in function
GenerateLinkedProgram(), if that is also what the app does.
GenerateLinkedProgram() is part of the Mid Execution Capture
(MEC), and the purpose of the MEC is to setup a program that
more closely mirrors the original app.

The game World Cricket Championship2 detaches the shader object
before deleting the shader object. With this change, we can follow
the same behavior in GenerateLinkedProgram(). This ensures that
the Shader Object refcount is decremented to 0 before the
CaptureDeleteShader call is applied, and the ShaderProgramID
handle assigned to the Shader Object will be released and
can be reused for subsequent glCreateShader calls. The total number
of ShaderProgramID we need will be consistent between
SetupReplayContextShared() and the game uses.
We are allocating memory slots for gUniformLocations2 array
based on the total number of ShaderProgramID the game uses.
Keeping the ShaderProgramID counts the same between
trace replay and the game ensures we allocate the right amount
of memory for the trace replay.

Bug: angleproject:6621
Bug: b/194508692
Change-Id: Ib2810b486a6e9108db2a32f084d650a25f14bebd
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3246533
Reviewed-by: Tim Van Patten <timvp@google.com>
Reviewed-by: Cody Northrop <cnorthrop@google.com>
Commit-Queue: Yuxin Hu <yuxinhu@google.com>
This commit is contained in:
YuxinHu 2021-10-27 01:25:11 +00:00 коммит произвёл Angle LUCI CQ
Родитель ab514d4ac0
Коммит a514df081d
1 изменённых файлов: 40 добавлений и 13 удалений

Просмотреть файл

@ -2358,18 +2358,23 @@ void GenerateLinkedProgram(const gl::Context *context,
std::vector<CallCapture> *setupCalls,
gl::Program *program,
gl::ShaderProgramID id,
gl::ShaderProgramID tempIDStart,
const ProgramSources &linkedSources)
{
// Bump up our max program ID before creating temp shaders
resourceTracker->onShaderProgramAccess(id);
// Use max ID as a temporary shader ID.
// Note this isn't the real ID of the shader, just a lookup into the gShaderProgram map.
gl::ShaderProgramID tempShaderID = {resourceTracker->getMaxShaderPrograms()};
// A map to store the gShaderProgram map lookup index of the temp shaders we attached below. We
// need this map to retrieve the lookup index to pass to CaptureDetachShader calls at the end of
// GenerateLinkedProgram.
PackedEnumMap<gl::ShaderType, gl::ShaderProgramID> tempShaderIDTracker;
// Compile with last linked sources.
for (gl::ShaderType shaderType : program->getExecutable().getLinkedShaderStages())
{
// Bump the max shader program id for each new tempIDStart we use to create, compile, and
// attach the temp shader object.
resourceTracker->onShaderProgramAccess(tempIDStart);
// Store the tempIDStart in the tempShaderIDTracker to retrieve for CaptureDetachShader
// calls later.
tempShaderIDTracker[shaderType] = tempIDStart;
const std::string &sourceString = linkedSources[shaderType];
const char *sourcePointer = sourceString.c_str();
@ -2386,12 +2391,15 @@ void GenerateLinkedProgram(const gl::Context *context,
}
// Compile and attach the temporary shader. Then free it immediately.
Capture(setupCalls, CaptureCreateShader(replayState, true, shaderType, tempShaderID.value));
Capture(setupCalls, CaptureCreateShader(replayState, true, shaderType, tempIDStart.value));
Capture(setupCalls,
CaptureShaderSource(replayState, true, tempShaderID, 1, &sourcePointer, nullptr));
Capture(setupCalls, CaptureCompileShader(replayState, true, tempShaderID));
Capture(setupCalls, CaptureAttachShader(replayState, true, id, tempShaderID));
Capture(setupCalls, CaptureDeleteShader(replayState, true, tempShaderID));
CaptureShaderSource(replayState, true, tempIDStart, 1, &sourcePointer, nullptr));
Capture(setupCalls, CaptureCompileShader(replayState, true, tempIDStart));
Capture(setupCalls, CaptureAttachShader(replayState, true, id, tempIDStart));
// Increment tempIDStart to get a new gShaderProgram map index for the next linked stage
// shader object. We can't reuse the same tempIDStart as we need to retrieve the index of
// each attached shader object later to pass to CaptureDetachShader calls.
tempIDStart.value += 1;
}
// Gather XFB varyings
@ -2457,6 +2465,22 @@ void GenerateLinkedProgram(const gl::Context *context,
Capture(setupCalls, CaptureUniformBlockBinding(replayState, true, id, {uniformBlockIndex},
blockBinding));
}
// Add DetachShader call if that's what the app does, so that the
// ResourceManagerBase::mHandleAllocator can release the ShaderProgramID handle assigned to the
// shader object when glDeleteShader is called. This ensures the ShaderProgramID handles used in
// SetupReplayContextShared() are consistent with the ShaderProgramID handles used by the app.
for (gl::ShaderType shaderType : program->getExecutable().getLinkedShaderStages())
{
gl::Shader *attachedShader = program->getAttachedShader(shaderType);
if (attachedShader == nullptr)
{
Capture(setupCalls,
CaptureDetachShader(replayState, true, id, tempShaderIDTracker[shaderType]));
}
Capture(setupCalls,
CaptureDeleteShader(replayState, true, tempShaderIDTracker[shaderType]));
}
}
// TODO(http://anglebug.com/4599): Improve reset/restore call generation
@ -3016,6 +3040,7 @@ void CaptureShareGroupMidExecutionSetup(const gl::Context *context,
shadersAndPrograms.getProgramsForCaptureAndPerf();
// Capture Program binary state.
gl::ShaderProgramID tempShaderStartID = {resourceTracker->getMaxShaderPrograms()};
for (const auto &programIter : programs)
{
gl::ShaderProgramID id = {programIter.first};
@ -3037,7 +3062,7 @@ void CaptureShareGroupMidExecutionSetup(const gl::Context *context,
cap(CaptureCreateProgram(replayState, true, id.value));
GenerateLinkedProgram(context, replayState, resourceTracker, setupCalls, program, id,
linkedSources);
tempShaderStartID, linkedSources);
// Update the program in replayState
if (!replayState.getProgram() || replayState.getProgram()->id() != program->id())
@ -4787,8 +4812,10 @@ void FrameCaptureShared::overrideProgramBinary(const gl::Context *context,
gl::Program *program = context->getProgramResolveLink(id);
ASSERT(program);
mResourceTracker.onShaderProgramAccess(id);
gl::ShaderProgramID tempShaderStartID = {mResourceTracker.getMaxShaderPrograms()};
GenerateLinkedProgram(context, context->getState(), &mResourceTracker, &outCalls, program, id,
getProgramSources(id));
tempShaderStartID, getProgramSources(id));
}
void FrameCaptureShared::maybeOverrideEntryPoint(const gl::Context *context,