"Please Tear My Code Apart" // Code Review

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up guys my name is China I'm still on holiday at the moment this time I'm in Sweden uh and then this email popped up in my inbox please tear my code apart I just couldn't resist you know so we're gonna take a look at Cameron Otten who wrote hey channel so I made this thing a while back in C plus plus was intended really to be a game more than an engine per se I got a little stuck but recently went back and fixed a couple things all right guys we possibly might need to bounce um are you uh all right so joining me for this code review is Peter who works at Studio Channel he's a Hazel engineer the camera doesn't seem to like to focus on him because we all know that this is my channel yep definitely Okay so we've got a C plus plus thing it's a game more than an engine recently starting to think of my career and would like to actually get into the industry and use this code is good portfolio so this is going to be like he wants us to be a portfolio right and he wants me to tear it apart so we're not going to be we're going to be a bit roasty we're going to be a bit harsh here I want to be a bit realistic okay so object-oriented programming he understands and sees its strengths and weaknesses but ultimately prefers to have Global functions I think that's probably a good idea generally I don't like it when people constrain themselves to like a particular code style right like it's yeah it's good when when you use a mix of styles yeah you should use like whatever fits especially if you're using a language like C plus class that obviously doesn't like constrain you into specifically being object oriented you know like something like Java it's you know it's often better to pick the right tool for the job and I personally don't think that any particular programming Paradigm is necessarily 100 suited and perfect for something like that yeah yeah like you should definitely just use whatever Paradigm fits the best for the task alright so please look in depth with this code there's a lot of neat stuff as well as some hacky stuff but don't go easy on me look at it as if you were hiring someone and we're looking at their competency as a programmer and yes main is a mess I know I know okay so it's always interesting to me when people send in code with like a hundred disclaimers because like you know when you read the text look look at it as if you were hiring someone and we're looking at their competency as a programmer but then in the same sentence actually no I mean there's a full stop yes and maybe not the same sentence but yes main is a mess I know I know it's like maybe fix it up first and then I'll look at it as if I was hiring someone okay so this is the actual uh project Itself by the way it's called think it's got some nice looking Shadows we'll do a quick look at that it's uh basically Hazel's Shadow system yeah but implemented not as well because it doesn't look as good but it's pcss so we've got some debug rendering and I guess the physics is uh custom right yeah it's from what I could tell it's pretty much completely custom um and I'm not sure if all of these um boxes are individual colliders I highly doubt it but the debug rendering would indicate that in which case they most likely use some sort of a sprout face algorithm I think they might be because they sell remember the cell kind of and the way that we we've probably sure what the levels look like I've had a quick browse yeah but yeah I think this is basically kind of like they've used like a tile map setup so yeah so like this is what the levels look like so I guess the they look like nerds there's a free camera as well I mean yeah it looks like just like a little kind of physics demo slash level layout yeah thing although the mouse isn't like captured yeah the mouse is hidden not locked but yeah here we can actually see that it seems to be using some sort of velocity expanded um bounding box for doing basically a broad face uh Collision check um which you know is clever especially when you have a lot of colliders um so like I'd say physics wise in terms of the actual functionality of it it's not bad like it definitely seems to be working and it's running pretty well although some of the Collision checks aren't quite accurate on certain corners it's like you you can manage to get into the actual geometry there all right so I don't want this to be another video about the build system um Peter and I looked at the build system um and uh I don't like it yeah um it's just a batch file like this I'd had Echo off at the start we had to uh disable that because we had to debug the build scripts and disabling that somehow fixed it yes so great yeah like I mean my suggestion obviously is like to use something like cmake or pre-make I mean I don't know why I said yeah preferably pre-produced primate but you know using a build system is a lot better than trying to write a script like this um obviously this only works on Windows anyway and it only uses Visual Studio which also begs the question why is this not just a visual studio solution yeah it was hard-coded to visual studio 2019 yeah which means oh yeah that's right we also had to change that yeah anyway we're not going to talk about the build system in this video we're just going to move on to the code which again does not have a visual studio solution so we just open up the full day in visual studio and here we are in the main file all right so here we are in the main function Peter I want you to look at this and tell me what you see if there's anything that like jumps out at you and if you were hiring someone for Studio show no more juice say so I wouldn't say that there's a lot of if for debugging and I will say that the code is not the most readable just because there's like a lot of this I would have grouped into better kind of sections either by using like a vlog scope or by simple moving them into separate functions yeah it's weird that this is all on the main function yeah like I mean he did say that main is kind of messy and stuff but it seems like all right let's take a look at this quickly like how much stuff is in here I think it's like 700 700 lines of code but it's also like it's the it's the entire application yeah like everything from initializing sdl to loading meshes and assets and shaders dispatch and draw calls is in there as well yeah debug rendering opengl code like I mean I mean he did say that it's kind of more of a by the way they don't apparently they don't make good shares in Sweden I mean it's a 10 year old chair I think we need to go to IKEA now if you're enjoying this roasting and you want me to roast your code I mean sorry review your code my mistake send it into chair review gmail.com there'll be some instructions in the description below but if you're not quite ready for the roasting if you're still a beginner then there's an excellent free way that you can learn computer science online with sponsor of today's video brilliant.org brilliant.org is an amazing website filled with lots and lots of courses on various stem topics thing that really sets them apart in my opinion is they're kind of visual and interactive and engaging approach to learning they've got some excellent kind of beginner level computer science courses that will really kind of hold your hand and gently introduce you to being able to think like a programmer and then I really highly recommend their math courses everything from like the Everyday Math course which is excellent for beginners through to things like algebra linear algebra calculus stuff that is honestly really useful to know if you're programming things like this game engine now as I mentioned Visual and interactive they've got like these widgets you can play with in their bite-sized lessons taking this stuff in visual really really important and they'll also quiz you to make sure that you're paying attention retaining this information and learning now the best thing about brilliant is that they have a 30-day free trial you can just browse their entire platform see what courses they have available try them see if it works for you for free just go to brilliant.org the Cherno and if you do want to like it they'd be nice enough to offer the first 200 subscribers 20 off an annual membership huge thank you to brilliant.org as always for sponsoring this video I've said this before by the way in other code reviews and it's always really difficult to not repeat myself but I think it's really really important to have an application like file and class you know so that you can just shove in all of the initialization D initialization kind of code into one place so that you're not polluting like the main function there's also a lot of renderer initialization related stuff like that should be in the renderer class you know there's so many different Engine Systems that I'm seeing here that really shouldn't be just in one file and in one place like this they should just be separated out I can also kind of see why people do things like this because it's I I think a lot of it comes from them wanting to just get it up and running and then improving it afterwards but I think there's a limit to to that because like Fast iteration is good but you should still not just dump everything into a single place and keep it there yeah now I think that I think that the other thing is like possibly when people don't know what the architecture should be yeah yeah because they haven't written stuff you know like if you've built an engine before and you know exactly like okay I need a renderer I need an application like file or whatever I need like something to uh you know hold like game stay like a scene you know the concept of a scene system like if you know all of that then that's great you can just be like all right well I'm not gonna waste time I know I need this file this you you could almost just make like all the classes up front leave them empty and then fill them in as you go because you know how it goes yeah exactly you know but if you're like doing this for the first time you might not know enough about it to start making structural decisions yeah and so you might just kind of pull up everything all into one place and then be like okay I'm gonna do because I do this as well like when if I if I if like let's just say I'm implementing grass rendering or something like I've never done before I'm gonna sit down and I'm across today yeah like it would be a waste of time and also unnecessarily difficult for me to go through everything and just be like okay um I'm Gonna Make This Grass generator class I'm going to make like this grass cash class or whatever I'm gonna have to make like some renderer functions that are going to I don't know build up some storage buffers filled with grass blades or whatever right like it it doesn't make sense to me because I've never done it before yeah so it might make more sense for me to just be like here's a function called do grass and I'm going to put everything absolutely everything there and then I'm going to go back through it like once it works because again step one I feel is always just make it work definitely right like just make it work and then once you've made it work you can refactor it you can iterate over it a few times to make it more flexible and more kind of maybe add more features and works extendable as well in the future yeah you know I think that's generally speaking good philosophy to have it's like there's there's no no real point in actually architecting this really complex system if you don't actually have anything working yet because you don't necessarily know what it's going to end up looking like yeah you don't know exactly what you wanted to to do essentially I think if you have something already working you can then work backwards from there to some sort of API that you actually like yeah I think another thing is like recognizing potential like almost like patterns and cards like you know the code we're looking at right now on the screen kind of coincidentally because we just scrolled to a random place it's like you know creating these Samplers for textures yeah in opengl and like the thing is you can kind of see the parts here that are clearly the same right so like these sample parameters are identical they're just setting the magnification and minification filters to be linear then we need to set the Border color and they're both being set to wire here yeah um you know then we're doing the wrapping and the pair modes as well like all of this stuff like this is a really good kind of opportunity to take that and be like all right how can I condense this code um by potentially making like a texture class which I mean it looks like there is one oh but it's just a struck so see this is like this is actually really interesting because this this is kind of where it's shying away from object-oriented programming and going a little bit more C style because what you do there is you have structures of data right so we just have a struct that is just kind of a pod type plain old data type there's no functions in here there's no like deep kind of pointers to other blocks of memory yeah there's just four integers of like data and then the functions around that like we have a function like create texture which is just a global function which will run that so this is a very C style kind of approach right yeah but I would argue that like in this case I feel like it's not as good and you know a lot of this is obviously personal preference so like here's an example from Hazel you know we're creating just a white texture right and this white texture is just something of the renderer stores because whenever you need like you know basically to kind of not have a texture set or something that you can multiply by to just get like you know because white is one so if you multiply by a white texture you'll you won't change the original data uh and this is like all of the code you know that does I guess all of this yeah basically right and it's way more flexible as well uh because I mean well for one this doesn't even include oh no the data is here okay all right so that's so the white is the border so we're not actually setting any data here for the shadow map I guess which is fine so this is interesting because it's kind of like it's also got that approach you know where where like this is kind of a pod data struct right this is the actual like specification for that texture so what kind of texture would you like to create by the way what do you guys think of Peter's uh color Style a little bit different than mine I'm trying to get ripped from jet brains ah disgusting didn't tweet the things I didn't like because like most of it yeah pretty much so you can see that like this basically just tells you how to create that particular object right it's just the specification for it we can set it up we can share it it's very easy to copy it as well like if you want like a spec that does like 90 of the stuff similar to another spec then you can just go ahead and obviously copy it just like a normal object copy right um but then this is the line of code that creates the texture and you can see it just takes in the spec which tells it what kind of texture it is so it's a one by one rgba texture and then we take in the actual texture data that it will automatically kind of upload to the GPU and then internally obviously that will create like a Vulcan texture and it's ready to go and it's stored inside this object so what I like about that is that it's incredibly simple like from an API point of view you know as a human kind of reading this code you can immediately just be like what's going on here oh well I'm creating a one by one rgba texture with this data and it's ready to use like I don't think this could be more simple Ellie's not without sacrificing like the flexibility of what's possible with this actual API yeah by the way guys I'm trying to lean back so that we're both in Focus because autofocus yeah so don't mind us being blurry yeah but yeah no like even having like a specification struck for types like the application like it to me it just makes it nicer because you don't have 20 different parameters to a Constructor yeah well that that that's the thing like you know people don't like huge functions or huge Constructors with lots and lots of parameters but then like you know what happens if what you're writing is complex yeah you know that's the thing like I feel like a lot of programmers who are maybe more like beginners or inexperienced like you know they'll always be like they'll look at code and they'll maybe feel overwhelmed by it and they'll just be like no this sucks like I don't understand this or this is like why are you over complicating things why are you making it like this but the thing is there's a death and over complicating stuff an over engineering topic that's definitely a thing like that's a big thing right but there's a difference between over complicating something right and just having a piece of code that actually is complex because it just does a lot of stuff yeah like we were talking about this last night like game engines like physically do a lot of things yeah that's why the files are so big that's why there's so much stuff it's not that the actual code if you break it down piece by piece like at least with hazel like I don't think of course there are some complicated stuff maybe you know for someone the shaders and Graphics passes we might do that might require a little bit of research to understand but generally speaking the C plus plus code I don't think it's that complex yeah it's just there's physically a lot of it and I compared it to like you know a short story versus like an epic right like an Epic Novel like that obviously like the two different things like they're not necessarily going to be written in like you know one is like I mean shorter things generally might be like you know like a children's book is obviously generally not a thousand pages long but it's not necessarily like more difficult to read something that's longer because it entirely depends on the language that is used and the style that it's written in and so I think with code as well yeah you can obviously have something that is uh you know very very complicated and long or you can have something that is long but it's written really cleanly and it's easy to understand but you know a gay mentioned just has a lot of things that it physically has to do and there's no way around that yeah and like I think that becomes obvious when you look at some of his little system is it's just like sure you know we might have a file that's 5000 lines of code but when you're actually break it apart it's not overly complicated it's just there's a lot of code needed to get the job done yeah no I definitely say yeah when it comes to code there's a huge difference between complex code and large code okay so the other thing that uh kind of Peter mentioned a bit earlier was all this debug code right so again um just and it's funny how like I feel like Moses code review could really just take place in this file because even though there are other files here like you know a lot of it seems to be in Maine yeah um and I mean these files are huge which a lot of people would look down on but I don't I think that having large files is totally okay yeah as long as it makes sense like meaning that like you know all of your stuff is kind of relevant like this is another great example of why this main function is so bad there's so many reasons but one of it is because it's not just doing one thing it's not just doing like a couple things it's literally like everything from you know setting up this game setting game memory thing which by the way we probably should take a look at a little bit later as well just because this is kind of unique yeah um game State actually had like an application oh yeah but a safe destructive data yeah that's the thing like it which again it's fine like it's I like I don't agree with this I would make it more object-oriented but it's fine to have it this way if that's who you are as long as you still make an application.cpp file that contains those related Global functions yeah like you don't want to just put everything here and I mean the stuff here isn't even in a function it's in the main function yeah you know so all of this all of this is just kind of floating around here but again like with the main function specifically it's just because there's everything from like you know game State game memory initialization those kind of systems to like sdl and creating a window to or initializing opengl to loading data to you know obviously running the game Loop all of that stuff yeah it's like that oriented programming is perfectly fine and it's you know you should be using dot oriented programming at times it's when you have data oriented programming but there's no structure to it that it becomes an issue for me because it's like there's nothing wrong with you know working in C for an example just because it doesn't have classes and Constructors it's still fine because you can still emulate that and people haven't doing that for decades it's just when when when you have like data oriented programming in terms of the actual data structures but then everything else just dumped into random places that's when it becomes an issue for me I kind of I'm not sure if this is data oriented kind of programming like well at least the way like I mean the way I Define data or into programming is it's specifically designed in a way like where you're you're paying attention obviously to like the memory layout to the cache coherency yeah to all of that stuff right just by what he's done I mean I'd probably call this more of like just procedural kind of programming yeah where it's like you know you just have your structures which contain data and then you just have functions which run stuff on that data there's just everywhere like in the entire project really uh it's not just like in the main function there's other main function is like half of it yeah um there's just a lot of these if def debugs which actually like strip a lot of the code from release builds and like obviously you have to strip stuff from release builds because you you're gonna have code that you know shouldn't run in release mode because it's just there for debuggability which actually let me stop you right there this is also why I haste this idea of debug and release because there has to be like in my mind there has to be three configurations yeah there has to be that's why Hazel has debug release and dist yeah because like the problem is debug implies no optimization and like debug to me really means like break point IDE kind of debugging yeah you know and for that you obviously can't really optimize code can't really inline code at least not as well you can't go too crazy with the optimization otherwise you won't retain that original code structure that lets you kind of inspect every variable you know you'll strip stuff out there might not be used but that you wanted to debug because you're working on you're in the middle of working on something you know yeah like debugging that's what debug is right but the problem is if you just want to have debug rendering which like if we look at this code as well like you know debug Shader like this stuff is drawing debug graphics like you absolutely want that to run not only in debug because debug first of all might be too slow yeah like that's another thing right like because debug has an optimization like yeah it's great for breakpoint debugging but it's not good for debugging within the tools that you've built into the application yeah like if a game engine editor ran in debug mode it would be very very slow like it could be like 10 FPS right and it's unusable so basically you definitely want to like be able to run everything and release and still have all of your debug tools available to you so that's I think the weirdest thing to me straight away apart from again these if devs that just kind of make everything dirty but like it's just the fact that like you know you're stripping the set of release builds yeah like this stuff is really useful yeah it's kind of like um I I looked at that code I did Card review of a project where they did um I think it was like a ray Tracer and then they had debug single threaded and released multi-threaded yeah and it's like that's two different code like that's entitled two different like that shouldn't be you know if you want to have multi-threaded or single threaded and you you absolutely want that to be compile time make a separate macro or like a separate kind of Define that's like multi-threaded or not so that you can then be like okay I want single threaded debug mode or multi-threaded debug mode because you might want to be debugging your multi-threading code yeah you know like it's weird when people kind of tie stuff you know to debug even though I guess in a way that makes sense I mean it is possible though like we didn't really look at this though it's possible that we're just wrong about this like I mean this this might not be the debug configuration like this is defined anywhere might be in the old script um that's just yeah so it's defined the debug is on and this is why this is a debug build yeah they don't have a release built so so interestingly they don't seem to have in the build script there doesn't seem to be a release build they're just like I'm just looking at debug build finish debug build unsuccessful like everything's a debug build yeah so there's no concept of release configuration at all I don't know it's weird it's like it's so annoying to then go through and be like let me add another one of these for release like just use use either visual studio with Visual Studio project files and a solution and everything or use like pre-make or even like cmake would be better than this to be completely honest and that's saying a lot honestly probably even using make on a Windows but bit better than the Mac which you know that requires a whole rabbit hole that requires reading like a thousand page book probably probably but yeah wait you know some of that stuff that's been put into like these if deaths should not be uh probably done outside of a very explicit debug mode some of it should be done in debug and release but not a distribution yeah and some of you probably shouldn't even exist I guess my main point here would be that you want to run your your code you want to build your code with optimization on fast mode on but retaining your debug tools yeah right that needs to be a configuration because that is the most like how I mean how often do I run Hazel and debug yeah like very very rarely only if I'm really having to step through and debug stuff yeah usually for higher level stuff it's always running release mode and I just use the tools that I've built into Hazel yeah you know but then this distribution is for like I'm shipping my game so yeah absolutely strip all the debug code yeah like I spent quite a bit of time debugging Hazel in proper debug mode um like physics and C sharp scripting and all of that requires me to very uh like step through each line just and have all of the info that I can get from it and it like that's painful and you know I can't imagine doing that in a even more complex engine a lot of uh projects and I think it's a default in cmake they'd call it Rel with debug yeah where you have some optimizations on and you have some symbols on but not all of them and then there might be some other options like debug renderer so you can actually visualize the data itself yeah the only like in again Hazel like debugging release the only real difference is that like it is the optimization really it's just optimization but then release will add stuff like inlining and like actual just code optimization on and you know faster floating Point Precision that kind of stuff but like dist is the only config that actually strips debugs yes you know like debug symbols are very present in release still because that's still an internal build as far as we're concerned dist is the only build that gets distributed and so of course we want to strip all like the function names and all the symbols yeah you know from that like the debug information but I guess my point of view is that if it's not if it's still internal then like why remove stuff that helps debugging like internal should mean safe meaning that I'm not part of about being hacked from within my own company hopefully so like it's fine that we you know retain all that stuff obviously yeah because like here we have I'm not sure what screen space vertex does but it like presumably uh there's some like physics Collision debug rendering going on um and having that in release mode is incredibly useful especially considering like physics on its own can be quite heavy and you you really want to be able to debug the information accurately and you can't do that if each physics tick takes you know 25 milliseconds so these kinds of things probably should have just been a runtime Boolean that you can toggle on and off the other big thing about debug card as well like the whole if def debug you know because that comes up a lot like if we just go through this file and I was like seven or eight times so the thing is like obviously that's polluting the code but also when you're reading stuff like this you know it's it's really quite annoying to stumble upon stuff that's purely for debug and then obviously you have to scroll past that and kind of keep going yeah right like you I feel like because debug code like this is clearly supposed to be it's kind of circumstantial like it's only on in certain configurations like to me it's kind of like an optional module like you know you can compile this with extra debugging stuff kind of present yeah and so since it's an optional module it should be it should act like one it should be separated out into like a separate file ideally that is just like okay this is like I don't know what this is like some kind of debug Graphics stuff so make a file called debug Graphics you have your debug Graphics header you have your CPP file you can conditionally include that file for compilation only if you want debugging kind of enabled and so what what you're kind of doing there is you're separating it from the mainline code and you're making it non-intrusive anymore so that it doesn't kind of inject itself into there and it would only be kind of used if it's actually kind of present and I think a really good kind of comparison to what we have in Hazel is um we have you know the scene rantra and then we have something called the scene renderer panel and the scene renderer panel has an online GUI render function that is only present in hazelnut which is our editor and you can see that like there's a lot of iron gooist there's a lot of UI stuff here so what this does is it just gives you an entire panel inside the game engine editor that you can use to like control the graphic settings you know access kind of you know Graphics debugging tools and stuff like that that are relevant to the scene renderer which is what we use to render scenes in Hazel and you can see that like again it is a completely separate file and we can just be like you know what this file not compiled for distribution but in the past it used to be inside the scene renderer file and that was annoying because this is a huge file but that was annoying because obviously if it's inside this file then we'd either have to like put use macros or kind of if devs to strip that out and it kind of makes this file even longer and not so much relevant because you know the scene renderer like it's supposed to render scenes the ideal thing for that would be you know it contains only the code necessary to render a scene and then extra stuff that is only relevant to the game engine's editor can either be only in the kind of editor module so we can only have that in hazelnut for example or if we still want it present for like debug or release builds in the game Run time it could also still be in the common Hazel Library but the point is that it's not kind of a requirement of the scene renderer class to necessarily include debug stuff like you're kind of drawing that out and you're making about an optional extra Edition that is not intrusive at all to this kind of primary code third base and to me that's also a really important thing that you could do here like you know you could kind of bring that out into a debug renderer that is only present in whatever configuration you want and then set up your build system to just not compile those CPP files in certain configs um and that would just be a lot I think a lot cleaner yeah I think another example of that would be in physics there is yeah it's fair Collision check I believe it was we have this if that debug which first of all has a runtime check as well which you know is fine but it seems to submit actual geometry information for rendering the debug information for like this Collision check which I I can see why they would might put it here initially while they're writing the function so they can test everything but for actual like you know in a proper project I would probably have put this as a thing in the debug render and it would have some sort of internal State as to whether or not it should render the debug information for the physics and I think we have that in uh in Hazel as well although that might be in scene render um not actually I think this is one of the things in Hazel that I don't quite like yeah so in Hazel it's actually in the scene which probably should be in the scene renderer but it's still it it's not part of the actual Collision check yeah so in my opinion it shouldn't necessarily be right here it's weird as well because like sorry one thing I noticed is the debug memory is not part of this and I feel like the reason why it's not part of this is because see it's a required parameter yeah for this function right so sphere Collision check absolutely has to take in debug memory which may or may not be used I guess based on if this this macros on like if this Define is on yeah so that's a really good example of why this stuff needs to be separated like you should just have your sphere Collision check which does just the actual Collision check that it's supposed to do just the math really for that and then an entirely separate function in the debugger Android that could be used to visualize that and like again there's no reason why if like if this stuff is actually doing like well I mean what does this need it needs position and velocity and stuff and maybe this stuff like it's positioned in velocity are just kind of passed in anyway so they're not like calculated using this but even if they were dependent on this code you can just either copy and paste this code or separate this part up into a different function whatever you want but the point is there's nothing wrong with potentially even duplicating this code just for the debug rendering if it means that debug rendering is completely separate from the mainline kind of implementation because again I guess my point is it should be kind of like water and oil right you have your water and then the oil sits on top and it's completely separate it's completely clean when it starts being mixed together are and you just have debug stuff and debug rendering intertwined with your real code like that just kind of creates a huge mess unless you're maybe temporarily doing it while you're writing this function itself yeah doing it temporarily while you're writing it uh can be really useful but once you're done with the function and you know that it's well you know it works for now like you should move this out to a place where it doesn't interfere with the purpose of this particular function which is to check for a collision its purpose isn't to do rendering this shouldn't in my opinion should be aware of rendering at all it should just be practically pure math yeah all right last thing we kind of wanted to touch on is at the very beginning of this main function we have this concept of game memory and we call game memory dot allocate right so what this seems to be is a struct of memory blocks and like you know here you're using a function so it's clearly not like strictly I guess C style where it's like all of the structs that you ever use in all the classes structs you ever use are just pure D types like they're not but anyway um this has a bunch of memory locks and memory blocks are up here they seem to just be a pointer to block a memory which you can potentially request and then the allocate function will just do a bunch of math to calculate the total allocation size in bytes for all of these different Engine Systems and then you'll allocate that basically into a single block of memory and then kind of just segregate the blocks so that you have a pointer to each category you know within that one big memory allocation which is a very interesting concept like I usually would be on board with something like this because it does result in just faster a faster program because if you pre-allocate everything first of all you have a nice big block of memory second of all it's all contiguous yeah you know all the allocations are kind of free within that right because all you're doing is just moving pointers you're not actually doing any memory allocation and again it's all kind of close together physically it's like you've almost allocated a custom stack yeah point exactly yeah um and so it's good but what I don't like about it is how difficult it makes your life you know when you're using this system because first of all again you need to make sure that you have all of these defined set up right like I I'm gonna have you know how many is this even there's 10 million one million 10 million I think right by the way in C plus plus you can do stuff you can do you can do this yeah um which is super useful so yeah you know you have to be like oh yeah 10 million votes which first of all could potentially be a huge waste of memory yeah right because you don't know how much you need but also if you do happen to exceed that it'll crash which is you know an issue we currently have with Hazel's food your Android because I did the same thing so I'm guilty of doing stuff like this as well and it sucks like I've been through this I don't like it so this is kind of like at that awkward stage you know in life where you're like let's just say halfway between child and adult and you don't know what you're doing and because this is halfway between just using a C plus plus as memory allocation tools which are great like in in terms of ease of use I want memory let me just run new and that's it I'll get my memory done sorted is it the most efficient run time no but it's definitely the easiest if you're the programmer right and the other side of the spectrum is like an actual like potential Arena allocator or whatever per system or whatever which would speed up the program potentially significantly right and just be like a more efficient way to handle like the memory needs that your engine or application might have but this is in that in that awkward stage in between where like it's not easy it's not resizable it's not adjustable at all you have to decide up front at compile time exactly how much memory you want to allocate which might be true it's not going to be the perfect amount right it's going to be either too much or 2 too little too little means it crash too much means waste right and also using this stuff was the biggest issue for me like you know check this out oh I want to store the player transform let me just call memory.transforms.request from block one like what like you know what I mean as opposed to what like what is player transform it's an auto oh that's a memory request and then you have to be like player transform dot memory position right like so transforms is a memory block of transform which contains these things right so what like the alternative will kind of be like you know where's Sonic are this yeah so okay so Ctrl shift oh just uh shift and there okay and then you just you know you just do transform dot position equals I guess my point is that like you know if you've gone from this to this you know which in my mind is like like that's crazy yeah you know you've made life so much harder for yourself like and again like yes it might be faster on the on the CPU side of things which is great I'm all for that but uh what I'm saying is that your goal should be I want it to be like this now you're not gonna be able to get it perfectly like this and this is on the stack as well but there's no reason why you can't make it not this specific yeah right like you need to find a better way to make this API so kind of retain the usability and how intuitive it is right to kind of be as closely as possible to I guess like either the bass C plus plus or just like a good API right so your goal is kind of to make this transition from let's just say worse performance I mean this is on the stacks this is actually ideal but let's just say this was on the Heap right from kind of worst performance to better performance but you're trying to make that transition as frictionless as possible that's the key word frictionless you want it to be smooth yeah with something like the memory allocation um strategy Harry I mean first of all they did live a common saying they they know it's not good and that is problematic for all the reasons listed previously but this is a job interview yeah as I'm concerned exactly it's just too verbose first of all to actually like use the API it's you don't want to have to go through all these hoops just to get a new transfer what I would preferably want is to be able to do just a stack allocated transform you know set all my data on all of that uh possibly store that in some kind of component or on an entity and then what you could do is you could have a essentially a pre-allocated buffer in say your rendering system because your renderer needs to know the transforms and I should go when you submit matches and entities for rendering you just put all of the transforms into that buffer starting in zero and once you've done that you know you can go ahead and render everything at the correct positions and all that and yes that does result in a copy operation but you know so does this these are all copy assignments but yeah like the way I probably would have done this particular like allocation strategy might have been through some something like a um a lazy allocator that just grows as needed preferably not uh land nearly by just incrementing by one instead it might do what standard Vector does which is uh I believe Grows by 50 percent um because that way 50 I think in mscc and times everywhere else yeah and like that way you you still get that resizability but you won't grow so much that you end up using a lot of unnecessary memory or at least it will take you quite a long time to get to that point but this this doesn't grow at all does it no no this thing's just from a fixed thing but you can you can't just see the amount of items and obviously the amount of transforms that there are here have been reserved to be Max transforms which is a thousand yeah and then I guess all you're saying here is that I'd like one please yeah and you get I guess basically a pointer a rapid pointer into that one transform which you can then use yeah another problem I just realized that this is there's nothing preventing you from writing outside of this it's like sure I'm requesting one but I could easily just end up you know hiding yeah way outside yeah because if you change the one to a two then suddenly you can you know I mean because obviously you could just another way to write this would be right so that was that's identical to what he had before but obviously you only have one and if you suddenly change it to two then obviously array index one is now valid as well yeah and so I guess I mean yeah but I think the way it actually like does it is like if you take a look in here it just sets it to uh item index into block which means that like if I just say here I request three the thing is the pointer is obviously is pointing to contiguous memory yeah so what's to stop me from you know this could be done accidentally if you're doing it in a loop like I could still end up riding into index 10. yeah and like this is valid yeah in terms of the compiler no but it'll also be valid in run time until you end up overriding that because the allocator thing starts a free block of memory is there any kind of freeing uh I don't see anything yeah this so this is just a you can't reuse memory here either yeah so that's obviously not good nothing you do can be transient everything is permanent yeah and also I was I was just I was just thinking about this while you were talking is that like obviously like you know you're riding into player transform this is what you're dealing with so you're not dealing with transforms yeah you're dealing with memory requests of transforms which means that when you actually want to use it for something such as like hey here's the player entity player entity just has an index and that index is the index of like the memory request yeah and then you create like a render entity from that and then I guess that transform index like it's just I feel like it's it's adding an extra level of interaction and complexity to everywhere because you can't just pass objects or whatever around you end up passing some kind of memory request indices which yeah so I'm not a big fan of that either especially because it doesn't like this literally adds nothing these systems are fine I feel as long as they are abstracted away yeah because that really should be the goal when they're at the foreground then they make everything a lot harder yeah and like that kind of goes back to like what I was saying with um renderer having like a transform buffer that's first of all contained inside the renderer itself so you don't have to interact with that directly as the user and so what you just end up doing is saying Hey I want to submit transform to the renderer and this is the Transformer I want to submit and if you if you really don't want to do a copy here you know pause it by reference you should probably pass it by reference because it's a transform it's not small and then that could be stored internally in a buffer in the renderer which can then be used to draw entities at that transform um yeah so I don't know there's lots of other stuff we could talk about uh but I think that I'm probably going to end it here hopefully those three points are kind of helpful I guess we decided to kind of pick a few points and expand on them rather than actually go through every line of code just because that's a little bit unmanageable but thank you guys for watching hope you enjoyed the video and if you did don't forget to hit the like button if you want me to review your code then send it into channelreview gmail.com there'll be some instructions in description below and finally brilliant.org slash the channel check it out I'll see you guys next time goodbye
Info
Channel: The Cherno
Views: 41,867
Rating: undefined out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, game engine, how to make a game engine
Id: jCqO4hoB2EY
Channel Id: undefined
Length: 46min 36sec (2796 seconds)
Published: Thu Aug 24 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.