Advertisement

Black screen MSAA - ResolveSubresource

Started by August 05, 2019 05:22 PM
9 comments, last by komilll 5 years, 1 month ago

Hey,

To begin with - I was successful with creating MSAA using MSAA swap chain, but I am not satisfied with it, especially because it doesn't support changing MSAA settings on the fly.
I've already read many thread on this forum regarding MSAA and I learnt here about ResolveSubresource and how we deal with converting MSAA texture to non-MSAA to present it on screen with non-MSAA buffer.

A little background: I have forward rendering engine, I have also already used render targets. I am creating render target for scene, render models to it. Then I am creating G-buffers for SSAO which I render to another texture and then I apply another post-processes. For sake of testing MSAA, I am using no post-processes.
m_renderTextureMainScene is my MSAA buffer. Then I am trying to resolve it to non-MSAA render target but only black screen appears. When m_renderTextureMainScene is non-MSAA, rendering works fine:


	XMMATRIX worldMatrix, viewMatrix, projectionMatrix, lightViewMatrix, lightProjectionMatrix;

    m_renderTextureMainScene->SetRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView());
    m_renderTextureMainScene->ClearRenderTarget(m_D3D->GetDeviceContext(), m_D3D->GetDepthStencilView(), 0.0f, 0.0f, 0.0f, 1.0f);

	for (ModelClass* const& model : m_sceneModels)
	{
		// ...
		model->Render(m_D3D->GetDeviceContext());
		// ...
	}

	if (DRAW_SKYBOX)
	{
		if (RenderSkybox() == false)
			return false;
	}
	m_D3D->SetBackBufferRenderTarget();


	static RenderTextureClass *renderTexture;
	if (renderTexture == nullptr)
	{
		renderTexture = new RenderTextureClass;
		renderTexture->Initialize(m_D3D->GetDevice(), m_screenWidth, m_screenHeight, 1);
	}

    m_D3D->GetDeviceContext()->ResolveSubresource(renderTexture->GetShaderResource(), 0, m_renderTextureMainScene->GetShaderResource(), 0, DXGI_FORMAT_R16G16B16A16_FLOAT);

	m_renderTexturePreview->BindTexture(renderTexture->GetShaderResourceView());
	if (!m_renderTexturePreview->Render(m_D3D->GetDeviceContext(), 0, worldMatrix, viewMatrix, projectionMatrix))
		return false;

 

 

 

Have you enabled the debug layer? Does it say anything?

Advertisement

