//-------------------------------------------------------------------------- void VeRenderWindowD3D12::RecordScene(VeUInt32 u32Thread) noexcept { for (auto& cam : m_kCameraList) { for (auto idx : cam.m_kStageList) { FrameCache& kFrame = m_akFrameCache[m_u32FrameIndex]; ID3D12GraphicsCommandList* pkGCL = kFrame.m_kDirectCommandList[idx + u32Thread]; VE_ASSERT_GE(pkGCL->Reset(kFrame.m_pkDirectAllocator, nullptr), S_OK); VE_ASSERT_GE(pkGCL->Close(), S_OK); } } }
void* RenderAPI_D3D12::BeginModifyTexture(void* textureHandle, int textureWidth, int textureHeight, int* outRowPitch) { ID3D12Fence* fence = s_D3D12->GetFrameFence(); // Wait on the previous job (example only - simplifies resource management) if (fence->GetCompletedValue() < s_D3D12FenceValue) { fence->SetEventOnCompletion(s_D3D12FenceValue, s_D3D12Event); WaitForSingleObject(s_D3D12Event, INFINITE); } // Begin a command list s_D3D12CmdAlloc->Reset(); s_D3D12CmdList->Reset(s_D3D12CmdAlloc, nullptr); // Fill data const UINT64 kDataSize = textureWidth * textureHeight * 4; ID3D12Resource* upload = GetUploadResource(kDataSize); void* mapped = NULL; upload->Map(0, NULL, &mapped); *outRowPitch = textureWidth * 4; return mapped; }
void DXMultiAdapterRenderer::PopulateCommandLists() { // Primary rendering command list { ComPtr<ID3D12Resource> curPrimaryRenderTarget = mDXDevices[Device_Primary]->mRenderTargets[mCurrentFrameIndex]; // Reset allocator and command list for current render target ThrowIfFailed(mDXDevices[Device_Primary]->mCommandAllocator->Reset()); // Only do this when all command lists have finished executing ID3D12GraphicsCommandList* primaryCommandList = mCommandLists[Primary_CommandList_Scene].Get(); ThrowIfFailed(primaryCommandList->Reset(mDXDevices[Device_Primary]->mCommandAllocator.Get(), nullptr)); primaryCommandList->RSSetViewports(1, &mViewport); primaryCommandList->RSSetScissorRects(1, &mScissorRect); ID3D12DescriptorHeap* descHeaps[] = { mDXDevices[Device_Primary]->mCbvSrvUavHeap.Get() }; primaryCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps); // Allow for rending to current render target primaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curPrimaryRenderTarget.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(mDXDevices[Device_Primary]->mRtvHeap->GetCPUDescriptorHandleForHeapStart(), mCurrentFrameIndex, mDXDevices[Device_Primary]->mRtvDescriptorSize); primaryCommandList->OMSetRenderTargets(1, &rtvHandle, true, nullptr); primaryCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); primaryCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Primary_Quad_Top]); // Render top portion of scene on primary GPU primaryCommandList->SetGraphicsRootSignature(mRootSignatures[Primary_RootSignature_Scene].Get()); primaryCommandList->SetGraphicsRootDescriptorTable(0, mTimePrimaryCbvHandle); primaryCommandList->SetPipelineState(mPipelineStates[Primary_PipelineState_Scene].Get()); primaryCommandList->DrawInstanced(4, 1, 0, 0); // Indicate that render target will be used for copy primaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curPrimaryRenderTarget.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE)); ThrowIfFailed(mCommandLists[Primary_CommandList_Scene]->Close()); } // Copy command list - in DXCrossAdapterResources object { mCrossAdapterResources->PopulateCommandList(mCurrentFrameIndex); } // Reset command allocator for secondary device - used by all following command lists ThrowIfFailed(mDXDevices[Device_Secondary]->mCommandAllocator->Reset()); // Only do this when all command lists have finished executing // Secondary rendering command list { ID3D12GraphicsCommandList* secondaryCommandList = mCommandLists[Secondary_CommandList_Scene].Get(); ThrowIfFailed(secondaryCommandList->Reset(mDXDevices[Device_Secondary]->mCommandAllocator.Get(), nullptr)); secondaryCommandList->RSSetViewports(1, &mViewport); secondaryCommandList->RSSetScissorRects(1, &mScissorRect); ID3D12DescriptorHeap* descHeaps[] = { mDXDevices[Device_Secondary]->mCbvSrvUavHeap.Get() }; secondaryCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps); secondaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); secondaryCommandList->OMSetRenderTargets(1, &mTextureRtvHandle, true, nullptr); secondaryCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); secondaryCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Secondary_Quad_Bottom]); // Quad geometry // Render bottom portion of scene on secondary GPU secondaryCommandList->SetGraphicsRootSignature(mRootSignatures[Secondary_RootSignature_Scene].Get()); secondaryCommandList->SetGraphicsRootDescriptorTable(0, mTimeSecondaryCbvHandle); secondaryCommandList->SetPipelineState(mPipelineStates[Secondary_PipelineState_Scene].Get()); secondaryCommandList->DrawInstanced(4, 1, 0, 0); secondaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); ThrowIfFailed(mCommandLists[Secondary_CommandList_Scene]->Close()); } // Overlay Command List { ID3D12GraphicsCommandList* overlayCommandList = mCommandLists[Secondary_CommandList_Combine_Scene].Get(); ComPtr<ID3D12Resource> curSecondaryRenderTarget = mDXDevices[Device_Secondary]->mRenderTargets[mCurrentFrameIndex]; // Get secondary render target for current frame ThrowIfFailed(overlayCommandList->Reset(mDXDevices[Device_Secondary]->mCommandAllocator.Get(), nullptr)); overlayCommandList->RSSetViewports(1, &mViewport); overlayCommandList->RSSetScissorRects(1, &mScissorRect); ID3D12DescriptorHeap* descHeaps[] = { mDXDevices[Device_Secondary]->mCbvSrvUavHeap.Get() }; overlayCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps); overlayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curSecondaryRenderTarget.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(mDXDevices[Device_Secondary]->mRtvHeap->GetCPUDescriptorHandleForHeapStart(), mCurrentFrameIndex, mDXDevices[Device_Secondary]->mRtvDescriptorSize); overlayCommandList->OMSetRenderTargets(1, &rtvHandle, true, nullptr); static const float clearColor[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; overlayCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); overlayCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); // Render top quad with cross-adapter texture overlayCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Secondary_Quad_Combine_Top]); // Quad geometry CD3DX12_GPU_DESCRIPTOR_HANDLE crossAdapterSrvHandle(mDXDevices[Device_Secondary]->mCbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart(), mCurrentFrameIndex, mDXDevices[Device_Secondary]->mCbvSrvUavDescriptorSize); overlayCommandList->SetGraphicsRootSignature(mRootSignatures[Secondary_RootSignature_CrossAdapter].Get()); overlayCommandList->SetPipelineState(mPipelineStates[Secondary_PipelineState_CrossAdapter].Get()); overlayCommandList->SetGraphicsRootDescriptorTable(0, mTransformTopCbvHandle); overlayCommandList->SetGraphicsRootDescriptorTable(1, crossAdapterSrvHandle); // Scale and translate quad to top of screen mConstantBufferTransformTopData.modelViewProjection = DirectX::XMMatrixIdentity(); mConstantBufferTransformTopData.modelViewProjection *= DirectX::XMMatrixTranslation(0.0, ((1.0f / mSharePercentage) - 1.0f) + 0.015f, 0.0); mConstantBufferTransformTopData.modelViewProjection *= DirectX::XMMatrixScaling(1.0, mSharePercentage, 1.0); UpdateConstantBuffer(mConstantBufferTransformTop, &mConstantBufferTransformTopData, sizeof(mConstantBufferTransformTopData)); overlayCommandList->DrawInstanced(4, 1, 0, 0); // Render bottom quad with texture from secondary GPU overlayCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Secondary_Quad_Combine_Bottom]); // Quad geometry overlayCommandList->SetGraphicsRootDescriptorTable(0, mTransformBottomCbvHandle); overlayCommandList->SetGraphicsRootDescriptorTable(1, mTextureSrvHandle); // Scale and translate quad to bottom of screen mConstantBufferTransformBottomData.modelViewProjection = DirectX::XMMatrixIdentity(); mConstantBufferTransformBottomData.modelViewProjection *= DirectX::XMMatrixTranslation(0.0, -((1.0f / (1.0f - mSharePercentage)) - 1.0f) - 0.015f, 0.0); mConstantBufferTransformBottomData.modelViewProjection *= DirectX::XMMatrixScaling(1.0, (1.0f - mSharePercentage), 1.0); UpdateConstantBuffer(mConstantBufferTransformBottom, &mConstantBufferTransformBottomData, sizeof(mConstantBufferTransformBottomData)); overlayCommandList->DrawInstanced(4, 1, 0, 0); overlayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curSecondaryRenderTarget.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); ThrowIfFailed(mCommandLists[Secondary_CommandList_Combine_Scene]->Close()); } }
void TextureStore::loadTexture(wstring filename, string id) { TextureLoadResult result; TextureInfo initialTexture; // only use to initialize struct in texture store - do not access this after assignment to store vector<byte> file_buffer; initialTexture.id = id; textures[id] = initialTexture; TextureInfo *texture = &textures[id]; // find texture file, look in pak file first: PakEntry *pakFileEntry = nullptr; pakFileEntry = xapp().findFileInPak(filename.c_str()); // try file system if not found in pak: initialTexture.filename = filename; // TODO check: field not needed? only in this method? --> remove if (pakFileEntry == nullptr) { wstring binFile = xapp().findFile(filename.c_str(), XApp::TEXTURE); texture->filename = binFile; //initialTexture.filename = binFile; xapp().readFile(texture->filename.c_str(), file_buffer, XApp::FileCategory::TEXTURE); } else { xapp().readFile(pakFileEntry, file_buffer, XApp::FileCategory::TEXTURE); } ID3D12GraphicsCommandList *commandList = this->commandList.Get(); //D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV // create heap - TODO adjust for one heap for multiple textures // Describe and create a shader resource view (SRV) heap for the texture. D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; srvHeapDesc.NumDescriptors = 1; srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(xapp().device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&texture->m_srvHeap))); CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(texture->m_srvHeap->GetCPUDescriptorHandleForHeapStart()); //CD3DX12_CPU_DESCRIPTOR_HANDLE(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); CreateDDSTextureFromMemory( xapp().device.Get(), &file_buffer[0], file_buffer.size(), 0, true, &texture->texSRV, srvHandle, result ); //CreateDDSTextureFromFile( // xapp().device.Get(), // texture->filename.c_str(), // 0, // true, // &texture->texSRV, // srvHandle, // result // ); // upload texture to GPU: //ID3D12Resource* UploadBuffer; UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture->texSRV.Get(), 0, result.NumSubresources); //CommandContext& InitContext = CommandContext::Begin(); D3D12_HEAP_PROPERTIES HeapProps; HeapProps.Type = D3D12_HEAP_TYPE_UPLOAD; HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; HeapProps.CreationNodeMask = 1; HeapProps.VisibleNodeMask = 1; D3D12_RESOURCE_DESC BufferDesc; BufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; BufferDesc.Alignment = 0; BufferDesc.Width = uploadBufferSize; BufferDesc.Height = 1; BufferDesc.DepthOrArraySize = 1; BufferDesc.MipLevels = 1; BufferDesc.Format = DXGI_FORMAT_UNKNOWN; BufferDesc.SampleDesc.Count = 1; BufferDesc.SampleDesc.Quality = 0; BufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; BufferDesc.Flags = D3D12_RESOURCE_FLAG_NONE; ThrowIfFailed(xapp().device->CreateCommittedResource(&HeapProps, D3D12_HEAP_FLAG_NONE, &BufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&result.UploadBuffer))); // copy data to the intermediate upload heap and then schedule a copy from the upload heap to the default texture //InitContext.TransitionResource(Dest, D3D12_RESOURCE_STATE_COPY_DEST, true); commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(texture->texSRV.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST)); UpdateSubresources(commandList, texture->texSRV.Get(), result.UploadBuffer, 0, 0, result.NumSubresources, result.initData.get()); commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(texture->texSRV.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); //InitContext.TransitionResource(Dest, D3D12_RESOURCE_STATE_GENERIC_READ, true); // Execute the command list and wait for it to finish so we can release the upload buffer //InitContext.CloseAndExecute(true); //UploadBuffer->Release(); ThrowIfFailed(commandList->Close()); ID3D12CommandList* ppCommandLists[] = { this->commandList.Get() }; xapp().commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // Create synchronization objects and wait until assets have been uploaded to the GPU. //Sleep(300); EffectBase::createSyncPoint(updateFrameData, xapp().commandQueue); EffectBase::waitForSyncPoint(updateFrameData); //auto &f = frameData[frameIndex]; //createSyncPoint(f, xapp().commandQueue); //waitForSyncPoint(f); result.UploadBuffer->Release(); ThrowIfFailed(commandList->Reset(commandAllocator.Get(), pipelineState.Get())); }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::Record(VeUInt32 u32Index) noexcept { VeRendererD3D12& kRenderer = *VeMemberCast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); VE_ASSERT(u32Index < m_kRecorderList.size()); Recorder& kRecorder = m_kRecorderList[u32Index]; FrameCache& kFrame = m_akFrameCache[m_u32FrameIndex]; ID3D12GraphicsCommandList* pkGCL = kFrame.m_kDirectCommandList[kRecorder.m_u32CommandIndex]; VE_ASSERT_GE(pkGCL->Reset(kFrame.m_pkDirectAllocator, nullptr), S_OK); ID3D12DescriptorHeap* ppHeaps[] = { kRenderer.m_kSRVHeap.Get() }; pkGCL->SetDescriptorHeaps(1, ppHeaps); for (auto& task : kRecorder.m_kTaskList) { switch (task->m_eType) { case REC_BARRIER: { auto& list = ((RecordBarrier*)task)->m_akBarrierList[m_u32FrameIndex]; pkGCL->ResourceBarrier((VeUInt32)list.size(), &list.front()); } break; case REC_CLEAR_RTV: { RecordClearRTV& rec = *((RecordClearRTV*)task); pkGCL->ClearRenderTargetView(rec.m_ahHandle[m_u32FrameIndex], (const FLOAT*)&(rec.m_kColor), 0, nullptr); } break; case REC_CLEAR_DSV: { RecordClearDSV& rec = *((RecordClearDSV*)task); pkGCL->ClearDepthStencilView(rec.m_ahHandle[m_u32FrameIndex], rec.m_eFlags, rec.m_f32Depth, rec.m_u8Stencil, 0, nullptr); } break; case REC_RENDER_TARGET: { RecordRenderTarget& rec = *((RecordRenderTarget*)task); pkGCL->OMSetRenderTargets((VeUInt32)rec.m_akRTVList[m_u32FrameIndex].size(), &rec.m_akRTVList[m_u32FrameIndex].front(), FALSE, rec.m_ahDSV[m_u32FrameIndex].ptr ? &rec.m_ahDSV[m_u32FrameIndex] : nullptr); } break; case REC_VIEWPORT: { RecordViewport& rec = *((RecordViewport*)task); pkGCL->RSSetViewports((VeUInt32)rec.m_kViewportList.size(), &rec.m_kViewportList.front()); } break; case REC_SCISSOR_RECT: { RecordScissorRect& rec = *((RecordScissorRect*)task); pkGCL->RSSetScissorRects((VeUInt32)rec.m_kScissorRectList.size(), &rec.m_kScissorRectList.front()); } break; case REC_RENDER_QUAD: { RecordRenderQuad& rec = *((RecordRenderQuad*)task); pkGCL->SetPipelineState(rec.m_pkPipelineState); pkGCL->SetGraphicsRootSignature(rec.m_pkRootSignature); for (auto& itTab : rec.m_kTable) { pkGCL->SetGraphicsRootDescriptorTable(itTab.first, itTab.second); } pkGCL->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); pkGCL->IASetVertexBuffers(0, 1, &kRenderer.m_kQuadVBV); pkGCL->DrawInstanced(4, 1, 0, 0); } break; default: break; } } VE_ASSERT_GE(pkGCL->Close(), S_OK); }