Add qrenderdoc python SWIG bindings, for the stable/clean interface

This commit is contained in:
baldurk
2017-03-28 16:27:46 +01:00
parent 7a5bf26325
commit cbc27222e2
8 changed files with 145 additions and 25 deletions
+25 -13
View File
@@ -128,18 +128,31 @@ else()
"DEFINES+=PYSIDE2_ENABLED=0\n")
endif()
# generate the SWIG interface file
add_custom_command(OUTPUT renderdoc_python.cxx renderdoc.py
COMMAND ${CMAKE_BINARY_DIR}/bin/swig -v -Wextra -Werror -O -c++ -python -modern -modernargs -enumclass -fastunpack -py3 -builtin -I${CMAKE_SOURCE_DIR}/renderdoc/api/replay -outdir ${CMAKE_CURRENT_BINARY_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/renderdoc_python.cxx ${CMAKE_CURRENT_SOURCE_DIR}/Code/pyrenderdoc/renderdoc.i
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Code/pyrenderdoc/renderdoc.i
DEPENDS custom_swig
DEPENDS renderdoc)
# generate the SWIG interface files
set(swig_interfaces
Code/pyrenderdoc/renderdoc.i
Code/pyrenderdoc/qrenderdoc.i)
add_custom_command(OUTPUT renderdoc.py.c
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include-bin renderdoc.py renderdoc.py.c
DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include-bin
DEPENDS renderdoc_python.cxx)
set(swig_output)
foreach(in ${swig_interfaces})
get_filename_component(swig_file ${in} NAME_WE)
add_custom_command(OUTPUT ${swig_file}_python.cxx ${swig_file}.py
COMMAND ${CMAKE_BINARY_DIR}/bin/swig -v -Wextra -Werror -O -c++ -python -modern -modernargs -enumclass -fastunpack -py3 -builtin -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_SOURCE_DIR}/renderdoc/api/replay -outdir ${CMAKE_CURRENT_BINARY_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/${swig_file}_python.cxx ${CMAKE_CURRENT_SOURCE_DIR}/${in}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${in}
DEPENDS custom_swig
DEPENDS renderdoc)
add_custom_command(OUTPUT ${swig_file}.py.c
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include-bin ${swig_file}.py ${swig_file}.py.c
DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include-bin
DEPENDS ${swig_file}_python.cxx)
list(APPEND swig_output ${swig_file}_python.cxx)
list(APPEND swig_output ${swig_file}.py.c)
endforeach()
# The case here is deliberately not matching the executable name
# This means the custom command doesn't create this output file,
@@ -149,8 +162,7 @@ add_custom_command(OUTPUT QRenderDoc
COMMAND qmake "CMAKE_DIR=${CMAKE_BINARY_DIR}" ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND $(MAKE)
DEPENDS RenderDoc.icns
DEPENDS renderdoc_python.cxx
DEPENDS renderdoc.py.c)
DEPENDS ${swig_output})
add_custom_target(build-qrenderdoc ALL DEPENDS QRenderDoc DEPENDS renderdoc)
install (PROGRAMS ${CMAKE_BINARY_DIR}/bin/qrenderdoc DESTINATION bin)
+36 -9
View File
@@ -49,6 +49,8 @@ PyTypeObject **SbkPySide2_QtWidgetsTypes = NULL;
// defined in SWIG-generated renderdoc_python.cpp
extern "C" PyObject *PyInit__renderdoc(void);
extern "C" PyObject *PassObjectToPython(const char *type, void *obj);
// this one is in qrenderdoc_python.cpp
extern "C" PyObject *PyInit__qrenderdoc(void);
#ifdef WIN32
@@ -56,9 +58,9 @@ extern "C" PyObject *PassObjectToPython(const char *type, void *obj);
#include <windows.h>
#include "Resources/resource.h"
QByteArray GetWrapperModule()
QByteArray GetResourceContents(int resource)
{
HRSRC res = FindResource(NULL, MAKEINTRESOURCE(renderdoc_py_module), MAKEINTRESOURCE(TYPE_EMBED));
HRSRC res = FindResource(NULL, MAKEINTRESOURCE(resource), MAKEINTRESOURCE(TYPE_EMBED));
HGLOBAL data = LoadResource(NULL, res);
if(!data)
@@ -70,16 +72,17 @@ QByteArray GetWrapperModule()
return QByteArray(resData, (int)resSize);
}
#define GetWrapperModule(name) GetResourceContents(name##_py_module)
#else
// Otherwise it's compiled in via include-bin which converts to a .c with extern array
extern unsigned char renderdoc_py[];
extern unsigned int renderdoc_py_len;
extern unsigned char qrenderdoc_py[];
extern unsigned int qrenderdoc_py_len;
QByteArray GetWrapperModule()
{
return QByteArray((const char *)renderdoc_py, (int)renderdoc_py_len);
}
#define GetWrapperModule(name) QByteArray((const char *)name##_py, (int)name##_py_len);
#endif
@@ -198,6 +201,7 @@ void PythonContext::GlobalInit()
}
PyImport_AppendInittab("_renderdoc", &PyInit__renderdoc);
PyImport_AppendInittab("_qrenderdoc", &PyInit__qrenderdoc);
Py_SetProgramName(program_name);
@@ -205,17 +209,26 @@ void PythonContext::GlobalInit()
PyEval_InitThreads();
QByteArray module_src = GetWrapperModule();
QByteArray renderdoc_py_src = GetWrapperModule(renderdoc);
if(module_src.isEmpty())
if(renderdoc_py_src.isEmpty())
{
qCritical() << "renderdoc.py wrapper is corrupt/empty. Check build configuration to ensure "
"SWIG compiled properly with python support.";
return;
}
QByteArray qrenderdoc_py_src = GetWrapperModule(qrenderdoc);
if(qrenderdoc_py_src.isEmpty())
{
qCritical() << "qrenderdoc.py wrapper is corrupt/empty. Check build configuration to ensure "
"SWIG compiled properly with python support.";
return;
}
PyObject *renderdoc_py_compiled =
Py_CompileString(module_src.data(), "renderdoc.py", Py_file_input);
Py_CompileString(renderdoc_py_src.data(), "renderdoc.py", Py_file_input);
if(!renderdoc_py_compiled)
{
@@ -223,6 +236,16 @@ void PythonContext::GlobalInit()
return;
}
PyObject *qrenderdoc_py_compiled =
Py_CompileString(qrenderdoc_py_src.data(), "qrenderdoc.py", Py_file_input);
if(!qrenderdoc_py_compiled)
{
Py_DecRef(renderdoc_py_compiled);
qCritical() << "Failed to compile qrenderdoc.py wrapper, python will not be available";
return;
}
OutputRedirectorType.tp_name = "renderdoc_output_redirector";
OutputRedirectorType.tp_basicsize = sizeof(OutputRedirector);
OutputRedirectorType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE;
@@ -238,10 +261,13 @@ void PythonContext::GlobalInit()
PyObject *main_module = PyImport_AddModule("__main__");
PyObject *rdoc_module = PyImport_ExecCodeModule("renderdoc", renderdoc_py_compiled);
PyObject *qrdoc_module = PyImport_ExecCodeModule("qrenderdoc", qrenderdoc_py_compiled);
Py_XDECREF(renderdoc_py_compiled);
Py_XDECREF(qrenderdoc_py_compiled);
PyModule_AddObject(main_module, "renderdoc", rdoc_module);
PyModule_AddObject(main_module, "qrenderdoc", qrdoc_module);
main_dict = PyModule_GetDict(main_module);
@@ -480,6 +506,7 @@ void PythonContext::setGlobal(const char *varName, const char *typeName, void *o
PyGILState_STATE gil = PyGILState_Ensure();
// we don't need separate functions for each module, as they share type info
PyObject *obj = PassObjectToPython(typeName, object);
int ret = -1;
+58
View File
@@ -0,0 +1,58 @@
%module(docstring="This is the API to QRenderDoc's high-level UI panels and functionality.") qrenderdoc
%feature("autodoc", "0");
// use documentation for docstrings
#define DOCUMENT(text) %feature("docstring") text
// import the renderdoc interface that we depend on
%import "renderdoc.i"
SIMPLE_TYPEMAPS(QString)
SIMPLE_TYPEMAPS(QDateTime)
CONTAINER_TYPEMAPS(QList &)
CONTAINER_TYPEMAPS(QList *)
CONTAINER_TYPEMAPS(QList)
CONTAINER_TYPEMAPS(QStringList &)
CONTAINER_TYPEMAPS(QStringList *)
CONTAINER_TYPEMAPS(QStringList)
CONTAINER_TYPEMAPS(QVector &)
CONTAINER_TYPEMAPS(QVector *)
CONTAINER_TYPEMAPS(QVector)
CONTAINER_TYPEMAPS(QMap &)
CONTAINER_TYPEMAPS(QMap *)
CONTAINER_TYPEMAPS(QMap)
// ignore these functions as we don't map QVariantMap to/from python
%ignore EnvironmentModification::toJSON;
%ignore EnvironmentModification::fromJSON;
// rename the interfaces to remove the I prefix
%rename("%(regex:/^I([A-Z].*)/\\1/)s", %$isclass) "";
%{
#define ENABLE_QT_CONVERT
#include <QDateTime>
#include <QTimeZone>
#include <QMap>
#include <QString>
#include <QList>
#include <QVector>
#include "datetime.h"
#include "Code/Interface/QRDInterface.h"
%}
%include <stdint.i>
%include "Code/Interface/QRDInterface.h"
%include "Code/Interface/CommonPipelineState.h"
%include "Code/Interface/PersistantConfig.h"
%include "Code/Interface/RemoteHost.h"
%init %{
PyDateTime_IMPORT;
%}
+1
View File
@@ -101,6 +101,7 @@ END
// embed the renderdoc.py generated by SWIG
renderdoc_py_module TYPE_EMBED RENDERDOC_PY_PATH
qrenderdoc_py_module TYPE_EMBED QRENDERDOC_PY_PATH
/////////////////////////////////////////////////////////////////////////////
//
+1
View File
@@ -6,6 +6,7 @@
#define TYPE_EMBED 256
#define renderdoc_py_module 101
#define qrenderdoc_py_module 102
// Next default values for new objects
//
+6 -2
View File
@@ -52,16 +52,18 @@ win32 {
swig.name = SWIG ${QMAKE_FILE_IN}
swig.input = SWIGSOURCES
swig.output = ${QMAKE_FILE_BASE}_python.cxx
swig.commands = $$_PRO_FILE_PWD_/3rdparty/swig/swig.exe -v -Wextra -Werror -O -c++ -python -modern -modernargs -enumclass -fastunpack -py3 -builtin -I$$_PRO_FILE_PWD_/../renderdoc/api/replay -outdir . -o ${QMAKE_FILE_BASE}_python.cxx ${QMAKE_FILE_IN}
swig.commands = $$_PRO_FILE_PWD_/3rdparty/swig/swig.exe -v -Wextra -Werror -O -c++ -python -modern -modernargs -enumclass -fastunpack -py3 -builtin -I$$_PRO_FILE_PWD_ -I$$_PRO_FILE_PWD_/../renderdoc/api/replay -outdir . -o ${QMAKE_FILE_BASE}_python.cxx ${QMAKE_FILE_IN}
swig.CONFIG += target_predeps
swig.variable_out = GENERATED_SOURCES
silent:swig.commands = @echo SWIG ${QMAKE_FILE_IN} && $$swig.commands
QMAKE_EXTRA_COMPILERS += swig
SWIGSOURCES += Code/pyrenderdoc/renderdoc.i
SWIGSOURCES += Code/pyrenderdoc/qrenderdoc.i
# Embed renderdoc.py
# Embed renderdoc.py and qrenderdoc.py
RC_DEFINES = RENDERDOC_PY_PATH=renderdoc.py
RC_DEFINES += QRENDERDOC_PY_PATH=qrenderdoc.py
# Include and link against python
INCLUDEPATH += $$_PRO_FILE_PWD_/3rdparty/python/include
@@ -112,6 +114,8 @@ win32 {
# Add the SWIG files that were generated in cmake
SOURCES += $$CMAKE_DIR/qrenderdoc/renderdoc_python.cxx
SOURCES += $$CMAKE_DIR/qrenderdoc/renderdoc.py.c
SOURCES += $$CMAKE_DIR/qrenderdoc/qrenderdoc_python.cxx
SOURCES += $$CMAKE_DIR/qrenderdoc/qrenderdoc.py.c
CONFIG += warn_off
CONFIG += c++14
+12 -1
View File
@@ -689,6 +689,9 @@
<ClCompile Include="$(IntDir)generated\renderdoc_python.cxx">
<DisableSpecificWarnings>4127;4456;4459;4701;4244;4706;4101;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ClCompile Include="$(IntDir)generated\qrenderdoc_python.cxx">
<DisableSpecificWarnings>4127;4456;4459;4701;4244;4706;4101;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ClCompile Include="Widgets\BufferFormatSpecifier.cpp" />
<ClCompile Include="Widgets\FindReplace.cpp" />
<ClCompile Include="Widgets\Extended\RDListWidget.cpp" />
@@ -1178,6 +1181,14 @@
<Outputs>$(IntDir)generated\%(Filename).py;$(IntDir)generated\%(Filename)_python.cxx;%(Outputs)</Outputs>
<LinkObjects>false</LinkObjects>
</CustomBuild>
<CustomBuild Include="Code\pyrenderdoc\qrenderdoc.i">
<FileType>Document</FileType>
<AdditionalInputs>%(Fullpath);Code\Interface\QRDInterface.h;Code\Interface\CommonPipelineState.h;Code\Interface\PersistantConfig.h;Code\Interface\RemoteHost.h;$(IntDir)generated\renderdoc.py;%(AdditionalInputs)</AdditionalInputs>
<Command>$(ProjectDir)3rdparty\swig\swig.exe -v -Wextra -Werror -O -c++ -python -modern -modernargs -enumclass -fastunpack -py3 -builtin -I$(SolutionDir)renderdoc\api\replay -I$(ProjectDir) -outdir $(IntDir)generated -o $(IntDir)generated\%(Filename)_python.cxx %(FullPath)</Command>
<Message>Compiling SWIG interface</Message>
<Outputs>$(IntDir)generated\%(Filename).py;$(IntDir)generated\%(Filename)_python.cxx;%(Outputs)</Outputs>
<LinkObjects>false</LinkObjects>
</CustomBuild>
<CustomBuild Include="Widgets\BufferFormatSpecifier.ui">
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
<Command>$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe %(Fullpath) -o $(IntDir)generated\ui_%(Filename).h</Command>
@@ -1543,7 +1554,7 @@
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Resources\qrenderdoc.rc">
<PreprocessorDefinitions>RENDERDOC_PY_PATH=$(IntDir)\generated\renderdoc.py;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>RENDERDOC_PY_PATH=$(IntDir)\generated\renderdoc.py;QRENDERDOC_PY_PATH=$(IntDir)\generated\qrenderdoc.py;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
@@ -558,6 +558,9 @@
<ClCompile Include="Code\pyrenderdoc\PythonContext.cpp">
<Filter>Code\pyrenderdoc</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)generated\qrenderdoc_python.cxx">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)generated\moc_PythonContext.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
@@ -1316,5 +1319,8 @@
<CustomBuild Include="Code\pyrenderdoc\PythonContext.h">
<Filter>Code\pyrenderdoc</Filter>
</CustomBuild>
<CustomBuild Include="Code\pyrenderdoc\qrenderdoc.i">
<Filter>Code\pyrenderdoc</Filter>
</CustomBuild>
</ItemGroup>
</Project>