mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-07 02:20:31 +00:00
326ca2ebe8
* Expand the abilities of the GetTextureData in replay drivers to be able to resolve samples and render down to RGBA8 unorm for file export to other programs. * Greatly improve the ability to save textures - in theory any texture format/type/dimension/etc should now be mappable in sensible & useful ways to output formats.
893 lines
36 KiB
C#
893 lines
36 KiB
C#
/******************************************************************************
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2014 Crytek
|
|
*
|
|
* 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.
|
|
******************************************************************************/
|
|
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Collections.Generic;
|
|
|
|
namespace renderdoc
|
|
{
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public class RemoteMessage
|
|
{
|
|
public RemoteMessageType Type;
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct NewCaptureData
|
|
{
|
|
public UInt32 ID;
|
|
public UInt64 timestamp;
|
|
[CustomMarshalAs(CustomUnmanagedType.TemplatedArray)]
|
|
public byte[] thumbnail;
|
|
[CustomMarshalAs(CustomUnmanagedType.WideTemplatedString)]
|
|
public string localpath;
|
|
};
|
|
[CustomMarshalAs(CustomUnmanagedType.CustomClass)]
|
|
public NewCaptureData NewCapture;
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct RegisterAPIData
|
|
{
|
|
[CustomMarshalAs(CustomUnmanagedType.WideTemplatedString)]
|
|
public string APIName;
|
|
};
|
|
|
|
[CustomMarshalAs(CustomUnmanagedType.CustomClass)]
|
|
public RegisterAPIData RegisterAPI;
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct BusyData
|
|
{
|
|
[CustomMarshalAs(CustomUnmanagedType.WideTemplatedString)]
|
|
public string ClientName;
|
|
};
|
|
[CustomMarshalAs(CustomUnmanagedType.CustomClass)]
|
|
public BusyData Busy;
|
|
};
|
|
|
|
public class ReplayOutput
|
|
{
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_SetOutputConfig(IntPtr real, OutputConfig o);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_SetTextureDisplay(IntPtr real, TextureDisplay o);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_SetMeshDisplay(IntPtr real, MeshDisplay o);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_ClearThumbnails(IntPtr real);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_AddThumbnail(IntPtr real, IntPtr wnd, ResourceId texID);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_Display(IntPtr real);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_SetPixelContext(IntPtr real, IntPtr wnd);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayOutput_SetPixelContextLocation(IntPtr real, UInt32 x, UInt32 y);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void ReplayOutput_DisablePixelContext(IntPtr real);
|
|
|
|
[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);
|
|
|
|
private IntPtr m_Real = IntPtr.Zero;
|
|
|
|
public ReplayOutput(IntPtr real) { m_Real = real; }
|
|
|
|
public bool SetOutputConfig(OutputConfig o)
|
|
{
|
|
return ReplayOutput_SetOutputConfig(m_Real, o);
|
|
}
|
|
public bool SetTextureDisplay(TextureDisplay o)
|
|
{
|
|
return ReplayOutput_SetTextureDisplay(m_Real, o);
|
|
}
|
|
public bool SetMeshDisplay(MeshDisplay o)
|
|
{
|
|
return ReplayOutput_SetMeshDisplay(m_Real, o);
|
|
}
|
|
|
|
public bool ClearThumbnails()
|
|
{
|
|
return ReplayOutput_ClearThumbnails(m_Real);
|
|
}
|
|
public bool AddThumbnail(IntPtr wnd, ResourceId texID)
|
|
{
|
|
return ReplayOutput_AddThumbnail(m_Real, wnd, texID);
|
|
}
|
|
|
|
public bool Display()
|
|
{
|
|
return ReplayOutput_Display(m_Real);
|
|
}
|
|
|
|
public bool SetPixelContext(IntPtr wnd)
|
|
{
|
|
return ReplayOutput_SetPixelContext(m_Real, wnd);
|
|
}
|
|
public bool SetPixelContextLocation(UInt32 x, UInt32 y)
|
|
{
|
|
return ReplayOutput_SetPixelContextLocation(m_Real, x, y);
|
|
}
|
|
public void DisablePixelContext()
|
|
{
|
|
ReplayOutput_DisablePixelContext(m_Real);
|
|
}
|
|
|
|
public PixelValue PickPixel(ResourceId texID, bool customShader, UInt32 x, UInt32 y, UInt32 sliceFace, UInt32 mip, UInt32 sample)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(PixelValue));
|
|
|
|
bool success = ReplayOutput_PickPixel(m_Real, texID, customShader, x, y, sliceFace, mip, sample, mem);
|
|
|
|
PixelValue ret = null;
|
|
|
|
if(success)
|
|
ret = (PixelValue)CustomMarshal.PtrToStructure(mem, typeof(PixelValue), false);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
};
|
|
|
|
public class ReplayRenderer
|
|
{
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void ReplayRenderer_Shutdown(IntPtr real);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void ReplayRenderer_GetAPIProperties(IntPtr real, IntPtr propsOut);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr ReplayRenderer_CreateOutput(IntPtr real, IntPtr WindowHandle);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void ReplayRenderer_ShutdownOutput(IntPtr real, IntPtr replayOutput);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_HasCallstacks(IntPtr real);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_InitResolver(IntPtr real);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_SetContextFilter(IntPtr real, ResourceId id, UInt32 firstDefEv, UInt32 lastDefEv);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_SetFrameEvent(IntPtr real, UInt32 frameID, UInt32 eventID);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetD3D11PipelineState(IntPtr real, IntPtr mem);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetGLPipelineState(IntPtr real, IntPtr mem);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_BuildCustomShader(IntPtr real, string entry, string source, UInt32 compileFlags, ShaderStageType type, ref ResourceId shaderID, IntPtr errorMem);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_FreeCustomShader(IntPtr real, ResourceId id);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_BuildTargetShader(IntPtr real, string entry, string source, UInt32 compileFlags, ShaderStageType type, ref ResourceId shaderID, IntPtr errorMem);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_ReplaceResource(IntPtr real, ResourceId from, ResourceId to);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_RemoveReplacement(IntPtr real, ResourceId id);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_FreeTargetResource(IntPtr real, ResourceId id);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetFrameInfo(IntPtr real, IntPtr outframe);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetDrawcalls(IntPtr real, UInt32 frameID, bool includeTimes, IntPtr outdraws);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetTextures(IntPtr real, IntPtr outtexs);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetBuffers(IntPtr real, IntPtr outbufs);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetResolve(IntPtr real, UInt64[] callstack, UInt32 callstackLen, IntPtr outtrace);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr ReplayRenderer_GetShaderDetails(IntPtr real, ResourceId shader);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_PixelHistory(IntPtr real, ResourceId target, UInt32 x, UInt32 y, IntPtr history);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_VSGetDebugStates(IntPtr real, UInt32 vertid, UInt32 instid, UInt32 idx, UInt32 instOffset, UInt32 vertOffset, IntPtr outtrace);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_PSGetDebugStates(IntPtr real, UInt32 x, UInt32 y, IntPtr outtrace);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_CSGetDebugStates(IntPtr real, UInt32[] groupid, UInt32[] threadid, IntPtr outtrace);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetUsage(IntPtr real, ResourceId id, IntPtr outusage);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetCBufferVariableContents(IntPtr real, ResourceId shader, UInt32 cbufslot, ResourceId buffer, UInt32 offs, IntPtr outvars);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_SaveTexture(IntPtr real, TextureSave saveData, string path);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetPostVSData(IntPtr real, MeshDataStage stage, IntPtr outdata);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetMinMax(IntPtr real, ResourceId tex, UInt32 sliceFace, UInt32 mip, UInt32 sample, IntPtr outminval, IntPtr outmaxval);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetHistogram(IntPtr real, ResourceId tex, UInt32 sliceFace, UInt32 mip, UInt32 sample, float minval, float maxval, bool[] channels, IntPtr outhistogram);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool ReplayRenderer_GetBufferData(IntPtr real, ResourceId buff, UInt32 offset, UInt32 len, IntPtr outdata);
|
|
|
|
private IntPtr m_Real = IntPtr.Zero;
|
|
|
|
public ReplayRenderer(IntPtr real) { m_Real = real; }
|
|
|
|
public void Shutdown()
|
|
{
|
|
if (m_Real != IntPtr.Zero)
|
|
{
|
|
ReplayRenderer_Shutdown(m_Real);
|
|
m_Real = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
public APIProperties GetAPIProperties()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(APIProperties));
|
|
|
|
ReplayRenderer_GetAPIProperties(m_Real, mem);
|
|
|
|
APIProperties ret = (APIProperties)CustomMarshal.PtrToStructure(mem, typeof(APIProperties), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ReplayOutput CreateOutput(IntPtr WindowHandle)
|
|
{
|
|
IntPtr ret = ReplayRenderer_CreateOutput(m_Real, WindowHandle);
|
|
|
|
if (ret == IntPtr.Zero)
|
|
return null;
|
|
|
|
return new ReplayOutput(ret);
|
|
}
|
|
|
|
public bool HasCallstacks()
|
|
{ return ReplayRenderer_HasCallstacks(m_Real); }
|
|
|
|
public bool InitResolver()
|
|
{ return ReplayRenderer_InitResolver(m_Real); }
|
|
|
|
public bool SetContextFilter(ResourceId id, UInt32 firstDefEv, UInt32 lastDefEv)
|
|
{ return ReplayRenderer_SetContextFilter(m_Real, id, firstDefEv, lastDefEv); }
|
|
public bool SetFrameEvent(UInt32 frameID, UInt32 eventID)
|
|
{ return ReplayRenderer_SetFrameEvent(m_Real, frameID, eventID); }
|
|
|
|
public GLPipelineState GetGLPipelineState()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(GLPipelineState));
|
|
|
|
bool success = ReplayRenderer_GetGLPipelineState(m_Real, mem);
|
|
|
|
GLPipelineState ret = null;
|
|
|
|
if (success)
|
|
ret = (GLPipelineState)CustomMarshal.PtrToStructure(mem, typeof(GLPipelineState), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public D3D11PipelineState GetD3D11PipelineState()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(D3D11PipelineState));
|
|
|
|
bool success = ReplayRenderer_GetD3D11PipelineState(m_Real, mem);
|
|
|
|
D3D11PipelineState ret = null;
|
|
|
|
if (success)
|
|
ret = (D3D11PipelineState)CustomMarshal.PtrToStructure(mem, typeof(D3D11PipelineState), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ResourceId BuildCustomShader(string entry, string source, UInt32 compileFlags, ShaderStageType type, out string errors)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
ResourceId ret = ResourceId.Null;
|
|
|
|
bool success = ReplayRenderer_BuildCustomShader(m_Real, entry, source, compileFlags, type, ref ret, mem);
|
|
|
|
if (!success)
|
|
ret = ResourceId.Null;
|
|
|
|
errors = CustomMarshal.TemplatedArrayToUniString(mem, true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public bool FreeCustomShader(ResourceId id)
|
|
{ return ReplayRenderer_FreeCustomShader(m_Real, id); }
|
|
|
|
public ResourceId BuildTargetShader(string entry, string source, UInt32 compileFlags, ShaderStageType type, out string errors)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
ResourceId ret = ResourceId.Null;
|
|
|
|
bool success = ReplayRenderer_BuildTargetShader(m_Real, entry, source, compileFlags, type, ref ret, mem);
|
|
|
|
if (!success)
|
|
ret = ResourceId.Null;
|
|
|
|
errors = CustomMarshal.TemplatedArrayToUniString(mem, true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public bool ReplaceResource(ResourceId from, ResourceId to)
|
|
{ return ReplayRenderer_ReplaceResource(m_Real, from, to); }
|
|
public bool RemoveReplacement(ResourceId id)
|
|
{ return ReplayRenderer_RemoveReplacement(m_Real, id); }
|
|
public bool FreeTargetResource(ResourceId id)
|
|
{ return ReplayRenderer_FreeTargetResource(m_Real, id); }
|
|
|
|
public FetchFrameInfo[] GetFrameInfo()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_GetFrameInfo(m_Real, mem);
|
|
|
|
FetchFrameInfo[] ret = null;
|
|
|
|
if (success)
|
|
ret = (FetchFrameInfo[])CustomMarshal.GetTemplatedArray(mem, typeof(FetchFrameInfo), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
private void PopulateDraws(ref Dictionary<Int64, FetchDrawcall> map, FetchDrawcall[] draws)
|
|
{
|
|
if (draws.Length == 0) return;
|
|
|
|
foreach (var d in draws)
|
|
{
|
|
map.Add((Int64)d.eventID, d);
|
|
PopulateDraws(ref map, d.children);
|
|
}
|
|
}
|
|
|
|
private void FixupDraws(Dictionary<Int64, FetchDrawcall> map, FetchDrawcall[] draws)
|
|
{
|
|
if (draws.Length == 0) return;
|
|
|
|
foreach (var d in draws)
|
|
{
|
|
if (d.previousDrawcall != 0 && map.ContainsKey(d.previousDrawcall)) d.previous = map[d.previousDrawcall];
|
|
if (d.nextDrawcall != 0 && map.ContainsKey(d.nextDrawcall)) d.next = map[d.nextDrawcall];
|
|
if (d.parentDrawcall != 0 && map.ContainsKey(d.parentDrawcall)) d.parent = map[d.parentDrawcall];
|
|
|
|
FixupDraws(map, d.children);
|
|
}
|
|
}
|
|
|
|
public FetchDrawcall[] GetDrawcalls(UInt32 frameID, bool includeTimes)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_GetDrawcalls(m_Real, frameID, includeTimes, mem);
|
|
|
|
FetchDrawcall[] ret = null;
|
|
|
|
if (success)
|
|
{
|
|
ret = (FetchDrawcall[])CustomMarshal.GetTemplatedArray(mem, typeof(FetchDrawcall), true);
|
|
|
|
// fixup previous/next/parent pointers
|
|
var map = new Dictionary<Int64, FetchDrawcall>();
|
|
PopulateDraws(ref map, ret);
|
|
FixupDraws(map, ret);
|
|
}
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public FetchTexture[] GetTextures()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_GetTextures(m_Real, mem);
|
|
|
|
FetchTexture[] ret = null;
|
|
|
|
if (success)
|
|
ret = (FetchTexture[])CustomMarshal.GetTemplatedArray(mem, typeof(FetchTexture), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public FetchBuffer[] GetBuffers()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_GetBuffers(m_Real, mem);
|
|
|
|
FetchBuffer[] ret = null;
|
|
|
|
if (success)
|
|
ret = (FetchBuffer[])CustomMarshal.GetTemplatedArray(mem, typeof(FetchBuffer), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public string[] GetResolve(UInt64[] callstack)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
UInt32 len = (UInt32)callstack.Length;
|
|
|
|
bool success = ReplayRenderer_GetResolve(m_Real, callstack, len, mem);
|
|
|
|
string[] ret = null;
|
|
|
|
if (success)
|
|
ret = CustomMarshal.TemplatedArrayToUniStringArray(mem, true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ShaderReflection GetShaderDetails(ResourceId shader)
|
|
{
|
|
IntPtr mem = ReplayRenderer_GetShaderDetails(m_Real, shader);
|
|
|
|
ShaderReflection ret = null;
|
|
|
|
if (mem != IntPtr.Zero)
|
|
ret = (ShaderReflection)CustomMarshal.PtrToStructure(mem, typeof(ShaderReflection), false);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public PixelModification[] PixelHistory(ResourceId target, UInt32 x, UInt32 y)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_PixelHistory(m_Real, target, x, y, mem);
|
|
|
|
PixelModification[] ret = null;
|
|
|
|
if (success)
|
|
ret = (PixelModification[])CustomMarshal.GetTemplatedArray(mem, typeof(PixelModification), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ShaderDebugTrace VSGetDebugStates(UInt32 vertid, UInt32 instid, UInt32 idx, UInt32 instOffset, UInt32 vertOffset)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(ShaderDebugTrace));
|
|
|
|
bool success = ReplayRenderer_VSGetDebugStates(m_Real, vertid, instid, idx, instOffset, vertOffset, mem);
|
|
|
|
ShaderDebugTrace ret = null;
|
|
|
|
if (success)
|
|
ret = (ShaderDebugTrace)CustomMarshal.PtrToStructure(mem, typeof(ShaderDebugTrace), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ShaderDebugTrace PSGetDebugStates(UInt32 x, UInt32 y)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(ShaderDebugTrace));
|
|
|
|
bool success = ReplayRenderer_PSGetDebugStates(m_Real, x, y, mem);
|
|
|
|
ShaderDebugTrace ret = null;
|
|
|
|
if (success)
|
|
ret = (ShaderDebugTrace)CustomMarshal.PtrToStructure(mem, typeof(ShaderDebugTrace), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ShaderDebugTrace CSGetDebugStates(UInt32[] groupid, UInt32[] threadid)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(ShaderDebugTrace));
|
|
|
|
bool success = ReplayRenderer_CSGetDebugStates(m_Real, groupid, threadid, mem);
|
|
|
|
ShaderDebugTrace ret = null;
|
|
|
|
if (success)
|
|
ret = (ShaderDebugTrace)CustomMarshal.PtrToStructure(mem, typeof(ShaderDebugTrace), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public EventUsage[] GetUsage(ResourceId id)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_GetUsage(m_Real, id, mem);
|
|
|
|
EventUsage[] ret = null;
|
|
|
|
if (success)
|
|
ret = (EventUsage[])CustomMarshal.GetTemplatedArray(mem, typeof(EventUsage), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ShaderVariable[] GetCBufferVariableContents(ResourceId shader, UInt32 cbufslot, ResourceId buffer, UInt32 offs)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_GetCBufferVariableContents(m_Real, shader, cbufslot, buffer, offs, mem);
|
|
|
|
ShaderVariable[] ret = null;
|
|
|
|
if (success)
|
|
ret = (ShaderVariable[])CustomMarshal.GetTemplatedArray(mem, typeof(ShaderVariable), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public bool SaveTexture(TextureSave saveData, string path)
|
|
{ return ReplayRenderer_SaveTexture(m_Real, saveData, path); }
|
|
|
|
public PostVSMeshData GetPostVSData(MeshDataStage stage)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(PostVSMeshData));
|
|
|
|
PostVSMeshData ret = null;
|
|
|
|
bool success = ReplayRenderer_GetPostVSData(m_Real, stage, mem);
|
|
|
|
if (success)
|
|
ret = (PostVSMeshData)CustomMarshal.PtrToStructure(mem, typeof(PostVSMeshData), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public bool GetMinMax(ResourceId tex, UInt32 sliceFace, UInt32 mip, UInt32 sample, out PixelValue minval, out PixelValue maxval)
|
|
{
|
|
IntPtr mem1 = CustomMarshal.Alloc(typeof(PixelValue));
|
|
IntPtr mem2 = CustomMarshal.Alloc(typeof(PixelValue));
|
|
|
|
bool success = ReplayRenderer_GetMinMax(m_Real, tex, sliceFace, mip, sample, mem1, mem2);
|
|
|
|
if (success)
|
|
{
|
|
minval = (PixelValue)CustomMarshal.PtrToStructure(mem1, typeof(PixelValue), true);
|
|
maxval = (PixelValue)CustomMarshal.PtrToStructure(mem2, typeof(PixelValue), true);
|
|
}
|
|
else
|
|
{
|
|
minval = null;
|
|
maxval = null;
|
|
}
|
|
|
|
CustomMarshal.Free(mem1);
|
|
CustomMarshal.Free(mem2);
|
|
|
|
return success;
|
|
}
|
|
|
|
public bool GetHistogram(ResourceId tex, UInt32 sliceFace, UInt32 mip, UInt32 sample, float minval, float maxval,
|
|
bool Red, bool Green, bool Blue, bool Alpha,
|
|
out UInt32[] histogram)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool[] channels = new bool[] { Red, Green, Blue, Alpha };
|
|
|
|
bool success = ReplayRenderer_GetHistogram(m_Real, tex, sliceFace, mip, sample, minval, maxval, channels, mem);
|
|
|
|
histogram = null;
|
|
|
|
if (success)
|
|
histogram = (UInt32[])CustomMarshal.GetTemplatedArray(mem, typeof(UInt32), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return success;
|
|
}
|
|
|
|
public byte[] GetBufferData(ResourceId buff, UInt32 offset, UInt32 len)
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
|
|
bool success = ReplayRenderer_GetBufferData(m_Real, buff, offset, len, mem);
|
|
|
|
byte[] ret = null;
|
|
|
|
if (success)
|
|
ret = (byte[])CustomMarshal.GetTemplatedArray(mem, typeof(byte), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
public class RemoteRenderer
|
|
{
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RemoteRenderer_Shutdown(IntPtr real);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool RemoteRenderer_LocalProxies(IntPtr real, IntPtr outlist);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern bool RemoteRenderer_RemoteSupportedReplays(IntPtr real, IntPtr outlist);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern ReplayCreateStatus RemoteRenderer_CreateProxyRenderer(IntPtr real, UInt32 proxyid, string logfile, ref float progress, ref IntPtr rendPtr);
|
|
|
|
private IntPtr m_Real = IntPtr.Zero;
|
|
|
|
public RemoteRenderer(IntPtr real) { m_Real = real; }
|
|
|
|
public void Shutdown()
|
|
{
|
|
if (m_Real != IntPtr.Zero)
|
|
{
|
|
RemoteRenderer_Shutdown(m_Real);
|
|
m_Real = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
public string[] LocalProxies()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
bool success = RemoteRenderer_LocalProxies(m_Real, mem);
|
|
|
|
string[] ret = null;
|
|
|
|
if (success)
|
|
ret = CustomMarshal.TemplatedArrayToUniStringArray(mem, true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public string[] RemoteSupportedReplays()
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(templated_array));
|
|
bool success = RemoteRenderer_RemoteSupportedReplays(m_Real, mem);
|
|
|
|
string[] ret = null;
|
|
|
|
if (success)
|
|
ret = CustomMarshal.TemplatedArrayToUniStringArray(mem, true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public ReplayRenderer CreateProxyRenderer(int proxyid, string logfile, ref float progress)
|
|
{
|
|
IntPtr rendPtr = IntPtr.Zero;
|
|
|
|
ReplayCreateStatus ret = RemoteRenderer_CreateProxyRenderer(m_Real, (UInt32)proxyid, logfile, ref progress, ref rendPtr);
|
|
|
|
if (rendPtr == IntPtr.Zero || ret != ReplayCreateStatus.Success)
|
|
{
|
|
var e = new System.ApplicationException("Failed to set up local proxy replay with remote connection");
|
|
e.Data.Add("status", ret);
|
|
throw e;
|
|
}
|
|
|
|
return new ReplayRenderer(rendPtr);
|
|
}
|
|
};
|
|
|
|
public class RemoteAccess
|
|
{
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RemoteAccess_Shutdown(IntPtr real);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr RemoteAccess_GetTarget(IntPtr real);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr RemoteAccess_GetAPI(IntPtr real);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern IntPtr RemoteAccess_GetBusyClient(IntPtr real);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RemoteAccess_TriggerCapture(IntPtr real);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RemoteAccess_QueueCapture(IntPtr real, UInt32 frameNumber);
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RemoteAccess_CopyCapture(IntPtr real, UInt32 remoteID, string localpath);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern void RemoteAccess_ReceiveMessage(IntPtr real, IntPtr outmsg);
|
|
|
|
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
|
|
private static extern UInt32 RENDERDOC_EnumerateRemoteConnections(string host, UInt32[] idents);
|
|
|
|
private IntPtr m_Real = IntPtr.Zero;
|
|
private bool m_Connected;
|
|
|
|
public RemoteAccess(IntPtr real)
|
|
{
|
|
m_Real = real;
|
|
|
|
if (real == IntPtr.Zero)
|
|
{
|
|
m_Connected = false;
|
|
Target = "";
|
|
API = "";
|
|
BusyClient = "";
|
|
}
|
|
else
|
|
{
|
|
m_Connected = true;
|
|
Target = Marshal.PtrToStringUni(RemoteAccess_GetTarget(m_Real));
|
|
API = Marshal.PtrToStringUni(RemoteAccess_GetAPI(m_Real));
|
|
BusyClient = Marshal.PtrToStringUni(RemoteAccess_GetBusyClient(m_Real));
|
|
}
|
|
|
|
CaptureExists = false;
|
|
CaptureCopied = false;
|
|
InfoUpdated = false;
|
|
}
|
|
|
|
public static UInt32[] GetRemoteIdents(string host)
|
|
{
|
|
UInt32 numIdents = RENDERDOC_EnumerateRemoteConnections("", null);
|
|
|
|
UInt32[] idents = new UInt32[numIdents];
|
|
|
|
RENDERDOC_EnumerateRemoteConnections(host, idents);
|
|
|
|
return idents;
|
|
}
|
|
|
|
public bool Connected { get { return m_Connected; } }
|
|
|
|
public void Shutdown()
|
|
{
|
|
m_Connected = false;
|
|
if (m_Real != IntPtr.Zero) RemoteAccess_Shutdown(m_Real);
|
|
m_Real = IntPtr.Zero;
|
|
}
|
|
|
|
public void TriggerCapture()
|
|
{
|
|
RemoteAccess_TriggerCapture(m_Real);
|
|
}
|
|
|
|
public void QueueCapture(UInt32 frameNum)
|
|
{
|
|
RemoteAccess_QueueCapture(m_Real, frameNum);
|
|
}
|
|
|
|
public void CopyCapture(UInt32 id, string localpath)
|
|
{
|
|
RemoteAccess_CopyCapture(m_Real, id, localpath);
|
|
}
|
|
|
|
public void ReceiveMessage()
|
|
{
|
|
if (m_Real != IntPtr.Zero)
|
|
{
|
|
RemoteMessage msg = null;
|
|
|
|
{
|
|
IntPtr mem = CustomMarshal.Alloc(typeof(RemoteMessage));
|
|
|
|
RemoteAccess_ReceiveMessage(m_Real, mem);
|
|
|
|
if (mem != IntPtr.Zero)
|
|
msg = (RemoteMessage)CustomMarshal.PtrToStructure(mem, typeof(RemoteMessage), true);
|
|
|
|
CustomMarshal.Free(mem);
|
|
}
|
|
|
|
if (msg.Type == RemoteMessageType.Disconnected)
|
|
{
|
|
m_Connected = false;
|
|
RemoteAccess_Shutdown(m_Real);
|
|
m_Real = IntPtr.Zero;
|
|
}
|
|
else if (msg.Type == RemoteMessageType.NewCapture)
|
|
{
|
|
CaptureFile.ID = msg.NewCapture.ID;
|
|
CaptureFile.timestamp = msg.NewCapture.timestamp;
|
|
CaptureFile.localpath = msg.NewCapture.localpath;
|
|
CaptureFile.thumbnail = msg.NewCapture.thumbnail;
|
|
|
|
CaptureExists = true;
|
|
}
|
|
else if (msg.Type == RemoteMessageType.CaptureCopied)
|
|
{
|
|
CaptureFile.ID = msg.NewCapture.ID;
|
|
CaptureFile.localpath = msg.NewCapture.localpath;
|
|
CaptureCopied = true;
|
|
}
|
|
else if (msg.Type == RemoteMessageType.RegisterAPI)
|
|
{
|
|
API = msg.RegisterAPI.APIName;
|
|
InfoUpdated = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public string BusyClient;
|
|
public string Target;
|
|
public string API;
|
|
|
|
public bool CaptureExists;
|
|
public bool CaptureCopied;
|
|
public bool InfoUpdated;
|
|
|
|
public struct CaptureInfo
|
|
{
|
|
public UInt32 ID;
|
|
public UInt64 timestamp;
|
|
public byte[] thumbnail;
|
|
public string localpath;
|
|
};
|
|
public CaptureInfo CaptureFile = new CaptureInfo();
|
|
};
|
|
};
|