I've been a C++ dev for 16 years now. This series has been super helpful in getting my head around the Vulkan API
@paligamy93 Жыл бұрын
Its sooo many variables forreal.
@mananbhardwaj39762 ай бұрын
Vulkan the struct heaven. Gives me joy every second
@jentev72173 жыл бұрын
Really helpful source! I just started out trying to learn Vulkan, and got kind of overwhelmed in the beginning. The way you explain things and kind of work in a top-down manner really speeds up things and makes it more clear.
@BrendanGalea3 жыл бұрын
Awesome, thank you!
@fury26133 жыл бұрын
Please keep them coming. I would happily donate for these videos!
@BrendanGalea3 жыл бұрын
Thank you, that means a lot! I don't currently have any method for accepting donations but may set something up in the future. The next video in the series will be out very soon.
@pingosushi11542 жыл бұрын
Thanks for your videos Brendan Galea, I am a 12 year old, and I am having fun learning vulkan, and improving my c++. I tried learning openGL, but the tutorials were bad. I thought maybe try vulkan, and I found your series, I really like it, thanks!
@BrendanGalea2 жыл бұрын
Wow that's amazing, I wasn't even programming a hello world at that age! Glad you like the series so far!
@soolydooly1234 Жыл бұрын
Same here. Thanks @BrendanGalea!
@jyapp4489 Жыл бұрын
damn that comment about degrees vs radians hit hard. Trying to work on making my own game engine while refamiliarizing myself with Vulkan (worked with it a bit, but wanted to do it better this time around), and you're absolutely killing it with these tutorials.
@BrendanGalea Жыл бұрын
Thank you! Happy they’re helping
@DejaimeNeto3 жыл бұрын
All caught up! Thank you for the videos, I'm starting to feel like this graphics programming thing may not be black magic after all
@lukas-viering4 жыл бұрын
Awesome video, glad to see that youre still uploading!
@existentialchild6984 жыл бұрын
hi, i'm 15 and learning vulkan right now because i'm working on a 2d/3d python animation library with a C++ backend called "imagine" and this helps a lot! i can't wait until i finish the library so i can test out AI and make simulations like mandelbulb and other 3D fractals.
@BrendanGalea4 жыл бұрын
That’s awesome you’re already doing stuff like that at 15! I would’ve been just writing hello world. Ray marching is super cool and I want to do at least 1 video on it once the series is further along.
@existentialchild6984 жыл бұрын
@@BrendanGalea thanks and i can't wait until your tutorial on ray marching! you have really good production quality for such a small channel, keep up the great work!
@daniilvinnik4450 Жыл бұрын
How did it turn out, mate?
@coolmanthecool6038 ай бұрын
@@daniilvinnik4450 yeah ikr I gotta know more about this
@IvanHawkes3 жыл бұрын
These videos are really good, thank you, and please keep them coming.
@BrendanGalea3 жыл бұрын
Thank you! Next video should be out sometime this week
@nicobugs3 жыл бұрын
Did you actually follow the tutorial and reproduce or you just watch the video?
@flocela5 ай бұрын
Thanks! That was a really good one!
@magnias1214 жыл бұрын
Explained so nicely!
@ChrisCarlos643 жыл бұрын
Just commenting here for 2 things. I have been writing with Direct3D 11 for almost 2 years now, and working on my own engine for fun and learning. I have personally felt non-interleave buffers are generally better overall. Yes for simpler things it isn't an issue, but the usage of them isn't too difficult either and minimal changes could be made to use. I think it is also easier IMO to just read. I'm not sure why, but knowing I have my data of position, tex coords, and other types laid out sequentially in different layouts instead of interleaving them just works easier for me. My last comment is just saying thanks for this well done tutorial. I'm in process of trying to move out from D3D 11 and looking at Vulkan and D3D 12. It is nice that there are many similarities to help me jump in, but you do very well with going over the concepts and have some great diagrams to help illustrate, IMO, effectively.
@BrendanGalea3 жыл бұрын
Thank you, glad you liked the video! I don't quite remember how much detail I went into in this video. There's definitely pros and cons, but most of the time I'd say go with what you prefer. In the past for some older devices interleaved tended to be better performance wise, but that isn't really true anymore. In these earlier tutorials I wasn't on top of providing as many resources, I should have linked this anteru.net/blog/2016/storing-vertex-data-to-interleave-or-not-to-interleave/ It's a good example of how de-interleaved may be actually the better solution these days. One thing I would like to test out is if there's a measurable performance difference with a hybrid approach. The example I have in mind is that it's pretty common for some render passes such as when generating a shadow map to only need position data. In that case maybe doing a de-interleaved position attributes buffer so that it can be bound seperately, and then interleaving the rest of your data for doing more typical rendering passes would be the best? I really have no idea without actually taking the time to measure it. The main reason I chose to do interleaved in the tutorial series was mostly for educational puroposes, as it's the slightly more complicated thing to demonstrate and still commonly encountered.
@ChrisCarlos643 жыл бұрын
@@BrendanGalea this post is what got me to also make the switch! I had a hard time getting used to understanding VBs myself when starting out and when I read this post I started to see things differently. Making simple games and demos I used interleaved for a while but I just felt restricted and couldn't figure out ways of managing my data or when I wanted to expand or do something, I hated the feeling of dumping a large VB data just to only use one or two components. Thanks for the well detailed response and your work. I'm still trying to get into Vulkan, only been at it for a few weeks, but totally been doing some good progress thanks to your videos. :)
@nice_sprite5285 Жыл бұрын
I turn 9 this week and for my birthday im learning how to do a vulkan triangle, these tutoriald help a lot!
@fold4x11 ай бұрын
Didn't you mean 19 ?
@coolmanthecool6038 ай бұрын
are you sure?
@coolmanthecool6038 ай бұрын
You were making videos at age 1?
@this_is_private3 жыл бұрын
i'm really excited so far :-D thats the best tutorial for vulkan. :-D
@pachete.4 жыл бұрын
nice, keep it up. thank you!
@camus1413 жыл бұрын
Thank you very much!
@giantbee97633 жыл бұрын
Thank you for the videos, I just have three suggestions/thoughts on how the material have been presented so far: 1.It takes a long time for you to go through the parameters/validation layers line by line, where it is both mind numbing to listen to, and possibly not beneficial to skip (since you insert very useful information in between ;) ), I liked better the pastebin approach you took on the video in which the lve pipeline was created. Although this could certainly mean more time required for you to edit the videos and etc. 2.Also, it may be nicer to organize, the code writing to logical steps, rather than how the C++ code is structured in the end. I am certainly learning from how you organize your code, C++ code organization as well, which is great, and thank you again :) However, it could be difficult to follow when the narration just says : Write these lines, now write these lines, and these lines. I don't necessarily have a better alternative to what you are currently doing, but perhaps a suggestion could be to write the functions one by one in a logical manner, explaining why and what we are doing all the while, and then go back to the header files? Or just simply have the header file ready to start with, and only talk about the implementation? 3.Finally, the last thought is possibly the crux of the previous two combined, so what I find as the biggest and possibly only issue with the series so far, is that much code and every word/character is read out loud for no particular reason. By no particular reason I mean sometimes what is done on the screen is read and not explained. It maybe a principle to follow to not read out the code, but explain the parts which needs explaining, and skip the obvious boilerplate, C++ features, and etc? Although the detailed explaination, on things such as vulkan's expectation of data type, RAII, and etc have been very helpful. It may also be good to write the higher level functions in the beginning, and populate down to the details. It is impossible/unnecessary to remember each line of code, so the general ideas are the most important. But these are just my personal opinions. Aside from these suggestions, your videos have been enjoyable and educational. One thing that I do like in particular is your animations and illustrations! They are unique in style and very clear! Thanks again :) Giant Bee
@diegoaugusto15613 жыл бұрын
Loving the tutorials but gotta agree readingout loud lines is not very informative. I'm not using c++ so sometimes I get a bit lost when following line-by-line instructions. Maybe a high or mid-level explanation of what's happening would fit better, like "oh, we need to set all these parameters because of the way vulkan maps memory, etc". On parts 3 & 4 there was a lot of explanation of this sort and it helped a lot.
@BrendanGalea3 жыл бұрын
Thank you for the great feedback, i definitely appreciate it and see what you mean, especially concerning reading out loud every word/character. I'll try my best to improve on this in the future videos I make :)
@diegoaugusto15613 жыл бұрын
@@BrendanGalea Thanks dude, you're awesome :)
@giantbee97633 жыл бұрын
@@BrendanGalea Thank you! Your videos are great!
@willisburg25623 жыл бұрын
Amazing videos, easy to understand and very informative, though one thing I noticed is you saying "attribute" as "a tribute" xd
@BrendanGalea3 жыл бұрын
Haha now I’m always going to think about this 😅 glad you like the videos!
@pdgiddie2 жыл бұрын
I've not heard this pronunciation before. It's generally pronounced "AT-ribute", not "a-TRIB-ute". But when talking about the action (e.g. "attributing blame"), then that second pronunciation is used. No biggie. Could even be a regional variation. Just thought I'd throw it out there :)
@KoruxTV3 жыл бұрын
Great video! extremely resourceful
@PaulPaulPaulson2 жыл бұрын
Bonus points if you can implement the sierpinski triangle without recursion but with simple loops. This is something that is worth learning since replacing recursion with loops can optimize your code quite a lot in some cases.
@BrendanGalea Жыл бұрын
I don’t think I’ve seen anyone do that yet!! And your absolutely right that loops in many cases can be a lot more efficient
@lagmaster1025 ай бұрын
yup, looping is what i did: std::vector triangleList; triangleList.push_back(CreateTriangle(initialTrianglePositions)); while (i < iterations) { size_t newTriangleListArraySz = triangleList.size() * 3; Triangle* newTriangleListArray = (Triangle*)malloc(newTriangleListArraySz * sizeof(Triangle)); if (i >= 6) { // from here on, the iteration will require at least 3^5 operations, so swap to multithreading multi_sierpinskySubDivideAllTriangles(&triangleList, newTriangleListArray); } else { for (uint32_t it = 0; it < triangleList.size(); it++) { GraphicsEngine::SierpinskySubDivideTriangle(triangleList.at(it), newTriangleListArray + 3 * it); } } triangleList.clear(); triangleList.reserve(newTriangleListArraySz); triangleList.insert(triangleList.end(), &newTriangleListArray[0], &newTriangleListArray[newTriangleListArraySz]); free(newTriangleListArray); i++; }
@telli586811 ай бұрын
Hi, i have a validation layer error such as Perormance Warning: Unassigned core validation shader output not consumed, type VK_OBJECT_TYPE_SHADER_MODULE messageID= 0x609a13b. Vertex attribute 0 not consumed by vertex shader - edit: oops, recompiling the shaders fixes that error but i still get another that says terminator_createInstance: Failed to CreateInstance in ICD 0. Skipping ICD
@sp1xa3 жыл бұрын
Amazing tutorials
@BrendanGalea3 жыл бұрын
Glad you think so!
@user-dh8oi2mk4f3 жыл бұрын
9:34 Depth buffer values always range from 0 to 1. OpenGL simply uses a different range for the z axis.
@BrendanGalea3 жыл бұрын
yes you are right! I guess I wasn't remembering correctly :P
@yaircambordamorocho45063 жыл бұрын
omg!!!!!! tnhx so much.
@nikola3730 Жыл бұрын
Remember to recompile your shader afterwards, if you dont do so, it will always print a red triangle only because of hardcoded vertices
@brightonmica17543 жыл бұрын
Aren't you calling the copy constructor for LveDevice in LveModel's constructor? Amazing series. I've never donated to a Patreon before, but for content like this I gladly would.
@BrendanGalea3 жыл бұрын
Using a reference to the device avoids the copy constructor being called. I often will use reference types as member variables to imply that the class does not "own" the object member. So in this case the model class uses a reference to the device, which means that the model class has no ownership or responsibility to manage the device. This is probably something I should have explained in the series. Glad to hear you're enjoying the series so far!
@brightonmica17543 жыл бұрын
@@BrendanGalea Thanks for the explanation!
@TADevelopment2 жыл бұрын
For people struggling with Sierpinski Triangles.. My tip is to think of Coordinate Midpoints, depth value, and recursion. The algorithm is quite easy once you figure it out.
@magnias1214 жыл бұрын
Do you take donations? This has really helped me a lot
@BrendanGalea4 жыл бұрын
Thank you for offering! But no nothing currently., maybe in the future once I have completed more videos I'll set something up
@FunnyPigRun3 жыл бұрын
I don’t know if it is too late but may I make some suggestions about the build system? There is some bad practice going on with how you compile the shaders. I will explain in detail if needed. Anyways, thanks for the nice video.
@BrendanGalea3 жыл бұрын
Ya definitely!
@FunnyPigRun3 жыл бұрын
@@BrendanGalea Sorry for taking long to reply. The "Makefile" is supposed to describe dependencies within the project. Therefore, it defeats the point of the Makefile if you have to run "compile.sh" every time you type "make". So I suggest that you add the dependency between the final binary and the shaders. Since I use cmake, here is the code I use for that: "file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/res/shader) function(add_shader src) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/res/shader/${src}.spv COMMAND glslc ${CMAKE_CURRENT_SOURCE_DIR}/res/shader/${src} -o ${CMAKE_CURRENT_BINARY_DIR}/res/shader/${src}.spv DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/res/shader/${src} ) add_custom_target(${src}.spv ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/res/shader/${src}.spv ) endfunction() add_shader(test.frag) add_shader(test.vert) " If you were to directly write the Makefile (Note that cmake is just a tool to conveniently generate Makefiles which describe the dependencies between files), it would be something like "test.frag.spv: test.frag glsl ... ... test.vert.spv: test.vert glsl ... ..." Sorry if you knew all this but just omitted them for simplicity.
@BrendanGalea3 жыл бұрын
@@FunnyPigRun Yup absolutely right! I thought for sure I had mentioned this in a previous video... but it seems like I updated my makefile back in tutorial 2 and didn't show it in the video 🤦♂️
@Cobblestoned1002 жыл бұрын
Thanks for the great tutorials! Here's a cool trick how you can keep it readable and still use brace construction: std::vector model::vertex::getBindingDescriptions() { return {{.binding = 0, .stride = sizeof(vertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX}}; } std::vector model::vertex::getAttributeDescriptions() { return {{.location = 0, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = 0}}; }
@cnsujeer3 жыл бұрын
Again great video. May be a silly question.. I noticed that you mixed up the draw and bind names while coding. But, how did you figured that out after you ran? I could not interpret it from the validation layer message easily. But, was that your hint ?
@BrendanGalea3 жыл бұрын
That’s a good question! But unfortunately I coded this so long ago I don’t remember. Sorry!
@beaumanVienna3 жыл бұрын
GLM_FORCE_RADIANS could be deprecated. A grep over the GLM sources has zero hits. Do you guys agree that it's not a thing anymore?
@BrendanGalea3 жыл бұрын
hmm ya from some quick searching it seems as if radians is the default case now, and force radians is no longer necessary. But I guess having it there couldn't hurt in the case someone clones the repo but is using an old version of glm.
@VoylinsLife2 жыл бұрын
So far I feel like OpenGL is a lot easier, but it may just be because I am more familiar with it already. The shader stuff with the locations and such is luckily similar haha
@BrendanGalea2 жыл бұрын
Ya especially when getting started OpenGL is definitely easier. It’s not really until you get to the more advanced topics that the benefits of vulkan start to become apparent.
@Max298473 жыл бұрын
Is it normal to feel like I don't understand anything about Vulkan yet or am I just not cut out for Vulkan.
@BrendanGalea3 жыл бұрын
Vulkan can be overwhelming and can be something that takes a lot of time. I wouldn't feel discouraged if you're having trouble understanding the concepts right away. Many of the concepts being taught are interconnected so backtracking and reviewing is definitely recommended. Some other great resources are vulkan-tutorial.com/ vkguide.dev/ and software.intel.com/content/www/us/en/develop/articles/api-without-secrets-introduction-to-vulkan-part-1.html Reading multiple tutorials can help explain the bigger picture, even if you don't follow the tutorial directly.
@Max298473 жыл бұрын
@@BrendanGalea Thanks for the reply I decided to learn openGL first which has been much easier and I found that a lot of your explanations have also greatly helped me learn openGL. I will defiantly be coming back to Vulkan and these tutorials in a few months when I feel I have a greater understanding Graphics Apis.
@PP-ss3zf5 ай бұрын
after following this, i got this performance error from Validation Layer when running - Vertex attribute at location 0 not consumed by vertex shader. when i recompiled shaders, this error went away. i understand the premise of this error and why it went away after recompile, but would appreciate if soomeone could provide a more detailed explanation. is vertex attribute defined in a general sense for all verts?
@Kondensatorr3 жыл бұрын
How would I go about rendering multiple models? Would you need to change draw and bind methods?
@BrendanGalea3 жыл бұрын
I think that’s covered by tutorial 11
@mishabytes82092 жыл бұрын
bro help me , I dont undestand the part where u bind buffer and vertexbuffermemory, what exaclty it does do there? do u save a buffer into vertexbuffermemory, or it say that every thing that u save into vertexbuffermemory it will be a buffer ?
@BrendanGalea2 жыл бұрын
ok so we have two member variables we care about here, vertexBuffer and vertexBufferMemory. Both of these can be thought of as kind of handles to information the gpu needs. - The vertexBuffer variable is kind of like the meta data thats going to store the information the gpu needs to know about this buffer. Such as the buffers size, type of memory its using, the type of buffer it is, the actual location in memory to store the data for the contents, etc.. - The vertexBufferMemory is like a pointer to the start of the memory range in the gpu where the actual contents will be stored (in this case the vertex information) When we tell the gpu to run a pipeline, vertex buffers act as one of the inputs to the vertex shader. It might be helpful to think of the vertex shader in this case as a function, the binding and attribute signatures are like writing the function signatures inputs, essentially describing the type info that the shader takes in. So when we bind the buffer, thats like calling a function and passing in a value as the argument. for example if you have SomeFunction(int a, string b) { ... } A vertex shader is like the body/implementation of SomeFunction The (int a, string b, ) part -> is like us configuring the binding and attribute descriptions And binding the vertexBuffer is like passing in the arguments for when the function is actually called. Hope that helps!
@ABHISHEKSINGH-nv1se3 жыл бұрын
Hi Brendan, can i learn vulkan without learning opengl??.
@BrendanGalea3 жыл бұрын
Ya definitely! Learning vulkan first can be a bit more difficult but it's definitely do-able. There many people following the series so far with this being their first graphics API and are doing well. However I would recommend a couple years of programming experience, and already being comfortable with c and/or c++ and memory management without garbage collection. Since learning c/c++ as well as vulkan at the same time can be a bit much to take on at once. One other downside to learning vulkan first is that since it's a much newer API, there's significantly less educational content and resources out there.
@Paf20222 ай бұрын
I get the error "Failed to find suitable memory type!" from the devices cpp file in one of the previous tutorials, and I don't know what causes the error. If I remove the throw std::runtime_error from it, and instead force it to return 1, the app doesn't crash. I had to change VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT to VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD earlier when doing the model.cpp because otherwise it would throw an error about it being undeclared, which is probably because I have an amd gpu (rx 6600 xt, to be specific) so maybe that could be related, but I'm not sure what the fix would be, and I'm not sure what about AMD's vulkan implementation would make a difference to that anyway. For now, I'll just keep making it to return 1 if it doesn't find any other memory types in devices.cpp.
@slendi96236 ай бұрын
3:43 I did something like this to help with all these values: // clang-format off template struct GLMToVkFormat; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32_SFLOAT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R64_SFLOAT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32_SINT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32_UINT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32_SFLOAT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32B32_SFLOAT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32B32A32_SFLOAT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32_SINT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32B32_SINT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32B32A32_SINT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32_UINT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32B32_UINT; }; template struct GLMToVkFormat { static constexpr VkFormat value = VK_FORMAT_R32G32B32A32_UINT; }; #define GET_VK_FORMAT_V(type) GLMToVkFormat::value #define GET_VK_FORMAT(type) GLMToVkFormat::value // clang-format on
@TGAPOO3 жыл бұрын
My Sierpinski impl was better in one way and worse in one way than yours. Worse: I was passing down Model::Vertex instead of glm::vec2, making averaging a pain. Better, I reserved the Vertices space ahead of time with vertices.reserve(std::pow(3, depth+1)) to eliminate reallocations due to growth.
@BrendanGalea3 жыл бұрын
nice solution for pre-calculating the depth!!!
@meepk6332 жыл бұрын
Maybe I have broken code, but I spent about 20 minutes trying to figure out why my triangle wasn't updating like the one you showed at the end. I suspect it isn't meant to be changing. If that's the case, I think it would be good to include information like "yours will necessarily be different than this example."