SwapChain resize questions

Started by
16 comments, last by BlackJoker 10 years, 2 months ago

I have few questions regarding swapchain resizing:

First question:

I made resizing just like in MSDN article, but seems it works not fully correct.

After resizing back of my model begin to be visible from front. You can look this at screenshots

[attachment=19533:before_res.png]

[attachment=19534:after_res.png]

[attachment=19535:result.png]

first screenshot - before resizing

second - after

third - how it displays in another angle.

Looks like stencil operation not working. Here is the code of my swapchain resizing:


void D3D11::ResizeSwapChain()
{
	if (swapChain)
	{
		DeinitializeD2D11();
		RECT rc;
		GetClientRect(hwnd, &rc);
		UINT width = rc.right - rc.left;
		UINT height = rc.bottom - rc.top;

		d3d11_DeviceContext->OMSetRenderTargets(0, 0, 0);

		// Release all outstanding references to the swap chain's buffers.
		d3d11_RenderTargetView->Release();

		HRESULT hr;
		// Preserve the existing buffer count and format.
		// Automatically choose the width and height to match the client rect for HWNDs.
		hr = swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);


		// Perform error handling here!

		// Get buffer and create a render-target-view.
		ID3D11Texture2D* pBuffer;
		hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
			(void**)&pBuffer);
		// Perform error handling here!

		hr = d3d11_Device->CreateRenderTargetView(pBuffer, NULL,
			&d3d11_RenderTargetView);
		// Perform error handling here!
		pBuffer->Release();

		d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, NULL);

		// Set up the viewport.
		D3D11_VIEWPORT viewPort;

		viewPort.Width = (float)width;
		viewPort.Height = (float)height;
		viewPort.MinDepth = 0.0f;
		viewPort.MaxDepth = 1.0f;
		viewPort.TopLeftX = 0.0f;
		viewPort.TopLeftY = 0.0f;
		d3d11_DeviceContext->RSSetViewports(1, &viewPort);

		InitializeD2D11();
	}
}

And second question:

if I created swapchain with 2 or more buffers, is this code correct in this case or I need do some changes to correctly resize all buffers?

Advertisement

Looks like you don't set a depth-buffer (depth-stencil view, the final parameter of OMSetRenderTargets) anymore. Provided that you show us all.

I can do like this:




if (swapChain)
	{
		DeinitializeD2D11();
		RECT rc;
		GetClientRect(hwnd, &rc);
		UINT width = rc.right - rc.left;
		UINT height = rc.bottom - rc.top;

		d3d11_DeviceContext->OMSetRenderTargets(0, 0, 0);

		// Release all outstanding references to the swap chain's buffers.
		d3d11_RenderTargetView->Release();

		HRESULT hr;
		// Preserve the existing buffer count and format.
		// Automatically choose the width and height to match the client rect for HWNDs.
		hr = swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);


		// Perform error handling here!

		// Get buffer and create a render-target-view.
		ID3D11Texture2D* pBuffer;
		hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
			(void**)&pBuffer);

		
		// Perform error handling here!

		hr = d3d11_Device->CreateRenderTargetView(pBuffer, NULL,
			&d3d11_RenderTargetView);
		// Perform error handling here!
		
		//?????????????? ???????? ????????? Depth_Buffer
		ZeroMemory(&depthBufferDescription, sizeof(depthBufferDescription));

		//????????? ???????? ?????????
		depthBufferDescription.Width = width;
		depthBufferDescription.Height = height;
		depthBufferDescription.MipLevels = 1;
		depthBufferDescription.ArraySize = 1;
		depthBufferDescription.Format = DXGI_FORMAT_D32_FLOAT;
		depthBufferDescription.SampleDesc.Count = 4;
		depthBufferDescription.SampleDesc.Quality = 0;
		depthBufferDescription.Usage = D3D11_USAGE_DEFAULT;
		depthBufferDescription.BindFlags = D3D11_BIND_DEPTH_STENCIL;
		depthBufferDescription.CPUAccessFlags = 0;
		depthBufferDescription.MiscFlags = 0;

		d3d11_DepthStencilBuffer->Release();
		d3d11_DepthStencilBuffer = NULL;

		//??????? ???????? ??? ?????? ??????? ????????? ??????????? ?????????
		d3d11_Device->CreateTexture2D(&depthBufferDescription, NULL, &d3d11_DepthStencilBuffer);

		//?????? ????????? Depth Stencil State
		d3d11_DeviceContext->OMSetDepthStencilState(d3d11_DepthStencilState, 1);

		//?????????????? ????????? Depth Stencil View
		ZeroMemory(&depthStencilViewDescription, sizeof(depthStencilViewDescription));

		//????????? ???????? ????????? Depth_Stencil_View
		depthStencilViewDescription.Format = DXGI_FORMAT_D32_FLOAT;
		depthStencilViewDescription.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
		depthStencilViewDescription.Texture2D.MipSlice = 0;

		d3d11_DepthStencilView->Release();
		d3d11_DepthStencilView = NULL;

		//?????? ???????? ????????? Depth_Stencil_View
		d3d11_Device->CreateDepthStencilView(d3d11_DepthStencilBuffer, &depthStencilViewDescription, &d3d11_DepthStencilView);

		d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, d3d11_DepthStencilView);

		//d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, d3d11_DepthStencilView);
		pBuffer->Release();
		// Set up the viewport.
		D3D11_VIEWPORT viewPort;

		viewPort.Width = (float)width;
		viewPort.Height = (float)height;
		viewPort.MinDepth = 0.0f;
		viewPort.MaxDepth = 1.0f;
		viewPort.TopLeftX = 0.0f;
		viewPort.TopLeftY = 0.0f;
		d3d11_DeviceContext->RSSetViewports(1, &viewPort);

		InitializeD2D11();
	}

