// Copyright hdcmeta // Dual-Licensed under MIT and GPLv2+ // Refer to the license.txt file included. #include "VideoBackends/D3D12/D3DBase.h" #include "VideoBackends/D3D12/D3DQueuedCommandList.h" namespace DX12 { template constexpr size_t BufferOffsetForQueueItemType() { return sizeof(T) + sizeof(D3DQueueItemType) * 2; } void ID3D12QueuedCommandList::BackgroundThreadFunction(ID3D12QueuedCommandList* parent_queued_command_list) { ID3D12GraphicsCommandList* command_list = parent_queued_command_list->m_command_list; byte* queue_array = parent_queued_command_list->m_queue_array; unsigned int queue_array_front = 0; while (true) { WaitForSingleObject(parent_queued_command_list->m_begin_execution_event, INFINITE); byte* item = &queue_array[queue_array_front]; while (true) { switch (reinterpret_cast(item)->Type) { case D3DQueueItemType::ClearDepthStencilView: { command_list->ClearDepthStencilView(reinterpret_cast(item)->ClearDepthStencilView.DepthStencilView, D3D12_CLEAR_FLAG_DEPTH, 0.f, 0, 0, nullptr); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::ClearRenderTargetView: { float clearColor[4] = { 0.f, 0.f, 0.f, 1.f }; command_list->ClearRenderTargetView(reinterpret_cast(item)->ClearRenderTargetView.RenderTargetView, clearColor, 0, nullptr); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::CopyBufferRegion: { command_list->CopyBufferRegion( reinterpret_cast(item)->CopyBufferRegion.pDstBuffer, reinterpret_cast(item)->CopyBufferRegion.DstOffset, reinterpret_cast(item)->CopyBufferRegion.pSrcBuffer, reinterpret_cast(item)->CopyBufferRegion.SrcOffset, reinterpret_cast(item)->CopyBufferRegion.NumBytes ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::CopyTextureRegion: { // If box is completely empty, assume that the original API call has a NULL box (which means // copy from the entire resource. D3D12_BOX* src_box = &reinterpret_cast(item)->CopyTextureRegion.srcBox; // Front/Back never used, so don't need to check. bool empty_box = src_box->bottom == 0 && src_box->left == 0 && src_box->right == 0 && src_box->top == 0; command_list->CopyTextureRegion( &reinterpret_cast(item)->CopyTextureRegion.dst, reinterpret_cast(item)->CopyTextureRegion.DstX, reinterpret_cast(item)->CopyTextureRegion.DstY, reinterpret_cast(item)->CopyTextureRegion.DstZ, &reinterpret_cast(item)->CopyTextureRegion.src, empty_box ? nullptr : src_box ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::DrawIndexedInstanced: { command_list->DrawIndexedInstanced( reinterpret_cast(item)->DrawIndexedInstanced.IndexCount, 1, reinterpret_cast(item)->DrawIndexedInstanced.StartIndexLocation, reinterpret_cast(item)->DrawIndexedInstanced.BaseVertexLocation, 0 ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::DrawInstanced: { command_list->DrawInstanced( reinterpret_cast(item)->DrawInstanced.VertexCount, 1, reinterpret_cast(item)->DrawInstanced.StartVertexLocation, 0 ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::IASetPrimitiveTopology: { command_list->IASetPrimitiveTopology(reinterpret_cast(item)->IASetPrimitiveTopology.PrimitiveTopology); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::ResourceBarrier: { command_list->ResourceBarrier(1, &reinterpret_cast(item)->ResourceBarrier.barrier); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::RSSetScissorRects: { D3D12_RECT rect = { reinterpret_cast(item)->RSSetScissorRects.left, reinterpret_cast(item)->RSSetScissorRects.top, reinterpret_cast(item)->RSSetScissorRects.right, reinterpret_cast(item)->RSSetScissorRects.bottom }; command_list->RSSetScissorRects(1, &rect); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::RSSetViewports: { D3D12_VIEWPORT viewport = { reinterpret_cast(item)->RSSetViewports.TopLeftX, reinterpret_cast(item)->RSSetViewports.TopLeftY, reinterpret_cast(item)->RSSetViewports.Width, reinterpret_cast(item)->RSSetViewports.Height, reinterpret_cast(item)->RSSetViewports.MinDepth, reinterpret_cast(item)->RSSetViewports.MaxDepth }; command_list->RSSetViewports(1, &viewport); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetDescriptorHeaps: { command_list->SetDescriptorHeaps( reinterpret_cast(item)->SetDescriptorHeaps.NumDescriptorHeaps, reinterpret_cast(item)->SetDescriptorHeaps.ppDescriptorHeap ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetGraphicsRootConstantBufferView: { command_list->SetGraphicsRootConstantBufferView( reinterpret_cast(item)->SetGraphicsRootConstantBufferView.RootParameterIndex, reinterpret_cast(item)->SetGraphicsRootConstantBufferView.BufferLocation ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetGraphicsRootDescriptorTable: { command_list->SetGraphicsRootDescriptorTable( reinterpret_cast(item)->SetGraphicsRootDescriptorTable.RootParameterIndex, reinterpret_cast(item)->SetGraphicsRootDescriptorTable.BaseDescriptor ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetGraphicsRootSignature: { command_list->SetGraphicsRootSignature( reinterpret_cast(item)->SetGraphicsRootSignature.pRootSignature ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetIndexBuffer: { command_list->IASetIndexBuffer( &reinterpret_cast(item)->SetIndexBuffer.desc ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetVertexBuffers: { command_list->IASetVertexBuffers( 0, 1, &reinterpret_cast(item)->SetVertexBuffers.desc ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetPipelineState: { command_list->SetPipelineState(reinterpret_cast(item)->SetPipelineState.pPipelineStateObject); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::SetRenderTargets: { unsigned int render_target_count = 0; if (reinterpret_cast(item)->SetRenderTargets.RenderTargetDescriptor.ptr) { render_target_count = 1; } command_list->OMSetRenderTargets( render_target_count, reinterpret_cast(item)->SetRenderTargets.RenderTargetDescriptor.ptr == NULL ? nullptr : &reinterpret_cast(item)->SetRenderTargets.RenderTargetDescriptor, FALSE, reinterpret_cast(item)->SetRenderTargets.DepthStencilDescriptor.ptr == NULL ? nullptr : &reinterpret_cast(item)->SetRenderTargets.DepthStencilDescriptor ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::ResolveSubresource: { command_list->ResolveSubresource( reinterpret_cast(item)->ResolveSubresource.pDstResource, reinterpret_cast(item)->ResolveSubresource.DstSubresource, reinterpret_cast(item)->ResolveSubresource.pSrcResource, reinterpret_cast(item)->ResolveSubresource.SrcSubresource, reinterpret_cast(item)->ResolveSubresource.Format ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::BeginQuery: { command_list->BeginQuery( reinterpret_cast(item)->BeginQuery.pQueryHeap, reinterpret_cast(item)->BeginQuery.Type, reinterpret_cast(item)->BeginQuery.Index ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::EndQuery: { command_list->EndQuery( reinterpret_cast(item)->EndQuery.pQueryHeap, reinterpret_cast(item)->EndQuery.Type, reinterpret_cast(item)->EndQuery.Index ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::ResolveQueryData: { command_list->ResolveQueryData( reinterpret_cast(item)->ResolveQueryData.pQueryHeap, reinterpret_cast(item)->ResolveQueryData.Type, reinterpret_cast(item)->ResolveQueryData.StartElement, reinterpret_cast(item)->ResolveQueryData.ElementCount, reinterpret_cast(item)->ResolveQueryData.pDestinationBuffer, reinterpret_cast(item)->ResolveQueryData.AlignedDestinationBufferOffset ); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::CloseCommandList: { CheckHR(command_list->Close()); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::ExecuteCommandList: { parent_queued_command_list->m_command_queue->ExecuteCommandLists(1, reinterpret_cast(&command_list)); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::Present: { CheckHR(reinterpret_cast(item)->Present.swapChain->Present(reinterpret_cast(item)->Present.syncInterval, reinterpret_cast(item)->Present.flags)); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::ResetCommandList: { CheckHR(command_list->Reset(reinterpret_cast(item)->ResetCommandList.allocator, nullptr)); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::ResetCommandAllocator: { CheckHR(reinterpret_cast(item)->ResetCommandAllocator.allocator->Reset()); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::FenceGpuSignal: { CheckHR(parent_queued_command_list->m_command_queue->Signal(reinterpret_cast(item)->FenceGpuSignal.fence, reinterpret_cast(item)->FenceGpuSignal.fence_value)); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::FenceCpuSignal: { CheckHR(reinterpret_cast(item)->FenceCpuSignal.fence->Signal(reinterpret_cast(item)->FenceCpuSignal.fence_value)); item += BufferOffsetForQueueItemType(); break; } case D3DQueueItemType::Stop: // Use a goto to break out of the loop, since we can't exit the loop from // within a switch statement. We could use a separate 'if' after the switch, // but that was the highest source of overhead in the function after profiling. // http://stackoverflow.com/questions/1420029/how-to-break-out-of-a-loop-from-inside-a-switch bool eligible_to_move_to_front_of_queue = reinterpret_cast(item)->Stop.eligible_to_move_to_front_of_queue; bool signal_stop_event = reinterpret_cast(item)->Stop.signal_stop_event; bool terminate_worker_thread = reinterpret_cast(item)->Stop.terminate_worker_thread; item += BufferOffsetForQueueItemType(); if (eligible_to_move_to_front_of_queue && item - queue_array > QUEUE_ARRAY_SIZE * 2 / 3) { item = queue_array; } if (signal_stop_event) { SetEvent(parent_queued_command_list->m_stop_execution_event); } if (terminate_worker_thread) return; goto exitLoop; } } exitLoop: queue_array_front = static_cast(item - queue_array); } } ID3D12QueuedCommandList::ID3D12QueuedCommandList(ID3D12GraphicsCommandList* backing_command_list, ID3D12CommandQueue* backing_command_queue) : m_command_list(backing_command_list), m_command_queue(backing_command_queue) { memset(m_queue_array, 0, sizeof(m_queue_array)); m_queue_array_back = m_queue_array; m_begin_execution_event = CreateSemaphore(nullptr, 0, 256, nullptr); m_stop_execution_event = CreateEvent(nullptr, FALSE, FALSE, nullptr); m_background_thread = std::thread(BackgroundThreadFunction, this); } ID3D12QueuedCommandList::~ID3D12QueuedCommandList() { // Kick worker thread, and tell it to exit. ProcessQueuedItems(true, true, true); m_background_thread.join(); CloseHandle(m_begin_execution_event); CloseHandle(m_stop_execution_event); } void ID3D12QueuedCommandList::CheckForOverflow() { constexpr const unsigned int queue_space_allowed_per_frame = QUEUE_ARRAY_SIZE / 3; if (m_queue_array_back - m_queue_array_back_at_start_of_frame > queue_space_allowed_per_frame) { // Game is (possibly) using too much space, kick off queue processing and // wait on this thread till it chews through queue. // This means the game is submitting more than 28,000 draws a frame. ProcessQueuedItems(true, true); } } void ID3D12QueuedCommandList::ResetQueueOverflowTracking() { m_queue_array_back_at_start_of_frame = m_queue_array_back; } void ID3D12QueuedCommandList::QueueExecute() { reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::ExecuteCommandList; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void ID3D12QueuedCommandList::QueueFenceGpuSignal(ID3D12Fence* fence_to_signal, UINT64 fence_value) { D3DQueueItem item = {}; item.Type = D3DQueueItemType::FenceGpuSignal; item.FenceGpuSignal.fence = fence_to_signal; item.FenceGpuSignal.fence_value = fence_value; *reinterpret_cast(m_queue_array_back) = item; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void ID3D12QueuedCommandList::QueueFenceCpuSignal(ID3D12Fence* fence_to_signal, UINT64 fence_value) { D3DQueueItem item = {}; item.Type = D3DQueueItemType::FenceCpuSignal; item.FenceCpuSignal.fence = fence_to_signal; item.FenceCpuSignal.fence_value = fence_value; *reinterpret_cast(m_queue_array_back) = item; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void ID3D12QueuedCommandList::QueuePresent(IDXGISwapChain* swap_chain, UINT sync_interval, UINT flags) { D3DQueueItem item = {}; item.Type = D3DQueueItemType::Present; item.Present.swapChain = swap_chain; item.Present.flags = flags; item.Present.syncInterval = sync_interval; *reinterpret_cast(m_queue_array_back) = item; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void ID3D12QueuedCommandList::ProcessQueuedItems(bool eligible_to_move_to_front_of_queue, bool wait_for_stop, bool terminate_worker_thread) { D3DQueueItem item = {}; item.Type = D3DQueueItemType::Stop; item.Stop.eligible_to_move_to_front_of_queue = eligible_to_move_to_front_of_queue; item.Stop.signal_stop_event = wait_for_stop; item.Stop.terminate_worker_thread = terminate_worker_thread; *reinterpret_cast(m_queue_array_back) = item; m_queue_array_back += BufferOffsetForQueueItemType(); // Only (possibly) move to front of queue when finishing a frame, or when draining GPU queue. // Logic in ID3D12QueuedCommandList::CheckForOverflow // ensures that not more than one third of queue is used per frame. if (eligible_to_move_to_front_of_queue && (m_queue_array_back - m_queue_array > QUEUE_ARRAY_SIZE * 2 / 3)) { m_queue_array_back = m_queue_array; } if (eligible_to_move_to_front_of_queue) { ResetQueueOverflowTracking(); } ReleaseSemaphore(m_begin_execution_event, 1, nullptr); if (wait_for_stop) { WaitForSingleObject(m_stop_execution_event, INFINITE); ResetEvent(m_stop_execution_event); } } ULONG ID3D12QueuedCommandList::AddRef() { m_ref.fetch_add(1); return m_ref.load(); } ULONG ID3D12QueuedCommandList::Release() { // fetch_sub returns the value held before the subtraction. ULONG ref = m_ref.fetch_sub(1); if (ref == 1) { delete this; } return ref; } HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::QueryInterface( _In_ REFIID riid, _COM_Outptr_ void** ppvObject ) { *ppvObject = nullptr; HRESULT hr = S_OK; if (riid == __uuidof(ID3D12GraphicsCommandList)) { *ppvObject = reinterpret_cast(this); } else if (riid == __uuidof(ID3D12CommandList)) { *ppvObject = reinterpret_cast(this); } else if (riid == __uuidof(ID3D12DeviceChild)) { *ppvObject = reinterpret_cast(this); } else if (riid == __uuidof(ID3D12Object)) { *ppvObject = reinterpret_cast(this); } else { hr = E_NOINTERFACE; } if (*ppvObject != nullptr) { AddRef(); } return hr; } // ID3D12Object HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::GetPrivateData( _In_ REFGUID guid, _Inout_ UINT* pDataSize, _Out_writes_bytes_opt_(*pDataSize) void* pData ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); return E_FAIL; } HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::SetPrivateData( _In_ REFGUID guid, _In_ UINT DataSize, _In_reads_bytes_opt_(DataSize) const void* pData ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); return E_FAIL; } HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::SetPrivateDataInterface( _In_ REFGUID guid, _In_opt_ const IUnknown* pData ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); return E_FAIL; } HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::SetName( _In_z_ LPCWSTR pName ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); return E_FAIL; } // ID3D12DeviceChild D3D12_COMMAND_LIST_TYPE STDMETHODCALLTYPE ID3D12QueuedCommandList::GetType() { return D3D12_COMMAND_LIST_TYPE_DIRECT; } // ID3D12CommandList HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::GetDevice( REFIID riid, _Out_ void** ppDevice ) { return m_command_list->GetDevice(riid, ppDevice); } HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::Close() { reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::CloseCommandList; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); return S_OK; } HRESULT STDMETHODCALLTYPE ID3D12QueuedCommandList::Reset( _In_ ID3D12CommandAllocator* pAllocator, _In_opt_ ID3D12PipelineState* pInitialState ) { DEBUGCHECK(pInitialState == nullptr, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::ResetCommandList; reinterpret_cast(m_queue_array_back)->ResetCommandList.allocator = pAllocator; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); return S_OK; } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ClearState( _In_ ID3D12PipelineState* pPipelineState ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::DrawInstanced( _In_ UINT VertexCountPerInstance, _In_ UINT InstanceCount, _In_ UINT StartVertexLocation, _In_ UINT StartInstanceLocation ) { DEBUGCHECK(InstanceCount == 1, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(StartInstanceLocation == 0, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::DrawInstanced; reinterpret_cast(m_queue_array_back)->DrawInstanced.StartVertexLocation = StartVertexLocation; reinterpret_cast(m_queue_array_back)->DrawInstanced.VertexCount = VertexCountPerInstance; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::DrawIndexedInstanced( _In_ UINT IndexCountPerInstance, _In_ UINT InstanceCount, _In_ UINT StartIndexLocation, _In_ INT BaseVertexLocation, _In_ UINT StartInstanceLocation ) { DEBUGCHECK(InstanceCount == 1, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(StartInstanceLocation == 0, "Error: Invalid assumption in ID3D12QueuedCommandList."); D3DQueueItem* item = reinterpret_cast(m_queue_array_back); item->Type = D3DQueueItemType::DrawIndexedInstanced; item->DrawIndexedInstanced.BaseVertexLocation = BaseVertexLocation; item->DrawIndexedInstanced.IndexCount = IndexCountPerInstance; item->DrawIndexedInstanced.StartIndexLocation = StartIndexLocation; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::Dispatch( _In_ UINT ThreadGroupCountX, _In_ UINT ThreadGroupCountY, _In_ UINT ThreadGroupCountZ ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::DispatchIndirect( _In_ ID3D12Resource* pBufferForArgs, _In_ UINT AlignedByteOffsetForArgs ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::CopyBufferRegion( _In_ ID3D12Resource* pDstBuffer, UINT64 DstOffset, _In_ ID3D12Resource* pSrcBuffer, UINT64 SrcOffset, UINT64 NumBytes ) { reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::CopyBufferRegion; reinterpret_cast(m_queue_array_back)->CopyBufferRegion.pDstBuffer = pDstBuffer; reinterpret_cast(m_queue_array_back)->CopyBufferRegion.DstOffset = static_cast(DstOffset); reinterpret_cast(m_queue_array_back)->CopyBufferRegion.pSrcBuffer = pSrcBuffer; reinterpret_cast(m_queue_array_back)->CopyBufferRegion.SrcOffset = static_cast(SrcOffset); reinterpret_cast(m_queue_array_back)->CopyBufferRegion.NumBytes = static_cast(NumBytes); m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::CopyTextureRegion( _In_ const D3D12_TEXTURE_COPY_LOCATION* pDst, UINT DstX, UINT DstY, UINT DstZ, _In_ const D3D12_TEXTURE_COPY_LOCATION* pSrc, _In_opt_ const D3D12_BOX* pSrcBox ) { reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::CopyTextureRegion; reinterpret_cast(m_queue_array_back)->CopyTextureRegion.dst =* pDst; reinterpret_cast(m_queue_array_back)->CopyTextureRegion.src =* pSrc; reinterpret_cast(m_queue_array_back)->CopyTextureRegion.DstX = DstX; reinterpret_cast(m_queue_array_back)->CopyTextureRegion.DstY = DstY; reinterpret_cast(m_queue_array_back)->CopyTextureRegion.DstZ = DstZ; if (pSrcBox) reinterpret_cast(m_queue_array_back)->CopyTextureRegion.srcBox = *pSrcBox; else reinterpret_cast(m_queue_array_back)->CopyTextureRegion.srcBox = {}; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::CopyResource( _In_ ID3D12Resource* pDstResource, _In_ ID3D12Resource* pSrcResource ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::CopyTiles( _In_ ID3D12Resource* pTiledResource, _In_ const D3D12_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate, _In_ const D3D12_TILE_REGION_SIZE* pTileRegionSize, _In_ ID3D12Resource* pBuffer, UINT64 BufferStartOffsetInBytes, D3D12_TILE_COPY_FLAGS Flags ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ResolveSubresource( _In_ ID3D12Resource* pDstResource, _In_ UINT DstSubresource, _In_ ID3D12Resource* pSrcResource, _In_ UINT SrcSubresource, _In_ DXGI_FORMAT Format ) { // No ignored parameters, no assumptions to DEBUGCHECK. reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::ResolveSubresource; reinterpret_cast(m_queue_array_back)->ResolveSubresource.pDstResource = pDstResource; reinterpret_cast(m_queue_array_back)->ResolveSubresource.DstSubresource = DstSubresource; reinterpret_cast(m_queue_array_back)->ResolveSubresource.pSrcResource = pSrcResource; reinterpret_cast(m_queue_array_back)->ResolveSubresource.SrcSubresource = SrcSubresource; reinterpret_cast(m_queue_array_back)->ResolveSubresource.Format = Format; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::IASetPrimitiveTopology( _In_ D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology ) { // No ignored parameters, no assumptions to DEBUGCHECK. reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::IASetPrimitiveTopology; reinterpret_cast(m_queue_array_back)->IASetPrimitiveTopology.PrimitiveTopology = PrimitiveTopology; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::RSSetViewports( _In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT Count, _In_reads_(Count) const D3D12_VIEWPORT* pViewports ) { DEBUGCHECK(Count == 1, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::RSSetViewports; reinterpret_cast(m_queue_array_back)->RSSetViewports.Height = pViewports->Height; reinterpret_cast(m_queue_array_back)->RSSetViewports.Width = pViewports->Width; reinterpret_cast(m_queue_array_back)->RSSetViewports.TopLeftX = pViewports->TopLeftX; reinterpret_cast(m_queue_array_back)->RSSetViewports.TopLeftY = pViewports->TopLeftY; reinterpret_cast(m_queue_array_back)->RSSetViewports.MinDepth = pViewports->MinDepth; reinterpret_cast(m_queue_array_back)->RSSetViewports.MaxDepth = pViewports->MaxDepth; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::RSSetScissorRects( _In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT Count, _In_reads_(Count) const D3D12_RECT* pRects ) { DEBUGCHECK(Count == 1, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::RSSetScissorRects; reinterpret_cast(m_queue_array_back)->RSSetScissorRects.bottom = pRects->bottom; reinterpret_cast(m_queue_array_back)->RSSetScissorRects.left = pRects->left; reinterpret_cast(m_queue_array_back)->RSSetScissorRects.right = pRects->right; reinterpret_cast(m_queue_array_back)->RSSetScissorRects.top = pRects->top; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::OMSetBlendFactor( _In_opt_ const FLOAT BlendFactor[4] ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::OMSetStencilRef( _In_ UINT StencilRef ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetPipelineState( _In_ ID3D12PipelineState* pPipelineState ) { // No ignored parameters, no assumptions to DEBUGCHECK. D3DQueueItem* item = reinterpret_cast(m_queue_array_back); item->Type = D3DQueueItemType::SetPipelineState; item->SetPipelineState.pPipelineStateObject = pPipelineState; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ResourceBarrier( _In_ UINT NumBarriers, _In_reads_(NumBarriers) const D3D12_RESOURCE_BARRIER* pBarriers ) { DEBUGCHECK(NumBarriers == 1, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::ResourceBarrier; reinterpret_cast(m_queue_array_back)->ResourceBarrier.barrier = *pBarriers; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ExecuteBundle( _In_ ID3D12GraphicsCommandList *pCommandList ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::BeginQuery( _In_ ID3D12QueryHeap* pQueryHeap, _In_ D3D12_QUERY_TYPE Type, _In_ UINT Index ) { reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::BeginQuery; reinterpret_cast(m_queue_array_back)->BeginQuery.pQueryHeap = pQueryHeap; reinterpret_cast(m_queue_array_back)->BeginQuery.Type = Type; reinterpret_cast(m_queue_array_back)->BeginQuery.Index = Index; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::EndQuery( _In_ ID3D12QueryHeap* pQueryHeap, _In_ D3D12_QUERY_TYPE Type, _In_ UINT Index ) { reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::EndQuery; reinterpret_cast(m_queue_array_back)->EndQuery.pQueryHeap = pQueryHeap; reinterpret_cast(m_queue_array_back)->EndQuery.Type = Type; reinterpret_cast(m_queue_array_back)->EndQuery.Index = Index; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ResolveQueryData( _In_ ID3D12QueryHeap* pQueryHeap, _In_ D3D12_QUERY_TYPE Type, _In_ UINT StartElement, _In_ UINT ElementCount, _In_ ID3D12Resource* pDestinationBuffer, _In_ UINT64 AlignedDestinationBufferOffset ) { reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::ResolveQueryData; reinterpret_cast(m_queue_array_back)->ResolveQueryData.pQueryHeap = pQueryHeap; reinterpret_cast(m_queue_array_back)->ResolveQueryData.Type = Type; reinterpret_cast(m_queue_array_back)->ResolveQueryData.StartElement = StartElement; reinterpret_cast(m_queue_array_back)->ResolveQueryData.ElementCount = ElementCount; reinterpret_cast(m_queue_array_back)->ResolveQueryData.pDestinationBuffer = pDestinationBuffer; reinterpret_cast(m_queue_array_back)->ResolveQueryData.AlignedDestinationBufferOffset = AlignedDestinationBufferOffset; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetPredication( _In_opt_ ID3D12Resource* pBuffer, _In_ UINT64 AlignedBufferOffset, _In_ D3D12_PREDICATION_OP Operation ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetDescriptorHeaps( _In_ UINT NumDescriptorHeaps, _In_reads_(NumDescriptorHeaps) ID3D12DescriptorHeap *const * pDescriptorHeaps ) { // No ignored parameters, no assumptions to DEBUGCHECK. reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::SetDescriptorHeaps; reinterpret_cast(m_queue_array_back)->SetDescriptorHeaps.ppDescriptorHeap = pDescriptorHeaps; reinterpret_cast(m_queue_array_back)->SetDescriptorHeaps.NumDescriptorHeaps = NumDescriptorHeaps; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetComputeRootSignature( _In_ ID3D12RootSignature* pRootSignature ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetGraphicsRootSignature( _In_ ID3D12RootSignature* pRootSignature ) { // No ignored parameters, no assumptions to DEBUGCHECK. reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::SetGraphicsRootSignature; reinterpret_cast(m_queue_array_back)->SetGraphicsRootSignature.pRootSignature = pRootSignature; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetComputeRootDescriptorTable( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetGraphicsRootDescriptorTable( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor ) { // No ignored parameters, no assumptions to DEBUGCHECK. D3DQueueItem* item = reinterpret_cast(m_queue_array_back); item->Type = D3DQueueItemType::SetGraphicsRootDescriptorTable; item->SetGraphicsRootDescriptorTable.RootParameterIndex = RootParameterIndex; item->SetGraphicsRootDescriptorTable.BaseDescriptor = BaseDescriptor; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetComputeRoot32BitConstant( _In_ UINT RootParameterIndex, _In_ UINT SrcData, _In_ UINT DestOffsetIn32BitValues ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetGraphicsRoot32BitConstant( _In_ UINT RootParameterIndex, _In_ UINT SrcData, _In_ UINT DestOffsetIn32BitValues ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetComputeRoot32BitConstants( _In_ UINT RootParameterIndex, _In_ UINT Num32BitValuesToSet, _In_reads_(Num32BitValuesToSet*sizeof(UINT)) const void* pSrcData, _In_ UINT DestOffsetIn32BitValues ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetGraphicsRoot32BitConstants( _In_ UINT RootParameterIndex, _In_ UINT Num32BitValuesToSet, _In_reads_(Num32BitValuesToSet*sizeof(UINT)) const void* pSrcData, _In_ UINT DestOffsetIn32BitValues ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetGraphicsRootConstantBufferView( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation ) { // No ignored parameters, no assumptions to DEBUGCHECK. D3DQueueItem* item = reinterpret_cast(m_queue_array_back); item->Type = D3DQueueItemType::SetGraphicsRootConstantBufferView; item->SetGraphicsRootConstantBufferView.RootParameterIndex = RootParameterIndex; item->SetGraphicsRootConstantBufferView.BufferLocation = BufferLocation; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetComputeRootConstantBufferView( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_VIRTUAL_ADDRESS BufferLocation ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetComputeRootShaderResourceView( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_VIRTUAL_ADDRESS DescriptorHandle ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetGraphicsRootShaderResourceView( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_VIRTUAL_ADDRESS DescriptorHandle ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetComputeRootUnorderedAccessView( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_VIRTUAL_ADDRESS DescriptorHandle ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetGraphicsRootUnorderedAccessView( _In_ UINT RootParameterIndex, _In_ D3D12_GPU_VIRTUAL_ADDRESS DescriptorHandle ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::IASetIndexBuffer( _In_opt_ const D3D12_INDEX_BUFFER_VIEW* pDesc ) { // No ignored parameters, no assumptions to DEBUGCHECK. reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::SetIndexBuffer; reinterpret_cast(m_queue_array_back)->SetIndexBuffer.desc = *pDesc; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::IASetVertexBuffers( _In_ UINT StartSlot, _In_ UINT NumBuffers, _In_ const D3D12_VERTEX_BUFFER_VIEW* pDesc ) { DEBUGCHECK(StartSlot == 0, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(NumBuffers == 1, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::SetVertexBuffers; reinterpret_cast(m_queue_array_back)->SetVertexBuffers.desc = *pDesc; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SOSetTargets( _In_ UINT StartSlot, _In_ UINT NumViews, _In_ const D3D12_STREAM_OUTPUT_BUFFER_VIEW* pViews ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::OMSetRenderTargets( _In_ UINT NumRenderTargetDescriptors, _In_ const D3D12_CPU_DESCRIPTOR_HANDLE* pRenderTargetDescriptors, _In_ BOOL RTsSingleHandleToDescriptorRange, _In_opt_ const D3D12_CPU_DESCRIPTOR_HANDLE *pDepthStencilDescriptor ) { DEBUGCHECK(RTsSingleHandleToDescriptorRange == FALSE, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::SetRenderTargets; if (pRenderTargetDescriptors) reinterpret_cast(m_queue_array_back)->SetRenderTargets.RenderTargetDescriptor = *pRenderTargetDescriptors; else reinterpret_cast(m_queue_array_back)->SetRenderTargets.RenderTargetDescriptor = {}; if (pDepthStencilDescriptor) reinterpret_cast(m_queue_array_back)->SetRenderTargets.DepthStencilDescriptor = *pDepthStencilDescriptor; else reinterpret_cast(m_queue_array_back)->SetRenderTargets.DepthStencilDescriptor = {}; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ClearDepthStencilView( _In_ D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView, _In_ D3D12_CLEAR_FLAGS ClearFlags, _In_ FLOAT Depth, _In_ UINT8 Stencil, _In_ UINT NumRects, _In_reads_opt_(NumRects) const D3D12_RECT* pRect ) { DEBUGCHECK(ClearFlags == D3D12_CLEAR_FLAG_DEPTH, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(Depth == 0.0f, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(Stencil == 0, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(pRect == nullptr, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(NumRects == 0, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::ClearDepthStencilView; reinterpret_cast(m_queue_array_back)->ClearDepthStencilView.DepthStencilView = DepthStencilView; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ClearRenderTargetView( _In_ D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetView, _In_ const FLOAT ColorRGBA[4], _In_ UINT NumRects, _In_reads_opt_(NumRects) const D3D12_RECT* pRects ) { DEBUGCHECK(ColorRGBA[0] == 0.0f, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(ColorRGBA[1] == 0.0f, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(ColorRGBA[2] == 0.0f, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(ColorRGBA[3] == 1.0f, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(pRects == nullptr, "Error: Invalid assumption in ID3D12QueuedCommandList."); DEBUGCHECK(NumRects == 0, "Error: Invalid assumption in ID3D12QueuedCommandList."); reinterpret_cast(m_queue_array_back)->Type = D3DQueueItemType::ClearRenderTargetView; reinterpret_cast(m_queue_array_back)->ClearRenderTargetView.RenderTargetView = RenderTargetView; m_queue_array_back += BufferOffsetForQueueItemType(); CheckForOverflow(); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ClearUnorderedAccessViewUint( _In_ D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap, _In_ D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle, _In_ ID3D12Resource* pResource, _In_ const UINT Values[4], _In_ UINT NumRects, _In_reads_opt_(NumRects) const D3D12_RECT* pRects ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ClearUnorderedAccessViewFloat( _In_ D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap, _In_ D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle, _In_ ID3D12Resource* pResource, _In_ const FLOAT Values[4], _In_ UINT NumRects, _In_reads_opt_(NumRects) const D3D12_RECT* pRects ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::DiscardResource( _In_ ID3D12Resource* pResource, _In_opt_ const D3D12_DISCARD_REGION* pDesc ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetMarker( UINT Metadata, _In_reads_bytes_opt_(Size) const void* pData, UINT Size ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::BeginEvent( UINT Metadata, _In_reads_bytes_opt_(Size) const void* pData, UINT Size ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::EndEvent() { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } void STDMETHODCALLTYPE ID3D12QueuedCommandList::ExecuteIndirect( _In_ ID3D12CommandSignature* pCommandSignature, _In_ UINT MaxCommandCount, _In_ ID3D12Resource* pArgumentBuffer, _In_ UINT64 ArgumentBufferOffset, _In_opt_ ID3D12Resource* pCountBuffer, _In_ UINT64 CountBufferOffset ) { // Function not implemented yet. DEBUGCHECK(0, "Function not implemented yet."); } } // namespace DX12