12 VulkanStaticMeshRenderer::VulkanStaticMeshRenderer(VulkanRenderer * renderer, VulkanLogicalDevice * device, VulkanDescriptorPool * descriptorPool)
14 this->renderer_ = renderer;
15 this->device_ = device;
16 this->descriptorPool_ = descriptorPool;
17 this->allocator_ = renderer->GetVmaAllocator();
18 this->commandPool_ = renderer->GetGraphicsCommandPool();
20 staticMeshPipeline_ = eastl::unique_ptr<VulkanPipeline>(
new VulkanPipeline(device, renderer));
22 staticMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::VERTEX_SHADER,
"StaticMesh.vert.spv");
24 staticMeshPipeline_->LoadShader(VulkanPipeline::SHADER_TYPE::FRAGMENT_SHADER,
"Mesh.frag.spv");
26 staticMeshPipeline_->AddVertexInputBindingDescription(0,
27 static_cast<uint32_t>(
sizeof(
Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
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));
33 staticMeshPipeline_->AddVertexInputBindingDescription(1,
34 static_cast<uint32_t>(
sizeof(glm::mat4)), VK_VERTEX_INPUT_RATE_INSTANCE);
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));
41 staticMeshPipeline_->CreateDescriptorSet();
42 staticMeshPipeline_->AddDescriptorSetLayout(VulkanMaterial::CreateMaterialDescriptorSetLayout(device));
44 staticMeshPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
nullptr);
46 staticMeshPipeline_->SetRenderPassInfo(renderer->GetGBufferRenderPass(),
static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
48 staticMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
49 staticMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
50 staticMeshPipeline_->CreateColorBlendAttachment(VK_FALSE);
52 staticMeshPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
false);
54 staticMeshPipeline_->SetRasterizerSettings();
56 staticMeshPipeline_->Compile();
58 shadowPipeline_ = eastl::unique_ptr<VulkanPipeline>(
new VulkanPipeline(device_, renderer_));
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");
64 shadowPipeline_->AddVertexInputBindingDescription(0,
65 static_cast<uint32_t>(
sizeof(
Vertex)), VK_VERTEX_INPUT_RATE_VERTEX);
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));
71 shadowPipeline_->AddVertexInputBindingDescription(1,
72 static_cast<uint32_t>(
sizeof(glm::mat4)), VK_VERTEX_INPUT_RATE_INSTANCE);
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));
79 shadowPipeline_->CreateDescriptorSet();
80 shadowPipeline_->AddDescriptorSetLayout(renderer_->CreateLightDescriptorSetLayout());
82 shadowPipeline_->AddDescriptorSetBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT,
nullptr);
84 shadowPipeline_->SetRenderPassInfo(renderer->GetRenderPass(),
static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
86 shadowPipeline_->SetInputAssemblyState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
false);
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);
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;
97 front.writeMask = 0xff;
98 front.compareMask = 0xff;
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;
106 back.writeMask = 0xff;
107 back.compareMask = 0xff;
109 shadowPipeline_->SetDepthStencilState(VK_TRUE, VK_FALSE, VK_COMPARE_OP_LESS, VK_TRUE, 0.f, 1.f, VK_TRUE, front, back);
111 shadowPipeline_->CreateColorBlendAttachment(VK_TRUE, 0u);
113 shadowPipeline_->Compile();
115 ubo_ = { glm::mat4(), glm::mat4() };
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()));
120 uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(
sizeof(ubo_)));
122 uboDescriptors_.resize(renderer_->GetThreadCount());
124 for (
size_t i = 0, size = uboDescriptors_.size(); i < size; ++i) {
126 VkDescriptorSetLayout layouts[] = { staticMeshPipeline_->GetDescriptorSetLayout(0) };
127 renderer_->GetDescriptorPool(i)->AllocateDescriptorSet(1, layouts, &uboDescriptors_[i]);
129 renderer_->GetDescriptorPool(i)->DescriptorSetBindToBuffer(uboDescriptors_[i], uniformBuffer_->GetBuffer(),
130 0,
static_cast<VkDeviceSize
>(
sizeof(ubo_)), 0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
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());
139 VulkanStaticMeshRenderer::~VulkanStaticMeshRenderer()
142 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
143 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
145 for (; it != end; ++it) {
146 it->second->transformBuffer.reset();
150 uniformBuffer_.reset();
152 staticMeshPipeline_.reset();
153 shadowPipeline_.reset();
156 void VulkanStaticMeshRenderer::StartRender(glm::mat4 view, glm::mat4 projection)
158 if (ubo_.view != view || ubo_.proj != projection) {
160 ubo_.proj = projection;
162 uniformBuffer_->UpdateBuffer(&ubo_, 0, static_cast<uint32_t>(
sizeof(ubo_)));
165 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
166 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
168 for (; it != end; ++it) {
169 it->second->transforms.clear();
170 it->second->meshes = 0;
174 void VulkanStaticMeshRenderer::RenderMesh(
const glm::mat4x4 & modelMatrix, eastl::shared_ptr<VulkanMesh> mesh,
175 eastl::shared_ptr<VulkanMaterial> material,
const glm::vec4 & mainColor)
177 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
178 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
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++;
189 MeshData* data =
new MeshData;
190 data->material = material;
191 data->transforms.push_back(modelMatrix);
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));
200 void VulkanStaticMeshRenderer::FinishRender(
size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer)
209 VkCommandBuffer commandBuffer = buffer;
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);
219 VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
221 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
223 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, staticMeshPipeline_->GetPipeline());
225 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
226 staticMeshPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0,
nullptr);
228 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
229 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
231 for (; it != end; ++it) {
232 if (it->second->meshes == 0)
235 VkDescriptorSet materialDescriptor;
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));
243 eastl::shared_ptr<VulkanMesh> mesh = it->first;
245 it->second->transformBuffer->UpdateBuffer(it->second->transforms.data(), 0,
246 static_cast<uint32_t
>(
sizeof(glm::mat4)*it->second->meshes));
248 VkBuffer buffers[] = { mesh->GetVertexBuffer() };
249 VkDeviceSize offsets[] = { 0 };
250 vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
252 buffers[0] = it->second->transformBuffer->GetBuffer();
253 vkCmdBindVertexBuffers(commandBuffer, 1, 1, buffers, offsets);
255 vkCmdBindIndexBuffer(commandBuffer, mesh->GetIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
257 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, staticMeshPipeline_->GetPipelineLayout(),
258 1, 1, &(materialDescriptor), 0,
nullptr);
260 vkCmdDrawIndexed(commandBuffer, mesh->GetIndexCount(), it->second->meshes, 0, 0, 0);
263 renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
268 void VulkanStaticMeshRenderer::RenderShadows(
size_t threadID, VkCommandPool commandPool, VkCommandBuffer buffer, uint32_t lightOffset)
277 VkCommandBuffer commandBuffer = buffer;
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());
285 VkRect2D scissor = { 0,0,renderer_->GetSwapChainExtent() };
287 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
289 vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, shadowPipeline_->GetPipeline());
291 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
292 shadowPipeline_->GetPipelineLayout(), 0, 1, &uboDescriptors_[threadID], 0,
nullptr);
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));
298 vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
299 shadowPipeline_->GetPipelineLayout(), 1, 1, &lightDescriptor, 1, &lightOffset);
301 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator it = meshInstances_.begin();
302 eastl::multimap<eastl::shared_ptr<VulkanMesh>, MeshData*>::iterator end = meshInstances_.end();
304 for (; it != end; ++it) {
305 if (it->second->meshes == 0)
308 eastl::shared_ptr<VulkanMesh> mesh = it->first;
310 VkBuffer buffers[] = { mesh->GetVertexBuffer() };
311 VkDeviceSize offsets[] = { 0 };
312 vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
314 buffers[0] = it->second->transformBuffer->GetBuffer();
315 vkCmdBindVertexBuffers(commandBuffer, 1, 1, buffers, offsets);
317 vkCmdBindIndexBuffer(commandBuffer, mesh->GetShadowIndexBuffer(), 0, VK_INDEX_TYPE_UINT32);
319 vkCmdDrawIndexed(commandBuffer, mesh->GetShadowIndexCount(), it->second->meshes, 0, 0, 0);
322 renderer_->EndSecondaryCommandBufferRecording(commandBuffer);
327 void VulkanStaticMeshRenderer::Clean()
const 329 staticMeshPipeline_->Clean();
330 shadowPipeline_->Clean();
333 void VulkanStaticMeshRenderer::Recreate()
335 staticMeshPipeline_->SetRenderPassInfo(renderer_->GetGBufferRenderPass(),
static_cast<int>(VulkanRenderer::GBufferSubPasses::G_BUFFER_PASS));
336 staticMeshPipeline_->Recreate();
338 shadowPipeline_->SetRenderPassInfo(renderer_->GetRenderPass(),
static_cast<int>(VulkanRenderer::RenderSubPasses::RENDER_PASS));
339 shadowPipeline_->Recreate();
344 #endif // USING_VULKAN
This object is used to store general data for a vertex.