diff --git a/qrenderdoc/Code/Interface/PersistantConfig.cpp b/qrenderdoc/Code/Interface/PersistantConfig.cpp index da0b01f99..03ffa9a46 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.cpp +++ b/qrenderdoc/Code/Interface/PersistantConfig.cpp @@ -179,6 +179,23 @@ void PersistantConfig::applyValues(const QVariantMap &values) RENAMED_SETTING(QDateTime, DegradedLog_LastUpdate, DegradedCapture_LastUpdate); } +int PersistantConfig::RemoteHostCount() +{ + return RemoteHosts.count(); +} + +RemoteHost *PersistantConfig::GetRemoteHost(int index) +{ + if(index < 0 || index >= RemoteHostCount()) + return NULL; + return RemoteHosts[index]; +} + +void PersistantConfig::AddRemoteHost(RemoteHost host) +{ + RemoteHosts.push_back(new RemoteHost(host)); +} + void PersistantConfig::AddAndroidHosts() { QMap oldHosts; @@ -402,6 +419,11 @@ BugReport::BugReport(const QVariant &var) unreadUpdates = map[lit("unreadUpdates")].toBool(); } +rdcstr BugReport::URL() const +{ + return lit(BUGREPORT_URL "/report/%1").arg(QString(reportId)); +} + BugReport::operator QVariant() const { QVariantMap map; diff --git a/qrenderdoc/Code/Interface/PersistantConfig.h b/qrenderdoc/Code/Interface/PersistantConfig.h index 3edb8cb2c..b99ae415a 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.h +++ b/qrenderdoc/Code/Interface/PersistantConfig.h @@ -62,7 +62,7 @@ struct SPIRVDisassembler :return: The disassembly, or an empty string if something went wrong. :rtype: ``str`` )"); - QString DisassembleShader(QWidget *window, const ShaderReflection *reflection) const; + rdcstr DisassembleShader(QWidget *window, const ShaderReflection *reflection) const; }; DECLARE_REFLECTION_STRUCT(SPIRVDisassembler); @@ -95,9 +95,9 @@ struct BugReport DOCUMENT("The private ID of the bug report."); rdcstr reportId; DOCUMENT("The original date when this bug was submitted."); - QDateTime submitDate; + rdcdatetime submitDate; DOCUMENT("The last date that we checked for updates."); - QDateTime checkDate; + rdcdatetime checkDate; DOCUMENT("Unread updates to the bug exist"); bool unreadUpdates = false; @@ -106,7 +106,7 @@ struct BugReport :return: The URL to the report. :rtype: ``str`` )"); - rdcstr URL() const { return lit(BUGREPORT_URL "/report/%1").arg(QString(reportId)); } + rdcstr URL() const; }; DECLARE_REFLECTION_STRUCT(BugReport); @@ -188,11 +188,11 @@ DECLARE_REFLECTION_STRUCT(BugReport); \ CONFIG_SETTING_VAL(public, QString, rdcstr, CheckUpdate_UpdateResponse, "") \ \ - CONFIG_SETTING_VAL(public, QDateTime, QDateTime, CheckUpdate_LastUpdate, \ - QDateTime(QDate(2012, 06, 27), QTime(0, 0, 0))) \ + CONFIG_SETTING_VAL(public, QDateTime, rdcdatetime, CheckUpdate_LastUpdate, \ + rdcdatetime(2012, 06, 27)) \ \ - CONFIG_SETTING_VAL(public, QDateTime, QDateTime, DegradedCapture_LastUpdate, \ - QDateTime(QDate(2015, 01, 01), QTime(0, 0, 0))) \ + CONFIG_SETTING_VAL(public, QDateTime, rdcdatetime, DegradedCapture_LastUpdate, \ + rdcdatetime(2015, 01, 01)) \ \ CONFIG_SETTING_VAL(public, bool, bool, Tips_HasSeenFirst, false) \ \ @@ -570,25 +570,20 @@ public: :return: The number of remote hosts. :rtype: ``int`` )"); - int RemoteHostCount() { return RemoteHosts.count(); } + int RemoteHostCount(); DOCUMENT(R"(Returns a given remote host at an index. :param int index: The index of the remote host to retrieve :return: The remote host specified, or ``None`` if an invalid index was passed :rtype: ``RemoteHost`` )"); - RemoteHost *GetRemoteHost(int index) - { - if(index < 0 || index >= RemoteHostCount()) - return NULL; - return RemoteHosts[index]; - } + RemoteHost *GetRemoteHost(int index); DOCUMENT(R"(Adds a new remote host. :param RemoteHost host: The remote host to add. R)"); - void AddRemoteHost(RemoteHost host) { RemoteHosts.push_back(new RemoteHost(host)); } + void AddRemoteHost(RemoteHost host); DOCUMENT("If configured, queries ``adb`` to add android hosts to :data:`RemoteHosts`."); void AddAndroidHosts(); @@ -657,8 +652,11 @@ sure the new style is applied, the application should be restarted. private: bool Deserialize(const rdcstr &filename); bool Serialize(const rdcstr &filename); + +#if !defined(SWIG_GENERATED) QVariantMap storeValues() const; void applyValues(const QVariantMap &values); +#endif rdcstr m_Filename; }; diff --git a/qrenderdoc/Code/Interface/QRDInterface.h b/qrenderdoc/Code/Interface/QRDInterface.h index 4900d2666..d62326f04 100644 --- a/qrenderdoc/Code/Interface/QRDInterface.h +++ b/qrenderdoc/Code/Interface/QRDInterface.h @@ -1,11 +1,9 @@ #pragma once -// take care before adding any more headers here, as they must be converted to python types. Any -// types in the RenderDoc core interface are already wrapped, and Qt types must either be manually -// converted directly to python, or interfaced with PySide, otherwise we get into the situation -// where pyside and SWIG have independent incompatible wrappers of Qt types -#include - +// don't add any Qt headers visible to SWIG, as we don't want a Qt dependency for the SWIG-generated +// qrenderdoc module. Instead we should use public RDC types for any public QRenderDoc headers, and +// define conversions to/from Qt types. See rdcstr / QString, rdcpair / QPair, and +// rdcdatetime / QDateTime. #include // For string literals - use either tr() for translated strings, lit() for untranslated strings, or @@ -35,7 +33,7 @@ class QWidget; // we only support QVariant as an 'internal' interface, it's not exposed to python. However we need // to use it in constructors/operators so conditionally compile it rather than split small structs // into interface/implementations -#if defined(SWIG) +#if defined(SWIG) || defined(SWIG_GENERATED) #define VARIANT_CAST(classname) @@ -52,6 +50,7 @@ class QWidget; // is not exposed to swig #define RENDERDOC_QT_COMPAT #include +#include #include #include #include diff --git a/qrenderdoc/Code/Interface/SPIRVDisassembler.cpp b/qrenderdoc/Code/Interface/SPIRVDisassembler.cpp index b35dfbe22..aa3ee4661 100644 --- a/qrenderdoc/Code/Interface/SPIRVDisassembler.cpp +++ b/qrenderdoc/Code/Interface/SPIRVDisassembler.cpp @@ -27,11 +27,10 @@ #include "Code/QRDUtils.h" #include "QRDInterface.h" -QString SPIRVDisassembler::DisassembleShader(QWidget *window, - const ShaderReflection *shaderDetails) const +rdcstr SPIRVDisassembler::DisassembleShader(QWidget *window, const ShaderReflection *shaderDetails) const { if(executable.isEmpty()) - return QString(); + return ""; QString spv_bin_file = QDir(QDir::tempPath()).absoluteFilePath(lit("spv_bin.spv")); @@ -48,7 +47,7 @@ QString SPIRVDisassembler::DisassembleShader(QWidget *window, window, QApplication::translate("SPIRVDisassembler", "Error writing temp file"), QApplication::translate("SPIRVDisassembler", "Couldn't write temporary SPIR-V file %1.") .arg(spv_bin_file)); - return QString(); + return ""; } if(!QString(args).contains(lit("{spv_bin}"))) @@ -58,7 +57,7 @@ QString SPIRVDisassembler::DisassembleShader(QWidget *window, QApplication::translate( "SPIRVDisassembler", "Please use {spv_bin} in the disassembler arguments to specify the input file.")); - return QString(); + return ""; } QString glsl; diff --git a/qrenderdoc/Code/pyrenderdoc/CMakeLists.txt b/qrenderdoc/Code/pyrenderdoc/CMakeLists.txt index b652431c6..33ec09532 100644 --- a/qrenderdoc/Code/pyrenderdoc/CMakeLists.txt +++ b/qrenderdoc/Code/pyrenderdoc/CMakeLists.txt @@ -5,21 +5,6 @@ else () set (CMAKE_CXX_STANDARD 14) endif () -# Fetch the include and libs parameters for Qt -execute_process( - COMMAND pkg-config --cflags Qt5Widgets Qt5Core Qt5Gui - OUTPUT_VARIABLE QT5_INCLUDE - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND pkg-config --libs Qt5Widgets Qt5Core Qt5Gui - OUTPUT_VARIABLE QT5_LIBS - OUTPUT_STRIP_TRAILING_WHITESPACE) - -if(STATIC_QRENDERDOC) - set(QT5_LIBS "${QT5_LIBS} -lqtpcre") -endif() - # include paths for qrenderdoc, the internal renderdoc API, and Python set(MODULE_INCLUDES PRIVATE ${CMAKE_SOURCE_DIR}/qrenderdoc @@ -30,6 +15,8 @@ set(MODULE_INCLUDES set(MODULE_DEFINES PRIVATE -DRENDERDOC_PLATFORM_LINUX) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option -Wno-unused-private-field") + # Set up rpath to find librenderdoc.so set(CMAKE_SKIP_BUILD_RPATH TRUE) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) @@ -52,26 +39,15 @@ target_link_libraries(_renderdoc PRIVATE renderdoc) add_library(_qrenderdoc SHARED ${CMAKE_BINARY_DIR}/qrenderdoc/renderdoc_python.cxx ${CMAKE_BINARY_DIR}/qrenderdoc/qrenderdoc_python.cxx - ../Interface/CommonPipelineState.cpp - ../Interface/PersistantConfig.cpp - ../Interface/QRDInterface.cpp - ../Interface/RemoteHost.cpp pyrenderdoc_stub.cpp qrenderdoc_stub.cpp) set_source_files_properties(${CMAKE_BINARY_DIR}/qrenderdoc/qrenderdoc_python.cxx PROPERTIES GENERATED TRUE) -# Add in Qt includes and libraries -set (CMAKE_CXX_FLAGS "${QT5_INCLUDE} ${CMAKE_CXX_FLAGS}") -set (CMAKE_SHARED_LINKER_FLAGS "${QT5_LIBS} ${CMAKE_SHARED_LINKER_FLAGS}") -set (MODULE_LIBRARIES - PRIVATE renderdoc - ${QT5_LIBS}) - target_compile_definitions(_qrenderdoc ${MODULE_DEFINES}) target_include_directories(_qrenderdoc ${MODULE_INCLUDES}) -target_link_libraries(_qrenderdoc ${MODULE_LIBRARIES}) +target_link_libraries(_qrenderdoc PRIVATE renderdoc) # Don't prefix with lib, python expects a bare .so. # Also rename to non-underscore due to this (We couldn't call the diff --git a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp index 1631e08b9..d06712b88 100644 --- a/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp +++ b/qrenderdoc/Code/pyrenderdoc/PythonContext.cpp @@ -917,3 +917,13 @@ extern "C" void SetThreadBlocking(PyObject *global_handle, bool block) if(redirector && redirector->context) return redirector->context->setThreadBlocking(block); } + +extern "C" QWidget *QWidgetFromPy(PyObject *widget) +{ + return PythonContext::QWidgetFromPy(widget); +} + +extern "C" PyObject *QWidgetToPy(QWidget *widget) +{ + return PythonContext::QWidgetToPy(widget); +} \ No newline at end of file diff --git a/qrenderdoc/Code/pyrenderdoc/pyconversion.h b/qrenderdoc/Code/pyrenderdoc/pyconversion.h index 15ecdc203..eedd5154a 100644 --- a/qrenderdoc/Code/pyrenderdoc/pyconversion.h +++ b/qrenderdoc/Code/pyrenderdoc/pyconversion.h @@ -305,6 +305,33 @@ struct TypeConversion } }; +// specialisation for datetime +template <> +struct TypeConversion +{ + static int ConvertFromPy(PyObject *in, rdcdatetime &out) + { + if(!PyDateTime_Check(in)) + return SWIG_TypeError; + + out.year = PyDateTime_GET_YEAR(in); + out.month = PyDateTime_GET_MONTH(in); + out.day = PyDateTime_GET_DAY(in); + out.hour = PyDateTime_DATE_GET_HOUR(in); + out.minute = PyDateTime_DATE_GET_MINUTE(in); + out.second = PyDateTime_DATE_GET_SECOND(in); + out.microsecond = PyDateTime_TIME_GET_MICROSECOND(in); + + return SWIG_OK; + } + + static PyObject *ConvertToPy(const rdcdatetime &in) + { + return PyDateTime_FromDateAndTime(in.year, in.month, in.day, in.hour, in.minute, in.second, + in.microsecond); + } +}; + // specialisation for pair template struct TypeConversion, false> @@ -555,8 +582,6 @@ struct TypeConversion } }; -#include "qt_conversion.h" - #include "structured_conversion.h" // free functions forward to struct diff --git a/qrenderdoc/Code/pyrenderdoc/qrenderdoc.i b/qrenderdoc/Code/pyrenderdoc/qrenderdoc.i index e3431c3ee..6f524e28f 100644 --- a/qrenderdoc/Code/pyrenderdoc/qrenderdoc.i +++ b/qrenderdoc/Code/pyrenderdoc/qrenderdoc.i @@ -9,24 +9,16 @@ #define DOCUMENT4(text1, text2, text3, text4) %feature("docstring") text1 text2 text3 text4 %begin %{ - #undef slots + + #define SWIG_GENERATED %} %{ - #define ENABLE_QT_CONVERT - #define RENDERDOC_QT_COMPAT - - #include - #include - #include - #include - #include - #include - #include - #include "datetime.h" - +%} +%init %{ + PyDateTime_IMPORT; %} %include "pyconversion.i" @@ -34,14 +26,18 @@ // import the renderdoc interface that we depend on %import "renderdoc.i" -SIMPLE_TYPEMAPS(QString) -SIMPLE_TYPEMAPS(QDateTime) - TEMPLATE_ARRAY_DECLARE(rdcarray); // pass QWidget objects to PySide +%{ + class QWidget; + + extern "C" QWidget *QWidgetFromPy(PyObject *widget); + extern "C" PyObject *QWidgetToPy(QWidget *widget); +%} + %typemap(in) QWidget * { - $1 = PythonContext::QWidgetFromPy($input); + $1 = QWidgetFromPy($input); if($input && !$1) { SWIG_exception_fail(SWIG_TypeError, "in method '$symname' QWidget expected for argument $argnum of type '$1_basetype'"); @@ -49,7 +45,7 @@ TEMPLATE_ARRAY_DECLARE(rdcarray); } %typemap(out) QWidget * { - $result = PythonContext::QWidgetToPy($1); + $result = QWidgetToPy($1); } // need to ignore the original function and add a helper that releases the python GIL while calling @@ -63,12 +59,11 @@ TEMPLATE_ARRAY_DECLARE(rdcarray); %rename("%(regex:/^I([A-Z].*)/\\1/)s", %$isclass) ""; %{ -#ifndef slots -#define slots -#endif - #include "Code/Interface/QRDInterface.h" - #include "Code/pyrenderdoc/PythonContext.h" + + #ifndef slots + #define slots + #endif %} %include diff --git a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj index 0a5a23cd9..c3974d705 100644 --- a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj +++ b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj @@ -75,15 +75,15 @@ true true /wd4100 /wd4512 /wd4127 - $(ProjectDir)..\..\;..\..\3rdparty\python\include;$(SolutionDir)\renderdoc\api\replay;..\..\3rdparty\qt\$(Platform)\include;..\..\3rdparty\qt\$(Platform)\include\QtWidgets;..\..\3rdparty\qt\$(Platform)\include\QtGui;..\..\3rdparty\qt\$(Platform)\include\QtCore + $(ProjectDir)..\..\;..\..\3rdparty\python\include;$(SolutionDir)\renderdoc\api\replay 4714;%(DisableSpecificWarnings) Windows true Default - ..\..\3rdparty\python\$(Platform);..\..\3rdparty\qt\$(Platform)\lib;%(AdditionalLibraryDirectories) - python36.lib;Qt5Widgets.lib;Qt5Gui.lib;Qt5Core.lib;%(AdditionalDependencies) + ..\..\3rdparty\python\$(Platform);%(AdditionalLibraryDirectories) + python36.lib;%(AdditionalDependencies) true @@ -107,10 +107,6 @@ - - - - diff --git a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj.filters b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj.filters index 3b4b79ee3..a9fa02cf9 100644 --- a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj.filters +++ b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_module.vcxproj.filters @@ -2,23 +2,13 @@ + - - - Interface - - - Interface - - - Interface - - - Interface - + + diff --git a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp index 7f46c99d5..4a88c647e 100644 --- a/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp +++ b/qrenderdoc/Code/pyrenderdoc/qrenderdoc_stub.cpp @@ -23,47 +23,285 @@ ******************************************************************************/ #include -#include "Code/QRDUtils.h" -#include "Styles/StyleData.h" -#include "PythonContext.h" -namespace StyleData -{ -const ThemeDescriptor availStyles[] = { - ThemeDescriptor(QString(), QString(), QString(), []() -> QStyle * { return NULL; }), -}; -const int numAvailable = sizeof(availStyles) / sizeof(ThemeDescriptor); -}; +#define SWIG_GENERATED +#include "Code/Interface/QRDInterface.h" // we only support the qrenderdoc module for docs generation, so it doesn't matter that these stub // functions aren't valid -void Formatter::setParams(const PersistantConfig &config) +//////////////////////////////////////////////////////////////////////////////// +// QRDInterface.cpp stubs +//////////////////////////////////////////////////////////////////////////////// + +CaptureSettings::CaptureSettings() { + inject = false; + autoStart = false; + RENDERDOC_GetDefaultCaptureOptions(&options); } -bool SaveToJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion) +rdcstr configFilePath(const rdcstr &filename) { - return false; + return ""; } -bool LoadFromJSON(QVariantMap &data, QIODevice &f, const char *magicIdentifier, uint32_t magicVersion) -{ - return false; -} - -QWidget *PythonContext::QWidgetFromPy(PyObject *widget) +ICaptureContext *getCaptureContext(const QWidget *widget) { return NULL; } -PyObject *PythonContext::QtObjectToPython(const char *typeName, QObject *object) +//////////////////////////////////////////////////////////////////////////////// +// PythonContext.cpp stubs +//////////////////////////////////////////////////////////////////////////////// + +class QWidget; + +extern "C" QWidget *QWidgetFromPy(PyObject *widget) { return NULL; } -QString SPIRVDisassembler::DisassembleShader(QWidget *window, - const ShaderReflection *shaderDetails) const +extern "C" PyObject *QWidgetToPy(QWidget *widget) { - return QString(); + Py_IncRef(Py_None); + return Py_None; +} + +//////////////////////////////////////////////////////////////////////////////// +// SPIRVDisassembler.cpp stubs +//////////////////////////////////////////////////////////////////////////////// + +rdcstr SPIRVDisassembler::DisassembleShader(QWidget *window, const ShaderReflection *shaderDetails) const +{ + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +// PersistantConfig.cpp stubs +//////////////////////////////////////////////////////////////////////////////// + +rdcstr BugReport::URL() const +{ + return ""; +} + +bool PersistantConfig::SetStyle() +{ + return false; +} + +PersistantConfig::~PersistantConfig() +{ +} + +bool PersistantConfig::Load(const rdcstr &filename) +{ + return false; +} + +bool PersistantConfig::Save() +{ + return false; +} + +void PersistantConfig::Close() +{ +} + +int PersistantConfig::RemoteHostCount() +{ + return 0; +} + +RemoteHost *PersistantConfig::GetRemoteHost(int index) +{ + return NULL; +} + +void PersistantConfig::AddRemoteHost(RemoteHost host) +{ +} + +void PersistantConfig::AddAndroidHosts() +{ +} + +void PersistantConfig::SetupFormatting() +{ +} + +void AddRecentFile(rdcarray &recentList, const rdcstr &file, int maxItems) +{ +} + +void PersistantConfig::SetConfigSetting(const rdcstr &name, const rdcstr &value) +{ +} + +rdcstr PersistantConfig::GetConfigSetting(const rdcstr &name) +{ + return ""; +} + +//////////////////////////////////////////////////////////////////////////////// +// RemoteHost.cpp stubs +//////////////////////////////////////////////////////////////////////////////// + +RemoteHost::RemoteHost() +{ + serverRunning = connected = busy = versionMismatch = false; +} + +void RemoteHost::CheckStatus() +{ +} + +void RemoteHost::Launch() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// CommonPipelineState.cpp stubs +//////////////////////////////////////////////////////////////////////////////// + +rdcstr CommonPipelineState::GetResourceLayout(ResourceId id) +{ + return ""; +} + +rdcstr CommonPipelineState::Abbrev(ShaderStage stage) +{ + return ""; +} + +rdcstr CommonPipelineState::OutputAbbrev() +{ + return ""; +} + +const D3D11Pipe::Shader &CommonPipelineState::GetD3D11Stage(ShaderStage stage) +{ + static D3D11Pipe::Shader dummy; + return dummy; +} + +const D3D12Pipe::Shader &CommonPipelineState::GetD3D12Stage(ShaderStage stage) +{ + static D3D12Pipe::Shader dummy; + return dummy; +} + +const GLPipe::Shader &CommonPipelineState::GetGLStage(ShaderStage stage) +{ + static GLPipe::Shader dummy; + return dummy; +} + +const VKPipe::Shader &CommonPipelineState::GetVulkanStage(ShaderStage stage) +{ + static VKPipe::Shader dummy; + return dummy; +} + +rdcstr CommonPipelineState::GetShaderExtension() +{ + return ""; +} + +Viewport CommonPipelineState::GetViewport(int index) +{ + return Viewport(); +} + +Scissor CommonPipelineState::GetScissor(int index) +{ + return Scissor(); +} + +const ShaderBindpointMapping &CommonPipelineState::GetBindpointMapping(ShaderStage stage) +{ + static ShaderBindpointMapping dummy; + return dummy; +} + +const ShaderReflection *CommonPipelineState::GetShaderReflection(ShaderStage stage) +{ + return NULL; +} + +ResourceId CommonPipelineState::GetComputePipelineObject() +{ + return ResourceId(); +} + +ResourceId CommonPipelineState::GetGraphicsPipelineObject() +{ + return ResourceId(); +} + +rdcstr CommonPipelineState::GetShaderEntryPoint(ShaderStage stage) +{ + return ""; +} + +ResourceId CommonPipelineState::GetShader(ShaderStage stage) +{ + return ResourceId(); +} + +rdcstr CommonPipelineState::GetShaderName(ShaderStage stage) +{ + return ""; +} + +BoundVBuffer CommonPipelineState::GetIBuffer() +{ + return BoundVBuffer(); +} + +bool CommonPipelineState::IsStripRestartEnabled() +{ + return false; +} + +uint32_t CommonPipelineState::GetStripRestartIndex() +{ + return UINT32_MAX; +} + +rdcarray CommonPipelineState::GetVBuffers() +{ + return rdcarray(); +} + +rdcarray CommonPipelineState::GetVertexInputs() +{ + return rdcarray(); +} + +BoundCBuffer CommonPipelineState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx, + uint32_t ArrayIdx) +{ + return BoundCBuffer(); +} + +rdcarray CommonPipelineState::GetReadOnlyResources(ShaderStage stage) +{ + return rdcarray(); +} + +rdcarray CommonPipelineState::GetReadWriteResources(ShaderStage stage) +{ + return rdcarray(); +} + +BoundResource CommonPipelineState::GetDepthTarget() +{ + return BoundResource(); +} + +rdcarray CommonPipelineState::GetOutputTargets() +{ + return rdcarray(); } diff --git a/qrenderdoc/Code/pyrenderdoc/qt_conversion.h b/qrenderdoc/Code/pyrenderdoc/qt_conversion.h deleted file mode 100644 index f295059ed..000000000 --- a/qrenderdoc/Code/pyrenderdoc/qt_conversion.h +++ /dev/null @@ -1,323 +0,0 @@ -/****************************************************************************** - * The MIT License (MIT) - * - * Copyright (c) 2017 Baldur Karlsson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - ******************************************************************************/ - -#pragma once - -#ifdef ENABLE_QT_CONVERT - -template <> -struct TypeConversion -{ - static int ConvertFromPy(PyObject *in, QString &out) - { - if(PyUnicode_Check(in)) - { - PyObject *bytes = PyUnicode_AsUTF8String(in); - - if(!bytes) - return SWIG_ERROR; - - char *buf = NULL; - Py_ssize_t size = 0; - - int ret = PyBytes_AsStringAndSize(bytes, &buf, &size); - - if(ret == 0) - { - out = QString::fromUtf8(buf, (int)size); - - Py_DecRef(bytes); - - return SWIG_OK; - } - - Py_DecRef(bytes); - - return SWIG_ERROR; - } - - return SWIG_ERROR; - } - - static PyObject *ConvertToPy(const QString &in) - { - QByteArray bytes = in.toUtf8(); - return PyUnicode_FromStringAndSize(bytes.data(), bytes.size()); - } -}; - -template <> -struct TypeConversion -{ - static int ConvertFromPy(PyObject *in, QDateTime &out) - { - if(!PyDateTime_Check(in)) - return SWIG_TypeError; - - QDate date(PyDateTime_GET_YEAR(in), PyDateTime_GET_MONTH(in), PyDateTime_GET_DAY(in)); - QTime time(PyDateTime_DATE_GET_HOUR(in), PyDateTime_DATE_GET_MINUTE(in), - PyDateTime_DATE_GET_SECOND(in), PyDateTime_DATE_GET_MICROSECOND(in) / 1000); - - out = QDateTime(date, time, QTimeZone::utc()); - - return SWIG_OK; - } - - static PyObject *ConvertToPy(const QDateTime &in) - { - QDate date = in.date(); - QTime time = in.time(); - return PyDateTime_FromDateAndTime(date.year(), date.month(), date.day(), time.hour(), - time.minute(), time.second(), time.msec() * 1000); - } -}; - -template -struct ContainerConversion -{ - // we add some extra parameters so the typemaps for array can use these to get - // nicer failure error messages out with the index that failed - static int ConvertFromPy(PyObject *in, Container &out, int *failIdx) - { - if(!PyList_Check(in)) - return SWIG_TypeError; - - Py_ssize_t len = PyList_Size(in); - - for(Py_ssize_t i = 0; i < len; i++) - { - U u; - int ret = TypeConversion::ConvertFromPy(PyList_GetItem(in, i), u); - if(!SWIG_IsOK(ret)) - { - if(failIdx) - *failIdx = i; - return ret; - } - out.append(u); - } - - return SWIG_OK; - } - - static int ConvertFromPy(PyObject *in, Container &out) { return ConvertFromPy(in, out, NULL); } - static PyObject *ConvertToPyInPlace(PyObject *list, const Container &in, int *failIdx) - { - for(int i = 0; i < in.size(); i++) - { - PyObject *elem = TypeConversion::ConvertToPy(in[i]); - - if(elem) - { - PyList_Append(list, elem); - // release our reference - Py_DecRef(elem); - } - else - { - if(failIdx) - *failIdx = i; - - return NULL; - } - } - - return list; - } - - static PyObject *ConvertToPy(const Container &in, int *failIdx) - { - PyObject *list = PyList_New(0); - if(!list) - return NULL; - - PyObject *ret = ConvertToPyInPlace(list, in, failIdx); - - // if a failure happened, don't leak the list we created - if(!ret) - Py_XDECREF(list); - - return ret; - } - - static PyObject *ConvertToPy(const Container &in) { return ConvertToPy(in, NULL); } -}; - -template -struct TypeConversion, false> : ContainerConversion, U> -{ -}; - -template <> -struct TypeConversion : ContainerConversion, QString> -{ -}; - -template -struct TypeConversion, false> : ContainerConversion, U> -{ -}; - -// specialisation for pair -template -struct TypeConversion, false> -{ - static int ConvertFromPy(PyObject *in, QPair &out) - { - if(!PyTuple_Check(in)) - return SWIG_TypeError; - - Py_ssize_t size = PyTuple_Size(in); - - if(size != 2) - return SWIG_TypeError; - - int ret = TypeConversion::ConvertFromPy(PyTuple_GetItem(in, 0), out.first); - if(SWIG_IsOK(ret)) - ret = TypeConversion::ConvertFromPy(PyTuple_GetItem(in, 1), out.second); - - return ret; - } - - static PyObject *ConvertToPy(const QPair &in) - { - PyObject *first = TypeConversion::ConvertToPy(in.first); - if(!first) - return NULL; - - PyObject *second = TypeConversion::ConvertToPy(in.second); - if(!second) - return NULL; - - PyObject *ret = PyTuple_New(2); - if(!ret) - return NULL; - - PyTuple_SetItem(ret, 0, first); - PyTuple_SetItem(ret, 1, second); - - return ret; - } -}; - -template -struct TypeConversion, false> -{ - // we add some extra parameters so the typemaps for array can use these to get - // nicer failure error messages out with the index that failed - static int ConvertFromPy(PyObject *in, QMap &out, int *failIdx) - { - if(!PyDict_Check(in)) - return SWIG_TypeError; - - PyObject *keys = PyDict_Keys(in); - - if(!keys) - return SWIG_TypeError; - - Py_ssize_t len = PyList_Size(keys); - - for(Py_ssize_t i = 0; i < len; i++) - { - K k; - V v; - - PyObject *key = PyList_GetItem(keys, i); - PyObject *value = PyDict_GetItem(in, key); - int ret = TypeConversion::ConvertFromPy(key, k); - int ret2 = TypeConversion::ConvertFromPy(value, v); - if(!SWIG_IsOK(ret) || !SWIG_IsOK(ret2)) - { - if(failIdx) - *failIdx = i; - Py_DecRef(keys); - if(!SWIG_IsOK(ret)) - return ret; - else - return ret2; - } - out.insert(k, v); - } - - Py_DecRef(keys); - - return SWIG_OK; - } - - static int ConvertFromPy(PyObject *in, QMap &out) { return ConvertFromPy(in, out, NULL); } - static PyObject *ConvertToPyInPlace(PyObject *pymap, const QMap &in, int *failIdx) - { - QList keys = in.keys(); - - for(int i = 0; i < keys.size(); i++) - { - const K &k = keys[i]; - PyObject *key = TypeConversion::ConvertToPy(k); - - if(key) - { - PyObject *value = TypeConversion::ConvertToPy(in[k]); - - if(value) - { - PyDict_SetItem(pymap, key, value); - // release our reference - Py_DecRef(key); - // release our reference - Py_DecRef(value); - continue; - } - - // destroy unused key - Py_DecRef(key); - } - - if(failIdx) - *failIdx = i; - - return NULL; - } - - return pymap; - } - - static PyObject *ConvertToPy(const QMap &in, int *failIdx) - { - PyObject *list = PyDict_New(); - if(!list) - return NULL; - - PyObject *ret = ConvertToPyInPlace(list, in, failIdx); - - // if a failure happened, don't leak the map we created - if(!ret) - Py_XDECREF(list); - - return ret; - } - - static PyObject *ConvertToPy(const QMap &in) { return ConvertToPy(in, NULL); } -}; - -#endif diff --git a/qrenderdoc/Code/pyrenderdoc/renderdoc.i b/qrenderdoc/Code/pyrenderdoc/renderdoc.i index ef0f1bc42..815c84d2a 100644 --- a/qrenderdoc/Code/pyrenderdoc/renderdoc.i +++ b/qrenderdoc/Code/pyrenderdoc/renderdoc.i @@ -51,13 +51,21 @@ %rename("%(regex:/^VKPipe::(.*)/VK\\1/)s", regextarget=1, fullname=1, %$isclass) "VKPipe::.*"; %begin %{ + #undef slots +%} -#undef slots - +%{ + #include "datetime.h" +%} +%init %{ + PyDateTime_IMPORT; %} %include "pyconversion.i" +// completely ignore rdcdatetime, we custom convert to/from a native python datetime +%ignore rdcdatetime; + // ignore some operators SWIG doesn't have to worry about %ignore SDType::operator=; %ignore StructuredObjectList::swap; @@ -120,6 +128,7 @@ } SIMPLE_TYPEMAPS(rdcstr) +SIMPLE_TYPEMAPS(rdcdatetime) SIMPLE_TYPEMAPS(bytebuf) FIXED_ARRAY_TYPEMAPS(ResourceId) diff --git a/qrenderdoc/Windows/MainWindow.cpp b/qrenderdoc/Windows/MainWindow.cpp index 005c79423..f759fa3b0 100644 --- a/qrenderdoc/Windows/MainWindow.cpp +++ b/qrenderdoc/Windows/MainWindow.cpp @@ -229,7 +229,7 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai for(const BugReport &b : bugs) { // check bugs every two days - qint64 diff = b.checkDate.secsTo(now); + qint64 diff = QDateTime(b.checkDate).secsTo(now); if(diff > 2 * 24 * 60 * 60) { // update the check date on the stored bug @@ -1001,8 +1001,8 @@ void MainWindow::PopulateReportedBugs() if(bug.unreadUpdates) fmt = tr("&%1: (Update) Bug reported at %2"); - QAction *action = - ui->menu_Reported_Bugs->addAction(fmt.arg(idx).arg(bug.submitDate.toString()), [this, i] { + QAction *action = ui->menu_Reported_Bugs->addAction( + fmt.arg(idx).arg(QDateTime(bug.submitDate).toString()), [this, i] { BugReport &bug = m_Ctx.Config().CrashReport_ReportedBugs[i]; QDesktopServices::openUrl(QString(bug.URL())); diff --git a/qrenderdoc/qrenderdoc_local.vcxproj b/qrenderdoc/qrenderdoc_local.vcxproj index bc1547637..6c34bb88d 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj +++ b/qrenderdoc/qrenderdoc_local.vcxproj @@ -894,7 +894,6 @@ - diff --git a/qrenderdoc/qrenderdoc_local.vcxproj.filters b/qrenderdoc/qrenderdoc_local.vcxproj.filters index abc106382..951679304 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj.filters +++ b/qrenderdoc/qrenderdoc_local.vcxproj.filters @@ -1031,9 +1031,6 @@ Code\pyrenderdoc - - Code\pyrenderdoc - Code\pyrenderdoc diff --git a/renderdoc/api/replay/basic_types.h b/renderdoc/api/replay/basic_types.h index eacde46bb..a0e995974 100644 --- a/renderdoc/api/replay/basic_types.h +++ b/renderdoc/api/replay/basic_types.h @@ -50,6 +50,71 @@ typedef uint8_t byte; #define DOCUMENT4(text1, text2, text3, text4) #endif +// primarily here just to remove a dependency on QDateTime in the Qt UI, so we don't have to bind +// against Qt at all in the interface. +DOCUMENT(""); +struct rdcdatetime +{ + DOCUMENT(""); + int32_t year = 0; + int32_t month = 0; + int32_t day = 0; + int32_t hour = 0; + int32_t minute = 0; + int32_t second = 0; + int32_t microsecond = 0; + + rdcdatetime() = default; + + rdcdatetime(int y, int mn, int d, int h = 0, int m = 0, int s = 0, int us = 0) + : year(y), month(mn), day(d), hour(h), minute(m), second(s), microsecond(us) + { + } + + bool operator==(const rdcdatetime &o) const + { + return year == o.year && month == o.month && day == o.day && hour == o.hour && + minute == o.minute && second == o.second && microsecond == o.microsecond; + } + bool operator!=(const rdcdatetime &o) const { return !(*this == o); } + bool operator<(const rdcdatetime &o) const + { + if(year != o.year) + return year < o.year; + if(month != o.month) + return month < o.month; + if(day != o.day) + return day < o.day; + if(hour != o.hour) + return hour < o.hour; + if(minute != o.minute) + return minute < o.minute; + if(second != o.second) + return second < o.second; + if(microsecond != o.microsecond) + return microsecond < o.microsecond; + return false; + } + +#if defined(RENDERDOC_QT_COMPAT) + rdcdatetime(const QDateTime &in) + { + year = in.date().year(); + month = in.date().month(); + day = in.date().day(); + hour = in.time().hour(); + minute = in.time().minute(); + second = in.time().second(); + microsecond = in.time().msec() * 1000; + } + operator QDateTime() const + { + return QDateTime(QDate(year, month, day), QTime(hour, minute, second, microsecond / 1000)); + } + operator QVariant() const { return QVariant(QDateTime(*this)); } +#endif +}; + // here we define our own data structures that are ABI compatible between modules, as STL is not // safe to pass a module boundary. template