internal/graphicsdriver/directx: implement swap chains for Xbox

Updates #2084
This commit is contained in:
Hajime Hoshi 2022-06-17 18:57:52 +09:00
parent a641f9ede0
commit 7e92b79a00
2 changed files with 439 additions and 70 deletions

View File

@ -41,7 +41,6 @@ func boolToUintptr(v bool) uintptr {
// Reference:
// * https://github.com/microsoft/DirectX-Headers
// * https://github.com/microsoft/win32metadata
// * https://raw.githubusercontent.com/microsoft/win32metadata/master/generation/WinSDK/RecompiledIdlHeaders/um/d3d12.h
const (
_D3D12_APPEND_ALIGNED_ELEMENT = 0xffffffff
@ -258,7 +257,8 @@ const (
type _D3D12_HEAP_FLAGS int32
const (
_D3D12_HEAP_FLAG_NONE _D3D12_HEAP_FLAGS = 0
_D3D12_HEAP_FLAG_NONE _D3D12_HEAP_FLAGS = 0
_D3D12_HEAP_FLAG_ALLOW_DISPLAY _D3D12_HEAP_FLAGS = 0x8
)
type _D3D12_HEAP_TYPE int32
@ -413,6 +413,10 @@ const (
type _D3D12_RTV_DIMENSION int32
const (
_D3D12_RTV_DIMENSION_TEXTURE2D _D3D12_RTV_DIMENSION = 4
)
const (
_D3D12_SHADER_COMPONENT_MAPPING_MASK = 0x7
_D3D12_SHADER_COMPONENT_MAPPING_SHIFT = 3
@ -502,6 +506,36 @@ const (
type _D3D12XBOX_CREATE_DEVICE_FLAGS int32
type _D3D12XBOX_FRAME_EVENT_TYPE int32
const (
_D3D12XBOX_FRAME_EVENT_ORIGIN _D3D12XBOX_FRAME_EVENT_TYPE = 0
)
type _D3D12XBOX_FRAME_INTERVAL_FLAGS int32
const (
_D3D12XBOX_FRAME_INTERVAL_FLAG_NONE _D3D12XBOX_FRAME_INTERVAL_FLAGS = 0x0
)
type _D3D12XBOX_FRAME_PIPELINE_TOKEN uint64
const (
_D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL _D3D12XBOX_FRAME_PIPELINE_TOKEN = 0
)
type _D3D12XBOX_PRESENT_DESC_TITLE_PERFORMANCE_OVERLAY_FLAGS int32
type _D3D12XBOX_PRESENT_DESC_TYPE int32
type _D3D12XBOX_PRESENT_FLAGS int32
type _D3D12XBOX_PRESENT_PLANE_FLAGS int32
type _D3D12XBOX_PRESENT_PLANE_SCALE_FILTER int32
type _D3D12XBOX_PRESENT_PLANE_DESC_TYPE int32
type _D3D12XBOX_PROCESS_DEBUG_FLAGS int32
const (
@ -515,6 +549,22 @@ const (
_D3D12XBOX_PROCESS_DEBUG_FLAG_ENHANCED_VALIDATION _D3D12XBOX_PROCESS_DEBUG_FLAGS = 0x02000000
)
type _D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAGS int32
const (
_D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE _D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAGS = 0x0
)
type _D3D12XBOX_WAIT_FRAME_EVENT_FLAGS int32
const (
_D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE _D3D12XBOX_WAIT_FRAME_EVENT_FLAGS = 0x0
)
const (
_D3D12XBOX_FRAME_INTERVAL_60_HZ = 16667
)
type _DXGI_ALPHA_MODE uint32
const (
@ -525,6 +575,8 @@ const (
_DXGI_ALPHA_MODE_FORCE_DWORD _DXGI_ALPHA_MODE = 0xffffffff
)
type _DXGI_COLOR_SPACE_TYPE int32
type _DXGI_FORMAT int32
const (
@ -580,6 +632,7 @@ var (
_IID_ID3D12RootSignature = windows.GUID{Data1: 0xc54a6b66, Data2: 0x72df, Data3: 0x4ee8, Data4: [...]byte{0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14}}
_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: 0x99cdbe06, Data2: 0xc52d, Data3: 0xa562, Data4: [...]byte{0x8d, 0x0a, 0xc4, 0x2f, 0xe3, 0x33, 0xf9, 0x47}}
_IID_IDXGIFactory4 = windows.GUID{Data1: 0x1bc6ea02, Data2: 0xef36, Data3: 0x464f, Data4: [...]byte{0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a}}
)
@ -896,6 +949,62 @@ type _D3D12XBOX_CREATE_DEVICE_PARAMETERS struct {
DisableAutomaticCommandSegmentChaining _BOOL
}
type _D3D12XBOX_PRESENT_DESC_TITLE_PERFORMANCE_OVERLAY struct {
Flags _D3D12XBOX_PRESENT_DESC_TITLE_PERFORMANCE_OVERLAY_FLAGS
RenderResolutionWidth uint16
RenderResolutionHeight uint16
MaxResolutionWidth uint16
MaxResolutionHeight uint16
}
type _D3D12XBOX_PRESENT_PARAMETERS struct {
ImmediateThresholdPercent float32
ViewCount uint32
ExtendedDescCount uint32
pExtendedDescs *_D3D12XBOX_PRESENT_DESC
Flags _D3D12XBOX_PRESENT_FLAGS
}
type _D3D12XBOX_PRESENT_DESC struct {
Type _D3D12XBOX_PRESENT_DESC_TYPE
TitlePerfOverlay _D3D12XBOX_PRESENT_DESC_TITLE_PERFORMANCE_OVERLAY
}
type _D3D12XBOX_PRESENT_PLANE_DESC struct {
Type _D3D12XBOX_PRESENT_PLANE_DESC_TYPE
}
type _D3D12XBOX_PRESENT_PLANE_PARAMETERS struct {
Token _D3D12XBOX_FRAME_PIPELINE_TOKEN
ResourceCount uint32
ppResources **_ID3D12Resource
pSrcViewRects *_D3D12_RECT
pDestPlacementBase *_D3D12XBOX_VIEW_RECT
ColorSpace _DXGI_COLOR_SPACE_TYPE
ScaleFilter _D3D12XBOX_PRESENT_PLANE_SCALE_FILTER
ExtendedDescCount uint32
pExtendedDescs *_D3D12XBOX_PRESENT_PLANE_DESC
Flags _D3D12XBOX_PRESENT_PLANE_FLAGS
}
type _D3D12XBOX_SCHEDULE_FRAME_OBJECT_LIST struct {
Count uint32
pObjects *windows.Handle
}
type _D3D12XBOX_VIEW_RECT struct {
left float32
top float32
right float32
bottom float32
}
type _D3D12XBOX_WAIT_FRAME_OBJECT_LIST struct {
Count uint32
pObjects *windows.Handle
pSignaledObjectIndex *uint32
}
var (
d3d12 = windows.NewLazySystemDLL("d3d12.dll")
d3d12x = windows.NewLazySystemDLL(microsoftgdk.D3D12DLLName())
@ -1169,7 +1278,23 @@ type _ID3D12CommandQueue_Vtbl struct {
Wait uintptr
GetTimestampFrequency uintptr
GetClockCalibration uintptr
GetDesc uintptr
GetDesc uintptr // Is this another function for Xbox?
// These members are for Xbox.
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr // Is this GetDesc for Xbox?
_ uintptr
_ uintptr
_ uintptr
PresentX uintptr
_ uintptr
_ uintptr
}
func (i *_ID3D12CommandQueue) ExecuteCommandLists(ppCommandLists []*_ID3D12GraphicsCommandList) {
@ -1178,6 +1303,16 @@ func (i *_ID3D12CommandQueue) ExecuteCommandLists(ppCommandLists []*_ID3D12Graph
runtime.KeepAlive(ppCommandLists)
}
func (i *_ID3D12CommandQueue) PresentX(planeCount uint32, pPlaneParameters *_D3D12XBOX_PRESENT_PLANE_PARAMETERS, pPresentParameters *_D3D12XBOX_PRESENT_PARAMETERS) error {
r, _, _ := syscall.Syscall6(i.vtbl.PresentX, 4, uintptr(unsafe.Pointer(i)), uintptr(planeCount), uintptr(unsafe.Pointer(pPlaneParameters)), uintptr(unsafe.Pointer(pPresentParameters)), 0, 0)
runtime.KeepAlive(pPlaneParameters)
runtime.KeepAlive(pPresentParameters)
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("directx: ID3D12CommandQueue::PresentX failed: HRESULT(%d)", uint32(r))
}
return nil
}
func (i *_ID3D12CommandQueue) Signal(signal *_ID3D12Fence, value uint64) error {
r, _, _ := syscall.Syscall(i.vtbl.Signal, 3, uintptr(unsafe.Pointer(i)),
uintptr(unsafe.Pointer(signal)), uintptr(value))
@ -1379,45 +1514,49 @@ type _ID3D12Device_Vtbl struct {
GetAdapterLuid uintptr
// These members are for Xbox.
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
CreateCommandList_Xbox uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
CreateCommandListX uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
SetFrameIntervalX uintptr
ScheduleFrameEventX uintptr
WaitFrameEventX uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
_ uintptr
}
func (i *_ID3D12Device) CreateCommandAllocator(typ _D3D12_COMMAND_LIST_TYPE) (*_ID3D12CommandAllocator, error) {
@ -1446,7 +1585,7 @@ func (i *_ID3D12Device) CreateCommandList(nodeMask uint32, typ _D3D12_COMMAND_LI
Member3: nodeMask,
Member4: 0,
}
r, _, _ = syscall.Syscall6(i.vtbl.CreateCommandList_Xbox, 6,
r, _, _ = syscall.Syscall6(i.vtbl.CreateCommandListX, 6,
uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&desc)), uintptr(unsafe.Pointer(pCommandAllocator)),
uintptr(unsafe.Pointer(pInitialState)), uintptr(unsafe.Pointer(&_IID_ID3D12GraphicsCommandList)), uintptr(unsafe.Pointer(&commandList)))
} else {
@ -1596,6 +1735,42 @@ func (i *_ID3D12Device) GetDeviceRemovedReason() error {
return nil
}
func (i *_ID3D12Device) ScheduleFrameEventX(typ _D3D12XBOX_FRAME_EVENT_TYPE, intervalOffsetInMicroseconds uint32, pAncillarySignalList *_D3D12XBOX_SCHEDULE_FRAME_OBJECT_LIST, flags _D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAGS) error {
r, _, _ := syscall.Syscall6(i.vtbl.ScheduleFrameEventX, 5, uintptr(unsafe.Pointer(i)), uintptr(typ), uintptr(intervalOffsetInMicroseconds), uintptr(unsafe.Pointer(pAncillarySignalList)), uintptr(flags), 0)
runtime.KeepAlive(pAncillarySignalList)
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("directx: ID3D12Device::ScheduleFrameEventX failed: HRESULT(%d)", uint32(r))
}
return nil
}
func (i *_ID3D12Device) SetFrameIntervalX(pOutputSyncTarget *_IDXGIOutput, lengthInMicroseconds uint32, periodInIntervals uint32, flags _D3D12XBOX_FRAME_INTERVAL_FLAGS) error {
r, _, _ := syscall.Syscall6(i.vtbl.SetFrameIntervalX, 5, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(pOutputSyncTarget)), uintptr(lengthInMicroseconds), uintptr(periodInIntervals), uintptr(flags), 0)
runtime.KeepAlive(pOutputSyncTarget)
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("directx: ID3D12Device::SetFrameIntervalX failed: HRESULT(%d)", uint32(r))
}
return nil
}
func (i *_ID3D12Device) 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)))
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("directx: ID3D12Device::QueryInterface failed: HRESULT(%d)", uint32(r))
}
return nil
}
func (i *_ID3D12Device) WaitFrameEventX(typ _D3D12XBOX_FRAME_EVENT_TYPE, timeOutInMs uint32, pAncillaryWaitList *_D3D12XBOX_WAIT_FRAME_OBJECT_LIST, flags _D3D12XBOX_WAIT_FRAME_EVENT_FLAGS, pToken *_D3D12XBOX_FRAME_PIPELINE_TOKEN) error {
r, _, _ := syscall.Syscall6(i.vtbl.WaitFrameEventX, 6, uintptr(unsafe.Pointer(i)), uintptr(typ), uintptr(timeOutInMs), uintptr(unsafe.Pointer(pAncillaryWaitList)), uintptr(flags), uintptr(unsafe.Pointer(pToken)))
runtime.KeepAlive(pAncillaryWaitList)
runtime.KeepAlive(pToken)
if uint32(r) != uint32(windows.S_OK) {
return fmt.Errorf("directx: ID3D12Device::WaitFrameEventX failed: HRESULT(%d)", uint32(r))
}
return nil
}
type _ID3D12Fence struct {
vtbl *_ID3D12Fence_Vtbl
}
@ -2065,6 +2240,37 @@ func (i *_ID3DBlob) String() string {
return str
}
type _IDXGIAdapter struct {
vtbl *_IDXGIAdapter1_Vtbl
}
type _IDXGIAdapter_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
SetPrivateData uintptr
SetPrivateDataInterface uintptr
GetPrivateData uintptr
GetParent uintptr
EnumOutputs uintptr
GetDesc uintptr
CheckInterfaceSupport uintptr
}
func (i *_IDXGIAdapter) EnumOutputs(output uint32) (*_IDXGIOutput, error) {
var pOutput *_IDXGIOutput
r, _, _ := syscall.Syscall(i.vtbl.EnumOutputs, 3, uintptr(unsafe.Pointer(i)), uintptr(output), uintptr(unsafe.Pointer(&pOutput)))
if uint32(r) != uint32(windows.S_OK) {
return nil, fmt.Errorf("directx: IDXGIAdapter::EnumOutputs failed: HRESULT(%d)", uint32(r))
}
return pOutput, nil
}
func (i *_IDXGIAdapter) Release() {
syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
}
type _IDXGIAdapter1 struct {
vtbl *_IDXGIAdapter1_Vtbl
}
@ -2097,6 +2303,39 @@ func (i *_IDXGIAdapter1) GetDesc1() (*_DXGI_ADAPTER_DESC1, error) {
return &desc, nil
}
type _IDXGIDevice struct {
vtbl *_IDXGIDevice_Vtbl
}
type _IDXGIDevice_Vtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
SetPrivateData uintptr
SetPrivateDataInterface uintptr
GetPrivateData uintptr
GetParent uintptr
GetAdapter uintptr
CreateSurface uintptr
QueryResourceResidency uintptr
SetGPUThreadPriority uintptr
GetGPUThreadPriority uintptr
}
func (i *_IDXGIDevice) GetAdapter() (*_IDXGIAdapter, error) {
var adapter *_IDXGIAdapter
r, _, _ := syscall.Syscall(i.vtbl.GetAdapter, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&adapter)), 0)
if uint32(r) != uint32(windows.S_OK) {
return nil, fmt.Errorf("directx: IDXGIDevice::GetAdapter failed: HRESULT(%d)", uint32(r))
}
return adapter, nil
}
func (i *_IDXGIDevice) Release() {
syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
}
type _IDXGIFactory4 struct {
vtbl *_IDXGIFactory4_Vtbl
}
@ -2218,6 +2457,10 @@ type _IDXGIOutput_Vtbl struct {
GetFrameStatistics uintptr
}
func (i *_IDXGIOutput) Release() {
syscall.Syscall(i.vtbl.Release, 1, uintptr(unsafe.Pointer(i)), 0, 0)
}
type _ID3D12RootSignature struct {
vtbl *_ID3D12RootSignature_Vtbl
}

