Fix shader bug

This commit is contained in:
2025-10-08 00:18:57 +09:00
parent 9b67410063
commit e0aa81ed72
2 changed files with 140 additions and 14 deletions

View File

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

View File

@@ -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<uint8_t[]> 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;
}