mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Add first unit test for Open GL Pixel History
- Support for integer texture formats in OpenGL Pixel History implementation - Test reading pixels from a triangle with a variety of texture formats
This commit is contained in:
committed by
Baldur Karlsson
parent
40cd74c713
commit
08be49dce3
@@ -38,6 +38,42 @@ bool isDirectWrite(ResourceUsage usage)
|
||||
usage == ResourceUsage::GenMips);
|
||||
}
|
||||
|
||||
struct FramebufferKey
|
||||
{
|
||||
GLenum colorFormat;
|
||||
GLenum depthFormat;
|
||||
GLenum stencilFormat;
|
||||
uint32_t numSamples;
|
||||
bool operator<(const FramebufferKey &other) const
|
||||
{
|
||||
if(colorFormat < other.colorFormat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(colorFormat > other.colorFormat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(depthFormat < other.depthFormat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(depthFormat > other.depthFormat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(stencilFormat < other.stencilFormat)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(stencilFormat > other.stencilFormat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return numSamples < other.numSamples;
|
||||
}
|
||||
};
|
||||
|
||||
struct CopyFramebuffer
|
||||
{
|
||||
GLuint framebufferId;
|
||||
@@ -47,20 +83,15 @@ struct CopyFramebuffer
|
||||
GLuint stencilTextureId;
|
||||
GLuint stencilViewId;
|
||||
uint32_t width;
|
||||
FramebufferKey format;
|
||||
};
|
||||
|
||||
struct FramebufferKey
|
||||
struct ShaderOutFramebuffer
|
||||
{
|
||||
GLenum depthFormat;
|
||||
GLenum stencilFormat;
|
||||
uint32_t numSamples;
|
||||
bool operator<(const FramebufferKey &other) const
|
||||
{
|
||||
return depthFormat < other.depthFormat ||
|
||||
(depthFormat == other.depthFormat && stencilFormat < other.stencilFormat) ||
|
||||
(depthFormat == other.depthFormat && stencilFormat == other.stencilFormat &&
|
||||
numSamples < other.numSamples);
|
||||
}
|
||||
GLuint framebufferId;
|
||||
GLuint colorTextureId;
|
||||
GLuint dsTextureId;
|
||||
FramebufferKey format;
|
||||
};
|
||||
|
||||
struct GLPixelHistoryResources
|
||||
@@ -77,6 +108,7 @@ struct GLPixelHistoryResources
|
||||
GLuint msCopyUniformBlockBuffer;
|
||||
std::unordered_map<GLuint, GLuint> programs;
|
||||
std::map<FramebufferKey, CopyFramebuffer> copyFramebuffers;
|
||||
std::map<FramebufferKey, ShaderOutFramebuffer> shaderOutIntFramebuffers;
|
||||
};
|
||||
|
||||
enum class OpenGLTest
|
||||
@@ -121,8 +153,8 @@ GLuint GetPrimitiveIdProgram(WrappedOpenGL *driver, GLReplay *replay,
|
||||
// so that you can blit from the current bound framebuffer into the new framebuffer
|
||||
const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
std::map<FramebufferKey, CopyFramebuffer> ©Framebuffers,
|
||||
uint32_t numSamples, uint32_t numEvents,
|
||||
GLenum depthFormat, GLenum stencilFormat)
|
||||
uint32_t numSamples, uint32_t numEvents, GLenum depthFormat,
|
||||
GLenum stencilFormat, GLenum colorFormat)
|
||||
{
|
||||
bool multisampled = numSamples > 1;
|
||||
|
||||
@@ -145,7 +177,7 @@ const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &stencilType);
|
||||
|
||||
auto it = copyFramebuffers.find({depthFormat, stencilFormat, numSamples});
|
||||
auto it = copyFramebuffers.find({colorFormat, depthFormat, stencilFormat, numSamples});
|
||||
if(it != copyFramebuffers.end())
|
||||
{
|
||||
return it->second;
|
||||
@@ -165,14 +197,14 @@ const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
// Allocate a texture for the pixel history colour values
|
||||
GLenum textureTarget = multisampled ? eGL_TEXTURE_2D_MULTISAMPLE : eGL_TEXTURE_2D;
|
||||
driver->glGenTextures(1, ©Framebuffer.colorTextureId);
|
||||
driver->CreateTextureImage(copyFramebuffer.colorTextureId, eGL_RGBA32F, eGL_NONE, eGL_NONE,
|
||||
driver->CreateTextureImage(copyFramebuffer.colorTextureId, colorFormat, eGL_NONE, eGL_NONE,
|
||||
textureTarget, 2, copyFramebuffer.width, 1, 1, numSamples, 1);
|
||||
driver->glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0,
|
||||
copyFramebuffer.colorTextureId, 0);
|
||||
|
||||
// Allocate a texture(s) for the pixel history depth/stencil values matching the capture's
|
||||
// frambebuffer's formats
|
||||
if(curStencil == curDepth)
|
||||
if(curStencil == curDepth && curStencil != 0)
|
||||
{
|
||||
driver->glGenTextures(1, ©Framebuffer.dsTextureId);
|
||||
driver->CreateTextureImage(copyFramebuffer.dsTextureId, depthFormat, eGL_NONE, eGL_NONE,
|
||||
@@ -211,11 +243,71 @@ const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, savedDrawFramebuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, savedReadFramebuffer);
|
||||
|
||||
FramebufferKey key = {depthFormat, stencilFormat, numSamples};
|
||||
FramebufferKey key = {colorFormat, depthFormat, stencilFormat, numSamples};
|
||||
copyFramebuffer.format = key;
|
||||
copyFramebuffers[key] = copyFramebuffer;
|
||||
return copyFramebuffers[key];
|
||||
}
|
||||
|
||||
GLenum getTextureFormatType(GLenum internalFormat)
|
||||
{
|
||||
static GLenum unsignedIntegerTextureFormatsArray[] = {
|
||||
eGL_R8UI, eGL_R16UI, eGL_R32UI, eGL_RG8UI, eGL_RG16UI, eGL_RG32UI, eGL_RGB8UI,
|
||||
eGL_RGB16UI, eGL_RGB32UI, eGL_RGBA8UI, eGL_RGBA16UI, eGL_RGBA32UI, eGL_RGB10_A2UI};
|
||||
static std::set<GLenum> unsignedIntegerTextureFormats(
|
||||
unsignedIntegerTextureFormatsArray,
|
||||
unsignedIntegerTextureFormatsArray +
|
||||
(sizeof(unsignedIntegerTextureFormatsArray) / sizeof(GLenum)));
|
||||
static GLenum signedIntegerTextureFormatsArray[] = {
|
||||
eGL_R8I, eGL_R16I, eGL_R32I, eGL_RG8I, eGL_RG16I, eGL_RG32I,
|
||||
eGL_RGB8I, eGL_RGB16I, eGL_RGB32I, eGL_RGBA8I, eGL_RGBA16I, eGL_RGBA32I};
|
||||
static std::set<GLenum> signedIntegerTextureFormats(
|
||||
signedIntegerTextureFormatsArray,
|
||||
signedIntegerTextureFormatsArray + (sizeof(signedIntegerTextureFormatsArray) / sizeof(GLenum)));
|
||||
if(unsignedIntegerTextureFormats.count(internalFormat) != 0)
|
||||
{
|
||||
return eGL_UNSIGNED_INT;
|
||||
}
|
||||
if(signedIntegerTextureFormats.count(internalFormat) != 0)
|
||||
{
|
||||
return eGL_INT;
|
||||
}
|
||||
// There are other format types that this format could belong to, but they can be blitted between
|
||||
// each other
|
||||
return eGL_UNSIGNED_NORMALIZED;
|
||||
}
|
||||
|
||||
GLenum getCurrentTextureFormat(WrappedOpenGL *driver)
|
||||
{
|
||||
GLuint curColor;
|
||||
GLint colorType;
|
||||
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||
(GLint *)&curColor);
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &colorType);
|
||||
|
||||
GLenum colorFormat = eGL_NONE;
|
||||
|
||||
if(curColor != 0)
|
||||
{
|
||||
ResourceId id;
|
||||
if(colorType != eGL_RENDERBUFFER)
|
||||
{
|
||||
id = driver->GetResourceManager()->GetResID(TextureRes(driver->GetCtx(), curColor));
|
||||
}
|
||||
else
|
||||
{
|
||||
id = driver->GetResourceManager()->GetResID(RenderbufferRes(driver->GetCtx(), curColor));
|
||||
}
|
||||
WrappedOpenGL::TextureData textureData = driver->m_Textures[id];
|
||||
colorFormat = textureData.internalFormat;
|
||||
}
|
||||
|
||||
return colorFormat;
|
||||
}
|
||||
|
||||
const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
std::map<FramebufferKey, CopyFramebuffer> ©Framebuffers,
|
||||
uint32_t numSamples, uint32_t numEvents)
|
||||
@@ -224,6 +316,8 @@ const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
GLint depthType;
|
||||
GLuint curStencil;
|
||||
GLint stencilType;
|
||||
GLuint curColor;
|
||||
GLint colorType;
|
||||
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||
@@ -239,6 +333,13 @@ const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &stencilType);
|
||||
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
|
||||
(GLint *)&curColor);
|
||||
|
||||
driver->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0,
|
||||
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &colorType);
|
||||
|
||||
GLenum depthFormat = eGL_NONE;
|
||||
|
||||
if(curDepth != 0)
|
||||
@@ -270,8 +371,73 @@ const CopyFramebuffer &getCopyFramebuffer(WrappedOpenGL *driver,
|
||||
stencilFormat = driver->m_Textures[id].internalFormat;
|
||||
}
|
||||
|
||||
GLenum colorFormat = eGL_NONE;
|
||||
if(curColor != 0)
|
||||
{
|
||||
ResourceId id;
|
||||
if(colorType != eGL_RENDERBUFFER)
|
||||
{
|
||||
id = driver->GetResourceManager()->GetResID(TextureRes(driver->GetCtx(), curColor));
|
||||
}
|
||||
else
|
||||
{
|
||||
id = driver->GetResourceManager()->GetResID(RenderbufferRes(driver->GetCtx(), curColor));
|
||||
}
|
||||
WrappedOpenGL::TextureData textureData = driver->m_Textures[id];
|
||||
colorFormat = textureData.internalFormat;
|
||||
}
|
||||
|
||||
return getCopyFramebuffer(driver, copyFramebuffers, numSamples, numEvents, depthFormat,
|
||||
stencilFormat);
|
||||
stencilFormat, colorFormat);
|
||||
}
|
||||
|
||||
ShaderOutFramebuffer getShaderOutFramebuffer(WrappedOpenGL *driver,
|
||||
GLPixelHistoryResources &resources, FramebufferKey key,
|
||||
uint32_t width, uint32_t height)
|
||||
{
|
||||
std::map<FramebufferKey, ShaderOutFramebuffer> &shaderOutFramebuffers =
|
||||
resources.shaderOutIntFramebuffers;
|
||||
auto it = shaderOutFramebuffers.find(key);
|
||||
|
||||
if(it != shaderOutFramebuffers.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
GLint savedReadFramebuffer, savedDrawFramebuffer;
|
||||
driver->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, &savedDrawFramebuffer);
|
||||
driver->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &savedReadFramebuffer);
|
||||
|
||||
bool multisampled = key.numSamples > 1;
|
||||
GLenum textureTarget = multisampled ? eGL_TEXTURE_2D_MULTISAMPLE : eGL_TEXTURE_2D;
|
||||
ShaderOutFramebuffer shaderOutFramebuffer;
|
||||
RDCEraseEl(shaderOutFramebuffer);
|
||||
|
||||
// Allocate a framebuffer that will render to the textures
|
||||
driver->glGenFramebuffers(1, &shaderOutFramebuffer.framebufferId);
|
||||
driver->glBindFramebuffer(eGL_FRAMEBUFFER, shaderOutFramebuffer.framebufferId);
|
||||
|
||||
// Allocate a texture for the pixel history colour values
|
||||
driver->glGenTextures(1, &shaderOutFramebuffer.colorTextureId);
|
||||
driver->glBindTexture(textureTarget, shaderOutFramebuffer.colorTextureId);
|
||||
driver->CreateTextureImage(shaderOutFramebuffer.colorTextureId, key.colorFormat, eGL_NONE,
|
||||
eGL_NONE, textureTarget, 2, width, height, 1, key.numSamples, 1);
|
||||
driver->glFramebufferTexture(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0,
|
||||
shaderOutFramebuffer.colorTextureId, 0);
|
||||
|
||||
// Allocate a texture for the pixel history depth/stencil values
|
||||
driver->glGenTextures(1, &shaderOutFramebuffer.dsTextureId);
|
||||
driver->glBindTexture(textureTarget, shaderOutFramebuffer.dsTextureId);
|
||||
driver->CreateTextureImage(shaderOutFramebuffer.dsTextureId, eGL_DEPTH24_STENCIL8, eGL_NONE,
|
||||
eGL_NONE, textureTarget, 2, width, height, 1, key.numSamples, 1);
|
||||
driver->glFramebufferTexture(eGL_FRAMEBUFFER, eGL_DEPTH_STENCIL_ATTACHMENT,
|
||||
shaderOutFramebuffer.dsTextureId, 0);
|
||||
|
||||
// restore the capture's framebuffer
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, savedDrawFramebuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, savedReadFramebuffer);
|
||||
|
||||
return (shaderOutFramebuffers[key] = shaderOutFramebuffer);
|
||||
}
|
||||
|
||||
GLbitfield getFramebufferCopyMask(WrappedOpenGL *driver)
|
||||
@@ -411,6 +577,14 @@ bool PixelHistoryDestroyResources(WrappedOpenGL *driver, const GLPixelHistoryRes
|
||||
driver->glDeleteTextures(1, &cf.stencilViewId);
|
||||
}
|
||||
|
||||
for(const auto &pair : resources.shaderOutIntFramebuffers)
|
||||
{
|
||||
const ShaderOutFramebuffer &f = pair.second;
|
||||
driver->glDeleteFramebuffers(1, &f.framebufferId);
|
||||
driver->glDeleteTextures(1, &f.colorTextureId);
|
||||
driver->glDeleteTextures(1, &f.dsTextureId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -621,16 +795,27 @@ void readPixelValuesMS(WrappedOpenGL *driver, const GLPixelHistoryResources &res
|
||||
|
||||
void readPixelValues(WrappedOpenGL *driver, const GLPixelHistoryResources &resources,
|
||||
const CopyFramebuffer ©Framebuffer, rdcarray<PixelModification> &history,
|
||||
int historyIndex, bool readStencil, uint32_t numPixels)
|
||||
int historyIndex, bool readStencil, uint32_t numPixels, bool isIntegerColour)
|
||||
{
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, copyFramebuffer.framebufferId);
|
||||
rdcarray<float> colourValues;
|
||||
colourValues.resize(4 * numPixels);
|
||||
rdcarray<int> intColourValues;
|
||||
intColourValues.resize(4 * numPixels);
|
||||
rdcarray<float> floatColourValues;
|
||||
floatColourValues.resize(4 * numPixels);
|
||||
rdcarray<float> depthValues;
|
||||
depthValues.resize(numPixels);
|
||||
rdcarray<int> stencilValues;
|
||||
stencilValues.resize(numPixels);
|
||||
driver->glReadPixels(0, 0, GLint(numPixels), 1, eGL_RGBA, eGL_FLOAT, (void *)colourValues.data());
|
||||
if(isIntegerColour)
|
||||
{
|
||||
driver->glReadPixels(0, 0, GLint(numPixels), 1, eGL_RGBA_INTEGER, eGL_INT,
|
||||
(void *)intColourValues.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->glReadPixels(0, 0, GLint(numPixels), 1, eGL_RGBA, eGL_FLOAT,
|
||||
(void *)floatColourValues.data());
|
||||
}
|
||||
if(copyFramebuffer.dsTextureId != 0 || copyFramebuffer.depthTextureId != 0)
|
||||
{
|
||||
driver->glReadPixels(0, 0, GLint(numPixels), 1, eGL_DEPTH_COMPONENT, eGL_FLOAT,
|
||||
@@ -649,7 +834,14 @@ void readPixelValues(WrappedOpenGL *driver, const GLPixelHistoryResources &resou
|
||||
|
||||
for(int j = 0; j < 4; ++j)
|
||||
{
|
||||
modValue.col.floatValue[j] = colourValues[i * 4 + j];
|
||||
if(isIntegerColour)
|
||||
{
|
||||
modValue.col.intValue[j] = intColourValues[i * 4 + j];
|
||||
}
|
||||
else
|
||||
{
|
||||
modValue.col.floatValue[j] = floatColourValues[i * 4 + j];
|
||||
}
|
||||
}
|
||||
|
||||
modValue.depth = depthValues[i];
|
||||
@@ -697,12 +889,14 @@ void QueryPostModPixelValues(WrappedOpenGL *driver, GLPixelHistoryResources &res
|
||||
{
|
||||
CopyFramebuffer newCopyFramebuffer = getCopyFramebuffer(
|
||||
driver, resources.copyFramebuffers, 1 /*single sampled*/, int(modEvents.size()));
|
||||
GLenum colourFormatType = getTextureFormatType(copyFramebuffer.format.colorFormat);
|
||||
bool integerColour = colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT;
|
||||
if(newCopyFramebuffer.framebufferId != copyFramebuffer.framebufferId)
|
||||
{
|
||||
if(copyFramebuffer.framebufferId != ~0u)
|
||||
{
|
||||
readPixelValues(driver, resources, copyFramebuffer, history, lastHistoryIdx, true,
|
||||
(uint32_t)(i - lastHistoryIdx));
|
||||
(uint32_t)(i - lastHistoryIdx), integerColour);
|
||||
}
|
||||
lastHistoryIdx = int(i);
|
||||
}
|
||||
@@ -728,8 +922,10 @@ void QueryPostModPixelValues(WrappedOpenGL *driver, GLPixelHistoryResources &res
|
||||
|
||||
if(numSamples == 1 && copyFramebuffer.framebufferId != 0u)
|
||||
{
|
||||
GLenum colourFormatType = getTextureFormatType(copyFramebuffer.format.colorFormat);
|
||||
bool integerColour = colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT;
|
||||
readPixelValues(driver, resources, copyFramebuffer, history, lastHistoryIdx, true,
|
||||
int(modEvents.size()) - lastHistoryIdx);
|
||||
int(modEvents.size()) - lastHistoryIdx, integerColour);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,14 +950,45 @@ void readShaderOutMS(WrappedOpenGL *driver, const GLPixelHistoryResources &resou
|
||||
history[historyIndex].shaderOut = modValue;
|
||||
}
|
||||
|
||||
GLenum getShaderOutColourFormat(GLenum originalColourFormat)
|
||||
{
|
||||
switch(originalColourFormat)
|
||||
{
|
||||
case eGL_RGBA8I:
|
||||
case eGL_RGB8I:
|
||||
case eGL_RG8I:
|
||||
case eGL_R8I: return eGL_RGBA8I;
|
||||
case eGL_RGBA8UI:
|
||||
case eGL_RGB8UI:
|
||||
case eGL_RG8UI:
|
||||
case eGL_R8UI: return eGL_RGBA8UI;
|
||||
case eGL_RGBA16I:
|
||||
case eGL_RGB16I:
|
||||
case eGL_RG16I:
|
||||
case eGL_R16I: return eGL_RGBA16I;
|
||||
case eGL_RGBA16UI:
|
||||
case eGL_RGB16UI:
|
||||
case eGL_RG16UI:
|
||||
case eGL_R16UI: return eGL_RGBA16UI;
|
||||
case eGL_RGBA32I:
|
||||
case eGL_RGB32I:
|
||||
case eGL_RG32I:
|
||||
case eGL_R32I: return eGL_RGBA32I;
|
||||
case eGL_RGBA32UI:
|
||||
case eGL_RGB32UI:
|
||||
case eGL_RG32UI:
|
||||
case eGL_R32UI: return eGL_RGBA32UI;
|
||||
case eGL_RGB10_A2UI: return eGL_RGB10_A2UI;
|
||||
default: RDCERR("Unexpected colour format: %d", originalColourFormat); return eGL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// This function a) calculates the number of fagments per event
|
||||
// and b) calculates the shader output values per event
|
||||
std::map<uint32_t, uint32_t> QueryNumFragmentsByEvent(WrappedOpenGL *driver,
|
||||
GLPixelHistoryResources &resources,
|
||||
const rdcarray<EventUsage> &modEvents,
|
||||
rdcarray<PixelModification> &history, int x,
|
||||
int y, uint32_t numSamples,
|
||||
uint32_t sampleIndex)
|
||||
std::map<uint32_t, uint32_t> QueryNumFragmentsByEvent(
|
||||
WrappedOpenGL *driver, GLPixelHistoryResources &resources,
|
||||
const rdcarray<EventUsage> &modEvents, rdcarray<PixelModification> &history, int x, int y,
|
||||
uint32_t numSamples, uint32_t sampleIndex, uint32_t width, uint32_t height)
|
||||
{
|
||||
driver->ReplayLog(0, modEvents[0].eventId, eReplay_WithoutDraw);
|
||||
|
||||
@@ -772,8 +999,26 @@ std::map<uint32_t, uint32_t> QueryNumFragmentsByEvent(WrappedOpenGL *driver,
|
||||
GLint savedReadFramebuffer, savedDrawFramebuffer;
|
||||
driver->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, &savedDrawFramebuffer);
|
||||
driver->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &savedReadFramebuffer);
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
|
||||
GLenum colourFormat = getCurrentTextureFormat(driver);
|
||||
GLenum colourFormatType = getTextureFormatType(colourFormat);
|
||||
GLenum shaderOutColourFormat = eGL_NONE;
|
||||
|
||||
if(colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT)
|
||||
{
|
||||
shaderOutColourFormat = getShaderOutColourFormat(colourFormat);
|
||||
FramebufferKey key = {shaderOutColourFormat, eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8,
|
||||
numSamples};
|
||||
ShaderOutFramebuffer framebuffer =
|
||||
getShaderOutFramebuffer(driver, resources, key, width, height);
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, framebuffer.framebufferId);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, framebuffer.framebufferId);
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
}
|
||||
|
||||
driver->glStencilOp(eGL_INCR, eGL_INCR, eGL_INCR);
|
||||
driver->glStencilMask(0xff); // default for 1 byte
|
||||
@@ -801,7 +1046,15 @@ std::map<uint32_t, uint32_t> QueryNumFragmentsByEvent(WrappedOpenGL *driver,
|
||||
if(numSamples == 1)
|
||||
{
|
||||
ModificationValue modValue;
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT, (void *)modValue.col.floatValue.data());
|
||||
if(colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT)
|
||||
{
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA_INTEGER, eGL_INT,
|
||||
(void *)modValue.col.intValue.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT, (void *)modValue.col.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_UNSIGNED_INT, (void *)&numFragments);
|
||||
|
||||
@@ -813,11 +1066,15 @@ std::map<uint32_t, uint32_t> QueryNumFragmentsByEvent(WrappedOpenGL *driver,
|
||||
}
|
||||
else
|
||||
{
|
||||
const CopyFramebuffer ©Framebuffer =
|
||||
getCopyFramebuffer(driver, resources.copyFramebuffers, numSamples, int(modEvents.size()),
|
||||
eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8);
|
||||
GLenum copyFramebufferColourFormat =
|
||||
(colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT)
|
||||
? shaderOutColourFormat
|
||||
: eGL_RGBA32F;
|
||||
|
||||
const CopyFramebuffer ©Framebuffer = getCopyFramebuffer(
|
||||
driver, resources.copyFramebuffers, numSamples, int(modEvents.size()),
|
||||
eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8, copyFramebufferColourFormat);
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, copyFramebuffer.framebufferId);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
SafeBlitFramebuffer(x, y, x + 1, y + 1, 0, 0, 1, 1, getFramebufferCopyMask(driver),
|
||||
eGL_NEAREST);
|
||||
readShaderOutMS(driver, resources, copyFramebuffer, sampleIndex, 0, 0, history, int(i));
|
||||
@@ -961,7 +1218,8 @@ void QueryShaderOutPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
const rdcarray<EventUsage> &modEvents, int x, int y,
|
||||
rdcarray<PixelModification> &history,
|
||||
const std::map<uint32_t, uint32_t> &eventFragments,
|
||||
uint32_t numSamples, uint32_t sampleIndex)
|
||||
uint32_t numSamples, uint32_t sampleIndex, uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
driver->ReplayLog(0, modEvents[0].eventId, eReplay_WithoutDraw);
|
||||
for(size_t i = 0; i < modEvents.size(); ++i)
|
||||
@@ -1025,12 +1283,31 @@ void QueryShaderOutPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
driver->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, &savedDrawFramebuffer);
|
||||
driver->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &savedReadFramebuffer);
|
||||
|
||||
GLenum colourFormat = getCurrentTextureFormat(driver);
|
||||
GLenum colourFormatType = getTextureFormatType(colourFormat);
|
||||
GLenum shaderOutColourFormat = eGL_NONE;
|
||||
|
||||
for(size_t j = 0; j < RDCMAX(numFragments, 1u); ++j)
|
||||
{
|
||||
// Set the stencil function so only jth fragment will pass.
|
||||
driver->glStencilFunc(eGL_EQUAL, (int)j, 0xff);
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
|
||||
if(colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT)
|
||||
{
|
||||
shaderOutColourFormat = getShaderOutColourFormat(colourFormat);
|
||||
FramebufferKey key = {shaderOutColourFormat, eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8,
|
||||
numSamples};
|
||||
ShaderOutFramebuffer framebuffer =
|
||||
getShaderOutFramebuffer(driver, resources, key, width, height);
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, framebuffer.framebufferId);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, framebuffer.framebufferId);
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
}
|
||||
|
||||
driver->glClear(eGL_STENCIL_BUFFER_BIT | eGL_COLOR_BUFFER_BIT | eGL_DEPTH_BUFFER_BIT);
|
||||
|
||||
driver->ReplayLog(modEvents[i].eventId, modEvents[i].eventId, eReplay_OnlyDraw);
|
||||
@@ -1038,7 +1315,17 @@ void QueryShaderOutPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
if(numSamples == 1)
|
||||
{
|
||||
ModificationValue modValue;
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT, (void *)modValue.col.floatValue.data());
|
||||
|
||||
if(colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT)
|
||||
{
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA_INTEGER, eGL_INT,
|
||||
(void *)modValue.col.intValue.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_RGBA, eGL_FLOAT,
|
||||
(void *)modValue.col.floatValue.data());
|
||||
}
|
||||
driver->glReadPixels(x, y, 1, 1, eGL_DEPTH_COMPONENT, eGL_FLOAT, (void *)&modValue.depth);
|
||||
modValue.stencil = historyIndex->shaderOut.stencil;
|
||||
|
||||
@@ -1046,11 +1333,15 @@ void QueryShaderOutPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
}
|
||||
else
|
||||
{
|
||||
const CopyFramebuffer ©Framebuffer =
|
||||
getCopyFramebuffer(driver, resources.copyFramebuffers, numSamples,
|
||||
int(modEvents.size()), eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8);
|
||||
GLenum copyFramebufferColourFormat =
|
||||
(colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT)
|
||||
? shaderOutColourFormat
|
||||
: eGL_RGBA32F;
|
||||
|
||||
const CopyFramebuffer ©Framebuffer = getCopyFramebuffer(
|
||||
driver, resources.copyFramebuffers, numSamples, int(modEvents.size()),
|
||||
eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8, copyFramebufferColourFormat);
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, copyFramebuffer.framebufferId);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
SafeBlitFramebuffer(x, y, x + 1, y + 1, 0, 0, 1, 1, getFramebufferCopyMask(driver),
|
||||
eGL_NEAREST);
|
||||
int oldStencil = historyIndex->shaderOut.stencil;
|
||||
@@ -1118,6 +1409,10 @@ void QueryPostModPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
driver->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, &savedDrawFramebuffer);
|
||||
driver->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, &savedReadFramebuffer);
|
||||
|
||||
GLenum colourFormat = getCurrentTextureFormat(driver);
|
||||
GLenum colourFormatType = getTextureFormatType(colourFormat);
|
||||
bool integerColour = colourFormatType == eGL_UNSIGNED_INT || colourFormatType == eGL_INT;
|
||||
|
||||
CopyFramebuffer copyFramebuffer;
|
||||
RDCEraseEl(copyFramebuffer);
|
||||
copyFramebuffer.framebufferId = ~0u;
|
||||
@@ -1157,7 +1452,7 @@ void QueryPostModPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
{
|
||||
readPixelValues(driver, resources, copyFramebuffer, history,
|
||||
lastJ + int(historyIndex - history.begin()), false,
|
||||
(uint32_t)(j - lastJ));
|
||||
(uint32_t)(j - lastJ), integerColour);
|
||||
}
|
||||
lastJ = int(j);
|
||||
}
|
||||
@@ -1176,7 +1471,8 @@ void QueryPostModPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
if(numSamples == 1 && copyFramebuffer.framebufferId != ~0u)
|
||||
{
|
||||
readPixelValues(driver, resources, copyFramebuffer, history,
|
||||
lastJ + int(historyIndex - history.begin()), true, numFragments - lastJ);
|
||||
lastJ + int(historyIndex - history.begin()), true, numFragments - lastJ,
|
||||
integerColour);
|
||||
}
|
||||
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, savedDrawFramebuffer);
|
||||
@@ -1270,8 +1566,8 @@ void QueryPrimitiveIdPerFragment(WrappedOpenGL *driver, GLReplay *replay,
|
||||
else
|
||||
{
|
||||
const CopyFramebuffer ©Framebuffer =
|
||||
getCopyFramebuffer(driver, resources.copyFramebuffers, numSamples,
|
||||
int(modEvents.size()), eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8);
|
||||
getCopyFramebuffer(driver, resources.copyFramebuffers, numSamples, int(modEvents.size()),
|
||||
eGL_DEPTH24_STENCIL8, eGL_DEPTH24_STENCIL8, eGL_RGBA32F);
|
||||
driver->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, copyFramebuffer.framebufferId);
|
||||
driver->glBindFramebuffer(eGL_READ_FRAMEBUFFER, resources.fullPrecisionFrameBuffer);
|
||||
SafeBlitFramebuffer(x, y, x + 1, y + 1, 0, 0, 1, 1, getFramebufferCopyMask(driver),
|
||||
@@ -1441,8 +1737,11 @@ rdcarray<PixelModification> GLReplay::PixelHistory(rdcarray<EventUsage> events,
|
||||
QueryPostModPixelValues(m_pDriver, resources, modEvents, x, flippedY, history, textureDesc.msSamp,
|
||||
sampleIdx);
|
||||
|
||||
std::map<uint32_t, uint32_t> eventFragments = QueryNumFragmentsByEvent(
|
||||
m_pDriver, resources, modEvents, history, x, flippedY, textureDesc.msSamp, sampleIdx);
|
||||
uint32_t textureWidth = textureDesc.width >> sub.mip;
|
||||
uint32_t textureHeight = textureDesc.height >> sub.mip;
|
||||
std::map<uint32_t, uint32_t> eventFragments =
|
||||
QueryNumFragmentsByEvent(m_pDriver, resources, modEvents, history, x, flippedY,
|
||||
textureDesc.msSamp, sampleIdx, textureWidth, textureHeight);
|
||||
|
||||
// copy history entries to create one history per fragment
|
||||
for(size_t h = 0; h < history.size();)
|
||||
@@ -1465,7 +1764,8 @@ rdcarray<PixelModification> GLReplay::PixelHistory(rdcarray<EventUsage> events,
|
||||
}
|
||||
|
||||
QueryShaderOutPerFragment(m_pDriver, this, resources, modEvents, x, flippedY, history,
|
||||
eventFragments, textureDesc.msSamp, sampleIdx);
|
||||
eventFragments, textureDesc.msSamp, sampleIdx, textureWidth,
|
||||
textureHeight);
|
||||
QueryPrimitiveIdPerFragment(m_pDriver, this, resources, modEvents, x, flippedY, history,
|
||||
eventFragments, usingFloatForPrimitiveId, textureDesc.msSamp,
|
||||
sampleIdx);
|
||||
|
||||
@@ -103,6 +103,7 @@ set(OPENGL_SRC
|
||||
gl/gl_overlay_test.cpp
|
||||
gl/gl_parameter_zoo.cpp
|
||||
gl/gl_per_type_tex_units.cpp
|
||||
gl/gl_pixelhistory_formats.cpp
|
||||
gl/gl_queries_in_use.cpp
|
||||
gl/gl_renderbuffer_zoo.cpp
|
||||
gl/gl_resource_lifetimes.cpp
|
||||
|
||||
@@ -272,6 +272,7 @@
|
||||
<ClCompile Include="gl\gl_unsized_ms_fbo_attachment.cpp" />
|
||||
<ClCompile Include="gl\gl_vao_0.cpp" />
|
||||
<ClCompile Include="gl\gl_vertex_attr_zoo.cpp" />
|
||||
<ClCompile Include="gl\gl_pixelhistory_formats.cpp" />
|
||||
<ClCompile Include="linux\linux_platform.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
|
||||
@@ -643,6 +643,9 @@
|
||||
<ClCompile Include="d3d12\d3d12_vertex_uav.cpp">
|
||||
<Filter>D3D12\demos</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gl\gl_pixelhistory_formats.cpp">
|
||||
<Filter>OpenGL\demos</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="D3D11">
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019-2023 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "gl_test.h"
|
||||
|
||||
RD_TEST(GL_PixelHistory_Formats, OpenGLGraphicsTest)
|
||||
{
|
||||
static constexpr const char *Description =
|
||||
"Draw a triangle to a variety of texture formats (to test pixel history).";
|
||||
|
||||
std::string common = R"EOSHADER(
|
||||
|
||||
#version 420 core
|
||||
|
||||
#define v2f v2f_block \
|
||||
{ \
|
||||
vec4 pos; \
|
||||
vec4 col; \
|
||||
vec4 uv; \
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
std::string vertex = R"EOSHADER(
|
||||
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 1) in vec4 Color;
|
||||
layout(location = 2) in vec2 UV;
|
||||
|
||||
out v2f vertOut;
|
||||
|
||||
void main()
|
||||
{
|
||||
vertOut.pos = vec4(Position.xyz, 1);
|
||||
gl_Position = vertOut.pos;
|
||||
vertOut.col = Color;
|
||||
vertOut.uv = vec4(UV.xy, 0, 1);
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
std::string pixel = R"EOSHADER(
|
||||
|
||||
in v2f vertIn;
|
||||
|
||||
layout(location = 0, index = 0) out vec4 Color;
|
||||
|
||||
void main()
|
||||
{
|
||||
Color = vertIn.col;
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
int main()
|
||||
{
|
||||
// initialise, create window, create context, etc
|
||||
if(!Init())
|
||||
return 3;
|
||||
|
||||
GLuint vao = MakeVAO();
|
||||
glBindVertexArray(vao);
|
||||
|
||||
GLuint vb = MakeBuffer();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vb);
|
||||
const DefaultA2V DefaultTriWithALessBoringColour[3] = {
|
||||
{Vec3f(-0.5f, -0.5f, 0.0f), Vec4f(0.57721f, 0.27182f, 0.1385f, 1.0f), Vec2f(0.0f, 0.0f)},
|
||||
{Vec3f(0.0f, 0.5f, 0.0f), Vec4f(0.57721f, 0.27182f, 0.1385f, 1.0f), Vec2f(0.0f, 1.0f)},
|
||||
{Vec3f(0.5f, -0.5f, 0.0f), Vec4f(0.57721f, 0.27182f, 0.1385f, 1.0f), Vec2f(1.0f, 0.0f)},
|
||||
};
|
||||
glBufferStorage(GL_ARRAY_BUFFER, sizeof(DefaultTriWithALessBoringColour),
|
||||
DefaultTriWithALessBoringColour, 0);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(DefaultA2V), (void *)(0));
|
||||
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(DefaultA2V), (void *)(sizeof(Vec3f)));
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(DefaultA2V),
|
||||
(void *)(sizeof(Vec3f) + sizeof(Vec4f)));
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
GLuint program = MakeProgram(common + vertex, common + pixel);
|
||||
|
||||
GLenum colorFormats[] = {
|
||||
GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I, GL_RGBA8UI,
|
||||
GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI, GL_RGB8, GL_RGB16,
|
||||
GL_RGB16F, GL_RGB32F, GL_RGB8I, GL_RGB8UI, GL_RG8, GL_RG16,
|
||||
GL_RG16F, GL_RG32F, GL_RG8I, GL_RG8UI, GL_R8, GL_R16,
|
||||
GL_R16F, GL_R32F, GL_R8I, GL_R8UI, GL_RGB5_A1, GL_RGB10_A2,
|
||||
GL_RGB10_A2UI, GL_R11F_G11F_B10F, GL_RGB565};
|
||||
|
||||
GLenum depthFormats[] = {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32,
|
||||
GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8};
|
||||
|
||||
constexpr size_t colorFormatSize = sizeof(colorFormats) / sizeof(GLenum);
|
||||
constexpr size_t depthFormatSize = sizeof(depthFormats) / sizeof(GLenum);
|
||||
|
||||
GLuint colorTextures[colorFormatSize];
|
||||
GLuint multisampledColorTextures[colorFormatSize];
|
||||
GLuint depthTextures[depthFormatSize];
|
||||
|
||||
for(size_t i = 0; i < colorFormatSize; ++i)
|
||||
{
|
||||
colorTextures[i] = MakeTexture();
|
||||
multisampledColorTextures[i] = MakeTexture();
|
||||
glBindTexture(GL_TEXTURE_2D, colorTextures[i]);
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, colorFormats[i], screenWidth, screenHeight);
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, multisampledColorTextures[i]);
|
||||
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, colorFormats[i], screenWidth,
|
||||
screenHeight, GL_TRUE);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < depthFormatSize; ++i)
|
||||
{
|
||||
depthTextures[i] = MakeTexture();
|
||||
glBindTexture(GL_TEXTURE_2D, depthTextures[i]);
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, depthFormats[i], screenWidth, screenHeight);
|
||||
}
|
||||
|
||||
GLuint fbo = MakeFBO();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 0xcc, 0xff);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilMask(0xff);
|
||||
|
||||
while(Running())
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
for(size_t i = 0; i < colorFormatSize; ++i)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
colorTextures[i], 0);
|
||||
|
||||
if(i >= depthFormatSize)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
else if(depthFormats[i] == GL_DEPTH24_STENCIL8 || depthFormats[i] == GL_DEPTH32F_STENCIL8)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
|
||||
depthTextures[i], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
|
||||
depthTextures[i], 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
}
|
||||
|
||||
GLenum bufs[] = {GL_COLOR_ATTACHMENT0};
|
||||
glDrawBuffers(1, bufs);
|
||||
|
||||
float col[] = {0.2f, 0.2f, 0.2f, 1.0f};
|
||||
GLenum check = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if(check != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
printf("%x\n", colorFormats[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
glClearBufferfv(GL_COLOR, 0, col);
|
||||
glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
|
||||
|
||||
glBindVertexArray(vao);
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
glViewport(0, 0, GLsizei(screenWidth), GLsizei(screenHeight));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < colorFormatSize; ++i)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
multisampledColorTextures[i], 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
||||
|
||||
GLenum bufs[] = {GL_COLOR_ATTACHMENT0};
|
||||
glDrawBuffers(1, bufs);
|
||||
|
||||
float col[] = {0.2f, 0.2f, 0.2f, 1.0f};
|
||||
GLenum check = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if(check != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
printf("%x\n", colorFormats[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
glClearBufferfv(GL_COLOR, 0, col);
|
||||
|
||||
glBindVertexArray(vao);
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
glViewport(0, 0, GLsizei(screenWidth), GLsizei(screenHeight));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
Present();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST();
|
||||
@@ -0,0 +1,77 @@
|
||||
import renderdoc as rd
|
||||
import rdtest
|
||||
from typing import List
|
||||
|
||||
def event_id(x): return x.eventId
|
||||
|
||||
class GL_PixelHistory_Formats(rdtest.TestCase):
|
||||
demos_test_name = 'GL_PixelHistory_Formats'
|
||||
demos_frame_cap = 10
|
||||
|
||||
def check_capture(self):
|
||||
action = self.get_first_action()
|
||||
|
||||
while True:
|
||||
glclear: rd.ActionDescription = self.find_action('glClear', action.eventId)
|
||||
action: rd.ActionDescription = self.find_action('glDraw', action.eventId+1)
|
||||
|
||||
if action is None:
|
||||
break
|
||||
|
||||
rdtest.log.success(f'Test {action.eventId} started.')
|
||||
self.controller.SetFrameEvent(action.eventId, True)
|
||||
|
||||
pipe: rd.PipeState = self.controller.GetPipelineState()
|
||||
rt: rd.BoundResource = pipe.GetOutputTargets()[0]
|
||||
tex: rd.ResourceId = rt.resourceId
|
||||
sub = rd.Subresource()
|
||||
textures: List[rd.TextureDescription] = self.controller.GetTextures()
|
||||
def predicate(texDesc):
|
||||
return texDesc.resourceId == tex
|
||||
texDescription = next(filter(predicate, textures))
|
||||
|
||||
if texDescription.format.Name() == 'B5G5R5A1_UNORM' or texDescription.format.Name() == 'B5G6R5_UNORM':
|
||||
eps = 1.0 / 32.0
|
||||
elif texDescription.format.Name() == 'R10G10B10A2_UNORM':
|
||||
eps = 1.0 / 1024.0
|
||||
elif texDescription.format.Name() == 'R11G11B10_FLOAT':
|
||||
eps = 0.01
|
||||
elif texDescription.format.compByteWidth == 1:
|
||||
eps = 1.0 / 255.0
|
||||
else:
|
||||
eps = 2.0 / 16384.0
|
||||
|
||||
|
||||
|
||||
x, y = 190, 149
|
||||
events = [glclear.eventId, action.eventId]
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, modifs[-1].postMod.col.floatValue, sub=sub, cast=rt.typeCast, eps=eps)
|
||||
self.check_shader_out_with_postmod(modifs[-1].shaderOut.col.floatValue, modifs[-1].postMod.col.floatValue, texDescription.format.compCount, eps)
|
||||
|
||||
x, y = 328, 199
|
||||
events = [glclear.eventId]
|
||||
modifs: List[rd.pixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, modifs[-1].postMod.col.floatValue, sub=sub, cast=rt.typeCast, eps=eps)
|
||||
|
||||
rdtest.log.success('Test {} completed.'.format(action.eventId))
|
||||
|
||||
|
||||
def check_events(self, events, modifs, hasSecondary):
|
||||
self.check(len(modifs) == len(events), "Expected {} events, got {}, modifs {}".format(len(events), len(modifs), modifs))
|
||||
|
||||
for i in range(len(modifs)):
|
||||
self.check(modifs[i].eventId == events[i], f"Expected event with id {events[i]}, but got {modifs[i].eventId}")
|
||||
|
||||
|
||||
|
||||
def check_shader_out_with_postmod(self, shaderOut, postMod, compCount: int, eps: float):
|
||||
print(f"shaderOut: {shaderOut}, posMod: {postMod}")
|
||||
|
||||
diff = 0
|
||||
|
||||
for i in range(compCount):
|
||||
if not rdtest.value_compare(shaderOut[i], postMod[i], eps=eps):
|
||||
raise rdtest.TestFailureException(f"shaderOut and postMod differ by {shaderOut[i] - postMod[i]}")
|
||||
Reference in New Issue
Block a user