Implement right click to pick vertices in the mesh viewer. Refs #139

This commit is contained in:
baldurk
2015-07-07 10:02:36 +02:00
parent d6e1b012de
commit dd9aff3890
25 changed files with 975 additions and 220 deletions
+1
View File
@@ -50,6 +50,7 @@ data/glsl/generic.verto \
data/glsl/mesh.verto \
data/glsl/mesh.frago \
data/glsl/mesh.geomo \
data/glsl/mesh.compo \
data/glsl/text.verto \
data/glsl/text.frago \
data/glsl/quadoverdraw.frago \
+1
View File
@@ -116,6 +116,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC ReplayOutput_DisablePixelContext(Repl
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayOutput_PickPixel(ReplayOutput *output, ResourceId texID, bool32 customShader,
uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *val);
extern "C" RENDERDOC_API uint32_t RENDERDOC_CC ReplayOutput_PickVertex(ReplayOutput *output, uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y);
#ifdef RENDERDOC_EXPORTS
struct ReplayRenderer;
+2
View File
@@ -89,6 +89,8 @@ class ImageViewer : public IReplayDriver
bool RenderTexture(TextureDisplay cfg) { return m_Proxy->RenderTexture(cfg); }
void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4])
{ m_Proxy->PickPixel(texture, x, y, sliceFace, mip, sample, pixel); }
uint32_t PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y)
{ return m_Proxy->PickVertex(frameID, eventID, cfg, x, y); }
void BuildCustomShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors)
{ m_Proxy->BuildCustomShader(source, entry, compileFlags, type, id, errors); }
void FreeCustomShader(ResourceId id) { m_Proxy->FreeTargetResource(id); }
+25
View File
@@ -254,6 +254,31 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver
m_Proxy->RenderMesh(frameID, eventID, secDraws, cfg);
}
}
uint32_t PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y)
{
if(m_Proxy && cfg.position.buf != ResourceId())
{
EnsureBufCached(cfg.position.buf);
cfg.position.buf = m_ProxyBufferIds[cfg.position.buf];
if(cfg.second.buf != ResourceId())
{
EnsureBufCached(cfg.second.buf);
cfg.second.buf = m_ProxyBufferIds[cfg.second.buf];
}
if(cfg.position.idxbuf != ResourceId())
{
EnsureBufCached(cfg.position.idxbuf);
cfg.position.idxbuf = m_ProxyBufferIds[cfg.position.idxbuf];
}
return m_Proxy->PickVertex(frameID, eventID, cfg, x, y);
}
return ~0U;
}
void BuildCustomShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors)
{
+1
View File
@@ -40,6 +40,7 @@ DECLARE_EMBED(arraymscopy_comp);
DECLARE_EMBED(mesh_vert);
DECLARE_EMBED(mesh_frag);
DECLARE_EMBED(mesh_geom);
DECLARE_EMBED(mesh_comp);
DECLARE_EMBED(generic_vert);
DECLARE_EMBED(generic_frag);
DECLARE_EMBED(text_frag);
+83
View File
@@ -0,0 +1,83 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015 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.
******************************************************************************/
#version 420 core
#extension GL_ARB_compute_shader : require
#extension GL_ARB_shader_storage_buffer_object : require
layout(binding = 0) uniform atomic_uint pickresult_counter;
layout(binding = 0) writeonly buffer pickresult_buffer
{
uvec4 results[];
} pickresult;
layout(binding = 1) readonly buffer vertex_data
{
vec4 data[];
} vb;
layout(binding = 2) readonly buffer index_data
{
uint data[];
} ib;
uniform vec2 PickCoords;
uniform vec2 PickViewport;
uniform mat4 PickMVP;
uniform uint PickIdx;
uniform uint PickNumVerts;
layout (local_size_x = 1024, local_size_y = 1) in;
void main()
{
uvec3 tid = gl_GlobalInvocationID;
uint vertid = tid.x;
if(vertid >= PickNumVerts)
return;
uint idx = PickIdx != 0 ? ib.data[vertid] : vertid;
vec4 pos = vb.data[idx];
vec4 wpos = PickMVP * pos;
wpos.xyz /= wpos.www;
vec2 scr = (wpos.xy*vec2(1.0f, -1.0f) + 1.0f) * 0.5f * PickViewport;
// close to target co-ords? add to list
float len = length(scr - PickCoords);
if(len < 35.0f)
{
uint result_idx = atomicCounterIncrement(pickresult_counter);
pickresult.results[result_idx] = uvec4(vertid, idx, floatBitsToUint(len), floatBitsToUint(wpos.z));
}
}
-91
View File
@@ -188,97 +188,6 @@ struct wireframeV2F
float4 secondary : Secondary;
};
struct meshA2V
{
float4 pos : pos;
float4 secondary : sec;
};
wireframeV2F RENDERDOC_WireframeHomogVS(meshA2V IN, uint vid : SV_VertexID)
{
wireframeV2F OUT = (wireframeV2F)0;
OUT.pos = mul(IN.pos, ModelViewProj);
float2 psprite[4] =
{
float2(-1.0f, -1.0f),
float2(-1.0f, 1.0f),
float2( 1.0f, -1.0f),
float2( 1.0f, 1.0f)
};
OUT.pos.xy += SpriteSize.xy*0.01f*psprite[vid%4]*OUT.pos.w;
OUT.secondary = IN.secondary;
return OUT;
}
wireframeV2F RENDERDOC_MeshVS(meshA2V IN, uint vid : SV_VertexID)
{
wireframeV2F OUT = (wireframeV2F)0;
OUT.pos = mul(float4(IN.pos.xyz, 1), ModelViewProj);
OUT.norm = float3(0, 0, 1);
OUT.secondary = IN.secondary;
return OUT;
}
[maxvertexcount(3)]
void RENDERDOC_MeshGS(triangle wireframeV2F input[3], inout TriangleStream<wireframeV2F> TriStream)
{
wireframeV2F output;
float4 faceEdgeA = mul(input[1].pos, InvProj) - mul(input[0].pos, InvProj);
float4 faceEdgeB = mul(input[2].pos, InvProj) - mul(input[0].pos, InvProj);
float3 faceNormal = normalize( cross(faceEdgeA.xyz, faceEdgeB.xyz) );
for(int i=0; i<3; i++)
{
output.pos = input[i].pos;
output.norm = faceNormal;
output.secondary = input[i].secondary;
TriStream.Append(output);
}
TriStream.RestartStrip();
}
float4 RENDERDOC_MeshPS(wireframeV2F IN) : SV_Target0
{
uint type = OutputDisplayFormat;
if(type == MESHDISPLAY_SECONDARY)
return float4(IN.secondary.xyz, 1);
else if(type == MESHDISPLAY_SECONDARY_ALPHA)
return float4(IN.secondary.www, 1);
else if(type == MESHDISPLAY_FACELIT)
{
float3 lightDir = normalize(float3(0, -0.3f, -1));
return float4(WireframeColour.xyz*abs(dot(lightDir, IN.norm)), 1);
}
else //if(type == MESHDISPLAY_SOLID)
return float4(WireframeColour.xyz, 1);
}
wireframeV2F RENDERDOC_WireframeVS(float3 pos : POSITION, uint vid : SV_VertexID)
{
wireframeV2F OUT = (wireframeV2F)0;
OUT.pos = mul(float4(pos, 1), ModelViewProj);
float2 psprite[4] =
{
float2(-1.0f, -1.0f),
float2(-1.0f, 1.0f),
float2( 1.0f, -1.0f),
float2( 1.0f, 1.0f)
};
OUT.pos.xy += SpriteSize.xy*0.01f*psprite[vid%4]*OUT.pos.w;
return OUT;
}
wireframeV2F RENDERDOC_FullscreenVS(uint id : SV_VertexID)
{
wireframeV2F OUT = (wireframeV2F)0;
+161
View File
@@ -0,0 +1,161 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015 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.
******************************************************************************/
struct wireframeV2F
{
float4 pos : SV_Position;
float3 norm : Normal;
float4 secondary : Secondary;
};
struct meshA2V
{
float4 pos : pos;
float4 secondary : sec;
};
wireframeV2F RENDERDOC_WireframeHomogVS(meshA2V IN, uint vid : SV_VertexID)
{
wireframeV2F OUT = (wireframeV2F)0;
OUT.pos = mul(IN.pos, ModelViewProj);
float2 psprite[4] =
{
float2(-1.0f, -1.0f),
float2(-1.0f, 1.0f),
float2( 1.0f, -1.0f),
float2( 1.0f, 1.0f)
};
OUT.pos.xy += SpriteSize.xy*0.01f*psprite[vid%4]*OUT.pos.w;
OUT.secondary = IN.secondary;
return OUT;
}
wireframeV2F RENDERDOC_MeshVS(meshA2V IN, uint vid : SV_VertexID)
{
wireframeV2F OUT = (wireframeV2F)0;
OUT.pos = mul(float4(IN.pos.xyz, 1), ModelViewProj);
OUT.norm = float3(0, 0, 1);
OUT.secondary = IN.secondary;
return OUT;
}
[maxvertexcount(3)]
void RENDERDOC_MeshGS(triangle wireframeV2F input[3], inout TriangleStream<wireframeV2F> TriStream)
{
wireframeV2F output;
float4 faceEdgeA = mul(input[1].pos, InvProj) - mul(input[0].pos, InvProj);
float4 faceEdgeB = mul(input[2].pos, InvProj) - mul(input[0].pos, InvProj);
float3 faceNormal = normalize( cross(faceEdgeA.xyz, faceEdgeB.xyz) );
for(int i=0; i<3; i++)
{
output.pos = input[i].pos;
output.norm = faceNormal;
output.secondary = input[i].secondary;
TriStream.Append(output);
}
TriStream.RestartStrip();
}
float4 RENDERDOC_MeshPS(wireframeV2F IN) : SV_Target0
{
uint type = OutputDisplayFormat;
if(type == MESHDISPLAY_SECONDARY)
return float4(IN.secondary.xyz, 1);
else if(type == MESHDISPLAY_SECONDARY_ALPHA)
return float4(IN.secondary.www, 1);
else if(type == MESHDISPLAY_FACELIT)
{
float3 lightDir = normalize(float3(0, -0.3f, -1));
return float4(WireframeColour.xyz*abs(dot(lightDir, IN.norm)), 1);
}
else //if(type == MESHDISPLAY_SOLID)
return float4(WireframeColour.xyz, 1);
}
wireframeV2F RENDERDOC_WireframeVS(float3 pos : POSITION, uint vid : SV_VertexID)
{
wireframeV2F OUT = (wireframeV2F)0;
OUT.pos = mul(float4(pos, 1), ModelViewProj);
float2 psprite[4] =
{
float2(-1.0f, -1.0f),
float2(-1.0f, 1.0f),
float2( 1.0f, -1.0f),
float2( 1.0f, 1.0f)
};
OUT.pos.xy += SpriteSize.xy*0.01f*psprite[vid%4]*OUT.pos.w;
return OUT;
}
Buffer<uint> index : register(t0);
Buffer<float4> vertex : register(t1);
AppendStructuredBuffer<uint4> pickresult : register(u0);
cbuffer MeshPickData : register(b0)
{
float2 PickCoords;
float2 PickViewport;
row_major float4x4 PickMVP;
uint PickIdx;
uint PickNumVerts;
uint2 PickPadding;
};
[numthreads(1024, 1, 1)]
void RENDERDOC_MeshPickCS(uint3 tid : SV_DispatchThreadID)
{
uint vertid = tid.x;
if(vertid >= PickNumVerts)
return;
uint idx = PickIdx ? index[vertid] : vertid;
float4 pos = vertex[idx];
float4 wpos = mul(pos, PickMVP);
wpos.xyz /= wpos.w;
float2 scr = (wpos.xy*float2(1.0f, -1.0f) + 1.0f) * 0.5f * PickViewport;
// close to target co-ords? add to list
float len = length(scr - PickCoords);
if(len < 25.0f)
pickresult.Append(uint4(vertid, idx, asuint(len), asuint(wpos.z)));
}
+2
View File
@@ -108,6 +108,7 @@ RESOURCE_debugcommon_hlsl TYPE_EMBED "hlsl/debugcommon.hlsl"
RESOURCE_histogram_hlsl TYPE_EMBED "hlsl/histogram.hlsl"
RESOURCE_debugcbuffers_h TYPE_EMBED "hlsl/debugcbuffers.h"
RESOURCE_multisample_hlsl TYPE_EMBED "hlsl/multisample.hlsl"
RESOURCE_mesh_hlsl TYPE_EMBED "hlsl/mesh.hlsl"
RESOURCE_blit_vert TYPE_EMBED "glsl/blit.vert"
RESOURCE_blit_frag TYPE_EMBED "glsl/blit.frag"
@@ -123,6 +124,7 @@ RESOURCE_texsample_h TYPE_EMBED "glsl/texsample.h"
RESOURCE_histogram_comp TYPE_EMBED "glsl/histogram.comp"
RESOURCE_mesh_frag TYPE_EMBED "glsl/mesh.frag"
RESOURCE_mesh_geom TYPE_EMBED "glsl/mesh.geom"
RESOURCE_mesh_comp TYPE_EMBED "glsl/mesh.comp"
RESOURCE_arraymscopy_comp TYPE_EMBED "glsl/arraymscopy.comp"
RESOURCE_quadoverdraw_frag TYPE_EMBED "glsl/quadoverdraw.frag"
+4 -2
View File
@@ -10,6 +10,7 @@
#define RESOURCE_debugcommon_hlsl 104
#define RESOURCE_histogram_hlsl 105
#define RESOURCE_multisample_hlsl 106
#define RESOURCE_mesh_hlsl 107
#define RESOURCE_blit_vert 201
#define RESOURCE_blit_frag 202
@@ -25,8 +26,9 @@
#define RESOURCE_histogram_comp 212
#define RESOURCE_mesh_frag 213
#define RESOURCE_mesh_geom 214
#define RESOURCE_arraymscopy_comp 215
#define RESOURCE_quadoverdraw_frag 216
#define RESOURCE_mesh_comp 215
#define RESOURCE_arraymscopy_comp 216
#define RESOURCE_quadoverdraw_frag 217
#define RESOURCE_sourcecodepro_ttf 301
+214 -7
View File
@@ -24,6 +24,8 @@
#include "maths/vec.h"
#include "maths/matrix.h"
#include "maths/camera.h"
#include "d3d11_manager.h"
#include "d3d11_context.h"
#include "d3d11_debug.h"
@@ -570,7 +572,7 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global
{
if(WrappedID3D11Buffer::IsAlloc(res))
{
global.uavs[dsti].data = GetBufferData((ID3D11Buffer *)res, 0, 0);
global.uavs[dsti].data = GetBufferData((ID3D11Buffer *)res, 0, 0, true);
}
else
{
@@ -753,7 +755,7 @@ void D3D11DebugManager::CreateShaderGlobalState(ShaderDebug::GlobalState &global
{
if(WrappedID3D11Buffer::IsAlloc(res))
{
global.srvs[i].data = GetBufferData((ID3D11Buffer *)res, 0, 0);
global.srvs[i].data = GetBufferData((ID3D11Buffer *)res, 0, 0, true);
}
}
@@ -878,8 +880,8 @@ ShaderDebugTrace D3D11DebugManager::DebugVertex(uint32_t frameID, uint32_t event
UINT i = *it;
if(rs->IA.VBs[i])
{
vertData[i] = GetBufferData(rs->IA.VBs[i], rs->IA.Offsets[i] + rs->IA.Strides[i]*(vertOffset+idx), rs->IA.Strides[i]);
instData[i] = GetBufferData(rs->IA.VBs[i], rs->IA.Offsets[i] + rs->IA.Strides[i]*(instOffset+instid), rs->IA.Strides[i]);
vertData[i] = GetBufferData(rs->IA.VBs[i], rs->IA.Offsets[i] + rs->IA.Strides[i]*(vertOffset+idx), rs->IA.Strides[i], true);
instData[i] = GetBufferData(rs->IA.VBs[i], rs->IA.Offsets[i] + rs->IA.Strides[i]*(instOffset+instid), rs->IA.Strides[i], true);
}
}
@@ -887,7 +889,7 @@ ShaderDebugTrace D3D11DebugManager::DebugVertex(uint32_t frameID, uint32_t event
for(int i=0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
if(rs->VS.ConstantBuffers[i])
cbufData[i] = GetBufferData(rs->VS.ConstantBuffers[i], rs->VS.CBOffsets[i]*sizeof(Vec4f), 0);
cbufData[i] = GetBufferData(rs->VS.ConstantBuffers[i], rs->VS.CBOffsets[i]*sizeof(Vec4f), 0, true);
ShaderDebugTrace ret;
@@ -1498,7 +1500,7 @@ ShaderDebugTrace D3D11DebugManager::DebugPixel(uint32_t frameID, uint32_t eventI
for(int i=0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
if(rs->PS.ConstantBuffers[i])
cbufData[i] = GetBufferData(rs->PS.ConstantBuffers[i], rs->PS.CBOffsets[i]*sizeof(Vec4f), 0);
cbufData[i] = GetBufferData(rs->PS.ConstantBuffers[i], rs->PS.CBOffsets[i]*sizeof(Vec4f), 0, true);
D3D11_COMPARISON_FUNC depthFunc = D3D11_COMPARISON_LESS;
@@ -1757,7 +1759,7 @@ ShaderDebugTrace D3D11DebugManager::DebugThread(uint32_t frameID, uint32_t event
for(int i=0; i < D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
if(rs->CS.ConstantBuffers[i])
cbufData[i] = GetBufferData(rs->CS.ConstantBuffers[i], rs->CS.CBOffsets[i]*sizeof(Vec4f), 0);
cbufData[i] = GetBufferData(rs->CS.ConstantBuffers[i], rs->CS.CBOffsets[i]*sizeof(Vec4f), 0, true);
ShaderDebugTrace ret;
@@ -1790,6 +1792,211 @@ ShaderDebugTrace D3D11DebugManager::DebugThread(uint32_t frameID, uint32_t event
return ret;
}
uint32_t D3D11DebugManager::PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y)
{
D3D11RenderStateTracker tracker(m_WrappedContext);
struct MeshPickData
{
Vec2f PickCoords;
Vec2f PickViewport;
Matrix4f PickMVP;
uint32_t PickIdx;
uint32_t PickNumVerts;
uint32_t PickPadding[2];
} cbuf;
cbuf.PickCoords = Vec2f((float)x, (float)y);
cbuf.PickViewport = Vec2f((float)GetWidth(), (float)GetHeight());
cbuf.PickIdx = cfg.position.idxByteWidth ? 1 : 0;
cbuf.PickNumVerts = cfg.position.numVerts;
Matrix4f projMat = Matrix4f::Perspective(90.0f, 0.1f, 100000.0f, float(GetWidth())/float(GetHeight()));
Camera cam;
if(cfg.arcballCamera)
cam.Arcball(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), cfg.cameraPos.w, Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z));
else
cam.fpsLook(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z));
Matrix4f camMat = cam.GetMatrix();
cbuf.PickMVP = projMat.Mul(camMat);
ResourceFormat resFmt;
resFmt.compByteWidth = cfg.position.compByteWidth;
resFmt.compCount = cfg.position.compCount;
resFmt.compType = cfg.position.compType;
resFmt.special = false;
if(cfg.position.specialFormat != eSpecial_Unknown)
{
resFmt.special = true;
resFmt.specialFormat = cfg.position.specialFormat;
}
if(cfg.position.unproject)
{
// the derivation of the projection matrix might not be right (hell, it could be an
// orthographic projection). But it'll be close enough likely.
Matrix4f guessProj = Matrix4f::Perspective(cfg.fov, cfg.position.nearPlane, cfg.position.farPlane, cfg.aspect);
if(cfg.ortho)
guessProj = Matrix4f::Orthographic(cfg.position.nearPlane, cfg.position.farPlane);
cbuf.PickMVP = projMat.Mul(camMat.Mul(guessProj.Inverse()));
}
ID3D11Buffer *vb, *ib;
DXGI_FORMAT ifmt = cfg.position.idxByteWidth == 4 ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
{
auto it = WrappedID3D11Buffer::m_BufferList.find(cfg.position.buf);
if(it != WrappedID3D11Buffer::m_BufferList.end())
vb = UNWRAP(WrappedID3D11Buffer, it->second.m_Buffer);
it = WrappedID3D11Buffer::m_BufferList.find(cfg.position.idxbuf);
if(it != WrappedID3D11Buffer::m_BufferList.end())
ib = UNWRAP(WrappedID3D11Buffer, it->second.m_Buffer);
}
// most IB/VBs will not be available as SRVs. So, we copy into our own buffers.
// In the case of VB we also tightly pack and unpack the data. IB can just be
// read as R16 or R32 via the SRV so it is just a straight copy
if(cfg.position.idxByteWidth)
{
// resize up on demand
if(m_DebugRender.PickIBBuf == NULL || m_DebugRender.PickIBSize < cfg.position.numVerts*cfg.position.idxByteWidth)
{
SAFE_RELEASE(m_DebugRender.PickIBBuf);
SAFE_RELEASE(m_DebugRender.PickIBSRV);
D3D11_BUFFER_DESC desc = { cfg.position.numVerts*cfg.position.idxByteWidth, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, 0 };
m_DebugRender.PickIBSize = cfg.position.numVerts*cfg.position.idxByteWidth;
m_pDevice->CreateBuffer(&desc, NULL, &m_DebugRender.PickIBBuf);
D3D11_SHADER_RESOURCE_VIEW_DESC sdesc;
sdesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
sdesc.Format = ifmt;
sdesc.Buffer.FirstElement = 0;
sdesc.Buffer.NumElements = cfg.position.numVerts;
m_pDevice->CreateShaderResourceView(m_DebugRender.PickIBBuf, &sdesc, &m_DebugRender.PickIBSRV);
}
// copy index data as-is, the view format will take care of the rest
D3D11_BOX box;
box.front = 0;
box.back = 1;
box.left = cfg.position.idxoffs;
box.right = cfg.position.idxoffs + cfg.position.numVerts*cfg.position.idxByteWidth;
box.top = 0;
box.bottom = 1;
m_pImmediateContext->CopySubresourceRegion(m_DebugRender.PickIBBuf, 0, 0, 0, 0, ib, 0, &box);
}
if(m_DebugRender.PickVBBuf == NULL || m_DebugRender.PickVBSize < cfg.position.numVerts*sizeof(Vec4f))
{
SAFE_RELEASE(m_DebugRender.PickVBBuf);
SAFE_RELEASE(m_DebugRender.PickVBSRV);
D3D11_BUFFER_DESC desc = { cfg.position.numVerts*sizeof(Vec4f), D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, 0, 0 };
m_DebugRender.PickVBSize = cfg.position.numVerts*sizeof(Vec4f);
m_pDevice->CreateBuffer(&desc, NULL, &m_DebugRender.PickVBBuf);
D3D11_SHADER_RESOURCE_VIEW_DESC sdesc;
sdesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
sdesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
sdesc.Buffer.FirstElement = 0;
sdesc.Buffer.NumElements = cfg.position.numVerts;
m_pDevice->CreateShaderResourceView(m_DebugRender.PickVBBuf, &sdesc, &m_DebugRender.PickVBSRV);
}
// unpack and linearise the data
{
FloatVector *vbData = new FloatVector[cfg.position.numVerts];
vector<byte> oldData = GetBufferData(vb, cfg.position.offset, 0, false);
byte *data = &oldData[0];
byte *dataEnd = data + oldData.size();
bool valid;
for(uint32_t i=0; i < cfg.position.numVerts; i++)
vbData[i] = InterpretVertex(data, i, cfg, dataEnd, false, valid);
m_pImmediateContext->UpdateSubresource(m_DebugRender.PickVBBuf, 0, NULL, vbData, sizeof(Vec4f), sizeof(Vec4f));
delete[] vbData;
}
ID3D11ShaderResourceView *srvs[2] = { m_DebugRender.PickIBSRV, m_DebugRender.PickVBSRV };
ID3D11Buffer *buf = MakeCBuffer((float *)&cbuf, sizeof(cbuf));
m_pImmediateContext->CSSetConstantBuffers(0, 1, &buf);
m_pImmediateContext->CSSetShaderResources(0, 2, srvs);
UINT reset = 0;
m_pImmediateContext->CSSetUnorderedAccessViews(0, 1, &m_DebugRender.PickResultUAV, &reset);
m_pImmediateContext->CSSetShader(m_DebugRender.MeshPickCS, NULL, 0);
m_pImmediateContext->Dispatch(cfg.position.numVerts/1024 + 1, 1, 1);
m_pImmediateContext->CopyStructureCount(m_DebugRender.histogramBuff, 0, m_DebugRender.PickResultUAV);
vector<byte> results = GetBufferData(m_DebugRender.histogramBuff, 0, 0, false);
uint32_t numResults = *(uint32_t *)&results[0];
if(numResults > 0)
{
results = GetBufferData(m_DebugRender.PickResultBuf, 0, 0, false);
struct PickResult
{
uint32_t vertid; uint32_t idx; float len; float depth;
};
PickResult *pickResults = (PickResult *)&results[0];
PickResult *closest = pickResults;
// min with size of results buffer to protect against overflows
for(uint32_t i=1; i < RDCMIN(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;
}
return closest->vertid;
}
return ~0U;
}
void D3D11DebugManager::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4])
{
m_pImmediateContext->OMSetRenderTargets(1, &m_DebugRender.PickPixelRT, NULL);
@@ -3789,7 +3789,7 @@ bool WrappedID3D11DeviceContext::Serialise_DrawIndexedInstancedIndirect(ID3D11Bu
{
ID3D11Buffer *argBuffer = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetLiveResource(BufferForArgs);
vector<byte> args = m_pDevice->GetDebugManager()->GetBufferData(argBuffer, AlignedByteOffsetForArgs, 5*sizeof(uint32_t));
vector<byte> args = m_pDevice->GetDebugManager()->GetBufferData(argBuffer, AlignedByteOffsetForArgs, 5*sizeof(uint32_t), true);
uint32_t *uargs = (uint32_t *)&args[0];
name = "DrawIndexedInstancedIndirect(<" + ToStr::Get(uargs[0])
@@ -3864,7 +3864,7 @@ bool WrappedID3D11DeviceContext::Serialise_DrawInstancedIndirect(ID3D11Buffer *p
{
ID3D11Buffer *argBuffer = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetLiveResource(BufferForArgs);
vector<byte> args = m_pDevice->GetDebugManager()->GetBufferData(argBuffer, AlignedByteOffsetForArgs, 4*sizeof(uint32_t));
vector<byte> args = m_pDevice->GetDebugManager()->GetBufferData(argBuffer, AlignedByteOffsetForArgs, 4*sizeof(uint32_t), true);
uint32_t *uargs = (uint32_t *)&args[0];
name = "DrawInstancedIndirect(<" + ToStr::Get(uargs[0])
@@ -4555,7 +4555,7 @@ bool WrappedID3D11DeviceContext::Serialise_DispatchIndirect(ID3D11Buffer *pBuffe
{
ID3D11Buffer *argBuffer = (ID3D11Buffer *)m_pDevice->GetResourceManager()->GetLiveResource(BufferForArgs);
vector<byte> args = m_pDevice->GetDebugManager()->GetBufferData(argBuffer, AlignedByteOffsetForArgs, 5*sizeof(uint32_t));
vector<byte> args = m_pDevice->GetDebugManager()->GetBufferData(argBuffer, AlignedByteOffsetForArgs, 5*sizeof(uint32_t), true);
uint32_t *uargs = (uint32_t *)&args[0];
name = "DispatchIndirect(<" + ToStr::Get(uargs[0])
+93 -61
View File
@@ -771,6 +771,8 @@ bool D3D11DebugManager::InitDebugRendering()
displayhlsl += GetEmbeddedResource(debugcommon_hlsl);
displayhlsl += GetEmbeddedResource(debugdisplay_hlsl);
string meshhlsl = GetEmbeddedResource(debugcbuffers_h) + GetEmbeddedResource(mesh_hlsl);
m_DebugRender.FullscreenVS = MakeVShader(displayhlsl.c_str(), "RENDERDOC_FullscreenVS", "vs_4_0");
if(RenderDoc::Inst().IsReplayApp())
@@ -789,10 +791,10 @@ bool D3D11DebugManager::InitDebugRendering()
m_DebugRender.GenericVS = MakeVShader(displayhlsl.c_str(), "RENDERDOC_DebugVS", "vs_4_0");
m_DebugRender.TexDisplayPS = MakePShader(displayhlsl.c_str(), "RENDERDOC_TexDisplayPS", "ps_5_0");
m_DebugRender.WireframeVS = MakeVShader(displayhlsl.c_str(), "RENDERDOC_WireframeVS", "vs_4_0", 1, &inputDesc, &m_DebugRender.GenericLayout);
m_DebugRender.MeshVS = MakeVShader(displayhlsl.c_str(), "RENDERDOC_MeshVS", "vs_4_0", 0, NULL, NULL, &bytecode);
m_DebugRender.MeshGS = MakeGShader(displayhlsl.c_str(), "RENDERDOC_MeshGS", "gs_4_0");
m_DebugRender.MeshPS = MakePShader(displayhlsl.c_str(), "RENDERDOC_MeshPS", "ps_4_0");
m_DebugRender.WireframeVS = MakeVShader(meshhlsl.c_str(), "RENDERDOC_WireframeVS", "vs_4_0", 1, &inputDesc, &m_DebugRender.GenericLayout);
m_DebugRender.MeshVS = MakeVShader(meshhlsl.c_str(), "RENDERDOC_MeshVS", "vs_4_0", 0, NULL, NULL, &bytecode);
m_DebugRender.MeshGS = MakeGShader(meshhlsl.c_str(), "RENDERDOC_MeshGS", "gs_4_0");
m_DebugRender.MeshPS = MakePShader(meshhlsl.c_str(), "RENDERDOC_MeshPS", "ps_4_0");
m_DebugRender.MeshVSBytecode = new byte[bytecode.size()];
m_DebugRender.MeshVSBytelen = (uint32_t)bytecode.size();
@@ -816,7 +818,7 @@ bool D3D11DebugManager::InitDebugRendering()
inputDescHomog[1].AlignedByteOffset = 0;
inputDescHomog[1].InstanceDataStepRate = 0;
m_DebugRender.WireframeHomogVS = MakeVShader(displayhlsl.c_str(), "RENDERDOC_WireframeHomogVS", "vs_4_0", 2, inputDescHomog, &m_DebugRender.GenericHomogLayout, &bytecode);
m_DebugRender.WireframeHomogVS = MakeVShader(meshhlsl.c_str(), "RENDERDOC_WireframeHomogVS", "vs_4_0", 2, inputDescHomog, &m_DebugRender.GenericHomogLayout, &bytecode);
m_DebugRender.MeshHomogVSBytecode = new byte[bytecode.size()];
m_DebugRender.MeshHomogVSBytelen = (uint32_t)bytecode.size();
@@ -833,6 +835,8 @@ bool D3D11DebugManager::InitDebugRendering()
m_DebugRender.PixelHistoryCopyCS = MakeCShader(displayhlsl.c_str(), "RENDERDOC_PixelHistoryCopyPixel", "cs_5_0");
m_DebugRender.PrimitiveIDPS = MakePShader(displayhlsl.c_str(), "RENDERDOC_PrimitiveIDPS", "ps_5_0");
m_DebugRender.MeshPickCS = MakeCShader(meshhlsl.c_str(), "RENDERDOC_MeshPickCS", "cs_5_0");
string histogramhlsl = GetEmbeddedResource(debugcbuffers_h);
histogramhlsl += GetEmbeddedResource(debugcommon_hlsl);
histogramhlsl += GetEmbeddedResource(histogram_hlsl);
@@ -1215,6 +1219,34 @@ bool D3D11DebugManager::InitDebugRendering()
if(FAILED(hr))
RDCERR("Failed to create result stage buff %08x", hr);
bDesc.ByteWidth = sizeof(Vec4f)*DebugRenderData::maxMeshPicks;
bDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
bDesc.CPUAccessFlags = 0;
bDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
bDesc.StructureByteStride = sizeof(Vec4f);
bDesc.Usage = D3D11_USAGE_DEFAULT;
hr = m_pDevice->CreateBuffer(&bDesc, NULL, &m_DebugRender.PickResultBuf);
if(FAILED(hr))
RDCERR("Failed to create mesh pick result buff %08x", hr);
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.NumElements = DebugRenderData::maxMeshPicks;
uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_APPEND;
hr = m_pDevice->CreateUnorderedAccessView(m_DebugRender.PickResultBuf, &uavDesc, &m_DebugRender.PickResultUAV);
if(FAILED(hr))
RDCERR("Failed to create mesh pick result UAV %08x", hr);
// created/sized on demand
m_DebugRender.PickIBBuf = m_DebugRender.PickVBBuf = NULL;
m_DebugRender.PickIBSRV = m_DebugRender.PickVBSRV = NULL;
m_DebugRender.PickIBSize = m_DebugRender.PickVBSize = 0;
}
if(RenderDoc::Inst().IsReplayApp())
@@ -2099,10 +2131,10 @@ vector<byte> D3D11DebugManager::GetBufferData(ResourceId buff, uint32_t offset,
RDCASSERT(buffer);
return GetBufferData(buffer, offset, len);
return GetBufferData(buffer, offset, len, true);
}
vector<byte> D3D11DebugManager::GetBufferData(ID3D11Buffer *buffer, uint32_t offset, uint32_t len)
vector<byte> D3D11DebugManager::GetBufferData(ID3D11Buffer *buffer, uint32_t offset, uint32_t len, bool unwrap)
{
D3D11_MAPPED_SUBRESOURCE mapped;
@@ -2135,7 +2167,7 @@ vector<byte> D3D11DebugManager::GetBufferData(ID3D11Buffer *buffer, uint32_t off
box.front = 0;
box.back = 1;
ID3D11Buffer *src = UNWRAP(WrappedID3D11Buffer, buffer);
ID3D11Buffer *src = unwrap ? UNWRAP(WrappedID3D11Buffer, buffer) : buffer;
while(len > 0)
{
@@ -3911,7 +3943,7 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
ID3D11Buffer *origBuf = idxBuf;
vector<byte> idxdata = GetBufferData(idxBuf, idxOffs + drawcall->indexOffset*bytesize, drawcall->numIndices*bytesize);
vector<byte> idxdata = GetBufferData(idxBuf, idxOffs + drawcall->indexOffset*bytesize, drawcall->numIndices*bytesize, true);
SAFE_RELEASE(idxBuf);
@@ -4454,11 +4486,11 @@ void D3D11DebugManager::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
}
}
FloatVector D3D11DebugManager::InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool &valid)
FloatVector D3D11DebugManager::InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool useidx, bool &valid)
{
FloatVector ret(0.0f, 0.0f, 0.0f, 1.0f);
if(m_HighlightCache.useidx)
if(useidx && m_HighlightCache.useidx)
{
if(vert >= (uint32_t)m_HighlightCache.indices.size())
{
@@ -4966,7 +4998,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
primTopo = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
}
activeVertex = InterpretVertex(data, idx, cfg, dataEnd, valid);
activeVertex = InterpretVertex(data, idx, cfg, dataEnd, true, valid);
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx for
// how primitive topologies are laid out
@@ -4974,26 +5006,26 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
{
uint32_t v = uint32_t(idx/2) * 2; // find first vert in primitive
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
}
else if(meshtopo == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
{
uint32_t v = uint32_t(idx/3) * 3; // find first vert in primitive
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, true, valid));
}
else if(meshtopo == D3D11_PRIMITIVE_TOPOLOGY_LINELIST_ADJ)
{
uint32_t v = uint32_t(idx/4) * 4; // find first vert in primitive
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
};
adjacentPrimVertices.push_back(vs[0]);
@@ -5010,12 +5042,12 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
uint32_t v = uint32_t(idx/6) * 6; // find first vert in primitive
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+4, cfg, dataEnd, valid),
InterpretVertex(data, v+5, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
InterpretVertex(data, v+4, cfg, dataEnd, true, valid),
InterpretVertex(data, v+5, cfg, dataEnd, true, valid),
};
adjacentPrimVertices.push_back(vs[0]);
@@ -5042,8 +5074,8 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
// primitive, and thereafter each point is in the next primitive
uint32_t v = RDCMAX(idx, 1U) - 1;
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
}
else if(meshtopo == D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP)
{
@@ -5053,9 +5085,9 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
// primitive, and thereafter each point is in the next primitive
uint32_t v = RDCMAX(idx, 2U) - 2;
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, true, valid));
}
else if(meshtopo == D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ)
{
@@ -5066,10 +5098,10 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
uint32_t v = RDCMAX(idx, 3U) - 3;
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
};
adjacentPrimVertices.push_back(vs[0]);
@@ -5097,18 +5129,18 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
else if(idx <= 4 || numidx <= 7)
{
FloatVector vs[] = {
InterpretVertex(data, 0, cfg, dataEnd, valid),
InterpretVertex(data, 1, cfg, dataEnd, valid),
InterpretVertex(data, 2, cfg, dataEnd, valid),
InterpretVertex(data, 3, cfg, dataEnd, valid),
InterpretVertex(data, 4, cfg, dataEnd, valid),
InterpretVertex(data, 0, cfg, dataEnd, true, valid),
InterpretVertex(data, 1, cfg, dataEnd, true, valid),
InterpretVertex(data, 2, cfg, dataEnd, true, valid),
InterpretVertex(data, 3, cfg, dataEnd, true, valid),
InterpretVertex(data, 4, cfg, dataEnd, true, valid),
// note this one isn't used as it's adjacency for the next triangle
InterpretVertex(data, 5, cfg, dataEnd, valid),
InterpretVertex(data, 5, cfg, dataEnd, true, valid),
// min() with number of indices in case this is a tiny strip
// that is basically just a list
InterpretVertex(data, RDCMIN(6U, numidx-1), cfg, dataEnd, valid),
InterpretVertex(data, RDCMIN(6U, numidx-1), cfg, dataEnd, true, valid),
};
// these are the triangles on the far left of the MSDN diagram above
@@ -5133,18 +5165,18 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
// in diagram, numidx == 14
FloatVector vs[] = {
/*[0]=*/ InterpretVertex(data, numidx-8, cfg, dataEnd, valid), // 6 in diagram
/*[0]=*/ InterpretVertex(data, numidx-8, cfg, dataEnd, true, valid), // 6 in diagram
// as above, unused since this is adjacency for 2-previous triangle
/*[1]=*/ InterpretVertex(data, numidx-7, cfg, dataEnd, valid), // 7 in diagram
/*[2]=*/ InterpretVertex(data, numidx-6, cfg, dataEnd, valid), // 8 in diagram
/*[1]=*/ InterpretVertex(data, numidx-7, cfg, dataEnd, true, valid), // 7 in diagram
/*[2]=*/ InterpretVertex(data, numidx-6, cfg, dataEnd, true, valid), // 8 in diagram
// as above, unused since this is adjacency for previous triangle
/*[3]=*/ InterpretVertex(data, numidx-5, cfg, dataEnd, valid), // 9 in diagram
/*[4]=*/ InterpretVertex(data, numidx-4, cfg, dataEnd, valid), // 10 in diagram
/*[5]=*/ InterpretVertex(data, numidx-3, cfg, dataEnd, valid), // 11 in diagram
/*[6]=*/ InterpretVertex(data, numidx-2, cfg, dataEnd, valid), // 12 in diagram
/*[7]=*/ InterpretVertex(data, numidx-1, cfg, dataEnd, valid), // 13 in diagram
/*[3]=*/ InterpretVertex(data, numidx-5, cfg, dataEnd, true, valid), // 9 in diagram
/*[4]=*/ InterpretVertex(data, numidx-4, cfg, dataEnd, true, valid), // 10 in diagram
/*[5]=*/ InterpretVertex(data, numidx-3, cfg, dataEnd, true, valid), // 11 in diagram
/*[6]=*/ InterpretVertex(data, numidx-2, cfg, dataEnd, true, valid), // 12 in diagram
/*[7]=*/ InterpretVertex(data, numidx-1, cfg, dataEnd, true, valid), // 13 in diagram
};
// these are the triangles on the far right of the MSDN diagram above
@@ -5174,19 +5206,19 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
// these correspond to the indices in the MSDN diagram, with {2,4,6} as the
// main triangle
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
// this one is adjacency for 2-previous triangle
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
// this one is adjacency for previous triangle
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+4, cfg, dataEnd, valid),
InterpretVertex(data, v+5, cfg, dataEnd, valid),
InterpretVertex(data, v+6, cfg, dataEnd, valid),
InterpretVertex(data, v+7, cfg, dataEnd, valid),
InterpretVertex(data, v+8, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
InterpretVertex(data, v+4, cfg, dataEnd, true, valid),
InterpretVertex(data, v+5, cfg, dataEnd, true, valid),
InterpretVertex(data, v+6, cfg, dataEnd, true, valid),
InterpretVertex(data, v+7, cfg, dataEnd, true, valid),
InterpretVertex(data, v+8, cfg, dataEnd, true, valid),
};
// these are the triangles around {2,4,6} in the MSDN diagram above
@@ -5216,7 +5248,7 @@ void D3D11DebugManager::RenderMesh(uint32_t frameID, uint32_t eventID, const vec
for(uint32_t v = v0; v < v0+dim; v++)
{
if(v != idx && valid)
inactiveVertices.push_back(InterpretVertex(data, v, cfg, dataEnd, valid));
inactiveVertices.push_back(InterpretVertex(data, v, cfg, dataEnd, true, valid));
}
}
else // if(meshtopo == D3D11_PRIMITIVE_TOPOLOGY_POINTLIST) point list, or unknown/unhandled type
+20 -2
View File
@@ -119,8 +119,8 @@ class D3D11DebugManager
MeshFormat GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32_t instID, MeshDataStage stage);
uint32_t GetStructCount(ID3D11UnorderedAccessView *uav);
vector<byte> GetBufferData(ID3D11Buffer *buff, uint32_t offset, uint32_t len);
vector<byte> GetBufferData(ResourceId buff, uint32_t offset, uint32_t len);
vector<byte> GetBufferData(ID3D11Buffer *buff, uint32_t offset, uint32_t len, bool unwrap);
byte *GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool resolve, bool forceRGBA8unorm, float blackPoint, float whitePoint, size_t &dataSize);
@@ -171,6 +171,7 @@ class D3D11DebugManager
ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y, uint32_t sample, uint32_t primitive);
ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]);
void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4]);
uint32_t PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y);
ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents);
ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip);
@@ -343,7 +344,7 @@ class D3D11DebugManager
ID3D11Buffer *m_FrustumHelper;
ID3D11Buffer *m_TriHighlightHelper;
FloatVector InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool &valid);
FloatVector InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool useidx, bool &valid);
bool InitStreamOut();
void ShutdownStreamOut();
@@ -437,6 +438,14 @@ class D3D11DebugManager
SAFE_RELEASE(PixelHistoryCopyCS);
SAFE_RELEASE(PrimitiveIDPS);
SAFE_RELEASE(MeshPickCS);
SAFE_RELEASE(PickIBBuf);
SAFE_RELEASE(PickVBBuf);
SAFE_RELEASE(PickIBSRV);
SAFE_RELEASE(PickVBSRV);
SAFE_RELEASE(PickResultBuf);
SAFE_RELEASE(PickResultUAV);
SAFE_RELEASE(QuadOverdrawPS);
SAFE_RELEASE(QOResolvePS);
@@ -501,6 +510,15 @@ class D3D11DebugManager
ID3D11PixelShader *DepthCopyMSToArrayPS, *DepthCopyArrayToMSPS;
ID3D11ComputeShader *PixelHistoryUnusedCS, *PixelHistoryCopyCS;
ID3D11PixelShader *PrimitiveIDPS;
static const uint32_t maxMeshPicks = 500;
ID3D11ComputeShader *MeshPickCS;
ID3D11Buffer *PickIBBuf, *PickVBBuf;
uint32_t PickIBSize, PickVBSize;
ID3D11ShaderResourceView *PickIBSRV, *PickVBSRV;
ID3D11Buffer *PickResultBuf;
ID3D11UnorderedAccessView *PickResultUAV;
ID3D11PixelShader *QuadOverdrawPS, *QOResolvePS;
+5
View File
@@ -1374,6 +1374,11 @@ ShaderDebugTrace D3D11Replay::DebugThread(uint32_t frameID, uint32_t eventID, ui
return m_pDevice->GetDebugManager()->DebugThread(frameID, eventID, groupid, threadid);
}
uint32_t D3D11Replay::PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y)
{
return m_pDevice->GetDebugManager()->PickVertex(frameID, eventID, cfg, x, y);
}
void D3D11Replay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4])
{
m_pDevice->GetDebugManager()->PickPixel(texture, x, y, sliceFace, mip, sample, pixel);
+1
View File
@@ -121,6 +121,7 @@ class D3D11Replay : public IReplayDriver
ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y, uint32_t sample, uint32_t primitive);
ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]);
void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4]);
uint32_t PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y);
ResourceId RenderOverlay(ResourceId texid, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents);
+273 -52
View File
@@ -430,6 +430,26 @@ void GLReplay::InitDebugData()
DebugData.Array2MS = CreateCShaderProgram(glsl.c_str());
}
{
string glsl = GetEmbeddedResource(mesh_comp);
DebugData.meshPickProgram = CreateCShaderProgram(glsl.c_str());
}
{
gl.glGenBuffers(1, &DebugData.pickResultBuf);
gl.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickResultBuf);
gl.glNamedBufferStorageEXT(DebugData.pickResultBuf, sizeof(Vec4f)*DebugRenderData::maxMeshPicks, NULL, GL_MAP_READ_BIT);
gl.glGenBuffers(1, &DebugData.pickResultCounterBuf);
gl.glBindBuffer(eGL_ATOMIC_COUNTER_BUFFER, DebugData.pickResultCounterBuf);
gl.glNamedBufferStorageEXT(DebugData.pickResultCounterBuf, sizeof(uint32_t), NULL, GL_DYNAMIC_STORAGE_BIT);
// sized/created on demand
DebugData.pickVBBuf = DebugData.pickIBBuf = 0;
DebugData.pickVBSize = DebugData.pickIBSize = 0;
}
gl.glGenVertexArrays(1, &DebugData.meshVAO);
gl.glBindVertexArray(DebugData.meshVAO);
@@ -973,6 +993,207 @@ bool GLReplay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip,
return true;
}
uint32_t GLReplay::PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y)
{
WrappedOpenGL &gl = *m_pDriver;
MakeCurrentReplayContext(m_DebugCtx);
gl.glUseProgram(DebugData.meshPickProgram);
GLint loc = gl.glGetUniformLocation(DebugData.meshPickProgram, "PickCoords");
gl.glUniform2f(loc, (float)x, (float)y);
loc = gl.glGetUniformLocation(DebugData.meshPickProgram, "PickViewport");
gl.glUniform2f(loc, DebugData.outWidth, DebugData.outHeight);
loc = gl.glGetUniformLocation(DebugData.meshPickProgram, "PickIdx");
gl.glUniform1ui(loc, cfg.position.idxByteWidth ? 1U : 0U);
loc = gl.glGetUniformLocation(DebugData.meshPickProgram, "PickNumVerts");
gl.glUniform1ui(loc, cfg.position.numVerts);
Matrix4f projMat = Matrix4f::Perspective(90.0f, 0.1f, 100000.0f, DebugData.outWidth/DebugData.outHeight);
Camera cam;
if(cfg.arcballCamera)
cam.Arcball(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), cfg.cameraPos.w, Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z));
else
cam.fpsLook(Vec3f(cfg.cameraPos.x, cfg.cameraPos.y, cfg.cameraPos.z), Vec3f(cfg.cameraRot.x, cfg.cameraRot.y, cfg.cameraRot.z));
Matrix4f camMat = cam.GetMatrix();
Matrix4f PickMVP = projMat.Mul(camMat);
ResourceFormat resFmt;
resFmt.compByteWidth = cfg.position.compByteWidth;
resFmt.compCount = cfg.position.compCount;
resFmt.compType = cfg.position.compType;
resFmt.special = false;
if(cfg.position.specialFormat != eSpecial_Unknown)
{
resFmt.special = true;
resFmt.specialFormat = cfg.position.specialFormat;
}
if(cfg.position.unproject)
{
// the derivation of the projection matrix might not be right (hell, it could be an
// orthographic projection). But it'll be close enough likely.
Matrix4f guessProj = Matrix4f::Perspective(cfg.fov, cfg.position.nearPlane, cfg.position.farPlane, cfg.aspect);
if(cfg.ortho)
guessProj = Matrix4f::Orthographic(cfg.position.nearPlane, cfg.position.farPlane);
PickMVP = projMat.Mul(camMat.Mul(guessProj.Inverse()));
}
loc = gl.glGetUniformLocation(DebugData.meshPickProgram, "PickMVP");
gl.glUniformMatrix4fv(loc, 1, GL_FALSE, PickMVP.Data());
GLenum ifmt = cfg.position.idxByteWidth == 4 ? eGL_UNSIGNED_INT
: cfg.position.idxByteWidth == 2 ? eGL_UNSIGNED_SHORT
: eGL_UNSIGNED_BYTE;
GLuint ib = 0;
if(cfg.position.idxByteWidth && cfg.position.idxbuf != ResourceId())
ib = m_pDriver->GetResourceManager()->GetCurrentResource(cfg.position.idxbuf).name;
// We copy into our own buffers to promote to the target type (uint32) that the
// shader expects. Most IBs will be 16-bit indices, most VBs will not be float4.
if(ib)
{
// resize up on demand
if(DebugData.pickIBBuf == 0 || DebugData.pickIBSize < cfg.position.numVerts*sizeof(uint32_t))
{
gl.glDeleteBuffers(1, &DebugData.pickIBBuf);
gl.glGenBuffers(1, &DebugData.pickIBBuf);
gl.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickIBBuf);
gl.glNamedBufferStorageEXT(DebugData.pickIBBuf, cfg.position.numVerts*sizeof(uint32_t), NULL, GL_DYNAMIC_STORAGE_BIT);
DebugData.pickIBSize = cfg.position.numVerts*sizeof(uint32_t);
}
byte *idxs = new byte[cfg.position.numVerts*cfg.position.idxByteWidth];
uint32_t *outidxs = NULL;
if(cfg.position.idxByteWidth < 4)
outidxs = new uint32_t[cfg.position.numVerts];
gl.glBindBuffer(eGL_COPY_READ_BUFFER, ib);
gl.glGetBufferSubData(eGL_COPY_READ_BUFFER, cfg.position.idxoffs, cfg.position.numVerts*cfg.position.idxByteWidth, idxs);
uint16_t *idxs16 = (uint16_t *)idxs;
if(cfg.position.idxByteWidth == 1)
{
for(uint32_t i=0; i < cfg.position.numVerts; i++)
outidxs[i] = idxs[i];
gl.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickIBBuf);
gl.glBufferSubData(eGL_SHADER_STORAGE_BUFFER, 0, cfg.position.numVerts*sizeof(uint32_t), outidxs);
}
else if(cfg.position.idxByteWidth == 2)
{
for(uint32_t i=0; i < cfg.position.numVerts; i++)
outidxs[i] = idxs16[i];
gl.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickIBBuf);
gl.glBufferSubData(eGL_SHADER_STORAGE_BUFFER, 0, cfg.position.numVerts*sizeof(uint32_t), outidxs);
}
else
{
gl.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickIBBuf);
gl.glBufferSubData(eGL_SHADER_STORAGE_BUFFER, 0, cfg.position.numVerts*sizeof(uint32_t), idxs);
}
SAFE_DELETE_ARRAY(outidxs);
}
if(DebugData.pickVBBuf == 0 || DebugData.pickVBSize < cfg.position.numVerts*sizeof(uint32_t))
{
gl.glDeleteBuffers(1, &DebugData.pickVBBuf);
gl.glGenBuffers(1, &DebugData.pickVBBuf);
gl.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickVBBuf);
gl.glNamedBufferStorageEXT(DebugData.pickVBBuf, cfg.position.numVerts*sizeof(Vec4f), NULL, GL_DYNAMIC_STORAGE_BIT);
DebugData.pickVBSize = cfg.position.numVerts*sizeof(Vec4f);
}
// unpack and linearise the data
{
FloatVector *vbData = new FloatVector[cfg.position.numVerts];
vector<byte> oldData = GetBufferData(cfg.position.buf, cfg.position.offset, 0);
byte *data = &oldData[0];
byte *dataEnd = data + oldData.size();
bool valid;
for(uint32_t i=0; i < cfg.position.numVerts; i++)
vbData[i] = InterpretVertex(data, i, cfg, dataEnd, false, valid);
gl.glBindBuffer(eGL_SHADER_STORAGE_BUFFER, DebugData.pickVBBuf);
gl.glBufferSubData(eGL_SHADER_STORAGE_BUFFER, 0, cfg.position.numVerts*sizeof(Vec4f), vbData);
delete[] vbData;
}
uint32_t reset = 0;
gl.glBindBufferBase(eGL_ATOMIC_COUNTER_BUFFER, 0, DebugData.pickResultCounterBuf);
gl.glBufferSubData(eGL_ATOMIC_COUNTER_BUFFER, 0, sizeof(uint32_t), &reset);
gl.glBindBufferBase(eGL_SHADER_STORAGE_BUFFER, 0, DebugData.pickResultBuf);
gl.glBindBufferBase(eGL_SHADER_STORAGE_BUFFER, 1, DebugData.pickVBBuf);
gl.glBindBufferRange(eGL_SHADER_STORAGE_BUFFER, 2, DebugData.pickIBBuf,
cfg.position.idxoffs, cfg.position.idxoffs + cfg.position.idxByteWidth*cfg.position.numVerts);
gl.glDispatchCompute(GLuint(cfg.position.numVerts/1024 + 1), 1, 1);
gl.glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT|GL_SHADER_STORAGE_BARRIER_BIT);
uint32_t numResults = 0;
gl.glBindBuffer(eGL_COPY_READ_BUFFER, DebugData.pickResultCounterBuf);
gl.glGetBufferSubData(eGL_COPY_READ_BUFFER, 0, sizeof(uint32_t), &numResults);
if(numResults > 0)
{
struct PickResult
{
uint32_t vertid; uint32_t idx; float len; float depth;
};
PickResult *pickResults = (PickResult *)gl.glMapNamedBufferEXT(DebugData.pickResultBuf, eGL_READ_ONLY);
PickResult *closest = pickResults;
// min with size of results buffer to protect against overflows
for(uint32_t i=1; i < RDCMIN(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;
}
void GLReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4])
{
WrappedOpenGL &gl = *m_pDriver;
@@ -3012,11 +3233,11 @@ MeshFormat GLReplay::GetPostVSBuffers(uint32_t frameID, uint32_t eventID, uint32
return ret;
}
FloatVector GLReplay::InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool &valid)
FloatVector GLReplay::InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool useidx, bool &valid)
{
FloatVector ret(0.0f, 0.0f, 0.0f, 1.0f);
if(m_HighlightCache.useidx)
if(useidx && m_HighlightCache.useidx)
{
if(vert >= (uint32_t)m_HighlightCache.indices.size())
{
@@ -3588,7 +3809,7 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
primTopo = eGL_LINES;
}
activeVertex = InterpretVertex(data, idx, cfg, dataEnd, valid);
activeVertex = InterpretVertex(data, idx, cfg, dataEnd, true, valid);
// see Section 10.1 of the OpenGL 4.5 spec for
// how primitive topologies are laid out
@@ -3596,26 +3817,26 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
{
uint32_t v = uint32_t(idx/2) * 2; // find first vert in primitive
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
}
else if(meshtopo == eGL_TRIANGLES)
{
uint32_t v = uint32_t(idx/3) * 3; // find first vert in primitive
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, true, valid));
}
else if(meshtopo == eGL_LINES_ADJACENCY)
{
uint32_t v = uint32_t(idx/4) * 4; // find first vert in primitive
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
};
adjacentPrimVertices.push_back(vs[0]);
@@ -3632,12 +3853,12 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
uint32_t v = uint32_t(idx/6) * 6; // find first vert in primitive
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+4, cfg, dataEnd, valid),
InterpretVertex(data, v+5, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
InterpretVertex(data, v+4, cfg, dataEnd, true, valid),
InterpretVertex(data, v+5, cfg, dataEnd, true, valid),
};
adjacentPrimVertices.push_back(vs[0]);
@@ -3664,8 +3885,8 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
// primitive, and thereafter each point is in the next primitive
uint32_t v = RDCMAX(idx, 1U) - 1;
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
}
else if(meshtopo == eGL_TRIANGLE_STRIP)
{
@@ -3675,9 +3896,9 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
// primitive, and thereafter each point is in the next primitive
uint32_t v = RDCMAX(idx, 2U) - 2;
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, valid));
activePrim.push_back(InterpretVertex(data, v+0, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+1, cfg, dataEnd, true, valid));
activePrim.push_back(InterpretVertex(data, v+2, cfg, dataEnd, true, valid));
}
else if(meshtopo == eGL_LINE_STRIP_ADJACENCY)
{
@@ -3688,10 +3909,10 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
uint32_t v = RDCMAX(idx, 3U) - 3;
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
};
adjacentPrimVertices.push_back(vs[0]);
@@ -3719,18 +3940,18 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
else if(idx <= 4 || numidx <= 7)
{
FloatVector vs[] = {
InterpretVertex(data, 0, cfg, dataEnd, valid),
InterpretVertex(data, 1, cfg, dataEnd, valid),
InterpretVertex(data, 2, cfg, dataEnd, valid),
InterpretVertex(data, 3, cfg, dataEnd, valid),
InterpretVertex(data, 4, cfg, dataEnd, valid),
InterpretVertex(data, 0, cfg, dataEnd, true, valid),
InterpretVertex(data, 1, cfg, dataEnd, true, valid),
InterpretVertex(data, 2, cfg, dataEnd, true, valid),
InterpretVertex(data, 3, cfg, dataEnd, true, valid),
InterpretVertex(data, 4, cfg, dataEnd, true, valid),
// note this one isn't used as it's adjacency for the next triangle
InterpretVertex(data, 5, cfg, dataEnd, valid),
InterpretVertex(data, 5, cfg, dataEnd, true, valid),
// min() with number of indices in case this is a tiny strip
// that is basically just a list
InterpretVertex(data, RDCMIN(6U, numidx-1), cfg, dataEnd, valid),
InterpretVertex(data, RDCMIN(6U, numidx-1), cfg, dataEnd, true, valid),
};
// these are the triangles on the far left of the MSDN diagram above
@@ -3755,18 +3976,18 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
// in diagram, numidx == 14
FloatVector vs[] = {
/*[0]=*/ InterpretVertex(data, numidx-8, cfg, dataEnd, valid), // 6 in diagram
/*[0]=*/ InterpretVertex(data, numidx-8, cfg, dataEnd, true, valid), // 6 in diagram
// as above, unused since this is adjacency for 2-previous triangle
/*[1]=*/ InterpretVertex(data, numidx-7, cfg, dataEnd, valid), // 7 in diagram
/*[2]=*/ InterpretVertex(data, numidx-6, cfg, dataEnd, valid), // 8 in diagram
/*[1]=*/ InterpretVertex(data, numidx-7, cfg, dataEnd, true, valid), // 7 in diagram
/*[2]=*/ InterpretVertex(data, numidx-6, cfg, dataEnd, true, valid), // 8 in diagram
// as above, unused since this is adjacency for previous triangle
/*[3]=*/ InterpretVertex(data, numidx-5, cfg, dataEnd, valid), // 9 in diagram
/*[4]=*/ InterpretVertex(data, numidx-4, cfg, dataEnd, valid), // 10 in diagram
/*[5]=*/ InterpretVertex(data, numidx-3, cfg, dataEnd, valid), // 11 in diagram
/*[6]=*/ InterpretVertex(data, numidx-2, cfg, dataEnd, valid), // 12 in diagram
/*[7]=*/ InterpretVertex(data, numidx-1, cfg, dataEnd, valid), // 13 in diagram
/*[3]=*/ InterpretVertex(data, numidx-5, cfg, dataEnd, true, valid), // 9 in diagram
/*[4]=*/ InterpretVertex(data, numidx-4, cfg, dataEnd, true, valid), // 10 in diagram
/*[5]=*/ InterpretVertex(data, numidx-3, cfg, dataEnd, true, valid), // 11 in diagram
/*[6]=*/ InterpretVertex(data, numidx-2, cfg, dataEnd, true, valid), // 12 in diagram
/*[7]=*/ InterpretVertex(data, numidx-1, cfg, dataEnd, true, valid), // 13 in diagram
};
// these are the triangles on the far right of the MSDN diagram above
@@ -3796,19 +4017,19 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
// these correspond to the indices in the MSDN diagram, with {2,4,6} as the
// main triangle
FloatVector vs[] = {
InterpretVertex(data, v+0, cfg, dataEnd, valid),
InterpretVertex(data, v+0, cfg, dataEnd, true, valid),
// this one is adjacency for 2-previous triangle
InterpretVertex(data, v+1, cfg, dataEnd, valid),
InterpretVertex(data, v+2, cfg, dataEnd, valid),
InterpretVertex(data, v+1, cfg, dataEnd, true, valid),
InterpretVertex(data, v+2, cfg, dataEnd, true, valid),
// this one is adjacency for previous triangle
InterpretVertex(data, v+3, cfg, dataEnd, valid),
InterpretVertex(data, v+4, cfg, dataEnd, valid),
InterpretVertex(data, v+5, cfg, dataEnd, valid),
InterpretVertex(data, v+6, cfg, dataEnd, valid),
InterpretVertex(data, v+7, cfg, dataEnd, valid),
InterpretVertex(data, v+8, cfg, dataEnd, valid),
InterpretVertex(data, v+3, cfg, dataEnd, true, valid),
InterpretVertex(data, v+4, cfg, dataEnd, true, valid),
InterpretVertex(data, v+5, cfg, dataEnd, true, valid),
InterpretVertex(data, v+6, cfg, dataEnd, true, valid),
InterpretVertex(data, v+7, cfg, dataEnd, true, valid),
InterpretVertex(data, v+8, cfg, dataEnd, true, valid),
};
// these are the triangles around {2,4,6} in the MSDN diagram above
@@ -3838,7 +4059,7 @@ void GLReplay::RenderMesh(uint32_t frameID, uint32_t eventID, const vector<MeshF
for(uint32_t v = v0; v < v0+dim; v++)
{
if(v != idx && valid)
inactiveVertices.push_back(InterpretVertex(data, v, cfg, dataEnd, valid));
inactiveVertices.push_back(InterpretVertex(data, v, cfg, dataEnd, true, valid));
}
}
else // if(meshtopo == eGL_POINTS) point list, or unknown/unhandled type
+11 -2
View File
@@ -165,6 +165,7 @@ class GLReplay : public IReplayDriver
ShaderDebugTrace DebugPixel(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y, uint32_t sample, uint32_t primitive);
ShaderDebugTrace DebugThread(uint32_t frameID, uint32_t eventID, uint32_t groupid[3], uint32_t threadid[3]);
void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4]);
uint32_t PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y);
ResourceId RenderOverlay(ResourceId cfg, TextureDisplayOverlay overlay, uint32_t frameID, uint32_t eventID, const vector<uint32_t> &passEvents);
ResourceId ApplyCustomShader(ResourceId shader, ResourceId texid, uint32_t mip);
@@ -230,7 +231,7 @@ class GLReplay : public IReplayDriver
// any objects that are shared between contexts, we just initialise
// once
struct
struct DebugRenderData
{
float outWidth, outHeight;
@@ -255,6 +256,14 @@ class GLReplay : public IReplayDriver
GLuint customFBO;
GLuint customTex;
ResourceId CustomShaderTexID;
static const uint32_t maxMeshPicks = 500;
GLuint meshPickProgram;
GLuint pickIBBuf, pickVBBuf;
uint32_t pickIBSize, pickVBSize;
GLuint pickResultBuf;
GLuint pickResultCounterBuf;
GLuint MS2Array, Array2MS;
@@ -302,7 +311,7 @@ class GLReplay : public IReplayDriver
GLuint emptyVAO;
} DebugData;
FloatVector InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool &valid);
FloatVector InterpretVertex(byte *data, uint32_t vert, MeshDisplay cfg, byte *end, bool useidx, bool &valid);
// simple cache for when we need buffer data for highlighting
// vertices, typical use will be lots of vertices in the same
+2
View File
@@ -335,6 +335,7 @@
<None Include="data\glsl\generic.frag" />
<None Include="data\glsl\generic.vert" />
<None Include="data\glsl\histogram.comp" />
<None Include="data\glsl\mesh.comp" />
<None Include="data\glsl\mesh.frag" />
<None Include="data\glsl\mesh.geom" />
<None Include="data\glsl\mesh.vert" />
@@ -346,6 +347,7 @@
<None Include="data\hlsl\debugdisplay.hlsl" />
<None Include="data\hlsl\debugtext.hlsl" />
<None Include="data\hlsl\histogram.hlsl" />
<None Include="data\hlsl\mesh.hlsl" />
<None Include="data\hlsl\multisample.hlsl" />
<None Include="os\win32\comexport.def" />
</ItemGroup>
+6
View File
@@ -403,6 +403,12 @@
<None Include="data\glsl\quadoverdraw.frag">
<Filter>Resources\glsl</Filter>
</None>
<None Include="data\hlsl\mesh.hlsl">
<Filter>Resources\hlsl</Filter>
</None>
<None Include="data\glsl\mesh.comp">
<Filter>Resources\glsl</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="data\renderdoc.rc">
+1
View File
@@ -147,4 +147,5 @@ class IReplayDriver : public IRemoteDriver
virtual void RenderHighlightBox(float w, float h, float scale) = 0;
virtual void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4]) = 0;
virtual uint32_t PickVertex(uint32_t frameID, uint32_t eventID, MeshDisplay cfg, uint32_t x, uint32_t y) = 0;
};
+20
View File
@@ -307,6 +307,23 @@ bool ReplayOutput::PickPixel(ResourceId tex, bool customShader, uint32_t x, uint
return true;
}
uint32_t ReplayOutput::PickVertex(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y)
{
FetchDrawcall *draw = m_pRenderer->GetDrawcallByEID(eventID, 0);
if(!draw) return ~0U;
if(m_RenderData.meshDisplay.type == eMeshDataStage_Unknown) return ~0U;
if((draw->flags & eDraw_Drawcall) == 0) return ~0U;
MeshDisplay cfg = m_RenderData.meshDisplay;
cfg.position.buf = m_pDevice->GetLiveID(cfg.position.buf);
cfg.position.idxbuf = m_pDevice->GetLiveID(cfg.position.idxbuf);
cfg.second.buf = m_pDevice->GetLiveID(cfg.second.buf);
cfg.second.idxbuf = m_pDevice->GetLiveID(cfg.second.idxbuf);
return m_pDevice->PickVertex(m_FrameID, m_EventID, cfg, x, y);
}
bool ReplayOutput::SetPixelContextLocation(uint32_t x, uint32_t y)
{
m_ContextX = RDCMAX((float)x, 0.0f);
@@ -637,3 +654,6 @@ extern "C" RENDERDOC_API void RENDERDOC_CC ReplayOutput_DisablePixelContext(Repl
extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayOutput_PickPixel(ReplayOutput *output, ResourceId texID, bool32 customShader,
uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, PixelValue *val)
{ return output->PickPixel(texID, customShader != 0, x, y, sliceFace, mip, sample, val); }
extern "C" RENDERDOC_API uint32_t RENDERDOC_CC ReplayOutput_PickVertex(ReplayOutput *output, uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y)
{ return output->PickVertex(frameID, eventID, x, y); }
+1
View File
@@ -58,6 +58,7 @@ public:
bool PickPixel(ResourceId texID, bool customShader,
uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample,
PixelValue *val);
uint32_t PickVertex(uint32_t frameID, uint32_t eventID, uint32_t x, uint32_t y);
private:
ReplayOutput(ReplayRenderer *parent, void *w);
~ReplayOutput();
+7
View File
@@ -102,6 +102,8 @@ namespace renderdoc
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern bool ReplayOutput_PickPixel(IntPtr real, ResourceId texID, bool customShader,
UInt32 x, UInt32 y, UInt32 sliceFace, UInt32 mip, UInt32 sample, IntPtr outval);
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 ReplayOutput_PickVertex(IntPtr real, UInt32 frameID, UInt32 eventID, UInt32 x, UInt32 y);
private IntPtr m_Real = IntPtr.Zero;
@@ -163,6 +165,11 @@ namespace renderdoc
return ret;
}
public UInt32 PickVertex(UInt32 frameID, UInt32 eventID, UInt32 x, UInt32 y)
{
return ReplayOutput_PickVertex(m_Real, frameID, eventID, x, y);
}
};
public class ReplayRenderer
+38
View File
@@ -2005,6 +2005,38 @@ namespace renderdocui.Windows
}
}
private void PickVert(Point p)
{
if (!m_Core.LogLoaded)
return;
m_Core.Renderer.BeginInvoke((ReplayRenderer r) =>
{
UInt32 vertSelected = m_Output.PickVertex(m_Core.CurFrame, m_Core.CurEvent, (UInt32)p.X, (UInt32)p.Y);
if (vertSelected != UInt32.MaxValue)
{
this.BeginInvoke(new Action(() =>
{
var ui = GetUIState(m_MeshDisplay.type);
int row = (int)vertSelected;
if (row >= 0 && row < ui.m_GridView.RowCount)
{
if (ui.m_GridView.SelectedRows.Count == 0 || ui.m_GridView.SelectedRows[0] != ui.m_GridView.Rows[row])
{
ScrollToRow(ui.m_GridView, row);
ui.m_GridView.ClearSelection();
ui.m_GridView.Rows[row].Selected = true;
}
}
}));
}
});
}
void BufferViewer_KeyUp(object sender, KeyEventArgs e)
{
m_CurrentCamera.KeyUp(sender, e);
@@ -2023,11 +2055,17 @@ namespace renderdocui.Windows
private void render_MouseMove(object sender, MouseEventArgs e)
{
m_CurrentCamera.MouseMove(sender, e);
if (e.Button == MouseButtons.Right)
PickVert(e.Location);
}
private void render_MouseClick(object sender, MouseEventArgs e)
{
m_CurrentCamera.MouseClick(sender, e);
if (e.Button == MouseButtons.Right)
PickVert(e.Location);
}
private void render_MouseDown(object sender, MouseEventArgs e)