diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp index 10efd195d..69d5300b6 100644 --- a/qrenderdoc/Code/QRDUtils.cpp +++ b/qrenderdoc/Code/QRDUtils.cpp @@ -57,7 +57,7 @@ template <> rdcstr DoStringise(const uint32_t &el) { - return QString::number(el).toStdString(); + return QString::number(el); } // these ones we do by hand as it requires formatting @@ -2167,7 +2167,7 @@ QStringList ParseArgsList(const QString &args) LocalFree(argv); #else - std::string argString = args.toStdString(); + rdcstr argString = args; // perform some kind of sane parsing bool dquot = false, squot = false; // are we inside ''s or ""s @@ -2176,14 +2176,14 @@ QStringList ParseArgsList(const QString &args) char *c = &argString[0]; // current argument we're building - std::string a; + rdcstr a; while(*c) { if(!dquot && !squot && (*c == ' ' || *c == '\t')) { if(!a.empty()) - ret << QString::fromStdString(a); + ret << QString(a); a = ""; } @@ -2239,7 +2239,7 @@ QStringList ParseArgsList(const QString &args) // if we were building an argument when we hit the end of the string if(!a.empty()) - ret << QString::fromStdString(a); + ret << QString(a); #endif return ret; diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index 94d4a07aa..2d53a2cdf 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -46,13 +46,13 @@ inline T AlignUp(T x, T a) #define ARRAY_COUNT(arr) (sizeof(arr) / sizeof(arr[0])) #endif -// this will be here to lighten the burden of converting from std::string to +// this will be here to lighten the burden of converting from rdcstr to // QString everywhere. template inline QString ToQStr(const T &el) { - return QString::fromStdString(ToStr(el)); + return QString(ToStr(el)); } // overload for a couple of things that need to know the pipeline type when converting diff --git a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp index f0981fca1..d0d352583 100644 --- a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp +++ b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp @@ -1222,16 +1222,23 @@ extern "C" void HandleException(PyObject *global_handle) else if(redirector && !redirector->context) { // if still NULL we're running in the extension context - std::string exString; + rdcstr exString; if(!frames.isEmpty()) { exString += "Traceback (most recent call last):\n"; for(const QString &f : frames) - exString += " " + f.toUtf8().toStdString() + "\n"; + { + exString += " "; + exString += f; + exString += "\n"; + } } - exString += typeStr.toUtf8().toStdString() + ": " + valueStr.toUtf8().toStdString() + "\n"; + exString += typeStr; + exString += ": "; + exString += valueStr; + exString += "\n"; _frame *frame = PyEval_GetFrame(); diff --git a/qrenderdoc/Code/pyrenderdoc/interface_check.h b/qrenderdoc/Code/pyrenderdoc/interface_check.h index 9cdfa548c..434ac94bd 100644 --- a/qrenderdoc/Code/pyrenderdoc/interface_check.h +++ b/qrenderdoc/Code/pyrenderdoc/interface_check.h @@ -43,42 +43,40 @@ enum class NameType Member, }; -inline bool checkname(const char *baseType, std::string name, NameType nameType) +inline bool checkname(const char *baseType, rdcstr name, NameType nameType) { // skip __ prefixed names - if(name.length() > 2 && name[0] == '_' && name[1] == '_') + if(name.beginsWith("__")) return false; // skip any rdctype based types that are converted into equivalent python types - if((baseType && strstr(baseType, "rdcarray")) || name.find("rdcarray") != std::string::npos) + if((baseType && strstr(baseType, "rdcarray")) || name.contains("rdcarray")) return false; - if((baseType && strstr(baseType, "bytebuf")) || name.find("bytebuf") != std::string::npos) + if((baseType && strstr(baseType, "bytebuf")) || name.contains("bytebuf")) return false; - if((baseType && strstr(baseType, "rdcstr")) || name.find("rdcstr") != std::string::npos) + if((baseType && strstr(baseType, "rdcstr")) || name.contains("rdcstr")) return false; if((baseType && strstr(baseType, "StructuredBufferList")) || - name.find("StructuredBufferList") != std::string::npos) + name.contains("StructuredBufferList")) return false; - if((baseType && strstr(baseType, "StructuredChunkList")) || - name.find("StructuredChunkList") != std::string::npos) + if((baseType && strstr(baseType, "StructuredChunkList")) || name.contains("StructuredChunkList")) return false; if((baseType && strstr(baseType, "StructuredObjectList")) || - name.find("StructuredObjectList") != std::string::npos) + name.contains("StructuredObjectList")) return false; // allow the config to have different names - if((baseType && strstr(baseType, "PersistantConfig")) || - name.find("PersistantConfig") != std::string::npos) + if((baseType && strstr(baseType, "PersistantConfig")) || name.contains("PersistantConfig")) return false; // skip swig internal type - if((baseType && strstr(baseType, "SwigPyObject")) || name.find("SwigPyObject") != std::string::npos) + if((baseType && strstr(baseType, "SwigPyObject")) || name.contains("SwigPyObject")) return false; // remove the module prefix, if this is a type name we're checking - if(!strncmp(name.c_str(), "renderdoc.", 10)) + if(name.beginsWith("renderdoc.")) name.erase(0, 10); - if(!strncmp(name.c_str(), "qrenderdoc.", 11)) + if(name.beginsWith("qrenderdoc.")) name.erase(0, 11); // skip a few well-known members @@ -94,7 +92,7 @@ inline bool checkname(const char *baseType, std::string name, NameType nameType) else badfirstChar = name[0] < 'A' || name[0] > 'Z'; - if(badfirstChar || name.find('_') != std::string::npos) + if(badfirstChar || name.contains('_')) { const char *nameTypeStr = ""; @@ -126,7 +124,7 @@ inline bool check_interface(swig_type_info **swig_types, size_t numTypes) // the end of the world. bool errors_found = false; - std::set docstrings; + std::set docstrings; for(size_t i = 0; i < numTypes; i++) { SwigPyClientData *typeinfo = (SwigPyClientData *)swig_types[i]->clientdata; @@ -137,7 +135,7 @@ inline bool check_interface(swig_type_info **swig_types, size_t numTypes) PyTypeObject *typeobj = typeinfo->pytype; - std::string typedoc = typeobj->tp_doc; + rdcstr typedoc = typeobj->tp_doc; auto result = docstrings.insert(typedoc); @@ -162,7 +160,7 @@ inline bool check_interface(swig_type_info **swig_types, size_t numTypes) if(keys) { - std::set constants; + std::set constants; Py_ssize_t len = PyList_Size(keys); for(Py_ssize_t i = 0; i < len; i++) @@ -187,7 +185,7 @@ inline bool check_interface(swig_type_info **swig_types, size_t numTypes) } else { - std::string name(str, str + len); + rdcstr name(str, len); NameType nameType = NameType::Member; @@ -211,29 +209,27 @@ inline bool check_interface(swig_type_info **swig_types, size_t numTypes) if(!constants.empty()) { - std::set documented; - - const char *docstring = typedoc.data(); + std::set documented; const char identifier[] = ".. data::"; - const char *datadoc = strstr(docstring, identifier); + int32_t offs = typedoc.find(identifier); - while(datadoc) + while(offs >= 0) { - datadoc += sizeof(identifier) - 1; + offs += sizeof(identifier) - 1; - while(isspace(*datadoc)) - datadoc++; + while(isspace(typedoc[offs])) + offs++; - const char *eol = strchr(datadoc, '\n'); + int32_t eol = typedoc.indexOf('\n', offs); - if(!eol) + if(eol < 0) break; - documented.insert(std::string(datadoc, eol)); + documented.insert(typedoc.substr(offs, eol - offs)); - datadoc = strstr(datadoc, identifier); + offs = typedoc.find(identifier, offs); } for(auto it = constants.begin(); it != constants.end(); ++it) @@ -259,17 +255,17 @@ inline bool check_interface(swig_type_info **swig_types, size_t numTypes) while(method->ml_doc) { - std::string method_doc = method->ml_doc; + rdcstr method_doc = method->ml_doc; errors_found |= checkname(typeobj->tp_name, method->ml_name, NameType::Method); - size_t i = 0; + int32_t i = 0; while(method_doc[i] == '\n') i++; // skip the first line as it's autodoc generated i = method_doc.find('\n', i); - if(i != std::string::npos) + if(i >= 0) { while(method_doc[i] == '\n') i++; diff --git a/qrenderdoc/Code/pyrenderdoc/renderdoc.i b/qrenderdoc/Code/pyrenderdoc/renderdoc.i index bb20f194c..801fa941e 100644 --- a/qrenderdoc/Code/pyrenderdoc/renderdoc.i +++ b/qrenderdoc/Code/pyrenderdoc/renderdoc.i @@ -84,6 +84,7 @@ %ignore rdcstr; %ignore rdcliteral; %ignore rdcpair; +%ignore bytebuf; // special handling for RENDERDOC_GetDefaultCaptureOptions to transform output parameter to a return value %typemap(in, numinputs=0) CaptureOptions *defaultOpts { $1 = new CaptureOptions; } diff --git a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp index 582445410..6ebdb5866 100644 --- a/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp +++ b/qrenderdoc/Windows/Dialogs/PerformanceCounterSelection.cpp @@ -278,7 +278,7 @@ void PerformanceCounterSelection::SetCounters(const QVector RDTreeWidgetItem *currentRoot = NULL; CounterFamily currentFamily = CounterFamily::Unknown; - std::unordered_map categories; + QMap categories; for(const CounterDescription &desc : descriptions) { @@ -301,7 +301,7 @@ void PerformanceCounterSelection::SetCounters(const QVector RDTreeWidgetItem *categoryItem = NULL; - const std::string category = desc.category; + const rdcstr category = desc.category; auto categoryIterator = categories.find(category); if(categoryIterator == categories.end()) @@ -317,7 +317,7 @@ void PerformanceCounterSelection::SetCounters(const QVector } else { - categoryItem = categoryIterator->second; + categoryItem = categoryIterator.value(); } RDTreeWidgetItem *counterItem = new RDTreeWidgetItem(); diff --git a/renderdoc/3rdparty/catch/catch.cpp b/renderdoc/3rdparty/catch/catch.cpp index f68b55b3d..ba71454a7 100644 --- a/renderdoc/3rdparty/catch/catch.cpp +++ b/renderdoc/3rdparty/catch/catch.cpp @@ -109,7 +109,9 @@ struct AppVeyorListener : Catch::TestEventListenerBase << "\n"; } - errorList += msg.str(); + std::string formatted = msg.str(); + + errorList += rdcstr(formatted.c_str(), formatted.size()); } return true; @@ -126,7 +128,8 @@ struct AppVeyorListener : Catch::TestEventListenerBase { m_testcases.push_back({ durationInSeconds, testCaseStats.totals.assertions.allOk(), errorList, - testCaseStats.testInfo.name, testCaseStats.testInfo.lineInfo.file, + rdcstr(testCaseStats.testInfo.name.c_str(), testCaseStats.testInfo.name.size()), + testCaseStats.testInfo.lineInfo.file, }); errorList.clear(); diff --git a/renderdoc/3rdparty/catch/catch.hpp b/renderdoc/3rdparty/catch/catch.hpp index 3fc35c35c..971706696 100644 --- a/renderdoc/3rdparty/catch/catch.hpp +++ b/renderdoc/3rdparty/catch/catch.hpp @@ -25,25 +25,38 @@ // this file exists just to wrap the *real* catch.hpp and define any configuration defines we always // want on. -#define CATCH_CONFIG_FALLBACK_STRINGIFIER ToStr +#define CATCH_CONFIG_FALLBACK_STRINGIFIER ToStrAsStdString #define CATCH_CONFIG_FORCE_FALLBACK_STRINGIFIER #define CATCH_CONFIG_INLINE_DEBUG_BREAK #include "api/replay/rdcstr.h" #include "api/replay/stringise.h" -#include "official/catch.hpp" +#include +#include + +template +std::string ToStrAsStdString(const T &el) +{ + rdcstr s = ToStr(el); + return std::string(s.begin(), s.end()); +} inline std::ostream &operator<<(std::ostream &os, rdcstr const &str) { - return os << str.c_str(); + return os << std::string(str.begin(), str.end()); } +#include "official/catch.hpp" + namespace Catch { template <> struct StringMaker { - static std::string convert(rdcstr const &value) { return value; } + static std::string convert(rdcstr const &value) + { + return std::string(value.begin(), value.end()); + } }; } diff --git a/renderdoc/api/replay/rdcarray.h b/renderdoc/api/replay/rdcarray.h index 174068c76..fdc20c2dc 100644 --- a/renderdoc/api/replay/rdcarray.h +++ b/renderdoc/api/replay/rdcarray.h @@ -30,7 +30,6 @@ #include #include #include -#include #ifdef RENDERDOC_EXPORTS #include // for malloc/free @@ -421,7 +420,6 @@ public: } // a couple of helpers - inline void insert(size_t offs, const std::vector &in) { insert(offs, in.data(), in.size()); } inline void insert(size_t offs, const std::initializer_list &in) { insert(offs, in.begin(), in.size()); @@ -553,12 +551,6 @@ public: allocatedCount = usedCount = 0; assign(in, count); } - rdcarray(const std::vector &in) - { - elems = NULL; - allocatedCount = usedCount = 0; - assign(in); - } rdcarray(const std::initializer_list &in) { elems = NULL; @@ -613,27 +605,10 @@ public: } // assign forwards to operator = - inline void assign(const std::vector &in) { *this = in; } inline void assign(const std::initializer_list &in) { *this = in; } inline void assign(const rdcarray &in) { *this = in; } ///////////////////////////////////////////////////////////////// // assignment operators - rdcarray &operator=(const std::vector &in) - { - // make sure we have enough space, allocating more if needed - reserve(in.size()); - // destruct the old objects - clear(); - - // update new size - setUsedCount(in.size()); - - // copy construct the new elems - ItemCopyHelper::copyRange(elems, in.data(), usedCount); - - return *this; - } - rdcarray &operator=(const std::initializer_list &in) { // make sure we have enough space, allocating more if needed @@ -746,7 +721,6 @@ typedef uint8_t byte; struct bytebuf : public rdcarray { bytebuf() : rdcarray() {} - bytebuf(const std::vector &in) : rdcarray(in) {} bytebuf(const std::initializer_list &in) : rdcarray(in) {} bytebuf(const byte *in, size_t size) : rdcarray(in, size) {} #if defined(RENDERDOC_QT_COMPAT) diff --git a/renderdoc/api/replay/rdcstr.h b/renderdoc/api/replay/rdcstr.h index 0881bf6d4..97b8f2ac7 100644 --- a/renderdoc/api/replay/rdcstr.h +++ b/renderdoc/api/replay/rdcstr.h @@ -24,9 +24,9 @@ #pragma once -#include // for standard types -#include // for memcpy, etc -#include +#include // for standard types +#include // for memcpy, etc +#include // for std::swap #ifdef RENDERDOC_EXPORTS #include // for malloc/free @@ -238,11 +238,6 @@ public: memset(&d, 0, sizeof(d)); assign(in); } - rdcstr(const std::string &in) - { - memset(&d, 0, sizeof(d)); - assign(in.c_str(), in.size()); - } rdcstr(const char *const in) { memset(&d, 0, sizeof(d)); @@ -259,11 +254,6 @@ public: assign(in); return *this; } - rdcstr &operator=(const std::string &in) - { - assign(in.c_str(), in.size()); - return *this; - } rdcstr &operator=(const char *const in) { assign(in, strlen(in)); @@ -321,7 +311,6 @@ public: void assign(const char *const str) { assign(str, strlen(str)); } // in-place modification functions void append(const char *const str) { append(str, strlen(str)); } - void append(const std::string &str) { append(str.c_str(), str.size()); } void append(const rdcstr &str) { append(str.c_str(), str.size()); } void append(const char *const str, size_t length) { insert(size(), str, length); } void erase(size_t offs, size_t count) @@ -343,7 +332,6 @@ public: } void insert(size_t offset, const char *const str) { insert(offset, str, strlen(str)); } - void insert(size_t offset, const std::string &str) { insert(offset, str.c_str(), str.size()); } void insert(size_t offset, const rdcstr &str) { insert(offset, str.c_str(), str.size()); } void insert(size_t offset, char c) { insert(offset, &c, 1); } void insert(size_t offset, const char *const instr, size_t length) @@ -400,13 +388,6 @@ public: memset(data(), c, count); } - // cast operators - operator std::string() const - { - const char *s = c_str(); - return std::string(s, s + size()); - } - // read-only by-value accessor can look up directly in c_str() since it can't be modified const char &operator[](size_t i) const { return c_str()[i]; } // assignment operator must make the string mutable first @@ -611,11 +592,6 @@ public: append(str, strlen(str)); return *this; } - rdcstr &operator+=(const std::string &str) - { - append(str.c_str(), str.size()); - return *this; - } rdcstr &operator+=(const rdcstr &str) { append(str.c_str(), str.size()); @@ -632,12 +608,6 @@ public: ret += str; return ret; } - rdcstr operator+(const std::string &str) const - { - rdcstr ret = *this; - ret += str; - return ret; - } rdcstr operator+(const rdcstr &str) const { rdcstr ret = *this; @@ -740,10 +710,6 @@ public: { return find(needle.c_str(), needle.size(), first, last); } - int32_t find(const std::string &needle, int32_t first = 0, int32_t last = -1) const - { - return find(needle.c_str(), needle.size(), first, last); - } int32_t find(const char *needle, int32_t first = 0, int32_t last = -1) const { return find(needle, strlen(needle), first, last); @@ -815,7 +781,6 @@ private: public: bool contains(char needle) const { return indexOf(needle) != -1; } bool contains(const rdcstr &needle) const { return find(needle) != -1; } - bool contains(const std::string &needle) const { return find(needle) != -1; } bool contains(const char *needle) const { return find(needle) != -1; } bool beginsWith(const rdcstr &beginning) const { @@ -892,10 +857,8 @@ public: return size() == 0; return !strcmp(o, c_str()); } - bool operator==(const std::string &o) const { return o == c_str(); } // for inverse check just reverse results of above bool operator!=(const char *const o) const { return !(*this == o); } - bool operator!=(const std::string &o) const { return !(*this == o); } bool operator!=(const rdcstr &o) const { return !(*this == o); } // define ordering operators bool operator<(const rdcstr &o) const { return strcmp(c_str(), o.c_str()) < 0; } @@ -952,31 +915,16 @@ inline rdcstr operator+(const char *const left, const rdcstr &right) return rdcstr(left) += right; } -inline rdcstr operator+(const std::string &left, const rdcstr &right) -{ - return rdcstr(left) += right; -} - inline bool operator==(const char *const left, const rdcstr &right) { return right == left; } -inline bool operator==(const std::string &left, const rdcstr &right) -{ - return right == left; -} - inline bool operator!=(const char *const left, const rdcstr &right) { return right != left; } -inline bool operator!=(const std::string &left, const rdcstr &right) -{ - return right != left; -} - #if defined(RENDERDOC_QT_COMPAT) inline rdcstr operator+(const QString &left, const rdcstr &right) { diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index de20087b8..e2cc11555 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -24,6 +24,7 @@ ******************************************************************************/ #include "replay_proxy.h" +#include #include "3rdparty/lz4/lz4.h" #include "serialise/lz4io.h" @@ -1790,6 +1791,12 @@ struct DeltaSection { uint64_t offs = 0; bytebuf contents; + + void swap(DeltaSection &o) + { + std::swap(offs, o.offs); + contents.swap(o.contents); + } }; DECLARE_REFLECTION_STRUCT(DeltaSection); @@ -1804,10 +1811,6 @@ void DoSerialise(SerialiserType &ser, DeltaSection &el) template void ReplayProxy::DeltaTransferBytes(SerialiserType &xferser, bytebuf &referenceData, bytebuf &newData) { - // we use a list so that we don't have to reserve and pushing new sections will never cause - // previous ones to be reallocated and move around lots of data. - std::list deltas; - // lz4 compress if(xferser.IsReading()) { @@ -1822,6 +1825,8 @@ void ReplayProxy::DeltaTransferBytes(SerialiserType &xferser, bytebuf &reference } else { + rdcarray deltas; + { ReadSerialiser ser( new StreamReader(new LZ4Decompressor(xferser.GetReader(), Ownership::Nothing), @@ -1888,11 +1893,15 @@ void ReplayProxy::DeltaTransferBytes(SerialiserType &xferser, bytebuf &reference { uint64_t uncompSize = 0; + // we use a list so that we don't have to reserve and pushing new sections will never cause + // previous ones to be reallocated and move around lots of data. + std::list deltasList; + if(referenceData.empty()) { // no previous reference data, need to transfer the whole object. - deltas.resize(1); - deltas.back().contents = newData; + deltasList.resize(1); + deltasList.back().contents = newData; } else { @@ -1902,8 +1911,8 @@ void ReplayProxy::DeltaTransferBytes(SerialiserType &xferser, bytebuf &reference referenceData.size(), newData.size()); // re-transfer the whole block, something went seriously wrong if the resource changed size. - deltas.resize(1); - deltas.back().contents = newData; + deltasList.resize(1); + deltasList.back().contents = newData; } else { @@ -1956,9 +1965,9 @@ void ReplayProxy::DeltaTransferBytes(SerialiserType &xferser, bytebuf &reference // contents and move to state 2 if(chunkDiff) { - deltas.push_back(DeltaSection()); - deltas.back().offs = src - srcBegin; - deltas.back().contents.append(src, chunkSize); + deltasList.push_back(DeltaSection()); + deltasList.back().offs = src - srcBegin; + deltasList.back().contents.append(src, chunkSize); state = DeltaState::Active; } @@ -1969,7 +1978,7 @@ void ReplayProxy::DeltaTransferBytes(SerialiserType &xferser, bytebuf &reference // continue to append to the delta if there's another difference in this chunk. if(chunkDiff) { - deltas.back().contents.append(src, chunkSize); + deltasList.back().contents.append(src, chunkSize); } else { @@ -1988,13 +1997,26 @@ void ReplayProxy::DeltaTransferBytes(SerialiserType &xferser, bytebuf &reference // we ended in the active state. if(bytesRemain > 0 && memcmp(src, dst, bytesRemain)) { - deltas.push_back(DeltaSection()); - deltas.back().offs = src - srcBegin; - deltas.back().contents.append(src, bytesRemain); + deltasList.push_back(DeltaSection()); + deltasList.back().offs = src - srcBegin; + deltasList.back().contents.append(src, bytesRemain); } } } + // serialise as an array, move the storage from the list into here + rdcarray deltas(deltasList.size()); + + { + // swap between the list and array, so all the buffers just move storage + size_t i = 0; + for(auto it = deltasList.begin(); it != deltasList.end(); it++) + { + deltas[i].swap(*it); + i++; + } + } + // fast path - no changes. if(deltas.empty()) { diff --git a/renderdoc/data/glsl_shaders.cpp b/renderdoc/data/glsl_shaders.cpp index b560ca738..e21285b14 100644 --- a/renderdoc/data/glsl_shaders.cpp +++ b/renderdoc/data/glsl_shaders.cpp @@ -136,7 +136,7 @@ rdcstr GenerateGLSLShader(const rdcstr &shader, ShaderType type, int version, co std::string outstr; success = sh.preprocess(GetDefaultResources(), 100, ENoProfile, false, false, flags, &outstr, incl); - ret = outstr; + ret.assign(outstr.c_str(), outstr.size()); } int offs = ret.find(include_ext); diff --git a/renderdoc/driver/gl/gl_shader_refl.cpp b/renderdoc/driver/gl/gl_shader_refl.cpp index e3972a829..8847c99e3 100644 --- a/renderdoc/driver/gl/gl_shader_refl.cpp +++ b/renderdoc/driver/gl/gl_shader_refl.cpp @@ -270,10 +270,14 @@ GLuint MakeSeparableShaderProgram(WrappedOpenGL &drv, GLenum type, rdcarraygetUniformBlock(index).getBinding(); @@ -302,8 +302,8 @@ void glslangGetProgramResourceiv(glslang::TProgram *program, ReflectionInterface // add on the array index, if it exists, to the retrieved binding which is only for the base // variable - int offs = name.indexOf('['); - if(offs > 0) + size_t offs = name.find('['); + if(offs != std::string::npos) { char *nm = &name[offs + 1]; diff --git a/renderdoc/driver/shaders/spirv/spirv_compile.cpp b/renderdoc/driver/shaders/spirv/spirv_compile.cpp index 19d72bd96..fa4e55344 100644 --- a/renderdoc/driver/shaders/spirv/spirv_compile.cpp +++ b/renderdoc/driver/shaders/spirv/spirv_compile.cpp @@ -120,7 +120,7 @@ rdcstr rdcspv::Compile(const rdcspv::CompilationSettings &settings, const rdcarr std::vector spirvVec; glslang::GlslangToSpv(*intermediate, spirvVec, &opts); - spirv = spirvVec; + spirv.assign(spirvVec.data(), spirvVec.size()); } delete program; diff --git a/renderdoc/replay/basic_types_tests.cpp b/renderdoc/replay/basic_types_tests.cpp index b85d2f0ea..2644295fc 100644 --- a/renderdoc/replay/basic_types_tests.cpp +++ b/renderdoc/replay/basic_types_tests.cpp @@ -169,37 +169,6 @@ TEST_CASE("Test array type", "[basictypes]") { rdcarray test; - SECTION("std::vector") - { - std::vector vec = {2, 3, 4, 5}; - - test = vec; - - REQUIRE(test.size() == 4); - CHECK(test[0] == 2); - CHECK(test[1] == 3); - CHECK(test[2] == 4); - CHECK(test[3] == 5); - - rdcarray cc(vec); - - REQUIRE(cc.size() == 4); - CHECK(cc[0] == 2); - CHECK(cc[1] == 3); - CHECK(cc[2] == 4); - CHECK(cc[3] == 5); - - rdcarray ass; - - ass.assign(vec); - - REQUIRE(ass.size() == 4); - CHECK(ass[0] == 2); - CHECK(ass[1] == 3); - CHECK(ass[2] == 4); - CHECK(ass[3] == 5); - }; - SECTION("std::initializer_list") { test = {2, 3, 4, 5}; @@ -828,7 +797,6 @@ TEST_CASE("Test string type", "[basictypes][string]") CHECK(test == ""); CHECK(test == ((const char *)NULL)); CHECK(test == rdcstr()); - CHECK(test == std::string()); }; SECTION("Empty string after containing data") @@ -867,7 +835,6 @@ TEST_CASE("Test string type", "[basictypes][string]") CHECK(strcmp(test.c_str(), str) == 0); CHECK(test != ((const char *)NULL)); CHECK(test == str); - CHECK(test == std::string(str)); CHECK(test == rdcstr(str)); CHECK_NULL_TERM(test); @@ -898,7 +865,6 @@ TEST_CASE("Test string type", "[basictypes][string]") CHECK(test.c_str() != NULL); CHECK(strcmp(test.c_str(), str) < 0); CHECK(test != str); - CHECK(test != std::string(str)); CHECK(test != rdcstr(str)); CHECK_NULL_TERM(test); diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index ba6da9ab1..f3997e1ef 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -878,12 +878,6 @@ void DoSerialise(SerialiserType &ser, SDObject *el) ///////////////////////////////////////////////////////////// // Basic types -template <> -rdcstr DoStringise(const std::string &el) -{ - return el; -} - template <> rdcstr DoStringise(const rdcstr &el) { diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index 6bbe5d185..f4265d3b4 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -24,7 +24,6 @@ #pragma once -#include #include #include "api/replay/structured_data.h" #include "common/formatting.h" @@ -426,80 +425,6 @@ public: return *this; } - Serialiser &Serialise(const rdcliteral &name, std::vector &el, - SerialiserFlags flags = SerialiserFlags::NoFlags) - { - uint64_t count = (uint64_t)el.size(); - - { - m_InternalElement = true; - DoSerialise(*this, count); - m_InternalElement = false; - } - - if(IsReading()) - { - VerifyArraySize(count); - } - - if(ExportStructure()) - { - if(m_StructureStack.empty()) - { - RDCERR("Serialising object outside of chunk context! Start Chunk before any Serialise!"); - return *this; - } - - SDObject ¤t = *m_StructureStack.back(); - - current.data.basic.numChildren++; - current.data.children.push_back(new SDObject(name, "Byte Buffer"_lit)); - m_StructureStack.push_back(current.data.children.back()); - - SDObject &obj = *m_StructureStack.back(); - obj.type.basetype = SDBasic::Buffer; - obj.type.byteSize = count; - } - - { - if(IsWriting()) - { - // ensure byte alignment - m_Write->AlignTo(); - m_Write->Write(el.data(), count); - } - else if(IsReading()) - { - // ensure byte alignment - m_Read->AlignTo(); - - el.resize((size_t)count); - - m_Read->Read(el.data(), count); - } - } - - if(ExportStructure()) - { - if(m_ExportBuffers) - { - SDObject &obj = *m_StructureStack.back(); - - obj.data.basic.u = m_StructuredFile->buffers.size(); - - bytebuf *alloc = new bytebuf; - alloc->resize((size_t)count); - memcpy(alloc->data(), el.data(), alloc->size()); - - m_StructuredFile->buffers.push_back(alloc); - } - - m_StructureStack.pop_back(); - } - - return *this; - } - Serialiser &Serialise(const rdcliteral &name, void *&el, uint64_t byteSize, SerialiserFlags flags = SerialiserFlags::NoFlags) { @@ -755,149 +680,6 @@ public: } // specialisations for container types - template - Serialiser &Serialise(const rdcliteral &name, std::vector &el, - SerialiserFlags flags = SerialiserFlags::NoFlags) - { - uint64_t size = (uint64_t)el.size(); - - { - m_InternalElement = true; - DoSerialise(*this, size); - m_InternalElement = false; - } - - if(IsReading()) - { - VerifyArraySize(size); - } - - if(ExportStructure()) - { - if(m_StructureStack.empty()) - { - RDCERR("Serialising object outside of chunk context! Start Chunk before any Serialise!"); - return *this; - } - - SDObject &parent = *m_StructureStack.back(); - parent.data.basic.numChildren++; - parent.data.children.push_back(new SDObject(name, TypeName())); - m_StructureStack.push_back(parent.data.children.back()); - - SDObject &arr = *m_StructureStack.back(); - arr.type.basetype = SDBasic::Array; - arr.type.byteSize = size; - - arr.data.basic.numChildren = size; - arr.data.children.resize((size_t)size); - - if(IsReading()) - el.resize((size_t)size); - - for(size_t i = 0; i < (size_t)size; i++) - { - arr.data.children[i] = new SDObject("$el"_lit, TypeName()); - m_StructureStack.push_back(arr.data.children[i]); - - SDObject &obj = *m_StructureStack.back(); - - // default to struct. This will be overwritten if appropriate - obj.type.basetype = SDBasic::Struct; - obj.type.byteSize = sizeof(U); - - SerialiseDispatch::Do(*this, el[i]); - - m_StructureStack.pop_back(); - } - - m_StructureStack.pop_back(); - } - else - { - if(IsReading()) - el.resize((size_t)size); - - for(size_t i = 0; i < (size_t)size; i++) - SerialiseDispatch::Do(*this, el[i]); - } - - return *this; - } - - template - Serialiser &Serialise(const rdcliteral &name, std::list &el, - SerialiserFlags flags = SerialiserFlags::NoFlags) - { - uint64_t size = (uint64_t)el.size(); - - { - m_InternalElement = true; - DoSerialise(*this, size); - m_InternalElement = false; - } - - if(IsReading()) - { - VerifyArraySize(size); - } - - if(ExportStructure()) - { - if(m_StructureStack.empty()) - { - RDCERR("Serialising object outside of chunk context! Start Chunk before any Serialise!"); - return *this; - } - - SDObject &parent = *m_StructureStack.back(); - parent.data.basic.numChildren++; - parent.data.children.push_back(new SDObject(name, TypeName())); - m_StructureStack.push_back(parent.data.children.back()); - - SDObject &arr = *m_StructureStack.back(); - arr.type.basetype = SDBasic::Array; - arr.type.byteSize = size; - - arr.data.basic.numChildren = size; - arr.data.children.resize((size_t)size); - - if(IsReading()) - el.resize((size_t)size); - - auto it = el.begin(); - - for(size_t i = 0; i < (size_t)size; i++) - { - arr.data.children[i] = new SDObject("$el"_lit, TypeName()); - m_StructureStack.push_back(arr.data.children[i]); - - SDObject &obj = *m_StructureStack.back(); - - // default to struct. This will be overwritten if appropriate - obj.type.basetype = SDBasic::Struct; - obj.type.byteSize = sizeof(U); - - SerialiseDispatch::Do(*this, *it); - it++; - - m_StructureStack.pop_back(); - } - - m_StructureStack.pop_back(); - } - else - { - if(IsReading()) - el.resize((size_t)size); - - for(auto it = el.begin(); it != el.end(); ++it) - SerialiseDispatch::Do(*this, *it); - } - - return *this; - } - template Serialiser &Serialise(const rdcliteral &name, rdcarray &el, SerialiserFlags flags = SerialiserFlags::NoFlags) @@ -1381,35 +1163,6 @@ public: } } - // the only non POD basic type - void SerialiseValue(SDBasic type, size_t byteSize, std::string &el) - { - uint32_t len = 0; - - if(IsReading()) - { - m_Read->Read(len); - el.resize(len); - if(len > 0) - m_Read->Read(&el[0], len); - } - else - { - len = (uint32_t)el.length(); - m_Write->Write(len); - m_Write->Write(el.c_str(), len); - } - - if(ExportStructure()) - { - SDObject ¤t = *m_StructureStack.back(); - - current.type.basetype = type; - current.type.byteSize = len; - current.data.str = el; - } - } - void SerialiseValue(SDBasic type, size_t byteSize, rdcstr &el) { uint32_t len = 0; @@ -1679,16 +1432,6 @@ void DoSerialise(SerialiserType &ser, const char *&el) ser.SerialiseValue(SDBasic::String, 0, el); } -template <> -inline rdcliteral TypeName() -{ - return "string"_lit; -} -template -void DoSerialise(SerialiserType &ser, std::string &el) -{ - ser.SerialiseValue(SDBasic::String, 0, el); -} template <> inline rdcliteral TypeName() { diff --git a/renderdoc/serialise/serialiser_tests.cpp b/renderdoc/serialise/serialiser_tests.cpp index 7a14f3955..ef3b016ef 100644 --- a/renderdoc/serialise/serialiser_tests.cpp +++ b/renderdoc/serialise/serialiser_tests.cpp @@ -734,7 +734,6 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") rdcarray v; rdcpair p; - std::list l; v.push_back(1); v.push_back(1); @@ -745,16 +744,8 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") p = {3.14159f, "M_PI"}; - l.push_back(2U); - l.push_back(3U); - l.push_back(5U); - l.push_back(7U); - l.push_back(11U); - l.push_back(13U); - SERIALISE_ELEMENT(v); SERIALISE_ELEMENT(p); - SERIALISE_ELEMENT(l); } CHECK(buf->GetOffset() <= 128); @@ -771,11 +762,9 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") rdcarray v; rdcpair p; - std::list l; SERIALISE_ELEMENT(v); SERIALISE_ELEMENT(p); - SERIALISE_ELEMENT(l); ser.EndChunk(); @@ -784,7 +773,6 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") CHECK(ser.GetReader()->AtEnd()); REQUIRE(v.size() == 6); - REQUIRE(l.size() == 6); CHECK(v[0] == 1); CHECK(v[1] == 1); @@ -795,20 +783,6 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") CHECK(p.first == 3.14159f); CHECK(p.second == "M_PI"); - - auto it = l.begin(); - - CHECK(*it == 2U); - ++it; - CHECK(*it == 3U); - ++it; - CHECK(*it == 5U); - ++it; - CHECK(*it == 7U); - ++it; - CHECK(*it == 11U); - ++it; - CHECK(*it == 13U); } { @@ -820,11 +794,9 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") { rdcarray v; rdcpair p; - std::list l; SERIALISE_ELEMENT(v); SERIALISE_ELEMENT(p); - SERIALISE_ELEMENT(l); } ser.EndChunk(); @@ -841,7 +813,7 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") const SDChunk &chunk = *structData.chunks[0]; - CHECK(chunk.data.children.size() == 3); + CHECK(chunk.data.children.size() == 2); for(SDObject *o : chunk.data.children) REQUIRE(o); @@ -906,29 +878,6 @@ TEST_CASE("Read/write container types", "[serialiser][structured]") } } - { - SDObject &o = *chunk.data.children[childIdx++]; - - CHECK(o.name == "l"); - CHECK(o.type.basetype == SDBasic::Array); - CHECK(o.type.byteSize == 6); - CHECK(o.type.flags == SDTypeFlags::NoFlags); - CHECK(o.data.children.size() == 6); - - for(SDObject *child : o.data.children) - { - CHECK(child->type.basetype == SDBasic::UnsignedInteger); - CHECK(child->type.byteSize == 2); - } - - CHECK(o.data.children[0]->data.basic.u == 2U); - CHECK(o.data.children[1]->data.basic.u == 3U); - CHECK(o.data.children[2]->data.basic.u == 5U); - CHECK(o.data.children[3]->data.basic.u == 7U); - CHECK(o.data.children[4]->data.basic.u == 11U); - CHECK(o.data.children[5]->data.basic.u == 13U); - } - StreamWriter *rewriteBuf = new StreamWriter(StreamWriter::DefaultScratchSize); { diff --git a/renderdoccmd/renderdoccmd.cpp b/renderdoccmd/renderdoccmd.cpp index 93364310c..f559d29f0 100644 --- a/renderdoccmd/renderdoccmd.cpp +++ b/renderdoccmd/renderdoccmd.cpp @@ -28,6 +28,16 @@ #include #include +rdcstr conv(const std::string &s) +{ + return rdcstr(s.c_str(), s.size()); +} + +std::string conv(const rdcstr &s) +{ + return std::string(s.begin(), s.end()); +} + // normally this is in the renderdoc core library, but it's needed for the 'unknown enum' path, // so we implement it here using ostringstream. It's not great, but this is a very uncommon path - // either for invalid values or for when a new enum is added and the code isn't updated @@ -36,7 +46,7 @@ rdcstr DoStringise(const uint32_t &el) { std::ostringstream oss; oss << el; - return oss.str(); + return conv(oss.str()); } inline std::ostream &operator<<(std::ostream &os, rdcstr const &str) @@ -54,7 +64,7 @@ rdcarray convertArgs(const std::vector &args) rdcarray ret; ret.reserve(args.size()); for(size_t i = 0; i < args.size(); i++) - ret.push_back(args[i]); + ret.push_back(conv(args[i])); return ret; } @@ -641,8 +651,8 @@ struct formats_reader if(!f.openSupported && input) continue; - exts.push_back(f.extension); - names.push_back(f.name); + exts.push_back(conv(f.extension)); + names.push_back(conv(f.name)); } tmp->Shutdown(); @@ -699,8 +709,8 @@ struct ConvertCommand : public Command { std::cout << "Available formats:" << std::endl; for(CaptureFileFormat f : m_Formats) - std::cout << "'" << (std::string)f.extension << "': " << (std::string)f.name << std::endl - << " * " << (std::string)f.description << std::endl + std::cout << "'" << f.extension << "': " << f.name << std::endl + << " * " << f.description << std::endl << std::endl; return 0; } @@ -737,12 +747,9 @@ struct ConvertCommand : public Command // try to guess the format by looking for the extension in the filename for(CaptureFileFormat f : m_Formats) { - std::string extension = "."; - extension += f.extension; - - if(infile.find(extension.c_str()) != std::string::npos) + if(infile.find(conv("." + f.extension)) != std::string::npos) { - infmt = f.extension; + infmt = conv(f.extension); break; } } @@ -760,12 +767,9 @@ struct ConvertCommand : public Command // try to guess the format by looking for the extension in the filename for(CaptureFileFormat f : m_Formats) { - std::string extension = "."; - extension += f.extension; - - if(outfile.find(extension.c_str()) != std::string::npos) + if(outfile.find(conv("." + f.extension)) != std::string::npos) { - outfmt = f.extension; + outfmt = conv(f.extension); break; } } @@ -870,7 +874,7 @@ struct CapAltBitCommand : public Command virtual int Execute(cmdline::parser &parser, const CaptureOptions &) { CaptureOptions cmdopts; - cmdopts.DecodeFromString(parser.get("capopts")); + cmdopts.DecodeFromString(conv(parser.get("capopts"))); RENDERDOC_InitGlobalEnv(m_Env, rdcarray()); @@ -1153,11 +1157,11 @@ struct EmbeddedSectionCommand : public Command fclose(f); SectionProperties props; - props.name = section; + props.name = conv(section); for(SectionType s : values()) { - if(ToStr(s) == section) + if(ToStr(s) == props.name) { props.type = s; break; diff --git a/renderdoccmd/renderdoccmd_win32.cpp b/renderdoccmd/renderdoccmd_win32.cpp index 7b5de77b1..fc30ef8c0 100644 --- a/renderdoccmd/renderdoccmd_win32.cpp +++ b/renderdoccmd/renderdoccmd_win32.cpp @@ -560,7 +560,7 @@ struct CrashHandlerCommand : public Command milliseconds *= 1000; milliseconds += systime.wMilliseconds; - rdcstr dumpId; + std::string dumpId; char base62[63] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; while(milliseconds > 0) @@ -570,15 +570,18 @@ struct CrashHandlerCommand : public Command milliseconds /= 62; } - rdcstr reportPath = conv(dumpFolder) + "\\" + dumpId + ".zip"; + std::string reportPath = conv(dumpFolder) + "\\" + dumpId + ".zip"; - RENDERDOC_CreateBugReport(conv(wlogpath).c_str(), conv(wdump).c_str(), reportPath); + { + rdcstr tmp = rdcstr(reportPath.c_str(), reportPath.size()); + RENDERDOC_CreateBugReport(conv(wlogpath).c_str(), conv(wdump).c_str(), tmp); + } for(size_t i = 0; i < reportPath.size(); i++) if(reportPath[i] == '\\') reportPath[i] = '/'; - report += " \n\"report\": \"" + std::string(reportPath) + "\"\n"; + report += " \n\"report\": \"" + reportPath + "\"\n"; report += "}\n"; { @@ -668,9 +671,10 @@ struct GlobalHookCommand : public Command std::wstring wpathmatch = conv(parser.get("match")); std::string capfile = parser.get("capfile"); std::string debuglog = parser.get("debuglog"); + std::string opts = parser.get("capopts"); CaptureOptions cmdopts; - cmdopts.DecodeFromString(parser.get("capopts")); + cmdopts.DecodeFromString(rdcstr(opts.c_str(), opts.size())); // make sure the user doesn't accidentally run this with 'a' as a parameter or something. // "a.exe" is over 4 characters so this limit should not be a problem.