From d1c9564267f8aee41edab70f5a6b0075f8af514e Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 10 Aug 2020 11:19:57 +0100 Subject: [PATCH] Show float casting and normalising of GL vertex attributes. Closes #2013 --- .../PipelineState/GLPipelineStateViewer.cpp | 21 +++++++++-- renderdoc/api/replay/common_pipestate.h | 2 +- renderdoc/api/replay/gl_pipestate.h | 22 ++++++++++- renderdoc/driver/gl/gl_replay.cpp | 37 +++++++++++++++---- renderdoc/replay/renderdoc_serialise.inl | 4 +- 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp index 5727a8cd5..b886fd799 100644 --- a/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp +++ b/qrenderdoc/Windows/PipelineState/GLPipelineStateViewer.cpp @@ -1292,11 +1292,26 @@ void GLPipelineStateViewer::setState() if(showNode(usedSlot, filledSlot)) { - QString genericVal = tr("Generic=") + MakeGenericValueString(compCount, compType, a); + QString format = QString(a.format.Name()); + + if(!a.enabled) + { + format = tr("Generic=") + MakeGenericValueString(compCount, compType, a); + } + else + { + if(a.floatCast && a.normalizedCast) + { + format += tr(" Normalised and cast to float"); + } + else if(a.floatCast) + { + format += tr(" Cast to float"); + } + } RDTreeWidgetItem *node = - new RDTreeWidgetItem({i, a.enabled ? tr("Enabled") : tr("Disabled"), name, - a.enabled ? QString(a.format.Name()) : genericVal, + new RDTreeWidgetItem({i, a.enabled ? tr("Enabled") : tr("Disabled"), name, format, a.vertexBufferSlot, a.byteOffset, QString()}); node->setTag(i); diff --git a/renderdoc/api/replay/common_pipestate.h b/renderdoc/api/replay/common_pipestate.h index ba630dc90..b7f812c7c 100644 --- a/renderdoc/api/replay/common_pipestate.h +++ b/renderdoc/api/replay/common_pipestate.h @@ -448,7 +448,7 @@ no VB bound. )"); PixelValue genericValue; DOCUMENT("``True`` if this attribute is using :data:`genericValue` for its data."); - bool genericEnabled; + bool genericEnabled = false; DOCUMENT("``True`` if this attribute is enabled and used by the vertex shader."); bool used; }; diff --git a/renderdoc/api/replay/gl_pipestate.h b/renderdoc/api/replay/gl_pipestate.h index d124c5663..864e4c0cc 100644 --- a/renderdoc/api/replay/gl_pipestate.h +++ b/renderdoc/api/replay/gl_pipestate.h @@ -43,14 +43,18 @@ struct VertexAttribute bool operator==(const VertexAttribute &o) const { - return enabled == o.enabled && format == o.format && - !memcmp(&genericValue, &o.genericValue, sizeof(genericValue)) && + return enabled == o.enabled && floatCast == o.floatCast && normalizedCast == o.normalizedCast && + format == o.format && !memcmp(&genericValue, &o.genericValue, sizeof(genericValue)) && vertexBufferSlot == o.vertexBufferSlot && byteOffset == o.byteOffset; } bool operator<(const VertexAttribute &o) const { if(!(enabled == o.enabled)) return enabled < o.enabled; + if(!(floatCast == o.floatCast)) + return floatCast < o.floatCast; + if(!(normalizedCast == o.normalizedCast)) + return normalizedCast < o.normalizedCast; if(!(format == o.format)) return format < o.format; if(memcmp(&genericValue, &o.genericValue, sizeof(genericValue)) < 0) @@ -63,6 +67,20 @@ struct VertexAttribute } DOCUMENT("``True`` if this vertex attribute is enabled."); bool enabled = false; + + DOCUMENT(R"(Only valid for integer formatted attributes, ``True`` if they are cast to float. + +This is because they were specified with an integer format but glVertexAttribFormat (not +glVertexAttribIFormat) so they will be cast. See also :data:`normalisedCast` to see if the integer +data is normalised to [0,1] or [-1,1] while being cast. +)"); + bool floatCast = false; + + DOCUMENT(R"(Only valid for integer formatted attributes, ``True`` if the data is normalised while +cast to float. See :data:`floatCast` for more information. +)"); + bool normalizedCast = false; + DOCUMENT("The :class:`ResourceFormat` of the vertex attribute."); ResourceFormat format; diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 9a5371205..b65442891 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -877,34 +877,32 @@ void GLReplay::SavePipelineState(uint32_t eventId) fmt.compCount = (uint8_t)compCount; - bool intComponent = !normalized || integer; - switch(type) { default: case eGL_BYTE: fmt.compByteWidth = 1; - fmt.compType = intComponent ? CompType::SInt : CompType::SNorm; + fmt.compType = CompType::SInt; break; case eGL_UNSIGNED_BYTE: fmt.compByteWidth = 1; - fmt.compType = intComponent ? CompType::UInt : CompType::UNorm; + fmt.compType = CompType::UInt; break; case eGL_SHORT: fmt.compByteWidth = 2; - fmt.compType = intComponent ? CompType::SInt : CompType::SNorm; + fmt.compType = CompType::SInt; break; case eGL_UNSIGNED_SHORT: fmt.compByteWidth = 2; - fmt.compType = intComponent ? CompType::UInt : CompType::UNorm; + fmt.compType = CompType::UInt; break; case eGL_INT: fmt.compByteWidth = 4; - fmt.compType = intComponent ? CompType::SInt : CompType::SNorm; + fmt.compType = CompType::SInt; break; case eGL_UNSIGNED_INT: fmt.compByteWidth = 4; - fmt.compType = intComponent ? CompType::UInt : CompType::UNorm; + fmt.compType = CompType::UInt; break; case eGL_FLOAT: fmt.compByteWidth = 4; @@ -932,6 +930,8 @@ void GLReplay::SavePipelineState(uint32_t eventId) fmt.type = ResourceFormatType::R11G11B10; fmt.compCount = 3; fmt.compType = CompType::Float; + // spec says this format is never normalized regardless. + normalized = 0; break; } @@ -942,6 +942,9 @@ void GLReplay::SavePipelineState(uint32_t eventId) fmt.SetBGRAOrder(true); fmt.compType = CompType::UNorm; + // spec says BGRA inputs are ALWAYS normalised + normalized = 1; + if(type == eGL_UNSIGNED_INT_2_10_10_10_REV || type == eGL_INT_2_10_10_10_REV) { fmt.type = ResourceFormatType::R10G10B10A2; @@ -955,6 +958,24 @@ void GLReplay::SavePipelineState(uint32_t eventId) } pipe.vertexInput.attributes[i].format = fmt; + + // normalized/floatCast flags are irrelevant for float formats + if(fmt.compType == CompType::SInt || fmt.compType == CompType::UInt) + { + // if it wasn't an integer, it's cast to float + pipe.vertexInput.attributes[i].floatCast = !integer; + + // if we're casting, also store whether or not it's normalised + if(!integer) + pipe.vertexInput.attributes[i].normalizedCast = normalized != 0; + else + pipe.vertexInput.attributes[i].normalizedCast = false; + } + else + { + pipe.vertexInput.attributes[i].floatCast = pipe.vertexInput.attributes[i].normalizedCast = + false; + } } pipe.vertexInput.provokingVertexLast = (rs.ProvokingVertex != eGL_FIRST_VERTEX_CONVENTION); diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index 3c206d5c2..934c02115 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -1550,12 +1550,14 @@ template void DoSerialise(SerialiserType &ser, GLPipe::VertexAttribute &el) { SERIALISE_MEMBER(enabled); + SERIALISE_MEMBER(floatCast); + SERIALISE_MEMBER(normalizedCast); SERIALISE_MEMBER(format); SERIALISE_MEMBER(genericValue); SERIALISE_MEMBER(vertexBufferSlot); SERIALISE_MEMBER(byteOffset); - SIZE_CHECK(32); + SIZE_CHECK(36); } template