From 8851da66afde0d40010879151d658db55e04dbdb Mon Sep 17 00:00:00 2001 From: James Fulop Date: Sun, 18 Sep 2016 14:22:16 -0400 Subject: [PATCH] added original picking back in as a fallback. --- renderdoc/data/glsl/debuguniforms.h | 15 +++- renderdoc/data/glsl/mesh.comp | 60 ++++++++++++-- renderdoc/driver/gl/gl_debug.cpp | 120 ++++++++++++++++++++-------- 3 files changed, 152 insertions(+), 43 deletions(-) diff --git a/renderdoc/data/glsl/debuguniforms.h b/renderdoc/data/glsl/debuguniforms.h index 04190094c..89f3a0d6b 100644 --- a/renderdoc/data/glsl/debuguniforms.h +++ b/renderdoc/data/glsl/debuguniforms.h @@ -130,8 +130,9 @@ BINDING(0) uniform FontUBOData } INST_NAME(general); -#define MESH_TRIANGLE_LIST 0 -#define MESH_TRIANGLE_STRIP 1 +#define MESH_OTHER 0 // this covers points and lines, logic is the same +#define MESH_TRIANGLE_LIST 1 +#define MESH_TRIANGLE_STRIP 2 BINDING(0) uniform MeshPickUBOData { vec3 rayPos; @@ -140,8 +141,14 @@ BINDING(0) uniform MeshPickUBOData vec3 rayDir; uint numVerts; - int meshMode;//triangles, triangle strip, fan, etc... - vec3 padding; + vec2 coords; + vec2 viewport; + + uint meshMode; // triangles, triangle strip, fan, etc... + uint unproject; + vec2 padding; + + mat4 mvp; } INST_NAME(meshpick); diff --git a/renderdoc/data/glsl/mesh.comp b/renderdoc/data/glsl/mesh.comp index 1ec359962..e1d4c17e6 100644 --- a/renderdoc/data/glsl/mesh.comp +++ b/renderdoc/data/glsl/mesh.comp @@ -74,11 +74,9 @@ bool TriangleRayIntersect(vec3 A, vec3 B, vec3 C, return Result; } -void main() +void trianglePath(uint threadID) { - uvec3 tid = gl_GlobalInvocationID; - - uint vertid = tid.x; + uint vertid = threadID; // NOTE(james): when I turn on following early out the shader doesn't do anything. // so I end up with a lot of duplicated work on smaller meshes @@ -92,14 +90,16 @@ void main() uint idx2 = 0; switch (meshpick.meshMode) { - case MESH_TRIANGLE_LIST:{ + case MESH_TRIANGLE_LIST: + { vertid *= 3; idx0 = meshpick.use_indices != 0u ? ib.data[vertid ] : vertid; idx1 = meshpick.use_indices != 0u ? ib.data[vertid+1] : vertid+1; idx2 = meshpick.use_indices != 0u ? ib.data[vertid+2] : vertid+2; break; } - case MESH_TRIANGLE_STRIP:{ + case MESH_TRIANGLE_STRIP: + { idx0 = meshpick.use_indices != 0u ? ib.data[vertid ] : vertid; idx1 = meshpick.use_indices != 0u ? ib.data[vertid+1] : vertid+1; idx2 = meshpick.use_indices != 0u ? ib.data[vertid+2] : vertid+2; @@ -137,4 +137,52 @@ void main() pickresult.results[result_idx] = uvec4(vertid, floatBitsToUint(hitPosition.x), floatBitsToUint(hitPosition.y), floatBitsToUint(hitPosition.z)); } + +} + +void defaultPath(uint threadID) +{ + uint vertid = threadID; + + if(vertid >= meshpick.numVerts) + return; + + uint idx = meshpick.use_indices != 0u ? ib.data[vertid] : vertid; + + vec4 pos = vb.data[idx]; + +#ifdef VULKAN + if(meshpick.unproject == 1u) + pos = vec4(pos.x, -pos.y, pos.z, pos.w); +#endif + + vec4 wpos = meshpick.mvp * pos; + + wpos.xyz /= wpos.www; + + wpos.xy *= vec2(1.0f, -1.0f); + + vec2 scr = (wpos.xy + 1.0f) * 0.5f * meshpick.viewport; + + // close to target co-ords? add to list + float len = length(scr - meshpick.coords); + if(len < 35.0f) + { + uint result_idx = atomicAdd(pickresult.counter.x, 1u); + pickresult.results[result_idx] = uvec4(vertid, idx, floatBitsToUint(len), floatBitsToUint(wpos.z)); + } +} + +void main() +{ + if (meshpick.meshMode == MESH_TRIANGLE_LIST || + meshpick.meshMode == MESH_TRIANGLE_STRIP) + { + trianglePath(gl_GlobalInvocationID.x); + } + else + { + defaultPath(gl_GlobalInvocationID.x); + } + } diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index c694026e3..575682aec 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -1076,25 +1076,35 @@ uint32_t GLReplay::PickVertex(uint32_t eventID, const MeshDisplay &cfg, uint32_t cdata->rayDir = rayDir; cdata->use_indices = cfg.position.idxByteWidth ? 1U : 0U; cdata->numVerts = cfg.position.numVerts; + + bool isTriangleMesh = false; switch(cfg.position.topo) { case eTopology_TriangleList: { cdata->meshMode = MESH_TRIANGLE_LIST; + isTriangleMesh = true; break; }; case eTopology_TriangleStrip: { cdata->meshMode = MESH_TRIANGLE_STRIP; + isTriangleMesh = true; break; }; default: { - cdata->meshMode = -1; - RDCWARN("Mesh type unsupported by picking"); + cdata->meshMode = MESH_OTHER; + RDCWARN("Mesh type defaulting to screenspace point picking"); }; } + // line/point data + cdata->unproject = cfg.position.unproject; + cdata->mvp = PickMVP; + cdata->coords = Vec2f((float)x, (float)y); + cdata->viewport = Vec2f(DebugData.outWidth, DebugData.outHeight); + gl.glUnmapBuffer(eGL_UNIFORM_BUFFER); GLuint ib = 0; @@ -1213,44 +1223,88 @@ uint32_t GLReplay::PickVertex(uint32_t eventID, const MeshDisplay &cfg, uint32_t if(numResults > 0) { - struct PickResult + if(isTriangleMesh) { - uint32_t vertid; - vec3 intersectionPoint; - }; - - byte *mapped = (byte *)gl.glMapNamedBufferEXT(DebugData.pickResultBuf, eGL_READ_ONLY); - - mapped += sizeof(uint32_t) * 4; - - PickResult *pickResults = (PickResult *)mapped; - - PickResult *closest = pickResults; - // distance from raycast hit to nearest worldspace position of the mouse - float closestPickDistance = (closest->intersectionPoint - rayPos).Length(); - - // min with size of results buffer to protect against overflows - for(uint32_t i = 1; i < RDCMIN((uint32_t)DebugRenderData::maxMeshPicks, numResults); i++) - { - // We need to keep the picking order consistent in the face - // of random buffer appends, when multiple vertices have the - // identical position (e.g. if UVs or normals are different). - // - // We could do something to try and disambiguate, but it's - // never going to be intuitive, it's just going to flicker - // confusingly. - float pickDistance = (pickResults[i].intersectionPoint - rayPos).Length(); - if(pickDistance < closestPickDistance) + struct PickResult { - closest = pickResults + i; + uint32_t vertid; + vec3 intersectionPoint; + }; + + byte *mapped = (byte *)gl.glMapNamedBufferEXT(DebugData.pickResultBuf, eGL_READ_ONLY); + + mapped += sizeof(uint32_t) * 4; + + PickResult *pickResults = (PickResult *)mapped; + + PickResult *closest = pickResults; + // distance from raycast hit to nearest worldspace position of the mouse + float closestPickDistance = (closest->intersectionPoint - rayPos).Length(); + + // min with size of results buffer to protect against overflows + for(uint32_t i = 1; i < RDCMIN((uint32_t)DebugRenderData::maxMeshPicks, numResults); i++) + { + // We need to keep the picking order consistent in the face + // of random buffer appends, when multiple vertices have the + // identical position (e.g. if UVs or normals are different). + // + // We could do something to try and disambiguate, but it's + // never going to be intuitive, it's just going to flicker + // confusingly. + float pickDistance = (pickResults[i].intersectionPoint - rayPos).Length(); + if(pickDistance < closestPickDistance) + { + closest = pickResults + i; + } } + + uint32_t ret = closest->vertid; + + gl.glUnmapNamedBufferEXT(DebugData.pickResultBuf); + + return ret; } + else + { + struct PickResult + { + uint32_t vertid; + uint32_t idx; + float len; + float depth; + }; - uint32_t ret = closest->vertid; + byte *mapped = (byte *)gl.glMapNamedBufferEXT(DebugData.pickResultBuf, eGL_READ_ONLY); - gl.glUnmapNamedBufferEXT(DebugData.pickResultBuf); + mapped += sizeof(uint32_t) * 4; - return ret; + PickResult *pickResults = (PickResult *)mapped; + + PickResult *closest = pickResults; + + // min with size of results buffer to protect against overflows + for(uint32_t i = 1; i < RDCMIN((uint32_t)DebugRenderData::maxMeshPicks, numResults); i++) + { + // We need to keep the picking order consistent in the face + // of random buffer appends, when multiple vertices have the + // identical position (e.g. if UVs or normals are different). + // + // We could do something to try and disambiguate, but it's + // never going to be intuitive, it's just going to flicker + // confusingly. + if(pickResults[i].len < closest->len || + (pickResults[i].len == closest->len && pickResults[i].depth < closest->depth) || + (pickResults[i].len == closest->len && pickResults[i].depth == closest->depth && + pickResults[i].vertid < closest->vertid)) + closest = pickResults + i; + } + + uint32_t ret = closest->vertid; + + gl.glUnmapNamedBufferEXT(DebugData.pickResultBuf); + + return ret; + } } return ~0U;