From 05a70164f6650b620c32a90514882f216b28defb Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 13 Dec 2019 14:34:45 +0000 Subject: [PATCH] Remove use of legacy StringFormat::snprintf variants --- renderdoc/api/replay/shader_types.h | 6 +- renderdoc/common/common.cpp | 23 +- renderdoc/common/timing.h | 16 +- renderdoc/driver/d3d11/d3d11_device.cpp | 8 +- renderdoc/driver/d3d11/d3d11_rendertext.cpp | 38 ++- renderdoc/driver/d3d11/d3d11_rendertext.h | 4 +- renderdoc/driver/d3d11/d3d11_shaderdebug.cpp | 219 ++++++++---------- renderdoc/driver/d3d12/d3d12_common.cpp | 5 +- renderdoc/driver/d3d12/d3d12_device.cpp | 3 +- renderdoc/driver/d3d12/d3d12_rendertext.cpp | 36 +-- renderdoc/driver/d3d12/d3d12_rendertext.h | 4 +- renderdoc/driver/d3d12/d3d12_shaderdebug.cpp | 176 +++++++------- renderdoc/driver/d3d8/d3d8_debug.cpp | 32 +-- renderdoc/driver/d3d8/d3d8_debug.h | 4 +- renderdoc/driver/d3d8/d3d8_device.cpp | 3 +- renderdoc/driver/d3d9/d3d9_debug.cpp | 32 +-- renderdoc/driver/d3d9/d3d9_debug.h | 4 +- renderdoc/driver/d3d9/d3d9_device.cpp | 3 +- renderdoc/driver/gl/gl_driver.cpp | 7 +- renderdoc/driver/gl/gl_driver.h | 17 +- renderdoc/driver/gl/gl_rendertext.cpp | 44 ++-- renderdoc/driver/gl/gl_stringise.cpp | 10 +- .../driver/shaders/dxbc/dxbc_bytecode.cpp | 38 +-- .../driver/shaders/dxbc/dxbc_container.cpp | 23 +- renderdoc/driver/shaders/dxbc/dxbc_debug.cpp | 15 +- .../driver/shaders/dxbc/dxbc_disassemble.cpp | 202 +++++----------- renderdoc/driver/vulkan/vk_rendertext.cpp | 34 +-- renderdoc/driver/vulkan/vk_rendertext.h | 4 +- .../driver/vulkan/wrappers/vk_get_funcs.cpp | 6 +- .../driver/vulkan/wrappers/vk_wsi_funcs.cpp | 10 +- renderdoc/os/os_specific.cpp | 34 +-- renderdoc/os/os_specific.h | 12 +- .../os/posix/android/android_stringio.cpp | 9 +- renderdoc/os/posix/posix_network.cpp | 18 +- renderdoc/os/posix/posix_stringio.cpp | 52 +++-- renderdoc/os/win32/win32_network.cpp | 5 +- renderdoc/os/win32/win32_stringio.cpp | 39 +++- renderdoc/replay/entry_points.cpp | 5 +- renderdoc/serialise/serialiser_tests.cpp | 16 ++ renderdoc/strings/utf8printf.cpp | 28 +-- 40 files changed, 500 insertions(+), 744 deletions(-) diff --git a/renderdoc/api/replay/shader_types.h b/renderdoc/api/replay/shader_types.h index 6cf41f790..67884b54c 100644 --- a/renderdoc/api/replay/shader_types.h +++ b/renderdoc/api/replay/shader_types.h @@ -176,7 +176,7 @@ struct ShaderVariable } ShaderVariable(const ShaderVariable &) = default; ShaderVariable &operator=(const ShaderVariable &) = default; - ShaderVariable(const char *n, float x, float y, float z, float w) + ShaderVariable(const rdcstr &n, float x, float y, float z, float w) { name = n; rows = 1; @@ -190,7 +190,7 @@ struct ShaderVariable value.f.z = z; value.f.w = w; } - ShaderVariable(const char *n, int x, int y, int z, int w) + ShaderVariable(const rdcstr &n, int x, int y, int z, int w) { name = n; rows = 1; @@ -204,7 +204,7 @@ struct ShaderVariable value.i.z = z; value.i.w = w; } - ShaderVariable(const char *n, uint32_t x, uint32_t y, uint32_t z, uint32_t w) + ShaderVariable(const rdcstr &n, uint32_t x, uint32_t y, uint32_t z, uint32_t w) { name = n; rows = 1; diff --git a/renderdoc/common/common.cpp b/renderdoc/common/common.cpp index 74ca2c066..87e803de5 100644 --- a/renderdoc/common/common.cpp +++ b/renderdoc/common/common.cpp @@ -30,6 +30,9 @@ #include "os/os_specific.h" #include "strings/string_utils.h" +int utf8printv(char *buf, size_t bufsize, const char *fmt, va_list args); +int utf8printf(char *str, size_t bufSize, const char *fmt, ...); + void rdcassert(const char *msg, const char *file, unsigned int line, const char *func) { rdclog_direct(FILL_AUTO_VALUE, FILL_AUTO_VALUE, LogType::Error, RDCLOG_PROJECT, file, line, @@ -357,16 +360,16 @@ void rdclog_direct(time_t utcTime, uint32_t pid, LogType type, const char *proje va_list args2; va_copy(args2, args); - char timestamp[64] = {0}; + rdcstr timestamp; #if ENABLED(INCLUDE_TIMESTAMP_IN_LOG) - StringFormat::sntimef(utcTime, timestamp, 63, "[%H:%M:%S] "); + timestamp = StringFormat::sntimef(utcTime, "[%H:%M:%S] "); #endif char location[64] = {0}; #if ENABLED(INCLUDE_LOCATION_IN_LOG) rdcstr loc; loc = get_basename(file); - StringFormat::snprintf(location, 63, "% 20s(%4d) - ", loc.c_str(), line); + utf8printf(location, 63, "% 20s(%4d) - ", loc.c_str(), line); #endif const char *typestr[(uint32_t)LogType::Count] = { @@ -384,8 +387,8 @@ void rdclog_direct(time_t utcTime, uint32_t pid, LogType type, const char *proje char *base = output; - int numWritten = StringFormat::snprintf(output, available, "% 4s %06u: %s%s%s - ", project, pid, - timestamp, location, typestr[(uint32_t)type]); + int numWritten = utf8printf(output, available, "% 4s %06u: %s%s%s - ", project, pid, + timestamp.c_str(), location, typestr[(uint32_t)type]); if(numWritten < 0) { @@ -403,7 +406,7 @@ void rdclog_direct(time_t utcTime, uint32_t pid, LogType type, const char *proje int totalWritten = numWritten; - numWritten = StringFormat::vsnprintf(output, available, fmt, args); + numWritten = utf8printv(output, available, fmt, args); totalWritten += numWritten; @@ -426,9 +429,9 @@ void rdclog_direct(time_t utcTime, uint32_t pid, LogType type, const char *proje oversizedBuffer = output = new char[available + 3]; base = output; - numWritten = StringFormat::snprintf(output, available, "% 4s %06u: %s%s%s - ", project, - Process::GetCurrentPID(), timestamp, location, - typestr[(uint32_t)type]); + numWritten = + utf8printf(output, available, "% 4s %06u: %s%s%s - ", project, Process::GetCurrentPID(), + timestamp.c_str(), location, typestr[(uint32_t)type]); output += numWritten; available -= numWritten; @@ -437,7 +440,7 @@ void rdclog_direct(time_t utcTime, uint32_t pid, LogType type, const char *proje noPrefixOutput = (output - 3 - (sizeof(typestr[(uint32_t)type]) - 1)); - numWritten = StringFormat::vsnprintf(output, available, fmt, args2); + numWritten = utf8printv(output, available, fmt, args2); output += numWritten; diff --git a/renderdoc/common/timing.h b/renderdoc/common/timing.h index 46c87e73c..9c6eb1598 100644 --- a/renderdoc/common/timing.h +++ b/renderdoc/common/timing.h @@ -103,21 +103,12 @@ private: class ScopedTimer { public: - ScopedTimer(const char *file, unsigned int line, const char *fmt, ...) + ScopedTimer(const char *file, unsigned int line, const rdcstr &msg) { m_File = file; m_Line = line; - va_list args; - va_start(args, fmt); - - char buf[1024]; - buf[1023] = 0; - StringFormat::vsnprintf(buf, 1023, fmt, args); - - m_Message = buf; - - va_end(args); + m_Message = msg; } ~ScopedTimer() @@ -133,4 +124,5 @@ private: PerformanceTimer m_Timer; }; -#define SCOPED_TIMER(...) ScopedTimer CONCAT(timer, __LINE__)(__FILE__, __LINE__, __VA_ARGS__); +#define SCOPED_TIMER(...) \ + ScopedTimer CONCAT(timer, __LINE__)(__FILE__, __LINE__, StringFormat::Fmt(__VA_ARGS__)); diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 3c0014517..308d09a32 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -1948,8 +1948,9 @@ bool WrappedID3D11Device::EndFrameCapture(void *dev, void *wnd) m_TextRenderer->SetOutputDimensions(swapper->GetWidth(), swapper->GetHeight()); m_TextRenderer->SetOutputWindow(swapper->GetHWND()); - m_TextRenderer->RenderText(0.0f, 0.0f, "Failed to capture frame %u: %s", - m_CapturedFrames.back().frameNumber, reasonString); + m_TextRenderer->RenderText( + 0.0f, 0.0f, StringFormat::Fmt("Failed to capture frame %u: %s", + m_CapturedFrames.back().frameNumber, reasonString)); } old.ApplyState(m_pImmediateContext); @@ -2263,8 +2264,7 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapper *swapper, UINT SyncInterval, U overlayText += StringFormat::Fmt(" %s\n", reasonString); } - if(!overlayText.empty()) - m_TextRenderer->RenderText(0.0f, 0.0f, overlayText.c_str()); + m_TextRenderer->RenderText(0.0f, 0.0f, overlayText); old.ApplyState(m_pImmediateContext); } diff --git a/renderdoc/driver/d3d11/d3d11_rendertext.cpp b/renderdoc/driver/d3d11/d3d11_rendertext.cpp index fb140e5d6..10f086af7 100644 --- a/renderdoc/driver/d3d11/d3d11_rendertext.cpp +++ b/renderdoc/driver/d3d11/d3d11_rendertext.cpp @@ -25,6 +25,7 @@ #include "d3d11_rendertext.h" #include "maths/matrix.h" #include "stb/stb_truetype.h" +#include "strings/string_utils.h" #include "d3d11_context.h" #include "d3d11_device.h" #include "d3d11_resources.h" @@ -341,38 +342,25 @@ void D3D11TextRenderer::SetOutputWindow(HWND w) } } -void D3D11TextRenderer::RenderText(float x, float y, const char *textfmt, ...) +void D3D11TextRenderer::RenderText(float x, float y, const rdcstr &text) { - static char tmpBuf[4096]; + rdcarray lines; + split(text, lines, '\n'); - va_list args; - va_start(args, textfmt); - StringFormat::vsnprintf(tmpBuf, 4095, textfmt, args); - tmpBuf[4095] = '\0'; - va_end(args); - - RenderTextInternal(x, y, tmpBuf); + for(const rdcstr &line : lines) + RenderTextInternal(x, y, line); } -void D3D11TextRenderer::RenderTextInternal(float x, float y, const char *text) +void D3D11TextRenderer::RenderTextInternal(float x, float y, const rdcstr &text) { - if(char *t = strchr((char *)text, '\n')) - { - *t = 0; - RenderTextInternal(x, y, text); - RenderTextInternal(x, y + 1.0f, t + 1); - *t = '\n'; + if(text.empty()) return; - } - if(strlen(text) == 0) - return; + RDCASSERT(text.size() < FONT_MAX_CHARS); if(!VS || !PS) return; - RDCASSERT(strlen(text) < FONT_MAX_CHARS); - FontCBuffer data = {}; data.TextPosition.x = x; @@ -421,14 +409,14 @@ void D3D11TextRenderer::RenderTextInternal(float x, float y, const char *text) { unsigned long *texs = (unsigned long *)mapped.pData; - for(size_t i = 0; i < strlen(text); i++) + for(size_t i = 0; i < text.size(); i++) texs[i * 4] = (text[i] - ' '); } else { Vec4f *texs = (Vec4f *)mapped.pData; - for(size_t i = 0; i < strlen(text); i++) + for(size_t i = 0; i < text.size(); i++) { texs[i * 6 + 0] = Vec4f(quadPos[0].x, quadPos[0].y, float(i), float(text[i] - ' ')); texs[i * 6 + 1] = Vec4f(quadPos[1].x, quadPos[1].y, float(i), float(text[i] - ' ')); @@ -487,8 +475,8 @@ void D3D11TextRenderer::RenderTextInternal(float x, float y, const char *text) m_pImmediateContext->OMSetBlendState(BlendState, factor, 0xffffffff); if(modern) - m_pImmediateContext->DrawInstanced(4, (uint32_t)strlen(text), 0, 0); + m_pImmediateContext->DrawInstanced(4, (uint32_t)text.size(), 0, 0); else - m_pImmediateContext->Draw(6 * (uint32_t)strlen(text), 0); + m_pImmediateContext->Draw(6 * (uint32_t)text.size(), 0); } } diff --git a/renderdoc/driver/d3d11/d3d11_rendertext.h b/renderdoc/driver/d3d11/d3d11_rendertext.h index cf6d28c74..1f5b25ece 100644 --- a/renderdoc/driver/d3d11/d3d11_rendertext.h +++ b/renderdoc/driver/d3d11/d3d11_rendertext.h @@ -45,7 +45,7 @@ public: int GetHeight() { return RDCMAX(1, m_height); } void SetOutputWindow(HWND w); - void RenderText(float x, float y, const char *textfmt, ...); + void RenderText(float x, float y, const rdcstr &text); private: int m_width = 1, m_height = 1; @@ -54,7 +54,7 @@ private: WrappedID3D11Device *m_pDevice = NULL; WrappedID3D11DeviceContext *m_pImmediateContext = NULL; - void RenderTextInternal(float x, float y, const char *text); + void RenderTextInternal(float x, float y, const rdcstr &text); static const int FONT_TEX_WIDTH = 256; static const int FONT_TEX_HEIGHT = 128; diff --git a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp index 4336855c7..451acbda6 100644 --- a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp +++ b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp @@ -766,12 +766,11 @@ bool D3D11DebugAPIWrapper::CalculateSampleGather( DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_UNUSED }; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%s4", typeStr[resourceData.retType]); + rdcstr type = StringFormat::Fmt("%s4", typeStr[resourceData.retType]); if(retFmt == DXGI_FORMAT_UNKNOWN) { - funcRet = buf; + funcRet = type; retFmt = fmts[resourceData.retType]; } @@ -779,13 +778,10 @@ bool D3D11DebugAPIWrapper::CalculateSampleGather( resourceData.dim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY) { if(resourceData.sampleCount > 0) - StringFormat::snprintf(buf, 63, "%s4, %d", typeStr[resourceData.retType], - resourceData.sampleCount); + type += StringFormat::Fmt(", %d", resourceData.sampleCount); } - textureDecl += "<"; - textureDecl += buf; - textureDecl += "> t"; + textureDecl += "<" + type + "> t"; } char *formats[4][2] = { @@ -870,66 +866,35 @@ bool D3D11DebugAPIWrapper::CalculateSampleGather( } } - char buf[256] = {0}; - char buf2[256] = {0}; - char buf3[256] = {0}; + rdcstr texcoords; // because of unions in .value we can pass the float versions and printf will interpret it as // the right type according to formats if(texcoordType == 0) - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, - uv.value.f.y, uv.value.f.z, uv.value.f.w); + texcoords = StringFormat::Fmt(formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, + uv.value.f.y, uv.value.f.z, uv.value.f.w); else - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.i.x, - uv.value.i.y, uv.value.i.z, uv.value.i.w); - - if(ddxType == 0) - StringFormat::snprintf(buf2, 255, formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.f.x, - ddxCalc.value.f.y, ddxCalc.value.f.z, ddxCalc.value.f.w); - else - StringFormat::snprintf(buf2, 255, formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.i.x, - ddxCalc.value.i.y, ddxCalc.value.i.z, ddxCalc.value.i.w); - - if(ddyType == 0) - StringFormat::snprintf(buf3, 255, formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.f.x, - ddyCalc.value.f.y, ddyCalc.value.f.z, ddyCalc.value.f.w); - else - StringFormat::snprintf(buf3, 255, formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.i.x, - ddyCalc.value.i.y, ddyCalc.value.i.z, ddyCalc.value.i.w); - - rdcstr texcoords = buf; - rdcstr ddx = buf2; - rdcstr ddy = buf3; - - if(opcode == OPCODE_LD_MS) - { - StringFormat::snprintf(buf, 255, formats[0][1], multisampleIndex); - } - - rdcstr sampleIdx = buf; + texcoords = StringFormat::Fmt(formats[texdim + texdimOffs - 1][texcoordType], uv.value.i.x, + uv.value.i.y, uv.value.i.z, uv.value.i.w); rdcstr offsets = ""; if(useOffsets) { if(offsetDim == 1) - StringFormat::snprintf(buf, 255, ", int(%d)", texelOffsets[0]); + offsets = StringFormat::Fmt(", int(%d)", texelOffsets[0]); else if(offsetDim == 2) - StringFormat::snprintf(buf, 255, ", int2(%d, %d)", texelOffsets[0], texelOffsets[1]); + offsets = StringFormat::Fmt(", int2(%d, %d)", texelOffsets[0], texelOffsets[1]); else if(offsetDim == 3) - StringFormat::snprintf(buf, 255, ", int3(%d, %d, %d)", texelOffsets[0], texelOffsets[1], - texelOffsets[2]); + offsets = + StringFormat::Fmt(", int3(%d, %d, %d)", texelOffsets[0], texelOffsets[1], texelOffsets[2]); // texdim == 4 is cube arrays, no offset supported - - offsets = buf; } char elems[] = "xyzw"; rdcstr strSwizzle = "."; for(int i = 0; i < 4; ++i) - { strSwizzle += elems[swizzle[i]]; - } rdcstr strGatherChannel; switch(gatherChannel) @@ -948,120 +913,134 @@ bool D3D11DebugAPIWrapper::CalculateSampleGather( if(opcode == OPCODE_SAMPLE || opcode == OPCODE_SAMPLE_B || opcode == OPCODE_SAMPLE_D) { - sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + rdcstr ddx; + + if(ddxType == 0) + ddx = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.f.x, + ddxCalc.value.f.y, ddxCalc.value.f.z, ddxCalc.value.f.w); + else + ddx = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.i.x, + ddxCalc.value.i.y, ddxCalc.value.i.z, ddxCalc.value.i.w); + + rdcstr ddy; + + if(ddyType == 0) + ddy = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.f.x, + ddyCalc.value.f.y, ddyCalc.value.f.z, ddyCalc.value.f.w); + else + ddy = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.i.x, + ddyCalc.value.i.y, ddyCalc.value.i.z, ddyCalc.value.i.w); + + sampleProgram = StringFormat::Fmt("%s : register(t0);\n%s : register(s0);\n\n", + textureDecl.c_str(), samplerDecl.c_str()); + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; sampleProgram += - "t.SampleGrad(s, " + texcoords + ", " + ddx + ", " + ddy + offsets + ")" + strSwizzle + ";"; - sampleProgram += "\n}\n"; + StringFormat::Fmt("return t.SampleGrad(s, %s, %s, %s %s)%s;\n", texcoords.c_str(), + ddx.c_str(), ddy.c_str(), offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } else if(opcode == OPCODE_SAMPLE_L) { - // lod selection - StringFormat::snprintf(buf, 255, "%.10f", lodOrCompareValue); - - sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.SampleLevel(s, " + texcoords + ", " + buf + offsets + ")" + strSwizzle + ";"; - sampleProgram += "\n}\n"; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n%s : register(s0);\n\n", + textureDecl.c_str(), samplerDecl.c_str()); + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += + StringFormat::Fmt("return t.SampleLevel(s, %s, %.10f %s)%s;\n", texcoords.c_str(), + lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } else if(opcode == OPCODE_SAMPLE_C || opcode == OPCODE_LOD) { // these operations need derivatives but have no hlsl function to call to provide them, so // we fake it in the vertex shader - rdcstr uvDim = "1"; - uvDim[0] += char(texdim + texdimOffs - 1); + rdcstr uvdecl = StringFormat::Fmt("float%d uv : uvs", texdim + texdimOffs); - vsProgram = "void main(uint id : SV_VertexID, out float4 pos : SV_Position, out float" + uvDim + - " uv : uvs) {\n"; + vsProgram = + "void main(uint id : SV_VertexID, out float4 pos : SV_Position, out " + uvdecl + ") {\n"; - StringFormat::snprintf( - buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x + ddyCalc.value.f.x * 2.0f, uv.value.f.y + ddyCalc.value.f.y * 2.0f, - uv.value.f.z + ddyCalc.value.f.z * 2.0f, uv.value.f.w + ddyCalc.value.f.w * 2.0f); + rdcstr uvPlusDDX = StringFormat::Fmt( + formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x + ddyCalc.value.f.x * 2.0f, + uv.value.f.y + ddyCalc.value.f.y * 2.0f, uv.value.f.z + ddyCalc.value.f.z * 2.0f, + uv.value.f.w + ddyCalc.value.f.w * 2.0f); - vsProgram += "if(id == 0) uv = " + rdcstr(buf) + ";\n"; - - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, - uv.value.f.y, uv.value.f.z, uv.value.f.w); - - vsProgram += "if(id == 1) uv = " + rdcstr(buf) + ";\n"; - - StringFormat::snprintf( - buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x + ddxCalc.value.f.x * 2.0f, uv.value.f.y + ddxCalc.value.f.y * 2.0f, - uv.value.f.z + ddxCalc.value.f.z * 2.0f, uv.value.f.w + ddxCalc.value.f.w * 2.0f); - - vsProgram += "if(id == 2) uv = " + rdcstr(buf) + ";\n"; + rdcstr uvPlusDDY = StringFormat::Fmt( + formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x + ddxCalc.value.f.x * 2.0f, + uv.value.f.y + ddxCalc.value.f.y * 2.0f, uv.value.f.z + ddxCalc.value.f.z * 2.0f, + uv.value.f.w + ddxCalc.value.f.w * 2.0f); + vsProgram += "if(id == 0) uv = " + uvPlusDDX + ";\n"; + vsProgram += "if(id == 1) uv = " + texcoords + ";\n"; + vsProgram += "if(id == 2) uv = " + uvPlusDDY + ";\n"; vsProgram += "pos = float4((id == 2) ? 3.0f : -1.0f, (id == 0) ? -3.0f : 1.0f, 0.5, 1.0);\n"; vsProgram += "}"; if(opcode == OPCODE_SAMPLE_C) { - // comparison value - StringFormat::snprintf(buf, 255, "%.10f", lodOrCompareValue); - - sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; - sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + - " uv : uvs) : SV_Target0\n{\n"; - sampleProgram += "return t.SampleCmpLevelZero(s, uv, " + rdcstr(buf) + offsets + ").xxxx;"; - sampleProgram += "\n}\n"; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n%s : register(s0);\n\n", + textureDecl.c_str(), samplerDecl.c_str()); + sampleProgram += + funcRet + " main(float4 pos : SV_Position, " + uvdecl + ") : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("return t.SampleCmpLevelZero(s, uv, %.10f %s).xxxx;\n", + lodOrCompareValue, offsets.c_str()); + sampleProgram += "}\n"; } else if(opcode == OPCODE_LOD) { - sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; - sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + - " uv : uvs) : SV_Target0\n{\n"; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n%s : register(s0);\n\n", + textureDecl.c_str(), samplerDecl.c_str()); sampleProgram += - "return float4(t.CalculateLevelOfDetail(s, uv), t.CalculateLevelOfDetailUnclamped(s, " - "uv), 0.0f, 0.0f);"; - sampleProgram += "\n}\n"; + funcRet + " main(float4 pos : SV_Position, " + uvdecl + ") : SV_Target0\n{\n"; + sampleProgram += + "return float4(t.CalculateLevelOfDetail(s, uv),\n" + " t.CalculateLevelOfDetailUnclamped(s, uv),\n" + " 0.0f, 0.0f);\n"; + sampleProgram += "}\n"; } } else if(opcode == OPCODE_SAMPLE_C_LZ) { - // comparison value - StringFormat::snprintf(buf, 255, "%.10f", lodOrCompareValue); - - sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n%s : register(s0);\n\n", + textureDecl.c_str(), samplerDecl.c_str()); + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; sampleProgram += - "t.SampleCmpLevelZero(s, " + texcoords + ", " + buf + offsets + ")" + strSwizzle + ";"; - sampleProgram += "\n}\n"; + StringFormat::Fmt("return t.SampleCmpLevelZero(s, %s, %.10f %s)%s;\n", texcoords.c_str(), + lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } else if(opcode == OPCODE_LD) { - sampleProgram = textureDecl + " : register(t0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.Load(" + texcoords + offsets + ")" + strSwizzle + ";"; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n\n", textureDecl.c_str()); + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += "return t.Load(" + texcoords + offsets + ")" + strSwizzle + ";"; sampleProgram += "\n}\n"; } else if(opcode == OPCODE_LD_MS) { - sampleProgram = textureDecl + " : register(t0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.Load(" + texcoords + ", " + sampleIdx + offsets + ")" + strSwizzle + ";"; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n\n", textureDecl.c_str()); + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("t.Load(%s, int(%d) %s)%s;\n", texcoords.c_str(), + multisampleIndex, offsets.c_str(), strSwizzle.c_str()); sampleProgram += "\n}\n"; } else if(opcode == OPCODE_GATHER4 || opcode == OPCODE_GATHER4_PO) { - sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += - "t.Gather" + strGatherChannel + "(s, " + texcoords + offsets + ")" + strSwizzle + ";"; - sampleProgram += "\n}\n"; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n%s : register(s0);\n\n", + textureDecl.c_str(), samplerDecl.c_str()); + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("return t.Gather%s(s, %s %s)%s;\n", strGatherChannel.c_str(), + texcoords.c_str(), offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } else if(opcode == OPCODE_GATHER4_C || opcode == OPCODE_GATHER4_PO_C) { - // comparison value - StringFormat::snprintf(buf, 255, ", %.10f", lodOrCompareValue); - - sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.GatherCmp" + strGatherChannel + "(s, " + texcoords + buf + offsets + ")" + - strSwizzle + ";"; - sampleProgram += "\n}\n"; + sampleProgram = StringFormat::Fmt("%s : register(t0);\n%s : register(s0);\n\n", + textureDecl.c_str(), samplerDecl.c_str()); + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("return t.GatherCmp%s(s, %s, %.10f %s)%s;\n", + strGatherChannel.c_str(), texcoords.c_str(), + lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } ID3D11VertexShader *vs = diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index 832de5346..2a2ff0bc4 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -737,10 +737,7 @@ rdcstr PIX3SprintfParams(const rdcstr &Format, const UINT64 *pData) // numerical values else { - static const UINT MAX_CHARACTERS_FOR_VALUE = 32; - char formattedValue[MAX_CHARACTERS_FOR_VALUE]; - StringFormat::snprintf(formattedValue, MAX_CHARACTERS_FOR_VALUE, formatPart.c_str(), *pData); - finalString += formattedValue; + finalString += StringFormat::Fmt(formatPart.c_str(), *pData); ++pData; } diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 517f8a5ac..b61768e84 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -1590,8 +1590,7 @@ HRESULT WrappedID3D12Device::Present(ID3D12GraphicsCommandList *pOverlayCommandL if(m_InvalidPSO) overlayText += "ERROR: Invalid PSO created, likely using DXIL which is not supported.\n"; - if(!overlayText.empty()) - m_TextRenderer->RenderText(list, 0.0f, 0.0f, overlayText.c_str()); + m_TextRenderer->RenderText(list, 0.0f, 0.0f, overlayText); // transition backbuffer back again std::swap(barrier.Transition.StateBefore, barrier.Transition.StateAfter); diff --git a/renderdoc/driver/d3d12/d3d12_rendertext.cpp b/renderdoc/driver/d3d12/d3d12_rendertext.cpp index a0f015a4a..72b4879be 100644 --- a/renderdoc/driver/d3d12/d3d12_rendertext.cpp +++ b/renderdoc/driver/d3d12/d3d12_rendertext.cpp @@ -27,6 +27,7 @@ #include "maths/matrix.h" #include "maths/vec.h" #include "stb/stb_truetype.h" +#include "strings/string_utils.h" #include "d3d12_device.h" #include "d3d12_shader_cache.h" @@ -444,35 +445,22 @@ D3D12TextRenderer::~D3D12TextRenderer() } void D3D12TextRenderer::RenderText(ID3D12GraphicsCommandList *list, float x, float y, - const char *textfmt, ...) + const rdcstr &text) { - static char tmpBuf[4096]; + rdcarray lines; + split(text, lines, '\n'); - va_list args; - va_start(args, textfmt); - StringFormat::vsnprintf(tmpBuf, 4095, textfmt, args); - tmpBuf[4095] = '\0'; - va_end(args); - - RenderTextInternal(list, x, y, tmpBuf); + for(const rdcstr &line : lines) + RenderTextInternal(list, x, y, line); } void D3D12TextRenderer::RenderTextInternal(ID3D12GraphicsCommandList *list, float x, float y, - const char *text) + const rdcstr &text) { - if(char *t = strchr((char *)text, '\n')) - { - *t = 0; - RenderTextInternal(list, x, y, text); - RenderTextInternal(list, x, y + 1.0f, t + 1); - *t = '\n'; - return; - } - - if(strlen(text) == 0) + if(text.empty()) return; - RDCASSERT(strlen(text) < FONT_MAX_CHARS); + RDCASSERT(text.size() < FONT_MAX_CHARS); FontCBuffer data = {}; @@ -508,7 +496,7 @@ void D3D12TextRenderer::RenderTextInternal(ID3D12GraphicsCommandList *list, floa Constants->Unmap(0, &range); } - size_t chars = strlen(text); + size_t chars = text.size(); size_t charOffset = CharOffset; @@ -530,7 +518,7 @@ void D3D12TextRenderer::RenderTextInternal(ID3D12GraphicsCommandList *list, floa texs += charOffset * 4; - for(size_t i = 0; i < strlen(text); i++) + for(size_t i = 0; i < chars; i++) texs[i * 4] = (text[i] - ' '); CharBuffer->Unmap(0, NULL); @@ -563,7 +551,7 @@ void D3D12TextRenderer::RenderTextInternal(ID3D12GraphicsCommandList *list, floa 2, CharBuffer->GetGPUVirtualAddress() + charOffset * sizeof(Vec4f)); list->SetGraphicsRootDescriptorTable(3, descHeap->GetGPUDescriptorHandleForHeapStart()); - list->DrawInstanced(4, (uint32_t)strlen(text), 0, 0); + list->DrawInstanced(4, (uint32_t)chars, 0, 0); } ConstRingIdx++; diff --git a/renderdoc/driver/d3d12/d3d12_rendertext.h b/renderdoc/driver/d3d12/d3d12_rendertext.h index 79f203ca7..370a678d6 100644 --- a/renderdoc/driver/d3d12/d3d12_rendertext.h +++ b/renderdoc/driver/d3d12/d3d12_rendertext.h @@ -47,7 +47,7 @@ public: } int GetWidth() { return RDCMAX(1, m_width); } int GetHeight() { return RDCMAX(1, m_height); } - void RenderText(ID3D12GraphicsCommandList *list, float x, float y, const char *textfmt, ...); + void RenderText(ID3D12GraphicsCommandList *list, float x, float y, const rdcstr &text); private: int m_width = 1, m_height = 1; @@ -59,7 +59,7 @@ private: FMTNUM_BACKBUFFER, } m_BBFmtIdx; - void RenderTextInternal(ID3D12GraphicsCommandList *list, float x, float y, const char *text); + void RenderTextInternal(ID3D12GraphicsCommandList *list, float x, float y, const rdcstr &text); static const int FONT_TEX_WIDTH = 256; static const int FONT_TEX_HEIGHT = 128; diff --git a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp index 0ca46df03..ad94bca92 100644 --- a/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp +++ b/renderdoc/driver/d3d12/d3d12_shaderdebug.cpp @@ -254,12 +254,11 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_UNUSED }; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%s4", typeStr[resourceData.retType]); + rdcstr type = StringFormat::Fmt("%s4", typeStr[resourceData.retType]); if(retFmt == DXGI_FORMAT_UNKNOWN) { - funcRet = buf; + funcRet = type; retFmt = fmts[resourceData.retType]; } @@ -267,13 +266,10 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( resourceData.dim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY) { if(resourceData.sampleCount > 0) - StringFormat::snprintf(buf, 63, "%s4, %d", typeStr[resourceData.retType], - resourceData.sampleCount); + type += StringFormat::Fmt(", %d", resourceData.sampleCount); } - textureDecl += "<"; - textureDecl += buf; - textureDecl += "> t"; + textureDecl += "<" + type + "> t"; } char *formats[4][2] = { @@ -358,65 +354,35 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( } } - char buf[256] = {0}; - char buf2[256] = {0}; - char buf3[256] = {0}; + rdcstr texcoords; // because of unions in .value we can pass the float versions and printf will interpret it as // the right type according to formats if(texcoordType == 0) - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, - uv.value.f.y, uv.value.f.z, uv.value.f.w); + texcoords = StringFormat::Fmt(formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, + uv.value.f.y, uv.value.f.z, uv.value.f.w); else - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.i.x, - uv.value.i.y, uv.value.i.z, uv.value.i.w); + texcoords = StringFormat::Fmt(formats[texdim + texdimOffs - 1][texcoordType], uv.value.i.x, + uv.value.i.y, uv.value.i.z, uv.value.i.w); - if(ddxType == 0) - StringFormat::snprintf(buf2, 255, formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.f.x, - ddxCalc.value.f.y, ddxCalc.value.f.z, ddxCalc.value.f.w); - else - StringFormat::snprintf(buf2, 255, formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.i.x, - ddxCalc.value.i.y, ddxCalc.value.i.z, ddxCalc.value.i.w); - - if(ddyType == 0) - StringFormat::snprintf(buf3, 255, formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.f.x, - ddyCalc.value.f.y, ddyCalc.value.f.z, ddyCalc.value.f.w); - else - StringFormat::snprintf(buf3, 255, formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.i.x, - ddyCalc.value.i.y, ddyCalc.value.i.z, ddyCalc.value.i.w); - - rdcstr texcoords = buf; - rdcstr ddx = buf2; - rdcstr ddy = buf3; - - if(opcode == OPCODE_LD_MS) - { - StringFormat::snprintf(buf, 255, formats[0][1], multisampleIndex); - } - - rdcstr sampleIdx = buf; rdcstr offsets = ""; if(useOffsets) { if(offsetDim == 1) - StringFormat::snprintf(buf, 255, ", int(%d)", texelOffsets[0]); + offsets = StringFormat::Fmt(", int(%d)", texelOffsets[0]); else if(offsetDim == 2) - StringFormat::snprintf(buf, 255, ", int2(%d, %d)", texelOffsets[0], texelOffsets[1]); + offsets = StringFormat::Fmt(", int2(%d, %d)", texelOffsets[0], texelOffsets[1]); else if(offsetDim == 3) - StringFormat::snprintf(buf, 255, ", int3(%d, %d, %d)", texelOffsets[0], texelOffsets[1], - texelOffsets[2]); + offsets = + StringFormat::Fmt(", int3(%d, %d, %d)", texelOffsets[0], texelOffsets[1], texelOffsets[2]); // texdim == 4 is cube arrays, no offset supported - - offsets = buf; } char elems[] = "xyzw"; rdcstr strSwizzle = "."; for(int i = 0; i < 4; ++i) - { strSwizzle += elems[swizzle[i]]; - } rdcstr strGatherChannel; switch(gatherChannel) @@ -438,12 +404,30 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( if(opcode == OPCODE_SAMPLE || opcode == OPCODE_SAMPLE_B || opcode == OPCODE_SAMPLE_D) { + rdcstr ddx; + + if(ddxType == 0) + ddx = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.f.x, + ddxCalc.value.f.y, ddxCalc.value.f.z, ddxCalc.value.f.w); + else + ddx = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.i.x, + ddxCalc.value.i.y, ddxCalc.value.i.z, ddxCalc.value.i.w); + + rdcstr ddy; + + if(ddyType == 0) + ddy = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.f.x, + ddyCalc.value.f.y, ddyCalc.value.f.z, ddyCalc.value.f.w); + else + ddy = StringFormat::Fmt(formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.i.x, + ddyCalc.value.i.y, ddyCalc.value.i.z, ddyCalc.value.i.w); + sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += StringFormat::Fmt("t.SampleGrad(s, %s, %s, %s%s)%s;", texcoords.c_str(), + sampleProgram += StringFormat::Fmt("t.SampleGrad(s, %s, %s, %s %s)%s;\n", texcoords.c_str(), ddx.c_str(), ddy.c_str(), offsets.c_str(), strSwizzle.c_str()); - sampleProgram += "\n}\n"; + sampleProgram += "}\n"; } else if(opcode == OPCODE_SAMPLE_L) { @@ -451,40 +435,33 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += StringFormat::Fmt("t.SampleLevel(s, %s, %.10f%s)%s;", texcoords.c_str(), + sampleProgram += StringFormat::Fmt("t.SampleLevel(s, %s, %.10f %s)%s;\n", texcoords.c_str(), lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); - sampleProgram += "\n}\n"; + sampleProgram += "}\n"; } else if(opcode == OPCODE_SAMPLE_C || opcode == OPCODE_LOD) { // these operations need derivatives but have no hlsl function to call to provide them, so // we fake it in the vertex shader - rdcstr uvDim = "1"; - uvDim[0] += char(texdim + texdimOffs - 1); + rdcstr uvdecl = StringFormat::Fmt("float%d uv : uvs", texdim + texdimOffs); - vsProgram = "void main(uint id : SV_VertexID, out float4 pos : SV_Position, out float" + uvDim + - " uv : uvs) {\n"; + vsProgram = + "void main(uint id : SV_VertexID, out float4 pos : SV_Position, out " + uvdecl + ") {\n"; - StringFormat::snprintf( - buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x + ddyCalc.value.f.x * 2.0f, uv.value.f.y + ddyCalc.value.f.y * 2.0f, - uv.value.f.z + ddyCalc.value.f.z * 2.0f, uv.value.f.w + ddyCalc.value.f.w * 2.0f); + rdcstr uvPlusDDX = StringFormat::Fmt( + formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x + ddyCalc.value.f.x * 2.0f, + uv.value.f.y + ddyCalc.value.f.y * 2.0f, uv.value.f.z + ddyCalc.value.f.z * 2.0f, + uv.value.f.w + ddyCalc.value.f.w * 2.0f); - vsProgram += "if(id == 0) uv = " + rdcstr(buf) + ";\n"; - - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, - uv.value.f.y, uv.value.f.z, uv.value.f.w); - - vsProgram += "if(id == 1) uv = " + rdcstr(buf) + ";\n"; - - StringFormat::snprintf( - buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x + ddxCalc.value.f.x * 2.0f, uv.value.f.y + ddxCalc.value.f.y * 2.0f, - uv.value.f.z + ddxCalc.value.f.z * 2.0f, uv.value.f.w + ddxCalc.value.f.w * 2.0f); - - vsProgram += "if(id == 2) uv = " + rdcstr(buf) + ";\n"; + rdcstr uvPlusDDY = StringFormat::Fmt( + formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x + ddxCalc.value.f.x * 2.0f, + uv.value.f.y + ddxCalc.value.f.y * 2.0f, uv.value.f.z + ddxCalc.value.f.z * 2.0f, + uv.value.f.w + ddxCalc.value.f.w * 2.0f); + vsProgram += "if(id == 0) uv = " + uvPlusDDX + ";\n"; + vsProgram += "if(id == 1) uv = " + texcoords + ";\n"; + vsProgram += "if(id == 2) uv = " + uvPlusDDY + ";\n"; vsProgram += "pos = float4((id == 2) ? 3.0f : -1.0f, (id == 0) ? -3.0f : 1.0f, 0.5, 1.0);\n"; vsProgram += "}"; @@ -493,22 +470,23 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( // comparison value sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); - sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + - " uv : uvs) : SV_Target0\n{\n"; - sampleProgram += StringFormat::Fmt("return t.SampleCmpLevelZero(s, uv, %.10f%s).xxxx;", + sampleProgram += + funcRet + " main(float4 pos : SV_Position, " + uvdecl + ") : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("t.SampleCmpLevelZero(s, uv, %.10f %s).xxxx;\n", lodOrCompareValue, offsets.c_str()); - sampleProgram += "\n}\n"; + sampleProgram += "}\n"; } else if(opcode == OPCODE_LOD) { sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); - sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + - " uv : uvs) : SV_Target0\n{\n"; sampleProgram += - "return float4(t.CalculateLevelOfDetail(s, uv), t.CalculateLevelOfDetailUnclamped(s, " - "uv), 0.0f, 0.0f);"; - sampleProgram += "\n}\n"; + funcRet + " main(float4 pos : SV_Position, " + uvdecl + ") : SV_Target0\n{\n"; + sampleProgram += + "return float4(t.CalculateLevelOfDetail(s, uv),\n" + " t.CalculateLevelOfDetailUnclamped(s, uv),\n" + " 0.0f, 0.0f);\n"; + sampleProgram += "}\n"; } } else if(opcode == OPCODE_SAMPLE_C_LZ) @@ -516,44 +494,46 @@ bool D3D12DebugAPIWrapper::CalculateSampleGather( // comparison value sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += StringFormat::Fmt("t.SampleCmpLevelZero(s, %s, %.10f%s)%s;", texcoords.c_str(), - lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); - sampleProgram += "\n}\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += + StringFormat::Fmt("return t.SampleCmpLevelZero(s, %s, %.10f %s)%s;\n", texcoords.c_str(), + lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } else if(opcode == OPCODE_LD) { sampleProgram = StringFormat::Fmt("%s : register(t%u);\n\n", textureDecl.c_str(), texSlot); - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.Load(" + texcoords + offsets + ")" + strSwizzle + ";"; + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += "return t.Load(" + texcoords + offsets + ")" + strSwizzle + ";"; sampleProgram += "\n}\n"; } else if(opcode == OPCODE_LD_MS) { sampleProgram = StringFormat::Fmt("%s : register(t%u);\n\n", textureDecl.c_str(), texSlot); - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.Load(" + texcoords + ", " + sampleIdx + offsets + ")" + strSwizzle + ";"; + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("t.Load(%s, int(%d) %s)%s;\n", texcoords.c_str(), + multisampleIndex, offsets.c_str(), strSwizzle.c_str()); sampleProgram += "\n}\n"; } else if(opcode == OPCODE_GATHER4 || opcode == OPCODE_GATHER4_PO) { sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += - "t.Gather" + strGatherChannel + "(s, " + texcoords + offsets + ")" + strSwizzle + ";"; - sampleProgram += "\n}\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("return t.Gather%s(s, %s %s)%s;\n", strGatherChannel.c_str(), + texcoords.c_str(), offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } else if(opcode == OPCODE_GATHER4_C || opcode == OPCODE_GATHER4_PO_C) { // comparison value sampleProgram = StringFormat::Fmt("%s : register(t%u);\n%s : register(s%u);\n\n", textureDecl.c_str(), texSlot, samplerDecl.c_str(), sampSlot); - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += StringFormat::Fmt("t.GatherCmp%s(s, %s, %.10f%s)%s;", strGatherChannel.c_str(), - texcoords.c_str(), lodOrCompareValue, offsets.c_str(), - strSwizzle.c_str()); - sampleProgram += "\n}\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\n"; + sampleProgram += StringFormat::Fmt("return t.GatherCmp%s(s, %s, %.10f %s)%s;\n", + strGatherChannel.c_str(), texcoords.c_str(), + lodOrCompareValue, offsets.c_str(), strSwizzle.c_str()); + sampleProgram += "}\n"; } // Create VS/PS to fetch the sample diff --git a/renderdoc/driver/d3d8/d3d8_debug.cpp b/renderdoc/driver/d3d8/d3d8_debug.cpp index a935dce24..9d89ef960 100644 --- a/renderdoc/driver/d3d8/d3d8_debug.cpp +++ b/renderdoc/driver/d3d8/d3d8_debug.cpp @@ -25,6 +25,7 @@ #include "d3d8_debug.h" #include "os/os_specific.h" #include "stb/stb_truetype.h" +#include "strings/string_utils.h" D3D8DebugManager::D3D8DebugManager(WrappedD3DDevice8 *wrapper) : m_WrappedDevice(wrapper), m_fvf(D3DFVF_XYZ | D3DFVF_TEX1) @@ -127,34 +128,21 @@ void D3D8DebugManager::SetOutputWindow(HWND w) // m_supersamplingY = float(m_height) / float(rect.bottom - rect.top); } -void D3D8DebugManager::RenderText(float x, float y, const char *textfmt, ...) +void D3D8DebugManager::RenderText(float x, float y, const rdcstr &text) { - static char tmpBuf[4096]; + rdcarray lines; + split(text, lines, '\n'); - va_list args; - va_start(args, textfmt); - StringFormat::vsnprintf(tmpBuf, 4095, textfmt, args); - tmpBuf[4095] = '\0'; - va_end(args); - - RenderTextInternal(x, y, tmpBuf); + for(const rdcstr &line : lines) + RenderTextInternal(x, y, line); } -void D3D8DebugManager::RenderTextInternal(float x, float y, const char *text) +void D3D8DebugManager::RenderTextInternal(float x, float y, const rdcstr &text) { - if(char *t = strchr((char *)text, '\n')) - { - *t = 0; - RenderTextInternal(x, y, text); - RenderTextInternal(x, y + 1.0f, t + 1); - *t = '\n'; - return; - } - - if(strlen(text) == 0) + if(text.empty()) return; - RDCASSERT(strlen(text) < FONT_MAX_CHARS); + RDCASSERT(text.size() < FONT_MAX_CHARS); // transforms float width = (float)m_width; @@ -265,7 +253,7 @@ void D3D8DebugManager::RenderTextInternal(float x, float y, const char *text) Quad background; UINT triangleCount = 0; { - UINT quadCount = (UINT)strlen(text); // calculate string length + UINT quadCount = (UINT)text.size(); // calculate string length triangleCount = quadCount * 2; // create text VB diff --git a/renderdoc/driver/d3d8/d3d8_debug.h b/renderdoc/driver/d3d8/d3d8_debug.h index 9b56a1fec..5fb82f517 100644 --- a/renderdoc/driver/d3d8/d3d8_debug.h +++ b/renderdoc/driver/d3d8/d3d8_debug.h @@ -36,7 +36,7 @@ public: D3D8DebugManager(WrappedD3DDevice8 *wrapper); ~D3D8DebugManager(); - void RenderText(float x, float y, const char *textfmt, ...); + void RenderText(float x, float y, const rdcstr &text); void SetOutputDimensions(int w, int h) { @@ -49,7 +49,7 @@ public: bool InitFontRendering(); void ShutdownFontRendering(); - void RenderTextInternal(float x, float y, const char *text); + void RenderTextInternal(float x, float y, const rdcstr &text); static const int FONT_TEX_WIDTH = 256; static const int FONT_TEX_HEIGHT = 128; diff --git a/renderdoc/driver/d3d8/d3d8_device.cpp b/renderdoc/driver/d3d8/d3d8_device.cpp index e90afcbf1..c650c26f7 100644 --- a/renderdoc/driver/d3d8/d3d8_device.cpp +++ b/renderdoc/driver/d3d8/d3d8_device.cpp @@ -283,8 +283,7 @@ HRESULT __stdcall WrappedD3DDevice8::Present(CONST RECT *pSourceRect, CONST RECT overlayText += "Captures not supported with D3D8\n"; - if(!overlayText.empty()) - GetDebugManager()->RenderText(0.0f, 0.0f, overlayText.c_str()); + GetDebugManager()->RenderText(0.0f, 0.0f, overlayText); stateBlockRes = m_device->ApplyStateBlock(stateBlock); res |= m_device->EndScene(); diff --git a/renderdoc/driver/d3d9/d3d9_debug.cpp b/renderdoc/driver/d3d9/d3d9_debug.cpp index 7d654cf13..636bb0bfa 100644 --- a/renderdoc/driver/d3d9/d3d9_debug.cpp +++ b/renderdoc/driver/d3d9/d3d9_debug.cpp @@ -25,6 +25,7 @@ #include "d3d9_debug.h" #include "os/os_specific.h" #include "stb/stb_truetype.h" +#include "strings/string_utils.h" D3D9DebugManager::D3D9DebugManager(WrappedD3DDevice9 *wrapper) : m_WrappedDevice(wrapper), m_fvf(D3DFVF_XYZ | D3DFVF_TEX1) @@ -127,34 +128,21 @@ void D3D9DebugManager::SetOutputWindow(HWND w) // m_supersamplingY = float(m_height) / float(rect.bottom - rect.top); } -void D3D9DebugManager::RenderText(float x, float y, const char *textfmt, ...) +void D3D9DebugManager::RenderText(float x, float y, const rdcstr &text) { - static char tmpBuf[4096]; + rdcarray lines; + split(text, lines, '\n'); - va_list args; - va_start(args, textfmt); - StringFormat::vsnprintf(tmpBuf, 4095, textfmt, args); - tmpBuf[4095] = '\0'; - va_end(args); - - RenderTextInternal(x, y, tmpBuf); + for(const rdcstr &line : lines) + RenderTextInternal(x, y, line); } -void D3D9DebugManager::RenderTextInternal(float x, float y, const char *text) +void D3D9DebugManager::RenderTextInternal(float x, float y, const rdcstr &text) { - if(char *t = strchr((char *)text, '\n')) - { - *t = 0; - RenderTextInternal(x, y, text); - RenderTextInternal(x, y + 1.0f, t + 1); - *t = '\n'; - return; - } - - if(strlen(text) == 0) + if(text.empty()) return; - RDCASSERT(strlen(text) < FONT_MAX_CHARS); + RDCASSERT(text.size() < FONT_MAX_CHARS); // transforms float width = (float)m_width; @@ -272,7 +260,7 @@ void D3D9DebugManager::RenderTextInternal(float x, float y, const char *text) Quad background; UINT triangleCount = 0; { - UINT quadCount = (UINT)strlen(text); // calculate string length + UINT quadCount = (UINT)text.size(); // calculate string length triangleCount = quadCount * 2; // create text VB diff --git a/renderdoc/driver/d3d9/d3d9_debug.h b/renderdoc/driver/d3d9/d3d9_debug.h index a41233be0..f686a434e 100644 --- a/renderdoc/driver/d3d9/d3d9_debug.h +++ b/renderdoc/driver/d3d9/d3d9_debug.h @@ -36,7 +36,7 @@ public: D3D9DebugManager(WrappedD3DDevice9 *wrapper); ~D3D9DebugManager(); - void RenderText(float x, float y, const char *textfmt, ...); + void RenderText(float x, float y, const rdcstr &text); void SetOutputDimensions(int w, int h) { @@ -49,7 +49,7 @@ public: bool InitFontRendering(); void ShutdownFontRendering(); - void RenderTextInternal(float x, float y, const char *text); + void RenderTextInternal(float x, float y, const rdcstr &text); static const int FONT_TEX_WIDTH = 256; static const int FONT_TEX_HEIGHT = 128; diff --git a/renderdoc/driver/d3d9/d3d9_device.cpp b/renderdoc/driver/d3d9/d3d9_device.cpp index 34ea8effe..6ead53fcb 100644 --- a/renderdoc/driver/d3d9/d3d9_device.cpp +++ b/renderdoc/driver/d3d9/d3d9_device.cpp @@ -251,8 +251,7 @@ HRESULT __stdcall WrappedD3DDevice9::Present(CONST RECT *pSourceRect, CONST RECT overlayText += "Captures not supported with D3D9\n"; - if(!overlayText.empty()) - GetDebugManager()->RenderText(0.0f, 0.0f, overlayText.c_str()); + GetDebugManager()->RenderText(0.0f, 0.0f, overlayText); stateBlockRes = stateBlock->Apply(); res |= m_device->EndScene(); diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 034cd0b92..86e7d325f 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -2033,8 +2033,7 @@ void WrappedOpenGL::SwapBuffers(WindowingSystem winSystem, void *windowHandle) overlayText += StringFormat::Fmt(" %s\n", reasonString); } - if(!overlayText.empty()) - RenderOverlayText(0.0f, 0.0f, overlayText.c_str()); + RenderText(0.0f, 0.0f, overlayText); // swallow all errors we might have inadvertantly caused. This is // better than letting an error propagate and maybe screw up the @@ -2380,8 +2379,8 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd) { ContextData &ctxdata = GetCtxData(); - RenderOverlayText(0.0f, 0.0f, "Failed to capture frame %u: %s", - m_CapturedFrames.back().frameNumber, reasonString); + RenderText(0.0f, 0.0f, StringFormat::Fmt("Failed to capture frame %u: %s", + m_CapturedFrames.back().frameNumber, reasonString)); // swallow all errors we might have inadvertantly caused. This is // better than letting an error propagate and maybe screw up the diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index aac3c9d61..b3aedefaa 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -531,8 +531,8 @@ private: static const int FONT_TEX_HEIGHT = 128; static const int FONT_MAX_CHARS = 256; - void RenderOverlayText(float x, float y, const char *fmt, ...); - void RenderOverlayStr(float x, float y, const char *str); + void RenderText(float x, float y, const rdcstr &text); + void RenderTextInternal(float x, float y, const rdcstr &text); void CreateReplayBackbuffer(const GLInitParams ¶ms, ResourceId fboOrigId, GLuint &fbo, rdcstr bbname); @@ -593,7 +593,7 @@ public: } SDFile &GetStructuredFile() { return *m_StructuredFile; } void SetFetchCounters(bool in) { m_FetchCounters = in; }; - void SetDebugMsgContext(const char *context) { m_DebugMsgContext = context; } + void SetDebugMsgContext(const rdcstr &context) { m_DebugMsgContext = context; } void AddDebugMessage(DebugMessage msg) { if(IsReplayMode(m_State)) @@ -2496,17 +2496,10 @@ public: class ScopedDebugContext { public: - ScopedDebugContext(WrappedOpenGL *driver, const char *fmt, ...) + ScopedDebugContext(WrappedOpenGL *driver, const rdcstr &msg) { - va_list args; - va_start(args, fmt); - char buf[1024]; - buf[1023] = 0; - StringFormat::vsnprintf(buf, 1023, fmt, args); - va_end(args); - m_Driver = driver; - m_Driver->SetDebugMsgContext(buf); + m_Driver->SetDebugMsgContext(msg); } ~ScopedDebugContext() { m_Driver->SetDebugMsgContext(""); } diff --git a/renderdoc/driver/gl/gl_rendertext.cpp b/renderdoc/driver/gl/gl_rendertext.cpp index ee067d461..eba4932cf 100644 --- a/renderdoc/driver/gl/gl_rendertext.cpp +++ b/renderdoc/driver/gl/gl_rendertext.cpp @@ -277,42 +277,29 @@ void WrappedOpenGL::ContextData::CreateDebugData() } } -void WrappedOpenGL::RenderOverlayText(float x, float y, const char *fmt, ...) +void WrappedOpenGL::RenderText(float x, float y, const rdcstr &text) { - static char tmpBuf[4096]; - - va_list args; - va_start(args, fmt); - StringFormat::vsnprintf(tmpBuf, 4095, fmt, args); - tmpBuf[4095] = '\0'; - va_end(args); - ContextData &ctxdata = GetCtxData(); GLPushPopState textState; textState.Push(ctxdata.Modern()); - RenderOverlayStr(x, y, tmpBuf); + rdcarray lines; + split(text, lines, '\n'); + + for(const rdcstr &line : lines) + RenderTextInternal(x, y, line); textState.Pop(ctxdata.Modern()); } -void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) +void WrappedOpenGL::RenderTextInternal(float x, float y, const rdcstr &text) { - if(char *t = strchr((char *)text, '\n')) - { - *t = 0; - RenderOverlayStr(x, y, text); - RenderOverlayStr(x, y + 1.0f, t + 1); - *t = '\n'; - return; - } - - if(strlen(text) == 0) + if(text.empty()) return; - RDCASSERT(strlen(text) < (size_t)FONT_MAX_CHARS); + RDCASSERT(text.size() < FONT_MAX_CHARS); ContextData &ctxdata = GetCtxData(); @@ -324,7 +311,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) { GL.glBindBuffer(eGL_ARRAY_BUFFER, ctxdata.ArrayBuffer); - size_t len = strlen(text); + size_t len = text.size(); if((int)len > FONT_MAX_CHARS) { @@ -334,7 +321,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) if(!printedWarning) { printedWarning = true; - RDCWARN("log string '%s' is too long", text, (int)len); + RDCWARN("log string '%s' is too long", text.c_str(), (int)len); } len = FONT_MAX_CHARS; @@ -520,7 +507,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) stbtt_aligned_quad q; - const char *prepass = text; + const char *prepass = text.c_str(); while(*prepass) { char c = *prepass; @@ -554,9 +541,10 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) float mul = ctxdata.initParams.isYFlipped ? -1.0f : 1.0f; - while(*text) + const char *str = text.c_str(); + while(*str) { - char c = *text; + char c = *str; if(c > FONT_FIRST_CHAR && c < FONT_LAST_CHAR) { stbtt_GetBakedQuad(chardata, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, c - FONT_FIRST_CHAR - 1, &x, @@ -574,7 +562,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text) { x += chardata[0].xadvance; } - ++text; + ++str; } } m_Platform.DrawQuads((float)ctxdata.initParams.width, (float)ctxdata.initParams.height, vertices); diff --git a/renderdoc/driver/gl/gl_stringise.cpp b/renderdoc/driver/gl/gl_stringise.cpp index 09842baba..3b28b1f33 100644 --- a/renderdoc/driver/gl/gl_stringise.cpp +++ b/renderdoc/driver/gl/gl_stringise.cpp @@ -144,10 +144,7 @@ rdcstr DoStringise(const UniformType &el) default: break; } - char tostrBuf[256] = {0}; - StringFormat::snprintf(tostrBuf, 255, "WrappedOpenGL::UniformType<%d>", el); - - return tostrBuf; + return StringFormat::Fmt("UniformType(%d)", el); } template <> @@ -4118,10 +4115,7 @@ rdcstr DoStringise(const RDCGLenum &el) default: break; } - char tostrBuf[256] = {0}; - StringFormat::snprintf(tostrBuf, 255, "GLenum<%x>", (uint32_t)el); - - return tostrBuf; + return StringFormat::Fmt("GLenum(%x)", el); #define GLenum RDCGLenum } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp index 6d4dd0c2d..130140feb 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_bytecode.cpp @@ -46,8 +46,6 @@ DXBC::Reflection *Program::GuessReflection() // useful reflection is present DXBC::Reflection *ret = new DXBC::Reflection; - char buf[64] = {0}; - for(size_t i = 0; i < m_Declarations.size(); i++) { Declaration &dcl = m_Declarations[i]; @@ -64,9 +62,7 @@ DXBC::Reflection *Program::GuessReflection() uint32_t idx = (uint32_t)dcl.operand.indices[0].index; - StringFormat::snprintf(buf, 63, "sampler%u", idx); - - desc.name = buf; + desc.name = StringFormat::Fmt("sampler%u", idx); desc.type = DXBC::ShaderInputBind::TYPE_SAMPLER; desc.space = dcl.space; desc.reg = idx; @@ -97,9 +93,7 @@ DXBC::Reflection *Program::GuessReflection() uint32_t idx = (uint32_t)dcl.operand.indices[0].index; - StringFormat::snprintf(buf, 63, "texture%u", idx); - - desc.name = buf; + desc.name = StringFormat::Fmt("texture%u", idx); desc.type = DXBC::ShaderInputBind::TYPE_TEXTURE; desc.space = dcl.space; desc.reg = idx; @@ -170,10 +164,8 @@ DXBC::Reflection *Program::GuessReflection() uint32_t idx = (uint32_t)dcl.operand.indices[0].index; - StringFormat::snprintf(buf, 63, "%sbytebuffer%u", - dcl.operand.type != TYPE_RESOURCE ? "rw" : "", idx); - - desc.name = buf; + desc.name = + StringFormat::Fmt("%sbytebuffer%u", dcl.operand.type != TYPE_RESOURCE ? "rw" : "", idx); desc.type = dcl.operand.type == TYPE_RESOURCE ? DXBC::ShaderInputBind::TYPE_BYTEADDRESS : DXBC::ShaderInputBind::TYPE_UAV_RWBYTEADDRESS; @@ -209,9 +201,7 @@ DXBC::Reflection *Program::GuessReflection() uint32_t idx = (uint32_t)dcl.operand.indices[0].index; - StringFormat::snprintf(buf, 63, "structuredbuffer%u", idx); - - desc.name = buf; + desc.name = StringFormat::Fmt("structuredbuffer%u", idx); desc.type = DXBC::ShaderInputBind::TYPE_STRUCTURED; desc.space = dcl.space; desc.reg = idx; @@ -242,9 +232,7 @@ DXBC::Reflection *Program::GuessReflection() uint32_t idx = (uint32_t)dcl.operand.indices[0].index; - StringFormat::snprintf(buf, 63, "uav%u", idx); - - desc.name = buf; + desc.name = StringFormat::Fmt("uav%u", idx); desc.type = DXBC::ShaderInputBind::TYPE_UAV_RWSTRUCTURED; // doesn't seem to be anything that // determines append vs consume vs @@ -280,9 +268,7 @@ DXBC::Reflection *Program::GuessReflection() uint32_t idx = (uint32_t)dcl.operand.indices[0].index; - StringFormat::snprintf(buf, 63, "uav%u", idx); - - desc.name = buf; + desc.name = StringFormat::Fmt("uav%u", idx); desc.type = DXBC::ShaderInputBind::TYPE_UAV_RWTYPED; desc.space = dcl.space; desc.reg = idx; @@ -346,9 +332,7 @@ DXBC::Reflection *Program::GuessReflection() uint32_t idx = (uint32_t)dcl.operand.indices[0].index; uint32_t numVecs = (uint32_t)dcl.operand.indices[1].index; - StringFormat::snprintf(buf, 63, "cbuffer%u", idx); - - desc.name = buf; + desc.name = StringFormat::Fmt("cbuffer%u", idx); desc.type = DXBC::ShaderInputBind::TYPE_CBUFFER; desc.space = dcl.space; desc.reg = idx; @@ -386,11 +370,9 @@ DXBC::Reflection *Program::GuessReflection() DXBC::CBufferVariable var; if(desc.space > 0) - StringFormat::snprintf(buf, 63, "cb%u_%u_v%u", desc.space, desc.reg, v); + var.name = StringFormat::Fmt("cb%u_%u_v%u", desc.space, desc.reg, v); else - StringFormat::snprintf(buf, 63, "cb%u_v%u", desc.reg, v); - - var.name = buf; + var.name = StringFormat::Fmt("cb%u_v%u", desc.reg, v); var.descriptor.defaultValue.resize(4 * sizeof(float)); diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index 887594706..58d9eb970 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -342,27 +342,18 @@ rdcstr TypeName(CBufferVariableType::Descriptor desc) ret = ""; else { - char buf[64] = {0}; - if(desc.rows > 1) { - StringFormat::snprintf(buf, 63, "%s%dx%d", type, desc.rows, desc.cols); + ret = StringFormat::Fmt("%s%dx%d", type, desc.rows, desc.cols); if(desc.varClass == CLASS_MATRIX_ROWS) { - ret = "row_major "; - ret += buf; - } - else - { - ret = buf; + ret = "row_major " + ret; } } else if(desc.cols > 1) { - StringFormat::snprintf(buf, 63, "%s%d", type, desc.cols); - - ret = buf; + ret = StringFormat::Fmt("%s%d", type, desc.cols); } else { @@ -400,9 +391,7 @@ CBufferVariableType DXBCContainer::ParseRDEFType(RDEFHeader *h, char *chunkConte } else { - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "unnamed_iface_0x%08x", typeOffset); - ret.descriptor.name += " " + rdcstr(buf); + ret.descriptor.name += StringFormat::Fmt(" unnamed_iface_0x%08x", typeOffset); } } @@ -415,9 +404,7 @@ CBufferVariableType DXBCContainer::ParseRDEFType(RDEFHeader *h, char *chunkConte } else { - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "unnamed_struct_0x%08x", typeOffset); - ret.descriptor.name = buf; + ret.descriptor.name = StringFormat::Fmt("unnamed_struct_0x%08x", typeOffset); } } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index c2c096fa3..32d20bf36 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -1093,11 +1093,7 @@ void State::Init() for(uint32_t t = 0; t < decl.numTemps; t++) { - char buf[64] = {0}; - - StringFormat::snprintf(buf, 63, "r%d", t); - - registers.push_back(ShaderVariable(buf, 0l, 0l, 0l, 0l)); + registers.push_back(ShaderVariable(StringFormat::Fmt("r%u", t), 0l, 0l, 0l, 0l)); } } if(decl.declaration == OPCODE_DCL_INDEXABLE_TEMP) @@ -1115,18 +1111,15 @@ void State::Init() { indexableTemps.resize(indexTempSizes.size()); - for(int32_t i = 0; i < (int32_t)indexTempSizes.size(); i++) + for(size_t i = 0; i < indexTempSizes.size(); i++) { if(indexTempSizes[i] > 0) { indexableTemps[i].members.resize(indexTempSizes[i]); for(uint32_t t = 0; t < indexTempSizes[i]; t++) { - char buf[64] = {0}; - - StringFormat::snprintf(buf, 63, "x%u[%u]", i, t); - - indexableTemps[i].members[t] = ShaderVariable(buf, 0l, 0l, 0l, 0l); + indexableTemps[i].members[t] = + ShaderVariable(StringFormat::Fmt("x%zu[%u]", i, t), 0l, 0l, 0l, 0l); } } } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp index ca0524437..4c9ee9532 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp @@ -608,13 +608,15 @@ void Program::MakeDisassemblyString() prevLineInfo = lineInfo; } - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "% 4u", i); - m_Disassembly += buf; - m_Disassembly += ": "; - for(int in = 0; in < indent - (m_Instructions[i].operation == OPCODE_ELSE ? 1 : 0); in++) - m_Disassembly += " "; - m_Disassembly += m_Instructions[i].str + "\n"; + int curIndent = indent; + if(m_Instructions[i].operation == OPCODE_ELSE) + curIndent--; + + rdcstr whitespace; + whitespace.fill(curIndent * 2, ' '); + + m_Disassembly += + StringFormat::Fmt("% 4u: %s%s\n", i, whitespace.c_str(), m_Instructions[i].str.c_str()); if(m_Instructions[i].operation == OPCODE_IF || m_Instructions[i].operation == OPCODE_LOOP) { @@ -750,24 +752,18 @@ bool Program::ExtractOperand(uint32_t *&tokenStream, ToString flags, Operand &re RDCASSERT(ret); } - if(retOper.indices[idx].relative) - retOper.indices[idx].str = - "[" + retOper.indices[idx].operand.toString(m_Reflection, flags | ToString::ShowSwizzle) + - " + "; - - if(retOper.indices[idx].absolute) - { - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%llu", retOper.indices[idx].index); - retOper.indices[idx].str += buf; - } - else if(retOper.indices[idx].relative) - retOper.indices[idx].str += "0"; - - if(retOper.indices[idx].relative) - retOper.indices[idx].str += "]"; - RDCASSERT(retOper.indices[idx].relative || retOper.indices[idx].absolute); + + if(retOper.indices[idx].relative) + { + retOper.indices[idx].str = StringFormat::Fmt( + "[%s + 0]", + retOper.indices[idx].operand.toString(m_Reflection, flags | ToString::ShowSwizzle).c_str()); + } + else + { + retOper.indices[idx].str = ToStr(retOper.indices[idx].index); + } } if(retOper.type == TYPE_RESOURCE || retOper.type == TYPE_SAMPLER || @@ -847,16 +843,9 @@ rdcstr Operand::toString(const DXBC::Reflection *reflection, ToString flags) con } else if(type == TYPE_INTERFACE) { - str = "fp"; - RDCASSERT(indices.size() == 2); - str += indices[0].str; - str += "[" + indices[1].str + "]"; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "[%u]", funcNum); - str += buf; + str = StringFormat::Fmt("fp%s[%s][%u]", indices[0].str.c_str(), indices[1].str.c_str(), funcNum); } else if(type == TYPE_RESOURCE || type == TYPE_SAMPLER || type == TYPE_UNORDERED_ACCESS_VIEW) { @@ -1195,9 +1184,7 @@ rdcstr Operand::toString(const DXBC::Reflection *reflection, ToString flags) con else if(type == TYPE_IMMEDIATE64) { double *dv = (double *)values; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "d(%lfl, %lfl)", dv[0], dv[1]); - str += buf; + str += StringFormat::Fmt("d(%lfl, %lfl)", dv[0], dv[1]); } else if(type == TYPE_RASTERIZER) str = "rasterizer"; @@ -1503,20 +1490,14 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri } else if(op == OPCODE_DCL_TEMPS) { - retDecl.str += " "; - retDecl.numTemps = tokenStream[0]; tokenStream++; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.numTemps); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" %u", retDecl.numTemps); } else if(op == OPCODE_DCL_INDEXABLE_TEMP) { - retDecl.str += " "; - retDecl.tempReg = tokenStream[0]; tokenStream++; @@ -1526,10 +1507,8 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.tempComponentCount = tokenStream[0]; tokenStream++; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "x%u[%u], %u", retDecl.tempReg, retDecl.numTemps, - retDecl.tempComponentCount); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" x%u[%u], %u", retDecl.tempReg, retDecl.numTemps, + retDecl.tempComponentCount); } else if(op == OPCODE_DCL_OUTPUT) { @@ -1548,9 +1527,7 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri tokenStream++; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.maxOut); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" %u", retDecl.maxOut); } else if(op == OPCODE_DCL_INPUT_SIV || op == OPCODE_DCL_INPUT_SGV || op == OPCODE_DCL_INPUT_PS_SIV || op == OPCODE_DCL_INPUT_PS_SGV || @@ -1686,15 +1663,10 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.indexRange = tokenStream[0]; tokenStream++; - retDecl.str += " "; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.indexRange); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" %u", retDecl.indexRange); } else if(op == OPCODE_DCL_THREAD_GROUP) { - retDecl.str += " "; - retDecl.groupSize[0] = tokenStream[0]; tokenStream++; @@ -1703,17 +1675,9 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.groupSize[2] = tokenStream[0]; tokenStream++; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.groupSize[0]); - retDecl.str += buf; - retDecl.str += ", "; - StringFormat::snprintf(buf, 63, "%u", retDecl.groupSize[1]); - retDecl.str += buf; - retDecl.str += ", "; - - StringFormat::snprintf(buf, 63, "%u", retDecl.groupSize[2]); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" %u, %u, %u", retDecl.groupSize[0], retDecl.groupSize[1], + retDecl.groupSize[2]); } else if(op == OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW) { @@ -1726,11 +1690,7 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri tokenStream++; retDecl.str += retDecl.operand.toString(m_Reflection, flags); - retDecl.str += ", "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.count); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(", %u", retDecl.count); } else if(op == OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED) { @@ -1746,25 +1706,13 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri tokenStream++; retDecl.str += retDecl.operand.toString(m_Reflection, flags); - retDecl.str += ", "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.stride); - retDecl.str += buf; - retDecl.str += ", "; - - StringFormat::snprintf(buf, 63, "%u", retDecl.count); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(", %u, %u", retDecl.stride, retDecl.count); } else if(op == OPCODE_DCL_INPUT_CONTROL_POINT_COUNT || op == OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT) { - retDecl.str += " "; - retDecl.controlPointCount = Decl::ControlPointCount.Get(OpcodeToken0); - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.controlPointCount); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" %u", retDecl.controlPointCount); } else if(op == OPCODE_DCL_TESS_DOMAIN) { @@ -1814,11 +1762,8 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri else if(retDecl.inPrim >= PRIMITIVE_1_CONTROL_POINT_PATCH && retDecl.inPrim <= PRIMITIVE_32_CONTROL_POINT_PATCH) { - retDecl.str += "control_point_patch_"; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", - 1 + int(retDecl.inPrim - PRIMITIVE_1_CONTROL_POINT_PATCH)); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt("control_point_patch_%u", + 1 + int(retDecl.inPrim - PRIMITIVE_1_CONTROL_POINT_PATCH)); } else RDCERR("Unexpected primitive type"); @@ -1921,11 +1866,7 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri tokenStream++; retDecl.str += retDecl.operand.toString(m_Reflection, flags); - retDecl.str += ", "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.stride); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(", %u", retDecl.stride); if(retDecl.hasCounter) retDecl.str += ", hasOrderPreservingCounter"; @@ -2016,11 +1957,7 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.instanceCount = tokenStream[0]; tokenStream++; - retDecl.str += " "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%u", retDecl.instanceCount); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" %u", retDecl.instanceCount); } else if(op == OPCODE_DCL_HS_MAX_TESSFACTOR) { @@ -2028,33 +1965,21 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.maxTessFactor = *f; tokenStream++; - retDecl.str += " "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "l(%f)", retDecl.maxTessFactor); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" l(%f)", retDecl.maxTessFactor); } else if(op == OPCODE_DCL_FUNCTION_BODY) { retDecl.functionBody = tokenStream[0]; tokenStream++; - retDecl.str += " "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "fb%u", retDecl.functionBody); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" fb%u", retDecl.functionBody); } else if(op == OPCODE_DCL_FUNCTION_TABLE) { retDecl.functionTable = tokenStream[0]; tokenStream++; - retDecl.str += " "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "ft%u", retDecl.functionTable); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" ft%u", retDecl.functionTable); uint32_t TableLength = tokenStream[0]; tokenStream++; @@ -2063,8 +1988,7 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri for(uint32_t i = 0; i < TableLength; i++) { - StringFormat::snprintf(buf, 63, "fb%u", tokenStream[0]); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt("fb%u", tokenStream[0]); if(i + 1 < TableLength) retDecl.str += ", "; @@ -2089,19 +2013,14 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.numInterfaces = Decl::NumInterfaces.Get(CountToken); uint32_t TableLength = Decl::TableLength.Get(CountToken); - retDecl.str += " "; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "fp%u[%u][%u]", retDecl.interfaceID, retDecl.numInterfaces, - retDecl.numTypes); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt(" fp%u[%u][%u]", retDecl.interfaceID, retDecl.numInterfaces, + retDecl.numTypes); retDecl.str += " = {"; for(uint32_t i = 0; i < TableLength; i++) { - StringFormat::snprintf(buf, 63, "ft%u", tokenStream[0]); - retDecl.str += buf; + retDecl.str += StringFormat::Fmt("ft%u", tokenStream[0]); if(i + 1 < TableLength) retDecl.str += ", "; @@ -2113,7 +2032,8 @@ bool Program::ExtractDecl(uint32_t *&tokenStream, Declaration &retDecl, bool fri retDecl.str += "}"; } else if(op == OPCODE_HS_DECLS) - ; + { + } else { RDCERR("Unexpected opcode decl %d", op); @@ -2232,10 +2152,8 @@ bool Program::ExtractOperation(uint32_t *&tokenStream, Operation &retOp, bool fr if(retOp.texelOffset[2] > 7) retOp.texelOffset[2] -= 16; - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "(%d,%d,%d)", retOp.texelOffset[0], retOp.texelOffset[1], - retOp.texelOffset[2]); - retOp.str += buf; + retOp.str += StringFormat::Fmt("(%d,%d,%d)", retOp.texelOffset[0], retOp.texelOffset[1], + retOp.texelOffset[2]); } else if(type == EXTENDED_OPCODE_RESOURCE_DIM) { @@ -2243,16 +2161,10 @@ bool Program::ExtractOperation(uint32_t *&tokenStream, Operation &retOp, bool fr if(op == OPCODE_LD_STRUCTURED) { - retOp.str += "_indexable("; - retOp.str += toString(retOp.resDim); - retOp.stride = ExtendedOpcode::BufferStride.Get(OpcodeTokenN); - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, ", stride=%u", retOp.stride); - retOp.str += buf; - - retOp.str += ")"; + retOp.str += + StringFormat::Fmt("_indexable(%s, stride=%u)", toString(retOp.resDim), retOp.stride); } else { @@ -2646,20 +2558,18 @@ rdcstr toString(const uint32_t values[], uint32_t numComps) float *vf = (float *)&values[i]; int32_t *vi = (int32_t *)&values[i]; - char buf[64] = {0}; - - if(!floatOutput) + if(floatOutput) + { + str += ToStr(vf[0]); + } + else { // print small ints straight up, otherwise as hex if(vi[0] <= 10000 && vi[0] >= -10000) - StringFormat::snprintf(buf, 63, "%d", vi[0]); + str += ToStr(vi[0]); else - StringFormat::snprintf(buf, 63, "0x%08x", vi[0]); + str += StringFormat::Fmt("0x%08x", vi[0]); } - else - StringFormat::snprintf(buf, 63, "%f", vf[0]); - - str += buf; if(i + 1 < numComps) str += ", "; diff --git a/renderdoc/driver/vulkan/vk_rendertext.cpp b/renderdoc/driver/vulkan/vk_rendertext.cpp index da7bb522d..a75541727 100644 --- a/renderdoc/driver/vulkan/vk_rendertext.cpp +++ b/renderdoc/driver/vulkan/vk_rendertext.cpp @@ -25,6 +25,7 @@ #include "vk_rendertext.h" #include "3rdparty/stb/stb_truetype.h" #include "maths/matrix.h" +#include "strings/string_utils.h" #include "vk_shader_cache.h" #define VULKAN 1 @@ -597,32 +598,19 @@ void VulkanTextRenderer::BeginText(const TextPrintState &textstate) } void VulkanTextRenderer::RenderText(const TextPrintState &textstate, float x, float y, - const char *textfmt, ...) + const rdcstr &text) { - static char tmpBuf[4096]; + rdcarray lines; + split(text, lines, '\n'); - va_list args; - va_start(args, textfmt); - StringFormat::vsnprintf(tmpBuf, 4095, textfmt, args); - tmpBuf[4095] = '\0'; - va_end(args); - - RenderTextInternal(textstate, x, y, tmpBuf); + for(const rdcstr &line : lines) + RenderTextInternal(textstate, x, y, line); } void VulkanTextRenderer::RenderTextInternal(const TextPrintState &textstate, float x, float y, - const char *text) + const rdcstr &text) { - if(char *t = strchr((char *)text, '\n')) - { - *t = 0; - RenderTextInternal(textstate, x, y, text); - RenderTextInternal(textstate, x, y + 1.0f, t + 1); - *t = '\n'; - return; - } - - if(strlen(text) == 0) + if(text.empty()) return; uint32_t offsets[2] = {0}; @@ -643,14 +631,14 @@ void VulkanTextRenderer::RenderTextInternal(const TextPrintState &textstate, flo m_TextGeneralUBO.Unmap(); - size_t len = strlen(text); + size_t len = text.size(); RDCASSERT(len <= MAX_SINGLE_LINE_LENGTH); // only map enough for our string StringUBOData *stringData = (StringUBOData *)m_TextStringUBO.Map(&offsets[1], len * sizeof(Vec4u)); - for(size_t i = 0; i < strlen(text); i++) + for(size_t i = 0; i < len; i++) stringData->chars[i].x = uint32_t(text[i] - ' '); m_TextStringUBO.Unmap(); @@ -659,7 +647,7 @@ void VulkanTextRenderer::RenderTextInternal(const TextPrintState &textstate, flo ->CmdBindDescriptorSets(Unwrap(textstate.cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(m_TextPipeLayout), 0, 1, UnwrapPtr(m_TextDescSet), 2, offsets); - ObjDisp(textstate.cmd)->CmdDraw(Unwrap(textstate.cmd), 6 * (uint32_t)strlen(text), 1, 0, 0); + ObjDisp(textstate.cmd)->CmdDraw(Unwrap(textstate.cmd), 6 * (uint32_t)len, 1, 0, 0); } void VulkanTextRenderer::EndText(const TextPrintState &textstate) diff --git a/renderdoc/driver/vulkan/vk_rendertext.h b/renderdoc/driver/vulkan/vk_rendertext.h index ef0fb179b..d3524ba95 100644 --- a/renderdoc/driver/vulkan/vk_rendertext.h +++ b/renderdoc/driver/vulkan/vk_rendertext.h @@ -44,11 +44,11 @@ public: ~VulkanTextRenderer(); void BeginText(const TextPrintState &textstate); - void RenderText(const TextPrintState &textstate, float x, float y, const char *fmt, ...); + void RenderText(const TextPrintState &textstate, float x, float y, const rdcstr &text); void EndText(const TextPrintState &textstate); private: - void RenderTextInternal(const TextPrintState &textstate, float x, float y, const char *text); + void RenderTextInternal(const TextPrintState &textstate, float x, float y, const rdcstr &text); static const uint32_t FONT_TEX_WIDTH = 256; static const uint32_t FONT_TEX_HEIGHT = 128; diff --git a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp index f58223068..871e69140 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp @@ -25,7 +25,7 @@ #include "../vk_core.h" #include "api/replay/version.h" -static char fakeRenderDocUUID[VK_UUID_SIZE + 1] = {}; +static char fakeRenderDocUUID[VK_UUID_SIZE] = {}; void MakeFakeUUID() { @@ -37,7 +37,9 @@ void MakeFakeUUID() // rdocyymmddHHMMSS // we pass size+1 so that there's room for a null terminator (the UUID doesn't // need a null terminator as it's a fixed size non-string array) - StringFormat::sntimef(fakeRenderDocUUID, VK_UUID_SIZE + 1, "rdoc%y%m%d%H%M%S"); + rdcstr uuid = StringFormat::sntimef(Timing::GetUTCTime(), "rdoc%y%m%d%H%M%S"); + RDCASSERT(uuid.size() == sizeof(fakeRenderDocUUID)); + memcpy(fakeRenderDocUUID, uuid.c_str(), RDCMIN(VK_UUID_SIZE, uuid.count())); } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp index abf6b35ae..99595b964 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp @@ -832,15 +832,17 @@ VkResult WrappedVulkan::vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR SubmitAndFlushExtQueue(swapQueueIndex); } - m_TextRenderer->BeginText(textstate); - int flags = activeWindow ? RenderDoc::eOverlay_ActiveWindow : 0; rdcstr overlayText = RenderDoc::Inst().GetOverlayText(RDCDriver::Vulkan, m_FrameCounter, flags); if(!overlayText.empty()) - m_TextRenderer->RenderText(textstate, 0.0f, 0.0f, overlayText.c_str()); + { + m_TextRenderer->BeginText(textstate); - m_TextRenderer->EndText(textstate); + m_TextRenderer->RenderText(textstate, 0.0f, 0.0f, overlayText); + + m_TextRenderer->EndText(textstate); + } std::swap(bbBarrier.srcQueueFamilyIndex, bbBarrier.dstQueueFamilyIndex); std::swap(bbBarrier.oldLayout, bbBarrier.newLayout); diff --git a/renderdoc/os/os_specific.cpp b/renderdoc/os/os_specific.cpp index 94fca1b6a..cc4802d57 100644 --- a/renderdoc/os/os_specific.cpp +++ b/renderdoc/os/os_specific.cpp @@ -27,32 +27,10 @@ #include "api/replay/control_types.h" #include "strings/string_utils.h" -int utf8printf(char *buf, size_t bufsize, const char *fmt, va_list args); +int utf8printv(char *buf, size_t bufsize, const char *fmt, va_list args); namespace StringFormat { -int snprintf(char *str, size_t bufSize, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - - int ret = StringFormat::vsnprintf(str, bufSize, fmt, args); - - va_end(args); - - return ret; -} - -void sntimef(char *str, size_t bufSize, const char *format) -{ - StringFormat::sntimef(Timing::GetUTCTime(), str, bufSize, format); -} - -int vsnprintf(char *str, size_t bufSize, const char *format, va_list args) -{ - return ::utf8printf(str, bufSize, format, args); -} - rdcstr Fmt(const char *format, ...) { va_list args; @@ -61,11 +39,11 @@ rdcstr Fmt(const char *format, ...) va_list args2; va_copy(args2, args); - int size = StringFormat::vsnprintf(NULL, 0, format, args2); + int size = ::utf8printv(NULL, 0, format, args2); rdcstr ret; ret.resize(size); - StringFormat::vsnprintf(ret.data(), size + 1, format, args); + ::utf8printv(ret.data(), size + 1, format, args); va_end(args); va_end(args2); @@ -93,11 +71,9 @@ rdcstr Callstack::AddressDetails::formattedString(const char *commonPath) } if(line > 0) - StringFormat::snprintf(fmt, 511, "%s line %d", function.c_str(), line); + return StringFormat::Fmt("%s line %d", function.c_str(), line); else - StringFormat::snprintf(fmt, 511, "%s", function.c_str()); - - return fmt; + return function; } rdcstr OSUtility::MakeMachineIdentString(uint64_t ident) diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index 440636360..5eaa117d6 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -434,7 +434,7 @@ struct rdcwstr : private rdcarray // implemented per-platform namespace StringFormat { -void sntimef(time_t utcTime, char *str, size_t bufSize, const char *format); +rdcstr sntimef(time_t utcTime, const char *format); rdcstr Wide2UTF8(const rdcwstr &str); rdcwstr UTF82Wide(const rdcstr &s); @@ -442,16 +442,6 @@ rdcwstr UTF82Wide(const rdcstr &s); void Shutdown(); }; -// utility functions, implemented in os_specific.cpp, not per-platform (assuming standard stdarg.h) -// forwarded to custom printf implementation in utf8printf.cpp -namespace StringFormat -{ -int vsnprintf(char *str, size_t bufSize, const char *format, va_list v); -int snprintf(char *str, size_t bufSize, const char *format, ...); - -void sntimef(char *str, size_t bufSize, const char *format); -}; - namespace OSUtility { inline void ForceCrash(); diff --git a/renderdoc/os/posix/android/android_stringio.cpp b/renderdoc/os/posix/android/android_stringio.cpp index 42799ed29..a05c05840 100644 --- a/renderdoc/os/posix/android/android_stringio.cpp +++ b/renderdoc/os/posix/android/android_stringio.cpp @@ -26,6 +26,7 @@ #include #include #include "common/common.h" +#include "common/formatting.h" #include "os/os_specific.h" #define LOGCAT_TAG "renderdoc" @@ -77,13 +78,11 @@ rdcstr GetAppFolderFilename(const rdcstr &filename) // For other APKs, we use it to get the writable temp directory. void GetExecutableFilename(rdcstr &selfName) { - char buf[4096]; - snprintf(buf, sizeof(buf), "/proc/%u/cmdline", getpid()); - int fd = open(buf, O_RDONLY); + int fd = open(StringFormat::Fmt("/proc/%u/cmdline", getpid()).c_str(), O_RDONLY); if(fd < 0) - { return; - } + + char buf[4096]; ssize_t len = read(fd, buf, sizeof(buf)); close(fd); if(len < 0 || len == sizeof(buf)) diff --git a/renderdoc/os/posix/posix_network.cpp b/renderdoc/os/posix/posix_network.cpp index bdd24b5dc..727c8d341 100644 --- a/renderdoc/os/posix/posix_network.cpp +++ b/renderdoc/os/posix/posix_network.cpp @@ -388,9 +388,6 @@ Socket *CreateTCPServerSocket(const char *bindaddr, uint16_t port, int queuesize Socket *CreateAbstractServerSocket(uint16_t port, int queuesize) { - char socketName[17] = {0}; - StringFormat::snprintf(socketName, 16, "renderdoc_%d", port); - int socketNameLength = strlen(socketName); int s = socket(AF_UNIX, SOCK_STREAM, 0); if(s == -1) @@ -399,18 +396,20 @@ Socket *CreateAbstractServerSocket(uint16_t port, int queuesize) return NULL; } + rdcstr socketName = StringFormat::Fmt("renderdoc_%d", port); + sockaddr_un addr; RDCEraseEl(addr); addr.sun_family = AF_UNIX; // first char is '\0' addr.sun_path[0] = '\0'; - strncpy(addr.sun_path + 1, socketName, socketNameLength + 1); + strncpy(addr.sun_path + 1, socketName.c_str(), socketName.size() + 1); - int result = bind(s, (sockaddr *)&addr, offsetof(sockaddr_un, sun_path) + 1 + socketNameLength); + int result = bind(s, (sockaddr *)&addr, socketName.size()); if(result == -1) { - RDCWARN("Failed to create abstract socket: %s", socketName); + RDCWARN("Failed to create abstract socket: %s", socketName.c_str()); close(s); return NULL; } @@ -419,7 +418,7 @@ Socket *CreateAbstractServerSocket(uint16_t port, int queuesize) result = listen(s, queuesize); if(result == -1) { - RDCWARN("Failed to listen on %s", socketName); + RDCWARN("Failed to listen on %s", socketName.c_str()); close(s); return NULL; } @@ -432,9 +431,6 @@ Socket *CreateAbstractServerSocket(uint16_t port, int queuesize) Socket *CreateClientSocket(const char *host, uint16_t port, int timeoutMS) { - char portstr[7] = {0}; - StringFormat::snprintf(portstr, 6, "%d", port); - addrinfo hints; RDCEraseEl(hints); hints.ai_family = AF_INET; @@ -442,7 +438,7 @@ Socket *CreateClientSocket(const char *host, uint16_t port, int timeoutMS) hints.ai_protocol = IPPROTO_TCP; addrinfo *addrResult = NULL; - int res = getaddrinfo(host, portstr, &hints, &addrResult); + int res = getaddrinfo(host, ToStr(port).c_str(), &hints, &addrResult); if(res != 0) { RDCDEBUG("%s", gai_strerror(res)); diff --git a/renderdoc/os/posix/posix_stringio.cpp b/renderdoc/os/posix/posix_stringio.cpp index 16e95ca72..03bb8d559 100644 --- a/renderdoc/os/posix/posix_stringio.cpp +++ b/renderdoc/os/posix/posix_stringio.cpp @@ -38,6 +38,7 @@ #include #include "api/app/renderdoc_app.h" #include "api/replay/data_types.h" +#include "common/formatting.h" #include "common/threading.h" #include "os/os_specific.h" #include "strings/string_utils.h" @@ -221,24 +222,18 @@ void GetDefaultFiles(const char *logBaseName, rdcstr &capture_filename, rdcstr & temp_folder[--len] = 0; } - char temp_filename[2048 + 128] = {0}; - - snprintf(temp_filename, sizeof(temp_filename) - 1, "%s/RenderDoc/%s_%04d.%02d.%02d_%02d.%02d.rdc", - temp_folder, mod, 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, - now.tm_min); - - capture_filename = rdcstr(temp_filename); - - snprintf(temp_filename, sizeof(temp_filename) - 1, - "%s/RenderDoc/%s_%04d.%02d.%02d_%02d.%02d.%02d.log", temp_folder, logBaseName, - 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec); + capture_filename = + StringFormat::Fmt("%s/RenderDoc/%s_%04d.%02d.%02d_%02d.%02d.rdc", temp_folder, mod, + 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min); // set by UI when launching programs so all logging goes to the same file char *logfile_override = getenv("RENDERDOC_DEBUG_LOG_FILE"); if(logfile_override) logging_filename = rdcstr(logfile_override); else - logging_filename = rdcstr(temp_filename); + logging_filename = StringFormat::Fmt( + "%s/RenderDoc/%s_%04d.%02d.%02d_%02d.%02d.%02d.log", temp_folder, logBaseName, + 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec); } uint64_t GetModifiedTimestamp(const rdcstr &filename) @@ -568,10 +563,39 @@ void logfile_close(LogFileHandle *logHandle, const char *deleteFilename) namespace StringFormat { -void sntimef(time_t utcTime, char *str, size_t bufSize, const char *format) +rdcstr sntimef(time_t utcTime, const char *format) { tm *tmv = localtime(&utcTime); - strftime(str, bufSize, format, tmv); + // conservatively assume that most formatters will replace like-for-like (e.g. %H with 12) and + // a few will increase (%Y to 2019) but generally the string will stay the same size. + size_t len = strlen(format) + 16; + + size_t ret = 0; + char *buf = NULL; + + // loop until we have successfully formatted + while(ret == 0) + { + // delete any previous buffer + delete[] buf; + + // alloate new one of the new size + buf = new char[len + 1]; + buf[len] = 0; + + // try formatting + ret = strftime(buf, len, format, tmv); + + // double the length for next time, if this failed + len *= 2; + } + + rdcstr str = buf; + + // delete successful buffer + delete[] buf; + + return str; } }; diff --git a/renderdoc/os/win32/win32_network.cpp b/renderdoc/os/win32/win32_network.cpp index dbbb8e084..f04f53f4b 100644 --- a/renderdoc/os/win32/win32_network.cpp +++ b/renderdoc/os/win32/win32_network.cpp @@ -397,9 +397,8 @@ Socket *CreateClientSocket(const char *host, uint16_t port, int timeoutMS) wchar_t portwstr[7] = {0}; { - char buf[7] = {0}; - int n = StringFormat::snprintf(buf, 6, "%d", port); - for(int i = 0; i < n && i < 6; i++) + rdcstr buf = ToStr(port); + for(size_t i = 0; i < buf.size(); i++) portwstr[i] = (wchar_t)buf[i]; } diff --git a/renderdoc/os/win32/win32_stringio.cpp b/renderdoc/os/win32/win32_stringio.cpp index 7bb17cbab..bf9a64a16 100644 --- a/renderdoc/os/win32/win32_stringio.cpp +++ b/renderdoc/os/win32/win32_stringio.cpp @@ -745,26 +745,45 @@ void logfile_close(LogFileHandle *logHandle, const char *deleteFilename) namespace StringFormat { -void sntimef(time_t utcTime, char *str, size_t bufSize, const char *format) +rdcstr sntimef(time_t utcTime, const char *format) { tm tmv; localtime_s(&tmv, &utcTime); - wchar_t *buf = new wchar_t[bufSize + 1]; - buf[bufSize] = 0; + rdcstr result; + rdcwstr wfmt = StringFormat::UTF82Wide(format); - wcsftime(buf, bufSize, wfmt.c_str(), &tmv); + // conservatively assume that most formatters will replace like-for-like (e.g. %H with 12) and + // a few will increase (%Y to 2019) but generally the string will stay the same size. + size_t len = strlen(format) + 16; - rdcstr result = StringFormat::Wide2UTF8(buf); + size_t ret = 0; + wchar_t *buf = NULL; + // loop until we have successfully formatted + while(ret == 0) + { + // delete any previous buffer + delete[] buf; + + // alloate new one of the new size + buf = new wchar_t[len + 1]; + buf[len] = 0; + + // try formatting + ret = wcsftime(buf, len, wfmt.c_str(), &tmv); + + // double the length for next time, if this failed + len *= 2; + } + + rdcstr str = StringFormat::Wide2UTF8(buf); + + // delete successful buffer delete[] buf; - if(result.length() + 1 <= bufSize) - { - memcpy(str, result.c_str(), result.length()); - str[result.length()] = 0; - } + return str; } void Shutdown() diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index 24c430745..5725417e3 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -304,9 +304,8 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_CreateBugReport(const char if(report.empty()) { - char filename[128] = {}; - StringFormat::sntimef(filename, 127, "/renderdoc_report_%H%M%S.zip"); - report = FileIO::GetTempFolderFilename() + filename; + report = FileIO::GetTempFolderFilename() + + StringFormat::sntimef(Timing::GetUTCTime(), "/renderdoc_report_%H%M%S.zip"); } FileIO::Delete(report.c_str()); diff --git a/renderdoc/serialise/serialiser_tests.cpp b/renderdoc/serialise/serialiser_tests.cpp index ef3b016ef..4dcc29201 100644 --- a/renderdoc/serialise/serialiser_tests.cpp +++ b/renderdoc/serialise/serialiser_tests.cpp @@ -1368,6 +1368,11 @@ rdcstr DoStringise(const TestBitfield &el) END_BITFIELD_STRINGISE(); } +void test(const char *aasd) +{ + RDCLOG("got a test of %s", aasd); +} + TEST_CASE("Test stringification works as expected", "[tostr]") { SECTION("Enum classes") @@ -1391,6 +1396,17 @@ TEST_CASE("Test stringification works as expected", "[tostr]") CHECK(ToStr(foo) == "TestEnumClass(0)"); }; + SECTION("integers") + { + uint16_t a = 54; + uint32_t b = 22; + uint8_t c = 99; + + test(ToStr(a).c_str()); + test(ToStr(b).c_str()); + test(ToStr(c).c_str()); + }; + SECTION("plain enums") { TestEnum foo = TestA; diff --git a/renderdoc/strings/utf8printf.cpp b/renderdoc/strings/utf8printf.cpp index d22bbbc04..64678bdd6 100644 --- a/renderdoc/strings/utf8printf.cpp +++ b/renderdoc/strings/utf8printf.cpp @@ -1180,7 +1180,7 @@ void formatargument(char type, void *rawarg, FormatterParams formatter, char *&o } } -int utf8printf(char *buf, size_t bufsize, const char *fmt, va_list args) +int utf8printv(char *buf, size_t bufsize, const char *fmt, va_list args) { // format, buffer and string arguments are assumed to be UTF-8 (except wide strings). // note that since the format specifiers are entirely ascii, we can byte-copy safely and handle @@ -1452,23 +1452,23 @@ int utf8printf(char *buf, size_t bufsize, const char *fmt, va_list args) return int(actualsize); } -#if ENABLED(ENABLE_UNIT_TESTS) - -#include "3rdparty/catch/catch.hpp" -#include "common/formatting.h" - -int utf8printf_wrapper(char *buf, size_t bufsize, const char *fmt, ...) +int utf8printf(char *str, size_t bufSize, const char *fmt, ...) { va_list args; va_start(args, fmt); - int ret = utf8printf(buf, bufsize, fmt, args); + int ret = utf8printv(str, bufSize, fmt, args); va_end(args); return ret; } +#if ENABLED(ENABLE_UNIT_TESTS) + +#include "3rdparty/catch/catch.hpp" +#include "common/formatting.h" + TEST_CASE("utf8printf buffer sizing", "[utf8printf]") { int fourtytwo = 42; @@ -1477,7 +1477,7 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") SECTION("NULL input buffer") { - int a = utf8printf_wrapper(NULL, 0, "%d %c", fourtytwo, x); + int a = utf8printf(NULL, 0, "%d %c", fourtytwo, x); int b = snprintf(NULL, 0, "%d %c", fourtytwo, x); CHECK(a == 4); @@ -1490,7 +1490,7 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") char bufa[] = {0, 0, 0, 0, 0, 0}; char bufb[] = {0, 0, 0, 0, 0, 0}; - int a = utf8printf_wrapper(bufa, sizeof(bufa), "%d foo", largenum); + int a = utf8printf(bufa, sizeof(bufa), "%d foo", largenum); int b = snprintf(bufb, sizeof(bufb), "%d foo", largenum); RDCCOMPILE_ASSERT(sizeof(bufa) == 6, "bufa is mis-sized for test"); @@ -1513,7 +1513,7 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") SECTION("contains NULL terminator") { memset(bufa, 'a', sizeof(bufa)); - a = utf8printf_wrapper(bufa, sizeof(bufa), "%d foo", largenum); + a = utf8printf(bufa, sizeof(bufa), "%d foo", largenum); INFO("bufa is '" << rdcstr(bufa) << "'"); CHECK(memcmp(bufa, ref, sizeof(ref)) == 0); } @@ -1527,7 +1527,7 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") memset(bufa, 'a', sizeof(bufa)); memset(bufb, 'b', sizeof(bufb)); - int a = utf8printf_wrapper(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); + int a = utf8printf(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); int b = snprintf(bufb, sizeof(bufb), "foobar %c %d", x, fourtytwo); CHECK(a == sizeof(bufa) - 1); @@ -1556,7 +1556,7 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") memset(bufa, 'a', sizeof(bufa)); memset(bufb, 'b', sizeof(bufb)); - int a = utf8printf_wrapper(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); + int a = utf8printf(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); int b = snprintf(bufb, sizeof(bufb), "foobar %c %d", x, fourtytwo); CHECK(a == sizeof(bufa)); @@ -1585,7 +1585,7 @@ TEST_CASE("utf8printf buffer sizing", "[utf8printf]") memset(bufa, 'a', sizeof(bufa)); memset(bufb, 'b', sizeof(bufb)); - int a = utf8printf_wrapper(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); + int a = utf8printf(bufa, sizeof(bufa), "foobar %c %d", x, fourtytwo); int b = snprintf(bufb, sizeof(bufb), "foobar %c %d", x, fourtytwo); CHECK(a == 11);