This commit is contained in:
2025-10-03 21:41:18 +09:00
parent 7968c7e0be
commit 38e9055387
9 changed files with 96 additions and 115 deletions

View File

@@ -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": []

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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__)

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}