bool BinkDecoder::Open(const std::string &fileName) { // open the file (read only) file.Open(fileName); if (!file.Is_Open()) { BinkCommon::LogError("Can't open file " + fileName); return false; } // check the file signature signature = file.ReadUint32BE(); if ((signature != kBIKfID) && (signature != kBIKgID) && (signature != kBIKhID) && (signature != kBIKiID)) { BinkCommon::LogError("Unknown Bink signature"); return false; } fileSize = file.ReadUint32LE() + 8; nFrames = file.ReadUint32LE(); if (nFrames > 1000000) { BinkCommon::LogError("Invalid header, more than 1000000 frames"); return false; } largestFrameSize = file.ReadUint32LE(); if (largestFrameSize > fileSize) { BinkCommon::LogError("Largest frame size is greater than file size"); return false; } // skip some unknown data file.Skip(4); frameWidth = file.ReadUint32LE(); frameHeight = file.ReadUint32LE(); fpsDividend = file.ReadUint32LE(); fpsDivider = file.ReadUint32LE(); videoFlags = file.ReadUint32LE(); nAudioTracks = file.ReadUint32LE(); // audio is available if (nAudioTracks) { // skip some useless values (unknown and audio channels) file.Skip(4 * nAudioTracks); for (uint32_t i = 0; i < nAudioTracks; i++) { uint16_t sampleRate = file.ReadUint16LE(); uint16_t flags = file.ReadUint16LE(); CreateAudioTrack(sampleRate, flags); } // skip the audio track IDs file.Skip(4 * nAudioTracks); } // read the video frames frames.resize(nFrames); uint32_t pos, nextPos; nextPos = file.ReadUint32LE(); for (uint32_t i = 0; i < nFrames; i++) { pos = nextPos; if (i == nFrames - 1) { nextPos = fileSize; frames[i].keyFrame = 0; } else { nextPos = file.ReadUint32LE(); frames[i].keyFrame = pos & 1; } pos &= ~1; nextPos &= ~1; frames[i].offset = pos; frames[i].size = nextPos - pos; } // determine buffer sizes for audio tracks file.Seek(frames[0].offset); for (uint32_t trackIndex = 0; trackIndex < audioTracks.size(); trackIndex++) { // check for audio uint32_t audioPacketSize = file.ReadUint32LE(); if (audioPacketSize >= 4) { // size in bytes of largest decoded audio uint32_t reportedSize = file.ReadUint32LE(); AudioTrack *track = audioTracks[trackIndex]; // size in bytes track->bufferSize = reportedSize; track->buffer = new uint8_t[reportedSize]; // skip to next audio track (and -4 for reportedSize int we read) file.Skip(audioPacketSize-4); } else { file.Skip(audioPacketSize); } } hasAlpha = videoFlags & kFlagAlpha; swapPlanes = signature >= kBIKhID; InitBundles(); InitTrees(); uint32_t width = frameWidth; uint32_t height = frameHeight; // init plane memory Plane newPlane; planes.push_back(newPlane); // luma plane planes.back().Init(width, height); // chroma planes width /= 2; height /= 2; // 1 planes.push_back(newPlane); planes.back().Init(width, height); // 2 planes.push_back(newPlane); planes.back().Init(width, height); // alpha plane if (hasAlpha) { width *= 2; height *= 2; planes.push_back(newPlane); planes.back().Init(width, height); } return true; }
void AppTest::LoadAssets() { //Load and compile the shaders D3D12Shader vertShader = D3D12Shader(ShaderType::Vertex, L"TestShader.hlsl", "VS"); D3D12Shader pixelShader = D3D12Shader(ShaderType::Pixel, L"TestShader.hlsl", "PS"); std::vector<ShaderMacro> macros; macros.push_back({ "BOXCOLOR", "float4(1.0f, 1.0f, 1.0f, 1.0f)" }); vertShader.Compile(¯os[0], static_cast<uint32_t>(macros.size())); pixelShader.Compile(¯os[0], static_cast<uint32_t>(macros.size())); D3D12_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA , 0} }; UINT numElements = ARRAYSIZE(layout); //Create root signiture with one root constant buffer view D3D12_ROOT_PARAMETER param; D3D12_DESCRIPTOR_RANGE descriptorRange = {}; if (UseRootLevelCBV) { param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; param.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; param.Descriptor = { 0, 0 }; } else { //Used for if you need non root level constant buffer views //This is somewhat slower than switching out a root level CBV descriptorRange.BaseShaderRegister = 0; descriptorRange.NumDescriptors = 1; descriptorRange.OffsetInDescriptorsFromTableStart = 0; descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; descriptorRange.RegisterSpace = 0; param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; param.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; param.DescriptorTable.NumDescriptorRanges = 1; param.DescriptorTable.pDescriptorRanges = &descriptorRange; } ComPtr<ID3D10Blob> pOutBlob, pErrorBlob; D3D12_ROOT_SIGNATURE_DESC rootSigDesc; rootSigDesc.NumParameters = 1; rootSigDesc.pParameters = ¶m; rootSigDesc.NumStaticSamplers = 0; rootSigDesc.pStaticSamplers = nullptr; rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; CHK(D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, pOutBlob.GetAddressOf(), pErrorBlob.GetAddressOf())); CHK(Device->CreateRootSignature(0, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), IID_PPV_ARGS(RootSignature.GetAddressOf()))); //Create the PSO D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc; ZeroMemory(&psoDesc, sizeof(psoDesc)); psoDesc.InputLayout = { layout, numElements }; psoDesc.pRootSignature = RootSignature.Get(); psoDesc.VS = { reinterpret_cast<BYTE*>(vertShader.GetByteCodePtr()), vertShader.GetSize() }; psoDesc.PS = { reinterpret_cast<BYTE*>(pixelShader.GetByteCodePtr()), pixelShader.GetSize() }; psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);; psoDesc.RasterizerState.FrontCounterClockwise = true; //Using RH coordinate system psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); psoDesc.DepthStencilState.DepthEnable = true; psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL; psoDesc.DepthStencilState.StencilEnable = false; psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; psoDesc.SampleDesc.Count = 1; psoDesc.SampleDesc.Quality = 0; CHK(Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(PSO.GetAddressOf()))); //Create descriptor heap D3D12_DESCRIPTOR_HEAP_DESC descHeapDesc = {}; descHeapDesc.NumDescriptors = 1; descHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; descHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; CHK(Device->CreateDescriptorHeap(&descHeapDesc, IID_PPV_ARGS(DescriptorHeap.GetAddressOf()))); D3D12_DESCRIPTOR_HEAP_DESC DSVDescHeapDesc = {}; DSVDescHeapDesc.NumDescriptors = 1; DSVDescHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; DSVDescHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; CHK(Device->CreateDescriptorHeap(&DSVDescHeapDesc, IID_PPV_ARGS(DSVDescriptorHeap.GetAddressOf()))); CHK(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocator.Get(), PSO.Get(), IID_PPV_ARGS(CommandList.GetAddressOf()))); //Create the command lists for each thread for (unsigned int i = 0; i < ThreadCount; i++) { CHK(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocatorArray[i].Get(), PSO.Get(), IID_PPV_ARGS(CommandListArray[i].GetAddressOf()))); CommandListArray[i].Get()->Close(); } //Create back buffer and render target CHK(SwapChain->GetBuffer(0, IID_PPV_ARGS(RenderTarget.GetAddressOf()))); Device->CreateRenderTargetView(RenderTarget.Get(), nullptr, DescriptorHeap->GetCPUDescriptorHandleForHeapStart()); Viewport.TopLeftX = 0.0f; Viewport.TopLeftY = 0.0f; Viewport.Width = static_cast<float>(ViewportWidth); Viewport.Height = static_cast<float>(ViewportHeight); Viewport.MinDepth = 0.0f; Viewport.MaxDepth = 1.0f; RectScissor.left = 0; RectScissor.top = 0; RectScissor.right = ViewportWidth; RectScissor.bottom = ViewportHeight; //Create depth buffer D3D12_RESOURCE_DESC depthResDesc = CD3DX12_RESOURCE_DESC::Tex2D( DXGI_FORMAT_R32_TYPELESS, ViewportWidth, ViewportHeight, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN); D3D12_CLEAR_VALUE dsvClearValue; dsvClearValue.Format = DXGI_FORMAT_D32_FLOAT; dsvClearValue.DepthStencil.Depth = 1.0f; dsvClearValue.DepthStencil.Stencil = 0; CHK(Device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &depthResDesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &dsvClearValue, IID_PPV_ARGS(DepthBufferTexture.GetAddressOf()))); DepthBufferTexture->SetName(L"Depth Buffer"); D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; dsvDesc.Format = DXGI_FORMAT_D32_FLOAT; dsvDesc.Texture2D.MipSlice = 0; dsvDesc.Flags = D3D12_DSV_FLAG_NONE; Device->CreateDepthStencilView(DepthBufferTexture.Get(), &dsvDesc, DSVDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); //Allocate buffer for all constant buffers PerObjectConstantBuffers.Init(BoxCount, sizeof(CBPerObject), Device.Get()); //Create the constant buffer descriptor heap and populate it if (!UseRootLevelCBV) { ConstantBufferDescriptorHeap = std::make_unique<D3D12RHIDescriptorHeap>(BoxCount, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, true); HRESULT hr = ConstantBufferDescriptorHeap->Init(Device.Get()); assert(SUCCEEDED(hr)); D3D12_CONSTANT_BUFFER_VIEW_DESC constantBufferViewDesc = {}; constantBufferViewDesc.SizeInBytes = PerObjectConstantBuffers.GetAlignedStride(); D3D12_CPU_DESCRIPTOR_HANDLE cpuDescriptorHandle; for (unsigned int i = 0; i < BoxCount; i++) { cpuDescriptorHandle.ptr = reinterpret_cast<size_t>(ConstantBufferDescriptorHeap->GetDescriptorCPUPtr(i)); constantBufferViewDesc.BufferLocation = PerObjectConstantBuffers.GetGPUHandle(i); Device->CreateConstantBufferView(&constantBufferViewDesc, cpuDescriptorHandle); } } //Generate mesh GeometryGenerator::SimpleMesh shapeMesh; GeometryGenerator::CreateBox(1.0f, 1.0f, 1.0f, shapeMesh); //GeometryGenerator::CreateSphere(1.0f, 10, 10, shapeMesh); IndexCount = static_cast<uint32_t>(shapeMesh.Indices.size()); //Copy vertex data to buffer //This should be put into its own job system using the copy engine eventually Device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(sizeof(GeometryGenerator::SimpleVertex) * shapeMesh.Vertices.size()), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(VertBuffer.GetAddressOf())); Device->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(sizeof(uint32_t) * shapeMesh.Indices.size()), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(IndexBuffer.GetAddressOf())); UINT8* dataBegin; VertBuffer->Map(0, nullptr, reinterpret_cast<void**>(&dataBegin)); memcpy(dataBegin, &shapeMesh.Vertices[0], sizeof(GeometryGenerator::SimpleVertex) * shapeMesh.Vertices.size()); VertBuffer->Unmap(0, nullptr); IndexBuffer->Map(0, nullptr, reinterpret_cast<void**>(&dataBegin)); memcpy(dataBegin, &shapeMesh.Indices[0], sizeof(uint32_t) * shapeMesh.Indices.size()); IndexBuffer->Unmap(0, nullptr); //Create vertex buffer view DescViewBufVert.BufferLocation = VertBuffer->GetGPUVirtualAddress(); DescViewBufVert.StrideInBytes = sizeof(GeometryGenerator::SimpleVertex); DescViewBufVert.SizeInBytes = static_cast<UINT>(sizeof(GeometryGenerator::SimpleVertex) * shapeMesh.Vertices.size()); DescViewBufIndex.BufferLocation = IndexBuffer->GetGPUVirtualAddress(); DescViewBufIndex.Format = DXGI_FORMAT_R32_UINT; DescViewBufIndex.SizeInBytes = static_cast<UINT>(sizeof(uint32_t) * shapeMesh.Indices.size()); //Create fencing object Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(Fence.GetAddressOf())); CurrentFence = 1; //Initialize bundles for drawing if (UseBundles) { InitBundles(); } //Close the command list and use it to execute the GPU setup CommandList->Close(); ID3D12CommandList* ppCommandLists[] = { CommandList.Get() }; CommandQueue->ExecuteCommandLists(1, ppCommandLists); HandleEvent = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); WaitForGPU(); }