mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
Add per-fragment information to OpenGL Pixel History
This commit is contained in:
@@ -22,6 +22,9 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <algorithm>
|
||||
#include "data/glsl_shaders.h"
|
||||
#include "gl_common.h"
|
||||
#include "gl_driver.h"
|
||||
#include "gl_replay.h"
|
||||
|
||||
@@ -41,6 +44,8 @@ struct GLPixelHistoryResources
|
||||
GLuint colorImage;
|
||||
GLuint dsImage;
|
||||
GLuint frameBuffer;
|
||||
GLuint primitiveIdFragmentShader;
|
||||
std::unordered_map<GLuint, GLuint> programs;
|
||||
};
|
||||
|
||||
enum class OpenGLTest
|
||||
@@ -52,6 +57,82 @@ enum class OpenGLTest
|
||||
NumTests
|
||||
};
|
||||
|
||||
enum class PerFragmentQueryType
|
||||
{
|
||||
ShaderOut,
|
||||
PostMod,
|
||||
PrimitiveId
|
||||
};
|
||||
|
||||
GLuint GetPrimitiveIdProgram(WrappedOpenGL *driver, GLReplay *replay,
|
||||
GLPixelHistoryResources &resources, GLuint currentProgram)
|
||||
{
|
||||
auto programIterator = resources.programs.find(currentProgram);
|
||||
if(programIterator != resources.programs.end())
|
||||
{
|
||||
return programIterator->second;
|
||||
}
|
||||
|
||||
GLuint newProgram;
|
||||
|
||||
GLint numAttachedShaders;
|
||||
driver->glGetProgramiv(currentProgram, eGL_ATTACHED_SHADERS, &numAttachedShaders);
|
||||
|
||||
newProgram = driver->glCreateProgram();
|
||||
|
||||
GLuint *attachedShaders = new GLuint[numAttachedShaders];
|
||||
|
||||
driver->glGetAttachedShaders(currentProgram, numAttachedShaders, &numAttachedShaders,
|
||||
attachedShaders);
|
||||
|
||||
ShaderReflection *vsRefl = NULL;
|
||||
for(int i = 0; i < numAttachedShaders; ++i)
|
||||
{
|
||||
GLint shaderType;
|
||||
driver->glGetShaderiv(attachedShaders[i], eGL_SHADER_TYPE, &shaderType);
|
||||
|
||||
if(shaderType != eGL_FRAGMENT_SHADER)
|
||||
{
|
||||
driver->glAttachShader(newProgram, attachedShaders[i]);
|
||||
}
|
||||
|
||||
if(shaderType == eGL_VERTEX_SHADER)
|
||||
{
|
||||
vsRefl = replay->GetShader(ResourceId(), driver->GetResourceManager()->GetResID(
|
||||
ShaderRes(driver->GetCtx(), attachedShaders[i])),
|
||||
ShaderEntryPoint());
|
||||
}
|
||||
}
|
||||
delete[] attachedShaders;
|
||||
|
||||
driver->glAttachShader(newProgram, resources.primitiveIdFragmentShader);
|
||||
if(vsRefl)
|
||||
{
|
||||
CopyProgramAttribBindings(currentProgram, newProgram, vsRefl);
|
||||
}
|
||||
driver->glLinkProgram(newProgram);
|
||||
|
||||
char buffer[1024] = {};
|
||||
GLint status = 0;
|
||||
driver->glGetProgramiv(newProgram, eGL_LINK_STATUS, &status);
|
||||
if(status == 0)
|
||||
{
|
||||
GL.glGetProgramInfoLog(newProgram, 1024, NULL, buffer);
|
||||
RDCERR("Shader error: %s", buffer);
|
||||
}
|
||||
|
||||
resources.programs[currentProgram] = newProgram;
|
||||
|
||||
PerStageReflections dstStages;
|
||||
driver->FillReflectionArray(ProgramRes(driver->GetCtx(), newProgram), dstStages);
|
||||
|
||||
PerStageReflections stages;
|
||||
driver->FillReflectionArray(ProgramRes(driver->GetCtx(), newProgram), stages);
|
||||
CopyProgramUniforms(stages, currentProgram, dstStages, newProgram);
|
||||
|
||||
return newProgram;
|
||||
}
|
||||
|
||||
bool PixelHistorySetupResources(WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
const TextureDescription &desc, const Subresource &sub,
|
||||
uint32_t numEvents)
|
||||
@@ -75,6 +156,16 @@ bool PixelHistorySetupResources(WrappedOpenGL *driver, GLPixelHistoryResources &
|
||||
desc.msSamp, 1);
|
||||
driver->glFramebufferTexture(eGL_FRAMEBUFFER, eGL_DEPTH_STENCIL_ATTACHMENT, resources.dsImage, 0);
|
||||
|
||||
// The pixel history primitive ID Fragment Shader requires at least version 420.
|
||||
// This is because it requires scalars to be swizzled something enabled
|
||||
// in version 420. We also require intBitsToFloat which is introduced in
|
||||
// version 330.
|
||||
int GLSLVersion = 420;
|
||||
|
||||
rdcstr fs = GenerateGLSLShader(GetEmbeddedResource(glsl_pixelhistory_primid_frag),
|
||||
ShaderType::GLSL, GLSLVersion);
|
||||
resources.primitiveIdFragmentShader = CreateShader(eGL_FRAGMENT_SHADER, fs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -83,6 +174,12 @@ bool PixelHistoryDestroyResources(WrappedOpenGL *driver, const GLPixelHistoryRes
|
||||
driver->glDeleteTextures(1, &resources.colorImage);
|
||||
driver->glDeleteTextures(1, &resources.dsImage);
|
||||
driver->glDeleteFramebuffers(1, &resources.frameBuffer);
|
||||
driver->glDeleteShader(resources.primitiveIdFragmentShader);
|
||||
|
||||
for(const std::pair<const GLuint, GLuint> &resourceProgram : resources.programs)
|
||||
{
|
||||
driver->glDeleteProgram(resourceProgram.second);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -98,7 +195,7 @@ rdcarray<EventUsage> QueryModifyingEvents(WrappedOpenGL *driver, GLPixelHistoryR
|
||||
|
||||
driver->ReplayLog(0, events[0].eventId, eReplay_WithoutDraw);
|
||||
// execute the occlusion queries
|
||||
for(size_t i = 0; i < events.size(); i++)
|
||||
for(size_t i = 0; i < events.size(); ++i)
|
||||
{
|
||||
if(!(events[i].usage == ResourceUsage::Clear || isDirectWrite(events[i].usage)))
|
||||
{
|
||||
@@ -123,7 +220,7 @@ rdcarray<EventUsage> QueryModifyingEvents(WrappedOpenGL *driver, GLPixelHistoryR
|
||||
}
|
||||
}
|
||||
// read back the occlusion queries and generate the list of potentially modifying events
|
||||
for(size_t i = 0; i < events.size(); i++)
|
||||
for(size_t i = 0; i < events.size(); ++i)
|
||||
{
|
||||
if(events[i].usage == ResourceUsage::Clear || isDirectWrite(events[i].usage))
|
||||
{
|
||||
@@ -136,9 +233,10 @@ rdcarray<EventUsage> QueryModifyingEvents(WrappedOpenGL *driver, GLPixelHistoryR
|
||||
}
|
||||
else
|
||||
{
|
||||
int numFragments;
|
||||
driver->glGetQueryObjectiv(occlusionQueries[i], eGL_QUERY_RESULT, &numFragments);
|
||||
if(numFragments > 0)
|
||||
uint32_t numSamples;
|
||||
driver->glGetQueryObjectuiv(occlusionQueries[i], eGL_QUERY_RESULT, &numSamples);
|
||||
|
||||
if(numSamples > 0)
|
||||
{
|
||||
PixelModification mod;
|
||||
RDCEraseEl(mod);
|
||||
@@ -153,42 +251,51 @@ rdcarray<EventUsage> QueryModifyingEvents(WrappedOpenGL *driver, GLPixelHistoryR
|
||||
return modEvents;
|
||||
}
|
||||
|
||||
void QueryPostModPixelValues(WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
const rdcarray<EventUsage> &modEvents, int x, int y,
|
||||
rdcarray<PixelModification> &history)
|
||||
std::map<uint32_t, uint32_t> QueryNumFragmentsByEvent(WrappedOpenGL *driver,
|
||||
GLPixelHistoryResources &resources,
|
||||
const rdcarray<EventUsage> &modEvents, int x,
|
||||
int y)
|
||||
{
|
||||
driver->glBindFramebuffer(eGL_FRAMEBUFFER, resources.frameBuffer);
|
||||
driver->glClear(eGL_COLOR_BUFFER_BIT | eGL_DEPTH_BUFFER_BIT | eGL_STENCIL_BUFFER_BIT);
|
||||
driver->ReplayLog(0, modEvents[0].eventId, eReplay_WithoutDraw);
|
||||
|
||||
for(size_t i = 0; i < modEvents.size(); i++)
|
||||
std::map<uint32_t, uint32_t> eventFragments;
|
||||
|
||||
for(size_t i = 0; i < modEvents.size(); ++i)
|
||||
{
|
||||
GLint savedReadFramebuffer, savedDrawFramebuffer;
|
||||
driver->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, &savedDrawFramebuffer);
|
||||
driver->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &savedReadFramebuffer);
|
||||
// bind our own framebuffer to save the pixel values
|
||||
driver->glBindFramebuffer(eGL_FRAMEBUFFER, resources.frameBuffer);
|
||||
driver->ReplayLog(modEvents[i].eventId, modEvents[i].eventId, eReplay_Full);
|
||||
if(!isDirectWrite(modEvents[i].usage) && modEvents[i].usage != ResourceUsage::Clear)
|
||||
{
|
||||
GLint savedReadFramebuffer, savedDrawFramebuffer;
|
||||
driver->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, &savedDrawFramebuffer);
|
||||
driver->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &savedReadFramebuffer);
|
||||
// bind our own framebuffer to save the pixel values
|
||||
driver->glBindFramebuffer(eGL_FRAMEBUFFER, resources.frameBuffer);
|
||||
driver->glStencilOp(eGL_INCR, eGL_INCR, eGL_INCR);
|
||||
driver->glStencilMask(0xff);
|
||||
driver->glClearStencil(0);
|
||||
driver->glClear(eGL_STENCIL_BUFFER_BIT);
|
||||
driver->glEnable(eGL_STENCIL_TEST);
|
||||
driver->ReplayLog(modEvents[i].eventId, modEvents[i].eventId, eReplay_Full);
|
||||
|
||||
// read the post mod pixel value into the history event
|
||||
ModificationValue modValue;
|
||||
PixelValue pixelValue;
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT, (void *)pixelValue.floatValue.data());
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_DEPTH_COMPONENT, eGL_FLOAT, (void *)&modValue.depth);
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_STENCIL_INDEX, eGL_INT, (void *)&modValue.stencil);
|
||||
modValue.col = pixelValue;
|
||||
// read and get number of fragments
|
||||
uint32_t numFragments;
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_STENCIL_INDEX, eGL_INT, (void *)&numFragments);
|
||||
|
||||
history[i].postMod = modValue;
|
||||
eventFragments.emplace(modEvents[i].eventId, numFragments);
|
||||
|
||||
// restore the capture's framebuffer
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, savedDrawFramebuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, savedReadFramebuffer);
|
||||
// restore the capture's framebuffer
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, savedDrawFramebuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, savedReadFramebuffer);
|
||||
}
|
||||
|
||||
if(i < modEvents.size() - 1)
|
||||
{
|
||||
driver->ReplayLog(modEvents[i].eventId + 1, modEvents[i + 1].eventId, eReplay_WithoutDraw);
|
||||
}
|
||||
}
|
||||
|
||||
return eventFragments;
|
||||
}
|
||||
|
||||
bool QueryScissorTest(WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
@@ -277,13 +384,226 @@ void QueryFailedTests(WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that history objects are one-to-one mapped with modEvent objects
|
||||
RDCASSERT(history[i].eventId == modEvents[i].eventId);
|
||||
history[i].scissorClipped = failedTest == OpenGLTest::ScissorTest;
|
||||
history[i].stencilTestFailed = failedTest == OpenGLTest::StencilTest;
|
||||
history[i].depthTestFailed = failedTest == OpenGLTest::DepthTest;
|
||||
history[i].backfaceCulled = failedTest == OpenGLTest::FaceCulling;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void QueryPerFragmentValues(WrappedOpenGL *driver, GLReplay *replay,
|
||||
GLPixelHistoryResources &resources, const EventUsage &modEvent, int x,
|
||||
int y, rdcarray<PixelModification> &history,
|
||||
const std::map<uint32_t, uint32_t> &eventFragments,
|
||||
PerFragmentQueryType queryType)
|
||||
{
|
||||
driver->ReplayLog(0, modEvent.eventId - 1, eReplay_Full);
|
||||
driver->glBindFramebuffer(eGL_FRAMEBUFFER, resources.frameBuffer);
|
||||
driver->glReadBuffer(eGL_COLOR_ATTACHMENT0);
|
||||
|
||||
auto it = eventFragments.find(modEvent.eventId);
|
||||
uint32_t numFragments = (it != eventFragments.end()) ? it->second : 0;
|
||||
|
||||
driver->glEnable(eGL_SCISSOR_TEST);
|
||||
driver->glScissor(x, y, 1, 1);
|
||||
|
||||
driver->glClearStencil(0);
|
||||
|
||||
if(queryType == PerFragmentQueryType::ShaderOut || queryType == PerFragmentQueryType::PrimitiveId)
|
||||
{
|
||||
driver->glEnable(eGL_DEPTH_TEST);
|
||||
driver->glDepthFunc(eGL_ALWAYS);
|
||||
driver->glDepthMask(GL_TRUE);
|
||||
driver->glDisable(eGL_BLEND);
|
||||
}
|
||||
|
||||
driver->glStencilMask(0xff);
|
||||
driver->glStencilOp(eGL_INCR, eGL_INCR, eGL_INCR);
|
||||
driver->glEnable(eGL_STENCIL_TEST);
|
||||
|
||||
PixelModification referenceHistory;
|
||||
referenceHistory.eventId = modEvent.eventId;
|
||||
|
||||
auto historyIndex =
|
||||
std::lower_bound(history.begin(), history.end(), referenceHistory,
|
||||
[](const PixelModification &h1, const PixelModification &h2) -> bool {
|
||||
return h1.eventId < h2.eventId;
|
||||
});
|
||||
RDCASSERT(historyIndex != history.end());
|
||||
|
||||
if(queryType == PerFragmentQueryType::PostMod)
|
||||
{
|
||||
if(historyIndex != history.begin())
|
||||
{
|
||||
--historyIndex;
|
||||
|
||||
// Because we are replaying this draw into our own framebuffer
|
||||
// We need to set the values to the ones that they would be
|
||||
// before this draw call.
|
||||
driver->glClearColor(
|
||||
historyIndex->postMod.col.floatValue[0], historyIndex->postMod.col.floatValue[1],
|
||||
historyIndex->postMod.col.floatValue[2], historyIndex->postMod.col.floatValue[3]);
|
||||
|
||||
GLboolean depthWriteMask = false;
|
||||
driver->glGetBooleanv(eGL_DEPTH_WRITEMASK, &depthWriteMask);
|
||||
driver->glDepthMask(true);
|
||||
driver->glClearDepth(historyIndex->postMod.depth);
|
||||
|
||||
driver->glClear(eGL_COLOR_BUFFER_BIT | eGL_DEPTH_BUFFER_BIT);
|
||||
|
||||
driver->glDepthMask(depthWriteMask);
|
||||
++historyIndex;
|
||||
}
|
||||
}
|
||||
else if(queryType == PerFragmentQueryType::PrimitiveId)
|
||||
{
|
||||
// we expect this value to be overwritten by the primitive id shader. if not
|
||||
// it will cause an assertion that all color values are the same to fail
|
||||
driver->glClearColor(0.84f, 0.17f, 0.2f, 0.49f);
|
||||
driver->glClear(eGL_COLOR_BUFFER_BIT);
|
||||
|
||||
GLint currentProgram;
|
||||
|
||||
driver->glGetIntegerv(eGL_CURRENT_PROGRAM, ¤tProgram);
|
||||
|
||||
driver->glUseProgram(GetPrimitiveIdProgram(driver, replay, resources, currentProgram));
|
||||
}
|
||||
|
||||
for(size_t j = 0; j < std::max(numFragments, 1u); ++j)
|
||||
{
|
||||
ModificationValue modValue;
|
||||
PixelValue pixelValue;
|
||||
modValue.stencil = 0;
|
||||
driver->glStencilFunc(eGL_EQUAL, (int)j, 0xff);
|
||||
driver->glClear(eGL_STENCIL_BUFFER_BIT);
|
||||
|
||||
driver->ReplayLog(modEvent.eventId, modEvent.eventId, eReplay_Full);
|
||||
|
||||
if(queryType == PerFragmentQueryType::PrimitiveId)
|
||||
{
|
||||
int primitiveIds[4];
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT, (void *)primitiveIds);
|
||||
|
||||
RDCASSERT(primitiveIds[0] == primitiveIds[1] && primitiveIds[0] == primitiveIds[2] &&
|
||||
primitiveIds[0] == primitiveIds[3]);
|
||||
historyIndex->primitiveID = primitiveIds[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT, (void *)pixelValue.floatValue.data());
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_DEPTH_COMPONENT, eGL_FLOAT, (void *)&modValue.depth);
|
||||
|
||||
modValue.col = pixelValue;
|
||||
|
||||
if(queryType == PerFragmentQueryType::ShaderOut)
|
||||
{
|
||||
historyIndex->shaderOut = modValue;
|
||||
}
|
||||
else if(queryType == PerFragmentQueryType::PostMod)
|
||||
{
|
||||
historyIndex->postMod = modValue;
|
||||
}
|
||||
}
|
||||
++historyIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteClearValues(WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
const EventUsage clearEvent, int x, int y, rdcarray<PixelModification> &history)
|
||||
{
|
||||
driver->glBindFramebuffer(eGL_FRAMEBUFFER, resources.frameBuffer);
|
||||
driver->glClear(eGL_COLOR_BUFFER_BIT | eGL_DEPTH_BUFFER_BIT | eGL_STENCIL_BUFFER_BIT);
|
||||
driver->ReplayLog(0, clearEvent.eventId - 1, eReplay_WithoutDraw);
|
||||
|
||||
GLint savedReadFramebuffer, savedDrawFramebuffer;
|
||||
driver->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, &savedDrawFramebuffer);
|
||||
driver->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &savedReadFramebuffer);
|
||||
// bind our own framebuffer to save the pixel values
|
||||
driver->glBindFramebuffer(eGL_FRAMEBUFFER, resources.frameBuffer);
|
||||
driver->ReplayLog(clearEvent.eventId, clearEvent.eventId, eReplay_Full);
|
||||
|
||||
// read the post mod pixel value into the history event
|
||||
ModificationValue modValue;
|
||||
PixelValue pixelValue;
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT, (void *)pixelValue.floatValue.data());
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_DEPTH_COMPONENT, eGL_FLOAT, (void *)&modValue.depth);
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_STENCIL_INDEX, eGL_INT, (void *)&modValue.stencil);
|
||||
modValue.col = pixelValue;
|
||||
|
||||
PixelModification referenceHistory;
|
||||
referenceHistory.eventId = clearEvent.eventId;
|
||||
auto historyIndex =
|
||||
std::lower_bound(history.begin(), history.end(), referenceHistory,
|
||||
[](const PixelModification &h1, const PixelModification &h2) -> bool {
|
||||
return h1.eventId < h2.eventId;
|
||||
});
|
||||
|
||||
historyIndex->postMod = modValue;
|
||||
|
||||
// restore the capture's framebuffer
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, savedDrawFramebuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, savedReadFramebuffer);
|
||||
}
|
||||
|
||||
bool depthTestPassed(int depthFunc, float shaderOutputDepth, float depthInBuffer)
|
||||
{
|
||||
switch(depthFunc)
|
||||
{
|
||||
case eGL_NEVER: return false;
|
||||
case eGL_LESS: return shaderOutputDepth < depthInBuffer;
|
||||
case eGL_EQUAL: return shaderOutputDepth == depthInBuffer;
|
||||
case eGL_LEQUAL: return shaderOutputDepth <= depthInBuffer;
|
||||
case eGL_GREATER: return shaderOutputDepth > depthInBuffer;
|
||||
case eGL_NOTEQUAL: return shaderOutputDepth != depthInBuffer;
|
||||
case eGL_GEQUAL: return shaderOutputDepth >= depthInBuffer;
|
||||
case eGL_ALWAYS: return true;
|
||||
|
||||
default: RDCASSERT(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CalculateFragmentDepthTests(WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
const rdcarray<EventUsage> &modEvents,
|
||||
rdcarray<PixelModification> &history)
|
||||
{
|
||||
driver->ReplayLog(0, modEvents[0].eventId, eReplay_WithoutDraw);
|
||||
size_t historyIndex = 0;
|
||||
for(size_t i = 0; i < modEvents.size(); ++i)
|
||||
{
|
||||
for(; historyIndex < history.size() && modEvents[i].eventId == history[historyIndex].eventId;
|
||||
++historyIndex)
|
||||
{
|
||||
if(historyIndex == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(driver->glIsEnabled(eGL_DEPTH_TEST))
|
||||
{
|
||||
int depthFunc;
|
||||
driver->glGetIntegerv(eGL_DEPTH_FUNC, &depthFunc);
|
||||
|
||||
history[historyIndex].depthTestFailed = !depthTestPassed(
|
||||
depthFunc, history[historyIndex].shaderOut.depth, history[historyIndex].preMod.depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
// since there is no depth test, there is no failure.
|
||||
history[historyIndex].depthTestFailed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(i < modEvents.size() - 1)
|
||||
{
|
||||
driver->ReplayLog(modEvents[i].eventId + 1, modEvents[i + 1].eventId, eReplay_WithoutDraw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // end of anonymous namespace
|
||||
|
||||
rdcarray<PixelModification> GLReplay::PixelHistory(rdcarray<EventUsage> events, ResourceId target,
|
||||
uint32_t x, uint32_t y, const Subresource &sub,
|
||||
@@ -341,7 +661,45 @@ rdcarray<PixelModification> GLReplay::PixelHistory(rdcarray<EventUsage> events,
|
||||
}
|
||||
|
||||
QueryFailedTests(m_pDriver, resources, modEvents, x, flippedY, history);
|
||||
QueryPostModPixelValues(m_pDriver, resources, modEvents, x, flippedY, history);
|
||||
std::map<uint32_t, uint32_t> eventFragments =
|
||||
QueryNumFragmentsByEvent(m_pDriver, resources, modEvents, x, flippedY);
|
||||
|
||||
// copy history entries to create one history per fragment
|
||||
for(size_t h = 0; h < history.size();)
|
||||
{
|
||||
uint32_t frags = 1;
|
||||
auto it = eventFragments.find(history[h].eventId);
|
||||
if(it != eventFragments.end())
|
||||
{
|
||||
frags = it->second;
|
||||
}
|
||||
for(uint32_t f = 1; f < frags; ++f)
|
||||
{
|
||||
history.insert(h + 1, history[h]);
|
||||
}
|
||||
for(uint32_t f = 0; f < frags; ++f)
|
||||
{
|
||||
history[h + f].fragIndex = f;
|
||||
}
|
||||
h += RDCMAX(1u, frags);
|
||||
}
|
||||
|
||||
for(const EventUsage &modEvent : modEvents)
|
||||
{
|
||||
if(modEvent.usage == ResourceUsage::Clear)
|
||||
{
|
||||
WriteClearValues(m_pDriver, resources, modEvent, x, flippedY, history);
|
||||
}
|
||||
else
|
||||
{
|
||||
QueryPerFragmentValues(m_pDriver, this, resources, modEvent, x, flippedY, history,
|
||||
eventFragments, PerFragmentQueryType::ShaderOut);
|
||||
QueryPerFragmentValues(m_pDriver, this, resources, modEvent, x, flippedY, history,
|
||||
eventFragments, PerFragmentQueryType::PrimitiveId);
|
||||
QueryPerFragmentValues(m_pDriver, this, resources, modEvent, x, flippedY, history,
|
||||
eventFragments, PerFragmentQueryType::PostMod);
|
||||
}
|
||||
}
|
||||
|
||||
// copy the postMod to next history's preMod
|
||||
for(size_t i = 1; i < history.size(); ++i)
|
||||
@@ -349,6 +707,8 @@ rdcarray<PixelModification> GLReplay::PixelHistory(rdcarray<EventUsage> events,
|
||||
history[i].preMod = history[i - 1].postMod;
|
||||
}
|
||||
|
||||
CalculateFragmentDepthTests(m_pDriver, resources, modEvents, history);
|
||||
|
||||
PixelHistoryDestroyResources(m_pDriver, resources);
|
||||
return history;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user