 I will do a short talk, it's 15 minutes talk, and I will not go into depth about shaders how it works in Unity because it's too big and I don't really know that much about it. I'm just starting myself with this kind of stuff and the purpose of this talk is to kind of for you that know how to code but don't really know what to do with this shader stuff. So you can make use of your current intuition for programming to transfer it to the GPU. So this is the example, it's not very easy to see but there's a lot of costs here. And I'll start just with a standard Unity example and then we'll transform that into the GPU. So we have a Unity script and there's a quote here, there's a card and the script has four... No, it's done now. The speed is the speed variation because we don't want all the cars to have exactly the same speed because that's the point. And we have a width and depth of the field with all the cars. And this is what the script looks like. We have the star function. So here we create the mesh and the texture has a lot of cars to get different colors of the cars. So we randomize the stripes and we make the billboards around four meters and then we set the stacks. So we have three variables. One is just the position with depth, the positioning X where on the field and how fast they go. And there's nothing special about this except for this. This is just to make it centered on the local position in Unity. And then we go to update. And here, each frame we just add the current speed to the delta time. And then when it goes too far we just take it to the other side of the screen. And basically it looks like this. So now the width is set to very small. So it just goes maybe 10 meters and then it flips back. So it's a very simple example and I try to describe how you can transfer this animation to put on the GPU. And in Unity you have a few options that are quite intimidating. And it looks like this one is the simplest but it's not. Because this has all the Unity shader models with bump maps and lighting and all that. So these are actually simpler and the difference is not a lot. This one has fog and this one doesn't. And you will use this one without fog. So what is the shader? I just took away all the, there's a lot of details. I just go for the basics here. So we have variables and we have them both in the kind of shader. And we also have them in this kind of properties list. And they will show up in the Unity pane. So you can access these values and see how they change on screen. And then we just have these two functions. One for the vertex and one for each pixel. So if we want to animate all these cars in parallel on the GPU. We need them to be in the same draw call. And to be able to get any of these callbacks for the vertex and so you can do anything at all. We need to have a mesh. So then we can ask, what does 1000 unanimated objects look like? And you can do this in many ways. And I just choose to do this. It's just that I kind of tube and I just create quotes. And this is not done on the GPU. This is something you do in it, in your usual Unity code. And now we have to come to the actual problems. So we can't run the code we had before on the GPU. First we don't have the object callback. It would be nice to be able to do a calculation per quote that we want to animate each car. But we can't. We just get per vertex. And this sounds crazy, but we just do the work again. We just do it four times. Four times the work. And then how do we know if we are processing a vertex which quote we're processing? And for this we'll use the C value. Because if you're a quote, they always have the same depth. And there is no random function on the GPU. And then we'll use a hash function. And a unique value per object. And this hash function is actually this C value. It's not supported on that. And this is the hardest part. Now we have to rewrite the code without state. So in the beginning we had variables like current position, current speed, and current. We can't have anything with current. Because we can't write to anything in this state. We can just output the new vertex. So if we look at the code, let's strip it down to the simplest form. We randomize, and then we add the speed to the delta. And we just move the initiation into the actual object. So here instead of the random we have the hash we're pushing the unique value. And then instead of having the delta we used time in seconds from the beginning of the game and the initial position. So now we can calculate the position without any state. And I actually removed one thing here to make it simpler. So now it will just continue, pass the screen, it never wraps back. And to do this we'll use the modular function. Because if we use the if function we'll just snap back once and then we have the problem again. The modular function is like a remainder of the addition if you don't know what it is. And this we add and subtract just to have it around the center of the transformer unit. So here it's kind of more of a complete. So here we get the vertex in and we set the decision. And then here we get the unique value, which is just the same value. And this is actually a constant in unity, just time one to get the time in seconds. And this is actually the same code we saw before. So the simplified code you can run it on the GPU and the CPU. But you have to do a lot of this things around to make it work. And this one is also a bit different. Because here we have the random value. We used to hash instead with it. And then we want another random value for the variations of the speed. And then we can't use the same because only we'll get the same random value. We want the unique random value. So just any constant to hash function and we'll get the unique value. And this is actually generated by unity. So it's just an extra transform so it will be at the right place related to the camera. A real example I made that you can download on GitHub. It actually has a lot of other stuff going on. And it's still 10 times faster than the CPU version. But we do 10 times the work and it's still 10 times faster. But that doesn't mean the GPU is that fast. Because a lot of these things have to do with architecture. So when you move an object in Unity, Unity has to sort all these objects. And with the GPU, I actually just sort like this. I just make sure I prepare the codes in order. So then you don't have to do any sorting. So this kind of runs with 15,000 cars on the area. And if you do it with the CPU, it will start giving you problems like 3-4,000 etc. Questions? You tried before the shaders for OpenGL shaders or Directive shaders. What was the difference between Unity shaders in the language? I don't really have a lot of experience with shaders. I did some WebGL shaders. And it's basically the same. So I think if you're doing the service shaders, like the short ones with all the Unity special stuff, then it's very different. Because then you kind of have to learn this kind of fields, the lightning models in Unity. I don't know much about that. But when you go down to this low level, they're basically the same. Because it's basically just doing the hardware stuff. So one of the things I'm noticing is that you are dealing with static game objects. Does that automatically mean when you were benchmarking, could you tell that these things were actually being included in the static batch? It did dynamic batching when I did the CPU version. Because otherwise it would have died much faster. Because you can't have 3,000 batches. That's impossible. From here it's recommended like 100, 200 batches. And I also could see in the profiler that it does batches very good in Unity. So it does segment the batches, but it batches them all. It's just very large batches. I think the problem is, even if you do very little, you can't do it 15,000 times on the CPU. It doesn't matter how little you do, you just can't do that much on the CPU if you use power on the low spec system. But it's final desktop. It's more unpredictable. I don't know. I think it has a lot to do with architecture. Because even if it has to do calling, it has to do sorting, and all of this is in the same time. So that's the way. Any more questions? Why are you particularly interested in GPU? What is your plan? Where point do you use it? I just do it for fun. For mobile VR, I know. Yeah, it's very good to get these performance boots, especially for VR VR. It's some effects possible that you would not be able to do unless you code on the GPU. And for me personally, I feel it makes the code more interesting because you have to do more like mathematics and you have to generate a function. It's more pure. It's also very annoying sometimes. But I think it's a nice change. And then questions. So what tools do you... I mean, what method do you do when you're debugging the CPU, especially in mobile VR? Because you need to... Actually, you don't see this mobile one, I guess, is it? I don't do debugging. What? You don't do debugging? How come? Also, your GPU... JS has got no bug at all. You need to be careful. But the thing with GPU... It's very easy to switch. When you do the C-shark stuff, you need to start the application. When you do the GPU stuff, you just alt-tab, and it's flush automatically all the time. It's so fast that you feel that. So it's actually quite nice to work with the shapes. And the way I do it, I just change... But then sometimes you get the black screen and stuff like that, right? Yeah, they turn purple. They turn purple. But then it's syntax error. Your hard part is when you have a behavior that you don't expect. But I mean, you just have to change a little at a time. So instead of writing the whole shader, you begin with something that's kind of an embryo, and then you change one line at a time, and you make sure you change it often. You make it sound so easy, but actually it's not easy. At least for me. Another thing you could do, like I did now, is actually start with a unity version, like a C job version, that you can debug. And then you can convert it into a form that's deterministic. And then you can convert that one into a student. You have verified it in machine works before you actually move it to GPU. Yeah, makes sense. Thank you.