Jump to content
  • Advertisement
Sign in to follow this  
BlackJoker

SwapChain resize questions

This topic is 2091 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


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

Share this post


Link to post
Share on other sites

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.

Edited by BlackJoker

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • 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!