From 07aa906753eab0e96f0be4f754b44fef24295835 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 10 Jun 2022 21:35:15 +0900 Subject: [PATCH] internal/graphicsdriver/directx: fix GetCPU/GPUDescriptorHandleForHeapStart for Xbox Updates #2084 --- .../graphicsdriver/directx/api_windows.go | 44 ++++++++++++++++--- .../directx/graphics_windows.go | 30 ++++++++++--- .../directx/pipeline_windows.go | 27 +++++++++--- 3 files changed, 84 insertions(+), 17 deletions(-) diff --git a/internal/graphicsdriver/directx/api_windows.go b/internal/graphicsdriver/directx/api_windows.go index b5237b091..e9b3e9d87 100644 --- a/internal/graphicsdriver/directx/api_windows.go +++ b/internal/graphicsdriver/directx/api_windows.go @@ -1250,19 +1250,51 @@ type _ID3D12DescriptrHeap_Vtbl struct { GetGPUDescriptorHandleForHeapStart uintptr } -func (i *_ID3D12DescriptorHeap) GetCPUDescriptorHandleForHeapStart() _D3D12_CPU_DESCRIPTOR_HANDLE { +func (i *_ID3D12DescriptorHeap) GetCPUDescriptorHandleForHeapStart() (_D3D12_CPU_DESCRIPTOR_HANDLE, error) { + if microsoftgdk.IsXbox() { + r, _, e := syscall.Syscall(i.vtbl.GetCPUDescriptorHandleForHeapStart, 1, uintptr(unsafe.Pointer(i)), 0, 0) + if r == 0 { + return _D3D12_CPU_DESCRIPTOR_HANDLE{}, fmt.Errorf("directx: ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart failed: %w", e) + } + return _D3D12_CPU_DESCRIPTOR_HANDLE{ + ptr: r, + }, nil + } + // There is a bug in the header file: // https://stackoverflow.com/questions/34118929/getcpudescriptorhandleforheapstart-stack-corruption var handle _D3D12_CPU_DESCRIPTOR_HANDLE - syscall.Syscall(i.vtbl.GetCPUDescriptorHandleForHeapStart, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&handle)), 0) - return handle + _, _, e := syscall.Syscall(i.vtbl.GetCPUDescriptorHandleForHeapStart, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&handle)), 0) + if handle.ptr == 0 { + return _D3D12_CPU_DESCRIPTOR_HANDLE{}, fmt.Errorf("directx: ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart failed: %w", e) + } + return handle, nil } -func (i *_ID3D12DescriptorHeap) GetGPUDescriptorHandleForHeapStart() _D3D12_GPU_DESCRIPTOR_HANDLE { +func (i *_ID3D12DescriptorHeap) GetGPUDescriptorHandleForHeapStart() (_D3D12_GPU_DESCRIPTOR_HANDLE, error) { + if microsoftgdk.IsXbox() { + r1, r2, e := syscall.Syscall(i.vtbl.GetGPUDescriptorHandleForHeapStart, 1, uintptr(unsafe.Pointer(i)), 0, 0) + var ptr uint64 + if unsafe.Sizeof(uintptr(0)) == 4 { + ptr = uint64(r1) | uint64(r2)<<32 + } else { + ptr = uint64(r1) + } + if ptr == 0 { + return _D3D12_GPU_DESCRIPTOR_HANDLE{}, fmt.Errorf("directx: ID3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart failed: %w", e) + } + return _D3D12_GPU_DESCRIPTOR_HANDLE{ + ptr: ptr, + }, nil + } + // This has the same issue as GetCPUDescriptorHandleForHeapStart. var handle _D3D12_GPU_DESCRIPTOR_HANDLE - syscall.Syscall(i.vtbl.GetGPUDescriptorHandleForHeapStart, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&handle)), 0) - return handle + _, _, e := syscall.Syscall(i.vtbl.GetGPUDescriptorHandleForHeapStart, 2, uintptr(unsafe.Pointer(i)), uintptr(unsafe.Pointer(&handle)), 0) + if handle.ptr == 0 { + return _D3D12_GPU_DESCRIPTOR_HANDLE{}, fmt.Errorf("directx: ID3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart failed: %w", e) + } + return handle, nil } func (i *_ID3D12DescriptorHeap) Release() { diff --git a/internal/graphicsdriver/directx/graphics_windows.go b/internal/graphicsdriver/directx/graphics_windows.go index 60e387301..41a1bd0d4 100644 --- a/internal/graphicsdriver/directx/graphics_windows.go +++ b/internal/graphicsdriver/directx/graphics_windows.go @@ -571,7 +571,10 @@ func (g *Graphics) resizeSwapChain(width, height int) error { func (g *Graphics) createRenderTargetViews() (ferr error) { // Create frame resources. - h := g.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + h, err := g.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } for i := 0; i < frameCount; i++ { r, err := g.swapChain.GetBuffer(uint32(i)) if err != nil { @@ -1474,19 +1477,28 @@ func (i *Image) setAsRenderTarget(device *_ID3D12Device, useStencil bool) error } if i.screen { - rtv := i.graphics.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + rtv, err := i.graphics.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } rtv.Offset(int32(i.graphics.frameIndex), i.graphics.rtvDescriptorSize) i.graphics.drawCommandList.OMSetRenderTargets(1, &rtv, false, nil) return nil } - rtv := i.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + rtv, err := i.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } var dsv *_D3D12_CPU_DESCRIPTOR_HANDLE if useStencil { if err := i.ensureDepthStencilView(device); err != nil { return err } - v := i.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + v, err := i.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } dsv = &v i.graphics.drawCommandList.ClearDepthStencilView(v, _D3D12_CLEAR_FLAG_STENCIL, 0, 0, 0, nil) @@ -1517,7 +1529,10 @@ func (i *Image) ensureRenderTargetView(device *_ID3D12Device) error { } i.rtvDescriptorHeap = h - rtv := i.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + rtv, err := i.rtvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } device.CreateRenderTargetView(i.texture, nil, rtv) return nil @@ -1543,7 +1558,10 @@ func (i *Image) ensureDepthStencilView(device *_ID3D12Device) error { } i.dsvDescriptorHeap = h - dsv := i.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + dsv, err := i.dsvDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } if i.stencil == nil { s, err := device.CreateCommittedResource(&_D3D12_HEAP_PROPERTIES{ Type: _D3D12_HEAP_TYPE_DEFAULT, diff --git a/internal/graphicsdriver/directx/pipeline_windows.go b/internal/graphicsdriver/directx/pipeline_windows.go index e0947bfb2..9bf070e86 100644 --- a/internal/graphicsdriver/directx/pipeline_windows.go +++ b/internal/graphicsdriver/directx/pipeline_windows.go @@ -312,6 +312,10 @@ func (p *pipelineStates) initialize(device *_ID3D12Device) (ferr error) { } p.samplerDescriptorHeap = samplerH + h, err := p.samplerDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } device.CreateSampler(&_D3D12_SAMPLER_DESC{ Filter: _D3D12_FILTER_MIN_MAG_MIP_POINT, AddressU: _D3D12_TEXTURE_ADDRESS_MODE_WRAP, @@ -320,7 +324,7 @@ func (p *pipelineStates) initialize(device *_ID3D12Device) (ferr error) { ComparisonFunc: _D3D12_COMPARISON_FUNC_NEVER, MinLOD: -math.MaxFloat32, MaxLOD: math.MaxFloat32, - }, p.samplerDescriptorHeap.GetCPUDescriptorHandleForHeapStart()) + }, h) return nil } @@ -388,7 +392,10 @@ func (p *pipelineStates) useGraphicsPipelineState(device *_ID3D12Device, command } p.constantBuffers[frameIndex][idx] = cb - h := p.shaderDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + h, err := p.shaderDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } h.Offset(int32(frameIndex*numDescriptorsPerFrame+numConstantBufferAndSourceTextures*idx), p.shaderDescriptorSize) device.CreateConstantBufferView(&_D3D12_CONSTANT_BUFFER_VIEW_DESC{ BufferLocation: cb.GetGPUVirtualAddress(), @@ -396,7 +403,10 @@ func (p *pipelineStates) useGraphicsPipelineState(device *_ID3D12Device, command }, h) } - h := p.shaderDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + h, err := p.shaderDescriptorHeap.GetCPUDescriptorHandleForHeapStart() + if err != nil { + return err + } h.Offset(int32(frameIndex*numDescriptorsPerFrame+numConstantBufferAndSourceTextures*idx), p.shaderDescriptorSize) for _, src := range srcs { h.Offset(1, p.shaderDescriptorSize) @@ -436,12 +446,19 @@ func (p *pipelineStates) useGraphicsPipelineState(device *_ID3D12Device, command }) // Match the indices with rootParams in graphicsPipelineState. - gh := p.shaderDescriptorHeap.GetGPUDescriptorHandleForHeapStart() + gh, err := p.shaderDescriptorHeap.GetGPUDescriptorHandleForHeapStart() + if err != nil { + return err + } gh.Offset(int32(frameIndex*numDescriptorsPerFrame+numConstantBufferAndSourceTextures*idx), p.shaderDescriptorSize) commandList.SetGraphicsRootDescriptorTable(0, gh) gh.Offset(1, p.shaderDescriptorSize) commandList.SetGraphicsRootDescriptorTable(1, gh) - commandList.SetGraphicsRootDescriptorTable(2, p.samplerDescriptorHeap.GetGPUDescriptorHandleForHeapStart()) + sh, err := p.samplerDescriptorHeap.GetGPUDescriptorHandleForHeapStart() + if err != nil { + return err + } + commandList.SetGraphicsRootDescriptorTable(2, sh) return nil }