mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Implement right click to pick vertices in the mesh viewer. Refs #139
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user