Commit 769a7d76 authored by Laszlo Agocs's avatar Laszlo Agocs

d3d: Add support for MSAA (onscreen)

parent 2c0e4494
...@@ -69,6 +69,8 @@ void D3D11Window::init() ...@@ -69,6 +69,8 @@ void D3D11Window::init()
params.importExistingDevice = false; params.importExistingDevice = false;
m_r = QRhi::create(QRhi::D3D11, &params); m_r = QRhi::create(QRhi::D3D11, &params);
//setSampleCount(4); // enable 4x MSAA (except for the render-to-texture pass)
ExampleWindow::init(); ExampleWindow::init();
} }
......
...@@ -171,7 +171,26 @@ void QRhiD3D11::destroy() ...@@ -171,7 +171,26 @@ void QRhiD3D11::destroy()
QVector<int> QRhiD3D11::supportedSampleCounts() const QVector<int> QRhiD3D11::supportedSampleCounts() const
{ {
return { 1 }; return { 1, 2, 4, 8 };
}
DXGI_SAMPLE_DESC QRhiD3D11::effectiveSampleCount(int sampleCount) const
{
DXGI_SAMPLE_DESC desc;
desc.Count = 1;
desc.Quality = 0;
// Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
int s = qBound(1, sampleCount, 64);
if (!supportedSampleCounts().contains(s)) {
qWarning("Attempted to set unsupported sample count %d", sampleCount);
return desc;
}
desc.Count = s;
desc.Quality = s > 1 ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0;
return desc;
} }
QRhiSwapChain *QRhiD3D11::createSwapChain() QRhiSwapChain *QRhiD3D11::createSwapChain()
...@@ -435,7 +454,8 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain) ...@@ -435,7 +454,8 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain)
currentFrameSlot = swapChainD->currentFrame; currentFrameSlot = swapChainD->currentFrame;
swapChainD->rt.d.pixelSize = swapChainD->pixelSize; swapChainD->rt.d.pixelSize = swapChainD->pixelSize;
swapChainD->rt.d.rtv[0] = swapChainD->rtv[currentFrameSlot]; swapChainD->rt.d.rtv[0] = swapChainD->sampleDesc.Count > 1 ?
swapChainD->msaaRtv[currentFrameSlot] : swapChainD->rtv[currentFrameSlot];
swapChainD->rt.d.dsv = swapChainD->ds ? swapChainD->ds->dsv : nullptr; swapChainD->rt.d.dsv = swapChainD->ds ? swapChainD->ds->dsv : nullptr;
return QRhi::FrameOpSuccess; return QRhi::FrameOpSuccess;
...@@ -449,6 +469,12 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain) ...@@ -449,6 +469,12 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain)
QD3D11SwapChain *swapChainD = QRHI_RES(QD3D11SwapChain, swapChain); QD3D11SwapChain *swapChainD = QRHI_RES(QD3D11SwapChain, swapChain);
executeCommandBuffer(&swapChainD->cb); executeCommandBuffer(&swapChainD->cb);
if (swapChainD->sampleDesc.Count > 1) {
context->ResolveSubresource(swapChainD->tex[currentFrameSlot], 0,
swapChainD->msaaTex[currentFrameSlot], 0,
swapChainD->colorFormat);
}
const UINT swapInterval = 1; const UINT swapInterval = 1;
const UINT presentFlags = 0; const UINT presentFlags = 0;
HRESULT hr = swapChainD->swapChain->Present(swapInterval, presentFlags); HRESULT hr = swapChainD->swapChain->Present(swapInterval, presentFlags);
...@@ -937,7 +963,7 @@ bool QD3D11RenderBuffer::build() ...@@ -937,7 +963,7 @@ bool QD3D11RenderBuffer::build()
desc.MipLevels = 1; desc.MipLevels = 1;
desc.ArraySize = 1; desc.ArraySize = 1;
desc.Format = dsFormat; desc.Format = dsFormat;
desc.SampleDesc.Count = 1; desc.SampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
desc.Usage = D3D11_USAGE_DEFAULT; desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex); HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
...@@ -948,7 +974,7 @@ bool QD3D11RenderBuffer::build() ...@@ -948,7 +974,7 @@ bool QD3D11RenderBuffer::build()
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
memset(&dsvDesc, 0, sizeof(dsvDesc)); memset(&dsvDesc, 0, sizeof(dsvDesc));
dsvDesc.Format = dsFormat; dsvDesc.Format = dsFormat;
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv); hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
if (FAILED(hr)) { if (FAILED(hr)) {
qWarning("Failed to create dsv: %s", qPrintable(comErrorMessage(hr))); qWarning("Failed to create dsv: %s", qPrintable(comErrorMessage(hr)));
...@@ -1670,7 +1696,7 @@ bool QD3D11GraphicsPipeline::build() ...@@ -1670,7 +1696,7 @@ bool QD3D11GraphicsPipeline::build()
rastDesc.CullMode = toD3DCullMode(m_cullMode); rastDesc.CullMode = toD3DCullMode(m_cullMode);
rastDesc.FrontCounterClockwise = m_frontFace == CCW; rastDesc.FrontCounterClockwise = m_frontFace == CCW;
rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor); rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
//rastDesc.MultisampleEnable; rastDesc.MultisampleEnable = rhiD->effectiveSampleCount(m_sampleCount).Count > 1;
HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState); HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
if (FAILED(hr)) { if (FAILED(hr)) {
qWarning("Failed to create rasterizer state: %s", qPrintable(comErrorMessage(hr))); qWarning("Failed to create rasterizer state: %s", qPrintable(comErrorMessage(hr)));
...@@ -1811,14 +1837,13 @@ QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi) ...@@ -1811,14 +1837,13 @@ QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi)
for (int i = 0; i < BUFFER_COUNT; ++i) { for (int i = 0; i < BUFFER_COUNT; ++i) {
tex[i] = nullptr; tex[i] = nullptr;
rtv[i] = nullptr; rtv[i] = nullptr;
msaaTex[i] = nullptr;
msaaRtv[i] = nullptr;
} }
} }
void QD3D11SwapChain::release() void QD3D11SwapChain::releaseBuffers()
{ {
if (!swapChain)
return;
for (int i = 0; i < BUFFER_COUNT; ++i) { for (int i = 0; i < BUFFER_COUNT; ++i) {
if (rtv[i]) { if (rtv[i]) {
rtv[i]->Release(); rtv[i]->Release();
...@@ -1828,7 +1853,23 @@ void QD3D11SwapChain::release() ...@@ -1828,7 +1853,23 @@ void QD3D11SwapChain::release()
tex[i]->Release(); tex[i]->Release();
tex[i] = nullptr; tex[i] = nullptr;
} }
if (msaaRtv[i]) {
msaaRtv[i]->Release();
msaaRtv[i] = nullptr;
}
if (msaaTex[i]) {
msaaTex[i]->Release();
msaaTex[i] = nullptr;
}
} }
}
void QD3D11SwapChain::release()
{
if (!swapChain)
return;
releaseBuffers();
swapChain->Release(); swapChain->Release();
swapChain = nullptr; swapChain = nullptr;
...@@ -1854,6 +1895,38 @@ QRhiRenderPassDescriptor *QD3D11SwapChain::newCompatibleRenderPassDescriptor() ...@@ -1854,6 +1895,38 @@ QRhiRenderPassDescriptor *QD3D11SwapChain::newCompatibleRenderPassDescriptor()
return new QD3D11RenderPassDescriptor(rhi); return new QD3D11RenderPassDescriptor(rhi);
} }
bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
{
D3D11_TEXTURE2D_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.Width = size.width();
desc.Height = size.height();
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = format;
desc.SampleDesc = sampleDesc;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
QRHI_RES_RHI(QRhiD3D11);
HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, tex);
if (FAILED(hr)) {
qWarning("Failed to create color buffer texture: %s", qPrintable(comErrorMessage(hr)));
return false;
}
hr = rhiD->dev->CreateRenderTargetView(*tex, nullptr, rtv);
if (FAILED(hr)) {
qWarning("Failed to create color buffer rtv: %s", qPrintable(comErrorMessage(hr)));
(*tex)->Release();
*tex = nullptr;
return false;
}
return true;
}
bool QD3D11SwapChain::buildOrResize() bool QD3D11SwapChain::buildOrResize()
{ {
// Can be called multiple times due to window resizes - that is not the // Can be called multiple times due to window resizes - that is not the
...@@ -1864,14 +1937,13 @@ bool QD3D11SwapChain::buildOrResize() ...@@ -1864,14 +1937,13 @@ bool QD3D11SwapChain::buildOrResize()
window = m_window; window = m_window;
pixelSize = m_requestedPixelSize; pixelSize = m_requestedPixelSize;
colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
QRHI_RES_RHI(QRhiD3D11);
const DXGI_FORMAT colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
const UINT swapChainFlags = 0; const UINT swapChainFlags = 0;
QRHI_RES_RHI(QRhiD3D11);
if (!swapChain) { if (!swapChain) {
HWND hwnd = reinterpret_cast<HWND>(window->winId()); HWND hwnd = reinterpret_cast<HWND>(window->winId());
sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
// We use FLIP_DISCARD which implies a buffer count of 2 (as opposed to the // We use FLIP_DISCARD which implies a buffer count of 2 (as opposed to the
// old DISCARD with back buffer count == 1). This makes no difference for // old DISCARD with back buffer count == 1). This makes no difference for
...@@ -1900,16 +1972,7 @@ bool QD3D11SwapChain::buildOrResize() ...@@ -1900,16 +1972,7 @@ bool QD3D11SwapChain::buildOrResize()
return false; return false;
} }
} else { } else {
for (int i = 0; i < BUFFER_COUNT; ++i) { releaseBuffers();
if (rtv[i]) {
rtv[i]->Release();
rtv[i] = nullptr;
}
if (tex[i]) {
tex[i]->Release();
tex[i] = nullptr;
}
}
HRESULT hr = swapChain->ResizeBuffers(2, pixelSize.width(), pixelSize.height(), colorFormat, swapChainFlags); HRESULT hr = swapChain->ResizeBuffers(2, pixelSize.width(), pixelSize.height(), colorFormat, swapChainFlags);
if (FAILED(hr)) { if (FAILED(hr)) {
qWarning("Failed to resize D3D11 swapchain: %s", qPrintable(comErrorMessage(hr))); qWarning("Failed to resize D3D11 swapchain: %s", qPrintable(comErrorMessage(hr)));
...@@ -1928,6 +1991,10 @@ bool QD3D11SwapChain::buildOrResize() ...@@ -1928,6 +1991,10 @@ bool QD3D11SwapChain::buildOrResize()
qWarning("Failed to create rtv for swapchain buffer %d: %s", i, qPrintable(comErrorMessage(hr))); qWarning("Failed to create rtv for swapchain buffer %d: %s", i, qPrintable(comErrorMessage(hr)));
return false; return false;
} }
if (sampleDesc.Count > 1) {
if (!newColorBuffer(pixelSize, colorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
return false;
}
} }
currentFrame = 0; currentFrame = 0;
......
...@@ -326,14 +326,22 @@ struct QD3D11SwapChain : public QRhiSwapChain ...@@ -326,14 +326,22 @@ struct QD3D11SwapChain : public QRhiSwapChain
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override; QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
bool buildOrResize(); bool buildOrResize();
void releaseBuffers();
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
QWindow *window = nullptr; QWindow *window = nullptr;
QSize pixelSize; QSize pixelSize;
QD3D11ReferenceRenderTarget rt; QD3D11ReferenceRenderTarget rt;
QD3D11CommandBuffer cb; QD3D11CommandBuffer cb;
DXGI_FORMAT colorFormat;
IDXGISwapChain1 *swapChain = nullptr; IDXGISwapChain1 *swapChain = nullptr;
static const int BUFFER_COUNT = 2; static const int BUFFER_COUNT = 2;
ID3D11Texture2D *tex[BUFFER_COUNT]; ID3D11Texture2D *tex[BUFFER_COUNT];
ID3D11RenderTargetView *rtv[BUFFER_COUNT]; ID3D11RenderTargetView *rtv[BUFFER_COUNT];
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
DXGI_SAMPLE_DESC sampleDesc;
int currentFrame = 0; int currentFrame = 0;
QD3D11RenderBuffer *ds = nullptr; QD3D11RenderBuffer *ds = nullptr;
}; };
...@@ -407,6 +415,7 @@ public: ...@@ -407,6 +415,7 @@ public:
void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD); void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD);
void setShaderResources(QD3D11ShaderResourceBindings *srbD); void setShaderResources(QD3D11ShaderResourceBindings *srbD);
void executeCommandBuffer(QD3D11CommandBuffer *cbD); void executeCommandBuffer(QD3D11CommandBuffer *cbD);
DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
bool debugLayer = false; bool debugLayer = false;
bool importedDevice = false; bool importedDevice = false;
......
mtl: cubemaps mtl: cubemaps
mtl: targeting cubemap faces mtl: targeting cubemap faces
mtl: cbuffers, textures, samplers set should be batched too mtl: cbuffers, textures, samplers set should be batched too
d3d: msaa (onscreen)
mtl: msaa (onscreen) mtl: msaa (onscreen)
test cubemap test cubemap
test cubemap face as target test cubemap face as target
...@@ -38,11 +37,13 @@ more tex: 3d, array? ...@@ -38,11 +37,13 @@ more tex: 3d, array?
vk: support instanceStepRate via VK_EXT_vertex_attribute_divisor vk: support instanceStepRate via VK_EXT_vertex_attribute_divisor
shadertools: shadertools:
bytecode (fxc/dxc) for d3d? dxc for d3d as an alternative to fxc?
bytecode for metal?
hlsl -> dxc -> spirv -> spirv-cross hmmm... hlsl -> dxc -> spirv -> spirv-cross hmmm...
+++ done +++ done
d3d: msaa (onscreen)
bytecode for metal
bytecode (fxc) for d3d
vk: im.layout transition missing when no upload, no render to (or is the case invalid?) vk: im.layout transition missing when no upload, no render to (or is the case invalid?)
vk, d3d: verify no-color-just-depth again vk, d3d: verify no-color-just-depth again
preservecolor applies to which att. (all -> fix mtl) preservecolor applies to which att. (all -> fix mtl)
......
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