For rendering MSAA x2 I have those messages. Last message appear also for x1, others do not:

  • D3D11 ERROR: ID3D11DeviceContext::OMSetRenderTargets: The RenderTargetView at slot 0 is not compatable with the DepthStencilView. DepthStencilViews may only be used with RenderTargetViews if the effective dimensions of the Views are equal, as well as the Resource types, multisample count, and multisample quality. The RenderTargetView at slot 0 has (w:1280,h:720,as:1), while the Resource is a Texture2D with (mc:2,mq:0). The DepthStencilView has (w:1280,h:720,as:1), while the Resource is a Texture2D with (mc:1,mq:0). D3D11_RESOURCE_MISC_TEXTURECUBE factors into the Resource type, unless GetFeatureLevel() returns D3D_FEATURE_LEVEL_10_1 or greater. [ STATE_SETTING ERROR #388: OMSETRENDERTARGETS_INVALIDVIEW]
  • D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 1, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults.  [ EXECUTION WARNING #352: DEVICE_DRAW_SAMPLER_NOT_SET]
  •  ERROR: ID3D11DeviceContext::DrawIndexed: The Shader Resource View dimension declared in the shader code (TEXTURE2D) does not match the view type bound to slot 0 of the Pixel Shader unit (TEXTURE2DMS).  This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching). [ EXECUTION ERROR #354: DEVICE_DRAW_VIEW_DIMENSION_MISMATCH]

I found solution for last point I guess. Or is it different problem?

 

The first one is probably your primary problem. You have mixed MSAA between your render target and depth stencil, which is invalid.

When I am rendering model by model and not using rendered texture with MSAAx2 it works fine. However trying to resolve subresource or presenting that texture shows first error.

I don't really understand how did I mixed MSAA between render target and depth stencil. Could you explain more what that means?

Advertisement

If you render to an MSAA render target, then the depth/stencil buffer also needs to use the same MSAA mode (or the depth/stencil buffer needs to be NULL). So in this case you need to create depth/stencil buffer with sample count of 2.

Here is the code I'm using to create depth buffer. sizeMultiplier is set to 1 (I use higher values for SSAA).
I checked it through Nsight and rendering seems to be ok. There are less jaggies but when presenting buffer, black screen appears.

594948362_ss(2019-08-09at08_47.26).thumb.png.d549640c779ef9e83f0db368878ac0ed.png


bool D3DClass::CreateDepthBuffer(int sizeMultiplier)
{
    HRESULT result;
    DXGI_ADAPTER_DESC adapterDesc;
    D3D11_TEXTURE2D_DESC depthBufferDesc;
    D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;

    // Initialize the description of the depth buffer.
    ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));

    // Set up the description of the depth buffer.
    depthBufferDesc.Width = m_windowSizeX * sizeMultiplier;
    depthBufferDesc.Height = m_windowSizeY * sizeMultiplier;
    depthBufferDesc.MipLevels = 1;
    depthBufferDesc.ArraySize = 1;
    depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthBufferDesc.SampleDesc.Count = 2;
    depthBufferDesc.SampleDesc.Quality = 0;
    depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    depthBufferDesc.CPUAccessFlags = 0;
    depthBufferDesc.MiscFlags = 0;

    // Create the texture for the depth buffer using the filled out description.
    result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
    if (FAILED(result))
    {
        return false;
    }

    // Initialize the description of the stencil state.
    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));

    // Set up the description of the stencil state.
    depthStencilDesc.DepthEnable = true;
    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;

    depthStencilDesc.StencilEnable = true;
    depthStencilDesc.StencilReadMask = 0xFF;
    depthStencilDesc.StencilWriteMask = 0xFF;

    // Stencil operations if pixel is front-facing.
    depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Stencil operations if pixel is back-facing.
    depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Create the depth stencil state.
    result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
    if (FAILED(result))
    {
        return false;
    }

    depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
    result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilStateSkybox);
    if (FAILED(result))
    {
        return false;
    }

    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
    depthStencilDesc.DepthFunc = D3D11_COMPARISON_NEVER;
    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    depthStencilDesc.DepthEnable = false;
    depthStencilDesc.StencilEnable = false;
    result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilStateZBufferOff);
    if (FAILED(result))
    {
        return false;
    }

    // Set the depth stencil state.
    m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);

    // Initialize the depth stencil view.
    ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));

    // Set up the depth stencil view description.
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
    depthStencilViewDesc.Texture2D.MipSlice = 0;

    // Create the depth stencil view.
    result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
    if (FAILED(result))
    {
        return false;
    }

    return true;
}

 

Indeed, it looks like you're creating a depth buffer with 2x MSAA. Perhaps you have the wrong depth buffer bound at the time of a draw call? To help narrow it down, you can tell the debug layer to break into the debugger at the point where the warning/error happens:
 


ID3D11InfoQueue* infoQueue = nullptr;
device->QueryInterface(IID_PPV_ARGS(&infoQueue));
if(infoQueue != nullptr)
{
    infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, TRUE);
    infoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, TRUE);
    infoQueue->Release();
    infoQueue = nullptr;
}

This should help you figure out the draw call that's causing the error. Alternatively, you can use RenderDoc to capture a frame, and then within the capture you can double-click on the validation error and it will take you to the draw call that caused the error.

Thank you, sir. I had no idea that such debug options exist in DirectX, that's a great tool for debuging, thanks once again.

But back to what a problem was - I was using only one DepthStencilView for everything. When there was an intention to render data that doesn't use MSAA, there was a count mismatch, because the only stencil view was the one with MSAA.

That means that I created new StencilView:


m_depthStencilViewBackBuffer = CreateDepthBufferReturn(1, 1); //Size multiplier = 1 (higher values for SSAA), depth buffer count = 1
//...
void D3DClass::SetBackBufferRenderTarget() const //Use for non-MSAA rendering; Render MSAA directly to texture and resolve
{
	m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilViewBackBuffer);
}

However MSAA was working even without resolving texture, which is weird, I guess? Here is a result of MSAAx2 without resolving texture. Aftering uncommenting resolving, results are the same.

1595254788_ss(2019-08-11at04_08.04).thumb.png.3b3748a3bebabadea59504302993d3f5.png474741670_ss(2019-08-11at04_08.11).thumb.png.c9d607f43a764ee88267fdfff57bcaa7.png

This topic is closed to new replies.

Advertisement