void onRender() { // // record all the commands we need to render the scene into the command list // populateCommandLists(); // // execute the command list // ID3D12CommandList* ppCommandLists[] = { mCommandList.Get() }; mCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // // swap the back and front buffers // mSwapChain->Present(1, 0); mIndexLastSwapBuf = (1 + mIndexLastSwapBuf) % cNumSwapBufs; mSwapChain->GetBuffer(mIndexLastSwapBuf, IID_PPV_ARGS(mRenderTarget.ReleaseAndGetAddressOf())); mDevice->CreateRenderTargetView(mRenderTarget.Get(), nullptr, mDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); // // wait and reset everything // waitForGPU(); }
void onDestroy() { // // wait for the GPU to be done with all resources // waitForGPU(); mSwapChain->SetFullscreenState(FALSE, nullptr); CloseHandle(mHandleEvent); }
void loadAssets() { // // handles to vert and pixel shaders // ComPtr<ID3DBlob> blobShaderVert, blobShaderPixel; // // compile shaders // D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "VShader", "vs_5_0", 0, 0, blobShaderVert.GetAddressOf(), nullptr); D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "PShader", "ps_5_0", 0, 0, blobShaderPixel.GetAddressOf(), nullptr); // // create input layout // D3D12_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_PER_VERTEX_DATA, 0 } }; UINT numElements = sizeof(layout) / sizeof(layout[0]); // // create an empty root signature // ComPtr<ID3DBlob> pOutBlob, pErrorBlob; D3D12_ROOT_SIGNATURE_DESC descRootSignature; descRootSignature.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pOutBlob.GetAddressOf(), pErrorBlob.GetAddressOf()); mDevice->CreateRootSignature(0, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), IID_PPV_ARGS(mRootSignature.GetAddressOf())); // // create a PSO description // D3D12_GRAPHICS_PIPELINE_STATE_DESC descPso; ZeroMemory(&descPso, sizeof(descPso)); descPso.InputLayout = { layout, numElements }; descPso.pRootSignature = mRootSignature.Get(); descPso.VS = { reinterpret_cast<BYTE*>(blobShaderVert->GetBufferPointer()), blobShaderVert->GetBufferSize() }; descPso.PS = { reinterpret_cast<BYTE*>(blobShaderPixel->GetBufferPointer()), blobShaderPixel->GetBufferSize() }; descPso.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); descPso.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); descPso.DepthStencilState.DepthEnable = FALSE; descPso.DepthStencilState.StencilEnable = FALSE; descPso.SampleMask = UINT_MAX; descPso.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; descPso.NumRenderTargets = 1; descPso.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; descPso.SampleDesc.Count = 1; // // create the actual PSO // mDevice->CreateGraphicsPipelineState(&descPso, IID_PPV_ARGS(mPSO.GetAddressOf())); // // create descriptor heap // D3D12_DESCRIPTOR_HEAP_DESC descHeap = {}; descHeap.NumDescriptors = 1; descHeap.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; descHeap.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; mDevice->CreateDescriptorHeap(&descHeap, IID_PPV_ARGS(mDescriptorHeap.GetAddressOf())); // // create command list // mDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandAllocator.Get(), mPSO.Get(), IID_PPV_ARGS(mCommandList.GetAddressOf())); // // create backbuffer/rendertarget // mSwapChain->GetBuffer(0, IID_PPV_ARGS(mRenderTarget.GetAddressOf())); mDevice->CreateRenderTargetView(mRenderTarget.Get(), nullptr, mDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); // // set the viewport // mViewPort = { 0.0f, 0.0f, static_cast<float>(mWidth), static_cast<float>(mHeight), 0.0f, 1.0f }; // // create scissor rectangle // mRectScissor = { 0, 0, mWidth, mHeight }; // // create geometry for a triangle // VERTEX triangleVerts[] = { { 0.0f, 0.5f, 0.0f,{ 1.0f, 0.0f, 0.0f, 1.0f } }, { 0.45f, -0.5, 0.0f,{ 0.0f, 1.0f, 0.0f, 1.0f } }, { -0.45f, -0.5f, 0.0f,{ 0.0f, 0.0f, 1.0f, 1.0f } } }; // // actually create the vert buffer // Note: using upload heaps to transfer static data like vert buffers is not recommended. // Every time the GPU needs it, the upload heap will be marshalled over. Please read up on Default Heap usage. // An upload heap is used here for code simplicity and because there are very few verts to actually transfer // mDevice->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(3 * sizeof(VERTEX)), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, // Clear value IID_PPV_ARGS(mBufVerts.GetAddressOf())); // // copy the triangle data to the vertex buffer // UINT8* dataBegin; mBufVerts->Map(0, nullptr, reinterpret_cast<void**>(&dataBegin)); memcpy(dataBegin, triangleVerts, sizeof(triangleVerts)); mBufVerts->Unmap(0, nullptr); // // create vertex buffer view // mDescViewBufVert.BufferLocation = mBufVerts->GetGPUVirtualAddress(); mDescViewBufVert.StrideInBytes = sizeof(VERTEX); mDescViewBufVert.SizeInBytes = sizeof(triangleVerts); // // create fencing object // mDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(mFence.GetAddressOf())); mCurrentFence = 1; // // close the command list and use it to execute the initial GPU setup // mCommandList->Close(); ID3D12CommandList* ppCommandLists[] = { mCommandList.Get() }; mCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); // // create event handle // mHandleEvent = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS); // // wait for the command list to execute; we are reusing the same command list in our main loop but for now, // we just want to wait for setup to complete before continuing // waitForGPU(); }
void Window::afterPresent() { waitForGPU(f); }
QImage QD3D12Window::readbackRGBA8888(ID3D12Resource *rt, D3D12_RESOURCE_STATES rtState, ID3D12GraphicsCommandList *commandList) { ComPtr<ID3D12Resource> readbackBuf; D3D12_RESOURCE_DESC rtDesc = rt->GetDesc(); UINT64 textureByteSize = 0; D3D12_PLACED_SUBRESOURCE_FOOTPRINT textureLayout = {}; device()->GetCopyableFootprints(&rtDesc, 0, 1, 0, &textureLayout, Q_NULLPTR, Q_NULLPTR, &textureByteSize); D3D12_HEAP_PROPERTIES heapProp = {}; heapProp.Type = D3D12_HEAP_TYPE_READBACK; D3D12_RESOURCE_DESC bufDesc = {}; bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; bufDesc.Width = textureByteSize; bufDesc.Height = 1; bufDesc.DepthOrArraySize = 1; bufDesc.MipLevels = 1; bufDesc.Format = DXGI_FORMAT_UNKNOWN; bufDesc.SampleDesc.Count = 1; bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; if (FAILED(device()->CreateCommittedResource(&heapProp, D3D12_HEAP_FLAG_NONE, &bufDesc, D3D12_RESOURCE_STATE_COPY_DEST, Q_NULLPTR, IID_PPV_ARGS(&readbackBuf)))) { qWarning("Failed to create committed resource (readback buffer)"); return QImage(); } D3D12_TEXTURE_COPY_LOCATION dstLoc; dstLoc.pResource = readbackBuf.Get(); dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dstLoc.PlacedFootprint = textureLayout; D3D12_TEXTURE_COPY_LOCATION srcLoc; srcLoc.pResource = rt; srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; srcLoc.SubresourceIndex = 0; transitionResource(rt, commandList, rtState, D3D12_RESOURCE_STATE_COPY_SOURCE); commandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, Q_NULLPTR); transitionResource(rt, commandList, D3D12_RESOURCE_STATE_COPY_SOURCE, rtState); commandList->Close(); ID3D12CommandList *commandLists[] = { commandList }; commandQueue()->ExecuteCommandLists(_countof(commandLists), commandLists); QScopedPointer<Fence> f(createFence()); waitForGPU(f.data()); QImage img(rtDesc.Width, rtDesc.Height, QImage::Format_RGBA8888); quint8 *p = Q_NULLPTR; D3D12_RANGE readRange = { 0, 0 }; if (FAILED(readbackBuf->Map(0, &readRange, reinterpret_cast<void **>(&p)))) { qWarning("Mapping the readback buffer failed"); return QImage(); } for (UINT y = 0; y < rtDesc.Height; ++y) { quint8 *dst = img.scanLine(y); memcpy(dst, p, rtDesc.Width * 4); p += textureLayout.Footprint.RowPitch; } readbackBuf->Unmap(0, Q_NULLPTR); return img; }