But this leads to flickering of meshes during resizing.

I had the same issue, when I implemented the resizing and also got some ugly synchronization problems up to bluescreens from graphiccard-driver, cause I rendered in another thread to the window-messagequeue and called the resize-function on every WM_MOVE event.

When you trigger your resizefunction? I guess the order Drawing->Present->Resize or Resize->Drawing->Present should reduce flickering. In my solution I ended up in just resize the textures when resize is finished. So the rendered image gets scaled while resizing and corrected just once afterwards.

Auskennfuchs

I trigger my function before drawing. After your advice I move triggering after Present. Flickering reduced a little, but is not gone. How to completely remove it? It is interesting that if not recreate depth buffer during resizing, flickering will completely removed, but this will lead to loss of depth.

Just in case, I'd try clearing both buffers (textures) of the swap chain, if you have two, just after calling ResizeBuffers and before OMSetRenderTargets. You could use ID3D11DeviceContext::ClearRenderTargetView on your RTV, or Map, or UpdateSubresource or anything.

pcmaster

could you please give a little code sample regarding my situation?

Something like this:


        ID3D11Texture2D* pBuffer;
        hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBuffer);
        ID3D11Texture2D* pBuffer2;
        hr = swapChain->GetBuffer(1, __uuidof(ID3D11Texture2D), (void**)&pBuffer2); // the second buffer which might contain random data

        hr = d3d11_Device->CreateRenderTargetView(pBuffer, nullptr, &d3d11_RenderTargetView); // RTV for swap buffer "0"
        hr = d3d11_Device->CreateRenderTargetView(pBuffer2, nullptr, &tmpRTV2); // a TEMPORARY RTV for swap buffer "1"
        d3d11_DeviceContext->ClearRenderTargetView(d3d11_RenderTargetView, black); // clear everything, just in case
        d3d11_DeviceContext->ClearRenderTargetView(tmpRTV2, black); // black is 4 floats of 0
        pBuffer->Release();
        pBuffer2->Release();

        d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, d3d11_DepthStencilView);

This is just a blind shot, might not be the problem (it is on the newest consoles).

Also mind checking your initialize methods, if you don't reset some state that you don't want to reset.

Here is my initialize method.

Not sure that I work with 2 buffers correctly:


