From dbeae98d710998dc7d624d3e8d1571fd4ca63484 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sat, 13 Aug 2022 06:18:10 +0000 Subject: [PATCH] Get stuff rendering --- include/Orange/Core/Bitset.h | 117 +++++++++++++++++++++++ include/Orange/Core/Traits.h | 6 ++ include/Orange/Render/RenderContext.h | 24 +++-- include/Orange/Render/VulkanHelpers.h | 18 +++- src/Apps/Tools/CubeTest.cpp | 88 +++++++++++++---- src/Orange/Render/RenderContext_Util.cpp | 32 ++++++- src/Orange/Render/Shaders/vs_Mesh.vert | 3 +- src/Orange/Render/Swapchain.cpp | 8 +- src/Orange/Render/Window.cpp | 3 + 9 files changed, 263 insertions(+), 36 deletions(-) create mode 100644 include/Orange/Core/Bitset.h diff --git a/include/Orange/Core/Bitset.h b/include/Orange/Core/Bitset.h new file mode 100644 index 0000000..89cda0a --- /dev/null +++ b/include/Orange/Core/Bitset.h @@ -0,0 +1,117 @@ +#pragma once + +#include +#include +#include + +namespace orange +{ + + template + struct Bitset { + static constexpr size_t DwordCount = Align(BitCount, 32) / 32; + + constexpr Bitset() + : dwords{ } { } + + + constexpr bool get(size_t idx) const + { + uint32_t dword = 0u; + uint32_t bit = idx; + + if constexpr (DwordCount > 1u) { + dword = idx / 32u; + bit = idx % 32u; + } + + return dwords[dword] & (1u << bit); + } + + + constexpr void set(uint32_t idx, bool value) + { + uint32_t dword = 0u; + uint32_t bit = idx; + + if constexpr (DwordCount > 1u) { + dword = idx / 32u; + bit = idx % 32u; + } + + if (value) + dwords[dword] |= 1u << bit; + else + dwords[dword] &= ~(1u << bit); + } + + + constexpr bool exchange(uint32_t idx, bool value) + { + bool oldValue = get(idx); + set(idx, value); + return oldValue; + } + + + constexpr void flip(uint32_t idx) + { + uint32_t dword = 0u; + uint32_t bit = idx; + + if constexpr (DwordCount > 1) { + dword = idx / 32u; + bit = idx % 32u; + } + + dwords[dword] ^= 1u << bit; + } + + + constexpr void setAll() + { + if constexpr (BitCount % 32u == 0u) + { + for (size_t i = 0; i < DwordCount; i++) + dwords[i] = std::numeric_limits::max(); + } + else + { + for (size_t i = 0; i < DwordCount - 1u; i++) + dwords[i] = std::numeric_limits::max(); + + dwords[DwordCount - 1] = (1u << (BitCount % 32u)) - 1u; + } + } + + + constexpr void clearAll() + { + for (size_t i = 0; i < DwordCount; i++) + dwords[i] = 0u; + } + + + constexpr bool any() const + { + for (size_t i = 0; i < DwordCount; i++) + { + if (dwords[i] != 0u) + return true; + } + + return false; + } + + + constexpr bool operator [] (uint32_t idx) const + { + return get(idx); + } + + + Array dwords; + + }; + +} diff --git a/include/Orange/Core/Traits.h b/include/Orange/Core/Traits.h index dea4040..e887936 100644 --- a/include/Orange/Core/Traits.h +++ b/include/Orange/Core/Traits.h @@ -150,6 +150,12 @@ namespace orange return Min( Max( val, minVal ), maxVal ); } + template + [[nodiscard]] constexpr T Align(T what, U to) + { + return (what + to - 1) & ~(to - 1); + } + // Transformations template diff --git a/include/Orange/Render/RenderContext.h b/include/Orange/Render/RenderContext.h index d8eb79b..558ce3c 100644 --- a/include/Orange/Render/RenderContext.h +++ b/include/Orange/Render/RenderContext.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -23,23 +24,29 @@ namespace orange void* ptr; }; - class BufferPooler + class MemoryPool { public: - BufferPooler(GPUMemoryBuffer buffer) + MemoryPool(GPUMemoryBuffer buffer) : m_buffer{ buffer } {} - Result AllocSlice(VkDeviceSize size) + Result AllocSlice(VkDeviceSize size, VkDeviceSize alignment = 1u) { - BufferSlice slice{ m_buffer.buffer, m_offset, size }; + uint32_t offset = Align(m_offset, alignment); + BufferSlice slice{ m_buffer.buffer, offset, size }; - if (m_offset + size > m_buffer.size) + if (offset + size > m_buffer.size) return Result::Error(); - m_offset += size; + m_offset = offset + size; return Result::Success(slice); } + + VkDeviceMemory Memory() const + { + return m_buffer.memory; + } private: GPUMemoryBuffer m_buffer = {}; VkDeviceSize m_offset = 0u; @@ -73,8 +80,11 @@ namespace orange VulkanResult BeginCommandBuffer(VkCommandBuffer buffer); VulkanResult EndCommandBuffer(VkCommandBuffer buffer); VulkanResult CreateBuffer(VkDeviceSize size); + VulkanResult CreateImage(MemoryPool& pool, uint32_t width, uint32_t height, VkFormat format); VulkanResult CreateShader(Span code); + + const VkPhysicalDeviceProperties& Props() const { return m_props; } protected: friend VulkanResult; RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, @@ -118,6 +128,7 @@ namespace orange } } + vkGetPhysicalDeviceProperties(m_physicalDevice, &m_props); } private: VkInstance m_instance = VK_NULL_HANDLE; @@ -126,6 +137,7 @@ namespace orange VkQueue m_queue = VK_NULL_HANDLE; VkCommandPool m_commandPool = VK_NULL_HANDLE; + VkPhysicalDeviceProperties m_props{}; VkMemoryTypes m_memoryTypes{}; }; } \ No newline at end of file diff --git a/include/Orange/Render/VulkanHelpers.h b/include/Orange/Render/VulkanHelpers.h index 3dbf792..4b6cb9b 100644 --- a/include/Orange/Render/VulkanHelpers.h +++ b/include/Orange/Render/VulkanHelpers.h @@ -20,7 +20,7 @@ namespace orange return count; } - static constexpr VkImageSubresourceRange FirstMipSubresourceRange = + static constexpr VkImageSubresourceRange FirstColorMipSubresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, @@ -29,6 +29,15 @@ namespace orange .layerCount = 1, }; + static constexpr VkImageSubresourceRange FirstDepthMipSubresourceRange = + { + .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; + constexpr VkFormat FormatToSrgbFormat(VkFormat format) { switch (format) @@ -59,4 +68,11 @@ namespace orange return Result::Error(BasicErrorCode::NotFound); } + + inline Result FindDepthFormat(VkPhysicalDevice physicalDevice) + { + return FindSupportedFormat(physicalDevice, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT); + } + } diff --git a/src/Apps/Tools/CubeTest.cpp b/src/Apps/Tools/CubeTest.cpp index d597e84..671a66e 100644 --- a/src/Apps/Tools/CubeTest.cpp +++ b/src/Apps/Tools/CubeTest.cpp @@ -262,8 +262,8 @@ int main(int argc, char** argv) if (!r_swapchain) return 1; - //auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/chair.obj"); - auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/cube.obj"); + auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/chair.obj"); + //auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/cube.obj"); if (!r_objData) return 1; @@ -489,13 +489,15 @@ int main(int argc, char** argv) VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; vkCreatePipelineLayout(r_renderContext->Device(), &pipelineLayoutInfo, nullptr, &pipelineLayout); - VkFormat format = FormatToSrgbFormat(r_swapchain->Format()); + VkFormat colorFormat = FormatToSrgbFormat(r_swapchain->Format()); + VkFormat depthFormat = *FindDepthFormat(r_renderContext->PhysicalDevice()); VkPipelineRenderingCreateInfo renderingInfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, - .viewMask = 0u, - .colorAttachmentCount = 1u, - .pColorAttachmentFormats = &format, + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .viewMask = 0u, + .colorAttachmentCount = 1u, + .pColorAttachmentFormats = &colorFormat, + .depthAttachmentFormat = depthFormat }; VkGraphicsPipelineCreateInfo pipelineInfo = @@ -546,14 +548,28 @@ int main(int argc, char** argv) UniformData uniformData { .projection = perspective(Degree(90.0f), 16.0f / 9.0f, 0.01f, 1024.0f), - .view = translate(vec3{0.0f, 0.0f, -4.0f}), + .view = translate(vec3{0.0f, 0.0f, -80.0f}), }; - auto pooler = BufferPooler{ *r_buffer }; + auto pooler = MemoryPool{ *r_buffer }; auto meshData = r_mesh->vertexData.View(); - auto vertexSlice = *pooler.AllocSlice(meshData.size); - auto indexSlice = *pooler.AllocSlice(r_mesh->indices.Size() * sizeof(uint16_t)); - auto uniformSlice = *pooler.AllocSlice(sizeof(UniformData)); + auto vertexSlice = *pooler.AllocSlice(meshData.size, 16); + auto indexSlice = *pooler.AllocSlice(r_mesh->indices.Size() * sizeof(uint16_t), 16); + auto uniformSlice = *pooler.AllocSlice(sizeof(UniformData), 16); + auto r_depthImage = r_renderContext->CreateImage(pooler, 1280, 720, depthFormat); + + VkImageViewCreateInfo depthImageViewInfo = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = *r_depthImage, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = depthFormat, + .subresourceRange = FirstDepthMipSubresourceRange, + }; + + VkImageView depthImageView = VK_NULL_HANDLE; + if (vkCreateImageView(r_renderContext->Device(), &depthImageViewInfo, nullptr, &depthImageView) != VK_SUCCESS) + return 1; VkDescriptorBufferInfo bufferInfo = { @@ -601,7 +617,7 @@ int main(int argc, char** argv) .extent = r_swapchain->Extent(), }; - vkCmdSetViewport(cmdBuf, 0, 1, &viewport); + vkCmdSetViewport(cmdBuf, 0, 1, &viewport); vkCmdSetScissor(cmdBuf, 0, 1, &scissor); vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); @@ -617,7 +633,7 @@ int main(int argc, char** argv) .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .image = r_swapchain->Image(), - .subresourceRange = FirstMipSubresourceRange, + .subresourceRange = FirstColorMipSubresourceRange, }; vkCmdPipelineBarrier( @@ -629,14 +645,45 @@ int main(int argc, char** argv) 0, nullptr, 1, &undefinedToColorBarrier); - const VkRenderingAttachmentInfoKHR attachmentInfo = + const VkImageMemoryBarrier undefinedToDepthBarrier = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + .image = *r_depthImage, + .subresourceRange = FirstColorMipSubresourceRange, + }; + + vkCmdPipelineBarrier( + cmdBuf, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &undefinedToDepthBarrier); + + const VkRenderingAttachmentInfoKHR colorAttachmentInfos[] = + { + { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, + .imageView = r_swapchain->ImageView(), + .imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = { .color = { .float32 = { 1.0f, 0.5f, 0.0f, 1.0f } } }, + }, + }; + + const VkRenderingAttachmentInfoKHR depthAttachmentInfo = { .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, - .imageView = r_swapchain->ImageView(), + .imageView = depthImageView, .imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .clearValue = { .color = { .float32 = { 1.0f, 0.5f, 0.0f, 1.0f } } }, + .clearValue = { .color = { .float32 = { 1.0f, 1.0f, 1.0f, 1.0f } } }, }; const VkRenderingInfo renderInfo = @@ -644,8 +691,9 @@ int main(int argc, char** argv) .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, .renderArea = { {}, r_swapchain->Extent() }, .layerCount = 1, - .colorAttachmentCount = 1, - .pColorAttachments = &attachmentInfo, + .colorAttachmentCount = Size(colorAttachmentInfos), + .pColorAttachments = colorAttachmentInfos, + .pDepthAttachment = &depthAttachmentInfo, }; vkCmdBeginRendering(cmdBuf, &renderInfo); vkCmdDrawIndexed(cmdBuf, r_mesh->indices.Size(), 1, 0, 0, 0); @@ -658,7 +706,7 @@ int main(int argc, char** argv) .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .image = r_swapchain->Image(), - .subresourceRange = FirstMipSubresourceRange, + .subresourceRange = FirstColorMipSubresourceRange, }; vkCmdPipelineBarrier( diff --git a/src/Orange/Render/RenderContext_Util.cpp b/src/Orange/Render/RenderContext_Util.cpp index f0dafb5..d61645b 100644 --- a/src/Orange/Render/RenderContext_Util.cpp +++ b/src/Orange/Render/RenderContext_Util.cpp @@ -82,7 +82,7 @@ namespace orange .memoryTypeIndex = m_memoryTypes.gpuHostVisibleTypeIdx, }; - VkDeviceMemory memory; + VkDeviceMemory memory = VK_NULL_HANDLE; VkResult res = VK_SUCCESS; if ((res = vkAllocateMemory(m_device, &memoryInfo, nullptr, &memory)) != VK_SUCCESS) return VulkanResult::Error(res); @@ -112,4 +112,34 @@ namespace orange return VulkanResult::Success(memory, buffer, size, data); } + + VulkanResult RenderContext::CreateImage(MemoryPool& pool, uint32_t width, uint32_t height, VkFormat format) + { + VkImageCreateInfo imageInfo = + { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .format = format, + .extent = VkExtent3D{ width, height, 1u }, + .mipLevels = 1u, + .arrayLayers = 1u, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + }; + + VkImage image = VK_NULL_HANDLE; + VkResult res = VK_SUCCESS; + if ((res = vkCreateImage(m_device, &imageInfo, nullptr, &image)) != VK_SUCCESS) + return VulkanResult::Error(res); + + VkMemoryRequirements imageMemRequirements; + vkGetImageMemoryRequirements(m_device, image, &imageMemRequirements); + + auto imageSlice = *pool.AllocSlice(imageMemRequirements.size, imageMemRequirements.alignment); + if ((res = vkBindImageMemory(m_device, image, pool.Memory(), imageSlice.offset)) != VK_SUCCESS) + return VulkanResult::Error(res); + + return VulkanResult::Success(image); + } } diff --git a/src/Orange/Render/Shaders/vs_Mesh.vert b/src/Orange/Render/Shaders/vs_Mesh.vert index ce4e138..0ec7e48 100644 --- a/src/Orange/Render/Shaders/vs_Mesh.vert +++ b/src/Orange/Render/Shaders/vs_Mesh.vert @@ -21,5 +21,6 @@ vec3 k_colors[3] = vec3[] void main() { gl_Position = u_data.projection * u_data.view * vec4(i_pos, 1.0); - o_color = vec4(k_colors[gl_VertexIndex % 3], 1.0); + //o_color = vec4(k_colors[gl_VertexIndex % 3], 1.0); + o_color = vec4(i_uv, 0.0f, 1.0); } \ No newline at end of file diff --git a/src/Orange/Render/Swapchain.cpp b/src/Orange/Render/Swapchain.cpp index 3ae613d..d36b23e 100644 --- a/src/Orange/Render/Swapchain.cpp +++ b/src/Orange/Render/Swapchain.cpp @@ -66,12 +66,6 @@ namespace orange return imageCount; } - static Result FindDepthFormat(VkPhysicalDevice physicalDevice) - { - return FindSupportedFormat(physicalDevice, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT - VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT); - } - Result Swapchain::Create(RenderContext& context, VkSurfaceKHR surface) { VkSurfaceCapabilitiesKHR capabilities; @@ -133,7 +127,7 @@ namespace orange .image = swapchainImages[i], .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = FormatToSrgbFormat(r_format->format), - .subresourceRange = FirstMipSubresourceRange, + .subresourceRange = FirstColorMipSubresourceRange, }; if (vkCreateImageView(context.Device(), &imageViewInfo, nullptr, &swapchainImageViews[i]) != VK_SUCCESS) diff --git a/src/Orange/Render/Window.cpp b/src/Orange/Render/Window.cpp index 04bd0ac..5a5ee2f 100644 --- a/src/Orange/Render/Window.cpp +++ b/src/Orange/Render/Window.cpp @@ -67,6 +67,9 @@ namespace orange { switch (e.type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + break; case SDL_QUIT: quit = true; break;