diff --git a/kraken/KRMesh.cpp b/kraken/KRMesh.cpp index 270593b..aa82e9a 100755 --- a/kraken/KRMesh.cpp +++ b/kraken/KRMesh.cpp @@ -1082,6 +1082,29 @@ size_t KRMesh::AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_ return VertexSizeForAttributes(mask); } +VkFormat KRMesh::AttributeVulkanFormat(__int32 vertex_attrib) +{ + switch (vertex_attrib) { + case KRENGINE_ATTRIB_VERTEX: + case KRENGINE_ATTRIB_NORMAL: + case KRENGINE_ATTRIB_TANGENT: + case KRENGINE_ATTRIB_BONEWEIGHTS: + return VK_FORMAT_R32G32B32_SFLOAT; + case KRENGINE_ATTRIB_TEXUVA: + case KRENGINE_ATTRIB_TEXUVB: + return VK_FORMAT_R32G32_SFLOAT; + case KRENGINE_ATTRIB_BONEINDEXES: + return VK_FORMAT_R8G8B8A8_UINT; + case KRENGINE_ATTRIB_VERTEX_SHORT: + case KRENGINE_ATTRIB_NORMAL_SHORT: + case KRENGINE_ATTRIB_TANGENT_SHORT: + return VK_FORMAT_R16G16B16_SFLOAT; + case KRENGINE_ATTRIB_TEXUVA_SHORT: + case KRENGINE_ATTRIB_TEXUVB_SHORT: + return VK_FORMAT_R16G16_SFLOAT; + } +} + int KRMesh::getBoneCount() { pack_header *header = getHeader(); diff --git a/kraken/KRMesh.h b/kraken/KRMesh.h index 30b3609..8005350 100755 --- a/kraken/KRMesh.h +++ b/kraken/KRMesh.h @@ -203,6 +203,7 @@ public: static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags); static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags); + static VkFormat AttributeVulkanFormat(__int32 vertex_attrib); int getBoneCount(); char *getBoneName(int bone_index); diff --git a/kraken/KRMeshManager.cpp b/kraken/KRMeshManager.cpp index f98480e..686045e 100755 --- a/kraken/KRMeshManager.cpp +++ b/kraken/KRMeshManager.cpp @@ -878,3 +878,9 @@ VkBuffer& KRMeshManager::KRVBOData::getIndexBuffer() assert(m_is_vbo_ready); return m_allocations->index_buffer; } + + +uint32_t KRMeshManager::KRVBOData::getVertexAttributes() +{ + return m_vertex_attrib_flags; +} diff --git a/kraken/KRMeshManager.h b/kraken/KRMeshManager.h index 479c9c7..23e8574 100755 --- a/kraken/KRMeshManager.h +++ b/kraken/KRMeshManager.h @@ -114,6 +114,7 @@ public: VkBuffer& getVertexBuffer(); VkBuffer& getIndexBuffer(); + uint32_t getVertexAttributes(); private: KRMeshManager *m_manager; diff --git a/kraken/KRPipeline.cpp b/kraken/KRPipeline.cpp index b890cda..8686580 100644 --- a/kraken/KRPipeline.cpp +++ b/kraken/KRPipeline.cpp @@ -109,14 +109,14 @@ const char *KRPipeline::KRENGINE_UNIFORM_NAMES[] = { "fade_color", // KRENGINE_UNIFORM_FADE_COLOR }; -KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat swapChainImageFormat, uint32_t swapChainWidth, uint32_t swapChainHeight, const char* szKey, const std::vector& shaders) +KRPipeline::KRPipeline(KRContext& context, KRSurface& surface, const char* szKey, const std::vector& shaders, uint32_t vertexAttributes) : KRContextObject(context) , m_iProgram(0) // not used for Vulkan { m_pipelineLayout = nullptr; m_graphicsPipeline = nullptr; - m_renderPass = nullptr; - KRDevice& device = *m_pContext->getDeviceManager()->getDevice(deviceHandle); + + std::unique_ptr& device = surface.getDevice(); // TODO - Handle device removal strcpy(m_szKey, szKey); @@ -126,15 +126,55 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat memset(static_cast(stages), 0, sizeof(VkPipelineShaderStageCreateInfo) * kMaxStages); size_t stage_count = 0; + // TODO - Refactor this... These lookup tables should be in KRMesh... + static const KRMesh::vertex_attrib_t attribute_mapping[KRMesh::KRENGINE_NUM_ATTRIBUTES] = { + KRMesh::KRENGINE_ATTRIB_VERTEX, + KRMesh::KRENGINE_ATTRIB_NORMAL, + KRMesh::KRENGINE_ATTRIB_TANGENT, + KRMesh::KRENGINE_ATTRIB_TEXUVA, + KRMesh::KRENGINE_ATTRIB_TEXUVB, + KRMesh::KRENGINE_ATTRIB_BONEINDEXES, + KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS, + KRMesh::KRENGINE_ATTRIB_VERTEX, + KRMesh::KRENGINE_ATTRIB_NORMAL, + KRMesh::KRENGINE_ATTRIB_TANGENT, + KRMesh::KRENGINE_ATTRIB_TEXUVA, + KRMesh::KRENGINE_ATTRIB_TEXUVB, + }; + + uint32_t attribute_locations[KRMesh::KRENGINE_NUM_ATTRIBUTES] = {}; + for (KRShader* shader : shaders) { VkShaderModule shaderModule; - if (!shader->createShaderModule(device.m_logicalDevice, shaderModule)) { + if (!shader->createShaderModule(device->m_logicalDevice, shaderModule)) { // failed! TODO - Error handling } + const SpvReflectShaderModule* reflection = shader->getReflection(); VkPipelineShaderStageCreateInfo& stageInfo = stages[stage_count++]; stageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; if (shader->getSubExtension().compare("vert") == 0) { stageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + + for (uint32_t i = 0; i < reflection->input_variable_count; i++) { + // TODO - We should have an interface to allow classes such as KRMesh to expose bindings + SpvReflectInterfaceVariable& input_var = *reflection->input_variables[i]; + if (strcmp(input_var.name, "vertex_position") == 0) { + attribute_locations[KRMesh::KRENGINE_ATTRIB_VERTEX] = input_var.location + 1; + } else if (strcmp(input_var.name, "vertex_normal") == 0) { + attribute_locations[KRMesh::KRENGINE_ATTRIB_NORMAL] = input_var.location + 1; + } else if (strcmp(input_var.name, "vertex_tangent") == 0) { + attribute_locations[KRMesh::KRENGINE_ATTRIB_TANGENT] = input_var.location + 1; + } else if (strcmp(input_var.name, "vertex_uv") == 0) { + attribute_locations[KRMesh::KRENGINE_ATTRIB_TEXUVA] = input_var.location + 1; + } else if (strcmp(input_var.name, "vertex_lightmap_uv") == 0) { + attribute_locations[KRMesh::KRENGINE_ATTRIB_TEXUVB] = input_var.location + 1; + } else if (strcmp(input_var.name, "bone_indexes") == 0) { + attribute_locations[KRMesh::KRENGINE_ATTRIB_BONEINDEXES] = input_var.location + 1; + } else if (strcmp(input_var.name, "bone_weights") == 0) { + attribute_locations[KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS] = input_var.location + 1; + } + } + } else if (shader->getSubExtension().compare("frag") == 0) { stageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; } else { @@ -144,71 +184,31 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat stageInfo.pName = "main"; } - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = swapChainImageFormat; - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentRef{}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass{}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - - VkSubpassDependency dependency{}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &colorAttachment; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 1; - renderPassInfo.pDependencies = &dependency; - - if (vkCreateRenderPass(device.m_logicalDevice, &renderPassInfo, nullptr, &m_renderPass) != VK_SUCCESS) { - // failed! TODO - Error handling - } - - // TODO - Make bindings dynamic... VkVertexInputBindingDescription bindingDescription{}; bindingDescription.binding = 0; - bindingDescription.stride = sizeof(float) * 3 + sizeof(uint16_t) * 2; + bindingDescription.stride = KRMesh::VertexSizeForAttributes(vertexAttributes); bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - const int kMaxVertexDescriptions = 16; - VkVertexInputAttributeDescription vertexAttributeDescriptions[kMaxVertexDescriptions]{}; - // position - vertexAttributeDescriptions[0].binding = 0; - vertexAttributeDescriptions[0].location = 0; - vertexAttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; - vertexAttributeDescriptions[0].offset = 0; + uint32_t vertexAttributeCount = 0; + VkVertexInputAttributeDescription vertexAttributeDescriptions[KRMesh::KRENGINE_NUM_ATTRIBUTES]{}; - // uv - vertexAttributeDescriptions[1].binding = 0; - vertexAttributeDescriptions[1].location = 1; - vertexAttributeDescriptions[1].format = VK_FORMAT_R32G32_SFLOAT; - vertexAttributeDescriptions[1].offset = sizeof(float) * 3; + for (int i = KRMesh::KRENGINE_ATTRIB_VERTEX; i < KRMesh::KRENGINE_NUM_ATTRIBUTES; i++) { + KRMesh::vertex_attrib_t mesh_attrib = static_cast(i); + int location_attrib = attribute_mapping[i]; + if (KRMesh::has_vertex_attribute(vertexAttributes, (KRMesh::vertex_attrib_t)i) && attribute_locations[location_attrib]) { + VkVertexInputAttributeDescription& desc = vertexAttributeDescriptions[vertexAttributeCount++]; + desc.binding = 0; + desc.location = attribute_locations[location_attrib] - 1; + desc.format = KRMesh::AttributeVulkanFormat(mesh_attrib); + desc.offset = KRMesh::AttributeOffset(mesh_attrib, vertexAttributes); + } + } VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputInfo.vertexBindingDescriptionCount = 1; vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; - vertexInputInfo.vertexAttributeDescriptionCount = 2; + vertexInputInfo.vertexAttributeDescriptionCount = vertexAttributeCount; vertexInputInfo.pVertexAttributeDescriptions = vertexAttributeDescriptions; VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; @@ -219,15 +219,15 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = static_cast(swapChainWidth); - viewport.height = static_cast(swapChainHeight); + viewport.width = static_cast(surface.getWidth()); + viewport.height = static_cast(surface.getHeight()); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor{}; scissor.offset = { 0, 0 }; - scissor.extent.width = swapChainWidth; - scissor.extent.height = swapChainHeight; + scissor.extent.width = surface.getWidth(); + scissor.extent.height = surface.getHeight(); VkPipelineViewportStateCreateInfo viewportState{}; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; @@ -286,7 +286,7 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat pipelineLayoutInfo.pushConstantRangeCount = 0; pipelineLayoutInfo.pPushConstantRanges = nullptr; - if (vkCreatePipelineLayout(device.m_logicalDevice, &pipelineLayoutInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) { + if (vkCreatePipelineLayout(device->m_logicalDevice, &pipelineLayoutInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) { // failed! TODO - Error handling } @@ -303,12 +303,12 @@ KRPipeline::KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDynamicState = nullptr; pipelineInfo.layout = m_pipelineLayout; - pipelineInfo.renderPass = m_renderPass; + pipelineInfo.renderPass = surface.getRenderPass(); pipelineInfo.subpass = 0; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineIndex = -1; - if (vkCreateGraphicsPipelines(device.m_logicalDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_graphicsPipeline) != VK_SUCCESS) { + if (vkCreateGraphicsPipelines(device->m_logicalDevice, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_graphicsPipeline) != VK_SUCCESS) { // Failed! TODO - Error handling } } @@ -428,9 +428,6 @@ KRPipeline::~KRPipeline() { if (m_pipelineLayout) { // TODO: vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr); } - if (m_renderPass) { - // TODO: vkDestroyRenderPass(device, m_renderPass, nullptr); - } if(m_iProgram) { GLDEBUG(glDeleteProgram(m_iProgram)); @@ -795,11 +792,6 @@ const char *KRPipeline::getKey() const { return m_szKey; } -VkRenderPass& KRPipeline::getRenderPass() -{ - return m_renderPass; -} - VkPipeline& KRPipeline::getPipeline() { return m_graphicsPipeline; diff --git a/kraken/KRPipeline.h b/kraken/KRPipeline.h index 06b2b90..cb07c53 100644 --- a/kraken/KRPipeline.h +++ b/kraken/KRPipeline.h @@ -41,10 +41,11 @@ #include "KRViewport.h" class KRShader; +class KRSurface; class KRPipeline : public KRContextObject { public: - KRPipeline(KRContext& context, KrDeviceHandle deviceHandle, VkFormat swapChainImageFormat, uint32_t swapChainWidth, uint32_t swapChainHeight, const char* szKey, const std::vector& shaders); + KRPipeline(KRContext& context, KRSurface& surface, const char* szKey, const std::vector& shaders, uint32_t vertexAttributes); KRPipeline(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource); virtual ~KRPipeline(); const char *getKey() const; @@ -145,12 +146,10 @@ public: void setUniform(int location, const Vector4 &value); void setUniform(int location, const Matrix4 &value); - VkRenderPass& getRenderPass(); VkPipeline& getPipeline(); private: GLuint m_iProgram; - VkRenderPass m_renderPass; VkPipelineLayout m_pipelineLayout; VkPipeline m_graphicsPipeline; diff --git a/kraken/KRPipelineManager.h b/kraken/KRPipelineManager.h index 2427f26..dee8b9b 100644 --- a/kraken/KRPipelineManager.h +++ b/kraken/KRPipelineManager.h @@ -52,9 +52,9 @@ class KRPipelineManager : public KRContextObject { public: KRPipelineManager(KRContext &context); virtual ~KRPipelineManager(); - void createPipelines(KRSurface& surface); KRPipeline* get(const char* szKey); + KRPipeline *getPipeline(KRSurface& surface, const std::string& shader_name, uint32_t vertexAttributes); KRPipeline *getPipeline(const std::string &pipeline_name, KRCamera *pCamera, const std::vector &point_lights, const std::vector &directional_lights, const std::vector&spot_lights, int bone_count, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, bool bRimColor = false); bool selectPipeline(KRCamera &camera, KRPipeline *pPipeline, const KRViewport &viewport, const Matrix4 &matModel, const std::vector &point_lights, const std::vector &directional_lights, const std::vector&spot_lights, int bone_count, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color); @@ -66,7 +66,8 @@ public: KRPipeline *m_active_pipeline; private: - std::map >, KRPipeline *> m_pipelines; + typedef std::map >, KRPipeline*> PipelineMap; + PipelineMap m_pipelines; }; #endif diff --git a/kraken/KRShader.cpp b/kraken/KRShader.cpp index caa5991..a8aa496 100644 --- a/kraken/KRShader.cpp +++ b/kraken/KRShader.cpp @@ -121,6 +121,7 @@ void KRShader::parseReflection() return; } + m_reflectionValid = true; m_pData->unlock(); }