diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 1892c526a..2f706848e 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -179,6 +179,7 @@ struct IReplayRenderer virtual bool SetFrameEvent(uint32_t frameID, uint32_t eventID) = 0; virtual bool GetD3D11PipelineState(D3D11PipelineState *state) = 0; virtual bool GetGLPipelineState(GLPipelineState *state) = 0; + virtual bool GetVulkanPipelineState(VulkanPipelineState *state) = 0; virtual ResourceId BuildCustomShader(const char *entry, const char *source, const uint32_t compileFlags, ShaderStageType type, rdctype::str *errors) = 0; virtual bool FreeCustomShader(ResourceId id) = 0; @@ -246,6 +247,7 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_SetContextFilter(Rep extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_SetFrameEvent(ReplayRenderer *rend, uint32_t frameID, uint32_t eventID); extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetD3D11PipelineState(ReplayRenderer *rend, D3D11PipelineState *state); extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetGLPipelineState(ReplayRenderer *rend, GLPipelineState *state); +extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetVulkanPipelineState(ReplayRenderer *rend, VulkanPipelineState *state); extern "C" RENDERDOC_API void RENDERDOC_CC ReplayRenderer_BuildCustomShader(ReplayRenderer *rend, const char *entry, const char *source, const uint32_t compileFlags, ShaderStageType type, ResourceId *shaderID, rdctype::str *errors); extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_FreeCustomShader(ReplayRenderer *rend, ResourceId id); diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 52d4a2962..6b1969773 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -211,6 +211,7 @@ enum APIPipelineStateType { ePipelineState_D3D11, ePipelineState_OpenGL, + ePipelineState_Vulkan, }; enum PrimitiveTopology diff --git a/renderdoc/api/replay/vk_pipestate.h b/renderdoc/api/replay/vk_pipestate.h index e17d2a9ee..2d438816c 100644 --- a/renderdoc/api/replay/vk_pipestate.h +++ b/renderdoc/api/replay/vk_pipestate.h @@ -36,6 +36,7 @@ struct VulkanPipelineState struct DescriptorSet { ResourceId layout; + ResourceId descset; struct DescriptorBinding { @@ -53,7 +54,7 @@ struct VulkanPipelineState }; // may only be one element if not an array - rdctype::array elems; + rdctype::array binds; }; rdctype::array bindings; }; @@ -221,12 +222,12 @@ struct VulkanPipelineState bool32 stencilTestEnable; struct StencilOp { - StencilOp() : ref(0) {} + StencilOp() : stencilref(0) {} rdctype::str failOp; rdctype::str depthFailOp; rdctype::str passOp; rdctype::str func; - uint32_t ref; + uint32_t stencilref; } front, back; ResourceId state; @@ -240,6 +241,10 @@ struct VulkanPipelineState { ResourceId obj; // VKTODOMED renderpass and subpass information here + + rdctype::array inputAttachments; + rdctype::array colorAttachments; + int32_t depthstencilAttachment; } renderpass; struct Framebuffer diff --git a/renderdoc/core/image_viewer.cpp b/renderdoc/core/image_viewer.cpp index 0ea5625a1..bffc311b1 100644 --- a/renderdoc/core/image_viewer.cpp +++ b/renderdoc/core/image_viewer.cpp @@ -117,6 +117,7 @@ class ImageViewer : public IReplayDriver FetchBuffer GetBuffer(ResourceId id) { FetchBuffer ret; RDCEraseEl(ret); return ret; } void SavePipelineState() {} GLPipelineState GetGLPipelineState() { return GLPipelineState(); } + VulkanPipelineState GetVulkanPipelineState() { return VulkanPipelineState(); } void SetContextFilter(ResourceId id, uint32_t firstDefEv, uint32_t lastDefEv) {} void ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType) {} vector GetUsage(ResourceId id) { return vector(); } diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index cd0488dcb..fe1789c94 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -1193,6 +1193,8 @@ bool ProxySerialiser::Tick() bool ProxySerialiser::IsRenderOutput(ResourceId id) { + // TODO this should go remote + for(int32_t i=0; i < m_D3D11PipelineState.m_OM.RenderTargets.count; i++) { if(m_D3D11PipelineState.m_OM.RenderTargets[i].View == id || @@ -1339,6 +1341,7 @@ void ProxySerialiser::SavePipelineState() m_Remote->SavePipelineState(); m_D3D11PipelineState = m_Remote->GetD3D11PipelineState(); m_GLPipelineState = m_Remote->GetGLPipelineState(); + m_VulkanPipelineState = m_Remote->GetVulkanPipelineState(); } else { @@ -1347,10 +1350,13 @@ void ProxySerialiser::SavePipelineState() m_D3D11PipelineState = D3D11PipelineState(); m_GLPipelineState = GLPipelineState(); + m_VulkanPipelineState = VulkanPipelineState(); } m_FromReplaySerialiser->Serialise("", m_D3D11PipelineState); m_FromReplaySerialiser->Serialise("", m_GLPipelineState); + // VKTODOLOW - serialise pipe state + //m_FromReplaySerialiser->Serialise("", m_VulkanPipelineState); } void ProxySerialiser::SetContextFilter(ResourceId id, uint32_t firstDefEv, uint32_t lastDefEv) diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index cb2c76c84..c542624d2 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -329,6 +329,7 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver void SavePipelineState(); D3D11PipelineState GetD3D11PipelineState() { return m_D3D11PipelineState; } GLPipelineState GetGLPipelineState() { return m_GLPipelineState; } + VulkanPipelineState GetVulkanPipelineState() { return m_VulkanPipelineState; } void SetContextFilter(ResourceId id, uint32_t firstDefEv, uint32_t lastDefEv); void ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType); @@ -442,4 +443,5 @@ class ProxySerialiser : public IReplayDriver, Callstack::StackResolver APIProperties m_APIProperties; D3D11PipelineState m_D3D11PipelineState; GLPipelineState m_GLPipelineState; + VulkanPipelineState m_VulkanPipelineState; }; diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index 3ae3ccc36..6ab94e50c 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -62,6 +62,7 @@ class D3D11Replay : public IReplayDriver void SavePipelineState() { m_CurPipelineState = MakePipelineState(); } D3D11PipelineState GetD3D11PipelineState() { return m_CurPipelineState; } GLPipelineState GetGLPipelineState() { return GLPipelineState(); } + VulkanPipelineState GetVulkanPipelineState() { return VulkanPipelineState(); } void FreeTargetResource(ResourceId id); void FreeCustomShader(ResourceId id); diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 4fe524858..55398ba48 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -109,6 +109,7 @@ class GLReplay : public IReplayDriver void SavePipelineState(); D3D11PipelineState GetD3D11PipelineState() { return D3D11PipelineState(); } GLPipelineState GetGLPipelineState() { return m_CurPipelineState; } + VulkanPipelineState GetVulkanPipelineState() { return VulkanPipelineState(); } void FreeTargetResource(ResourceId id); diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index 8e6d322e8..f4c0f4d51 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -146,6 +146,24 @@ void VulkanCreationInfo::DepthStencil::Init(const VkDynamicDepthStencilStateCrea stencilBackRef = pCreateInfo->stencilBackRef; } +void VulkanCreationInfo::RenderPass::Init(const VkRenderPassCreateInfo* pCreateInfo) +{ + // VKTODOMED figure out how subpasses work + RDCASSERT(pCreateInfo->subpassCount > 0); + const VkSubpassDescription &subp = pCreateInfo->pSubpasses[0]; + + inputAttachments.resize(subp.inputCount); + for(uint32_t i=0; i < subp.inputCount; i++) + inputAttachments[i] = subp.inputAttachments[i].attachment; + + colorAttachments.resize(subp.colorCount); + for(uint32_t i=0; i < subp.colorCount; i++) + colorAttachments[i] = subp.colorAttachments[i].attachment; + + depthstencilAttachment = (subp.depthStencilAttachment.attachment == VK_ATTACHMENT_UNUSED + ? (int32_t)subp.depthStencilAttachment.attachment : -1); +} + void VulkanCreationInfo::Framebuffer::Init(const VkFramebufferCreateInfo* pCreateInfo) { width = pCreateInfo->width; diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 500cfccfe..747a3a46a 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -151,6 +151,16 @@ struct VulkanCreationInfo uint32_t stencilBackRef; }; map m_DepthStencil; + + struct RenderPass + { + void Init(const VkRenderPassCreateInfo* pCreateInfo); + + vector inputAttachments; + vector colorAttachments; + int32_t depthstencilAttachment; + }; + map m_RenderPass; struct Framebuffer { diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 008c92c1b..219dbc5e5 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -428,7 +428,7 @@ APIProperties VulkanReplay::GetAPIProperties() { APIProperties ret; - ret.pipelineType = ePipelineState_D3D11; + ret.pipelineType = ePipelineState_Vulkan; ret.degraded = false; return ret; @@ -1197,7 +1197,7 @@ FetchBuffer VulkanReplay::GetBuffer(ResourceId id) ShaderReflection *VulkanReplay::GetShader(ResourceId id) { - RDCUNIMPLEMENTED("GetShader"); + VULKANNOTIMP("GetShader"); return NULL; } @@ -1297,6 +1297,7 @@ void VulkanReplay::SavePipelineState() ResourceId src = (*srcs[p])[i]; VulkanPipelineState::Pipeline::DescriptorSet &dst = (*dsts[p])[i]; + dst.descset = src; dst.layout = m_pDriver->m_DescriptorSetInfo[src].layout; create_array_uninit(dst.bindings, m_pDriver->m_DescriptorSetInfo[src].currentBindings.size()); for(size_t b=0; b < m_pDriver->m_DescriptorSetInfo[src].currentBindings.size(); b++) @@ -1324,21 +1325,21 @@ void VulkanReplay::SavePipelineState() RDCERR("Unexpected descriptor type"); } - create_array_uninit(dst.bindings[b].elems, layoutBind.arraySize); + create_array_uninit(dst.bindings[b].binds, layoutBind.arraySize); for(uint32_t a=0; a < layoutBind.arraySize; a++) { if(layoutBind.immutableSampler) - dst.bindings[b].elems[a].sampler = layoutBind.immutableSampler[a]; + dst.bindings[b].binds[a].sampler = layoutBind.immutableSampler[a]; else if(info->sampler != VK_NULL_HANDLE) - dst.bindings[b].elems[a].sampler = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->sampler)->id); + dst.bindings[b].binds[a].sampler = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->sampler)->id); // only one of these is ever set if(info->imageView != VK_NULL_HANDLE) - dst.bindings[b].elems[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->imageView)->id); + dst.bindings[b].binds[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->imageView)->id); if(info->bufferView != VK_NULL_HANDLE) - dst.bindings[b].elems[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->bufferView)->id); + dst.bindings[b].binds[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->bufferView)->id); if(info->attachmentView != VK_NULL_HANDLE) - dst.bindings[b].elems[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->attachmentView)->id); + dst.bindings[b].binds[a].view = rm->GetOriginalID(VKMGR()->GetNonDispWrapper(info->attachmentView)->id); } } } @@ -1451,14 +1452,18 @@ void VulkanReplay::SavePipelineState() m_VulkanPipelineState.DS.minDepthBounds = c.m_DepthStencil[state.dynamicDS].minDepthBounds; m_VulkanPipelineState.DS.maxDepthBounds = c.m_DepthStencil[state.dynamicDS].maxDepthBounds; - m_VulkanPipelineState.DS.front.ref = c.m_DepthStencil[state.dynamicDS].stencilFrontRef; - m_VulkanPipelineState.DS.back.ref = c.m_DepthStencil[state.dynamicDS].stencilBackRef; + m_VulkanPipelineState.DS.front.stencilref = c.m_DepthStencil[state.dynamicDS].stencilFrontRef; + m_VulkanPipelineState.DS.back.stencilref = c.m_DepthStencil[state.dynamicDS].stencilBackRef; m_VulkanPipelineState.DS.stencilReadMask = c.m_DepthStencil[state.dynamicDS].stencilReadMask; m_VulkanPipelineState.DS.stencilWriteMask = c.m_DepthStencil[state.dynamicDS].stencilWriteMask; // Renderpass m_VulkanPipelineState.Pass.renderpass.obj = state.renderPass; + m_VulkanPipelineState.Pass.renderpass.inputAttachments = c.m_RenderPass[state.renderPass].inputAttachments; + m_VulkanPipelineState.Pass.renderpass.colorAttachments = c.m_RenderPass[state.renderPass].colorAttachments; + m_VulkanPipelineState.Pass.renderpass.depthstencilAttachment = c.m_RenderPass[state.renderPass].depthstencilAttachment; + m_VulkanPipelineState.Pass.framebuffer.obj = state.framebuffer; m_VulkanPipelineState.Pass.framebuffer.width = c.m_Framebuffer[state.framebuffer].width; diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index 2eebb1bdb..2e8afc070 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -546,6 +546,9 @@ bool WrappedVulkan::Serialise_vkCreateRenderPass( { device = GetResourceManager()->GetLiveHandle(devId); VkRenderPass rp = VK_NULL_HANDLE; + + // use original ID + m_CreationInfo.m_RenderPass[id].Init(&info); VkResult ret = ObjDisp(device)->CreateRenderPass(Unwrap(device), &info, &rp); diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index 2a8d9de96..404ffd621 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -69,6 +69,7 @@ class IRemoteDriver virtual void SavePipelineState() = 0; virtual D3D11PipelineState GetD3D11PipelineState() = 0; virtual GLPipelineState GetGLPipelineState() = 0; + virtual VulkanPipelineState GetVulkanPipelineState() = 0; virtual vector GetFrameRecord() = 0; diff --git a/renderdoc/replay/replay_renderer.cpp b/renderdoc/replay/replay_renderer.cpp index 383feff26..4b3495a24 100644 --- a/renderdoc/replay/replay_renderer.cpp +++ b/renderdoc/replay/replay_renderer.cpp @@ -232,6 +232,17 @@ bool ReplayRenderer::GetGLPipelineState(GLPipelineState *state) return false; } +bool ReplayRenderer::GetVulkanPipelineState(VulkanPipelineState *state) +{ + if(state) + { + *state = m_VulkanPipelineState; + return true; + } + + return false; +} + bool ReplayRenderer::GetFrameInfo(rdctype::array *arr) { if(arr == NULL) return false; @@ -1546,6 +1557,7 @@ void ReplayRenderer::FetchPipelineState() m_D3D11PipelineState = m_pDevice->GetD3D11PipelineState(); m_GLPipelineState = m_pDevice->GetGLPipelineState(); + m_VulkanPipelineState = m_pDevice->GetVulkanPipelineState(); { D3D11PipelineState::ShaderStage *stage = &m_D3D11PipelineState.m_VS; @@ -1560,6 +1572,13 @@ void ReplayRenderer::FetchPipelineState() if(stage[i].Shader != ResourceId()) stage[i].ShaderDetails = m_pDevice->GetShader(m_pDevice->GetLiveID(stage[i].Shader)); } + + { + VulkanPipelineState::ShaderStage *stage = &m_VulkanPipelineState.VS; + for(int i=0; i < 6; i++) + if(stage[i].Shader != ResourceId()) + stage[i].ShaderDetails = m_pDevice->GetShader(m_pDevice->GetLiveID(stage[i].Shader)); + } } extern "C" RENDERDOC_API void RENDERDOC_CC ReplayRenderer_GetAPIProperties(ReplayRenderer *rend, APIProperties *props) @@ -1588,6 +1607,8 @@ extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetD3D11PipelineStat { return rend->GetD3D11PipelineState(state); } extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetGLPipelineState(ReplayRenderer *rend, GLPipelineState *state) { return rend->GetGLPipelineState(state); } +extern "C" RENDERDOC_API bool32 RENDERDOC_CC ReplayRenderer_GetVulkanPipelineState(ReplayRenderer *rend, VulkanPipelineState *state) +{ return rend->GetVulkanPipelineState(state); } extern "C" RENDERDOC_API void RENDERDOC_CC ReplayRenderer_BuildCustomShader(ReplayRenderer *rend, const char *entry, const char *source, const uint32_t compileFlags, ShaderStageType type, ResourceId *shaderID, rdctype::str *errors) { diff --git a/renderdoc/replay/replay_renderer.h b/renderdoc/replay/replay_renderer.h index 388cdba99..8780cfa78 100644 --- a/renderdoc/replay/replay_renderer.h +++ b/renderdoc/replay/replay_renderer.h @@ -150,6 +150,7 @@ struct ReplayRenderer : public IReplayRenderer bool GetD3D11PipelineState(D3D11PipelineState *state); bool GetGLPipelineState(GLPipelineState *state); + bool GetVulkanPipelineState(VulkanPipelineState *state); ResourceId BuildCustomShader(const char *entry, const char *source, const uint32_t compileFlags, ShaderStageType type, rdctype::str *errors); bool FreeCustomShader(ResourceId id); @@ -218,6 +219,7 @@ struct ReplayRenderer : public IReplayRenderer D3D11PipelineState m_D3D11PipelineState; GLPipelineState m_GLPipelineState; + VulkanPipelineState m_VulkanPipelineState; std::vector m_Outputs; diff --git a/renderdocui/Code/CommonPipelineState.cs b/renderdocui/Code/CommonPipelineState.cs index e7cb2cff9..84848e845 100644 --- a/renderdocui/Code/CommonPipelineState.cs +++ b/renderdocui/Code/CommonPipelineState.cs @@ -34,24 +34,26 @@ namespace renderdocui.Code { private D3D11PipelineState m_D3D11 = null; private GLPipelineState m_GL = null; + private VulkanPipelineState m_VK = null; private APIProperties m_APIProps = null; public CommonPipelineState() { } - public void SetStates(APIProperties props, D3D11PipelineState d3d11, GLPipelineState gl) + public void SetStates(APIProperties props, D3D11PipelineState d3d11, GLPipelineState gl, VulkanPipelineState vk) { m_APIProps = props; m_D3D11 = d3d11; m_GL = gl; + m_VK = vk; } private bool LogLoaded { get { - return m_D3D11 != null || m_GL != null; + return m_D3D11 != null || m_GL != null || m_VK != null; } } @@ -71,6 +73,14 @@ namespace renderdocui.Code } } + private bool IsLogVK + { + get + { + return LogLoaded && m_APIProps.pipelineType == APIPipelineStateType.Vulkan && m_VK != null; + } + } + // add a bunch of generic properties that people can check to save having to see which pipeline state // is valid and look at the appropriate part of it public bool IsTessellationEnabled @@ -84,6 +94,9 @@ namespace renderdocui.Code if (IsLogGL) return m_GL != null && m_GL.m_TES.Shader != ResourceId.Null; + + if (IsLogVK) + return m_VK != null && m_VK.TES.Shader != ResourceId.Null; } return false; @@ -120,6 +133,18 @@ namespace renderdocui.Code case ShaderStageType.Compute: return m_GL.m_CS.BindpointMapping; } } + else if (IsLogVK) + { + switch (stage) + { + case ShaderStageType.Vertex: return m_VK.VS.BindpointMapping; + case ShaderStageType.Tess_Control: return m_VK.TCS.BindpointMapping; + case ShaderStageType.Tess_Eval: return m_VK.TES.BindpointMapping; + case ShaderStageType.Geometry: return m_VK.GS.BindpointMapping; + case ShaderStageType.Fragment: return m_VK.FS.BindpointMapping; + case ShaderStageType.Compute: return m_VK.CS.BindpointMapping; + } + } } return null; @@ -153,6 +178,18 @@ namespace renderdocui.Code case ShaderStageType.Compute: return m_GL.m_CS.ShaderDetails; } } + else if (IsLogVK) + { + switch (stage) + { + case ShaderStageType.Vertex: return m_VK.VS.ShaderDetails; + case ShaderStageType.Tess_Control: return m_VK.TCS.ShaderDetails; + case ShaderStageType.Tess_Eval: return m_VK.TES.ShaderDetails; + case ShaderStageType.Geometry: return m_VK.GS.ShaderDetails; + case ShaderStageType.Fragment: return m_VK.FS.ShaderDetails; + case ShaderStageType.Compute: return m_VK.CS.ShaderDetails; + } + } } return null; @@ -186,6 +223,18 @@ namespace renderdocui.Code case ShaderStageType.Compute: return m_GL.m_CS.Shader; } } + else if (IsLogVK) + { + switch (stage) + { + case ShaderStageType.Vertex: return m_VK.VS.Shader; + case ShaderStageType.Tess_Control: return m_VK.TCS.Shader; + case ShaderStageType.Tess_Eval: return m_VK.TES.Shader; + case ShaderStageType.Geometry: return m_VK.GS.Shader; + case ShaderStageType.Fragment: return m_VK.FS.Shader; + case ShaderStageType.Compute: return m_VK.CS.Shader; + } + } } return ResourceId.Null; @@ -219,6 +268,18 @@ namespace renderdocui.Code case ShaderStageType.Compute: return String.Format("Shader {0}", m_GL.m_CS.Shader); } } + else if (IsLogVK) + { + switch (stage) + { + case ShaderStageType.Vertex: return m_VK.VS.ShaderName; + case ShaderStageType.Domain: return m_VK.TCS.ShaderName; + case ShaderStageType.Hull: return m_VK.TES.ShaderName; + case ShaderStageType.Geometry: return m_VK.GS.ShaderName; + case ShaderStageType.Pixel: return m_VK.FS.ShaderName; + case ShaderStageType.Compute: return m_VK.CS.ShaderName; + } + } } return ""; @@ -240,6 +301,14 @@ namespace renderdocui.Code buf = m_GL.m_VtxIn.ibuffer; ByteOffset = 0; // GL only has per-draw index offset + return; + } + else if (IsLogVK) + { + buf = m_VK.IA.ibuffer.buf; + // VKTODOLOW maybe increase parameter to ulong and upcast others? + ByteOffset = (uint)m_VK.IA.ibuffer.offs; + return; } } @@ -261,6 +330,10 @@ namespace renderdocui.Code { return m_GL.m_VtxIn.primitiveRestart; } + else if (IsLogVK) + { + return m_VK.IA.primitiveRestartEnable; + } } return false; @@ -270,9 +343,9 @@ namespace renderdocui.Code { if (LogLoaded) { - if (IsLogD3D11) + if (IsLogD3D11 || IsLogVK) { - // D3D11 this is always '-1' in whichever size of index we're using + // D3D11 or Vulkan this is always '-1' in whichever size of index we're using return indexByteWidth == 2 ? ushort.MaxValue : uint.MaxValue; } else if (IsLogGL) @@ -322,6 +395,19 @@ namespace renderdocui.Code ret[i].ByteStride = m_GL.m_VtxIn.vbuffers[i].Stride; } + return ret; + } + else if (IsLogVK) + { + VBuffer[] ret = new VBuffer[m_VK.VI.binds.Length]; + for (int i = 0; i < m_VK.VI.binds.Length; i++) + { + ret[i].Buffer = m_VK.VI.vbuffers[i].buffer; + // VKTODOLOW maybe increase parameter to ulong and upcast others? + ret[i].ByteOffset = (uint)m_VK.VI.vbuffers[i].offset; + ret[i].ByteStride = m_VK.VI.binds[i].bytestride; + } + return ret; } } @@ -468,6 +554,42 @@ namespace renderdocui.Code a++; } + return ret; + } + else if (IsLogVK) + { + var attrs = m_VK.VI.attrs; + + int num = 0; + for (int i = 0; i < attrs.Length; i++) + { + int attrib = -1; + if (m_VK.VS.BindpointMapping != null && m_VK.VS.ShaderDetails != null) + attrib = m_VK.VS.BindpointMapping.InputAttributes[i]; + else + attrib = i; + + if (attrib >= 0) + num++; + } + + int a = 0; + VertexInputAttribute[] ret = new VertexInputAttribute[num]; + for (int i = 0; i < attrs.Length && a < num; i++) + { + ret[a].Name = String.Format("attr{0}", i); + ret[a].GenericValue = null; + ret[a].VertexBuffer = (int)attrs[i].binding; + ret[a].RelativeByteOffset = attrs[i].byteoffset; + ret[a].PerInstance = m_VK.VI.binds[attrs[i].binding].perInstance; + ret[a].InstanceRate = 1; + ret[a].Format = attrs[i].format; + ret[a].Used = true; + + // VKTODOMED use shader reflection & attrs[i].location to get better name + a++; + } + return ret; } } @@ -622,6 +744,10 @@ namespace renderdocui.Code return m_D3D11.m_OM.DepthTarget.Resource; else if (IsLogGL) return m_GL.m_FB.m_DrawFBO.Depth.Obj; + else if (IsLogVK) + return m_VK.Pass.renderpass.depthstencilAttachment >= 0 + ? m_VK.Pass.framebuffer.attachments[m_VK.Pass.renderpass.depthstencilAttachment].img + : ResourceId.Null; } return ResourceId.Null; @@ -635,6 +761,10 @@ namespace renderdocui.Code return m_D3D11.m_OM.DepthTarget.Resource; else if (IsLogGL) return m_GL.m_FB.m_DrawFBO.Stencil.Obj; + else if (IsLogVK) + return m_VK.Pass.renderpass.depthstencilAttachment >= 0 + ? m_VK.Pass.framebuffer.attachments[m_VK.Pass.renderpass.depthstencilAttachment].img + : ResourceId.Null; } return ResourceId.Null; @@ -662,6 +792,14 @@ namespace renderdocui.Code ret[i] = m_GL.m_FB.m_DrawFBO.Color[db].Obj; } + return ret; + } + else if (IsLogVK) + { + ResourceId[] ret = new ResourceId[m_VK.Pass.renderpass.colorAttachments.Length]; + for (int i = 0; i < m_VK.Pass.renderpass.colorAttachments.Length; i++) + ret[i] = m_VK.Pass.framebuffer.attachments[m_VK.Pass.renderpass.colorAttachments[i]].img; + return ret; } } @@ -669,40 +807,6 @@ namespace renderdocui.Code return new ResourceId[0]; } - public ResourceId OutputDepth - { - get - { - if (LogLoaded) - { - if (IsLogD3D11) - return m_D3D11.m_OM.DepthTarget.Resource; - - if (IsLogGL) - return m_GL.m_FB.m_DrawFBO.Depth.Obj; - } - - return ResourceId.Null; - } - } - - public ResourceId OutputStencil - { - get - { - if (LogLoaded) - { - if (IsLogD3D11) - return m_D3D11.m_OM.DepthTarget.Resource; - - if (IsLogGL) - return m_GL.m_FB.m_DrawFBO.Stencil.Obj; - } - - return ResourceId.Null; - } - } - // Still to add: // [ShaderViewer] * {FetchTexture,FetchBuffer} GetFetchBufferOrFetchTexture(ShaderResource) } diff --git a/renderdocui/Code/Core.cs b/renderdocui/Code/Core.cs index ded2d658b..b56af143e 100644 --- a/renderdocui/Code/Core.cs +++ b/renderdocui/Code/Core.cs @@ -75,6 +75,7 @@ namespace renderdocui.Code private D3D11PipelineState m_D3D11PipelineState = null; private GLPipelineState m_GLPipelineState = null; + private VulkanPipelineState m_VulkanPipelineState = null; private CommonPipelineState m_PipelineState = new CommonPipelineState(); private List m_LogViewers = new List(); @@ -151,6 +152,7 @@ namespace renderdocui.Code // direct access (note that only one of these will be valid for a log, check APIProps.pipelineType) public D3D11PipelineState CurD3D11PipelineState { get { return m_D3D11PipelineState; } } public GLPipelineState CurGLPipelineState { get { return m_GLPipelineState; } } + public VulkanPipelineState CurVulkanPipelineState { get { return m_VulkanPipelineState; } } public CommonPipelineState CurPipelineState { get { return m_PipelineState; } } #endregion @@ -504,7 +506,8 @@ namespace renderdocui.Code m_D3D11PipelineState = r.GetD3D11PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); - m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState); + m_VulkanPipelineState = r.GetVulkanPipelineState(); + m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState, m_VulkanPipelineState); UnreadMessageCount = 0; AddMessages(m_FrameInfo[0].debugMessages); @@ -603,7 +606,8 @@ namespace renderdocui.Code m_D3D11PipelineState = null; m_GLPipelineState = null; - m_PipelineState.SetStates(null, null, null); + m_VulkanPipelineState = null; + m_PipelineState.SetStates(null, null, null, null); DebugMessages.Clear(); UnreadMessageCount = 0; @@ -812,7 +816,8 @@ namespace renderdocui.Code r.SetFrameEvent(m_FrameID, m_EventID); m_D3D11PipelineState = r.GetD3D11PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); - m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState); + m_VulkanPipelineState = r.GetVulkanPipelineState(); + m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState, m_VulkanPipelineState); }); foreach (var logviewer in m_LogViewers) @@ -841,7 +846,8 @@ namespace renderdocui.Code r.SetFrameEvent(m_FrameID, m_EventID); m_D3D11PipelineState = r.GetD3D11PipelineState(); m_GLPipelineState = r.GetGLPipelineState(); - m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState); + m_VulkanPipelineState = r.GetVulkanPipelineState(); + m_PipelineState.SetStates(m_APIProperties, m_D3D11PipelineState, m_GLPipelineState, m_VulkanPipelineState); }); foreach (var logviewer in m_LogViewers) diff --git a/renderdocui/Interop/Enums.cs b/renderdocui/Interop/Enums.cs index 34e659d02..6ee41f09a 100644 --- a/renderdocui/Interop/Enums.cs +++ b/renderdocui/Interop/Enums.cs @@ -74,6 +74,20 @@ namespace renderdoc TextureCubeArray, }; + public enum ShaderBindType + { + Unknown = 0, + Sampler, + ImageSampler, + ReadOnlyImage, + ReadWriteImage, + ReadOnlyTBuffer, + ReadWriteTBuffer, + ReadOnlyBuffer, + ReadWriteBuffer, + InputAttachment, + }; + public enum SystemAttribute { None = 0, @@ -190,6 +204,7 @@ namespace renderdoc { D3D11, OpenGL, + Vulkan, }; public enum PrimitiveTopology @@ -279,6 +294,20 @@ namespace renderdoc Compute, }; + [Flags] + public enum ShaderStageBits + { + Vertex = (1 << ShaderStageType.Vertex), + Hull = (1 << ShaderStageType.Hull), + Tess_Control = (1 << ShaderStageType.Tess_Control), + Domain = (1 << ShaderStageType.Domain), + Tess_Eval = (1 << ShaderStageType.Tess_Eval), + Geometry = (1 << ShaderStageType.Geometry), + Pixel = (1 << ShaderStageType.Pixel), + Fragment = (1 << ShaderStageType.Fragment), + Compute = (1 << ShaderStageType.Compute), + }; + public enum DebugMessageSource { API = 0, diff --git a/renderdocui/Interop/ReplayRenderer.cs b/renderdocui/Interop/ReplayRenderer.cs index 0297e7e6f..90c59836b 100644 --- a/renderdocui/Interop/ReplayRenderer.cs +++ b/renderdocui/Interop/ReplayRenderer.cs @@ -213,6 +213,8 @@ namespace renderdoc 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_GetVulkanPipelineState(IntPtr real, IntPtr mem); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern void ReplayRenderer_BuildCustomShader(IntPtr real, IntPtr entry, IntPtr source, UInt32 compileFlags, ShaderStageType type, ref ResourceId shaderID, IntPtr errorMem); @@ -362,6 +364,22 @@ namespace renderdoc return ret; } + public VulkanPipelineState GetVulkanPipelineState() + { + IntPtr mem = CustomMarshal.Alloc(typeof(VulkanPipelineState)); + + bool success = ReplayRenderer_GetVulkanPipelineState(m_Real, mem); + + VulkanPipelineState ret = null; + + if (success) + ret = (VulkanPipelineState)CustomMarshal.PtrToStructure(mem, typeof(VulkanPipelineState), 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)); diff --git a/renderdocui/Interop/VulkanPipelineState.cs b/renderdocui/Interop/VulkanPipelineState.cs new file mode 100644 index 000000000..10d50e6ae --- /dev/null +++ b/renderdocui/Interop/VulkanPipelineState.cs @@ -0,0 +1,349 @@ +/****************************************************************************** + * 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. + ******************************************************************************/ + +using System; +using System.Runtime.InteropServices; + +namespace renderdoc +{ + [StructLayout(LayoutKind.Sequential)] + public class VulkanPipelineState + { + [StructLayout(LayoutKind.Sequential)] + public class Pipeline + { + public ResourceId obj; + public UInt32 flags; + + [StructLayout(LayoutKind.Sequential)] + public class DescriptorSet + { + public ResourceId layout; + public ResourceId descset; + + [StructLayout(LayoutKind.Sequential)] + public class DescriptorBinding + { + public UInt32 arraySize; + public ShaderBindType type; + public ShaderStageBits stageFlags; + + [StructLayout(LayoutKind.Sequential)] + public class BindingElement + { + public ResourceId view; + public ResourceId sampler; + public UInt32 offset; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public BindingElement[] binds; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public DescriptorBinding[] bindings; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public DescriptorSet[] DescSets; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public Pipeline compute; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public Pipeline graphics; + + [StructLayout(LayoutKind.Sequential)] + public class InputAssembly + { + public bool primitiveRestartEnable; + + [StructLayout(LayoutKind.Sequential)] + public class IndexBuffer + { + public ResourceId buf; + public UInt64 offs; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public IndexBuffer ibuffer; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public InputAssembly IA; + + [StructLayout(LayoutKind.Sequential)] + public class VertexInput + { + [StructLayout(LayoutKind.Sequential)] + public class Attribute + { + public UInt32 location; + public UInt32 binding; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public ResourceFormat format; + public UInt32 byteoffset; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public Attribute[] attrs; + + [StructLayout(LayoutKind.Sequential)] + public class Binding + { + public UInt32 vbufferBinding; + public UInt32 bytestride; + public bool perInstance; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public Binding[] binds; + + [StructLayout(LayoutKind.Sequential)] + public class VertexBuffer + { + public ResourceId buffer; + public UInt64 offset; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public VertexBuffer[] vbuffers; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public VertexInput VI; + + [StructLayout(LayoutKind.Sequential)] + public class ShaderStage + { + private void PostMarshal() + { + if (_ptr_ShaderDetails != IntPtr.Zero) + ShaderDetails = (ShaderReflection)CustomMarshal.PtrToStructure(_ptr_ShaderDetails, typeof(ShaderReflection), false); + else + ShaderDetails = null; + + _ptr_ShaderDetails = IntPtr.Zero; + } + + public ResourceId Shader; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string ShaderName; + public bool customName; + private IntPtr _ptr_ShaderDetails; + [CustomMarshalAs(CustomUnmanagedType.Skip)] + public ShaderReflection ShaderDetails; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public ShaderBindpointMapping BindpointMapping; + + public ShaderStageType stage; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public ShaderStage VS, TCS, TES, GS, FS, CS; + + [StructLayout(LayoutKind.Sequential)] + public class Tessellation + { + public UInt32 numControlPoints; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public Tessellation Tess; + + [StructLayout(LayoutKind.Sequential)] + public class ViewState + { + public ResourceId state; + + [StructLayout(LayoutKind.Sequential)] + public class ViewportScissor + { + [StructLayout(LayoutKind.Sequential)] + public class Viewport + { + public float x, y; + public float Width, Height; + public float MinDepth, MaxDepth; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public Viewport vp; + + [StructLayout(LayoutKind.Sequential)] + public class Scissor + { + public Int32 x, y, right, bottom; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public Scissor scissor; + }; + + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public ViewportScissor[] viewportScissors; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public ViewState VP; + + [StructLayout(LayoutKind.Sequential)] + public class Raster + { + public bool depthClipEnable; + public bool rasterizerDiscardEnable; + public bool FrontCCW; + public TriangleFillMode FillMode; + public TriangleCullMode CullMode; + + // from dynamic state + public ResourceId state; + public float depthBias; + public float depthBiasClamp; + public float slopeScaledDepthBias; + public float lineWidth; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public Raster RS; + + [StructLayout(LayoutKind.Sequential)] + public class MultiSample + { + public UInt32 rasterSamples; + public bool sampleShadingEnable; + public float minSampleShading; + public UInt32 sampleMask; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public MultiSample MSAA; + + [StructLayout(LayoutKind.Sequential)] + public class ColorBlend + { + public bool alphaToCoverageEnable; + public bool logicOpEnable; + + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string LogicOp; + + [StructLayout(LayoutKind.Sequential)] + public class Attachment + { + public bool blendEnable; + + [StructLayout(LayoutKind.Sequential)] + public class BlendOp + { + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string Source; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string Destination; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string Operation; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public BlendOp m_Blend, m_AlphaBlend; + + public byte WriteMask; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public Attachment[] attachments; + + public ResourceId state; + [CustomMarshalAs(CustomUnmanagedType.FixedArray, FixedLength = 4)] + public float[] blendConst; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public ColorBlend CB; + + + [StructLayout(LayoutKind.Sequential)] + public class DepthStencil + { + public bool depthTestEnable; + public bool depthWriteEnable; + public bool depthBoundsEnable; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string depthCompareOp; + + public bool stencilTestEnable; + [StructLayout(LayoutKind.Sequential)] + public class StencilOp + { + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string failOp; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string depthFailOp; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string passOp; + [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] + public string func; + public UInt32 stencilref; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public StencilOp front, back; + + public ResourceId State; + public float minDepthBounds; + public float maxDepthBounds; + public UInt32 StencilReadMask; + public UInt32 StencilWriteMask; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public DepthStencil DS; + + [StructLayout(LayoutKind.Sequential)] + public class CurrentPass + { + [StructLayout(LayoutKind.Sequential)] + public class RenderPass + { + public ResourceId obj; + + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public UInt32[] inputAttachments; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public UInt32[] colorAttachments; + public Int32 depthstencilAttachment; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public RenderPass renderpass; + + [StructLayout(LayoutKind.Sequential)] + public class Framebuffer + { + public ResourceId obj; + + [StructLayout(LayoutKind.Sequential)] + public class Attachment + { + public ResourceId view; + public ResourceId img; + }; + [CustomMarshalAs(CustomUnmanagedType.TemplatedArray)] + public Attachment[] attachments; + + public UInt32 width, height, layers; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public Framebuffer framebuffer; + + [StructLayout(LayoutKind.Sequential)] + public class RenderArea + { + public Int32 x, y, width, height; + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public RenderArea renderArea; + + }; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public CurrentPass Pass; + }; +} diff --git a/renderdocui/renderdocui.csproj b/renderdocui/renderdocui.csproj index 46551cc37..63829b5ab 100644 --- a/renderdocui/renderdocui.csproj +++ b/renderdocui/renderdocui.csproj @@ -107,6 +107,7 @@ +