Reputation: 7925
I'm working on a solution within Visual Studio. It currently has two projects.
I will represent Directories or folders with capitals letters, and filenames will be all lower case. My solution structure is as follows:
Within ProjectLib
I have a function to open and read my Shader files. Here is what my function looks like:
std::vector<char> VRXShader::readFile(std::string_view shadername) {
std::string filename = std::string("Shaders/");
filename.append(shadername);
std::ifstream file(filename.data(), std::ios::ate | std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("failed to open file!");
}
size_t fileSize = static_cast<size_t>(file.tellg());
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
return buffer;
}
This function is being called within my VRXDevices::createPipeline
function and here is the relevant code:
void VRXDevices::createPipeline(
VkDevice device, VkExtent2D swapChainExtent, VkRenderPass renderPass,
const std::vector<std::string_view>& shaderNames,
VkPipelineLayout& pipelineLayout, VkPipeline& pipeline
) {
std::vector<std::vector<char>> shaderCodes;
shaderCodes.resize(shaderNames.size());
for (auto& name : shaderNames) {
auto shaderCode = VRXShader::readFile(name.data());
}
// .... more code
}
The names are being created and passed to this function from my VRXEngine::initVulkan
function which can be seen here:
void VRXEngine::initVulkan(
std::string_view app_name, std::string_view engine_name,
glm::ivec3 app_version, glm::ivec3 engine_version
) {
//... code
std::vector<std::string_view> shaderFilenames{ "vert.spv", "frag.spv" };
VRXDevices::createPipeline(device_, swapChainExtent_, renderPass_, shaderFilenames, pipelineLayout_, graphicsPipeline_);
}
I'm using just the name of the shader files such as vert.spv
, frag.spv
, geom.spv
etc. I'm not including the paths here because these will be used as the key to a std::map<string_view, object>
. So I'm passing a vector of these names from my ::initVulkan
function into ::createPipeline()
.
Within ::createPipeline()
is where ::readFile()
is being called passing in the string_view
.
Now as for my question... within ::readFile()
I'm creating a local string
and trying to initialize it with the appropriate path... then append to it the string_view
for the shader's filename as can be seen from these two lines...
std::string filename = std::string("Shaders/");
filename.append(shadername);
I'm trying to figure out the appropriate string to initialize filename
with... Shaders/
will be a part of the name, but it's not finding the file and I'm not sure what the appropriate prefix should be...
My working directories within both projects are as follows:
So I need to go back 2 directories then into VRX Engine/Shader
...
What is the correct string value for navigating back directories?
Would I initialize filename
with "../../VRX Engine/Shaders/"
or is it "././"
also, should I have quotes around VRX Engine
since there is a space in the folder name? What do I need to initialize filename
with before I append the shader name
to it?
Upvotes: 1
Views: 3177
Reputation: 1
How to properly navigate directory paths in C++
C++ is useful on computers without directories (e.g. inside some operating system kernel coded in C++ and compiled with GCC, see OSDEV for examples).
Licensing constraints could matter when using extra open source libraries.
If your implementation is C++17 compliant (in a "hosted" not "freestanding" way), use the std::filesystem
part of the standard library.
If your operating system supports the Qt or POCO frameworks and you are allowed to use them (e.g. on C++11), you could use appropriate APIs. So QDir
and related classes with Qt, Poco::Path
and related classes with POCO.
Perhaps you want to code just for the WinAPI. Then read its documentation (I never coded on Windows myself, just on POSIX or Unix -e.g. Linux- and MSDOS....).
Upvotes: 1
Reputation: 7925
I was originally initializing my local temp string
properly with "../../VRX Engine/Shaders/"
before appending the string_view
to it to be able to open the file. This was actually correct, but because it didn't initially work, I was assuming that it was wrong.
The correct string value for going back one directory should be "../"
at least on Windows
, I'm not sure about Linux
, Mac
, Android
, etc...
My problem wasn't with the string at all, it pertained to settings within my projects. Within my project that builds into an executable, I had its working directory set to $(SolutionDir)x64/Debug
and $(SolutionDir)x64/Release
respectively which is correct for my solutions structure.
The issue was within my Engine
project that is being built as a static library. Within its settings for its working directory, I had forgotten to modify both of the Debug
and Release
build options... These were still set to the default values of Visual Studio which I believe is (ProjectDir)
. Once I changed these to $(SolutionDir)x64/Debug
and $(SolutionDir)x64/Release
to match that of my ApplicationProject
, I was able to open and read the contents of the files.
Upvotes: 0