Jump to content
  • Advertisement
komilll

DX11 Black screen MSAA - ResolveSubresource

Recommended Posts

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;

 

 

 

Share this post


Link to post
Share on other sites
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?

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
Posted (edited)

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;
}

 

Edited by komilll
Change quote to code snippet

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

@MJP

Well, my previous assumption was only partially right. In post above I managed to get version without skybox working, but I was investigating it for the last two days and I find why it actually doesn't work with skybox.

  1. Render scene to texture (msaa x2)
  2. Render skybox
  3. Resolve texture
  4. Present

After resolve step, render target is black and just black screen is presented at the end.

However, when I am not using msaa it works without problem. When I am not using skybox, it also works ok. Problem is that I don't know how to use MSAA with skybox. I am using CreateDDSTextureFromFile for importing .DDS skybox file.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!