WIP
This commit is contained in:
@@ -99,9 +99,10 @@
|
||||
"Bash(py:*)",
|
||||
"Bash(\"D:/Project/video-av1/vav2/platforms/windows/tests/red-surface-nvdec/bin/Debug/RedSurfaceNVDECTest.exe\" \"D:/Project/video-av1/sample/simple_test.webm\")",
|
||||
"Bash(\"D:/Project/video-av1/vav2/platforms/windows/tests/red-surface-nvdec/bin/Debug/RedSurfaceNVDECTest.exe\" \"D:/Project/video-av1/sample/test_720p_stripe.webm\")",
|
||||
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"D:/Project/video-av1/vav2/platforms/windows/tests/red-surface-nvdec/RedSurfaceNVDECTest.vcxproj\" //p:Configuration=Debug //p:Platform=x64 //p:RebuildV avCore=true //v:minimal)"
|
||||
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"D:/Project/video-av1/vav2/platforms/windows/tests/red-surface-nvdec/RedSurfaceNVDECTest.vcxproj\" //p:Configuration=Debug //p:Platform=x64 //p:RebuildV avCore=true //v:minimal)",
|
||||
"Bash(\"D:/Project/video-av1/vav2/platforms/windows/tests/large-resolution/bin/Debug/LargeResolutionTest.exe\" \"D:/Project/video-av1/sample/test_2160p_av1.webm\")"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{B2C3D4E5-6789-ABCD-EF01-23456789ABCD}</ProjectGuid>
|
||||
<RootNamespace>LargeResolutionTest</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(ProjectDir)bin\$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)obj\$(Configuration)\</IntDir>
|
||||
<TargetName>LargeResolutionTest</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\..\vavcore\include</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\vavcore\lib</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>VavCore-debug.lib;d3d12.lib;dxgi.lib;kernel32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>echo Copying VavCore DLL...
|
||||
copy "$(ProjectDir)..\..\vavcore\lib\VavCore-debug.dll" "$(TargetDir)VavCore-debug.dll"
|
||||
echo Done.</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\main.cpp" />
|
||||
<ClCompile Include="src\D3D12Manager.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\D3D12Manager.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,341 @@
|
||||
#include "D3D12Manager.h"
|
||||
#include <stdio.h>
|
||||
|
||||
D3D12Manager::D3D12Manager()
|
||||
: m_device(nullptr)
|
||||
, m_command_queue(nullptr)
|
||||
, m_command_allocator(nullptr)
|
||||
, m_command_list(nullptr)
|
||||
, m_fence(nullptr)
|
||||
, m_fence_value(0)
|
||||
, m_fence_event(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
D3D12Manager::~D3D12Manager()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
bool D3D12Manager::Initialize()
|
||||
{
|
||||
if (!CreateDevice()) {
|
||||
printf("[D3D12Manager] Failed to create D3D12 device\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateCommandObjects()) {
|
||||
printf("[D3D12Manager] Failed to create command objects\n");
|
||||
Cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("[D3D12Manager] Initialized successfully\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D12Manager::Cleanup()
|
||||
{
|
||||
WaitForGPU();
|
||||
|
||||
if (m_fence_event) {
|
||||
CloseHandle(m_fence_event);
|
||||
m_fence_event = nullptr;
|
||||
}
|
||||
|
||||
if (m_fence) {
|
||||
m_fence->Release();
|
||||
m_fence = nullptr;
|
||||
}
|
||||
|
||||
if (m_command_list) {
|
||||
m_command_list->Release();
|
||||
m_command_list = nullptr;
|
||||
}
|
||||
|
||||
if (m_command_allocator) {
|
||||
m_command_allocator->Release();
|
||||
m_command_allocator = nullptr;
|
||||
}
|
||||
|
||||
if (m_command_queue) {
|
||||
m_command_queue->Release();
|
||||
m_command_queue = nullptr;
|
||||
}
|
||||
|
||||
if (m_device) {
|
||||
m_device->Release();
|
||||
m_device = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool D3D12Manager::CreateDevice()
|
||||
{
|
||||
// Create DXGI factory
|
||||
IDXGIFactory4* factory = nullptr;
|
||||
HRESULT hr = CreateDXGIFactory2(0, IID_PPV_ARGS(&factory));
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to create DXGI factory: 0x%08X\n", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enumerate adapters and find the first hardware adapter
|
||||
IDXGIAdapter1* adapter = nullptr;
|
||||
for (UINT i = 0; factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; ++i) {
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
adapter->GetDesc1(&desc);
|
||||
|
||||
// Skip software adapter
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
|
||||
adapter->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to create D3D12 device
|
||||
hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
||||
if (SUCCEEDED(hr)) {
|
||||
printf("[D3D12Manager] Created D3D12 device on adapter: %ls\n", desc.Description);
|
||||
adapter->Release();
|
||||
factory->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
adapter->Release();
|
||||
}
|
||||
|
||||
factory->Release();
|
||||
printf("[D3D12Manager] No suitable D3D12 adapter found\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool D3D12Manager::CreateCommandObjects()
|
||||
{
|
||||
// Create command queue
|
||||
D3D12_COMMAND_QUEUE_DESC queue_desc = {};
|
||||
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
|
||||
HRESULT hr = m_device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&m_command_queue));
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to create command queue: 0x%08X\n", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create command allocator
|
||||
hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
IID_PPV_ARGS(&m_command_allocator));
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to create command allocator: 0x%08X\n", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create command list
|
||||
hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
m_command_allocator, nullptr, IID_PPV_ARGS(&m_command_list));
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to create command list: 0x%08X\n", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Close command list (we'll reset it when needed)
|
||||
m_command_list->Close();
|
||||
|
||||
// Create fence
|
||||
hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to create fence: 0x%08X\n", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fence_value = 1;
|
||||
|
||||
// Create fence event
|
||||
m_fence_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
if (m_fence_event == nullptr) {
|
||||
printf("[D3D12Manager] Failed to create fence event\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D12Manager::WaitForGPU()
|
||||
{
|
||||
if (!m_command_queue || !m_fence || !m_fence_event) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Signal the fence
|
||||
const UINT64 fence = m_fence_value;
|
||||
m_command_queue->Signal(m_fence, fence);
|
||||
m_fence_value++;
|
||||
|
||||
// Wait for fence
|
||||
if (m_fence->GetCompletedValue() < fence) {
|
||||
m_fence->SetEventOnCompletion(fence, m_fence_event);
|
||||
WaitForSingleObject(m_fence_event, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
ID3D12Resource* D3D12Manager::CreateNV12Texture(uint32_t width, uint32_t height)
|
||||
{
|
||||
D3D12_RESOURCE_DESC desc = {};
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_NV12;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
|
||||
D3D12_HEAP_PROPERTIES heap_props = {};
|
||||
heap_props.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
|
||||
ID3D12Resource* texture = nullptr;
|
||||
HRESULT hr = m_device->CreateCommittedResource(
|
||||
&heap_props,
|
||||
D3D12_HEAP_FLAG_SHARED,
|
||||
&desc,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to create NV12 texture: 0x%08X\n", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
uint8_t* D3D12Manager::ReadbackTexture(ID3D12Resource* texture, uint32_t width, uint32_t height)
|
||||
{
|
||||
// Get texture description
|
||||
D3D12_RESOURCE_DESC desc = texture->GetDesc();
|
||||
|
||||
// Calculate layout for both Y and UV planes
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[2];
|
||||
UINT num_rows[2] = { 0 };
|
||||
UINT64 row_sizes[2] = { 0 };
|
||||
UINT64 total_bytes = 0;
|
||||
|
||||
m_device->GetCopyableFootprints(&desc, 0, 2, 0, layouts, num_rows, row_sizes, &total_bytes);
|
||||
|
||||
// Create readback buffer
|
||||
D3D12_HEAP_PROPERTIES readback_heap_props = {};
|
||||
readback_heap_props.Type = D3D12_HEAP_TYPE_READBACK;
|
||||
|
||||
D3D12_RESOURCE_DESC readback_desc = {};
|
||||
readback_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
readback_desc.Width = total_bytes;
|
||||
readback_desc.Height = 1;
|
||||
readback_desc.DepthOrArraySize = 1;
|
||||
readback_desc.MipLevels = 1;
|
||||
readback_desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
readback_desc.SampleDesc.Count = 1;
|
||||
readback_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
|
||||
ID3D12Resource* readback_buffer = nullptr;
|
||||
HRESULT hr = m_device->CreateCommittedResource(
|
||||
&readback_heap_props,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&readback_desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
nullptr,
|
||||
IID_PPV_ARGS(&readback_buffer));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to create readback buffer: 0x%08X\n", hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Reset command list
|
||||
m_command_allocator->Reset();
|
||||
m_command_list->Reset(m_command_allocator, nullptr);
|
||||
|
||||
// Transition texture to COPY_SOURCE
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Transition.pResource = texture;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
m_command_list->ResourceBarrier(1, &barrier);
|
||||
|
||||
// Copy Y plane (subresource 0)
|
||||
D3D12_TEXTURE_COPY_LOCATION src_y = {};
|
||||
src_y.pResource = texture;
|
||||
src_y.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
src_y.SubresourceIndex = 0;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dst_y = {};
|
||||
dst_y.pResource = readback_buffer;
|
||||
dst_y.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
dst_y.PlacedFootprint = layouts[0];
|
||||
|
||||
m_command_list->CopyTextureRegion(&dst_y, 0, 0, 0, &src_y, nullptr);
|
||||
|
||||
// Copy UV plane (subresource 1)
|
||||
D3D12_TEXTURE_COPY_LOCATION src_uv = {};
|
||||
src_uv.pResource = texture;
|
||||
src_uv.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
src_uv.SubresourceIndex = 1;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dst_uv = {};
|
||||
dst_uv.pResource = readback_buffer;
|
||||
dst_uv.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
dst_uv.PlacedFootprint = layouts[1];
|
||||
|
||||
m_command_list->CopyTextureRegion(&dst_uv, 0, 0, 0, &src_uv, nullptr);
|
||||
|
||||
// Transition texture back to COMMON
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON;
|
||||
m_command_list->ResourceBarrier(1, &barrier);
|
||||
|
||||
// Execute command list
|
||||
m_command_list->Close();
|
||||
ID3D12CommandList* cmd_lists[] = { m_command_list };
|
||||
m_command_queue->ExecuteCommandLists(1, cmd_lists);
|
||||
|
||||
// Wait for GPU
|
||||
WaitForGPU();
|
||||
|
||||
// Map readback buffer
|
||||
void* mapped_data = nullptr;
|
||||
D3D12_RANGE read_range = { 0, static_cast<SIZE_T>(total_bytes) };
|
||||
hr = readback_buffer->Map(0, &read_range, &mapped_data);
|
||||
if (FAILED(hr)) {
|
||||
printf("[D3D12Manager] Failed to map readback buffer: 0x%08X\n", hr);
|
||||
readback_buffer->Release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Allocate CPU buffer (NV12 format: Y plane + UV plane)
|
||||
uint32_t y_size = width * height;
|
||||
uint32_t uv_size = width * (height / 2);
|
||||
uint8_t* cpu_buffer = new uint8_t[y_size + uv_size];
|
||||
|
||||
// Copy Y plane
|
||||
uint8_t* src_y_data = static_cast<uint8_t*>(mapped_data) + layouts[0].Offset;
|
||||
uint8_t* dst_y_data = cpu_buffer;
|
||||
for (UINT row = 0; row < height; ++row) {
|
||||
memcpy(dst_y_data + row * width, src_y_data + row * layouts[0].Footprint.RowPitch, width);
|
||||
}
|
||||
|
||||
// Copy UV plane
|
||||
uint8_t* src_uv_data = static_cast<uint8_t*>(mapped_data) + layouts[1].Offset;
|
||||
uint8_t* dst_uv_data = cpu_buffer + y_size;
|
||||
for (UINT row = 0; row < height / 2; ++row) {
|
||||
memcpy(dst_uv_data + row * width, src_uv_data + row * layouts[1].Footprint.RowPitch, width);
|
||||
}
|
||||
|
||||
// Unmap and release readback buffer
|
||||
readback_buffer->Unmap(0, nullptr);
|
||||
readback_buffer->Release();
|
||||
|
||||
return cpu_buffer;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class D3D12Manager
|
||||
{
|
||||
public:
|
||||
D3D12Manager();
|
||||
~D3D12Manager();
|
||||
|
||||
bool Initialize();
|
||||
void Cleanup();
|
||||
|
||||
// Create NV12 texture for CUDA interop
|
||||
ID3D12Resource* CreateNV12Texture(uint32_t width, uint32_t height);
|
||||
|
||||
// Readback D3D12 texture to CPU memory
|
||||
uint8_t* ReadbackTexture(ID3D12Resource* texture, uint32_t width, uint32_t height);
|
||||
|
||||
// Get D3D12 device
|
||||
ID3D12Device* GetDevice() const { return m_device; }
|
||||
|
||||
private:
|
||||
ID3D12Device* m_device;
|
||||
ID3D12CommandQueue* m_command_queue;
|
||||
ID3D12CommandAllocator* m_command_allocator;
|
||||
ID3D12GraphicsCommandList* m_command_list;
|
||||
ID3D12Fence* m_fence;
|
||||
UINT64 m_fence_value;
|
||||
HANDLE m_fence_event;
|
||||
|
||||
bool CreateDevice();
|
||||
bool CreateCommandObjects();
|
||||
void WaitForGPU();
|
||||
};
|
||||
222
vav2/platforms/windows/tests/large-resolution/src/main.cpp
Normal file
222
vav2/platforms/windows/tests/large-resolution/src/main.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <VavCore/VavCore.h>
|
||||
#include "D3D12Manager.h"
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
struct FrameTask {
|
||||
int frame_index;
|
||||
ID3D12Resource* texture;
|
||||
VavCoreVideoFrame frame;
|
||||
VavCoreResult result;
|
||||
uint8_t* cpu_buffer;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
printf("[LargeResolutionTest] Starting test...\n");
|
||||
|
||||
// Parse command line arguments
|
||||
if (argc < 2) {
|
||||
printf("[ERROR] Usage: LargeResolutionTest.exe <video_file_path>\n");
|
||||
printf("[INFO] Test videos:\n");
|
||||
printf(" - D:/Project/video-av1/sample/test_2160p_av1.webm\n");
|
||||
printf(" - D:/Project/video-av1/sample/test_1080p_stripe.webm\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* video_path = argv[1];
|
||||
printf("[LargeResolutionTest] Video: %s\n", video_path);
|
||||
|
||||
// Step 1: Initialize VavCore
|
||||
printf("\n[Step 1] Initializing VavCore...\n");
|
||||
VavCoreResult result = vavcore_initialize();
|
||||
if (result != VAVCORE_SUCCESS) {
|
||||
printf("[ERROR] Failed to initialize VavCore: error code %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
printf("[OK] VavCore initialized successfully\n");
|
||||
|
||||
// Step 2: Create D3D12 device (headless)
|
||||
printf("\n[Step 2] Creating D3D12 device...\n");
|
||||
D3D12Manager d3d12;
|
||||
if (!d3d12.Initialize()) {
|
||||
printf("[ERROR] Failed to create D3D12 device\n");
|
||||
vavcore_cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("[OK] D3D12 device created\n");
|
||||
|
||||
// Step 3: Create VavCore player
|
||||
printf("\n[Step 3] Creating VavCore player...\n");
|
||||
VavCorePlayer* player = vavcore_create_player();
|
||||
if (!player) {
|
||||
printf("[ERROR] Failed to create VavCore player\n");
|
||||
d3d12.Cleanup();
|
||||
vavcore_cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("[OK] VavCore player created\n");
|
||||
|
||||
// Step 4: Set decoder type to NVDEC explicitly
|
||||
printf("\n[Step 4] Setting decoder type to NVDEC...\n");
|
||||
result = vavcore_set_decoder_type(player, VAVCORE_DECODER_NVDEC);
|
||||
if (result != VAVCORE_SUCCESS) {
|
||||
printf("[ERROR] Failed to set decoder type: error code %d\n", result);
|
||||
vavcore_destroy_player(player);
|
||||
d3d12.Cleanup();
|
||||
vavcore_cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("[OK] Decoder type set to NVDEC\n");
|
||||
|
||||
// Step 5: Set D3D12 device for zero-copy
|
||||
printf("\n[Step 5] Setting D3D12 device for VavCore...\n");
|
||||
result = vavcore_set_d3d_device(player, d3d12.GetDevice(), VAVCORE_SURFACE_D3D12_RESOURCE);
|
||||
if (result != VAVCORE_SUCCESS) {
|
||||
printf("[ERROR] Failed to set D3D12 device: error code %d\n", result);
|
||||
vavcore_destroy_player(player);
|
||||
d3d12.Cleanup();
|
||||
vavcore_cleanup();
|
||||
return 1;
|
||||
}
|
||||
printf("[OK] D3D12 device set for VavCore\n");
|
||||
|
||||
// Step 6: Open video file
|
||||
printf("\n[Step 6] Opening video file...\n");
|
||||
result = vavcore_open_file(player, video_path);
|
||||
if (result != VAVCORE_SUCCESS) {
|
||||
printf("[ERROR] Failed to open video file: error code %d\n", result);
|
||||
vavcore_destroy_player(player);
|
||||
d3d12.Cleanup();
|
||||
vavcore_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get video metadata
|
||||
VavCoreVideoMetadata metadata = {};
|
||||
result = vavcore_get_metadata(player, &metadata);
|
||||
if (result != VAVCORE_SUCCESS) {
|
||||
printf("[ERROR] Failed to get video metadata: error code %d\n", result);
|
||||
vavcore_close_file(player);
|
||||
vavcore_destroy_player(player);
|
||||
d3d12.Cleanup();
|
||||
vavcore_cleanup();
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("[OK] Video opened: %dx%d, %.2f fps, %llu frames\n",
|
||||
metadata.width, metadata.height, metadata.frame_rate, (unsigned long long)metadata.total_frames);
|
||||
printf("[LargeResolutionTest] Decoder: NVDEC (explicit)\n");
|
||||
printf("[LargeResolutionTest] Surface: D3D12\n");
|
||||
|
||||
// Step 7: Continuous frame decoding (limited to ~10 seconds)
|
||||
const int MAX_FRAMES = 300; // ~10 seconds at 30fps
|
||||
printf("\n[Step 7] Decoding video (limited to %d frames for testing)...\n\n", MAX_FRAMES);
|
||||
printf("[INFO] NVDEC pipeline priming: Calling decode continuously\n");
|
||||
printf("[INFO] First 2 frames will be skipped for priming\n");
|
||||
printf("[INFO] Total frames in video: %llu\n\n", (unsigned long long)metadata.total_frames);
|
||||
|
||||
int decode_errors = 0;
|
||||
int successful_decodes = 0;
|
||||
int frame_index = 0;
|
||||
|
||||
// Performance measurement
|
||||
auto start_time = high_resolution_clock::now();
|
||||
auto last_report_time = start_time;
|
||||
int frames_since_last_report = 0;
|
||||
|
||||
// Continuous decode loop - decode limited frames
|
||||
while (!vavcore_is_end_of_file(player) && frame_index < MAX_FRAMES) {
|
||||
// Create NV12 texture
|
||||
ID3D12Resource* texture = d3d12.CreateNV12Texture(metadata.width, metadata.height);
|
||||
if (!texture) {
|
||||
printf("[ERROR] Failed to create texture for frame %d\n", frame_index);
|
||||
decode_errors++;
|
||||
frame_index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Decode frame to D3D12 surface
|
||||
VavCoreVideoFrame frame;
|
||||
VavCoreResult result = vavcore_decode_to_surface(
|
||||
player,
|
||||
VAVCORE_SURFACE_D3D12_RESOURCE,
|
||||
texture,
|
||||
&frame
|
||||
);
|
||||
|
||||
if (result != VAVCORE_SUCCESS) {
|
||||
printf("Frame %3d: Decode failed (error code %d)\n", frame_index, result);
|
||||
texture->Release();
|
||||
decode_errors++;
|
||||
frame_index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip first 2 frames (priming)
|
||||
if (frame_index < 2) {
|
||||
printf("Frame %3d: PRIMING (decoded but skipped)\n", frame_index);
|
||||
} else {
|
||||
successful_decodes++;
|
||||
frames_since_last_report++;
|
||||
|
||||
// Print performance report every 30 frames
|
||||
if (frame_index % 30 == 0) {
|
||||
auto current_time = high_resolution_clock::now();
|
||||
auto elapsed_ms = duration_cast<milliseconds>(current_time - last_report_time).count();
|
||||
double fps = (frames_since_last_report * 1000.0) / elapsed_ms;
|
||||
|
||||
printf("Frame %3d: Decoded successfully (progress: %d/%llu, FPS: %.1f)\n",
|
||||
frame_index, frame_index, (unsigned long long)metadata.total_frames, fps);
|
||||
|
||||
last_report_time = current_time;
|
||||
frames_since_last_report = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup texture immediately to prevent memory buildup
|
||||
texture->Release();
|
||||
frame_index++;
|
||||
}
|
||||
|
||||
// Calculate overall performance
|
||||
auto end_time = high_resolution_clock::now();
|
||||
auto total_ms = duration_cast<milliseconds>(end_time - start_time).count();
|
||||
double overall_fps = (successful_decodes * 1000.0) / total_ms;
|
||||
double decode_time_per_frame = (double)total_ms / successful_decodes;
|
||||
|
||||
// Step 8: Print results
|
||||
printf("\n[LargeResolutionTest] Results:\n");
|
||||
printf(" Resolution: %dx%d\n", metadata.width, metadata.height);
|
||||
printf(" Total frames in video: %llu\n", (unsigned long long)metadata.total_frames);
|
||||
printf(" Total frames decoded: %d\n", frame_index);
|
||||
printf(" Priming frames: 2\n");
|
||||
printf(" Successful decodes (after priming): %d\n", successful_decodes);
|
||||
printf(" Decode errors: %d\n", decode_errors);
|
||||
printf("\n[LargeResolutionTest] Performance:\n");
|
||||
printf(" Total time: %.2f seconds\n", total_ms / 1000.0);
|
||||
printf(" Average FPS: %.1f fps\n", overall_fps);
|
||||
printf(" Average decode time per frame: %.2f ms\n", decode_time_per_frame);
|
||||
printf(" Target FPS (30fps): %s\n", overall_fps >= 30.0 ? "PASS" : "FAIL");
|
||||
|
||||
bool test_passed = (decode_errors == 0 && successful_decodes == (frame_index - 2) && overall_fps >= 30.0);
|
||||
|
||||
if (test_passed) {
|
||||
printf("\n[LargeResolutionTest] Test SUCCESS - All frames decoded successfully\n");
|
||||
} else {
|
||||
printf("\n[LargeResolutionTest] Test FAILED - Some frames failed to decode\n");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
vavcore_close_file(player);
|
||||
vavcore_destroy_player(player);
|
||||
d3d12.Cleanup();
|
||||
vavcore_cleanup();
|
||||
|
||||
return test_passed ? 0 : 1;
|
||||
}
|
||||
@@ -32,6 +32,8 @@ bool D3D12SurfaceHandler::CopyNV12Frame(CUdeviceptr src_frame,
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGF_DEBUG("[D3D12SurfaceHandler] dst_ptr (base from ExternalMemory)=0x%llX", dst_ptr);
|
||||
|
||||
// Get D3D12 texture layout for both Y and UV planes
|
||||
D3D12_RESOURCE_DESC desc = dst_texture->GetDesc();
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[2];
|
||||
@@ -55,6 +57,10 @@ bool D3D12SurfaceHandler::CopyNV12Frame(CUdeviceptr src_frame,
|
||||
LOGF_DEBUG("[D3D12SurfaceHandler] Texture descriptor: allocated height=%u (logical video height=%u)",
|
||||
(uint32_t)desc.Height, height);
|
||||
|
||||
LOGF_DEBUG("[D3D12SurfaceHandler] Y plane offset: 0x%llX", layouts[0].Offset);
|
||||
LOGF_DEBUG("[D3D12SurfaceHandler] UV plane offset: 0x%llX", layouts[1].Offset);
|
||||
LOGF_DEBUG("[D3D12SurfaceHandler] Total texture size: %llu bytes", total_bytes);
|
||||
|
||||
LOGF_DEBUG("[D3D12SurfaceHandler] Y plane: width=%u, height=%u, srcPitch=%u, dstPitch=%u, rows=%u",
|
||||
width, height, src_pitch, y_dst_pitch, y_rows);
|
||||
|
||||
|
||||
@@ -92,6 +92,9 @@ bool ExternalMemoryCache::ImportD3D12Resource(ID3D12Resource* resource,
|
||||
D3D12_RESOURCE_DESC desc = resource->GetDesc();
|
||||
D3D12_RESOURCE_ALLOCATION_INFO alloc_info = m_device->GetResourceAllocationInfo(0, 1, &desc);
|
||||
|
||||
LOGF_DEBUG("[ExternalMemoryCache] Resource allocation info: size=%llu, alignment=%llu",
|
||||
alloc_info.SizeInBytes, alloc_info.Alignment);
|
||||
|
||||
// Import external memory
|
||||
cudaExternalMemoryHandleDesc mem_desc = {};
|
||||
mem_desc.type = cudaExternalMemoryHandleTypeD3D12Resource; // Use resource type for individual textures
|
||||
@@ -126,6 +129,9 @@ bool ExternalMemoryCache::ImportD3D12Resource(ID3D12Resource* resource,
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGF_DEBUG("[ExternalMemoryCache] Successfully mapped external memory: device_ptr=0x%llX, size=%llu",
|
||||
device_ptr, buffer_desc.size);
|
||||
|
||||
*out_ext_mem = external_memory;
|
||||
*out_ptr = device_ptr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user