Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Değiştirme zincirinin yeni bir çerçeve işlemeye başlamak için uygun zamanı işaretlemesini bekleyerek etkin çerçeve gecikme süresini azaltmak için DXGI 1.3 kullanın. Oyunların genellikle oyuncu girişinin alındığı zamandan, oyunun ekranı güncelleştirerek bu girişe yanıt vermesine kadar mümkün olan en düşük gecikme süresini sağlaması gerekir. Bu konu başlığı altında, Direct3D 11.2'den başlayarak oyununuzda etkili kare gecikme süresini en aza indirmek için kullanabileceğiniz bir teknik açıklanmaktadır.
Arka arabellekte beklemek gecikme süresini nasıl azaltır?
Flip model takas zinciriyle, oyununuz IDXGISwapChain::P resent
DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT bayrağıyla beklenebilir bir takas zinciri oluşturun. Bu şekilde oluşturulan takas zincirleri, sistem gerçekten yeni bir çerçeveyi kabul etmeye hazır olduğunda işleme döngünüzü bilgilendirebilir. Bu, oyununuzun geçerli verilere göre işlenmesine ve ardından sonucu hemen mevcut kuyruğa koymasına olanak tanır.
Adım 1. Beklenebilir bir takas zinciri oluşturun
CreateSwapChainForCoreWindow
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; // Enable GetFrameLatencyWaitableObject().
Uyarı
Bazı bayrakların aksine, bu bayrak ResizeBufferskullanılarak eklenemez veya kaldırılamaz. Bu bayrak değiştirme zincirinin oluşturulduğundan farklı ayarlanırsa DXGI bir hata kodu döndürür.
// If the swap chain already exists, resize it.
HRESULT hr = m_swapChain->ResizeBuffers(
2, // Double-buffered swap chain.
static_cast<UINT>(m_d3dRenderTargetSize.Width),
static_cast<UINT>(m_d3dRenderTargetSize.Height),
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT // Enable GetFrameLatencyWaitableObject().
);
Adım 2. Çerçeve gecikme süresini ayarlama
IDXGISwapChain2::SetMaximumFrameLatency API'si ile IDXGIDevice1::SetMaximumFrameLatencyçağırmak yerine çerçeve gecikme süresini ayarlayın.
Varsayılan olarak, beklenebilir takas zincirleri için çerçeve gecikme süresi 1 olarak ayarlanır, bu da mümkün olan en düşük gecikmeye neden olur ancak CPU-GPU paralelliği azaltır. 60 FPS'ye ulaşmak için artan CPU-GPU paralelliğe ihtiyacınız varsa , yani CPU ve GPU'ların her biri 16,7 ms'den az bir çerçeve işleme işi harcarsa, ancak toplamları 16,7 ms'den büyükse, çerçeve gecikme süresini 2 olarak ayarlayın. Bu, GPU'ya, önceki kare sırasında CPU tarafından kuyruğa alınan işleri işlerken aynı anda CPU'nın geçerli kare için işleme komutlarını bağımsız olarak göndermesine olanak tanır.
// Swapchains created with the DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT flag use their
// own per-swapchain latency setting instead of the one associated with the DXGI device. The
// default per-swapchain latency is 1, which ensures that DXGI does not queue more than one frame
// at a time. This both reduces latency and ensures that the application will only render after
// each VSync, minimizing power consumption.
//DX::ThrowIfFailed(
// swapChain2->SetMaximumFrameLatency(1)
// );
Adım 3. Takas zincirinden beklenebilir nesneyi elde etme
IDXGISwapChain2::GetFrameLatencyWaitableObject çağırarak bekleme tutamacını alın. Bekleme tutamacı, beklenebilir nesnenin işaretçisidir. Bu tanıtıcıyı işleme döngünüz tarafından kullanılmak üzere depolayın.
// Get the frame latency waitable object, which is used by the WaitOnSwapChain method. This
// requires that swap chain be created with the DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
// flag.
m_frameLatencyWaitableObject = swapChain2->GetFrameLatencyWaitableObject();
Adım 4. Her çerçeveyi işlemeden önce bekleyin
İşleme döngünüz, her kareyi işlemeye başlamadan önce takas zincirinin beklenebilir nesne üzerinden sinyal göndermesini beklemelidir. Bu, değiştirme zinciriyle işlenen ilk çerçeveyi içerir. WaitForSingleObjectExkullanarak, 2. Adımda elde edilen bekleme tutamacını sağlayın ve her kareyi başlatmak için sinyal verin.
Aşağıdaki örnekte DirectXLatency örneğinden işleme döngüsü gösterilmektedir:
while (!m_windowClosed)
{
if (m_windowVisible)
{
// Block this thread until the swap chain is finished presenting. Note that it is
// important to call this before the first Present in order to minimize the latency
// of the swap chain.
m_deviceResources->WaitOnSwapChain();
// Process any UI events in the queue.
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
// Update app state in response to any UI events that occurred.
m_main->Update();
// Render the scene.
m_main->Render();
// Present the scene.
m_deviceResources->Present();
}
else
{
// The window is hidden. Block until a UI event occurs.
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
}
}
Aşağıdaki örnekte DirectXLatency örneğinden WaitForSingleObjectEx çağrısı gösterilmektedir:
// Block the current thread until the swap chain has finished presenting.
void DX::DeviceResources::WaitOnSwapChain()
{
DWORD result = WaitForSingleObjectEx(
m_frameLatencyWaitableObject,
1000, // 1 second timeout (shouldn't ever occur)
true
);
}
Takas zincirinin sunulmasını beklerken oyunum ne yapmalı?
Oyununuzun işleme döngüsünü engelleyen herhangi bir görevi yoksa, takas zincirinin sunulması için bekletmek avantajlı olabilir çünkü güç tasarrufu sağlar, bu da özellikle mobil cihazlarda önemlidir. Aksi takdirde, oyununuz takas zincirinin sunumunu beklerken işleri gerçekleştirmek için çoklu iş parçacığı kullanabilirsiniz. Oyununuzun tamamlayabildiği birkaç görev şunlardır:
- Ağ olaylarını işleme
- Yapay zekayı güncelleştirme
- CPU tabanlı fizik
- Ertelenmiş bağlam işleme (desteklenen cihazlarda)
- Varlık yükleme
Windows'ta çok iş parçacıklı programlama hakkında daha fazla bilgi için aşağıdaki ilgili konulara bakın.