UINT numFeatureLevels = ARRAYSIZE(featureLevels);
	factory->EnumAdapters(0,&adapter);
	//??????? ?????????? Direct3D ? ???????? ?????????? Direct3D
	result = D3D11CreateDevice(adapterList[0]->adapter, driverType, NULL, D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels,numFeatureLevels,
		D3D11_SDK_VERSION, &d3d11_Device, &featureLevel, &d3d11_DeviceContext );

	if (FAILED(result))
	{
		return false;
	}
	UINT qualityLevels;
	result = d3d11_Device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 8, &qualityLevels);


	//?????????????? ????????? swap chain description
	ZeroMemory(&swapChainDescription, sizeof(swapChainDescription));
	

	//????????????? ?????????? ???????
	swapChainDescription.BufferCount = 2;

	//????????????? ?????? ? ?????? ??????? ??????
	swapChainDescription.Width = settingsContainer->renderSettingsDX11->GetScreenWidth();
	swapChainDescription.Height = settingsContainer->renderSettingsDX11->GetScreenHeight();

	//????????????? ?????? ????????
	swapChainDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

	swapChainDescription.SampleDesc.Count = 4;
	swapChainDescription.SampleDesc.Quality = 0;

	//????????????? ????????????? ??????? ??????
	swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
	swapChainDescription.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;

	DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen;
	fullscreen.RefreshRate.Numerator = 60;
	fullscreen.RefreshRate.Denominator = 1;
	fullscreen.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
	fullscreen.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
	//????????????? ? ????????????? ????? ? ???????
	if (settingsContainer->renderSettingsDX11->IsFullScreenEnabled())
	{
		fullscreen.Windowed = FALSE;
	}
	else
	{
		fullscreen.Windowed = TRUE;
	}
	
	

	//??????? swap chain
	result = factory->CreateSwapChainForHwnd(d3d11_Device, hwnd, &swapChainDescription, &fullscreen, NULL, &swapChain);
	if(FAILED(result))
		return false;
	
	//???????? ????????? ?? ?????? ?????
	result = swapChain->GetBuffer(0,__uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
	if (FAILED(result))
		return false;

	
	//??????? render target view ? ?????????? ?? ?????? ?????
	result = d3d11_Device->CreateRenderTargetView(backBufferPtr, NULL, &d3d11_RenderTargetView);
	if(FAILED(result))
		return false;
	
	//??????????? ????????? ?? ?????? ?????, ??? ??? ?? ?????? ?? ?????
	backBufferPtr->Release();
	backBufferPtr = 0;

	//?????????????? ???????? ????????? Depth_Buffer
	ZeroMemory(&depthBufferDescription, sizeof(depthBufferDescription));

	//????????? ???????? ?????????
	depthBufferDescription.Width = settingsContainer->renderSettingsDX11->GetScreenWidth();
	depthBufferDescription.Height = settingsContainer->renderSettingsDX11->GetScreenHeight();
	depthBufferDescription.MipLevels = 1;
	depthBufferDescription.ArraySize = 1;
	depthBufferDescription.Format = DXGI_FORMAT_D32_FLOAT;
	depthBufferDescription.SampleDesc.Count = 4;
	depthBufferDescription.SampleDesc.Quality = 0;
	depthBufferDescription.Usage = D3D11_USAGE_DEFAULT;
	depthBufferDescription.BindFlags = D3D11_BIND_DEPTH_STENCIL;
	depthBufferDescription.CPUAccessFlags = 0;
	depthBufferDescription.MiscFlags = 0;

	//??????? ???????? ??? ?????? ??????? ????????? ??????????? ?????????
	result = d3d11_Device->CreateTexture2D(&depthBufferDescription, NULL, &d3d11_DepthStencilBuffer);
	if (FAILED(result))
		return false;
		


	//?????????????? ???????? stencil state
	ZeroMemory(&depthStencilDescription, sizeof(depthStencilDescription));

	//?????? ???????? ????????? stencil_state
	depthStencilDescription.DepthEnable = true;
	depthStencilDescription.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	depthStencilDescription.DepthFunc = D3D11_COMPARISON_LESS;

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

	//????????? ???????? ???? ??????? ???????
	depthStencilDescription.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDescription.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
	depthStencilDescription.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDescription.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	//????????? ????????, ???? ??????? ?? ???????? ???????
	depthStencilDescription.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDescription.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
	depthStencilDescription.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDescription.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
	
	//??????? Depth_Stencil_State
	result = d3d11_Device->CreateDepthStencilState(&depthStencilDescription, &d3d11_DepthStencilState);
	if (FAILED(result))
	{
		return false;
	}
	//?????? ????????? Depth Stencil State
	d3d11_DeviceContext->OMSetDepthStencilState(d3d11_DepthStencilState,1);
	
	//?????????????? ????????? Depth Stencil View
	ZeroMemory (&depthStencilViewDescription, sizeof(depthStencilViewDescription));
	
	//????????? ???????? ????????? Depth_Stencil_View
	depthStencilViewDescription.Format = DXGI_FORMAT_D32_FLOAT;
	depthStencilViewDescription.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
	depthStencilViewDescription.Flags = 0;

	//?????? ???????? ????????? Depth_Stencil_View
	result = d3d11_Device->CreateDepthStencilView(d3d11_DepthStencilBuffer, &depthStencilViewDescription, &d3d11_DepthStencilView);
	if (FAILED(result))
		return false;

	//??????????? render target view ? depth stencil buffer ? output pipeline
	d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, d3d11_DepthStencilView);

	//????????? ????????? Raster_Description, ??????? ????? ?????????? ??? ? ????? ???????? ????? ??????????
	rasterizerDescription.AntialiasedLineEnable = true;
	rasterizerDescription.CullMode = D3D11_CULL_BACK;
	rasterizerDescription.DepthBias = 0;
	rasterizerDescription.DepthBiasClamp = 0.0f;
	rasterizerDescription.DepthClipEnable = true;
	rasterizerDescription.FillMode = D3D11_FILL_SOLID;
	rasterizerDescription.FrontCounterClockwise = false;
	rasterizerDescription.MultisampleEnable = true;
	rasterizerDescription.ScissorEnable = false;
	rasterizerDescription.SlopeScaledDepthBias = 0.0f;

	//??????? rasterizerState ?? ????????, ??????? ?????? ??? ?????????
	result = d3d11_Device->CreateRasterizerState(&rasterizerDescription, &d3d11_RasterizerStateSolid);
	if(FAILED(result))
	{
		return false;
	}
	
	//????????????? rasterizer state (????? ?????? ????????? ? D3D11_FILL_SOLID ?? D3D11_FILL_WIREFRAME)
	d3d11_DeviceContext->RSSetState(d3d11_RasterizerStateSolid);

	//????????? ????????? Raster_Description, ??????? ????? ?????????? ??? ? ????? ???????? ????? ??????????
	rasterizerDescription.AntialiasedLineEnable = true;
	rasterizerDescription.CullMode = D3D11_CULL_NONE;
	rasterizerDescription.DepthBias = 0;
	rasterizerDescription.DepthBiasClamp = 0.0f;
	rasterizerDescription.DepthClipEnable = true;
	rasterizerDescription.FillMode = D3D11_FILL_WIREFRAME;
	rasterizerDescription.FrontCounterClockwise = false;
	rasterizerDescription.MultisampleEnable = true;
	rasterizerDescription.ScissorEnable = false;
	rasterizerDescription.SlopeScaledDepthBias = 0.0f;

	//??????? rasterizerState ?? ????????, ??????? ?????? ??? ?????????
	result = d3d11_Device->CreateRasterizerState(&rasterizerDescription, &d3d11_RasterizerStateWireFrame);
	if(FAILED(result))
	{
		return false;
	}

	//????????????? ??????? ??? ??????????
	viewPort.Width = (float)settingsContainer->renderSettingsDX11->GetScreenWidth();
	viewPort.Height = (float)settingsContainer->renderSettingsDX11->GetScreenHeight();
	viewPort.MinDepth = 0.0f;
	viewPort.MaxDepth = 1.0f;
	viewPort.TopLeftX = 0.0f;
	viewPort.TopLeftY = 0.0f;

	//??????? ViewPort
	d3d11_DeviceContext->RSSetViewports(1,&viewPort);