View File

@ -91,12 +91,13 @@ func init() {
}
type Graphics struct {
debug *_ID3D12Debug
device *_ID3D12Device
commandQueue *_ID3D12CommandQueue
rtvDescriptorHeap *_ID3D12DescriptorHeap
rtvDescriptorSize uint32
renderTargets [frameCount]*_ID3D12Resource
debug *_ID3D12Debug
device *_ID3D12Device
commandQueue *_ID3D12CommandQueue
rtvDescriptorHeap *_ID3D12DescriptorHeap
rtvDescriptorSize uint32
renderTargets [frameCount]*_ID3D12Resource
framePipelineToken _D3D12XBOX_FRAME_PIPELINE_TOKEN
fence *_ID3D12Fence
fenceValues [frameCount]uint64
@ -128,6 +129,9 @@ type Graphics struct {
frameIndex int
// frameStarted is true since Begin until End with present
frameStarted bool
images map[graphicsdriver.ImageID]*Image
screenImage *Image
nextImageID graphicsdriver.ImageID
@ -284,6 +288,31 @@ func (g *Graphics) initializeXbox(useWARP bool, useDebugLayer bool) (ferr error)
return err
}
var dxgiDevice *_IDXGIDevice
if err := g.device.QueryInterface(&_IID_IDXGIDevice, (*unsafe.Pointer)(unsafe.Pointer(dxgiDevice))); err != nil {
return err
}
defer dxgiDevice.Release()
dxgiAdapter, err := dxgiDevice.GetAdapter()
if err != nil {
return err
}
defer dxgiAdapter.Release()
dxgiOutput, err := dxgiAdapter.EnumOutputs(0)
if err != nil {
return err
}
defer dxgiOutput.Release()
if err := g.device.SetFrameIntervalX(dxgiOutput, _D3D12XBOX_FRAME_INTERVAL_60_HZ, frameCount-1, _D3D12XBOX_FRAME_INTERVAL_FLAG_NONE); err != nil {
return err
}
if err := g.device.ScheduleFrameEventX(_D3D12XBOX_FRAME_EVENT_ORIGIN, 0, nil, _D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE); err != nil {
return err
}
return nil
}
@ -456,19 +485,30 @@ func (g *Graphics) updateSwapChain(width, height int) error {
}
if g.swapChain == nil {
if err := g.initSwapChain(width, height); err != nil {
return err
}
} else {
if err := g.resizeSwapChain(width, height); err != nil {
return err
if microsoftgdk.IsXbox() {
if err := g.initSwapChainXbox(width, height); err != nil {
return err
}
} else {
if err := g.initSwapChainDesktop(width, height); err != nil {
return err
}
}
return nil
}
if microsoftgdk.IsXbox() {
return errors.New("directx: resizing should never happen on Xbox")
}
if err := g.resizeSwapChainDesktop(width, height); err != nil {
return err
}
return nil
}
func (g *Graphics) initSwapChain(width, height int) (ferr error) {
func (g *Graphics) initSwapChainDesktop(width, height int) (ferr error) {
// Create a swap chain.
//
// DXGI_ALPHA_MODE_PREMULTIPLIED doesn't work with a HWND well.
@ -506,7 +546,7 @@ func (g *Graphics) initSwapChain(width, height int) (ferr error) {
// TODO: Get the current buffer index?
if err := g.createRenderTargetViews(); err != nil {
if err := g.createRenderTargetViewsDesktop(); err != nil {
return err
}
@ -515,7 +555,59 @@ func (g *Graphics) initSwapChain(width, height int) (ferr error) {
return nil
}
func (g *Graphics) resizeSwapChain(width, height int) error {
func (g *Graphics) initSwapChainXbox(width, height int) (ferr error) {
h, err := g.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
if err != nil {
return err
}
for i := 0; i < frameCount; i++ {
r, err := g.device.CreateCommittedResource(&_D3D12_HEAP_PROPERTIES{
Type: _D3D12_HEAP_TYPE_DEFAULT,
CPUPageProperty: _D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: _D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
}, _D3D12_HEAP_FLAG_ALLOW_DISPLAY, &_D3D12_RESOURCE_DESC{
Dimension: _D3D12_RESOURCE_DIMENSION_TEXTURE2D,
Alignment: 0,
Width: uint64(width),
Height: uint32(height),
DepthOrArraySize: 1,
MipLevels: 1, // Use a single mipmap level
Format: _DXGI_FORMAT_B8G8R8A8_UNORM,
SampleDesc: _DXGI_SAMPLE_DESC{
Count: 1,
Quality: 0,
},
Layout: _D3D12_TEXTURE_LAYOUT_UNKNOWN,
Flags: _D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
}, _D3D12_RESOURCE_STATE_PRESENT, &_D3D12_CLEAR_VALUE{
Format: _DXGI_FORMAT_B8G8R8A8_UNORM,
})
if err != nil {
return err
}
g.renderTargets[i] = r
defer func(i int) {
if ferr != nil {
g.renderTargets[i].Release()
g.renderTargets[i] = nil
}
}(i)
g.device.CreateRenderTargetView(r, &_D3D12_RENDER_TARGET_VIEW_DESC{
Format: _DXGI_FORMAT_B8G8R8A8_UNORM,
ViewDimension: _D3D12_RTV_DIMENSION_TEXTURE2D,
}, h)
h.Offset(1, g.rtvDescriptorSize)
}
return nil
}
func (g *Graphics) resizeSwapChainDesktop(width, height int) error {
if err := g.flushCommandList(g.copyCommandList); err != nil {
return err
}
@ -549,7 +641,7 @@ func (g *Graphics) resizeSwapChain(width, height int) error {
return err
}
if err := g.createRenderTargetViews(); err != nil {
if err := g.createRenderTargetViewsDesktop(); err != nil {
return err
}
@ -566,7 +658,7 @@ func (g *Graphics) resizeSwapChain(width, height int) error {
return nil
}
func (g *Graphics) createRenderTargetViews() (ferr error) {
func (g *Graphics) createRenderTargetViewsDesktop() (ferr error) {
// Create frame resources.
h, err := g.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart()
if err != nil {
@ -598,6 +690,14 @@ func (g *Graphics) SetWindow(window uintptr) {
}
func (g *Graphics) Begin() error {
if microsoftgdk.IsXbox() && !g.frameStarted {
g.framePipelineToken = _D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL
if err := g.device.WaitFrameEventX(_D3D12XBOX_FRAME_EVENT_ORIGIN, windows.INFINITE, nil, _D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &g.framePipelineToken); err != nil {
return err
}
}
g.frameStarted = true
if err := g.drawCommandList.Reset(g.drawCommandAllocators[g.frameIndex], nil); err != nil {
return err
}
@ -640,16 +740,14 @@ func (g *Graphics) End(present bool) error {
g.pipelineStates.resetConstantBuffers(g.frameIndex)
if present {
if g.swapChain == nil {
return fmt.Errorf("directx: the swap chain is not initialized yet at End")
}
var syncInterval uint32
if g.vsyncEnabled {
syncInterval = 1
}
if err := g.swapChain.Present(syncInterval, 0); err != nil {
return err
if microsoftgdk.IsXbox() {
if err := g.presentXbox(); err != nil {
return err
}
} else {
if err := g.presentDesktop(); err != nil {
return err
}
}
if err := g.moveToNextFrame(); err != nil {
@ -661,7 +759,35 @@ func (g *Graphics) End(present bool) error {
if err := g.resetCommandAllocators(g.frameIndex); err != nil {
return err
}
g.frameStarted = false
}
return nil
}
func (g *Graphics) presentDesktop() error {
if g.swapChain == nil {
return fmt.Errorf("directx: the swap chain is not initialized yet at End")
}
var syncInterval uint32
if g.vsyncEnabled {
syncInterval = 1
}
if err := g.swapChain.Present(syncInterval, 0); err != nil {
return err
}
return nil
}
func (g *Graphics) presentXbox() error {
g.commandQueue.PresentX(1, &_D3D12XBOX_PRESENT_PLANE_PARAMETERS{
Token: g.framePipelineToken,
ResourceCount: 1,
ppResources: &g.renderTargets[g.frameIndex],
}, nil)
return nil
}