Commit ea79bca0 authored by Laszlo Agocs's avatar Laszlo Agocs

d3d: implement rsh

parent 195978d3
......@@ -48,6 +48,8 @@
**
****************************************************************************/
// Demonstrates using the same QRhiTexture with two QRhi instances.
#include <QGuiApplication>
#include <QCommandLineParser>
......@@ -161,7 +163,7 @@ void createRhi(QWindow *window, QRhi **rhi, QOffscreenSurface **fallbackSurface)
class Window : public QWindow
{
public:
Window(const QString &title, const QColor &bgColor);
Window(const QString &title, const QColor &bgColor, int windowNumber);
~Window();
protected:
......@@ -177,12 +179,14 @@ protected:
QRhi *m_rhi = nullptr;
QOffscreenSurface *m_fallbackSurface = nullptr;
QColor m_bgColor;
int m_windowNumber;
bool m_running = false;
bool m_notExposed = false;
bool m_newlyExposed = false;
QMatrix4x4 m_proj;
float m_rotation = 0;
QVector<QRhiResource *> m_releasePool;
bool m_hasSwapChain = false;
......@@ -199,8 +203,9 @@ protected:
QRhiGraphicsPipeline *ps = nullptr;
};
Window::Window(const QString &title, const QColor &bgColor)
: m_bgColor(bgColor)
Window::Window(const QString &title, const QColor &bgColor, int windowNumber)
: m_bgColor(bgColor),
m_windowNumber(windowNumber)
{
switch (graphicsApi) {
case OpenGL:
......@@ -461,6 +466,8 @@ void Window::render()
QMatrix4x4 mvp = m_proj;
mvp.scale(2.5f);
mvp.rotate(m_rotation, m_windowNumber == 2, m_windowNumber == 1, m_windowNumber == 0);
m_rotation += 0.5f;
u->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
......@@ -545,8 +552,8 @@ int main(int argc, char **argv)
// lifetime: make sure the QWindows are gone when we move on to destroying
// the Vulkan instance and such.
{
Window windowA(QLatin1String("QRhi #1"), Qt::green);
Window windowB(QLatin1String("QRhi #2"), Qt::blue);
Window windowA(QLatin1String("QRhi #1"), Qt::green, 0);
Window windowB(QLatin1String("QRhi #2"), Qt::blue, 1);
windowA.show();
windowB.show();
......
......@@ -35,6 +35,7 @@
****************************************************************************/
#include "qrhid3d11_p.h"
#include "qrhirsh_p.h"
#include <QWindow>
#include <QBakedShader>
#include <qmath.h>
......@@ -127,6 +128,9 @@ QT_BEGIN_NAMESPACE
QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice)
: ofr(this)
{
if (params->resourceSharingHost)
rsh = QRhiResourceSharingHostPrivate::get(params->resourceSharingHost);
debugLayer = params->enableDebugLayer;
importedDevice = importDevice != nullptr;
if (importedDevice) {
......@@ -169,6 +173,8 @@ bool QRhiD3D11::create(QRhi::Flags flags)
{
Q_UNUSED(flags);
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
uint devFlags = 0;
if (debugLayer)
devFlags |= D3D11_CREATE_DEVICE_DEBUG;
......@@ -180,42 +186,53 @@ bool QRhiD3D11::create(QRhi::Flags flags)
}
if (!importedDevice) {
IDXGIAdapter1 *adapterToUse = nullptr;
IDXGIAdapter1 *adapter;
int requestedAdapterIndex = -1;
if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX"))
requestedAdapterIndex = qEnvironmentVariableIntValue("QT_D3D_ADAPTER_INDEX");
for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
const QString name = QString::fromUtf16((char16_t *) desc.Description);
qDebug("Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags);
if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
adapterToUse = adapter;
qDebug(" using this adapter");
if (!rsh || !rsh->d_d3d11.dev) {
IDXGIAdapter1 *adapterToUse = nullptr;
IDXGIAdapter1 *adapter;
int requestedAdapterIndex = -1;
if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX"))
requestedAdapterIndex = qEnvironmentVariableIntValue("QT_D3D_ADAPTER_INDEX");
for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(adapterIndex, &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
const QString name = QString::fromUtf16((char16_t *) desc.Description);
qDebug("Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags);
if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
adapterToUse = adapter;
qDebug(" using this adapter");
} else {
adapter->Release();
}
}
if (!adapterToUse) {
qWarning("No adapter");
return false;
}
ID3D11DeviceContext *ctx = nullptr;
HRESULT hr = D3D11CreateDevice(adapterToUse, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
nullptr, 0, D3D11_SDK_VERSION,
&dev, &featureLevel, &ctx);
adapterToUse->Release();
if (FAILED(hr)) {
qWarning("Failed to create D3D11 device and context: %s", qPrintable(comErrorMessage(hr)));
return false;
}
if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
ctx->Release();
} else {
adapter->Release();
qWarning("ID3D11DeviceContext1 not supported");
return false;
}
}
if (!adapterToUse) {
qWarning("No adapter");
return false;
}
ID3D11DeviceContext *ctx = nullptr;
HRESULT hr = D3D11CreateDevice(adapterToUse, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
nullptr, 0, D3D11_SDK_VERSION,
&dev, &featureLevel, &ctx);
adapterToUse->Release();
if (FAILED(hr)) {
qWarning("Failed to create D3D11 device and context: %s", qPrintable(comErrorMessage(hr)));
return false;
}
if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
ctx->Release();
if (rsh) {
rsh->d_d3d11.dev = dev;
rsh->d_d3d11.context = context;
}
} else {
qWarning("ID3D11DeviceContext1 not supported");
return false;
dev = reinterpret_cast<ID3D11Device *>(rsh->d_d3d11.dev);
context = reinterpret_cast<ID3D11DeviceContext1 *>(rsh->d_d3d11.context);
featureLevel = dev->GetFeatureLevel();
}
} else {
Q_ASSERT(dev && context);
......@@ -228,6 +245,9 @@ bool QRhiD3D11::create(QRhi::Flags flags)
nativeHandlesStruct.dev = dev;
nativeHandlesStruct.context = context;
if (rsh)
rsh->rhiCount += 1;
return true;
}
......@@ -235,6 +255,8 @@ void QRhiD3D11::destroy()
{
finishActiveReadbacks();
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
if (annotations) {
annotations->Release();
annotations = nullptr;
......@@ -242,15 +264,31 @@ void QRhiD3D11::destroy()
if (!importedDevice) {
if (context) {
context->Release();
if (!rsh || rsh->d_d3d11.context != context)
context->Release();
context = nullptr;
}
if (dev) {
dev->Release();
if (!rsh || rsh->d_d3d11.dev != dev)
dev->Release();
dev = nullptr;
}
}
if (rsh) {
rsh->rhiCount -= 1;
if (rsh->rhiCount == 0) {
if (rsh->d_d3d11.context) {
reinterpret_cast<ID3D11DeviceContext1 *>(rsh->d_d3d11.context)->Release();
rsh->d_d3d11.context = nullptr;
}
if (rsh->d_d3d11.dev) {
reinterpret_cast<ID3D11Device *>(rsh->d_d3d11.dev)->Release();
rsh->d_d3d11.dev = nullptr;
}
}
}
if (dxgiFactory) {
dxgiFactory->Release();
dxgiFactory = nullptr;
......@@ -712,6 +750,8 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
Q_ASSERT(inFrame);
inFrame = false;
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
QD3D11SwapChain *swapChainD = QRHI_RES(QD3D11SwapChain, swapChain);
Q_ASSERT(contextState.currentSwapChain = swapChainD);
const int currentFrameSlot = swapChainD->currentFrameSlot;
......@@ -722,10 +762,12 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
ID3D11Query *tsEnd = swapChainD->timestampQuery[tsIdx + 1];
const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !swapChainD->timestampActive[currentFrameSlot];
// send all commands to the context. we already do the rsh lock ourselves
// hence lockWithRsh == false.
if (recordTimestamps)
executeCommandBuffer(&swapChainD->cb, swapChainD);
executeCommandBuffer(&swapChainD->cb, swapChainD, false);
else
executeCommandBuffer(&swapChainD->cb);
executeCommandBuffer(&swapChainD->cb, nullptr, false);
if (swapChainD->sampleDesc.Count > 1) {
context->ResolveSubresource(swapChainD->tex[currentFrameSlot], 0,
......@@ -740,6 +782,9 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
swapChainD->timestampActive[currentFrameSlot] = true;
}
// avoid keeping the mutex when issuing the Present
lock.unlock();
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
// this must be done before the Present
QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
......@@ -1466,8 +1511,10 @@ void QRhiD3D11::setRenderTarget(QRhiRenderTarget *rt)
context->OMSetRenderTargets(rtD->colorAttCount, rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
}
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain, bool lockWithRsh)
{
QMutexLocker lock((lockWithRsh && rsh) ? &rsh->mtx : nullptr);
quint32 stencilRef = 0;
float blendConstants[] = { 1, 1, 1, 1 };
......
......@@ -51,6 +51,8 @@
QT_BEGIN_NAMESPACE
class QRhiResourceSharingHostPrivate;
struct QD3D11Buffer : public QRhiBuffer
{
QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
......@@ -525,10 +527,13 @@ public:
void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD);
void setShaderResources(QD3D11ShaderResourceBindings *srbD);
void setRenderTarget(QRhiRenderTarget *rt);
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
void executeCommandBuffer(QD3D11CommandBuffer *cbD,
QD3D11SwapChain *timestampSwapChain = nullptr,
bool lockWithRsh = true);
DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
void finishActiveReadbacks();
QRhiResourceSharingHostPrivate *rsh = nullptr;
bool debugLayer = false;
bool importedDevice = false;
ID3D11Device *dev = nullptr;
......
......@@ -308,14 +308,18 @@ void QRhiGles2::destroy()
QMutexLocker lock(rsh ? &rsh->mtx : nullptr);
if (!importedContext) {
if (!rsh || rsh->rhiCount == 1) {
if (!rsh || rsh->d_gles2.context != ctx)
delete ctx;
ctx = nullptr;
}
ctx = nullptr;
}
if (rsh)
if (rsh) {
rsh->rhiCount -= 1;
if (rsh->rhiCount == 0) {
delete rsh->d_gles2.context;
rsh->d_gles2.context = nullptr;
}
}
}
// Strictly speaking this is not necessary since we could do the deletes in
......
res.sh.: reuse device / create sharing context
res.sh.: example to show using same texture
res.sh.: example to show read/write same texture
res.sh.: d3d context sync
res.sh.: exercise it in multiwindow_threaded too
advanced blend modes
gl: tex formats (texture, readback)
......@@ -50,6 +48,8 @@ dxc for d3d as an alternative to fxc?
hlsl -> dxc -> spirv -> spirv-cross hmmm...
+++ done
res.sh.: example to show using same texture
res.sh.: d3d context sync
revise create() and importing external device objects
revise structs in api
primitive restart
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment