Engine
Frameworkcreatedbymeusableforthecreationofsimplegames.CurrentlysupportsOpenGL(Verysimple)andVulkan.
VulkanStaticMeshRenderer.cpp
Go to the documentation of this file.
2 
3 #ifdef USING_VULKAN
4 
8 #include "Engine/engine.hpp"
9 
10 namespace Engine {
11 
12  VulkanStaticMeshRenderer::VulkanStaticMeshRenderer(VulkanRenderer * renderer, VulkanLogicalDevice * device, VulkanDescriptorPool * descriptorPool)
13  {
14  this->renderer_ = renderer;
15  this->device_ = device;
16  this->descriptorPool_ = descriptorPool;
17  this->allocator_ = renderer->GetVmaAllocator();
18  this->commandPool_ = renderer->GetGraphicsCommandPool();
19 
20  staticMeshPipeline_ = eastl::unique_ptr<VulkanPipeline>(new VulkanPipeline(device, renderer));
21 
22  staticMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER, "StaticMesh.vert.spv");
23  //staticMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::GEOMETRY_SHADER, "Mesh.geom.spv");
24  staticMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER, "Mesh.frag.spv");
25 
26  staticMeshPipeline_->AddVertexInputBindingDescription(0,
27  static_cast<uint32_t>(sizeof(Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
28 
29  staticMeshPipeline_->AddVertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position));
30  staticMeshPipeline_->AddVertexInputAttributeDescription(1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal));
31  staticMeshPipeline_->AddVertexInputAttributeDescription(2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoords));
32 
33  staticMeshPipeline_->AddVertexInputBindingDescription(1,
34  static_cast<uint32_t>(sizeof(glm::mat4)), VK_VERTEX_INPUT_RATE_INSTANCE);
35 
36  staticMeshPipeline_->AddVertexInputAttributeDescription(3, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 0));
37  staticMeshPipeline_->AddVertexInputAttributeDescription(4, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 1));
38  staticMeshPipeline_->AddVertexInputAttributeDescription(5, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 2));
39  staticMeshPipeline_->AddVertexInputAttributeDescription(6, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 3));
40 
41  staticMeshPipeline_->CreateDescriptorSet();
42  staticMeshPipeline_->AddDescriptorSetLayout(VulkanMaterial::CreateMaterialDescriptorSetLayout(device));
43 
44  staticMeshPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, nullptr);
45 
46  staticMeshPipeline_->SetRenderPassInfo(renderer->GetGBufferRenderPass(), static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
47 
48  staticMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
49  staticMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
50  staticMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
51 
52  staticMeshPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false);
53 
54  staticMeshPipeline_->SetRasterizerSettings();
55 
56  staticMeshPipeline_->Compile();
57 
58  shadowPipeline_ = eastl::unique_ptr<VulkanPipeline>(new VulkanPipeline(device_, renderer_));
59 
60  shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER, "StaticShadow.vert.spv");
61  shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::GEOMETRY_SHADER, "ShadowVolume.geom.spv");
62  shadowPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER, "ShadowVolume.frag.spv");
63 
64  shadowPipeline_->AddVertexInputBindingDescription(0,
65  static_cast<uint32_t>(sizeof(Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
66 
67  shadowPipeline_->AddVertexInputAttributeDescription(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position));
68  shadowPipeline_->AddVertexInputAttributeDescription(1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal));
69  shadowPipeline_->AddVertexInputAttributeDescription(2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoords));
70 
71  shadowPipeline_->AddVertexInputBindingDescription(1,
72  static_cast<uint32_t>(sizeof(glm::mat4)), VK_VERTEX_INPUT_RATE_INSTANCE);
73 
74  shadowPipeline_->AddVertexInputAttributeDescription(3, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 0));
75  shadowPipeline_->AddVertexInputAttributeDescription(4, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 1));
76  shadowPipeline_->AddVertexInputAttributeDescription(5, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 2));
77  shadowPipeline_->AddVertexInputAttributeDescription(6, 1, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<uint32_t>(sizeof(glm::vec4) * 3));
78 
79  shadowPipeline_->CreateDescriptorSet();
80  shadowPipeline_->AddDescriptorSetLayout(renderer_->CreateLightDescriptorSetLayout());
81 
82  shadowPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, nullptr);
83 
84  shadowPipeline_->SetRenderPassInfo(renderer->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
85 
86  shadowPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, false);
87 
88  shadowPipeline_->SetRasterizerSettings(VK_TRUE, VK_FALSE,
89  VK_POLYGON_MODE_FILL, 1.f, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, VK_FALSE, 0.0, 0.f, 0.f);
90 
91  VkStencilOpState front = {};
92  front.failOp = VK_STENCIL_OP_KEEP;
93  front.passOp = VK_STENCIL_OP_KEEP;
94  front.depthFailOp = VK_STENCIL_OP_DECREMENT_AND_WRAP;
95  front.compareOp = VK_COMPARE_OP_ALWAYS;
96  front.reference = 0;
97  front.writeMask = 0xff;
98  front.compareMask = 0xff;
99 
100  VkStencilOpState back = {};
101  back.failOp = VK_STENCIL_OP_KEEP;
102  back.passOp = VK_STENCIL_OP_KEEP;
103  back.depthFailOp = VK_STENCIL_OP_INCREMENT_AND_WRAP;
104  back.compareOp = VK_COMPARE_OP_ALWAYS;
105  back.reference = 0;
106  back.writeMask = 0xff;
107  back.compareMask = 0xff;
108 
109  shadowPipeline_->SetDepthStencilState(VK_TRUE, VK_FALSE, VK_COMPARE_OP_LESS, VK_TRUE, 0.f, 1.f, VK_TRUE, front, back);
110 
111  shadowPipeline_->CreateColorBlendAttachment(VK_TRUE, 0u);
112 
113  shadowPipeline_->Compile();
114 
115  ubo_ = { glm::mat4(), glm::mat4() };
116 
117  uniformBuffer_ = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, renderer->GetVmaAllocator(),
118  static_cast<uint32_t>(sizeof(ubo_)), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, false, renderer->GetGraphicsCommandPool()));
119 
120  uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(sizeof(ubo_)));
121 
122  uboDescriptors_.resize(renderer_->GetThreadCount());
123 
124  for (size_t i = 0, size = uboDescriptors_.size(); i < size; ++i) {
125 
126  VkDescriptorSetLayout layouts[] = { staticMeshPipeline_->GetDescriptorSetLayout(0) };
127  renderer_->GetDescriptorPool(i)->AllocateDescriptorSet(1, layouts, &uboDescriptors_[i]);
128 
129  renderer_->GetDescriptorPool(i)->DescriptorSetBindToBuffer(uboDescriptors_[i], uniformBuffer_->GetBuffer(),
130  0, static_cast<VkDeviceSize>(sizeof(ubo_)), 0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
131 
132  }
133 
134  Engine::GetEngine().lock()->GetResourceManager().lock()->CreateTexture("default.png");
135  defaultTexture_ = eastl::dynamic_pointer_cast<VulkanTexture, Texture>(
136  Engine::GetEngine().lock()->GetResourceManager().lock()->GetTexture("default.png").lock());
137  }
138 
139  VulkanStaticMeshRenderer::~VulkanStaticMeshRenderer()
140  {
141 
142  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
143  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
144 
145  for (; it != end; ++it) {
146  it->second->transformBuffer.reset();
147  delete it->second;
148  }
149 
150  uniformBuffer_.reset();
151 
152  staticMeshPipeline_.reset();
153  shadowPipeline_.reset();
154  }
155 
156  void VulkanStaticMeshRenderer::StartRender(glm::mat4 view, glm::mat4 projection)
157  {
158  if (ubo_.view != view || ubo_.proj != projection) {
159  ubo_.view = view;
160  ubo_.proj = projection;
161 
162  uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(sizeof(ubo_)));
163  }
164 
165  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
166  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
167 
168  for (; it != end; ++it) {
169  it->second->transforms.clear();
170  it->second->meshes = 0;
171  }
172  }
173 
174  void VulkanStaticMeshRenderer::RenderMesh(const glm::mat4x4 & modelMatrix, eastl::shared_ptr<VulkanMesh> mesh,
175  eastl::shared_ptr<VulkanMaterial> material, const glm::vec4 & mainColor)
176  {
177  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
178  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
179 
180  for (; it != end; ++it) {
181  if (it->first == mesh && it->second->meshes < MAX_INSTANCE_COUNT && *(it->second->material)==*(material)) {
182  it->second->transforms.push_back(modelMatrix);
183  it->second->meshes++;
184  break;
185  }
186  }
187 
188  if (it == end) {
189  MeshData* data = new MeshData;
190  data->material = material;
191  data->transforms.push_back(modelMatrix);
192  data->meshes = 1;
193  data->transformBuffer = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(
194  device_, allocator_, static_cast<uint32_t>(sizeof(glm::mat4)*MAX_INSTANCE_COUNT),
195  VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, false, commandPool_));
196  meshInstances_.emplace(eastl::pair<eastl::shared_ptr<VulkanMesh>,MeshData*>(mesh, data));
197  }
198  }
199 
200  void VulkanStaticMeshRenderer::FinishRender(size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer)
201  {
202 /*
203  VkCommandBufferAllocateInfo allocInfo = {};
204  allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
205  allocInfo.commandBufferCount = 1;
206  allocInfo.commandPool = commandPool;
207  allocInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;*/
208 
209  VkCommandBuffer commandBuffer = buffer;
210 
211  //vkAllocateCommandBuffers(device->GetDevice(), &allocInfo, &commandBuffer);
212 
213 
214  renderer_->StartSecondaryCommandBufferRecording(commandBuffer,
215  VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
216  renderer_->GetGBufferRenderPass(), static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS), VK_NULL_HANDLE);
217 
218 
219  VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
220 
221  vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
222 
223  vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, staticMeshPipeline_->GetPipeline());
224 
225  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
226  staticMeshPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0, nullptr);
227 
228  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
229  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
230 
231  for (; it != end; ++it) {
232  if (it->second->meshes == 0)
233  continue;
234 
235  VkDescriptorSet materialDescriptor;
236 
237  materialDescriptor = it->second->material->GetMaterialDescriptorSet(threadID, staticMeshPipeline_->GetPipelineId(), 1);
238  if (materialDescriptor == VK_NULL_HANDLE)
239  materialDescriptor = it->second->material->CreateMaterialDescriptorSet(
240  threadID, staticMeshPipeline_->GetPipelineId(),
241  1, staticMeshPipeline_->GetDescriptorSetLayout(1));
242 
243  eastl::shared_ptr<VulkanMesh> mesh = it->first;
244 
245  it->second->transformBuffer->UpdateBuffer(it->second->transforms.data(), 0,
246  static_cast<uint32_t>(sizeof(glm::mat4)*it->second->meshes));
247 
248  VkBuffer buffers[] = { mesh->GetVertexBuffer() };
249  VkDeviceSize offsets[] = { 0 };
250  vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
251 
252  buffers[0] = it->second->transformBuffer->GetBuffer();
253  vkCmdBindVertexBuffers(commandBuffer, 1, 1, buffers, offsets);
254 
255  vkCmdBindIndexBuffer(commandBuffer, mesh->GetIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
256 
257  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, staticMeshPipeline_->GetPipelineLayout(),
258  1, 1, &(materialDescriptor), 0, nullptr);
259 
260  vkCmdDrawIndexed(commandBuffer, mesh->GetIndexCount(), it->second->meshes, 0, 0, 0);
261  }
262 
263  renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
264 
265  //*(buffer) = commandBuffer;
266  }
267 
268  void VulkanStaticMeshRenderer::RenderShadows(size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer, uint32_t lightOffset)
269  {
270 /*
271  VkCommandBufferAllocateInfo allocInfo = {};
272  allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
273  allocInfo.commandBufferCount = 1;
274  allocInfo.commandPool = commandPool;
275  allocInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;*/
276 
277  VkCommandBuffer commandBuffer = buffer;
278 
279  //vkAllocateCommandBuffers(device->GetDevice(), &allocInfo, &commandBuffer);
280 
281  renderer_->StartSecondaryCommandBufferRecording(commandBuffer,
282  VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
283  renderer_->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS), renderer_->GetFrameBuffer());
284 
285  VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
286 
287  vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
288 
289  vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipeline());
290 
291  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
292  shadowPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0, nullptr);
293 
294  VkDescriptorSet lightDescriptor = renderer_->GetLightDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 1);
295  if (lightDescriptor == VK_NULL_HANDLE)
296  lightDescriptor = renderer_->CreateLightDescriptorSet(threadID, shadowPipeline_->GetPipelineId(), 1, shadowPipeline_->GetDescriptorSetLayout(1));
297 
298  vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
299  shadowPipeline_->GetPipelineLayout(), 1, 1, &lightDescriptor, 1, &lightOffset);
300 
301  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
302  eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
303 
304  for (; it != end; ++it) {
305  if (it->second->meshes == 0)
306  continue;
307 
308  eastl::shared_ptr<VulkanMesh> mesh = it->first;
309 
310  VkBuffer buffers[] = { mesh->GetVertexBuffer() };
311  VkDeviceSize offsets[] = { 0 };
312  vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
313 
314  buffers[0] = it->second->transformBuffer->GetBuffer();
315  vkCmdBindVertexBuffers(commandBuffer, 1, 1, buffers, offsets);
316 
317  vkCmdBindIndexBuffer(commandBuffer, mesh->GetShadowIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
318 
319  vkCmdDrawIndexed(commandBuffer, mesh->GetShadowIndexCount(), it->second->meshes, 0, 0, 0);
320  }
321 
322  renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
323 
324  //*(buffer) = commandBuffer;
325  }
326 
327  void VulkanStaticMeshRenderer::Clean() const
328  {
329  staticMeshPipeline_->Clean();
330  shadowPipeline_->Clean();
331  }
332 
333  void VulkanStaticMeshRenderer::Recreate()
334  {
335  staticMeshPipeline_->SetRenderPassInfo(renderer_->GetGBufferRenderPass(), static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
336  staticMeshPipeline_->Recreate();
337 
338  shadowPipeline_->SetRenderPassInfo(renderer_->GetRenderPass(), static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
339  shadowPipeline_->Recreate();
340  }
341 
342 }
343 
344 #endif // USING_VULKAN
This object is used to store general data for a vertex.
Definition: Vertex.hpp:6