From e0aa81ed72be66081e71b96ed39377e4b1f338ef Mon Sep 17 00:00:00 2001 From: ened Date: Wed, 8 Oct 2025 00:18:57 +0900 Subject: [PATCH] Fix shader bug --- .../src/Rendering/YUV420PUploadBackend.cpp | 37 +++++- .../windows/vavcore/src/Common/ImageUtils.cpp | 117 ++++++++++++++++-- 2 files changed, 140 insertions(+), 14 deletions(-) diff --git a/vav2/platforms/windows/applications/vav2player/Vav2Player/src/Rendering/YUV420PUploadBackend.cpp b/vav2/platforms/windows/applications/vav2player/Vav2Player/src/Rendering/YUV420PUploadBackend.cpp index 2587bbc..ea14bb0 100644 --- a/vav2/platforms/windows/applications/vav2player/Vav2Player/src/Rendering/YUV420PUploadBackend.cpp +++ b/vav2/platforms/windows/applications/vav2player/Vav2Player/src/Rendering/YUV420PUploadBackend.cpp @@ -306,9 +306,40 @@ HRESULT YUV420PUploadBackend::CreateGraphicsResources() { } HRESULT YUV420PUploadBackend::CompileGraphicsShaders() { - const char* vsSource = R"(struct VSOutput { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; VSOutput main(uint id : SV_VertexID) { VSOutput o; o.uv = float2((id << 1) & 2, id & 2); o.pos = float4(o.uv * float2(2, -2) + float2(-1, 1), 0, 1); return o; })"; - const char* psSource = R"(Texture2D t : register(t0); SamplerState s : register(s0); cbuffer C : register(b0) { float4x4 xf; }; float4 main(float4 pos : SV_POSITION, float2 uv : TEXCOORD0) : SV_TARGET { return t.Sample(s, mul(float4(uv, 0, 1), xf).xy); })"; - // Simplified for brevity, real implementation would be more robust + const char* vsSource = R"( +struct VSOutput { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; +}; + +VSOutput main(uint id : SV_VertexID) { + VSOutput o; + o.uv = float2((id << 1) & 2, id & 2); + o.pos = float4(o.uv * float2(2, -2) + float2(-1, 1), 0, 1); + return o; +})"; + + const char* psSource = R"( +Texture2D t : register(t0); +SamplerState s : register(s0); +cbuffer C : register(b0) { + float videoAspectRatio; + float containerAspectRatio; + float uvScaleX; + float uvScaleY; + float uvOffsetX; + float uvOffsetY; + float2 padding; +}; + +float4 main(float4 pos : SV_POSITION, float2 uv : TEXCOORD0) : SV_TARGET { + // Apply AspectFit transformation + float2 transformedUV = uv * float2(uvScaleX, uvScaleY) + float2(uvOffsetX, uvOffsetY); + float4 color = t.Sample(s, transformedUV); + // RGB texture (RGBA format) to BGRA backbuffer - no swizzle needed + return color; +})"; + ComPtr errorBlob; HRESULT hr = D3DCompile(vsSource, strlen(vsSource), nullptr, nullptr, nullptr, "main", "vs_5_0", D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &m_vertexShaderBlob, &errorBlob); if (FAILED(hr)) return hr; diff --git a/vav2/platforms/windows/vavcore/src/Common/ImageUtils.cpp b/vav2/platforms/windows/vavcore/src/Common/ImageUtils.cpp index ad31c7d..5afe1b9 100644 --- a/vav2/platforms/windows/vavcore/src/Common/ImageUtils.cpp +++ b/vav2/platforms/windows/vavcore/src/Common/ImageUtils.cpp @@ -132,6 +132,49 @@ bool ImageUtils::SaveYUV420PToBMP(const char* filename, const VideoFrame& yuv_fr return false; } + // Convert relative path to absolute path based on executable directory + wchar_t module_path_w[MAX_PATH]; + DWORD module_len = GetModuleFileNameW(nullptr, module_path_w, MAX_PATH); + if (module_len == 0 || module_len >= MAX_PATH) { + LOGF_ERROR("[ImageUtils] Failed to get module file name (error: %lu)", GetLastError()); + return false; + } + + // Remove filename to get directory + wchar_t* last_slash = wcsrchr(module_path_w, L'\\'); + if (!last_slash) { + last_slash = wcsrchr(module_path_w, L'/'); + } + if (last_slash) { + *last_slash = L'\0'; + } + + // Convert input path to wide string + wchar_t filename_w[MAX_PATH]; + int converted = MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_w, MAX_PATH); + if (converted == 0) { + LOGF_ERROR("[ImageUtils] Failed to convert filename to wide string (error: %lu)", GetLastError()); + return false; + } + + // Build absolute path: module_dir + filename + wchar_t absolute_filename_w[MAX_PATH]; + if (filename_w[0] == L'.' && (filename_w[1] == L'/' || filename_w[1] == L'\\')) { + // Relative path starting with "./" or ".\" + swprintf_s(absolute_filename_w, MAX_PATH, L"%s\\%s", module_path_w, filename_w + 2); + } else if (filename_w[0] != L'\\' && filename_w[1] != L':') { + // Relative path without leading "./" + swprintf_s(absolute_filename_w, MAX_PATH, L"%s\\%s", module_path_w, filename_w); + } else { + // Already absolute path + wcscpy_s(absolute_filename_w, MAX_PATH, filename_w); + } + + // Convert back to UTF-8 for logging + char absolute_filename_utf8[MAX_PATH]; + WideCharToMultiByte(CP_UTF8, 0, absolute_filename_w, -1, absolute_filename_utf8, MAX_PATH, nullptr, nullptr); + LOGF_INFO("[ImageUtils] Saving BMP to: %s", absolute_filename_utf8); + // Allocate RGB buffer size_t rgb_size = yuv_frame.width * yuv_frame.height * 3; std::unique_ptr rgb_buffer(new uint8_t[rgb_size]); @@ -142,8 +185,8 @@ bool ImageUtils::SaveYUV420PToBMP(const char* filename, const VideoFrame& yuv_fr return false; } - // Save RGB to BMP - if (!SaveRGB24ToBMP(filename, rgb_buffer.get(), yuv_frame.width, yuv_frame.height)) { + // Convert wide string path to UTF-8 for SaveRGB24ToBMP + if (!SaveRGB24ToBMP(absolute_filename_utf8, rgb_buffer.get(), yuv_frame.width, yuv_frame.height)) { LOGF_ERROR("[ImageUtils] BMP save failed"); return false; } @@ -156,40 +199,92 @@ bool ImageUtils::CreateDirectoryIfNotExists(const char* dir_path) { return false; } + // Convert relative path to absolute path based on executable directory + wchar_t module_path_w[MAX_PATH]; + DWORD module_len = GetModuleFileNameW(nullptr, module_path_w, MAX_PATH); + if (module_len == 0 || module_len >= MAX_PATH) { + LOGF_ERROR("[ImageUtils] Failed to get module file name (error: %lu)", GetLastError()); + return false; + } + + // Remove filename to get directory + wchar_t* last_slash = wcsrchr(module_path_w, L'\\'); + if (!last_slash) { + last_slash = wcsrchr(module_path_w, L'/'); + } + if (last_slash) { + *last_slash = L'\0'; + } + + // Convert input path to wide string + wchar_t dir_path_w[MAX_PATH]; + int converted = MultiByteToWideChar(CP_UTF8, 0, dir_path, -1, dir_path_w, MAX_PATH); + if (converted == 0) { + LOGF_ERROR("[ImageUtils] Failed to convert path to wide string (error: %lu)", GetLastError()); + return false; + } + + // Build absolute path: module_dir + dir_path + wchar_t absolute_path_w[MAX_PATH]; + if (dir_path_w[0] == L'.' && (dir_path_w[1] == L'/' || dir_path_w[1] == L'\\')) { + // Relative path starting with "./" or ".\" + swprintf_s(absolute_path_w, MAX_PATH, L"%s\\%s", module_path_w, dir_path_w + 2); + } else if (dir_path_w[0] != L'\\' && dir_path_w[1] != L':') { + // Relative path without leading "./" + swprintf_s(absolute_path_w, MAX_PATH, L"%s\\%s", module_path_w, dir_path_w); + } else { + // Already absolute path + wcscpy_s(absolute_path_w, MAX_PATH, dir_path_w); + } + + // Convert back to UTF-8 for logging + char absolute_path_utf8[MAX_PATH]; + WideCharToMultiByte(CP_UTF8, 0, absolute_path_w, -1, absolute_path_utf8, MAX_PATH, nullptr, nullptr); + // Check if directory already exists first - DWORD attribs = GetFileAttributesA(dir_path); + DWORD attribs = GetFileAttributesW(absolute_path_w); if (attribs != INVALID_FILE_ATTRIBUTES && (attribs & FILE_ATTRIBUTE_DIRECTORY)) { // Directory already exists return true; } // Try to create the directory - BOOL result = CreateDirectoryA(dir_path, nullptr); + BOOL result = CreateDirectoryW(absolute_path_w, nullptr); if (result == 0) { DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { // Race condition: directory was created between check and create + LOGF_INFO("[ImageUtils] Directory created by another thread: %s", absolute_path_utf8); return true; } // Try to create parent directories recursively - std::string path_str(dir_path); - size_t pos = path_str.find_last_of("/\\"); - if (pos != std::string::npos && pos > 0) { - std::string parent = path_str.substr(0, pos); - if (CreateDirectoryIfNotExists(parent.c_str())) { + std::wstring path_str_w(absolute_path_w); + size_t pos = path_str_w.find_last_of(L"/\\"); + if (pos != std::wstring::npos && pos > 0) { + std::wstring parent_w = path_str_w.substr(0, pos); + + // Convert parent path to UTF-8 for logging + char parent_utf8[MAX_PATH]; + WideCharToMultiByte(CP_UTF8, 0, parent_w.c_str(), -1, parent_utf8, MAX_PATH, nullptr, nullptr); + LOGF_INFO("[ImageUtils] Creating parent directory: %s", parent_utf8); + + // Convert parent path to UTF-8 for recursive call + if (CreateDirectoryIfNotExists(parent_utf8)) { // Retry after creating parent - result = CreateDirectoryA(dir_path, nullptr); + result = CreateDirectoryW(absolute_path_w, nullptr); if (result != 0 || GetLastError() == ERROR_ALREADY_EXISTS) { + LOGF_INFO("[ImageUtils] Directory created after parent: %s", absolute_path_utf8); return true; } } } - LOGF_ERROR("[ImageUtils] Failed to create directory: %s (error: %lu)", dir_path, GetLastError()); + LOGF_ERROR("[ImageUtils] Failed to create directory: %s (error: %lu)", absolute_path_utf8, GetLastError()); return false; } + LOGF_INFO("[ImageUtils] Directory created successfully: %s", absolute_path_utf8); return true; }