Skip to content

Commit

Permalink
internal/graphicsdriver/directx: initialize a device for Xbox
Browse files Browse the repository at this point in the history
Updates #1162
  • Loading branch information
hajimehoshi committed May 29, 2022
1 parent 59798d2 commit d422665
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 13 deletions.
93 changes: 81 additions & 12 deletions internal/graphicsdriver/directx/api_windows.go
Expand Up @@ -19,12 +19,17 @@ import (
"math"
"reflect"
"runtime"
"sync"
"syscall"
"unsafe"

"golang.org/x/sys/windows"
)

type (
_BOOL int32
)

func boolToUintptr(v bool) uintptr {
if v {
return 1
Expand All @@ -49,6 +54,10 @@ const (
_D3D12_MIN_DEPTH = 0.0
_D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION = 16384
_D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES = 0xffffffff
_D3D12_SDK_VERSION = (_D3D12_SDK_VERSION_MAJOR << 16) | _D3D12_SDK_VERSION_MINOR
_D3D12_SDK_VERSION_MAJOR = 2
_D3D12_SDK_VERSION_MINOR = 4
_D3D12XBOX_DEFAULT_SIZE_BYTES = 0xffffffff
)

type _D3D_FEATURE_LEVEL int32
Expand Down Expand Up @@ -471,6 +480,21 @@ const (
_D3D12_TEXTURE_LAYOUT_64KB_STANDARD_SWIZZLE _D3D12_TEXTURE_LAYOUT = 3
)

type _D3D12XBOX_CREATE_DEVICE_FLAGS int32

type _D3D12XBOX_PROCESS_DEBUG_FLAGS int32

const (
_D3D12XBOX_PROCESS_DEBUG_FLAG_NONE _D3D12XBOX_PROCESS_DEBUG_FLAGS = 0x0
_D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG _D3D12XBOX_PROCESS_DEBUG_FLAGS = 0x00000001
_D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED _D3D12XBOX_PROCESS_DEBUG_FLAGS = _D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG
_D3D12XBOX_PROCESS_DEBUG_FLAG_INSTRUMENTED _D3D12XBOX_PROCESS_DEBUG_FLAGS = 0x00100000
_D3D12XBOX_PROCESS_DEBUG_FLAG_VALIDATED _D3D12XBOX_PROCESS_DEBUG_FLAGS = _D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG
_D3D12XBOX_PROCESS_DEBUG_FLAG_NULL_GPU _D3D12XBOX_PROCESS_DEBUG_FLAGS = 0x00400000
_D3D12XBOX_PROCESS_DEBUG_FLAG_ENABLE_COMMON_STATE_PROMOTION _D3D12XBOX_PROCESS_DEBUG_FLAGS = 0x01000000
_D3D12XBOX_PROCESS_DEBUG_FLAG_ENHANCED_VALIDATION _D3D12XBOX_PROCESS_DEBUG_FLAGS = 0x02000000
)

type _DXGI_ALPHA_MODE uint32

const (
Expand Down Expand Up @@ -537,8 +561,8 @@ var (
)

type _D3D12_BLEND_DESC struct {
AlphaToCoverageEnable int32
IndependentBlendEnable int32
AlphaToCoverageEnable _BOOL
IndependentBlendEnable _BOOL
RenderTarget [8]_D3D12_RENDER_TARGET_BLEND_DESC
}

Expand Down Expand Up @@ -584,10 +608,10 @@ type _D3D12_DEPTH_STENCIL_VIEW_DESC struct {
}

type _D3D12_DEPTH_STENCIL_DESC struct {
DepthEnable int32
DepthEnable _BOOL
DepthWriteMask _D3D12_DEPTH_WRITE_MASK
DepthFunc _D3D12_COMPARISON_FUNC
StencilEnable int32
StencilEnable _BOOL
StencilReadMask uint8
StencilWriteMask uint8
FrontFace _D3D12_DEPTH_STENCILOP_DESC
Expand Down Expand Up @@ -680,13 +704,13 @@ type _D3D12_RANGE struct {
type _D3D12_RASTERIZER_DESC struct {
FillMode _D3D12_FILL_MODE
CullMode _D3D12_CULL_MODE
FrontCounterClockwise int32
FrontCounterClockwise _BOOL
DepthBias int32
DepthBiasClamp float32
SlopeScaledDepthBias float32
DepthClipEnable int32
MultisampleEnable int32
AntialiasedLineEnable int32
DepthClipEnable _BOOL
MultisampleEnable _BOOL
AntialiasedLineEnable _BOOL
ForcedSampleCount uint32
ConservativeRaster _D3D12_CONSERVATIVE_RASTERIZATION_MODE
}
Expand Down Expand Up @@ -829,15 +853,52 @@ type _D3D12_VIEWPORT struct {
MaxDepth float32
}

type _D3D12XBOX_CREATE_DEVICE_PARAMETERS struct {
Version uint32
ProcessDebugFlags _D3D12XBOX_PROCESS_DEBUG_FLAGS
GraphicsCommandQueueRingSizeBytes uint32
pOffchipTessellationBuffer _D3D12_GPU_VIRTUAL_ADDRESS
GraphicsScratchMemorySizeBytes uint32
ComputeScratchMemorySizeBytes uint32
DisableGeometryShaderAllocations _BOOL
DisableTessellationShaderAllocations _BOOL

// These members are for Xbox Series.
DisableDXR _BOOL
DisableAutomaticDPBBBreakBatchEvents _BOOL
pDXRStackBuffer _D3D12_GPU_VIRTUAL_ADDRESS
DXRStackBufferOverrideSizeBytes uint32
CreateDeviceFlags _D3D12XBOX_CREATE_DEVICE_FLAGS
AutoHDRPaperWhiteLevelNits uint32
DisableAutomaticCommandSegmentChaining _BOOL
}

var (
d3d12 = windows.NewLazySystemDLL("d3d12.dll")
d3dcompiler = windows.NewLazySystemDLL("d3dcompiler_47.dll")
dxgi = windows.NewLazySystemDLL("dxgi.dll")

d3d12xDLL *windows.LazyDLL
d3d12xOnce sync.Once
)

func d3d12x() *windows.LazyDLL {
d3d12xOnce.Do(func() {
d3d12xDLL = windows.NewLazySystemDLL("d3d12_xs.dll")
if d3d12xDLL.Load() != nil {
d3d12xDLL = windows.NewLazySystemDLL("d3d12_x.dll")
}
})
return d3d12xDLL
}

var (
procD3D12CreateDevice = d3d12.NewProc("D3D12CreateDevice")
procD3D12GetDebugInterface = d3d12.NewProc("D3D12GetDebugInterface")
procD3D12SerializeRootSignature = d3d12.NewProc("D3D12SerializeRootSignature")

procD3D12XboxCreateDevice = d3d12x().NewProc("D3D12XboxCreateDevice")

procD3DCompile = d3dcompiler.NewProc("D3DCompile")

procCreateDXGIFactory2 = dxgi.NewProc("CreateDXGIFactory2")
Expand Down Expand Up @@ -877,6 +938,14 @@ func _D3D12SerializeRootSignature(pRootSignature *_D3D12_ROOT_SIGNATURE_DESC, ve
return blob, nil
}

func _D3D12XboxCreateDevice(pAdapter unsafe.Pointer, pParameters *_D3D12XBOX_CREATE_DEVICE_PARAMETERS, riid *windows.GUID, ppDevice *unsafe.Pointer) error {
r, _, _ := procD3D12XboxCreateDevice.Call(uintptr(pAdapter), uintptr(unsafe.Pointer(pParameters)), uintptr(unsafe.Pointer(riid)), uintptr(unsafe.Pointer(ppDevice)))
if windows.Handle(r) != windows.S_OK {
return fmt.Errorf("directx: D3D12XboxCreateDevice failed: %w", windows.Errno(r))
}
return nil
}

func _D3DCompile(srcData []byte, sourceName string, pDefines []_D3D_SHADER_MACRO, pInclude unsafe.Pointer, entryPoint string, target string, flags1 uint32, flags2 uint32) (*_ID3DBlob, error) {
// TODO: Define _ID3DInclude for pInclude, but is it possible in Go?

Expand Down Expand Up @@ -943,8 +1012,8 @@ type _D3D12_PLACED_SUBRESOURCE_FOOTPRINT struct {
}

type _D3D12_RENDER_TARGET_BLEND_DESC struct {
BlendEnable int32
LogicOpEnable int32
BlendEnable _BOOL
LogicOpEnable _BOOL
SrcBlend _D3D12_BLEND
DestBlend _D3D12_BLEND
BlendOp _D3D12_BLEND_OP
Expand Down Expand Up @@ -999,7 +1068,7 @@ type _DXGI_SWAP_CHAIN_FULLSCREEN_DESC struct {
RefreshRate _DXGI_RATIONAL
ScanlineOrdering _DXGI_MODE_SCANLINE_ORDER
Scaling _DXGI_MODE_SCALING
Windowed int32
Windowed _BOOL
}

type _DXGI_RATIONAL struct {
Expand All @@ -1016,7 +1085,7 @@ type _DXGI_SWAP_CHAIN_DESC1 struct {
Width uint32
Height uint32
Format _DXGI_FORMAT
Stereo int32
Stereo _BOOL
SampleDesc _DXGI_SAMPLE_DESC
BufferUsage _DXGI_USAGE
BufferCount uint32
Expand Down
38 changes: 37 additions & 1 deletion internal/graphicsdriver/directx/graphics_windows.go
Expand Up @@ -27,14 +27,15 @@ import (

"github.com/hajimehoshi/ebiten/v2/internal/graphics"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/microsoftgdk"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
"github.com/hajimehoshi/ebiten/v2/internal/shaderir/hlsl"
)

const frameCount = 2

// isDirectXAvailable indicates whether DirectX is available or not.
var (
// isDirectXAvailable indicates whether DirectX is available or not.
isDirectXAvailable bool
isDirectXAvailableOnce sync.Once
)
Expand Down Expand Up @@ -159,12 +160,26 @@ func (g *Graphics) initializeDevice() (ferr error) {
for _, t := range strings.Split(os.Getenv("EBITEN_DIRECTX"), ",") {
switch strings.TrimSpace(t) {
case "warp":
// TODO: Is WARP available on Xbox?
useWARP = true
case "debug":
useDebugLayer = true
}
}

if microsoftgdk.IsXbox() {
if err := g.initializeDeviceXbox(useWARP, useDebugLayer); err != nil {
return err
}
} else {
if err := g.initializeDeviceDesktop(useWARP, useDebugLayer); err != nil {
return err
}
}
return nil
}

func (g *Graphics) initializeDeviceDesktop(useWARP bool, useDebugLayer bool) (ferr error) {
if err := d3d12.Load(); err != nil {
return err
}
Expand Down Expand Up @@ -261,6 +276,27 @@ func (g *Graphics) initializeDevice() (ferr error) {
return nil
}

func (g *Graphics) initializeDeviceXbox(useWARP bool, useDebugLayer bool) (ferr error) {
if err := d3d12x().Load(); err != nil {
return err
}

params := &_D3D12XBOX_CREATE_DEVICE_PARAMETERS{
Version: _D3D12_SDK_VERSION, // TODO: Can we always use the same value?
GraphicsCommandQueueRingSizeBytes: _D3D12XBOX_DEFAULT_SIZE_BYTES,
GraphicsScratchMemorySizeBytes: _D3D12XBOX_DEFAULT_SIZE_BYTES,
ComputeScratchMemorySizeBytes: _D3D12XBOX_DEFAULT_SIZE_BYTES,
}
if useDebugLayer {
params.ProcessDebugFlags = _D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED
}
if err := _D3D12XboxCreateDevice(nil, params, &_IID_ID3D12Device, (*unsafe.Pointer)(unsafe.Pointer(&g.device))); err != nil {
return err
}

return nil
}

func (g *Graphics) Initialize() (ferr error) {
// Create an event for a fence.
e, err := windows.CreateEvent(nil, 0, 0, nil)
Expand Down

1 comment on commit d422665

@hajimehoshi
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for #2084, not #1162

Please sign in to comment.