diff --git a/Assets/Shaders/Mesh.slang b/Assets/Shaders/Mesh.slang index 0b7bb1c..95784fb 100644 --- a/Assets/Shaders/Mesh.slang +++ b/Assets/Shaders/Mesh.slang @@ -12,11 +12,10 @@ struct CameraData { }; struct PerFrameData { - CameraData camera; - Sampler2D texture; } -ParameterBlock perFrameData; +[vk::binding(0, 0)] uniform ConstantBuffer camera; +[vk::binding(0, 1)] uniform Sampler2D texture; struct PerInstanceData { float4x4 transform; @@ -33,8 +32,8 @@ VertexOut VertexMain( float2 texCoord0, ) { VertexOut output; - output.outPosition = mul(perFrameData.camera.proj, mul(perFrameData.camera.view, mul(pcb.transform, float4(position, 1.0f)))); - output.screenPosition = mul(perFrameData.camera.proj, mul(perFrameData.camera.view, mul(pcb.transform, float4(position, 1.0f)))); + output.outPosition = mul(camera.proj, mul(camera.view, mul(pcb.transform, float4(position, 1.0f)))); + output.screenPosition = mul(camera.proj, mul(camera.view, mul(pcb.transform, float4(position, 1.0f)))); output.vertexColor = float4(color, 1.0f); output.texCoord0 = texCoord0 * 2.0f; return output; @@ -46,6 +45,6 @@ float4 FragmentMain( float4 interpolatedColors : CoarseColor, float2 uv0 : TexCoord0, ) : SV_Target0 { - return float4(perFrameData.texture.Sample(uv0).rgb, 1.0f) * interpolatedColors; + return float4(texture.Sample(uv0).rgb, 1.0f) * interpolatedColors; } diff --git a/Blaze.vcxproj b/Blaze.vcxproj index f2f9332..a5132e9 100644 --- a/Blaze.vcxproj +++ b/Blaze.vcxproj @@ -109,7 +109,7 @@ true stdcpp20 false - true + false Sync false /utf-8 %(AdditionalOptions) @@ -132,7 +132,7 @@ true stdcpp20 false - true + false /EH- false /utf-8 %(AdditionalOptions) @@ -171,6 +171,7 @@ + @@ -181,6 +182,7 @@ + diff --git a/Blaze.vcxproj.filters b/Blaze.vcxproj.filters index 2a159ed..53936ef 100644 --- a/Blaze.vcxproj.filters +++ b/Blaze.vcxproj.filters @@ -68,6 +68,9 @@ Header Files + + Header Files + @@ -94,6 +97,9 @@ Source Files\HeaderOnlyImpl + + Source Files + diff --git a/Blaze/AppState.cpp b/Blaze/AppState.cpp index 522c362..a090fb1 100644 --- a/Blaze/AppState.cpp +++ b/Blaze/AppState.cpp @@ -2,6 +2,7 @@ #include +#include "EntityManager.h" #include "GlobalMemory.h" #include "MiscData.h" #include "RenderDevice.h" @@ -19,12 +20,18 @@ void AppState::destroy() Take( miscData )->destroy( *renderDevice ); + Take( entityManager )->destroy(); + Take( renderDevice )->destroy(); SDL_DestroyWindow( Take( window ) ); } -AppState::AppState( SDL_Window* window, RenderDevice* renderDevice, MiscData* miscData ) - : window{ window }, renderDevice{ renderDevice }, miscData{ miscData }, sprintfBuffer{ 0 } +AppState::AppState( SDL_Window* window, RenderDevice* renderDevice, EntityManager* entityManager, MiscData* miscData ) + : window{ window } + , renderDevice{ renderDevice } + , entityManager{ entityManager } + , miscData{ miscData } + , sprintfBuffer{ 0 } {} AppState* AppState_Create( GlobalMemory* memory, uint32_t const width, uint32_t const height ) @@ -38,20 +45,37 @@ AppState* AppState_Create( GlobalMemory* memory, uint32_t const width, uint32_t } RenderDevice* renderDevice = RenderDevice_Create( memory, { .window = window } ); - if ( !renderDevice->isInit() ) + if ( !renderDevice or !renderDevice->isInit() ) { SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "RenderDevice failed to init" ); SDL_DestroyWindow( window ); return nullptr; } + EntityManager* entityManager = EntityManager_Create( memory, renderDevice, 10 ); + if ( !entityManager ) + { + SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "EntityManager failed to init" ); + renderDevice->destroy(); + SDL_DestroyWindow( window ); + return nullptr; + } + auto* miscDataAllocation = memory->allocate( sizeof( MiscData ) ); MiscData* miscData = new ( miscDataAllocation ) MiscData{}; - if ( !miscData->init( *renderDevice ) ) return nullptr; + if ( !miscData->init( *renderDevice ) ) + { + SDL_LogError( SDL_LOG_CATEGORY_APPLICATION, "MiscData failed to init" ); + + entityManager->destroy(); + renderDevice->destroy(); + SDL_DestroyWindow( window ); + return nullptr; + } auto* allocation = memory->allocate( sizeof( AppState ) ); - AppState* appState = new ( allocation ) AppState{ window, renderDevice, miscData }; + AppState* appState = new ( allocation ) AppState{ window, renderDevice, entityManager, miscData }; return appState; } diff --git a/Blaze/AppState.h b/Blaze/AppState.h index e423c80..3469d58 100644 --- a/Blaze/AppState.h +++ b/Blaze/AppState.h @@ -2,6 +2,8 @@ #include + +struct EntityManager; struct SDL_Window; struct GlobalMemory; @@ -12,13 +14,14 @@ struct AppState { SDL_Window* window; RenderDevice* renderDevice; + EntityManager* entityManager; MiscData* miscData; char sprintfBuffer[256]; [[nodiscard]] bool isInit() const; void destroy(); - AppState( SDL_Window* window, RenderDevice* renderDevice, MiscData* miscData ); + AppState( SDL_Window* window, RenderDevice* renderDevice, EntityManager* entityManager, MiscData* miscData ); AppState( AppState const& other ) = delete; AppState( AppState&& other ) noexcept = delete; diff --git a/Blaze/Blaze.cpp b/Blaze/Blaze.cpp index 59066ac..c59b11c 100644 --- a/Blaze/Blaze.cpp +++ b/Blaze/Blaze.cpp @@ -15,6 +15,7 @@ #include #include "AppState.h" +#include "EntityManager.h" #include "Frame.h" #include "GlobalMemory.h" #include "MacroUtils.h" @@ -40,18 +41,82 @@ SDL_AppResult SDL_AppInit( void** appstate, int, char** ) *appstate = AppState_Create( &Blaze::Global::g_Memory, WIDTH, HEIGHT ); if ( !*appstate ) return SDL_APP_FAILURE; + AppState& appState = *static_cast( *appstate ); + + // TODO: Integrate this + + // Model Setup + + // modelTransform[1].position = { -1.0f, 0.0f, 0.0f }; + // modelTransform[1].scale = 1.0f; + // modelTransform[1].rotation = + // DirectX::XMQuaternionRotationAxis( DirectX::XMVectorSet( 1.0f, 0.0f, 0.0f, 0.0f ), 0.0f ); + + // TL----TR + // | \ | + // | \ | + // | \ | + // BL----BR + // + // BL -> BR -> TL + // TL -> BR -> TR + + std::array vertices = { + // Bottom Left + Vertex{ + .position = { -1.0f, -1.0f, 0.0f }, + .color = { 0.0f, 0.0f, 1.0f }, + .texCoord0 = { 0.0f, 0.0f }, + }, + // Bottom Right + Vertex{ + .position = { 1.0f, -1.0f, 0.0f }, + .color = { 1.0f, 0.0f, 0.0f }, + .texCoord0 = { 1.0f, 0.0f }, + }, + // Top Left + Vertex{ + .position = { -1.0f, 1.0f, 0.0f }, + .color = { 0.0f, 1.0f, 0.0f }, + .texCoord0 = { 0.0f, 1.0f }, + }, + // Top Right + Vertex{ + .position = { 1.0f, 1.0f, 0.0f }, + .color = { 1.0f, 1.0f, 0.0f }, + .texCoord0 = { 1.0f, 1.0f }, + } + }; + + Transform modelTransform = { + .position = { 1.0f, 0.0f, 0.0f }, + .scale = 1.0f, + .rotation = DirectX::XMQuaternionRotationAxis( DirectX::XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ), 0.0f ), + }; + + for ( int i = -3; i <= 3; ++i ) + { + modelTransform.position.x = static_cast( i ); + appState.entityManager->createEntity( + modelTransform, + vertices, + "Assets/Textures/wall.jpg", + appState.miscData->descriptorSetLayout[1], + appState.miscData->descriptorPool ); + } + return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppIterate( void* appstate ) { - AppState& appState = *static_cast( appstate ); - RenderDevice& renderDevice = *appState.renderDevice; - MiscData& misc = *appState.miscData; - Frame& currentFrame = renderDevice.frames[renderDevice.frameIndex]; + AppState& appState = *static_cast( appstate ); + RenderDevice& renderDevice = *appState.renderDevice; + EntityManager& entityManager = *appState.entityManager; + MiscData& misc = *appState.miscData; + Frame& currentFrame = renderDevice.frames[renderDevice.frameIndex]; - VK_CHECK( vkWaitForFences( - renderDevice.device, 1, ¤tFrame.frameReadyToReuse, VK_TRUE, std::numeric_limits::max() ) ); + VK_CHECK( vkWaitForFences( renderDevice.device, 1, ¤tFrame.frameReadyToReuse, VK_TRUE, UINT32_MAX ) ); // All resources of frame 'frameIndex' are free. // time calc @@ -70,13 +135,13 @@ SDL_AppResult SDL_AppIterate( void* appstate ) SDL_SetWindowTitle( appState.window, appState.sprintfBuffer ); } - for ( Transform& transform : misc.modelTransform ) + for ( Entity& entity : entityManager.iter() ) { - transform.rotation = DirectX::XMQuaternionMultiply( + entity.transform().rotation = DirectX::XMQuaternionMultiply( DirectX::XMQuaternionRotationAxis( DirectX::XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ), DirectX::XMConvertToRadians( 60.0f ) * static_cast( deltaTime ) ), - transform.rotation ); + entity.transform().rotation ); } uint32_t currentImageIndex; @@ -88,6 +153,8 @@ SDL_AppResult SDL_AppIterate( void* appstate ) nullptr, ¤tImageIndex ) ); + // TODO: Resize Swapchain if required. + VK_CHECK( vkResetFences( renderDevice.device, 1, ¤tFrame.frameReadyToReuse ) ); VK_CHECK( vkResetCommandPool( renderDevice.device, currentFrame.commandPool, 0 ) ); @@ -155,12 +222,24 @@ SDL_AppResult SDL_AppIterate( void* appstate ) // Render Something? vkCmdBindPipeline( cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, misc.meshPipeline ); - VkDeviceSize constexpr offset = 0; - vkCmdBindVertexBuffers( cmd, 0, 1, &misc.vertexBuffer, &offset ); - vkCmdBindDescriptorSets( - cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, misc.pipelineLayout, 0, 1, &misc.descriptorSet, 0, nullptr ); - for ( Transform& localTransform : misc.modelTransform ) + for ( Entity const& entity : entityManager.iter() ) { + VkDeviceSize constexpr offset = 0; + vkCmdBindVertexBuffers( cmd, 0, 1, &entity.mesh().vertexBuffer, &offset ); + vkCmdBindDescriptorSets( + cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, misc.pipelineLayout, 0, 1, &misc.descriptorSet, 0, nullptr ); + + vkCmdBindDescriptorSets( + cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + misc.pipelineLayout, + 1, + 1, + &entity.material().descriptorSet, + 0, + nullptr ); + + Transform const& localTransform = entity.transform(); DirectX::XMMATRIX worldTransform; { auto [x, y, z] = localTransform.position; @@ -171,7 +250,7 @@ SDL_AppResult SDL_AppIterate( void* appstate ) } vkCmdPushConstants( cmd, misc.pipelineLayout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, sizeof worldTransform, &worldTransform ); - vkCmdDraw( cmd, static_cast( misc.vertices.size() ), 1, 0, 0 ); + vkCmdDraw( cmd, entity.mesh().vertexCount, 1, 0, 0 ); } } vkCmdEndRendering( cmd ); diff --git a/Blaze/EntityManager.cpp b/Blaze/EntityManager.cpp new file mode 100644 index 0000000..96d798d --- /dev/null +++ b/Blaze/EntityManager.cpp @@ -0,0 +1,584 @@ +#include "EntityManager.h" + +#include + +#include "GlobalMemory.h" +#include "RenderDevice.h" + +#include + +#include "Frame.h" + +Entity* EntityManager::createEntity( + Transform const& transform, + std::span const vertices, + const char* textureFile, + VkDescriptorSetLayout layout, + VkDescriptorPool pool ) +{ + ASSERT( pRenderDevice ); + RenderDevice& renderDevice = *pRenderDevice; + + Mesh mesh; + { + mesh.vertexCount = static_cast( vertices.size() ); + mesh.vertexBufferSize = static_cast( vertices.size_bytes() ); + + VkBufferCreateInfo const bufferCreateInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = mesh.vertexBufferSize, + .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + }; + + VmaAllocationCreateInfo constexpr allocationCreateInfo = { + .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .usage = VMA_MEMORY_USAGE_AUTO, + .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + .preferredFlags = 0, + .memoryTypeBits = 0, + .pool = nullptr, + .pUserData = nullptr, + .priority = 1.0f, + }; + + VmaAllocationInfo allocationInfo; + + VK_CHECK( vmaCreateBuffer( + pRenderDevice->gpuAllocator, + &bufferCreateInfo, + &allocationCreateInfo, + &mesh.vertexBuffer, + &mesh.vertexBufferAllocation, + &allocationInfo ) ); + + if ( allocationInfo.pMappedData ) + { + memcpy( allocationInfo.pMappedData, vertices.data(), vertices.size_bytes() ); + } + } + + Material material; + { + VkImage texture; + VmaAllocation textureAllocation; + VkImageView textureView; + VkSampler sampler; + + uint32_t width; + uint32_t height; + uint32_t numChannels = 4; + stbi_uc* textureData; + { + int w; + int h; + int nc; + int requestedChannels = static_cast( numChannels ); + + textureData = stbi_load( textureFile, &w, &h, &nc, requestedChannels ); + ASSERT( nc <= requestedChannels ); + + if ( !textureData ) + { + vmaDestroyBuffer( pRenderDevice->gpuAllocator, Take( mesh.vertexBuffer ), Take( mesh.vertexBufferAllocation ) ); + SDL_LogError( SDL_LOG_CATEGORY_ERROR, "%s", stbi_failure_reason() ); + return nullptr; + } + + width = static_cast( w ); + height = static_cast( h ); + } + + // Calculate mips + uint32_t mipLevels = + 1 + static_cast( floorf( log2f( static_cast( std::max( width, height ) ) ) ) ); + + VkImageCreateInfo const imageCreateInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .imageType = VK_IMAGE_TYPE_2D, + .format = VK_FORMAT_R8G8B8A8_SRGB, + .extent = { .width = width, .height = height, .depth = 1 }, + .mipLevels = mipLevels, + .arrayLayers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + }; + + VmaAllocationCreateInfo constexpr allocationCreateInfo = { + .flags = 0, + .usage = VMA_MEMORY_USAGE_AUTO, + .requiredFlags = 0, + .preferredFlags = 0, + .memoryTypeBits = 0, + .pool = nullptr, + .pUserData = nullptr, + .priority = 1.0f, + }; + + VK_CHECK( vmaCreateImage( + renderDevice.gpuAllocator, &imageCreateInfo, &allocationCreateInfo, &texture, &textureAllocation, nullptr ) ); + + VkImageSubresourceRange const subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = mipLevels, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + VkComponentMapping constexpr componentMapping = { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }; + + VkImageViewCreateInfo const imageViewCreateInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .image = texture, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = imageCreateInfo.format, + .components = componentMapping, + .subresourceRange = subresourceRange, + }; + + VK_CHECK( vkCreateImageView( renderDevice.device, &imageViewCreateInfo, nullptr, &textureView ) ); + + VkSamplerCreateInfo constexpr samplerCreateInfo = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .magFilter = VK_FILTER_LINEAR, + .minFilter = VK_FILTER_LINEAR, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT, + .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, + .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, + .mipLodBias = 0.0, + .anisotropyEnable = true, + .maxAnisotropy = 1.0f, + .compareEnable = false, + .compareOp = VK_COMPARE_OP_NEVER, + .minLod = 0.0f, + .maxLod = VK_LOD_CLAMP_NONE, + .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, + .unnormalizedCoordinates = false, + }; + + VK_CHECK( vkCreateSampler( renderDevice.device, &samplerCreateInfo, nullptr, &sampler ) ); + + // Staging Buffer Create + VkBuffer stagingBuffer; + VmaAllocation stagingAllocation; + { + VkBufferCreateInfo const stagingBufferCreateInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = static_cast( width ) * height * numChannels * sizeof( textureData[0] ), + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + }; + + VmaAllocationCreateInfo constexpr stagingAllocationCreateInfo = { + .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + .usage = VMA_MEMORY_USAGE_AUTO, + .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + .preferredFlags = 0, + .memoryTypeBits = 0, + .pool = nullptr, + .pUserData = nullptr, + .priority = 1.0f, + }; + + VmaAllocationInfo allocationInfo; + + VK_CHECK( vmaCreateBuffer( + renderDevice.gpuAllocator, + &stagingBufferCreateInfo, + &stagingAllocationCreateInfo, + &stagingBuffer, + &stagingAllocation, + &allocationInfo ) ); + + if ( allocationInfo.pMappedData ) + { + memcpy( allocationInfo.pMappedData, textureData, stagingBufferCreateInfo.size ); + } + } + + // All data is copied to stagingBuffer, don't need this. + stbi_image_free( textureData ); + + // Staging -> Texture transfer + { + Frame& frameInUse = renderDevice.frames[renderDevice.frameIndex]; + + // This should just pass. + VK_CHECK( vkWaitForFences( renderDevice.device, 1, &frameInUse.frameReadyToReuse, VK_TRUE, INT64_MAX ) ); + + // Reset Frame + VK_CHECK( vkResetFences( renderDevice.device, 1, &frameInUse.frameReadyToReuse ) ); + VK_CHECK( vkResetCommandPool( renderDevice.device, frameInUse.commandPool, 0 ) ); + + VkCommandBufferBeginInfo constexpr beginInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .pNext = nullptr, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + .pInheritanceInfo = nullptr, + }; + + VkImageMemoryBarrier2 const creationToTransferImageBarrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, + .srcAccessMask = VK_ACCESS_2_NONE, + .dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT, + .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = texture, + .subresourceRange = subresourceRange, + }; + + VkDependencyInfo const creationToTransferDependency = { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = 0, + .memoryBarrierCount = 0, + .pMemoryBarriers = nullptr, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = nullptr, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &creationToTransferImageBarrier, + }; + + std::array transferToReadyImageBarriers{ + // transferToReadyImageBarrier + VkImageMemoryBarrier2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + .dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = texture, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = mipLevels-1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }, + VkImageMemoryBarrier2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + .dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = texture, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = mipLevels-1, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + } + }; + + VkDependencyInfo const transferToReadyDependency = { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = 0, + .memoryBarrierCount = 0, + .pMemoryBarriers = nullptr, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = nullptr, + .imageMemoryBarrierCount = static_cast( transferToReadyImageBarriers.size() ), + .pImageMemoryBarriers = transferToReadyImageBarriers.data(), + }; + + VkImageSubresourceRange const mipLevelSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + std::array prepareNextMipLevelBarriers{ + // prepareNextMipLevelSrcImageBarrier + VkImageMemoryBarrier2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = texture, + .subresourceRange = mipLevelSubresource, + }, + // prepareNextMipLevelDstImageBarrier + VkImageMemoryBarrier2{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT, + .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT, + .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = texture, + .subresourceRange = mipLevelSubresource, + } + }; + + VkDependencyInfo const prepareNextMipLevelDependency = { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = 0, + .memoryBarrierCount = 0, + .pMemoryBarriers = nullptr, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = nullptr, + .imageMemoryBarrierCount = static_cast( prepareNextMipLevelBarriers.size() ), + .pImageMemoryBarriers = prepareNextMipLevelBarriers.data(), + }; + + + vkBeginCommandBuffer( frameInUse.commandBuffer, &beginInfo ); + { + VkImageSubresourceLayers imageSubresourceLayers = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + // TODO: Ensure `bufferRowLength` and `bufferImageHeight` are not required. + VkBufferImageCopy copyRegion = { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = imageSubresourceLayers, + .imageOffset = { 0, 0, 0 }, + .imageExtent = imageCreateInfo.extent + }; + + // Start + vkCmdPipelineBarrier2( frameInUse.commandBuffer, &creationToTransferDependency ); + + // Staging -> Image L0 + vkCmdCopyBufferToImage( + frameInUse.commandBuffer, stagingBuffer, texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region ); + + prepareNextMipLevelBarriers[0].subresourceRange.baseMipLevel = 0; + prepareNextMipLevelBarriers[1].subresourceRange.baseMipLevel = 1; + + int32_t mipSrcWidth = static_cast( width ); + int32_t mipSrcHeight = static_cast( height ); + int32_t mipDstWidth = std::max( mipSrcWidth / 2, 1 ); + int32_t mipDstHeight = std::max( mipSrcHeight / 2, 1 ); + + VkImageSubresourceLayers constexpr mipSubresourceLayers = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }; + + VkImageBlit2 imageBlit = { + .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + .pNext = nullptr, + .srcSubresource = mipSubresourceLayers, + .srcOffsets = { { 0, 0, 0 }, { mipSrcWidth, mipSrcHeight, 1 } }, + .dstSubresource = mipSubresourceLayers, + .dstOffsets = { { 0, 0, 0 }, { mipDstWidth, mipDstHeight, 1 } }, + }; + + imageBlit.srcSubresource.mipLevel = 0; + imageBlit.dstSubresource.mipLevel = 1; + imageBlit.srcOffsets[1].x = mipSrcWidth; + imageBlit.srcOffsets[1].y = mipSrcHeight; + imageBlit.dstOffsets[1].x = mipDstWidth; + imageBlit.dstOffsets[1].y = mipDstHeight; + + VkBlitImageInfo2 blitInfo = { + .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, + .pNext = nullptr, + .srcImage = texture, + .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .dstImage = texture, + .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .regionCount = 1, + .pRegions = &imageBlit, + .filter = VK_FILTER_LINEAR, + }; + + // MipMapping + for ( uint32_t dstMipLevel = 1; dstMipLevel < mipLevels; ++dstMipLevel ) + { + vkCmdPipelineBarrier2( frameInUse.commandBuffer, &prepareNextMipLevelDependency ); + vkCmdBlitImage2( frameInUse.commandBuffer, &blitInfo ); + + // Prep for NEXT iteration + + mipSrcWidth = mipDstWidth; + mipSrcHeight = mipDstHeight; + mipDstWidth = std::max( mipSrcWidth / 2, 1 ); + mipDstHeight = std::max( mipSrcHeight / 2, 1 ); + + imageBlit.srcSubresource.mipLevel = dstMipLevel; + imageBlit.dstSubresource.mipLevel = dstMipLevel + 1; + imageBlit.srcOffsets[1].x = mipSrcWidth; + imageBlit.srcOffsets[1].y = mipSrcHeight; + imageBlit.dstOffsets[1].x = mipDstWidth; + imageBlit.dstOffsets[1].y = mipDstHeight; + + // Prep current mip level as source + prepareNextMipLevelBarriers[0].subresourceRange.baseMipLevel = dstMipLevel; + prepareNextMipLevelBarriers[1].subresourceRange.baseMipLevel = dstMipLevel + 1; + } + + // End + vkCmdPipelineBarrier2( frameInUse.commandBuffer, &transferToReadyDependency ); + } + vkEndCommandBuffer( frameInUse.commandBuffer ); + + VkSubmitInfo submitInfo = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = nullptr, + .waitSemaphoreCount = 0, + .pWaitSemaphores = nullptr, + .pWaitDstStageMask = nullptr, + .commandBufferCount = 1, + .pCommandBuffers = &frameInUse.commandBuffer, + .signalSemaphoreCount = 0, + .pSignalSemaphores = nullptr, + }; + VK_CHECK( vkQueueSubmit( renderDevice.directQueue, 1, &submitInfo, frameInUse.frameReadyToReuse ) ); + + // Do not reset this. Else, the frame will never be available to the main loop. + VK_CHECK( vkWaitForFences( renderDevice.device, 1, &frameInUse.frameReadyToReuse, VK_TRUE, UINT64_MAX ) ); + + renderDevice.frameIndex = ( renderDevice.frameIndex + 1 ) % renderDevice.getNumFrames(); + } + + vmaDestroyBuffer( renderDevice.gpuAllocator, stagingBuffer, stagingAllocation ); + + VkDescriptorSetAllocateInfo const descriptorSetAllocateInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .pNext = nullptr, + .descriptorPool = pool, + .descriptorSetCount = 1, + .pSetLayouts = &layout, + }; + + VkDescriptorSet descriptorSet; + VK_CHECK( vkAllocateDescriptorSets( renderDevice.device, &descriptorSetAllocateInfo, &descriptorSet ) ); + + VkDescriptorImageInfo const descriptorImageInfo = { + .sampler = sampler, + .imageView = textureView, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet writeDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = descriptorSet, + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &descriptorImageInfo, + .pBufferInfo = nullptr, + .pTexelBufferView = nullptr, + }; + + vkUpdateDescriptorSets( renderDevice.device, 1, &writeDescriptorSet, 0, nullptr ); + + material = { texture, textureAllocation, textureView, sampler, descriptorSet }; + } + + entities[count++] = Entity( transform, mesh, material ); + + return entities + count; +} + +void EntityManager::destroyEntity( Entity* entity ) +{ + ASSERT( entity ); + if ( !entity->isInit() ) return; + + VkDevice const device = pRenderDevice->device; + VmaAllocator const allocator = pRenderDevice->gpuAllocator; + + vkDestroySampler( device, Take( entity->material().sampler ), nullptr ); + vkDestroyImageView( device, Take( entity->material().textureView ), nullptr ); + + vmaDestroyImage( allocator, Take( entity->material().texture ), Take( entity->material().textureAllocation ) ); + vmaDestroyBuffer( allocator, Take( entity->mesh().vertexBuffer ), Take( entity->mesh().vertexBufferAllocation ) ); + + // TODO: Leaking descriptor set. +} + +void EntityManager::destroy() +{ + Entity const* end = entities + capacity; + for ( Entity* iter = entities; iter != end; ++iter ) + { + destroyEntity( iter ); + } + + entities = nullptr; + capacity = 0; + count = 0; +} + +EntityManager::~EntityManager() +{ + assert( !entities ); +} + +EntityManager* EntityManager_Create( GlobalMemory* mem, RenderDevice* renderDevice, uint32_t const capacity ) +{ + Entity* data = reinterpret_cast( mem->allocate( capacity * sizeof( Entity ), alignof( Entity ) ) ); + memset( data, 0, capacity * sizeof( Entity ) ); + + std::byte* alloc = mem->allocate( sizeof( EntityManager ), alignof( EntityManager ) ); + return new ( alloc ) EntityManager{ renderDevice, data, capacity }; +} diff --git a/Blaze/EntityManager.h b/Blaze/EntityManager.h new file mode 100644 index 0000000..64fcad0 --- /dev/null +++ b/Blaze/EntityManager.h @@ -0,0 +1,148 @@ +#pragma once + +#include + +#include + +#include + +#include +#include + + +struct RenderDevice; +struct GlobalMemory; + +struct Vertex +{ + DirectX::XMFLOAT3 position; + DirectX::XMFLOAT3 color; + DirectX::XMFLOAT2 texCoord0; +}; + +struct Transform +{ + DirectX::XMFLOAT3 position; + float scale; + DirectX::XMVECTOR rotation; +}; + +struct Mesh +{ + VkBuffer vertexBuffer; + VmaAllocation vertexBufferAllocation; + uint32_t vertexBufferSize; + uint32_t vertexCount; +}; + +struct Material +{ + VkImage texture; + VmaAllocation textureAllocation; + VkImageView textureView; + VkSampler sampler; // TODO: Reuse + VkDescriptorSet descriptorSet; +}; + +struct Entity +{ +private: + Transform m_transform; + Mesh m_mesh; + Material m_material; + +public: + [[nodiscard]] Transform& transform() + { + return m_transform; + } + + [[nodiscard]] Transform const& transform() const + { + return m_transform; + } + + [[nodiscard]] Mesh& mesh() + { + return m_mesh; + } + + [[nodiscard]] Mesh const& mesh() const + { + return m_mesh; + } + + [[nodiscard]] Material& material() + { + return m_material; + } + + [[nodiscard]] Material const& material() const + { + return m_material; + } + + [[nodiscard]] bool isInit() const + { + return m_mesh.vertexBuffer or m_material.texture; + } + + Entity( Transform const& transform, Mesh const& mesh, Material const& material ) + : m_transform{ transform }, m_mesh{ mesh }, m_material{ material } + {} +}; + +struct EntityManager +{ + struct Iterable + { + private: + Entity* m_begin; + Entity* m_end; + + public: + Iterable( Entity* begin, uint32_t const count ) : m_begin{ begin }, m_end{ begin + count } + {} + + // Iterator + [[nodiscard]] Entity* begin() const + { + return m_begin; + } + [[nodiscard]] Entity* end() const + { + return m_end; + } + }; + + RenderDevice* pRenderDevice; + Entity* entities; + uint32_t count; + uint32_t capacity; + + EntityManager( RenderDevice* renderDevice, Entity* data, uint32_t const capacity ) + : pRenderDevice{ renderDevice }, entities{ data }, count{ 0 }, capacity{ capacity } + {} + + [[nodiscard]] Iterable iter() const + { + return Iterable{ entities, count }; + } + + // Make Entities return ID, make it a sparse indexing system. + // TODO: Remove the descriptor pool dependency. + Entity* createEntity( + Transform const& transform, + std::span vertices, + const char* textureFile, + VkDescriptorSetLayout layout, + VkDescriptorPool pool ); + + void destroyEntity( Entity* entity ); + + void destroy(); + + ~EntityManager(); +}; + +EntityManager* EntityManager_Create( GlobalMemory* mem, RenderDevice* renderDevice, uint32_t capacity ); diff --git a/Blaze/MacroUtils.h b/Blaze/MacroUtils.h index d722799..137d5fc 100644 --- a/Blaze/MacroUtils.h +++ b/Blaze/MacroUtils.h @@ -4,6 +4,8 @@ #include #include +#include + #define G_ASSERT( COND ) \ do \ { \ diff --git a/Blaze/MiscData.cpp b/Blaze/MiscData.cpp index 429e6a2..d10ba1b 100644 --- a/Blaze/MiscData.cpp +++ b/Blaze/MiscData.cpp @@ -4,9 +4,7 @@ #include -#include - -#include "Frame.h" +#include "EntityManager.h" // Refactor away. #include "MacroUtils.h" #include "RenderDevice.h" @@ -41,31 +39,40 @@ bool MiscData::init( RenderDevice const& renderDevice ) VkShaderModule shaderModule; VK_CHECK( vkCreateShaderModule( device, &shaderModuleCreateInfo, nullptr, &shaderModule ) ); - std::array descriptorSetLayoutBindings{ - VkDescriptorSetLayoutBinding{ - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .pImmutableSamplers = nullptr, - }, - VkDescriptorSetLayoutBinding{ - .binding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - .pImmutableSamplers = nullptr, - }, + VkDescriptorSetLayoutBinding constexpr perFrameDescriptorBinding{ + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .pImmutableSamplers = nullptr, }; - VkDescriptorSetLayoutCreateInfo const descriptorSetLayoutCreateInfo = { + VkDescriptorSetLayoutBinding constexpr perMaterialDescriptorBinding{ + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .pImmutableSamplers = nullptr, + }; + + VkDescriptorSetLayoutCreateInfo perFrameDescriptorSetLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, - .bindingCount = static_cast( descriptorSetLayoutBindings.size() ), - .pBindings = descriptorSetLayoutBindings.data(), + .bindingCount = 1, + .pBindings = &perFrameDescriptorBinding, }; - VK_CHECK( vkCreateDescriptorSetLayout( device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayout ) ); + VK_CHECK( vkCreateDescriptorSetLayout( + device, &perFrameDescriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayout[0] ) ); + VkDescriptorSetLayoutCreateInfo perMaterialDescriptorSetLayoutCreateInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .bindingCount = 1, + .pBindings = &perMaterialDescriptorBinding, + }; + VK_CHECK( vkCreateDescriptorSetLayout( + device, &perMaterialDescriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayout[1] ) ); VkPushConstantRange const pushConstantRange = { .stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS, @@ -77,8 +84,8 @@ bool MiscData::init( RenderDevice const& renderDevice ) .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, - .setLayoutCount = 1, - .pSetLayouts = &descriptorSetLayout, + .setLayoutCount = static_cast( descriptorSetLayout.size() ), + .pSetLayouts = descriptorSetLayout.data(), .pushConstantRangeCount = 1, .pPushConstantRanges = &pushConstantRange, }; @@ -279,525 +286,6 @@ bool MiscData::init( RenderDevice const& renderDevice ) SDL_free( rawData ); } - // Vertex Buffer Creation - { - vertexBufferSize = sizeof vertices[0] * vertices.size(); - - // TL----TR - // | \ | - // | \ | - // | \ | - // BL----BR - // - // BL -> BR -> TL - // TL -> BR -> TR - - vertices = std::array{ - // Bottom Left - Vertex{ - .position = { -1.0f, -1.0f, 0.0f }, - .color = { 0.0f, 0.0f, 1.0f }, - .texCoord0 = { 0.0f, 0.0f }, - }, - // Bottom Right - Vertex{ - .position = { 1.0f, -1.0f, 0.0f }, - .color = { 1.0f, 0.0f, 0.0f }, - .texCoord0 = { 1.0f, 0.0f }, - }, - // Top Left - Vertex{ - .position = { -1.0f, 1.0f, 0.0f }, - .color = { 0.0f, 1.0f, 0.0f }, - .texCoord0 = { 0.0f, 1.0f }, - }, - // Top Right - Vertex{ - .position = { 1.0f, 1.0f, 0.0f }, - .color = { 1.0f, 1.0f, 0.0f }, - .texCoord0 = { 1.0f, 1.0f }, - } - }; - - VkBufferCreateInfo const bufferCreateInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = vertexBufferSize, - .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - }; - - VmaAllocationCreateInfo constexpr allocationCreateInfo = { - .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, - .usage = VMA_MEMORY_USAGE_AUTO, - .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - .preferredFlags = 0, - .memoryTypeBits = 0, - .pool = nullptr, - .pUserData = nullptr, - .priority = 1.0f, - }; - - VmaAllocationInfo allocationInfo; - - VK_CHECK( vmaCreateBuffer( - renderDevice.gpuAllocator, - &bufferCreateInfo, - &allocationCreateInfo, - &vertexBuffer, - &vertexBufferAllocation, - &allocationInfo ) ); - - if ( allocationInfo.pMappedData ) - { - memcpy( allocationInfo.pMappedData, vertices.data(), vertices.size() * sizeof vertices[0] ); - } - } - - // Texture - { - uint32_t width; - uint32_t height; - uint32_t numChannels = 4; - stbi_uc* textureData; - { - int w; - int h; - int nc; - int requestedChannels = static_cast( numChannels ); - - textureData = stbi_load( "Assets/Textures/wall.jpg", &w, &h, &nc, requestedChannels ); - ASSERT( nc <= requestedChannels ); - - if ( !textureData ) - { - vkDestroyPipeline( device, Take( meshPipeline ), nullptr ); - vmaDestroyBuffer( renderDevice.gpuAllocator, Take( vertexBuffer ), Take( vertexBufferAllocation ) ); - SDL_LogError( SDL_LOG_CATEGORY_ERROR, "%s", stbi_failure_reason() ); - return false; - } - - width = static_cast( w ); - height = static_cast( h ); - } - - // Calculate mips - uint32_t mipLevels = - 1 + static_cast( floorf( log2f( static_cast( std::max( width, height ) ) ) ) ); - - VkImageCreateInfo const imageCreateInfo = { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .imageType = VK_IMAGE_TYPE_2D, - .format = VK_FORMAT_R8G8B8A8_SRGB, - .extent = { .width = width, .height = height, .depth = 1 }, - .mipLevels = mipLevels, - .arrayLayers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - }; - - VmaAllocationCreateInfo constexpr allocationCreateInfo = { - .flags = 0, - .usage = VMA_MEMORY_USAGE_AUTO, - .requiredFlags = 0, - .preferredFlags = 0, - .memoryTypeBits = 0, - .pool = nullptr, - .pUserData = nullptr, - .priority = 1.0f, - }; - - VK_CHECK( vmaCreateImage( - renderDevice.gpuAllocator, &imageCreateInfo, &allocationCreateInfo, &texture, &textureAllocation, nullptr ) ); - - VkImageSubresourceRange const subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = mipLevels, - .baseArrayLayer = 0, - .layerCount = 1, - }; - - VkComponentMapping constexpr componentMapping = { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, - }; - - VkImageViewCreateInfo const imageViewCreateInfo = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .image = texture, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = imageCreateInfo.format, - .components = componentMapping, - .subresourceRange = subresourceRange, - }; - - VK_CHECK( vkCreateImageView( device, &imageViewCreateInfo, nullptr, &textureView ) ); - - VkSamplerCreateInfo constexpr samplerCreateInfo = { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .magFilter = VK_FILTER_LINEAR, - .minFilter = VK_FILTER_LINEAR, - .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT, - .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, - .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, - .mipLodBias = 0.0, - .anisotropyEnable = true, - .maxAnisotropy = 1.0f, - .compareEnable = false, - .compareOp = VK_COMPARE_OP_NEVER, - .minLod = 0.0f, - .maxLod = VK_LOD_CLAMP_NONE, - .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, - .unnormalizedCoordinates = false, - }; - - VK_CHECK( vkCreateSampler( device, &samplerCreateInfo, nullptr, &sampler ) ); - - // Staging Buffer Create - VkBuffer stagingBuffer; - VmaAllocation stagingAllocation; - { - VkBufferCreateInfo const stagingBufferCreateInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = static_cast( width ) * height * numChannels * sizeof( textureData[0] ), - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - }; - - VmaAllocationCreateInfo constexpr stagingAllocationCreateInfo = { - .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, - .usage = VMA_MEMORY_USAGE_AUTO, - .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - .preferredFlags = 0, - .memoryTypeBits = 0, - .pool = nullptr, - .pUserData = nullptr, - .priority = 1.0f, - }; - - VmaAllocationInfo allocationInfo; - - VK_CHECK( vmaCreateBuffer( - renderDevice.gpuAllocator, - &stagingBufferCreateInfo, - &stagingAllocationCreateInfo, - &stagingBuffer, - &stagingAllocation, - &allocationInfo ) ); - - if ( allocationInfo.pMappedData ) - { - memcpy( allocationInfo.pMappedData, textureData, stagingBufferCreateInfo.size ); - } - } - - // All data is copied to stagingBuffer, don't need this. - stbi_image_free( textureData ); - - // Staging -> Texture transfer - { - Frame& frameInUse = renderDevice.frames[0]; - - // This should just pass. - VK_CHECK( vkWaitForFences( device, 1, &frameInUse.frameReadyToReuse, VK_TRUE, INT64_MAX ) ); - VK_CHECK( vkResetFences( device, 1, &frameInUse.frameReadyToReuse ) ); - - VkCommandBufferBeginInfo constexpr beginInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .pNext = nullptr, - .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - .pInheritanceInfo = nullptr, - }; - - VkImageMemoryBarrier2 const creationToTransferImageBarrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, - .srcAccessMask = VK_ACCESS_2_NONE, - .dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT, - .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture, - .subresourceRange = subresourceRange, - }; - - VkDependencyInfo const creationToTransferDependency = { - .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - .pNext = nullptr, - .dependencyFlags = 0, - .memoryBarrierCount = 0, - .pMemoryBarriers = nullptr, - .bufferMemoryBarrierCount = 0, - .pBufferMemoryBarriers = nullptr, - .imageMemoryBarrierCount = 1, - .pImageMemoryBarriers = &creationToTransferImageBarrier, - }; - - std::array transferToReadyImageBarriers{ - // transferToReadyImageBarrier - VkImageMemoryBarrier2{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, - .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, - .dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT, - .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = mipLevels-1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }, - VkImageMemoryBarrier2{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, - .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, - .dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT, - .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = mipLevels-1, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - } - }; - - VkDependencyInfo const transferToReadyDependency = { - .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - .pNext = nullptr, - .dependencyFlags = 0, - .memoryBarrierCount = 0, - .pMemoryBarriers = nullptr, - .bufferMemoryBarrierCount = 0, - .pBufferMemoryBarriers = nullptr, - .imageMemoryBarrierCount = static_cast( transferToReadyImageBarriers.size() ), - .pImageMemoryBarriers = transferToReadyImageBarriers.data(), - }; - - VkImageSubresourceRange const mipLevelSubresource = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }; - - std::array prepareNextMipLevelBarriers{ - // prepareNextMipLevelSrcImageBarrier - VkImageMemoryBarrier2{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, - .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, - .dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT, - .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture, - .subresourceRange = mipLevelSubresource, - }, - // prepareNextMipLevelDstImageBarrier - VkImageMemoryBarrier2{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT, - .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT, - .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture, - .subresourceRange = mipLevelSubresource, - } - }; - - VkDependencyInfo const prepareNextMipLevelDependency = { - .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - .pNext = nullptr, - .dependencyFlags = 0, - .memoryBarrierCount = 0, - .pMemoryBarriers = nullptr, - .bufferMemoryBarrierCount = 0, - .pBufferMemoryBarriers = nullptr, - .imageMemoryBarrierCount = static_cast( prepareNextMipLevelBarriers.size() ), - .pImageMemoryBarriers = prepareNextMipLevelBarriers.data(), - }; - - - vkBeginCommandBuffer( frameInUse.commandBuffer, &beginInfo ); - { - VkImageSubresourceLayers imageSubresourceLayers = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }; - - // TODO: Ensure `bufferRowLength` and `bufferImageHeight` are not required. - VkBufferImageCopy copyRegion = { - .bufferOffset = 0, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = imageSubresourceLayers, - .imageOffset = { 0, 0, 0 }, - .imageExtent = imageCreateInfo.extent - }; - - // Start - vkCmdPipelineBarrier2( frameInUse.commandBuffer, &creationToTransferDependency ); - - // Staging -> Image L0 - vkCmdCopyBufferToImage( - frameInUse.commandBuffer, stagingBuffer, texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region ); - - prepareNextMipLevelBarriers[0].subresourceRange.baseMipLevel = 0; - prepareNextMipLevelBarriers[1].subresourceRange.baseMipLevel = 1; - - int32_t mipSrcWidth = static_cast( width ); - int32_t mipSrcHeight = static_cast( height ); - int32_t mipDstWidth = std::max( mipSrcWidth / 2, 1 ); - int32_t mipDstHeight = std::max( mipSrcHeight / 2, 1 ); - - VkImageSubresourceLayers constexpr mipSubresourceLayers = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }; - - VkImageBlit2 imageBlit = { - .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, - .pNext = nullptr, - .srcSubresource = mipSubresourceLayers, - .srcOffsets = { { 0, 0, 0 }, { mipSrcWidth, mipSrcHeight, 1 } }, - .dstSubresource = mipSubresourceLayers, - .dstOffsets = { { 0, 0, 0 }, { mipDstWidth, mipDstHeight, 1 } }, - }; - - imageBlit.srcSubresource.mipLevel = 0; - imageBlit.dstSubresource.mipLevel = 1; - imageBlit.srcOffsets[1].x = mipSrcWidth; - imageBlit.srcOffsets[1].y = mipSrcHeight; - imageBlit.dstOffsets[1].x = mipDstWidth; - imageBlit.dstOffsets[1].y = mipDstHeight; - - VkBlitImageInfo2 blitInfo = { - .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, - .pNext = nullptr, - .srcImage = texture, - .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - .dstImage = texture, - .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .regionCount = 1, - .pRegions = &imageBlit, - .filter = VK_FILTER_LINEAR, - }; - - // MipMapping - for ( uint32_t dstMipLevel = 1; dstMipLevel < mipLevels; ++dstMipLevel ) - { - vkCmdPipelineBarrier2( frameInUse.commandBuffer, &prepareNextMipLevelDependency ); - vkCmdBlitImage2( frameInUse.commandBuffer, &blitInfo ); - - // Prep for NEXT iteration - - mipSrcWidth = mipDstWidth; - mipSrcHeight = mipDstHeight; - mipDstWidth = std::max( mipSrcWidth / 2, 1 ); - mipDstHeight = std::max( mipSrcHeight / 2, 1 ); - - imageBlit.srcSubresource.mipLevel = dstMipLevel; - imageBlit.dstSubresource.mipLevel = dstMipLevel + 1; - imageBlit.srcOffsets[1].x = mipSrcWidth; - imageBlit.srcOffsets[1].y = mipSrcHeight; - imageBlit.dstOffsets[1].x = mipDstWidth; - imageBlit.dstOffsets[1].y = mipDstHeight; - - // Prep current mip level as source - prepareNextMipLevelBarriers[0].subresourceRange.baseMipLevel = dstMipLevel; - prepareNextMipLevelBarriers[1].subresourceRange.baseMipLevel = dstMipLevel + 1; - } - - // End - vkCmdPipelineBarrier2( frameInUse.commandBuffer, &transferToReadyDependency ); - } - vkEndCommandBuffer( frameInUse.commandBuffer ); - - VkSubmitInfo submitInfo = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = nullptr, - .waitSemaphoreCount = 0, - .pWaitSemaphores = nullptr, - .pWaitDstStageMask = nullptr, - .commandBufferCount = 1, - .pCommandBuffers = &frameInUse.commandBuffer, - .signalSemaphoreCount = 0, - .pSignalSemaphores = nullptr, - }; - VK_CHECK( vkQueueSubmit( renderDevice.directQueue, 1, &submitInfo, frameInUse.frameReadyToReuse ) ); - - // Do not reset this. Else, the frame will never be available to the main loop. - VK_CHECK( vkWaitForFences( device, 1, &frameInUse.frameReadyToReuse, VK_TRUE, INT64_MAX ) ); - } - - vmaDestroyBuffer( renderDevice.gpuAllocator, stagingBuffer, stagingAllocation ); - } - - // Model Setup - modelTransform[0].position = { 1.0f, 0.0f, 0.0f }; - modelTransform[0].scale = 1.0f; - modelTransform[0].rotation = - DirectX::XMQuaternionRotationAxis( DirectX::XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ), 0.0f ); - - modelTransform[1].position = { -1.0f, 0.0f, 0.0f }; - modelTransform[1].scale = 1.0f; - modelTransform[1].rotation = - DirectX::XMQuaternionRotationAxis( DirectX::XMVectorSet( 1.0f, 0.0f, 0.0f, 0.0f ), 0.0f ); - // Camera { cameraPosition = DirectX::XMVectorSet( 0.0f, 0.0f, -4.0f, 1.0f ); @@ -853,18 +341,18 @@ bool MiscData::init( RenderDevice const& renderDevice ) std::array poolSizes = { VkDescriptorPoolSize{ .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = renderDevice.getNumFrames(), + .descriptorCount = 3, }, VkDescriptorPoolSize{ .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = renderDevice.getNumFrames(), + .descriptorCount = 100, }, }; VkDescriptorPoolCreateInfo const descriptorPoolCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .pNext = nullptr, .flags = 0, - .maxSets = renderDevice.getNumFrames(), + .maxSets = 101, .poolSizeCount = static_cast( poolSizes.size() ), .pPoolSizes = poolSizes.data(), }; @@ -876,7 +364,7 @@ bool MiscData::init( RenderDevice const& renderDevice ) .pNext = nullptr, .descriptorPool = descriptorPool, .descriptorSetCount = 1, - .pSetLayouts = &descriptorSetLayout, + .pSetLayouts = &descriptorSetLayout[0], }; VK_CHECK( vkAllocateDescriptorSets( device, &descriptorSetAllocateInfo, &descriptorSet ) ); @@ -887,12 +375,6 @@ bool MiscData::init( RenderDevice const& renderDevice ) .range = sizeof CameraData, }; - VkDescriptorImageInfo const descriptorImageInfo = { - .sampler = sampler, - .imageView = textureView, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; - std::array writeDescriptorSets = { VkWriteDescriptorSet{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, @@ -906,19 +388,6 @@ bool MiscData::init( RenderDevice const& renderDevice ) .pBufferInfo = &descriptorBufferInfo, .pTexelBufferView = nullptr, }, - - VkWriteDescriptorSet{ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = descriptorSet, - .dstBinding = 1, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = &descriptorImageInfo, - .pBufferInfo = nullptr, - .pTexelBufferView = nullptr, - } }; vkUpdateDescriptorSets( @@ -998,13 +467,8 @@ void MiscData::destroy( RenderDevice const& renderDevice ) vkDestroyDescriptorPool( device, Take( descriptorPool ), nullptr ); vmaDestroyBuffer( renderDevice.gpuAllocator, Take( cameraUniformBuffer ), Take( cameraUniformBufferAllocation ) ); - vkDestroySampler( device, Take( sampler ), nullptr ); - vkDestroyImageView( device, Take( textureView ), nullptr ); - - vmaDestroyImage( renderDevice.gpuAllocator, Take( texture ), Take( textureAllocation ) ); - vmaDestroyBuffer( renderDevice.gpuAllocator, Take( vertexBuffer ), Take( vertexBufferAllocation ) ); - vkDestroyPipeline( device, Take( meshPipeline ), nullptr ); vkDestroyPipelineLayout( device, Take( pipelineLayout ), nullptr ); - vkDestroyDescriptorSetLayout( device, Take( descriptorSetLayout ), nullptr ); + vkDestroyDescriptorSetLayout( device, Take( descriptorSetLayout[1] ), nullptr ); + vkDestroyDescriptorSetLayout( device, Take( descriptorSetLayout[0] ), nullptr ); } diff --git a/Blaze/MiscData.h b/Blaze/MiscData.h index cd1d18b..70e7642 100644 --- a/Blaze/MiscData.h +++ b/Blaze/MiscData.h @@ -10,20 +10,6 @@ struct GlobalMemory; struct RenderDevice; -struct Vertex -{ - DirectX::XMFLOAT3 position; - DirectX::XMFLOAT3 color; - DirectX::XMFLOAT2 texCoord0; -}; - -struct Transform -{ - DirectX::XMFLOAT3 position; - float scale; - DirectX::XMVECTOR rotation; -}; - struct MiscData { struct CameraData @@ -32,42 +18,30 @@ struct MiscData DirectX::XMMATRIX projectionMatrix; }; - uint64_t previousCounter; + uint64_t previousCounter; - VkDescriptorSetLayout descriptorSetLayout; - VkPipelineLayout pipelineLayout; - VkPipeline meshPipeline; + std::array descriptorSetLayout; + VkPipelineLayout pipelineLayout; + VkPipeline meshPipeline; - VkBuffer vertexBuffer; - VmaAllocation vertexBufferAllocation; - size_t vertexBufferSize; - std::array vertices; + uint64_t _padding; // TODO: Optimize out? - VkImage texture; - VmaAllocation textureAllocation; - VkImageView textureView; - VkSampler sampler; + DirectX::XMVECTOR cameraPosition; + DirectX::XMVECTOR cameraTarget; + DirectX::XMVECTOR cameraUp; + CameraData cameraData; + VkBuffer cameraUniformBuffer; + VmaAllocation cameraUniformBufferAllocation; + size_t cameraUniformBufferSize; + uint8_t* cameraUniformBufferPtr; + VkDescriptorPool descriptorPool; + VkDescriptorSet descriptorSet; - uint64_t _padding; // TODO: Optimize out? + VkImageMemoryBarrier2 acquireToRenderBarrier; + VkDependencyInfo acquireToRenderDependency; + VkImageMemoryBarrier2 renderToPresentBarrier; + VkDependencyInfo renderToPresentDependency; - std::array modelTransform; - - DirectX::XMVECTOR cameraPosition; - DirectX::XMVECTOR cameraTarget; - DirectX::XMVECTOR cameraUp; - CameraData cameraData; - VkBuffer cameraUniformBuffer; - VmaAllocation cameraUniformBufferAllocation; - size_t cameraUniformBufferSize; - uint8_t* cameraUniformBufferPtr; - VkDescriptorPool descriptorPool; - VkDescriptorSet descriptorSet; - - VkImageMemoryBarrier2 acquireToRenderBarrier; - VkDependencyInfo acquireToRenderDependency; - VkImageMemoryBarrier2 renderToPresentBarrier; - VkDependencyInfo renderToPresentDependency; - - bool init( RenderDevice const& renderDevice ); - void destroy( RenderDevice const& renderDevice ); + bool init( RenderDevice const& renderDevice ); + void destroy( RenderDevice const& renderDevice ); };