DirectX 11 从全屏切换 ->窗口问题
我一直在各个网站上寻找管理切换的正确方法。
我以为我已经破解了它,但现在我注意到一个奇怪的问题,因为我正在为绘制调用设置顶点和像素着色器。
我可以使用 alt-enter 切换到全屏,一切都很好,切换回来要么留下空白窗口,要么正确渲染,但永远不会继续渲染任何更新。
即,它基本上会渲染一帧,并且任何输入都会被注册,但在屏幕上不可见,直到您切换到全屏。
很明显,我可能缺少交换链或设备上下文的某些内容,因为我注意到使用 Flush() 会强制它工作,但我意识到这显然不是解决方案。
渲染函数片段
cube_.setToContext(context);
context->VSSetConstantBuffers( 0, 1, &cb_NeverChanges_ );
context->VSSetConstantBuffers( 1, 1, &cb_ResizeChanges_ );
context->VSSetConstantBuffers( 2, 1, &cb_FrameChanges_ );
context->PSSetConstantBuffers( 0, 1, &cb_NeverChanges_ );
context->PSSetConstantBuffers( 1, 1, &cb_ResizeChanges_ );
context->PSSetConstantBuffers( 2, 1, &cb_FrameChanges_ );
context->VSSetShader( vertexShader_, nullptr, 0 );
context->PSSetShader( pixelShader_, nullptr, 0 );
context->Draw(cube_.getVertexTotal(), 0);
dx_.getSwapChain()->Present(0,0);
传递高度/宽度,
if(FAILED(swapChain_->GetFullscreenState(&fullScreen, nullptr)))
OutputDebugStringA("Failed to get fullscreen state.\n");
swapChain_->GetDesc(&swapChainDesc);
swapChainDesc.Windowed = !fullScreen;
swapChainDesc.Flags = 0;
if(fullScreen)
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
//Release renderTarget, depth stencil, depth stencil view, etc
depthStencilView_->Release();
depthStencil_->Release();
renderTarget_->Release();
if(FAILED(swapChain_->ResizeBuffers(swapChainDesc.BufferCount,width,height, swapChainDesc.BufferDesc.Format ,swapChainDesc.Flags)))
{
MessageBox( NULL, "Failed to resize buffers.", "Error", MB_OK );
return false;
}
//recreate everything that was released
if(!createRenderTarget())
return false;
if(!createDepthStencils(width,height))
return false;
context_->OMSetRenderTargets( 1, &renderTarget_, depthStencilView_);
D3D11_VIEWPORT vp; //Should be a member of dx!
vp.Width = (float)width;
vp.Height = (float)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
context_->RSSetViewports( 1, &vp );
调整大小函数,该函数从 WM_SIZE 案例交换链设置中
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory( &swapChainDesc, sizeof( swapChainDesc ) );
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; //auto =0, originally 60
swapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = TRUE;
我一直在使用 D3D11_CREATE_DEVICE_DEBUG 对此进行测试,没有错误/警告/泄漏,欢迎任何评论或输入。
I've been trawling various sites looking for the correct way to manage switching.
I thought I had cracked it but I've noticed a bizarre issue now that I am setting vertex and pixel shaders for a draw call.
I can swap to full screen using alt-enter and everything is fine, swapping back with either leave a blank window or render correctly but never continue to render any updates.
I.e it'll basically render one frame and any input is registered but not visible on screen till you swap to full screen.
Its clear I'm probably missing something with the swapchain or devicecontext as I noticed using Flush() it would force it to work however I realize that clearly isn't the solution.
Render function snippet
cube_.setToContext(context);
context->VSSetConstantBuffers( 0, 1, &cb_NeverChanges_ );
context->VSSetConstantBuffers( 1, 1, &cb_ResizeChanges_ );
context->VSSetConstantBuffers( 2, 1, &cb_FrameChanges_ );
context->PSSetConstantBuffers( 0, 1, &cb_NeverChanges_ );
context->PSSetConstantBuffers( 1, 1, &cb_ResizeChanges_ );
context->PSSetConstantBuffers( 2, 1, &cb_FrameChanges_ );
context->VSSetShader( vertexShader_, nullptr, 0 );
context->PSSetShader( pixelShader_, nullptr, 0 );
context->Draw(cube_.getVertexTotal(), 0);
dx_.getSwapChain()->Present(0,0);
Resize function which gets passed height/width from WM_SIZE case
if(FAILED(swapChain_->GetFullscreenState(&fullScreen, nullptr)))
OutputDebugStringA("Failed to get fullscreen state.\n");
swapChain_->GetDesc(&swapChainDesc);
swapChainDesc.Windowed = !fullScreen;
swapChainDesc.Flags = 0;
if(fullScreen)
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
//Release renderTarget, depth stencil, depth stencil view, etc
depthStencilView_->Release();
depthStencil_->Release();
renderTarget_->Release();
if(FAILED(swapChain_->ResizeBuffers(swapChainDesc.BufferCount,width,height, swapChainDesc.BufferDesc.Format ,swapChainDesc.Flags)))
{
MessageBox( NULL, "Failed to resize buffers.", "Error", MB_OK );
return false;
}
//recreate everything that was released
if(!createRenderTarget())
return false;
if(!createDepthStencils(width,height))
return false;
context_->OMSetRenderTargets( 1, &renderTarget_, depthStencilView_);
D3D11_VIEWPORT vp; //Should be a member of dx!
vp.Width = (float)width;
vp.Height = (float)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
context_->RSSetViewports( 1, &vp );
Swap Chain setup with this
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory( &swapChainDesc, sizeof( swapChainDesc ) );
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; //auto =0, originally 60
swapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = TRUE;
I've been testing this with D3D11_CREATE_DEVICE_DEBUG and no errors/warnings/leaks, any comments or input welcome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最新的 nvidia 驱动程序已针对测试的 gtx460 和 gtx570 解决了此问题(驱动程序 275.33)。
显然有一个软件解释和解决这个问题的答案,但它现在正在工作,这就是我想要的。
任何人将来阅读本文并偶然发现其他修复程序,请告诉我。
The latest nvidia drivers have resolved this issue (drivers 275.33) for the gtx460 and gtx570 tested on.
There obviously is a software explanation and answer to this problem but its working now and that is what I wanted.
Anyone reading this in the future and stumble upon the other fix please let me know.
从 D3D10 移植到 11 后,我的应用程序遇到了同样的问题。从全屏模式切换到窗口模式时,一切都是空白。安装最新的 GeForce 驱动器解决了该问题(无需更改任何代码)。
After porting from D3D10 to 11 my I ran into the same issues with my app. Everything blank when switching from fullscreen to windowed mode. Installing the latest GeForce drives resolved the issue (without any code changes).