And another one issue. I justed noticed That if I made resizing just like I did before, but if OMSetRenderTargets will contain depth-StencilView, then my mesh disapper if I make window bigget that it was and appear, if I make window smaller, that it was. Is it Correct behavior?


RECT rc;
		GetClientRect(hwnd, &rc);
		UINT width = rc.right - rc.left;
		UINT height = rc.bottom - rc.top;

		d3d11_DeviceContext->OMSetRenderTargets(0, 0, 0);

		// Release all outstanding references to the swap chain's buffers.
		d3d11_RenderTargetView->Release();

		HRESULT hr;
		// Preserve the existing buffer count and format.
		// Automatically choose the width and height to match the client rect for HWNDs.
		hr = swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);


		// Perform error handling here!

		// Get buffer and create a render-target-view.
		ID3D11Texture2D* pBuffer;
		hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
			(void**)&pBuffer);

		
		// Perform error handling here!

		hr = d3d11_Device->CreateRenderTargetView(pBuffer, NULL,
			&d3d11_RenderTargetView);
		
		d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, d3d11_DepthStencilView);
		pBuffer->Release();
		// Set up the viewport.
		D3D11_VIEWPORT viewPort;

		viewPort.Width = (float)width;
		viewPort.Height = (float)height;
		viewPort.MinDepth = 0.0f;
		viewPort.MaxDepth = 1.0f;
		viewPort.TopLeftX = 0.0f;
		viewPort.TopLeftY = 0.0f;
		d3d11_DeviceContext->RSSetViewports(1, &viewPort);

As i underatnd resizeBuffer function resizes depthBuffer also? If so, Why in this case mesh just disappears after resizing?

This topic is closed to new replies.

Advertisement