WIP
This commit is contained in:
@@ -91,7 +91,10 @@
|
||||
"Bash(tasklist)",
|
||||
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" \"D:/Project/video-av1/vav2/platforms/windows/applications/vav2player/Vav2Player/Vav2Player.vcxproj\" //p:Configuration=Debug //p:Platform=x64 //t:Clean)",
|
||||
"Bash(./Vav2Player.exe)",
|
||||
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal)"
|
||||
"Bash(\"/c/Program Files/Microsoft Visual Studio/2022/Community/MSBuild/Current/Bin/MSBuild.exe\" Vav2Player.vcxproj //p:Configuration=Debug //p:Platform=x64 //v:minimal)",
|
||||
"Bash(git checkout:*)",
|
||||
"Bash(python:*)",
|
||||
"Bash(\"C:\\Users\\emocr\\AppData\\Local\\Microsoft\\WindowsApps\\python.exe\" fix_logf.py)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
@@ -51,6 +51,25 @@ size_t required_size = frame.width * frame.height * 4;
|
||||
// [ERROR] Failed to initialize D3D12 device
|
||||
```
|
||||
|
||||
### 🧪 **테스트 코드 규칙 (REQUIRED)**
|
||||
**🚨 중요**: 테스트 코드는 **절대로 프로덕션 코드에 작성하지 않습니다**.
|
||||
|
||||
#### 금지 사항
|
||||
- ❌ `App.xaml.cpp`에 테스트 함수 추가 금지
|
||||
- ❌ `MainWindow.xaml.cpp`에 테스트 코드 추가 금지
|
||||
- ❌ 프로덕션 클래스에 `Test*()` 함수 추가 금지
|
||||
- ❌ 프로덕션 코드에 임시 검증 로직 추가 금지
|
||||
|
||||
#### 테스트 코드 작성 위치
|
||||
✅ **반드시 별도 테스트 프로젝트에 작성**:
|
||||
- `vav2/platforms/windows/tests/unit-tests/` - 단위 테스트
|
||||
- `vav2/platforms/windows/tests/headless/` - 헤드리스 통합 테스트
|
||||
- `vav2/platforms/windows/tests/integration/` - 통합 테스트
|
||||
|
||||
#### 이유
|
||||
- 테스트 코드를 프로덕션 파일에 작성 → 빌드 후 제거를 잊어버림 → 반복적인 문제 발생
|
||||
- 명확한 분리를 통한 코드 관리 및 유지보수성 향상
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **현재 프로젝트 상태** (2025-10-01)
|
||||
|
||||
@@ -9,43 +9,21 @@ using namespace winrt::Microsoft::UI::Xaml;
|
||||
|
||||
namespace winrt::Vav2Player::implementation
|
||||
{
|
||||
// Simple VavCore test function
|
||||
void TestVavCoreIntegration()
|
||||
{
|
||||
// Test VavCore C API
|
||||
VavCoreResult result = vavcore_initialize();
|
||||
if (result == VAVCORE_SUCCESS)
|
||||
{
|
||||
const char* version = vavcore_get_version_string();
|
||||
LOGF_INFO("[App] VavCore initialized successfully, version: %s", version);
|
||||
|
||||
// Test creating a player
|
||||
VavCorePlayer* player = vavcore_create_player();
|
||||
if (player)
|
||||
{
|
||||
LOGF_INFO("[App] VavCore player created successfully");
|
||||
vavcore_destroy_player(player);
|
||||
}
|
||||
|
||||
// C++ wrapper test disabled for now (only using C API)
|
||||
// VavCore::VideoPlayer cppPlayer;
|
||||
// LOGF_INFO("[App] VavCore C++ player created successfully");
|
||||
|
||||
vavcore_cleanup();
|
||||
LOGF_INFO("[App] VavCore cleanup completed");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGF_ERROR("[App] Failed to initialize VavCore");
|
||||
}
|
||||
}
|
||||
|
||||
App::App()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Test VavCore integration on startup
|
||||
// TestVavCoreIntegration(); // Disabled for logging system test
|
||||
// Initialize VavCore on startup
|
||||
VavCoreResult result = vavcore_initialize();
|
||||
if (result == VAVCORE_SUCCESS)
|
||||
{
|
||||
const char* version = vavcore_get_version_string();
|
||||
::Vav2Player::SimpleLogger::GetInstance().LogInfoF("[App] VavCore initialized successfully, version: %s", version);
|
||||
}
|
||||
else
|
||||
{
|
||||
::Vav2Player::SimpleLogger::GetInstance().LogErrorF("[App] Failed to initialize VavCore: error code %d", result);
|
||||
}
|
||||
|
||||
#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
|
||||
UnhandledException([](IInspectable const&, UnhandledExceptionEventArgs const& e)
|
||||
|
||||
@@ -123,15 +123,15 @@ namespace Vav2Player
|
||||
}
|
||||
|
||||
// Convenience macros for easier logging
|
||||
#define LOG_DEBUG(message) Vav2Player::LogManager::LogDebug(message, __FUNCTIONW__)
|
||||
#define LOG_INFO(message) Vav2Player::LogManager::LogInfo(message, __FUNCTIONW__)
|
||||
#define LOG_WARNING(message) Vav2Player::LogManager::LogWarning(message, __FUNCTIONW__)
|
||||
#define LOG_ERROR(message) Vav2Player::LogManager::LogError(message, __FUNCTIONW__)
|
||||
#define LOG_MAN_DEBUG(message) Vav2Player::LogManager::LogDebug(message, __FUNCTIONW__)
|
||||
#define LOG_MAN_INFO(message) Vav2Player::LogManager::LogInfo(message, __FUNCTIONW__)
|
||||
#define LOG_MAN_WARNING(message) Vav2Player::LogManager::LogWarning(message, __FUNCTIONW__)
|
||||
#define LOG_MAN_ERROR(message) Vav2Player::LogManager::LogError(message, __FUNCTIONW__)
|
||||
|
||||
#define LOG_VIDEO_LOAD(filename, success) Vav2Player::LogManager::LogVideoLoad(filename, success)
|
||||
#define LOG_VIDEO_PLAY(filename) Vav2Player::LogManager::LogVideoPlay(filename)
|
||||
#define LOG_VIDEO_PAUSE(filename) Vav2Player::LogManager::LogVideoPause(filename)
|
||||
#define LOG_VIDEO_STOP(filename) Vav2Player::LogManager::LogVideoStop(filename)
|
||||
#define LOG_VIDEO_ERROR(error, filename) Vav2Player::LogManager::LogVideoError(error, filename)
|
||||
#define LOG_DECODER_INFO(type, info) Vav2Player::LogManager::LogDecoderInfo(type, info)
|
||||
#define LOG_FRAME_INFO(index, total, fps) Vav2Player::LogManager::LogFrameInfo(index, total, fps)
|
||||
#define LOG_MAN_VIDEO_LOAD(filename, success) Vav2Player::LogManager::LogVideoLoad(filename, success)
|
||||
#define LOG_MAN_VIDEO_PLAY(filename) Vav2Player::LogManager::LogVideoPlay(filename)
|
||||
#define LOG_MAN_VIDEO_PAUSE(filename) Vav2Player::LogManager::LogVideoPause(filename)
|
||||
#define LOG_MAN_VIDEO_STOP(filename) Vav2Player::LogManager::LogVideoStop(filename)
|
||||
#define LOG_MAN_VIDEO_ERROR(error, filename) Vav2Player::LogManager::LogVideoError(error, filename)
|
||||
#define LOG_MAN_DECODER_INFO(type, info) Vav2Player::LogManager::LogDecoderInfo(type, info)
|
||||
#define LOG_MAN_FRAME_INFO(index, total, fps) Vav2Player::LogManager::LogFrameInfo(index, total, fps)
|
||||
@@ -1,16 +1,10 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include "LogManager.h" // Use LogLevel from LogManager.h
|
||||
|
||||
namespace Vav2Player {
|
||||
|
||||
enum class LogLevel {
|
||||
Debug = 0,
|
||||
Info = 1,
|
||||
Warning = 2,
|
||||
Error = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple logger with support for both wstring and variadic arguments
|
||||
* Thread-safe singleton logger for both console and WinUI3 environments
|
||||
@@ -73,13 +67,6 @@ private:
|
||||
// ===== Logging Macros =====
|
||||
// Use these macros instead of creating new logging functions
|
||||
|
||||
// LOG_* : For std::wstring messages with optional source parameter
|
||||
// Usage: LOG_INFO(L"Video loaded", L"VideoPlayer")
|
||||
#define LOG_DEBUG(msg, source) Vav2Player::SimpleLogger::GetInstance().LogDebug(msg, source)
|
||||
#define LOG_INFO(msg, source) Vav2Player::SimpleLogger::GetInstance().LogInfo(msg, source)
|
||||
#define LOG_WARNING(msg, source) Vav2Player::SimpleLogger::GetInstance().LogWarning(msg, source)
|
||||
#define LOG_ERROR(msg, source) Vav2Player::SimpleLogger::GetInstance().LogError(msg, source)
|
||||
|
||||
// LOGF_* : For printf-style formatted messages (const char* format, ...)
|
||||
// Usage: LOGF_INFO("[Component] Value: %d", value)
|
||||
#define LOGF_DEBUG(...) Vav2Player::SimpleLogger::GetInstance().LogDebugF(__VA_ARGS__)
|
||||
|
||||
@@ -206,8 +206,6 @@ HRESULT D3D12VideoRenderer::RenderFrame(const VavCoreVideoFrame& frame)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
// Execute command list
|
||||
ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
|
||||
m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include "GlobalD3D12SyncManager.h"
|
||||
#include "../Logger/SimpleLogger.h"
|
||||
#include <chrono>
|
||||
|
||||
namespace Vav2Player {
|
||||
@@ -26,8 +27,7 @@ void GlobalD3D12SyncManager::Initialize(size_t numThreads) {
|
||||
m_workerThreads.emplace_back(&GlobalD3D12SyncManager::WorkerThreadFunc, this);
|
||||
}
|
||||
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] Initialized with ");
|
||||
OutputDebugStringA((std::to_string(numThreads) + " worker threads\n").c_str());
|
||||
LOGF_INFO("[GlobalD3D12SyncManager] Initialized with %zu worker threads", numThreads);
|
||||
}
|
||||
|
||||
void GlobalD3D12SyncManager::Shutdown() {
|
||||
@@ -54,7 +54,7 @@ void GlobalD3D12SyncManager::Shutdown() {
|
||||
m_taskQueue.pop();
|
||||
}
|
||||
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] Shutdown completed\n");
|
||||
LOGF_INFO("[GlobalD3D12SyncManager] Shutdown completed");
|
||||
}
|
||||
|
||||
std::future<void> GlobalD3D12SyncManager::SubmitTask(std::function<void()> task) {
|
||||
@@ -114,13 +114,11 @@ void GlobalD3D12SyncManager::WorkerThreadFunc() {
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
task.completion.set_exception(std::current_exception());
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] Task exception: ");
|
||||
OutputDebugStringA(e.what());
|
||||
OutputDebugStringA("\n");
|
||||
LOGF_ERROR("[GlobalD3D12SyncManager] Task exception: %s", e.what());
|
||||
}
|
||||
catch (...) {
|
||||
task.completion.set_exception(std::current_exception());
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] Unknown task exception\n");
|
||||
LOGF_ERROR("[GlobalD3D12SyncManager] Unknown task exception");
|
||||
}
|
||||
|
||||
--m_activeTasks;
|
||||
@@ -141,7 +139,7 @@ void GlobalD3D12SyncManager::WaitForFenceInternal(ComPtr<ID3D12Fence> fence, UIN
|
||||
// Set event for completion
|
||||
HRESULT hr = fence->SetEventOnCompletion(targetValue, fenceEvent);
|
||||
if (FAILED(hr)) {
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] SetEventOnCompletion failed\n");
|
||||
LOGF_ERROR("[GlobalD3D12SyncManager] SetEventOnCompletion failed");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,7 +159,7 @@ void GlobalD3D12SyncManager::WaitForFrameCompletionInternal(ComPtr<ID3D12Fence>
|
||||
while (fence->GetCompletedValue() < targetValue) {
|
||||
HRESULT hr = fence->SetEventOnCompletion(targetValue, fenceEvent);
|
||||
if (FAILED(hr)) {
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] SetEventOnCompletion failed for frame\n");
|
||||
LOGF_ERROR("[GlobalD3D12SyncManager] SetEventOnCompletion failed for frame");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -169,12 +167,12 @@ void GlobalD3D12SyncManager::WaitForFrameCompletionInternal(ComPtr<ID3D12Fence>
|
||||
if (result == WAIT_TIMEOUT) {
|
||||
auto elapsed = std::chrono::high_resolution_clock::now() - startTime;
|
||||
if (elapsed >= timeoutDuration) {
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] Frame completion timeout exceeded\n");
|
||||
LOGF_ERROR("[GlobalD3D12SyncManager] Frame completion timeout exceeded");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (result != WAIT_OBJECT_0) {
|
||||
OutputDebugStringA("[GlobalD3D12SyncManager] WaitForSingleObject failed for frame\n");
|
||||
LOGF_ERROR("[GlobalD3D12SyncManager] WaitForSingleObject failed for frame");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,14 +680,12 @@ HRESULT SimpleGPURenderer::CreateNV12TextureR8Layout(uint32_t videoWidth, uint32
|
||||
UINT64 requiredBytes = 0;
|
||||
m_device->GetCopyableFootprints(&nv12TextureDesc, 0, 2, 0, layouts, numRows, rowSizes, &requiredBytes);
|
||||
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] GetCopyableFootprints requires: ");
|
||||
<< requiredBytes << " bytes" << std::endl;
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] GetCopyableFootprints requires: %llu bytes", requiredBytes);
|
||||
|
||||
// Query actual allocation size for this descriptor
|
||||
D3D12_RESOURCE_ALLOCATION_INFO allocInfo = m_device->GetResourceAllocationInfo(0, 1, &nv12TextureDesc);
|
||||
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] GetResourceAllocationInfo returns: ");
|
||||
<< allocInfo.SizeInBytes << " bytes" << std::endl;
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] GetResourceAllocationInfo returns: %llu bytes", allocInfo.SizeInBytes);
|
||||
|
||||
// If allocation is too small, increase texture height until we have enough space
|
||||
if (allocInfo.SizeInBytes < requiredBytes)
|
||||
@@ -699,20 +697,17 @@ HRESULT SimpleGPURenderer::CreateNV12TextureR8Layout(uint32_t videoWidth, uint32
|
||||
nv12TextureDesc.Height = videoHeight + extraHeight;
|
||||
allocInfo = m_device->GetResourceAllocationInfo(0, 1, &nv12TextureDesc);
|
||||
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Testing height %d", nv12TextureDesc.Height);
|
||||
<< ": " << allocInfo.SizeInBytes << " bytes" << std::endl;
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Testing height %d: %llu bytes", nv12TextureDesc.Height, allocInfo.SizeInBytes);
|
||||
|
||||
if (allocInfo.SizeInBytes >= requiredBytes)
|
||||
{
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Found sufficient height: ");
|
||||
<< nv12TextureDesc.Height << std::endl;
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Found sufficient height: %d", nv12TextureDesc.Height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Final NV12 texture: %dx", videoWidth);
|
||||
<< nv12TextureDesc.Height << ", allocation: " << allocInfo.SizeInBytes << " bytes" << std::endl;
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Final NV12 texture: %dx%d, allocation: %llu bytes", videoWidth, nv12TextureDesc.Height, allocInfo.SizeInBytes);
|
||||
|
||||
D3D12_HEAP_PROPERTIES sharedHeapProps = {};
|
||||
sharedHeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
@@ -728,13 +723,11 @@ HRESULT SimpleGPURenderer::CreateNV12TextureR8Layout(uint32_t videoWidth, uint32
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOGF_ERROR("[SimpleGPURenderer::CreateNV12Texture] Failed to create NV12 shared texture: 0x");
|
||||
<< std::hex << hr << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer::CreateNV12Texture] Failed to create NV12 shared texture: 0x%08X", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Created NV12 shared texture (");
|
||||
<< videoWidth << "x" << videoHeight << ") for VavCore zero-copy decode" << std::endl;
|
||||
LOGF_INFO("[SimpleGPURenderer::CreateNV12Texture] Created NV12 shared texture (%dx%d) for VavCore zero-copy decode", videoWidth, videoHeight);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -824,8 +817,7 @@ float4 PSMain(PSInput input) : SV_TARGET
|
||||
"VSMain", "vs_5_0", compileFlags, 0, &m_nv12VertexShaderBlob, &errorBlob);
|
||||
if (FAILED(hr)) {
|
||||
if (errorBlob) {
|
||||
LOGF_INFO("[SimpleGPURenderer] NV12 Vertex shader compilation error: ");
|
||||
<< (char*)errorBlob->GetBufferPointer() << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer] NV12 Vertex shader compilation error: %s", (char*)errorBlob->GetBufferPointer());
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@@ -835,8 +827,7 @@ float4 PSMain(PSInput input) : SV_TARGET
|
||||
"PSMain", "ps_5_0", compileFlags, 0, &m_nv12PixelShaderBlob, &errorBlob);
|
||||
if (FAILED(hr)) {
|
||||
if (errorBlob) {
|
||||
LOGF_INFO("[SimpleGPURenderer] NV12 Pixel shader compilation error: ");
|
||||
<< (char*)errorBlob->GetBufferPointer() << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer] NV12 Pixel shader compilation error: %s", (char*)errorBlob->GetBufferPointer());
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@@ -900,8 +891,7 @@ HRESULT SimpleGPURenderer::CreateNV12RootSignature()
|
||||
HRESULT hr = D3D12SerializeVersionedRootSignature(&rootSigDesc, &signature, &error);
|
||||
if (FAILED(hr)) {
|
||||
if (error) {
|
||||
LOGF_INFO("[SimpleGPURenderer] NV12 Root signature serialization error: ");
|
||||
<< (char*)error->GetBufferPointer() << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer] NV12 Root signature serialization error: %s", (char*)error->GetBufferPointer());
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@@ -1005,8 +995,7 @@ HRESULT SimpleGPURenderer::CreateNV12GraphicsPipeline()
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOGF_ERROR("[SimpleGPURenderer] Failed to create NV12 constant buffer: 0x");
|
||||
<< std::hex << hr << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer] Failed to create NV12 constant buffer: 0x%08X", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
@@ -1618,8 +1607,7 @@ HRESULT SimpleGPURenderer::CreateComputeRootSignature()
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
LOGF_INFO("[SimpleGPURenderer] Root signature serialization error: ");
|
||||
<< (char*)error->GetBufferPointer() << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer] Root signature serialization error: %s", (char*)error->GetBufferPointer());
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@@ -1716,8 +1704,7 @@ void main(uint3 id : SV_DispatchThreadID)
|
||||
{
|
||||
if (errorBlob)
|
||||
{
|
||||
LOGF_ERROR("[SimpleGPURenderer] Shader compilation failed: ");
|
||||
<< (char*)errorBlob->GetBufferPointer() << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer] Shader compilation failed: %s", (char*)errorBlob->GetBufferPointer());
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@@ -1745,8 +1732,7 @@ HRESULT SimpleGPURenderer::CreateComputePipelineState()
|
||||
HRESULT hr = m_device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&m_computePipelineState));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
LOGF_ERROR("[SimpleGPURenderer] Failed to create compute pipeline state: 0x");
|
||||
<< std::hex << hr << std::endl;
|
||||
LOGF_ERROR("[SimpleGPURenderer] Failed to create compute pipeline state: 0x%08X", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,39 +32,42 @@ bool D3D12SurfaceHandler::CopyNV12Frame(CUdeviceptr src_frame,
|
||||
}
|
||||
|
||||
// Get D3D12 texture layout for both Y and UV planes
|
||||
// CRITICAL: Must use the ACTUAL texture descriptor as-is (including any padding)
|
||||
// DO NOT override height - GetCopyableFootprints needs the real allocation size
|
||||
D3D12_RESOURCE_DESC desc = dst_texture->GetDesc();
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layouts[2];
|
||||
UINT num_rows[2] = {0};
|
||||
UINT64 row_sizes[2] = {0};
|
||||
UINT64 total_bytes = 0;
|
||||
|
||||
// Use descriptor directly without modification (preserves allocated height/pitch)
|
||||
// CRITICAL: Use the ACTUAL allocated texture descriptor (including padding)
|
||||
// SimpleGPURenderer may have allocated extra height to satisfy GetCopyableFootprints requirements
|
||||
// We MUST use the real descriptor to get correct Y/UV plane offsets
|
||||
// Query BOTH subresources (plane 0: Y, plane 1: UV) in a SINGLE call
|
||||
m_device->GetCopyableFootprints(&desc, 0, 2, 0,
|
||||
layouts, num_rows, row_sizes, &total_bytes);
|
||||
|
||||
uint32_t y_dst_pitch = layouts[0].Footprint.RowPitch;
|
||||
uint32_t uv_dst_pitch = layouts[1].Footprint.RowPitch;
|
||||
UINT64 uv_offset = layouts[1].Offset;
|
||||
|
||||
// Get actual row counts from GetCopyableFootprints
|
||||
uint32_t y_rows = num_rows[0];
|
||||
uint32_t uv_rows = num_rows[1];
|
||||
|
||||
// Debug logging
|
||||
char buf[512];
|
||||
sprintf_s(buf, "[D3D12SurfaceHandler] Video: %ux%u, Y: pitch=%u rows=%u, UV: pitch=%u rows=%u offset=%llu\n",
|
||||
width, height, y_dst_pitch, y_rows, uv_dst_pitch, uv_rows, uv_offset);
|
||||
sprintf_s(buf, "[D3D12SurfaceHandler] Texture descriptor: allocated height=%u (logical video height=%u)\n",
|
||||
(uint32_t)desc.Height, height);
|
||||
OutputDebugStringA(buf);
|
||||
sprintf_s(buf, "[D3D12SurfaceHandler] Source: pitch=%u, Y ptr=0x%llX, UV ptr=0x%llX\n",
|
||||
src_pitch, src_frame, src_frame + (static_cast<UINT64>(src_pitch) * height));
|
||||
|
||||
sprintf_s(buf, "[D3D12SurfaceHandler] Y plane: width=%u, height=%u, srcPitch=%u, dstPitch=%u, rows=%u\n",
|
||||
width, height, src_pitch, y_dst_pitch, y_rows);
|
||||
OutputDebugStringA(buf);
|
||||
|
||||
sprintf_s(buf, "[D3D12SurfaceHandler] UV plane: width=%u, height=%u, srcPitch=%u, dstPitch=%u, rows=%u, offset=%llu\n",
|
||||
width, height / 2, src_pitch, uv_dst_pitch, uv_rows, uv_offset);
|
||||
OutputDebugStringA(buf);
|
||||
|
||||
// Copy Y plane
|
||||
if (!CopyYPlane(src_frame, src_pitch,
|
||||
dst_ptr, y_dst_pitch,
|
||||
width, y_rows)) {
|
||||
width, height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -74,10 +77,11 @@ bool D3D12SurfaceHandler::CopyNV12Frame(CUdeviceptr src_frame,
|
||||
|
||||
if (!CopyUVPlane(src_uv, src_pitch,
|
||||
dst_uv, uv_dst_pitch,
|
||||
width, uv_rows)) {
|
||||
width, height / 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OutputDebugStringA("[D3D12SurfaceHandler] NV12 frame copied successfully\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -97,10 +101,12 @@ bool D3D12SurfaceHandler::CopyYPlane(CUdeviceptr src, uint32_t src_pitch,
|
||||
CUdeviceptr dst, uint32_t dst_pitch,
|
||||
uint32_t width, uint32_t height)
|
||||
{
|
||||
// Copy Y plane: single 8-bit channel
|
||||
// Width parameter is in bytes (same as pixel width for 8-bit format)
|
||||
cudaError_t err = cudaMemcpy2D(
|
||||
(void*)dst, dst_pitch,
|
||||
(void*)src, src_pitch,
|
||||
width, height, // Use the logical width, not the pitch, for the copy width.
|
||||
width, height,
|
||||
cudaMemcpyDeviceToDevice
|
||||
);
|
||||
|
||||
@@ -111,6 +117,8 @@ bool D3D12SurfaceHandler::CopyYPlane(CUdeviceptr src, uint32_t src_pitch,
|
||||
OutputDebugStringA(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
OutputDebugStringA("[D3D12SurfaceHandler] Y plane copied\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -118,11 +126,13 @@ bool D3D12SurfaceHandler::CopyUVPlane(CUdeviceptr src, uint32_t src_pitch,
|
||||
CUdeviceptr dst, uint32_t dst_pitch,
|
||||
uint32_t width, uint32_t height)
|
||||
{
|
||||
// For interleaved NV12, the byte width of the UV plane is the same as the Y plane.
|
||||
// Copy UV plane: interleaved U and V (NV12 format)
|
||||
// Width in bytes = width of Y plane (because U and V are interleaved)
|
||||
// Height = half of Y plane height
|
||||
cudaError_t err = cudaMemcpy2D(
|
||||
(void*)dst, dst_pitch,
|
||||
(void*)src, src_pitch,
|
||||
width, height, // Use the logical width, not the pitch, for the copy width.
|
||||
width, height,
|
||||
cudaMemcpyDeviceToDevice
|
||||
);
|
||||
|
||||
@@ -133,6 +143,8 @@ bool D3D12SurfaceHandler::CopyUVPlane(CUdeviceptr src, uint32_t src_pitch,
|
||||
OutputDebugStringA(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
OutputDebugStringA("[D3D12SurfaceHandler] UV plane copied\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user