mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-24 13:44:58 +00:00
fix: Update shader file error messages and validation to improve clarity
This commit is contained in:
@@ -65,7 +65,7 @@ Now validates before attempting to read:
|
||||
|
||||
**Example error messages**:
|
||||
```
|
||||
File not found: /path/to/shader.spv
|
||||
File not found: /path/to/shader.vert
|
||||
|
||||
Please ensure the file exists at this location.
|
||||
```
|
||||
@@ -79,15 +79,15 @@ The file exists but cannot be opened. Check file permissions.
|
||||
#### Shader File Validation
|
||||
- Checks both vertex and fragment shader files exist before loading
|
||||
- Provides the shader key to help identify which pipeline failed
|
||||
- Suggests checking that shaders are compiled and in the correct directory
|
||||
- Suggests checking that shader sources are present in the correct directory
|
||||
|
||||
**Example error message**:
|
||||
```
|
||||
Vertex shader not found: shaders/cube.vert.spv
|
||||
Vertex shader not found: shaders/cube.vert
|
||||
|
||||
Shader key: default
|
||||
|
||||
Please ensure shader files are compiled and present in the shaders directory.
|
||||
Please ensure shader source files are present in the shaders directory.
|
||||
```
|
||||
|
||||
### 4. Structured Vulkan Initialization ([sdl3_app_core.cpp](src/app/sdl3_app_core.cpp))
|
||||
@@ -160,14 +160,14 @@ Plus a message box with the same error.
|
||||
### Test Case 2: Missing Shader File
|
||||
```bash
|
||||
cd build/Release
|
||||
mv shaders/cube.vert.spv shaders/cube.vert.spv.backup
|
||||
mv shaders/cube.vert shaders/cube.vert.backup
|
||||
./sdl3_app --json-file-in ./config/seed_runtime.json
|
||||
```
|
||||
|
||||
**Expected Result**:
|
||||
Message box showing:
|
||||
```
|
||||
Vertex shader not found: shaders/cube.vert.spv
|
||||
Vertex shader not found: shaders/cube.vert
|
||||
|
||||
Shader key: default
|
||||
|
||||
@@ -226,4 +226,3 @@ Application runs normally. If any errors occur during initialization, they will
|
||||
## Conclusion
|
||||
|
||||
The application now provides comprehensive error feedback instead of failing silently with a "see-through window". Every potential failure point has been wrapped with validation and clear error messages, making it much easier to diagnose and fix issues.
|
||||
|
||||
|
||||
@@ -247,18 +247,6 @@ shaderc_shader_kind ShadercKindFromStage(VkShaderStageFlagBits stage) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ReadBinaryFile(const std::filesystem::path& path) {
|
||||
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to read file: " + path.string());
|
||||
}
|
||||
size_t fileSize = static_cast<size_t>(file.tellg());
|
||||
std::vector<uint8_t> buffer(fileSize);
|
||||
file.seekg(0);
|
||||
file.read(reinterpret_cast<char*>(buffer.data()), static_cast<std::streamsize>(fileSize));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ReadShaderFile(const std::filesystem::path& path,
|
||||
VkShaderStageFlagBits stage,
|
||||
ILogger* logger) {
|
||||
@@ -273,36 +261,25 @@ std::vector<uint8_t> ReadShaderFile(const std::filesystem::path& path,
|
||||
}
|
||||
|
||||
std::filesystem::path shaderPath = path;
|
||||
if (!std::filesystem::exists(shaderPath) && shaderPath.extension() == ".spv") {
|
||||
if (shaderPath.extension() == ".spv") {
|
||||
std::filesystem::path sourcePath = shaderPath;
|
||||
sourcePath.replace_extension();
|
||||
if (std::filesystem::exists(sourcePath)) {
|
||||
if (logger) {
|
||||
logger->Trace("GuiRenderer", "ReadShaderFile",
|
||||
"usingSource=" + sourcePath.string());
|
||||
}
|
||||
shaderPath = sourcePath;
|
||||
if (logger) {
|
||||
logger->Trace("GuiRenderer", "ReadShaderFile",
|
||||
"usingSource=" + sourcePath.string());
|
||||
}
|
||||
shaderPath = sourcePath;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(shaderPath)) {
|
||||
throw std::runtime_error("Shader file not found: " + shaderPath.string() +
|
||||
"\n\nPlease ensure the source (.vert/.frag/etc.) or compiled .spv exists.");
|
||||
"\n\nPlease ensure the shader source (.vert/.frag/etc.) exists.");
|
||||
}
|
||||
|
||||
if (!std::filesystem::is_regular_file(shaderPath)) {
|
||||
throw std::runtime_error("Path is not a regular file: " + shaderPath.string());
|
||||
}
|
||||
|
||||
if (shaderPath.extension() == ".spv") {
|
||||
auto buffer = ReadBinaryFile(shaderPath);
|
||||
if (logger) {
|
||||
logger->Trace("GuiRenderer", "ReadShaderFile",
|
||||
"loadedSpirvBytes=" + std::to_string(buffer.size()));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::ifstream sourceFile(shaderPath);
|
||||
if (!sourceFile) {
|
||||
throw std::runtime_error("Failed to open shader source: " + shaderPath.string());
|
||||
@@ -689,9 +666,9 @@ const std::vector<uint8_t>& GuiRenderer::LoadShaderBytes(const std::filesystem::
|
||||
void GuiRenderer::CreatePipeline(VkRenderPass renderPass, VkExtent2D extent) {
|
||||
// Load shader modules
|
||||
const std::filesystem::path vertexShaderPath =
|
||||
scriptDirectory_.parent_path() / "shaders" / "gui_2d.vert.spv";
|
||||
scriptDirectory_.parent_path() / "shaders" / "gui_2d.vert";
|
||||
const std::filesystem::path fragmentShaderPath =
|
||||
scriptDirectory_.parent_path() / "shaders" / "gui_2d.frag.spv";
|
||||
scriptDirectory_.parent_path() / "shaders" / "gui_2d.frag";
|
||||
if (logger_) {
|
||||
logger_->Trace("GuiRenderer", "CreatePipeline",
|
||||
"renderPassIsNull=" + std::string(renderPass == VK_NULL_HANDLE ? "true" : "false") +
|
||||
|
||||
@@ -265,7 +265,7 @@ void PipelineService::CreatePipelinesInternal(VkRenderPass renderPass, VkExtent2
|
||||
throw std::runtime_error(
|
||||
label + " shader not found: " + path +
|
||||
"\n\nShader key: " + key +
|
||||
"\n\nPlease ensure the shader source (.vert/.frag/etc.) or compiled .spv exists.");
|
||||
"\n\nPlease ensure the shader source (.vert/.frag/etc.) exists.");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -393,15 +393,10 @@ bool PipelineService::HasShaderSource(const std::string& path) const {
|
||||
return false;
|
||||
}
|
||||
std::filesystem::path shaderPath(path);
|
||||
if (std::filesystem::exists(shaderPath)) {
|
||||
return true;
|
||||
}
|
||||
if (shaderPath.extension() == ".spv") {
|
||||
std::filesystem::path sourcePath = shaderPath;
|
||||
sourcePath.replace_extension();
|
||||
return std::filesystem::exists(sourcePath);
|
||||
shaderPath.replace_extension();
|
||||
}
|
||||
return false;
|
||||
return std::filesystem::exists(shaderPath);
|
||||
}
|
||||
|
||||
const std::vector<char>& PipelineService::ReadShaderFile(const std::string& path, VkShaderStageFlagBits stage) {
|
||||
@@ -413,19 +408,17 @@ const std::vector<char>& PipelineService::ReadShaderFile(const std::string& path
|
||||
}
|
||||
|
||||
std::filesystem::path shaderPath(path);
|
||||
if (!std::filesystem::exists(shaderPath) && shaderPath.extension() == ".spv") {
|
||||
if (shaderPath.extension() == ".spv") {
|
||||
std::filesystem::path sourcePath = shaderPath;
|
||||
sourcePath.replace_extension();
|
||||
if (std::filesystem::exists(sourcePath)) {
|
||||
logger_->Trace("PipelineService", "ReadShaderFile",
|
||||
"usingSource=" + sourcePath.string());
|
||||
shaderPath = sourcePath;
|
||||
}
|
||||
logger_->Trace("PipelineService", "ReadShaderFile",
|
||||
"usingSource=" + sourcePath.string());
|
||||
shaderPath = sourcePath;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(shaderPath)) {
|
||||
throw std::runtime_error("Shader file not found: " + shaderPath.string() +
|
||||
"\n\nPlease ensure the source (.vert/.frag/etc.) or compiled .spv exists.");
|
||||
"\n\nPlease ensure the shader source (.vert/.frag/etc.) exists.");
|
||||
}
|
||||
|
||||
if (!std::filesystem::is_regular_file(shaderPath)) {
|
||||
@@ -441,53 +434,34 @@ const std::vector<char>& PipelineService::ReadShaderFile(const std::string& path
|
||||
return cached->second;
|
||||
}
|
||||
|
||||
std::vector<char> buffer;
|
||||
if (shaderPath.extension() == ".spv") {
|
||||
std::ifstream file(shaderPath, std::ios::ate | std::ios::binary);
|
||||
if (!file) {
|
||||
throw std::runtime_error("Failed to open shader file: " + shaderPath.string() +
|
||||
"\n\nCheck file permissions.");
|
||||
}
|
||||
|
||||
size_t fileSize = static_cast<size_t>(file.tellg());
|
||||
buffer.resize(fileSize);
|
||||
|
||||
file.seekg(0);
|
||||
file.read(buffer.data(), static_cast<std::streamsize>(fileSize));
|
||||
file.close();
|
||||
|
||||
logger_->Debug("Read shader file: " + shaderPath.string() +
|
||||
" (" + std::to_string(fileSize) + " bytes)");
|
||||
} else {
|
||||
std::ifstream sourceFile(shaderPath);
|
||||
if (!sourceFile) {
|
||||
throw std::runtime_error("Failed to open shader source: " + shaderPath.string());
|
||||
}
|
||||
std::string source((std::istreambuf_iterator<char>(sourceFile)),
|
||||
std::istreambuf_iterator<char>());
|
||||
sourceFile.close();
|
||||
|
||||
shaderc::Compiler compiler;
|
||||
shaderc::CompileOptions options;
|
||||
options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2);
|
||||
|
||||
shaderc_shader_kind kind = ShadercKindFromStage(stage);
|
||||
auto result = compiler.CompileGlslToSpv(source, kind, shaderPath.string().c_str(), options);
|
||||
if (result.GetCompilationStatus() != shaderc_compilation_status_success) {
|
||||
std::string error = result.GetErrorMessage();
|
||||
logger_->Error("Shader compilation failed: " + shaderPath.string() + "\n" + error);
|
||||
throw std::runtime_error("Shader compilation failed: " + shaderPath.string() + "\n" + error);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> spirv(result.cbegin(), result.cend());
|
||||
buffer.resize(spirv.size() * sizeof(uint32_t));
|
||||
if (!buffer.empty()) {
|
||||
std::memcpy(buffer.data(), spirv.data(), buffer.size());
|
||||
}
|
||||
|
||||
logger_->Debug("Compiled shader: " + shaderPath.string() +
|
||||
" (" + std::to_string(buffer.size()) + " bytes)");
|
||||
std::ifstream sourceFile(shaderPath);
|
||||
if (!sourceFile) {
|
||||
throw std::runtime_error("Failed to open shader source: " + shaderPath.string());
|
||||
}
|
||||
std::string source((std::istreambuf_iterator<char>(sourceFile)),
|
||||
std::istreambuf_iterator<char>());
|
||||
sourceFile.close();
|
||||
|
||||
shaderc::Compiler compiler;
|
||||
shaderc::CompileOptions options;
|
||||
options.SetTargetEnvironment(shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2);
|
||||
|
||||
shaderc_shader_kind kind = ShadercKindFromStage(stage);
|
||||
auto result = compiler.CompileGlslToSpv(source, kind, shaderPath.string().c_str(), options);
|
||||
if (result.GetCompilationStatus() != shaderc_compilation_status_success) {
|
||||
std::string error = result.GetErrorMessage();
|
||||
logger_->Error("Shader compilation failed: " + shaderPath.string() + "\n" + error);
|
||||
throw std::runtime_error("Shader compilation failed: " + shaderPath.string() + "\n" + error);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> spirv(result.cbegin(), result.cend());
|
||||
std::vector<char> buffer(spirv.size() * sizeof(uint32_t));
|
||||
if (!buffer.empty()) {
|
||||
std::memcpy(buffer.data(), spirv.data(), buffer.size());
|
||||
}
|
||||
|
||||
logger_->Debug("Compiled shader: " + shaderPath.string() +
|
||||
" (" + std::to_string(buffer.size()) + " bytes)");
|
||||
|
||||
auto inserted = shaderSpirvCache_.emplace(cacheKey, std::move(buffer));
|
||||
logger_->Trace("PipelineService", "ReadShaderFile",
|
||||
|
||||
Reference in New Issue
Block a user