diff --git a/libs/directx/dx/Dx12.hx b/libs/directx/dx/Dx12.hx index 2a7d7971a..6cda0f57f 100644 --- a/libs/directx/dx/Dx12.hx +++ b/libs/directx/dx/Dx12.hx @@ -350,6 +350,7 @@ enum abstract ResourceState(Int) { public var VIDE_PROCESS_WRITE = 0x80000; public var VIDE_ENCODE_READ = 0x200000; public var VIDE_ENCODE_WRITE = 0x800000; + @:op(a|b) function or(r:ResourceState):ResourceState; } @:struct class Color { @@ -1195,38 +1196,6 @@ enum ResourceFlag { } } -enum abstract ResourceStates(Int) { - var COMMON = 0; - var VERTEX_AND_CONSTANT_BUFFER = 0x1; - var INDEX_BUFFER = 0x2; - var RENDER_TARGET = 0x4; - var UNORDERED_ACCESS = 0x8; - var DEPTH_WRITE = 0x10; - var DEPTH_READ = 0x20; - var NON_PIXEL_SHADER_RESOURCE = 0x40; - var PIXEL_SHADER_RESOURCE = 0x80; - var STREAM_OUT = 0x100; - var INDIRECT_ARGUMENT = 0x200; - var COPY_DEST = 0x400; - var COPY_SOURCE = 0x800; - var RESOLVE_DEST = 0x1000; - var RESOLVE_SOURCE = 0x2000; - var RAYTRACING_ACCELERATION_STRUCTURE = 0x400000; - var SHADING_RATE_SOURCE = 0x1000000; - var GENERIC_READ = ( ( ( ( ( 0x1 | 0x2 ) | 0x40 ) | 0x80 ) | 0x200 ) | 0x800 ) ; - var ALL_SHADER_RESOURCE = ( 0x40 | 0x80 ) ; - var PRESENT = 0; - var PREDICATION = 0x200; - var VIDEO_DECODE_READ = 0x10000; - var VIDEO_DECODE_WRITE = 0x20000; - var VIDEO_PROCESS_READ = 0x40000; - var VIDEO_PROCESS_WRITE = 0x80000; - var VIDEO_ENCODE_READ = 0x200000; - var VIDEO_ENCODE_WRITE = 0x800000; - @:op(a|b) function or(r:ResourceStates):ResourceStates; -} - - enum abstract SrvDimension(Int) { var UNKNOWN = 0; var BUFFER = 1; @@ -1527,7 +1496,7 @@ class Dx12 { public static function createSampler( desc : SamplerDesc, target : Address ) { } - public static function createCommittedResource( heapProperties : HeapProperties, heapFlags : haxe.EnumFlags, desc : ResourceDesc, initialState : ResourceStates, clearValue : ClearValue ) : GpuResource { + public static function createCommittedResource( heapProperties : HeapProperties, heapFlags : haxe.EnumFlags, desc : ResourceDesc, initialState : ResourceState, clearValue : ClearValue ) : GpuResource { return null; } @@ -1548,6 +1517,12 @@ class Dx12 { public static function present( vsync : Bool ) { } + public static function suspend() { + } + + public static function resume() { + } + public static function getDeviceName() { return @:privateAccess String.fromUCS2(dxGetDeviceName()); } diff --git a/libs/directx/dx12.cpp b/libs/directx/dx12.cpp index cd324d1ad..69327df80 100644 --- a/libs/directx/dx12.cpp +++ b/libs/directx/dx12.cpp @@ -8,19 +8,48 @@ #include #endif +#ifdef HL_XBS +#ifdef _GAMING_XBOX_SCARLETT +#include +#include +#include +#else +#include +#include +#include +#endif + +#define IID_PPV_ARGS_OLD(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType) +#undef IID_PPV_ARGS +#define IID_PPV_ARGS IID_GRAPHICS_PPV_ARGS +#endif + #define DXERR(cmd) { HRESULT __ret = cmd; if( __ret == E_OUTOFMEMORY ) return NULL; if( __ret != S_OK ) ReportDxError(__ret,__LINE__); } #define CHKERR(cmd) { HRESULT __ret = cmd; if( __ret != S_OK ) ReportDxError(__ret,__LINE__); } typedef struct { HWND wnd; + ID3D12CommandQueue *commandQueue; +#ifndef HL_XBS IDXGIFactory4 *factory; IDXGIAdapter1 *adapter; IDXGISwapChain4 *swapchain; ID3D12Device *device; - ID3D12CommandQueue *commandQueue; ID3D12Debug1 *debug; - ID3D12DebugDevice *debugDevice; + ID3D12DebugDevice *debugDevice; ID3D12InfoQueue *infoQueue; +#else + ID3D12Device2 *device; + ID3D12Debug *debug; + ID3D12DebugDevice *debugDevice; + // SwapChain + UINT swapBufferCount; + UINT backBufferIndex; + ID3D12Resource **swapBuffers; + D3D12XBOX_FRAME_PIPELINE_TOKEN pipelineToken; + // Cached values + IDXGIAdapter *adapter; +#endif } dx_driver; static dx_driver *static_driver = NULL; @@ -44,6 +73,7 @@ void *pContext ) { } HL_PRIM varray *HL_NAME(list_devices)() { +#ifndef HL_XBS static int MAX_DEVICES = 64; int index = 0, write = 0; IDXGIAdapter1 *adapter = NULL; @@ -64,24 +94,38 @@ HL_PRIM varray *HL_NAME(list_devices)() { if( !static_driver ) factory->Release(); return arr; +#else + varray *arr = hl_alloc_array(&hlt_bytes, 1); + DXGI_ADAPTER_DESC desc; + static_driver->adapter->GetDesc(&desc); + hl_aptr(arr, uchar*)[0] = ustrdup(desc.Description); + return arr; +#endif } HL_PRIM dx_driver *HL_NAME(create)( HWND window, int flags, uchar *dev_desc ) { UINT dxgiFlags = 0; dx_driver *drv = (dx_driver*)hl_gc_alloc_raw(sizeof(dx_driver)); - memset(drv,0,sizeof(dx_driver)); + memset(drv, 0, sizeof(dx_driver)); drv->wnd = window; if( flags & 1 ) { ID3D12Debug *debugController; D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)); + debugController->EnableDebugLayer(); +#ifndef HL_XBS debugController->QueryInterface(&drv->debug); drv->debug->EnableDebugLayer(); drv->debug->SetEnableGPUBasedValidation(true); dxgiFlags |= DXGI_CREATE_FACTORY_DEBUG; +#else + debugController->QueryInterface(IID_PPV_ARGS(&drv->debug)); +#endif debugController->Release(); } + +#ifndef HL_XBS CHKERR(CreateDXGIFactory2(dxgiFlags, IID_PPV_ARGS(&drv->factory))); UINT index = 0; @@ -107,6 +151,42 @@ HL_PRIM dx_driver *HL_NAME(create)( HWND window, int flags, uchar *dev_desc ) { CHKERR(drv->device->QueryInterface(IID_PPV_ARGS(&drv->infoQueue))); drv->infoQueue->ClearStoredMessages(); } +#else + D3D12XBOX_CREATE_DEVICE_PARAMETERS params = {}; + params.Version = D3D12_SDK_VERSION; +#if defined(_DEBUG) + params.ProcessDebugFlags = D3D12_PROCESS_DEBUG_FLAG_DEBUG_LAYER_ENABLED; +#endif + params.GraphicsCommandQueueRingSizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.GraphicsScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.ComputeScratchMemorySizeBytes = static_cast(D3D12XBOX_DEFAULT_SIZE_BYTES); + params.DisableGeometryShaderAllocations = TRUE; + params.DisableTessellationShaderAllocations = TRUE; +#ifdef _GAMING_XBOX_SCARLETT + params.DisableDXR = TRUE; + params.CreateDeviceFlags = D3D12XBOX_CREATE_DEVICE_FLAG_NONE; +#endif + + CHKERR(D3D12XboxCreateDevice(nullptr,¶ms, IID_PPV_ARGS(&drv->device))) + drv->device->SetName(L"HL_DX12_XBS"); + if (drv->debug) { + CHKERR(drv->device->QueryInterface(IID_PPV_ARGS(&drv->debugDevice))); + } + + // Prepare for PresentX + { + IDXGIDevice1 *dxgiDevice; + CHKERR(drv->device->QueryInterface(IID_PPV_ARGS(&dxgiDevice))); + IDXGIAdapter *dxgiAdapter; + CHKERR(dxgiDevice->GetAdapter(&dxgiAdapter)); + DXGI_ADAPTER_DESC desc; + dxgiAdapter->GetDesc(&desc); + if (dev_desc) { + wcsstr(desc.Description, dev_desc); + } + drv->adapter = dxgiAdapter; + } +#endif { D3D12_COMMAND_QUEUE_DESC desc = {}; @@ -114,15 +194,47 @@ HL_PRIM dx_driver *HL_NAME(create)( HWND window, int flags, uchar *dev_desc ) { desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; desc.NodeMask = CURRENT_NODEMASK; - CHKERR(drv->device->CreateCommandQueue(&desc,IID_PPV_ARGS(&drv->commandQueue))); + CHKERR(drv->device->CreateCommandQueue(&desc, IID_PPV_ARGS(&drv->commandQueue))); } static_driver = drv; return drv; } +#ifdef HL_XBS +void register_frame_events() { + dx_driver *drv = static_driver; + // Prepare PresentX + IDXGIOutput *dxgiOutput; + CHKERR(drv->adapter->EnumOutputs(0, &dxgiOutput)); + // May return S_OK, S_FALSE + HRESULT hr = drv->device->SetFrameIntervalX(dxgiOutput, D3D12XBOX_FRAME_INTERVAL_60_HZ, drv->swapBufferCount - 1u /* Allow n-1 frames of latency */, D3D12XBOX_FRAME_INTERVAL_FLAG_NONE); + if (hr < 0) ReportDxError(hr, __LINE__); + CHKERR(drv->device->ScheduleFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, 0U, nullptr, D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE)); + + // Prepare first pipeline token + drv->pipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + CHKERR(drv->device->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &drv->pipelineToken)); +} +#endif + +HL_PRIM void HL_NAME(suspend)() { +#ifdef HL_XBS + // Must be called from the render thread + CHKERR(static_driver->commandQueue->SuspendX(0)); +#endif +} + +HL_PRIM void HL_NAME(resume)() { +#ifdef HL_XBS + CHKERR(static_driver->commandQueue->ResumeX()); + register_frame_events(); +#endif +} + HL_PRIM void HL_NAME(resize)( int width, int height, int buffer_count, DXGI_FORMAT format ) { dx_driver *drv = static_driver; +#ifndef HL_XBS if( drv->swapchain ) { CHKERR(drv->swapchain->ResizeBuffers(buffer_count, width, height, format, 0)); } else { @@ -140,17 +252,59 @@ HL_PRIM void HL_NAME(resize)( int width, int height, int buffer_count, DXGI_FORM if( !swapchain ) CHKERR(E_INVALIDARG); swapchain->QueryInterface(IID_PPV_ARGS(&drv->swapchain)); } +#else + if (drv->swapBuffers) { + free(drv->swapBuffers); + } + + // Create swap buffers + CD3DX12_HEAP_PROPERTIES swapChainHeapProperties(D3D12_HEAP_TYPE_DEFAULT); + D3D12_RESOURCE_DESC swapChainBufferDesc = CD3DX12_RESOURCE_DESC::Tex2D(format, width, height, + 1, // This resource has only one texture. + 1 // Use a single mipmap level. + ); + swapChainBufferDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + D3D12_CLEAR_VALUE swapChainOptimizedClearValue = {}; + swapChainOptimizedClearValue.Format = format; + drv->swapBuffers = (ID3D12Resource**) malloc(sizeof(ID3D12Resource*) * buffer_count); + if (drv->swapBuffers == nullptr) + hl_error("malloc drv->swapBuffers failed"); + drv->swapBufferCount = buffer_count; + drv->backBufferIndex = 0; + for (int n = 0; n < buffer_count; n++) + { + drv->device->CreateCommittedResource(&swapChainHeapProperties, D3D12_HEAP_FLAG_ALLOW_DISPLAY, &swapChainBufferDesc, D3D12_RESOURCE_STATE_PRESENT, &swapChainOptimizedClearValue, IID_PPV_ARGS(&drv->swapBuffers[n])); + } + + register_frame_events(); +#endif } HL_PRIM void HL_NAME(present)( bool vsync ) { dx_driver *drv = static_driver; +#ifndef HL_XBS UINT syncInterval = vsync ? 1 : 0; UINT presentFlags = 0; CHKERR(drv->swapchain->Present(syncInterval, presentFlags)); +#else + D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParameters = {}; + planeParameters.Token = drv->pipelineToken; + planeParameters.ResourceCount = 1; + planeParameters.ppResources = &drv->swapBuffers[drv->backBufferIndex]; + CHKERR(drv->commandQueue->PresentX(1, &planeParameters, nullptr)); + drv->backBufferIndex = (drv->backBufferIndex + 1) % drv->swapBufferCount; + // Prepare next pipeline token + drv->pipelineToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL; + CHKERR(drv->device->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, nullptr, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &drv->pipelineToken)); +#endif } int HL_NAME(get_current_back_buffer_index)() { +#ifndef HL_XBS return static_driver->swapchain->GetCurrentBackBufferIndex(); +#else + return static_driver->backBufferIndex; +#endif } void HL_NAME(signal)( ID3D12Fence *fence, int64 value ) { @@ -158,6 +312,7 @@ void HL_NAME(signal)( ID3D12Fence *fence, int64 value ) { } void HL_NAME(flush_messages)() { +#ifndef HL_XBS dx_driver *drv = static_driver; if( !drv->infoQueue ) return; int count = (int)drv->infoQueue->GetNumStoredMessages(); @@ -174,10 +329,12 @@ void HL_NAME(flush_messages)() { fflush(stdout); } drv->infoQueue->ClearStoredMessages(); +#endif } uchar *HL_NAME(get_device_name)() { DXGI_ADAPTER_DESC desc; +#ifndef HL_XBS IDXGIAdapter *adapter = NULL; if( !static_driver ) { IDXGIFactory4 *factory = NULL; @@ -188,7 +345,10 @@ uchar *HL_NAME(get_device_name)() { } else adapter = static_driver->adapter; adapter->GetDesc(&desc); - return (uchar*)hl_copy_bytes((vbyte*)desc.Description,(int)(ustrlen((uchar*)desc.Description)+1)*2); +#else + static_driver->adapter->GetDesc(&desc); +#endif + return (uchar*)hl_copy_bytes((vbyte*)desc.Description, (int)(ustrlen((uchar*)desc.Description) + 1) * 2); } int64 HL_NAME(get_timestamp_frequency)() { @@ -204,6 +364,8 @@ DEFINE_PRIM(_ARR, list_devices, _NO_ARG); DEFINE_PRIM(_DRIVER, create, _ABSTRACT(dx_window) _I32 _BYTES); DEFINE_PRIM(_VOID, resize, _I32 _I32 _I32 _I32); DEFINE_PRIM(_VOID, present, _BOOL); +DEFINE_PRIM(_VOID, suspend, _NO_ARG); +DEFINE_PRIM(_VOID, resume, _NO_ARG); DEFINE_PRIM(_I32, get_current_back_buffer_index, _NO_ARG); DEFINE_PRIM(_VOID, signal, _RES _I64); DEFINE_PRIM(_VOID, flush_messages, _NO_ARG); @@ -212,151 +374,162 @@ DEFINE_PRIM(_I64, get_timestamp_frequency, _NO_ARG); /// --- utilities (from d3dx12.h) +#ifndef HL_XBS struct CD3DX12_TEXTURE_COPY_LOCATION : public D3D12_TEXTURE_COPY_LOCATION { - CD3DX12_TEXTURE_COPY_LOCATION() = default; - explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) noexcept : - D3D12_TEXTURE_COPY_LOCATION(o) - {} - CD3DX12_TEXTURE_COPY_LOCATION(_In_ ID3D12Resource* pRes) noexcept - { - pResource = pRes; - Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - PlacedFootprint = {}; - } - CD3DX12_TEXTURE_COPY_LOCATION(_In_ ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint) noexcept - { - pResource = pRes; - Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - PlacedFootprint = Footprint; - } - CD3DX12_TEXTURE_COPY_LOCATION(_In_ ID3D12Resource* pRes, UINT Sub) noexcept - { - pResource = pRes; - Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - PlacedFootprint = {}; - SubresourceIndex = Sub; - } + CD3DX12_TEXTURE_COPY_LOCATION() = default; + explicit CD3DX12_TEXTURE_COPY_LOCATION(const D3D12_TEXTURE_COPY_LOCATION &o) noexcept : + D3D12_TEXTURE_COPY_LOCATION(o) + {} + CD3DX12_TEXTURE_COPY_LOCATION(_In_ ID3D12Resource* pRes) noexcept + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + PlacedFootprint = {}; + } + CD3DX12_TEXTURE_COPY_LOCATION(_In_ ID3D12Resource* pRes, D3D12_PLACED_SUBRESOURCE_FOOTPRINT const& Footprint) noexcept + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + PlacedFootprint = Footprint; + } + CD3DX12_TEXTURE_COPY_LOCATION(_In_ ID3D12Resource* pRes, UINT Sub) noexcept + { + pResource = pRes; + Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + PlacedFootprint = {}; + SubresourceIndex = Sub; + } }; inline void MemcpySubresource( - _In_ const D3D12_MEMCPY_DEST* pDest, - _In_ const D3D12_SUBRESOURCE_DATA* pSrc, - SIZE_T RowSizeInBytes, - UINT NumRows, - UINT NumSlices) noexcept + _In_ const D3D12_MEMCPY_DEST* pDest, + _In_ const D3D12_SUBRESOURCE_DATA* pSrc, + SIZE_T RowSizeInBytes, + UINT NumRows, + UINT NumSlices) noexcept { - for (UINT z = 0; z < NumSlices; ++z) - { - auto pDestSlice = static_cast(pDest->pData) + pDest->SlicePitch * z; - auto pSrcSlice = static_cast(pSrc->pData) + pSrc->SlicePitch * LONG_PTR(z); - for (UINT y = 0; y < NumRows; ++y) - { - memcpy(pDestSlice + pDest->RowPitch * y, - pSrcSlice + pSrc->RowPitch * LONG_PTR(y), - RowSizeInBytes); - } - } + for (UINT z = 0; z < NumSlices; ++z) + { + auto pDestSlice = static_cast(pDest->pData) + pDest->SlicePitch * z; + auto pSrcSlice = static_cast(pSrc->pData) + pSrc->SlicePitch * LONG_PTR(z); + for (UINT y = 0; y < NumRows; ++y) + { + memcpy(pDestSlice + pDest->RowPitch * y, + pSrcSlice + pSrc->RowPitch * LONG_PTR(y), + RowSizeInBytes); + } + } } inline UINT64 UpdateSubresources( - _In_ ID3D12GraphicsCommandList* pCmdList, - _In_ ID3D12Resource* pDestinationResource, - _In_ ID3D12Resource* pIntermediate, - _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, - _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, - UINT64 RequiredSize, - _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, - _In_reads_(NumSubresources) const UINT* pNumRows, - _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, - _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + UINT64 RequiredSize, + _In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts, + _In_reads_(NumSubresources) const UINT* pNumRows, + _In_reads_(NumSubresources) const UINT64* pRowSizesInBytes, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept { - // Minor validation - auto IntermediateDesc = pIntermediate->GetDesc(); - auto DestinationDesc = pDestinationResource->GetDesc(); - if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || - IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || - RequiredSize > SIZE_T(-1) || - (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && - (FirstSubresource != 0 || NumSubresources != 1))) - { - return 0; - } - - BYTE* pData; - HRESULT hr = pIntermediate->Map(0, nullptr, reinterpret_cast(&pData)); - if (FAILED(hr)) - { - return 0; - } - - for (UINT i = 0; i < NumSubresources; ++i) - { - if (pRowSizesInBytes[i] > SIZE_T(-1)) return 0; - D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, SIZE_T(pLayouts[i].Footprint.RowPitch) * SIZE_T(pNumRows[i]) }; - MemcpySubresource(&DestData, &pSrcData[i], static_cast(pRowSizesInBytes[i]), pNumRows[i], pLayouts[i].Footprint.Depth); - } - pIntermediate->Unmap(0, nullptr); - - if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) - { - pCmdList->CopyBufferRegion( - pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); - } - else - { - for (UINT i = 0; i < NumSubresources; ++i) - { - CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); - CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); - pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); - } - } - return RequiredSize; + // Minor validation + auto IntermediateDesc = pIntermediate->GetDesc(); + auto DestinationDesc = pDestinationResource->GetDesc(); + if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER || + IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset || + RequiredSize > SIZE_T(-1) || + (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + (FirstSubresource != 0 || NumSubresources != 1))) + { + return 0; + } + + BYTE* pData; + HRESULT hr = pIntermediate->Map(0, nullptr, reinterpret_cast(&pData)); + if (FAILED(hr)) + { + return 0; + } + + for (UINT i = 0; i < NumSubresources; ++i) + { + if (pRowSizesInBytes[i] > SIZE_T(-1)) return 0; + D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, SIZE_T(pLayouts[i].Footprint.RowPitch) * SIZE_T(pNumRows[i]) }; + MemcpySubresource(&DestData, &pSrcData[i], static_cast(pRowSizesInBytes[i]), pNumRows[i], pLayouts[i].Footprint.Depth); + } + pIntermediate->Unmap(0, nullptr); + + if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + pCmdList->CopyBufferRegion( + pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width); + } + else + { + for (UINT i = 0; i < NumSubresources; ++i) + { + CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource); + CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]); + pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr); + } + } + return RequiredSize; } inline UINT64 UpdateSubresources( - _In_ ID3D12GraphicsCommandList* pCmdList, - _In_ ID3D12Resource* pDestinationResource, - _In_ ID3D12Resource* pIntermediate, - UINT64 IntermediateOffset, - _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, - _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, - _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept + _In_ ID3D12GraphicsCommandList* pCmdList, + _In_ ID3D12Resource* pDestinationResource, + _In_ ID3D12Resource* pIntermediate, + UINT64 IntermediateOffset, + _In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource, + _In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources, + _In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept { - UINT64 RequiredSize = 0; - auto MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; - if (MemToAlloc > SIZE_MAX) - { - return 0; - } - void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); - if (pMem == nullptr) - { - return 0; - } - auto pLayouts = static_cast(pMem); - auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); - auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); - - auto Desc = pDestinationResource->GetDesc(); - static_driver->device->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); - - UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); - HeapFree(GetProcessHeap(), 0, pMem); - return Result; + UINT64 RequiredSize = 0; + auto MemToAlloc = static_cast(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources; + if (MemToAlloc > SIZE_MAX) + { + return 0; + } + void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast(MemToAlloc)); + if (pMem == nullptr) + { + return 0; + } + auto pLayouts = static_cast(pMem); + auto pRowSizesInBytes = reinterpret_cast(pLayouts + NumSubresources); + auto pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); + + auto Desc = pDestinationResource->GetDesc(); + static_driver->device->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); + + UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData); + HeapFree(GetProcessHeap(), 0, pMem); + return Result; } +#endif + // ---- RESOURCES ID3D12Resource *HL_NAME(get_back_buffer)( int index ) { ID3D12Resource *buf = NULL; +#ifndef HL_XBS static_driver->swapchain->GetBuffer(index, IID_PPV_ARGS(&buf)); +#else + buf = static_driver->swapBuffers[index]; +#endif return buf; } ID3D12Resource *HL_NAME(create_committed_resource)( D3D12_HEAP_PROPERTIES *heapProperties, D3D12_HEAP_FLAGS heapFlags, D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initialState, D3D12_CLEAR_VALUE *clearValue ) { ID3D12Resource *res = NULL; +#ifdef HL_XBS + // In normal dx, INDIRECT_ARGUMENT is included in GENERIC_READ (but we never use it alone) , so we remove it to obtain GENERIC_READ in xbox + initialState = (D3D12_RESOURCE_STATES)(initialState & ~D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT); +#endif DXERR(static_driver->device->CreateCommittedResource(heapProperties, heapFlags, desc, initialState, clearValue, IID_PPV_ARGS(&res))); return res; } @@ -404,10 +577,15 @@ void HL_NAME(resource_unmap)( ID3D12Resource *res, int subres, D3D12_RANGE *rang } int64 HL_NAME(get_required_intermediate_size)( ID3D12Resource *res, int first, int count ) { - auto desc = res->GetDesc(); - UINT64 size = 0; - static_driver->device->GetCopyableFootprints(&desc, first, count, 0, NULL, NULL, NULL, &size); - return size; + auto desc = res->GetDesc(); + UINT64 size = 0; + static_driver->device->GetCopyableFootprints(&desc, first, count, 0, NULL, NULL, NULL, &size); +#ifdef HL_XBS + D3D12_PLACED_SUBRESOURCE_FOOTPRINT pLayouts; + static_driver->device->GetCopyableFootprints(&desc, first, 1, 0, &pLayouts, NULL, NULL, NULL); + size += pLayouts.Offset; +#endif + return size; } bool HL_NAME(update_sub_resource)( ID3D12GraphicsCommandList *cmd, ID3D12Resource *res, ID3D12Resource *tmp, int64 tmpOffs, int first, int count, D3D12_SUBRESOURCE_DATA *data ) { @@ -415,7 +593,7 @@ bool HL_NAME(update_sub_resource)( ID3D12GraphicsCommandList *cmd, ID3D12Resourc } void HL_NAME(get_copyable_footprints)( D3D12_RESOURCE_DESC *desc, int first, int count, int64 offset, D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts, int *numRows, int64 *rowSizes, int64 *totalBytes ) { - static_driver->device->GetCopyableFootprints(desc, first, count, offset, layouts, (UINT*)numRows, (UINT64*)rowSizes, (UINT64*)totalBytes); + static_driver->device->GetCopyableFootprints(desc, first, count, offset, layouts, (UINT*)numRows, (UINT64*)rowSizes, (UINT64*)totalBytes); } DEFINE_PRIM(_VOID, create_render_target_view, _RES _STRUCT _I64); @@ -437,25 +615,49 @@ DEFINE_PRIM(_VOID, get_copyable_footprints, _STRUCT _I32 _I32 _I64 _STRUCT _BYTE // ---- SHADERS typedef struct { +#ifndef HL_XBS IDxcLibrary *library; IDxcCompiler *compiler; +#else + IDxcUtils *utils; + IDxcCompiler3 *compiler; +#endif } dx_compiler; dx_compiler *HL_NAME(compiler_create)() { dx_compiler *comp = (dx_compiler*)hl_gc_alloc_raw(sizeof(dx_compiler)); memset(comp,0,sizeof(dx_compiler)); +#ifndef HL_XBS CHKERR(DxcCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&comp->library))); CHKERR(DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&comp->compiler))); +#else + CHKERR(DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS_OLD(&comp->utils))); + CHKERR(DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS_OLD(&comp->compiler))); +#endif return comp; } vbyte *HL_NAME(compiler_compile)( dx_compiler *comp, uchar *source, uchar *profile, varray *args, int *dataLen ) { IDxcBlobEncoding *blob = NULL; IDxcOperationResult *result = NULL; +#ifndef HL_XBS comp->library->CreateBlobWithEncodingFromPinned(source,(int)ustrlen(source)*2,1200/*DXC_CP_UTF16*/,&blob); +#else + comp->utils->CreateBlobFromPinned(source, (int)ustrlen(source) * 2, 1200/*DXC_CP_UTF16*/, &blob); +#endif if( blob == NULL ) hl_error("Could not create blob"); +#ifndef HL_XBS comp->compiler->Compile(blob,L"",L"main",profile,hl_aptr(args,LPCWSTR),args->size,NULL,0,NULL,&result); +#else + BOOL knownEncoding = FALSE; + UINT32 encoding = 0U; + blob->GetEncoding(&knownEncoding, &encoding); + DxcBuffer dxcBuffer = { blob->GetBufferPointer(), blob->GetBufferSize(), encoding }; + std::vector arguments(hl_aptr(args, LPCWSTR), hl_aptr(args, LPCWSTR) + args->size); + arguments.insert(arguments.end(), { L"-E", L"main", L"-T", profile, L"-D", L"__XBOX_DISABLE_PRECOMPILE" }); + CHKERR(comp->compiler->Compile(&dxcBuffer, arguments.data(), arguments.size(), NULL, IID_PPV_ARGS_OLD(&result))); +#endif HRESULT hr; result->GetStatus(&hr); if( !SUCCEEDED(hr) ) { diff --git a/src/hl.h b/src/hl.h index b6291ae99..74f366331 100644 --- a/src/hl.h +++ b/src/hl.h @@ -31,7 +31,7 @@ #if defined(_WIN32) # define HL_WIN -# ifndef _DURANGO +# if !defined(_DURANGO) && !defined(_GAMING_XBOX) # define HL_WIN_DESKTOP # endif #endif @@ -74,7 +74,11 @@ # define HL_XBO #endif -#if defined(HL_PS) || defined(HL_NX) || defined(HL_XBO) +#ifdef _GAMING_XBOX +# define HL_XBS +#endif + +#if defined(HL_PS) || defined(HL_NX) || defined(HL_XBO) || defined(HL_XBS) # define HL_CONSOLE #endif @@ -220,7 +224,7 @@ typedef unsigned long long uint64; // -------------- UNICODE ----------------------------------- #if defined(HL_WIN) && !defined(HL_LLVM) -#if defined(HL_WIN_DESKTOP) && !defined(HL_MINGW) +#if (defined(HL_WIN_DESKTOP) && !defined(HL_MINGW)) || defined(HL_XBS) # include #elif defined(HL_WIN_DESKTOP) && defined(HL_MINGW) # include diff --git a/src/jit.c b/src/jit.c index 000918fc3..1a187d60e 100644 --- a/src/jit.c +++ b/src/jit.c @@ -1629,7 +1629,7 @@ static void on_jit_error( const char *msg, int_val line ) { char buf[256]; int iline = (int)line; sprintf(buf,"%s (line %d)",msg,iline); -#ifdef HL_WIN +#ifdef HL_WIN_DESKTOP MessageBoxA(NULL,buf,"JIT ERROR",MB_OK); #else printf("JIT ERROR : %s\n",buf); diff --git a/src/profile.c b/src/profile.c index 5cca25d61..d9ab9fd14 100644 --- a/src/profile.c +++ b/src/profile.c @@ -63,7 +63,7 @@ typedef struct _profile_data profile_data; struct _thread_handle { int tid; -# ifdef HL_WIN_DESKTOP +# ifdef HL_WIN HANDLE h; # endif hl_thread_info *inf; diff --git a/src/std/file.c b/src/std/file.c index a117294e0..2e057d008 100644 --- a/src/std/file.c +++ b/src/std/file.c @@ -33,7 +33,7 @@ # include # include # include -#else +#elif HL_XBO # include #endif # define fopen(name,mode) _wfopen(name,mode) diff --git a/src/std/sys.c b/src/std/sys.c index f52d41f8a..e971fcf03 100644 --- a/src/std/sys.c +++ b/src/std/sys.c @@ -148,7 +148,7 @@ HL_PRIM int hl_sys_set_flags( int flags ) { HL_PRIM void hl_sys_print( vbyte *msg ) { hl_blocking(true); -# ifdef HL_XBO +# if defined(HL_XBO) || defined(HL_XBS) OutputDebugStringW((LPCWSTR)msg); # else # ifdef HL_WIN_DESKTOP