diff --git a/renderdoc/Makefile b/renderdoc/Makefile index 4bcd76bc3..9b7c1c90d 100644 --- a/renderdoc/Makefile +++ b/renderdoc/Makefile @@ -66,6 +66,8 @@ data/glsl/outline.frago \ data/spv/blitvs.spvo \ data/spv/checkerboardfs.spvo \ data/spv/texdisplayfs.spvo \ +data/spv/textvs.spvo \ +data/spv/textfs.spvo \ data/sourcecodepro.ttfo .PHONY: all diff --git a/renderdoc/data/embedded_files.h b/renderdoc/data/embedded_files.h index 57a62bf15..8da73cee5 100644 --- a/renderdoc/data/embedded_files.h +++ b/renderdoc/data/embedded_files.h @@ -50,5 +50,7 @@ DECLARE_EMBED(outline_frag); DECLARE_EMBED(blitvs_spv); DECLARE_EMBED(checkerboardfs_spv); DECLARE_EMBED(texdisplayfs_spv); +DECLARE_EMBED(textvs_spv); +DECLARE_EMBED(textfs_spv); #undef DECLARE_EMBED diff --git a/renderdoc/data/renderdoc.rc b/renderdoc/data/renderdoc.rc index c3bf30139..7d46c78b6 100644 --- a/renderdoc/data/renderdoc.rc +++ b/renderdoc/data/renderdoc.rc @@ -134,6 +134,8 @@ RESOURCE_sourcecodepro_ttf TYPE_EMBED "sourcecodepro.ttf" RESOURCE_blitvs_spv TYPE_EMBED "spv/blitvs.spv" RESOURCE_checkerboardfs_spv TYPE_EMBED "spv/checkerboardfs.spv" RESOURCE_texdisplayfs_spv TYPE_EMBED "spv/texdisplayfs.spv" +RESOURCE_textvs_spv TYPE_EMBED "spv/textvs.spv" +RESOURCE_textfs_spv TYPE_EMBED "spv/textfs.spv" #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/renderdoc/data/resource.h b/renderdoc/data/resource.h index 25971279c..ab659df2f 100644 --- a/renderdoc/data/resource.h +++ b/renderdoc/data/resource.h @@ -36,6 +36,8 @@ #define RESOURCE_blitvs_spv 401 #define RESOURCE_checkerboardfs_spv 402 #define RESOURCE_texdisplayfs_spv 403 +#define RESOURCE_textvs_spv 404 +#define RESOURCE_textfs_spv 405 #if !defined(STRINGIZE) #define STRINGIZE2(a) #a diff --git a/renderdoc/data/spv/text.frag b/renderdoc/data/spv/text.frag new file mode 100644 index 000000000..57716fe9d --- /dev/null +++ b/renderdoc/data/spv/text.frag @@ -0,0 +1,50 @@ +/****************************************************************************** + * 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 + +layout (binding = 3) uniform sampler2D tex0; +layout (location = 0) out vec4 color_out; + +in v2f +{ + vec4 tex; + vec2 glyphuv; +} IN; + +void main(void) +{ + float text = 0; + + if(IN.glyphuv.x >= 0.0f && IN.glyphuv.x <= 1.0f && + IN.glyphuv.y >= 0.0f && IN.glyphuv.y <= 1.0f) + { + vec2 uv; + uv.x = mix(IN.tex.x, IN.tex.z, IN.glyphuv.x); + uv.y = mix(IN.tex.y, IN.tex.w, IN.glyphuv.y); + text = texture(tex0, uv.xy).x; + } + + color_out = vec4(text.xxx, clamp(text + 0.5f, 0.0f, 1.0f)); +} diff --git a/renderdoc/data/spv/text.vert b/renderdoc/data/spv/text.vert new file mode 100644 index 000000000..b6ce640d7 --- /dev/null +++ b/renderdoc/data/spv/text.vert @@ -0,0 +1,96 @@ +/****************************************************************************** + * 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 + +layout (binding = 0, std140) uniform fontuniforms +{ + vec2 TextPosition; + float txtpadding; + float TextSize; + + vec2 CharacterSize; + vec2 FontScreenAspect; +} general; + +struct glyph +{ + vec4 posdata; + vec4 uvdata; +}; + +layout (binding = 1, std140) uniform glyphdata +{ + glyph data[127-32]; +} glyphs; + +layout (binding = 2, std140) uniform stringdata +{ + uvec4 chars[256]; +} str; + +out gl_PerVertex +{ + vec4 gl_Position; + float gl_PointSize; + float gl_ClipDistance[]; +}; + +out v2f +{ + vec4 tex; + vec2 glyphuv; +} OUT; + +void main(void) +{ + // VKTODOMED temporarily drawing lists + const vec3 verts[6] = vec3[6](vec3( 0.0, 0.0, 0.5), + vec3( 1.0, 0.0, 0.5), + vec3( 0.0, 1.0, 0.5), + + vec3( 1.0, 0.0, 0.5), + vec3( 0.0, 1.0, 0.5), + vec3( 1.0, 1.0, 0.5)); + + vec3 pos = verts[gl_VertexID%6]; + uint strindex = (gl_VertexID/6); + + vec2 charPos = vec2(strindex + pos.x + general.TextPosition.x, pos.y + general.TextPosition.y); + + gl_Position = vec4(charPos.xy*2.0f*general.TextSize*general.FontScreenAspect.xy + vec2(-1, -1), 1, 1); + + uint chars[20] = uint[20](0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19); + + glyph G = glyphs.data[ str.chars[strindex].x ]; + + OUT.glyphuv.xy = (pos.xy - G.posdata.xy) * G.posdata.zw; + OUT.tex = G.uvdata * general.CharacterSize.xyxy; + + const vec3 cols[5] = vec3[5](vec3(0, 0, 0), + vec3(1, 0, 0), + vec3(0, 1, 0), + vec3(0, 0, 1), + vec3(1, 0, 1)); +} \ No newline at end of file diff --git a/renderdoc/driver/vulkan/Makefile b/renderdoc/driver/vulkan/Makefile index 4b18a2209..47868dcdf 100644 --- a/renderdoc/driver/vulkan/Makefile +++ b/renderdoc/driver/vulkan/Makefile @@ -15,6 +15,7 @@ vk_core.o \ vk_common.o \ vk_manager.o \ vk_resources.o \ +vk_debug.o \ LoaderAndTools/layers/vk_layer_table.o \ vk_replay.o \ vk_info.o \ @@ -24,6 +25,9 @@ DOBJDIR=../../.obj/data/spv DATA=blitvs.spvo \ checkerboardfs.spvo \ texdisplayfs.spvo \ +textvs.spvo \ +textfs.spvo \ +../sourcecodepro.ttfo OBJDIR_DATA=$(addprefix $(DOBJDIR)/, $(DATA)) @@ -55,11 +59,13 @@ vk_info.o \ vk_replay_linux.o \ ) +EXTRA_OBJECTS=../../.obj/3rdparty/stb/stb_impl.o ../../.obj/3rdparty/jpeg-compressor/jpge.o + rdoc_vulkan.a: $(STATIC_OBJECTS) ar rcs rdoc_vulkan.a $(STATIC_OBJECTS) -libVKLayerRenderdoc.so: $(OBJDIR_OBJECTS) $(OBJDIR_DATA) $(VULKAN_SDK_SRC)/build/layers/liblayer_utils.so - /usr/bin/c++ -fPIC -std=c++11 -DVK_PROTOTYPES -Wpointer-arith -g -Wl,-Bsymbolic -shared -Wl,-soname,libVKLayerRenderdoc.so -o libVKLayerRenderdoc.so $(OBJDIR_OBJECTS) $(OBJDIR_DATA) ../../.obj/os/linux/linux_threading.o ../../.obj/os/linux/linux_stringio.o ../../.obj/os/linux/linux_network.o ../../.obj/os/os_specific.o ../../.obj/serialise/utf8printf.o ../../.obj/serialise/grisu2.o ../../.obj/core/core.o ../../.obj/core/remote_access.o ../../.obj/replay/capture_options.o ../../.obj/replay/type_helpers.o ../../.obj/serialise/serialiser.o ../../.obj/core/resource_manager.o ../../.obj/common/common.o $(VULKAN_SDK_SRC)/build/layers/liblayer_utils.so -Wl,-rpath,$(VULKAN_SDK_SRC)/build/layers -lpthread -lrt -ldl -lX11 +libVKLayerRenderdoc.so: $(OBJDIR_OBJECTS) $(EXTRA_OBJECTS) $(OBJDIR_DATA) $(VULKAN_SDK_SRC)/build/layers/liblayer_utils.so + /usr/bin/c++ -fPIC -std=c++11 -DVK_PROTOTYPES -Wpointer-arith -g -Wl,-Bsymbolic -shared -Wl,-soname,libVKLayerRenderdoc.so -o libVKLayerRenderdoc.so $(OBJDIR_OBJECTS) $(EXTRA_OBJECTS) $(OBJDIR_DATA) ../../.obj/os/linux/linux_threading.o ../../.obj/os/linux/linux_stringio.o ../../.obj/os/linux/linux_network.o ../../.obj/os/os_specific.o ../../.obj/serialise/utf8printf.o ../../.obj/serialise/grisu2.o ../../.obj/core/core.o ../../.obj/core/remote_access.o ../../.obj/replay/capture_options.o ../../.obj/replay/type_helpers.o ../../.obj/serialise/serialiser.o ../../.obj/core/resource_manager.o ../../.obj/common/common.o $(VULKAN_SDK_SRC)/build/layers/liblayer_utils.so -Wl,-rpath,$(VULKAN_SDK_SRC)/build/layers -lpthread -lrt -ldl -lX11 .PHONY: clean clean: diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 1bcb7a425..f89e54837 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -434,6 +434,8 @@ WrappedVulkan::~WrappedVulkan() //if(it->second.rp != VK_NULL_HANDLE) //device_dispatch_table(GetDev())->DestroyRenderPass(GetDev(), it->second.rp); + //if(it->second.vp != VK_NULL_HANDLE) + //device_dispatch_table(GetDev())->DestroyDynamicViewportState(GetDev(), it->second.vp); } m_SwapChainInfo.clear(); @@ -6701,6 +6703,19 @@ VkResult WrappedVulkan::vkCreateSwapChainWSI( RDCASSERT(vkr == VK_SUCCESS); } + { + VkViewport vp = { 0.0f, 0.0f, (float)pCreateInfo->imageExtent.width, (float)pCreateInfo->imageExtent.height, 0.0f, 1.0f, }; + VkRect2D sc = { { 0, 0 }, { pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height } }; + + VkDynamicViewportStateCreateInfo vpInfo = { + VK_STRUCTURE_TYPE_DYNAMIC_VIEWPORT_STATE_CREATE_INFO, NULL, + 1, &vp, &sc + }; + + vkr = vt->CreateDynamicViewportState(device, &vpInfo, &swapInfo.vp); + RDCASSERT(vkr == VK_SUCCESS); + } + // serialise out the swap chain images { size_t swapChainImagesSize; @@ -6783,10 +6798,8 @@ VkResult WrappedVulkan::vkQueuePresentWSI( VkQueue queue, VkPresentInfoWSI* pPresentInfo) { - VkResult ret = device_dispatch_table(queue)->QueuePresentWSI(queue, pPresentInfo); - - if(ret != VK_SUCCESS || pPresentInfo->swapChainCount == 0) - return ret; + if(pPresentInfo->swapChainCount == 0) + return VK_ERROR_INVALID_VALUE; RenderDoc::Inst().SetCurrentDriver(RDC_Vulkan); @@ -6808,6 +6821,9 @@ VkResult WrappedVulkan::vkQueuePresentWSI( const SwapInfo &swapInfo = m_SwapChainInfo[swapid]; VkImage backbuffer = swapInfo.images[pPresentInfo->imageIndices[0]].im; + + // VKTODOLOW multiple windows/captures etc + bool activeWindow = true; //RenderDoc::Inst().IsActiveWindow((ID3D11Device *)this, swapdesc.OutputWindow); if(m_State == WRITING_IDLE) { @@ -6836,14 +6852,104 @@ VkResult WrappedVulkan::vkQueuePresentWSI( m_AvgFrametime /= double(m_FrameTimes.size()); m_FrameTimes.clear(); + } + + uint32_t overlay = RenderDoc::Inst().GetOverlayBits(); + + if(overlay & eRENDERDOC_Overlay_Enabled) + { + VkRenderPass rp = swapInfo.rp; + VkDynamicViewportState vp = swapInfo.vp; + VkFramebuffer fb = swapInfo.images[pPresentInfo->imageIndices[0]].fb; + + // VKTODOLOW only handling queue == GetQ() + RDCASSERT(GetQ() == queue); + + VkLayerDispatchTable *vt = device_dispatch_table(GetDev()); + + vt->QueueWaitIdle(GetQ()); + + TextPrintState textstate = { GetQ(), GetCmd(), rp, fb, vp, swapInfo.extent.width, swapInfo.extent.height }; + + if(activeWindow) + { + vector keys = RenderDoc::Inst().GetCaptureKeys(); + + string overlayText = "Vulkan. "; + + for(size_t i=0; i < keys.size(); i++) + { + if(i > 0) + overlayText += ", "; + + overlayText += ToStr::Get(keys[i]); + } + + if(!keys.empty()) + overlayText += " to capture."; + + if(overlay & eRENDERDOC_Overlay_FrameNumber) + { + overlayText += StringFormat::Fmt(" Frame: %d.", m_FrameCounter); + } + if(overlay & eRENDERDOC_Overlay_FrameRate) + { + overlayText += StringFormat::Fmt(" %.2lf ms (%.2lf .. %.2lf) (%.0lf FPS)", + m_AvgFrametime, m_MinFrametime, m_MaxFrametime, 1000.0f/m_AvgFrametime); + } + + float y=0.0f; + + if(!overlayText.empty()) + { + GetDebugManager()->RenderText(textstate, 0.0f, y, overlayText.c_str()); + y += 1.0f; + } + + if(overlay & eRENDERDOC_Overlay_CaptureList) + { + GetDebugManager()->RenderText(textstate, 0.0f, y, "%d Captures saved.\n", (uint32_t)m_FrameRecord.size()); + y += 1.0f; + + uint64_t now = Timing::GetUnixTimestamp(); + for(size_t i=0; i < m_FrameRecord.size(); i++) + { + if(now - m_FrameRecord[i].frameInfo.captureTime < 20) + { + GetDebugManager()->RenderText(textstate, 0.0f, y, "Captured frame %d.\n", m_FrameRecord[i].frameInfo.frameNumber); + y += 1.0f; + } + } + } + + // VKTODOLOW failed frames - RDCLOG("Frame: %d. F12/PrtScr to capture. %.2lf ms (%.2lf .. %.2lf) (%.0lf FPS)", - m_FrameCounter, m_AvgFrametime, m_MinFrametime, m_MaxFrametime, 1000.0f/m_AvgFrametime); - for(size_t i=0; i < m_FrameRecord.size(); i++) - RDCLOG("Captured Frame %d. Multiple frame capture not supported.\n", m_FrameRecord[i].frameInfo.frameNumber); #if !defined(RELEASE) - // RDCLOG("%llu chunks - %.2f MB", Chunk::NumLiveChunks(), float(Chunk::TotalMem())/1024.0f/1024.0f); + GetDebugManager()->RenderText(textstate, 0.0f, y, "%llu chunks - %.2f MB", Chunk::NumLiveChunks(), float(Chunk::TotalMem())/1024.0f/1024.0f); + y += 1.0f; #endif + } + else + { + vector keys = RenderDoc::Inst().GetFocusKeys(); + + string str = "Vulkan. Inactive swapchain."; + + for(size_t i=0; i < keys.size(); i++) + { + if(i == 0) + str += " "; + else + str += ", "; + + str += ToStr::Get(keys[i]); + } + + if(!keys.empty()) + str += " to cycle between swapchains"; + + GetDebugManager()->RenderText(textstate, 0.0f, 0.0f, str.c_str()); + } } } @@ -7182,6 +7288,7 @@ VkResult WrappedVulkan::vkQueuePresentWSI( FetchFrameRecord record; record.frameInfo.frameNumber = m_FrameCounter+1; + record.frameInfo.captureTime = Timing::GetUnixTimestamp(); m_FrameRecord.push_back(record); GetResourceManager()->ClearReferencedResources(); @@ -7194,8 +7301,8 @@ VkResult WrappedVulkan::vkQueuePresentWSI( RDCLOG("Starting capture, frame %u", m_FrameCounter); } - - return ret; + + return device_dispatch_table(queue)->QueuePresentWSI(queue, pPresentInfo); } bool WrappedVulkan::Prepare_InitialState(VkResource res) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 2ea5e81d0..8a624677c 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -339,6 +339,7 @@ private: int arraySize; VkRenderPass rp; + VkDynamicViewportState vp; struct SwapImage { diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index ee12aba38..8851232d3 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -25,6 +25,8 @@ #include "vk_debug.h" #include "vk_core.h" +#include "stb/stb_truetype.h" + // VKTODOMED should share this between shader and C++ - need #include support in glslang struct displayuniforms { @@ -51,6 +53,32 @@ struct displayuniforms Vec2f Padding; }; +struct fontuniforms +{ + Vec2f TextPosition; + float txtpadding; + float TextSize; + + Vec2f CharacterSize; + Vec2f FontScreenAspect; +}; + +struct glyph +{ + Vec4f posdata; + Vec4f uvdata; +}; + +struct glyphdata +{ + glyph glyphs[127-32]; +}; + +struct stringdata +{ + uint32_t str[256][4]; +}; + void VulkanDebugManager::UBO::Create(WrappedVulkan *driver, VkDevice dev, VkDeviceSize size) { const VkLayerDispatchTable *vt = device_dispatch_table(dev); @@ -130,6 +158,8 @@ void VulkanDebugManager::UBO::Unmap(const VkLayerDispatchTable *vt, VkDevice dev VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkImageView fakeBBView) { + // VKTODOLOW needs tidy up - isn't scalable. Needs more classes like UBO above. + m_PipelineCache = VK_NULL_HANDLE; m_DescriptorPool = VK_NULL_HANDLE; m_DynamicCBStateWhite = VK_NULL_HANDLE; @@ -152,6 +182,17 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm m_TexDisplayPipeline = VK_NULL_HANDLE; m_TexDisplayBlendPipeline = VK_NULL_HANDLE; RDCEraseEl(m_TexDisplayUBO); + + m_TextDescSetLayout = VK_NULL_HANDLE; + m_TextPipeLayout = VK_NULL_HANDLE; + m_TextDescSet = VK_NULL_HANDLE; + m_TextPipeline = VK_NULL_HANDLE; + RDCEraseEl(m_TextGeneralUBO); + RDCEraseEl(m_TextGlyphUBO); + RDCEraseEl(m_TextStringUBO); + m_TextAtlas = VK_NULL_HANDLE; + m_TextAtlasMem = VK_NULL_HANDLE; + m_TextAtlasView = VK_NULL_HANDLE; m_Device = dev; @@ -187,6 +228,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm RDCASSERT(vkr == VK_SUCCESS); { + // VKTODOLOW not sure if these stage flags VK_SHADER_STAGE_... work yet? VkDescriptorSetLayoutBinding layoutBinding[] = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, } }; @@ -215,6 +257,23 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm RDCASSERT(vkr == VK_SUCCESS); } + { + VkDescriptorSetLayoutBinding layoutBinding[] = { + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, }, + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL, } + }; + + VkDescriptorSetLayoutCreateInfo descsetLayoutInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, + ARRAY_COUNT(layoutBinding), &layoutBinding[0], + }; + + vkr = vt->CreateDescriptorSetLayout(dev, &descsetLayoutInfo, &m_TextDescSetLayout); + RDCASSERT(vkr == VK_SUCCESS); + } + VkPipelineLayoutCreateInfo pipeLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, NULL, 1, &m_TexDisplayDescSetLayout, @@ -229,6 +288,11 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm vkr = vt->CreatePipelineLayout(dev, &pipeLayoutInfo, &m_CheckerboardPipeLayout); RDCASSERT(vkr == VK_SUCCESS); + pipeLayoutInfo.pSetLayouts = &m_TextDescSetLayout; + + vkr = vt->CreatePipelineLayout(dev, &pipeLayoutInfo, &m_TextPipeLayout); + RDCASSERT(vkr == VK_SUCCESS); + VkDescriptorTypeCount descPoolTypes[] = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024, }, { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1024, }, @@ -239,7 +303,7 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm ARRAY_COUNT(descPoolTypes), &descPoolTypes[0], }; - vkr = vt->CreateDescriptorPool(dev, VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 2, &descpoolInfo, &m_DescriptorPool); + vkr = vt->CreateDescriptorPool(dev, VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 3, &descpoolInfo, &m_DescriptorPool); RDCASSERT(vkr == VK_SUCCESS); uint32_t count; @@ -250,41 +314,21 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm vkr = vt->AllocDescriptorSets(dev, m_DescriptorPool, VK_DESCRIPTOR_SET_USAGE_STATIC, 1, &m_TexDisplayDescSetLayout, &m_TexDisplayDescSet, &count); RDCASSERT(vkr == VK_SUCCESS); + + vkr = vt->AllocDescriptorSets(dev, m_DescriptorPool, VK_DESCRIPTOR_SET_USAGE_STATIC, 1, + &m_TextDescSetLayout, &m_TextDescSet, &count); + RDCASSERT(vkr == VK_SUCCESS); m_CheckerboardUBO.Create(driver, dev, 128); m_TexDisplayUBO.Create(driver, dev, 128); - RDCCOMPILE_ASSERT(sizeof(displayuniforms) < 128, "tex display size"); + RDCCOMPILE_ASSERT(sizeof(displayuniforms) <= 128, "tex display size"); + + m_TextGeneralUBO.Create(driver, dev, 128); + RDCCOMPILE_ASSERT(sizeof(fontuniforms) <= 128, "font uniforms size"); - VkDescriptorInfo desc[3]; - RDCEraseEl(desc); - - desc[0].bufferView = m_CheckerboardUBO.view; - desc[1].bufferView = m_TexDisplayUBO.view; - desc[2].imageLayout = VK_IMAGE_LAYOUT_GENERAL; - desc[2].imageView = m_FakeBBImView; - desc[2].sampler = m_LinearSampler; - - VkWriteDescriptorSet writeSet[] = { - { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, - m_CheckerboardDescSet, 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &desc[0] - }, - { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, - m_TexDisplayDescSet, 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &desc[1] - }, - { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, - m_TexDisplayDescSet, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &desc[2] - }, - }; - - if(m_FakeBBImView != VK_NULL_HANDLE) - { - vkr = vt->UpdateDescriptorSets(dev, ARRAY_COUNT(writeSet), writeSet, 0, NULL); - RDCASSERT(vkr == VK_SUCCESS); - } + m_TextStringUBO.Create(driver, dev, 4096); + RDCCOMPILE_ASSERT(sizeof(stringdata) <= 4096, "font uniforms size"); VkDynamicRasterStateCreateInfo rsInfo = { VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO, NULL, @@ -314,6 +358,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm GetEmbeddedResource(blitvs_spv), GetEmbeddedResource(checkerboardfs_spv), GetEmbeddedResource(texdisplayfs_spv), + GetEmbeddedResource(textvs_spv), + GetEmbeddedResource(textfs_spv), }; enum shaderIdx @@ -321,6 +367,8 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm BLITVS, CHECKERBOARDFS, TEXDISPLAYFS, + TEXTVS, + TEXTFS, }; VkShaderModule module[ARRAY_COUNT(shaderSources)]; @@ -429,6 +477,16 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm vkr = vt->CreateGraphicsPipelines(dev, m_PipelineCache, 1, &pipeInfo, &m_TexDisplayBlendPipeline); RDCASSERT(vkr == VK_SUCCESS); + ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + stages[0].shader = shader[TEXTVS]; + stages[1].shader = shader[TEXTFS]; + + pipeInfo.layout = m_TextPipeLayout; + + vkr = vt->CreateGraphicsPipelines(dev, m_PipelineCache, 1, &pipeInfo, &m_TextPipeline); + RDCASSERT(vkr == VK_SUCCESS); + for(size_t i=0; i < ARRAY_COUNT(module); i++) { vkr = vt->DestroyShader(dev, shader[i]); @@ -437,6 +495,210 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkIm vkr = vt->DestroyShaderModule(dev, module[i]); RDCASSERT(vkr == VK_SUCCESS); } + + { + int width = FONT_TEX_WIDTH, height = FONT_TEX_HEIGHT; + + VkImageCreateInfo imInfo = { + /*.sType =*/ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + /*.pNext =*/ NULL, + /*.imageType =*/ VK_IMAGE_TYPE_2D, + /*.format =*/ VK_FORMAT_R8_UNORM, + /*.extent =*/ { width, height, 1 }, + /*.mipLevels =*/ 1, + /*.arraySize =*/ 1, + /*.samples =*/ 1, + /*.tiling =*/ VK_IMAGE_TILING_LINEAR, + /*.usage =*/ VK_IMAGE_USAGE_SAMPLED_BIT, + /*.flags =*/ 0, + }; + + string font = GetEmbeddedResource(sourcecodepro_ttf); + byte *ttfdata = (byte *)font.c_str(); + + const int firstChar = int(' ') + 1; + const int lastChar = 127; + const int numChars = lastChar-firstChar; + + byte *buf = new byte[width*height]; + + const float pixelHeight = 20.0f; + + stbtt_bakedchar chardata[numChars]; + int ret = stbtt_BakeFontBitmap(ttfdata, 0, pixelHeight, buf, width, height, firstChar, numChars, chardata); + + m_FontCharSize = pixelHeight; + m_FontCharAspect = chardata->xadvance / pixelHeight; + + stbtt_fontinfo f = {0}; + stbtt_InitFont(&f, ttfdata, 0); + + int ascent = 0; + stbtt_GetFontVMetrics(&f, &ascent, NULL, NULL); + + float maxheight = float(ascent)*stbtt_ScaleForPixelHeight(&f, pixelHeight); + + // create and fill image + { + vkr = vt->CreateImage(dev, &imInfo, &m_TextAtlas); + RDCASSERT(vkr == VK_SUCCESS); + + VkMemoryRequirements mrq; + vkr = vt->GetImageMemoryRequirements(dev, m_TextAtlas, &mrq); + RDCASSERT(vkr == VK_SUCCESS); + + VkImageSubresource subr = { VK_IMAGE_ASPECT_COLOR, 0, 0 }; + VkSubresourceLayout layout = { 0 }; + vt->GetImageSubresourceLayout(dev, m_TextAtlas, &subr, &layout); + + // allocate readback memory + VkMemoryAllocInfo allocInfo = { + VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO, NULL, + mrq.size, driver->GetUploadMemoryIndex(mrq.memoryTypeBits), + }; + + vkr = vt->AllocMemory(dev, &allocInfo, &m_TextAtlasMem); + RDCASSERT(vkr == VK_SUCCESS); + vkr = vt->BindImageMemory(dev, m_TextAtlas, m_TextAtlasMem, 0); + RDCASSERT(vkr == VK_SUCCESS); + + VkImageViewCreateInfo viewInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, NULL, + m_TextAtlas, VK_IMAGE_VIEW_TYPE_2D, + imInfo.format, + { VK_CHANNEL_SWIZZLE_R, VK_CHANNEL_SWIZZLE_G, VK_CHANNEL_SWIZZLE_B, VK_CHANNEL_SWIZZLE_A }, + { VK_IMAGE_ASPECT_COLOR, 0, 1, 0, 1, } + }; + + // VKTODOMED used for texture display, but eventually will have to be created on the fly + // for whichever image we're viewing (and cached), not specifically created here. + VkResult vkr = vt->CreateImageView(dev, &viewInfo, &m_TextAtlasView); + RDCASSERT(vkr == VK_SUCCESS); + + // need to transition image into valid state, then upload + VkCmdBuffer cmd = driver->GetCmd(); + VkQueue q = driver->GetQ(); + + VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT }; + + vkr = vt->ResetCommandBuffer(cmd, 0); + RDCASSERT(vkr == VK_SUCCESS); + vkr = vt->BeginCommandBuffer(cmd, &beginInfo); + RDCASSERT(vkr == VK_SUCCESS); + + VkImageMemoryBarrier trans = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, NULL, + 0, 0, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + 0, 0, m_TextAtlas, + { VK_IMAGE_ASPECT_COLOR, 0, 1, 0, 1 } }; + + void *barrier = (void *)&trans; + + vt->CmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + vt->EndCommandBuffer(cmd); + + vt->QueueSubmit(q, 1, &cmd, VK_NULL_HANDLE); + + // VKTODOMED ideally all the commands from Bind to Flip would be recorded + // into a single command buffer and we can just have several allocated + // ring-buffer style + vt->QueueWaitIdle(q); + + byte *pData = NULL; + vkr = vt->MapMemory(dev, m_TextAtlasMem, 0, 0, 0, (void **)&pData); + RDCASSERT(vkr == VK_SUCCESS); + + RDCASSERT(pData != NULL); + + for(int32_t row = 0; row < height; row++) + { + memcpy(pData, buf, width); + pData += layout.rowPitch; + buf += width; + } + + vkr = vt->UnmapMemory(dev, m_TextAtlasMem); + RDCASSERT(vkr == VK_SUCCESS); + } + + m_TextGlyphUBO.Create(driver, dev, 4096); + RDCCOMPILE_ASSERT(sizeof(Vec4f)*2*(numChars+1) < 4096, "font uniform size"); + + Vec4f *glyphData = (Vec4f *)m_TextGlyphUBO.Map(vt, dev); + + for(int i=0; i < numChars; i++) + { + stbtt_bakedchar *b = chardata+i; + + float x = b->xoff; + float y = b->yoff + maxheight; + + glyphData[(i+1)*2 + 0] = Vec4f(x/b->xadvance, y/pixelHeight, b->xadvance/float(b->x1 - b->x0), pixelHeight/float(b->y1 - b->y0)); + glyphData[(i+1)*2 + 1] = Vec4f(b->x0, b->y0, b->x1, b->y1); + } + + m_TextGlyphUBO.Unmap(vt, dev); + } + + VkDescriptorInfo desc[7]; + RDCEraseEl(desc); + + // checkerboard + desc[0].bufferView = m_CheckerboardUBO.view; + + // tex display + desc[1].bufferView = m_TexDisplayUBO.view; + desc[2].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + desc[2].imageView = m_FakeBBImView; + desc[2].sampler = m_LinearSampler; + + // text + desc[3].bufferView = m_TextGeneralUBO.view; + desc[4].bufferView = m_TextGlyphUBO.view; + desc[5].bufferView = m_TextStringUBO.view; + desc[6].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + desc[6].imageView = m_TextAtlasView; + desc[6].sampler = m_LinearSampler; + + VkWriteDescriptorSet writeSet[] = { + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, + m_CheckerboardDescSet, 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &desc[0] + }, + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, + m_TexDisplayDescSet, 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &desc[1] + }, + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, + m_TextDescSet, 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &desc[3] + }, + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, + m_TextDescSet, 1, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &desc[4] + }, + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, + m_TextDescSet, 2, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &desc[5] + }, + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, + m_TextDescSet, 3, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &desc[6] + }, + // this one is last so that we can skip it if we don't have m_FakeBBImView + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, + m_TexDisplayDescSet, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &desc[2] + }, + }; + + uint32_t writeCount = (uint32_t)ARRAY_COUNT(writeSet); + if(m_FakeBBImView == VK_NULL_HANDLE) + writeCount--; + + vkr = vt->UpdateDescriptorSets(dev, writeCount, writeSet, 0, NULL); + RDCASSERT(vkr == VK_SUCCESS); } VulkanDebugManager::~VulkanDebugManager() @@ -538,4 +800,129 @@ VulkanDebugManager::~VulkanDebugManager() m_CheckerboardUBO.Destroy(vt, dev); m_TexDisplayUBO.Destroy(vt, dev); + + if(m_TextDescSetLayout != VK_NULL_HANDLE) + { + vkr = vt->DestroyDescriptorSetLayout(dev, m_TextDescSetLayout); + RDCASSERT(vkr == VK_SUCCESS); + } + + if(m_TextPipeLayout != VK_NULL_HANDLE) + { + vkr = vt->DestroyPipelineLayout(dev, m_TextPipeLayout); + RDCASSERT(vkr == VK_SUCCESS); + } + + if(m_TextPipeline != VK_NULL_HANDLE) + { + vkr = vt->DestroyPipeline(dev, m_TextPipeline); + RDCASSERT(vkr == VK_SUCCESS); + } + + m_TextGeneralUBO.Destroy(vt, dev); + m_TextGlyphUBO.Destroy(vt, dev); + m_TextStringUBO.Destroy(vt, dev); + + if(m_TextAtlasView != VK_NULL_HANDLE) + { + vkr = vt->DestroyImageView(dev, m_TextAtlasView); + RDCASSERT(vkr == VK_SUCCESS); + } + + if(m_TextAtlas != VK_NULL_HANDLE) + { + vkr = vt->DestroyImage(dev, m_TextAtlas); + RDCASSERT(vkr == VK_SUCCESS); + } + + if(m_TextAtlasMem != VK_NULL_HANDLE) + { + vkr = vt->FreeMemory(dev, m_TextAtlasMem); + RDCASSERT(vkr == VK_SUCCESS); + } } + +void VulkanDebugManager::RenderText(const TextPrintState &textstate, float x, float y, const char *textfmt, ...) +{ + static char tmpBuf[4096]; + + va_list args; + va_start(args, textfmt); + StringFormat::vsnprintf( tmpBuf, 4095, textfmt, args ); + tmpBuf[4095] = '\0'; + va_end(args); + + RenderTextInternal(textstate, x, y, tmpBuf); +} + +void VulkanDebugManager::RenderTextInternal(const TextPrintState &textstate, float x, float y, const char *text) +{ + const VkLayerDispatchTable *vt = device_dispatch_table(m_Device); + + // VKTODOMED needs to be optimised to do all in one cmd buffer with + // a start/stop pair of calls that map a UBO, then do each draw with + // a push constant to tell it what the line should be. + + VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT }; + + VkResult vkr = VK_SUCCESS; + + fontuniforms *ubo = (fontuniforms *)m_TextGeneralUBO.Map(vt, m_Device); + + ubo->TextPosition.x = x; + ubo->TextPosition.y = y; + + ubo->FontScreenAspect.x = 1.0f/float(textstate.w); + ubo->FontScreenAspect.y = 1.0f/float(textstate.h); + + ubo->TextSize = m_FontCharSize; + ubo->FontScreenAspect.x *= m_FontCharAspect; + + ubo->CharacterSize.x = 1.0f/float(FONT_TEX_WIDTH); + ubo->CharacterSize.y = 1.0f/float(FONT_TEX_HEIGHT); + + m_TextGeneralUBO.Unmap(vt, m_Device); + + stringdata *stringData = (stringdata *)m_TextStringUBO.Map(vt, m_Device); + + for(size_t i=0; i < strlen(text); i++) + stringData->str[i][0] = uint32_t(text[i] - ' '); + + m_TextStringUBO.Unmap(vt, m_Device); + + vkr = vt->ResetCommandBuffer(textstate.cmd, 0); + RDCASSERT(vkr == VK_SUCCESS); + vkr = vt->BeginCommandBuffer(textstate.cmd, &beginInfo); + RDCASSERT(vkr == VK_SUCCESS); + + { + VkClearValue clearval = {0}; + VkRenderPassBeginInfo rpbegin = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, NULL, + textstate.rp, textstate.fb, + { { 0, 0, }, { textstate.w, textstate.h} }, + 1, &clearval, + }; + vt->CmdBeginRenderPass(textstate.cmd, &rpbegin, VK_RENDER_PASS_CONTENTS_INLINE); + + // VKTODOMED will need a way to disable blend for other things + vt->CmdBindPipeline(textstate.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_TextPipeline); + vt->CmdBindDescriptorSets(textstate.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_TextPipeLayout, 0, 1, &m_TextDescSet, 0, NULL); + + vt->CmdBindDynamicViewportState(textstate.cmd, textstate.vp); + vt->CmdBindDynamicRasterState(textstate.cmd, m_DynamicRSState); + vt->CmdBindDynamicColorBlendState(textstate.cmd, m_DynamicCBStateWhite); + vt->CmdBindDynamicDepthStencilState(textstate.cmd, m_DynamicDSStateDisabled); + + // VKTODOMED strip + instance ID doesn't seem to work atm? instance ID comes through 0 + // for now, do lists, but want to change back + vt->CmdDraw(textstate.cmd, 0, 6*(uint32_t)strlen(text), 0, 1); + vt->CmdEndRenderPass(textstate.cmd); + } + + vt->EndCommandBuffer(textstate.cmd); + + vt->QueueSubmit(textstate.q, 1, &textstate.cmd, VK_NULL_HANDLE); + + vt->QueueWaitIdle(textstate.q); +} \ No newline at end of file diff --git a/renderdoc/driver/vulkan/vk_debug.h b/renderdoc/driver/vulkan/vk_debug.h index 25d33673b..00e66b91e 100644 --- a/renderdoc/driver/vulkan/vk_debug.h +++ b/renderdoc/driver/vulkan/vk_debug.h @@ -30,11 +30,23 @@ #include "replay/replay_driver.h" #include "core/core.h" +struct TextPrintState +{ + VkQueue q; + VkCmdBuffer cmd; + VkRenderPass rp; + VkFramebuffer fb; + VkDynamicViewportState vp; + int32_t w, h; +}; + class VulkanDebugManager { public: VulkanDebugManager(WrappedVulkan *driver, VkDevice dev, VkImageView fakeBBView); ~VulkanDebugManager(); + + void RenderText(const TextPrintState &textstate, float x, float y, const char *fmt, ...); struct UBO { @@ -71,11 +83,30 @@ class VulkanDebugManager VkDescriptorSet m_TexDisplayDescSet; VkPipeline m_TexDisplayPipeline, m_TexDisplayBlendPipeline; UBO m_TexDisplayUBO; + + VkDescriptorSetLayout m_TextDescSetLayout; + VkPipelineLayout m_TextPipeLayout; + VkDescriptorSet m_TextDescSet; + VkPipeline m_TextPipeline; + UBO m_TextGeneralUBO; + UBO m_TextGlyphUBO; + UBO m_TextStringUBO; + VkImage m_TextAtlas; + VkDeviceMemory m_TextAtlasMem; + VkImageView m_TextAtlasView; private: void InitDebugData(); void ShutdownDebugData(); + void RenderTextInternal(const TextPrintState &textstate, float x, float y, const char *text); + static const int FONT_TEX_WIDTH = 256; + static const int FONT_TEX_HEIGHT = 128; + + float m_FontCharAspect; + float m_FontCharSize; + + WrappedVulkan *m_pDriver; VkDevice m_Device; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 096e94e0d..3c40ccf02 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -397,9 +397,9 @@ VulkanReplay::VulkanReplay() m_BindDepth = false; } -VulkanDebugManager &VulkanReplay::GetDebugManager() +VulkanDebugManager *VulkanReplay::GetDebugManager() { - return *m_pDriver->GetDebugManager(); + return m_pDriver->GetDebugManager(); } void VulkanReplay::Shutdown() @@ -627,7 +627,7 @@ bool VulkanReplay::RenderTexture(TextureDisplay cfg) // VKTODOHIGH once we stop doing DeviceWaitIdle/QueueWaitIdle all over, this // needs to be ring-buffered - displayuniforms *data = (displayuniforms *)GetDebugManager().m_TexDisplayUBO.Map(vt, dev); + displayuniforms *data = (displayuniforms *)GetDebugManager()->m_TexDisplayUBO.Map(vt, dev); data->Padding = 0; @@ -705,18 +705,18 @@ bool VulkanReplay::RenderTexture(TextureDisplay cfg) data->RawOutput = cfg.rawoutput ? 1 : 0; - GetDebugManager().m_TexDisplayUBO.Unmap(vt, dev); + GetDebugManager()->m_TexDisplayUBO.Unmap(vt, dev); VkDescriptorInfo desc = {0}; desc.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - desc.imageView = GetDebugManager().m_FakeBBImView; - desc.sampler = GetDebugManager().m_PointSampler; + desc.imageView = GetDebugManager()->m_FakeBBImView; + desc.sampler = GetDebugManager()->m_PointSampler; if(cfg.mip == 0 && cfg.scale < 1.0f) - desc.sampler = GetDebugManager().m_LinearSampler; + desc.sampler = GetDebugManager()->m_LinearSampler; VkWriteDescriptorSet writeSet = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, - GetDebugManager().m_TexDisplayDescSet, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &desc + GetDebugManager()->m_TexDisplayDescSet, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &desc }; VkResult vkr = vt->UpdateDescriptorSets(dev, 1, &writeSet, 0, NULL); @@ -752,13 +752,13 @@ bool VulkanReplay::RenderTexture(TextureDisplay cfg) vt->CmdBeginRenderPass(cmd, &rpbegin, VK_RENDER_PASS_CONTENTS_INLINE); // VKTODOMED will need a way to disable blend for other things - vt->CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cfg.rawoutput ? GetDebugManager().m_TexDisplayPipeline : GetDebugManager().m_TexDisplayBlendPipeline); - vt->CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, GetDebugManager().m_TexDisplayPipeLayout, 0, 1, &GetDebugManager().m_TexDisplayDescSet, 0, NULL); + vt->CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cfg.rawoutput ? GetDebugManager()->m_TexDisplayPipeline : GetDebugManager()->m_TexDisplayBlendPipeline); + vt->CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, GetDebugManager()->m_TexDisplayPipeLayout, 0, 1, &GetDebugManager()->m_TexDisplayDescSet, 0, NULL); vt->CmdBindDynamicViewportState(cmd, outw.fullVP); - vt->CmdBindDynamicRasterState(cmd, GetDebugManager().m_DynamicRSState); - vt->CmdBindDynamicColorBlendState(cmd, GetDebugManager().m_DynamicCBStateWhite); - vt->CmdBindDynamicDepthStencilState(cmd, GetDebugManager().m_DynamicDSStateDisabled); + vt->CmdBindDynamicRasterState(cmd, GetDebugManager()->m_DynamicRSState); + vt->CmdBindDynamicColorBlendState(cmd, GetDebugManager()->m_DynamicCBStateWhite); + vt->CmdBindDynamicDepthStencilState(cmd, GetDebugManager()->m_DynamicDSStateDisabled); vt->CmdDraw(cmd, 0, 4, 0, 1); vt->CmdEndRenderPass(cmd); @@ -803,14 +803,14 @@ void VulkanReplay::RenderCheckerboard(Vec3f light, Vec3f dark) // VKTODOHIGH once we stop doing DeviceWaitIdle/QueueWaitIdle all over, this // needs to be ring-buffered - Vec4f *data = (Vec4f *)GetDebugManager().m_CheckerboardUBO.Map(vt, dev); + Vec4f *data = (Vec4f *)GetDebugManager()->m_CheckerboardUBO.Map(vt, dev); data[0].x = light.x; data[0].y = light.y; data[0].z = light.z; data[1].x = dark.x; data[1].y = dark.y; data[1].z = dark.z; - GetDebugManager().m_CheckerboardUBO.Unmap(vt, dev); + GetDebugManager()->m_CheckerboardUBO.Unmap(vt, dev); { VkClearValue clearval = {0}; @@ -822,13 +822,13 @@ void VulkanReplay::RenderCheckerboard(Vec3f light, Vec3f dark) }; vt->CmdBeginRenderPass(cmd, &rpbegin, VK_RENDER_PASS_CONTENTS_INLINE); - vt->CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, GetDebugManager().m_CheckerboardPipeline); - vt->CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, GetDebugManager().m_CheckerboardPipeLayout, 0, 1, &GetDebugManager().m_CheckerboardDescSet, 0, NULL); + vt->CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, GetDebugManager()->m_CheckerboardPipeline); + vt->CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, GetDebugManager()->m_CheckerboardPipeLayout, 0, 1, &GetDebugManager()->m_CheckerboardDescSet, 0, NULL); vt->CmdBindDynamicViewportState(cmd, outw.fullVP); - vt->CmdBindDynamicRasterState(cmd, GetDebugManager().m_DynamicRSState); - vt->CmdBindDynamicColorBlendState(cmd, GetDebugManager().m_DynamicCBStateWhite); - vt->CmdBindDynamicDepthStencilState(cmd, GetDebugManager().m_DynamicDSStateDisabled); + vt->CmdBindDynamicRasterState(cmd, GetDebugManager()->m_DynamicRSState); + vt->CmdBindDynamicColorBlendState(cmd, GetDebugManager()->m_DynamicCBStateWhite); + vt->CmdBindDynamicDepthStencilState(cmd, GetDebugManager()->m_DynamicDSStateDisabled); vt->CmdDraw(cmd, 0, 4, 0, 1); vt->CmdEndRenderPass(cmd); diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index c77f1708e..762b1bf8c 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -215,5 +215,5 @@ class VulkanReplay : public IReplayDriver WrappedVulkan *m_pDriver; - VulkanDebugManager &GetDebugManager(); + VulkanDebugManager *GetDebugManager(); }; diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index 4c4dd0e48..c38612b9d 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -363,6 +363,10 @@ + + + + diff --git a/renderdoc/renderdoc.vcxproj.filters b/renderdoc/renderdoc.vcxproj.filters index c2cb2ee76..16d177975 100644 --- a/renderdoc/renderdoc.vcxproj.filters +++ b/renderdoc/renderdoc.vcxproj.filters @@ -448,6 +448,18 @@ Resources\spv + + Resources\spv + + + Resources\spv + + + Resources\spv + + + Resources\spv +