internal/graphicsdriver/directx: allow tearing when vsync is off

Updates #2034
Updates #2188
This commit is contained in:
Hajime Hoshi 2022-07-10 01:17:33 +09:00
parent a32a137fa8
commit 0035ba0bd1
2 changed files with 102 additions and 3 deletions

View File

@ -577,6 +577,12 @@ const (
type _DXGI_COLOR_SPACE_TYPE int32
type _DXGI_FEATURE int32
const (
_DXGI_FEATURE_PRESENT_ALLOW_TEARING _DXGI_FEATURE = 0
)
type _DXGI_FORMAT int32
const (
@ -593,8 +599,20 @@ type _DXGI_MODE_SCANLINE_ORDER int32
type _DXGI_MODE_SCALING int32
type _DXGI_PRESENT uint32
const (
_DXGI_PRESENT_ALLOW_TEARING _DXGI_PRESENT = 0x00000200
)
type _DXGI_SCALING int32
type _DXGI_SWAP_CHAIN_FLAG int32
const (
_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING _DXGI_SWAP_CHAIN_FLAG = 2048
)
type _DXGI_SWAP_EFFECT int32
const (
@ -634,6 +652,7 @@ var (
_IID_IDXGIAdapter1 = windows.GUID{Data1: 0x29038f61, Data2: 0x3839, Data3: 0x4626, Data4: [...]byte{0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a, 0x05}}
_IID_IDXGIDevice = windows.GUID{Data1: 0x54ec77fa, Data2: 0x1377, Data3: 0x44e6, Data4: [...]byte{0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c}}
_IID_IDXGIFactory4 = windows.GUID{Data1: 0x1bc6ea02, Data2: 0xef36, Data3: 0x464f, Data4: [...]byte{0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a}}
_IID_IDXGIFactory5 = windows.GUID{Data1: 0x7632e1f5, Data2: 0xee65, Data3: 0x4dca, Data4: [...]byte{0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d}}
)
type _D3D12_BLEND_DESC struct {
@ -2429,10 +2448,72 @@ func (i *_IDXGIFactory4) MakeWindowAssociation(windowHandle windows.HWND, flags
return nil
}
func (i *_IDXGIFactory4) QueryInterface(riid *windows.GUID, ppvObject *unsafe.Pointer) error {
r, _, _ := syscall.Syscall(i.vtbl.QueryInterface, 3, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(ppvObject)))
runtime.KeepAlive(riid)
runtime.KeepAlive(ppvObject)
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("directx: IDXGIFactory4::QueryInterface failed: HRESULT(%d)", uint32(r))
}
return nil
}
func (i *_IDXGIFactory4) Release() {
syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
}
type _IDXGIFactory5 struct {
vtbl *_IDXGIFactory5_Vtbl
}
type _IDXGIFactory5_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
SetPrivateData uintptr
SetPrivateDataInterface uintptr
GetPrivateData uintptr
GetParent uintptr
EnumAdapters uintptr
MakeWindowAssociation uintptr
GetWindowAssociation uintptr
CreateSwapChain uintptr
CreateSoftwareAdapter uintptr
EnumAdapters1 uintptr
IsCurrent uintptr
IsWindowedStereoEnabled uintptr
CreateSwapChainForHwnd uintptr
CreateSwapChainForCoreWindow uintptr
GetSharedResourceAdapterLuid uintptr
RegisterStereoStatusWindow uintptr
RegisterStereoStatusEvent uintptr
UnregisterStereoStatus uintptr
RegisterOcclusionStatusWindow uintptr
RegisterOcclusionStatusEvent uintptr
UnregisterOcclusionStatus uintptr
CreateSwapChainForComposition uintptr
GetCreationFlags uintptr
EnumAdapterByLuid uintptr
EnumWarpAdapter uintptr
CheckFeatureSupport uintptr
}
func (i *_IDXGIFactory5) CheckFeatureSupport(feature _DXGI_FEATURE, pFeatureSupportData unsafe.Pointer, featureSupportDataSize uint32) error {
r, _, _ := syscall.Syscall6(i.vtbl.CheckFeatureSupport, 4, uintptr(unsafe.Pointer(i)),
uintptr(feature), uintptr(pFeatureSupportData), uintptr(featureSupportDataSize),
0, 0)
runtime.KeepAlive(pFeatureSupportData)
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("directx: IDXGIFactory5::CheckFeatureSupport failed: HRESULT(%d)", uint32(r))
}
return nil
}
func (i *_IDXGIFactory5) Release() {
syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
}
type _IDXGIOutput struct {
vtbl *_IDXGIOutput_Vtbl
}

View File

@ -103,6 +103,8 @@ type Graphics struct {
fenceValues [frameCount]uint64
fenceWaitEvent windows.Handle
allowTearing bool
// drawCommandAllocators are command allocators for a 3D engine (DrawIndexedInstanced).
// For the word 'engine', see https://docs.microsoft.com/en-us/windows/win32/direct3d12/user-mode-heap-synchronization.
// The term 'draw' is used instead of '3D' in this package.
@ -268,6 +270,15 @@ func (g *Graphics) initializeDesktop(useWARP bool, useDebugLayer bool) (ferr err
return err
}
var factory *_IDXGIFactory5
if err := g.factory.QueryInterface(&_IID_IDXGIFactory5, (*unsafe.Pointer)(unsafe.Pointer(&factory))); err == nil && factory != nil {
defer factory.Release()
var allowTearing int32
if err := factory.CheckFeatureSupport(_DXGI_FEATURE_PRESENT_ALLOW_TEARING, unsafe.Pointer(&allowTearing), uint32(unsafe.Sizeof(allowTearing))); err == nil && allowTearing != 0 {
g.allowTearing = true
}
}
if err := g.initializeMembers(); err != nil {
return err
}
@ -524,7 +535,7 @@ func (g *Graphics) initSwapChainDesktop(width, height int) (ferr error) {
//
// IDXGIFactory::CreateSwapChain: Alpha blended swapchains must be created with CreateSwapChainForComposition,
// or CreateSwapChainForCoreWindow with the DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER flag
s, err := g.factory.CreateSwapChainForHwnd(unsafe.Pointer(g.commandQueue), g.window, &_DXGI_SWAP_CHAIN_DESC1{
desc := &_DXGI_SWAP_CHAIN_DESC1{
Width: uint32(width),
Height: uint32(height),
Format: _DXGI_FORMAT_B8G8R8A8_UNORM,
@ -535,7 +546,11 @@ func (g *Graphics) initSwapChainDesktop(width, height int) (ferr error) {
Count: 1,
Quality: 0,
},
}, nil, nil)
}
if g.allowTearing {
desc.Flags |= uint32(_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)
}
s, err := g.factory.CreateSwapChainForHwnd(unsafe.Pointer(g.commandQueue), g.window, desc, nil, nil)
if err != nil {
return err
}
@ -781,10 +796,13 @@ func (g *Graphics) presentDesktop() error {
}
var syncInterval uint32
var flags _DXGI_PRESENT
if g.vsyncEnabled {
syncInterval = 1
} else if g.allowTearing {
flags |= _DXGI_PRESENT_ALLOW_TEARING
}
if err := g.swapChain.Present(syncInterval, 0); err != nil {
if err := g.swapChain.Present(syncInterval, uint32(flags)); err != nil {
return err
}