#include "MiscData.h" #include #include #include #include "Frame.h" #include "MacroUtils.h" #include "RenderDevice.h" bool MiscData::init( RenderDevice const& renderDevice ) { VkDevice const device = renderDevice.device; previousCounter = 0; // Pipeline Creation { size_t dataSize; void* rawData = SDL_LoadFile( "Mesh.spv", &dataSize ); ASSERT( dataSize % 4 == 0 ); if ( !rawData ) { SDL_LogError( SDL_LOG_CATEGORY_SYSTEM, "%s", SDL_GetError() ); return false; } uint32_t const* data = static_cast( rawData ); // Create Shader Module VkShaderModuleCreateInfo const shaderModuleCreateInfo = { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .pNext = nullptr, .flags = 0, .codeSize = dataSize, .pCode = data, }; 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, }, }; VkDescriptorSetLayoutCreateInfo const descriptorSetLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, .bindingCount = static_cast( descriptorSetLayoutBindings.size() ), .pBindings = descriptorSetLayoutBindings.data(), }; VK_CHECK( vkCreateDescriptorSetLayout( device, &descriptorSetLayoutCreateInfo, nullptr, &descriptorSetLayout ) ); VkPipelineLayoutCreateInfo const pipelineLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, .setLayoutCount = 1, .pSetLayouts = &descriptorSetLayout, .pushConstantRangeCount = 0, .pPushConstantRanges = nullptr, }; VK_CHECK( vkCreatePipelineLayout( device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout ) ); std::array stages = { VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, .flags = 0, .stage = VK_SHADER_STAGE_VERTEX_BIT, .module = shaderModule, .pName = "VertexMain", .pSpecializationInfo = nullptr, }, VkPipelineShaderStageCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = nullptr, .flags = 0, .stage = VK_SHADER_STAGE_FRAGMENT_BIT, .module = shaderModule, .pName = "FragmentMain", .pSpecializationInfo = nullptr, } }; // Bindings VkVertexInputBindingDescription constexpr bindingDescription = { .binding = 0, .stride = sizeof( Vertex ), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, }; std::array attributeDescriptions = { VkVertexInputAttributeDescription{ .location = 0, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof( Vertex, position ), }, VkVertexInputAttributeDescription{ .location = 1, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof( Vertex, color ), }, VkVertexInputAttributeDescription{ .location = 2, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof( Vertex, texCoord0 ), }, }; VkPipelineVertexInputStateCreateInfo const vertexInputState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .vertexBindingDescriptionCount = 1, .pVertexBindingDescriptions = &bindingDescription, .vertexAttributeDescriptionCount = static_cast( attributeDescriptions.size() ), .pVertexAttributeDescriptions = attributeDescriptions.data(), }; VkPipelineInputAssemblyStateCreateInfo constexpr inputAssembly = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, .primitiveRestartEnable = VK_FALSE, }; VkPipelineTessellationStateCreateInfo constexpr tessellationState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .patchControlPoints = 0, }; VkPipelineViewportStateCreateInfo constexpr viewportState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .viewportCount = 1, .pViewports = nullptr, .scissorCount = 1, .pScissors = nullptr, }; VkPipelineRasterizationStateCreateInfo constexpr rasterizationState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .depthClampEnable = VK_TRUE, .rasterizerDiscardEnable = VK_FALSE, .polygonMode = VK_POLYGON_MODE_FILL, .cullMode = VK_CULL_MODE_NONE, .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, .depthBiasEnable = VK_FALSE, .depthBiasConstantFactor = 0.0f, .depthBiasClamp = 0.0f, .depthBiasSlopeFactor = 0.0f, .lineWidth = 1.0f, }; VkPipelineMultisampleStateCreateInfo constexpr multisampleState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, .sampleShadingEnable = VK_FALSE, .minSampleShading = 0.0f, .pSampleMask = nullptr, .alphaToCoverageEnable = VK_FALSE, .alphaToOneEnable = VK_FALSE, }; VkPipelineDepthStencilStateCreateInfo constexpr depthStencilState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .depthTestEnable = VK_FALSE, .depthWriteEnable = VK_FALSE, .depthCompareOp = VK_COMPARE_OP_ALWAYS, .depthBoundsTestEnable = VK_FALSE, .stencilTestEnable = VK_FALSE, .front = {}, .back = {}, .minDepthBounds = 0.0f, .maxDepthBounds = 1.0f, }; VkPipelineColorBlendAttachmentState constexpr colorBlendAttachmentState = { .blendEnable = VK_FALSE, .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, .colorBlendOp = VK_BLEND_OP_ADD, .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE, .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, .alphaBlendOp = VK_BLEND_OP_ADD, .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, }; VkPipelineColorBlendStateCreateInfo const colorBlendState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .logicOpEnable = VK_FALSE, .logicOp = VK_LOGIC_OP_COPY, .attachmentCount = 1, .pAttachments = &colorBlendAttachmentState, .blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }, }; std::array constexpr dynamicStates{ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; VkPipelineDynamicStateCreateInfo const dynamicStateCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, .dynamicStateCount = static_cast( dynamicStates.size() ), .pDynamicStates = dynamicStates.data() }; VkPipelineRenderingCreateInfoKHR const renderingCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, .colorAttachmentCount = 1, .pColorAttachmentFormats = &renderDevice.swapchainFormat, }; VkGraphicsPipelineCreateInfo const graphicsPipelineCreateInfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &renderingCreateInfo, .flags = 0, .stageCount = static_cast( stages.size() ), .pStages = stages.data(), .pVertexInputState = &vertexInputState, .pInputAssemblyState = &inputAssembly, .pTessellationState = &tessellationState, .pViewportState = &viewportState, .pRasterizationState = &rasterizationState, .pMultisampleState = &multisampleState, .pDepthStencilState = &depthStencilState, .pColorBlendState = &colorBlendState, .pDynamicState = &dynamicStateCreateInfo, .layout = pipelineLayout, .renderPass = nullptr, .subpass = 0, .basePipelineHandle = nullptr, .basePipelineIndex = 0, }; VK_CHECK( vkCreateGraphicsPipelines( device, nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &meshPipeline ) ); vkDestroyShaderModule( device, shaderModule, nullptr ); 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( "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 ); } 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 = 1, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, .usage = VK_IMAGE_USAGE_TRANSFER_DST_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 constexpr subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, .levelCount = 1, .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 = 0.0f, .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 ); { 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, }; VkImageMemoryBarrier2 const transferToReadyImageBarrier = { .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_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 = subresourceRange, }; VkDependencyInfo const transferToReadyDependency = { .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .pNext = nullptr, .dependencyFlags = 0, .memoryBarrierCount = 0, .pMemoryBarriers = nullptr, .bufferMemoryBarrierCount = 0, .pBufferMemoryBarriers = nullptr, .imageMemoryBarrierCount = 1, .pImageMemoryBarriers = &transferToReadyImageBarrier, }; 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 }; vkCmdPipelineBarrier2( frameInUse.commandBuffer, &creationToTransferDependency ); vkCmdCopyBufferToImage( frameInUse.commandBuffer, stagingBuffer, texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Region ); 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 ); } // Camera { cameraPosition = DirectX::XMVectorSet( 0.0f, 0.0f, -5.0f, 1.0f ); cameraTarget = DirectX::XMVectorSet( 0.0f, 0.0f, 0.0f, 1.0f ); cameraUp = DirectX::XMVectorSet( 0.0f, 1.0f, 0.0f, 1.0f ); cameraData.modelMatrix = DirectX::XMMatrixIdentity(); cameraData.viewMatrix = DirectX::XMMatrixLookAtLH( cameraPosition, cameraTarget, cameraUp ); cameraData.projectionMatrix = DirectX::XMMatrixPerspectiveFovLH( DirectX::XMConvertToRadians( 70.0f ), 16.0f / 9.0f, 0.1f, 1000.0f ); cameraUniformBufferSize = sizeof( CameraData ); VkBufferCreateInfo const bufferCreateInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, .size = cameraUniformBufferSize, .usage = VK_BUFFER_USAGE_UNIFORM_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, &cameraUniformBuffer, &cameraUniformBufferAllocation, &allocationInfo ) ); if ( allocationInfo.pMappedData ) { memcpy( allocationInfo.pMappedData, &cameraData, sizeof cameraData ); cameraUniformBufferPtr = static_cast( allocationInfo.pMappedData ); } } // Descriptors { std::array poolSizes = { VkDescriptorPoolSize{ .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = renderDevice.getNumFrames(), }, VkDescriptorPoolSize{ .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = renderDevice.getNumFrames(), }, }; VkDescriptorPoolCreateInfo const descriptorPoolCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .pNext = nullptr, .flags = 0, .maxSets = renderDevice.getNumFrames(), .poolSizeCount = static_cast( poolSizes.size() ), .pPoolSizes = poolSizes.data(), }; VK_CHECK( vkCreateDescriptorPool( device, &descriptorPoolCreateInfo, nullptr, &descriptorPool ) ); VkDescriptorSetAllocateInfo const descriptorSetAllocateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .pNext = nullptr, .descriptorPool = descriptorPool, .descriptorSetCount = 1, .pSetLayouts = &descriptorSetLayout, }; VK_CHECK( vkAllocateDescriptorSets( device, &descriptorSetAllocateInfo, &descriptorSet ) ); VkDescriptorBufferInfo const descriptorBufferInfo = { .buffer = cameraUniformBuffer, .offset = 0, .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, .pNext = nullptr, .dstSet = descriptorSet, .dstBinding = 0, .dstArrayElement = 0, .descriptorCount = 1, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .pImageInfo = nullptr, .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( device, static_cast( writeDescriptorSets.size() ), writeDescriptorSets.data(), 0, nullptr ); } // Barrier Creation { VkImageSubresourceRange subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1, }; acquireToRenderBarrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = nullptr, .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .subresourceRange = subresourceRange, }; acquireToRenderDependency = { .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .pNext = nullptr, .dependencyFlags = 0, .memoryBarrierCount = 0, .pMemoryBarriers = nullptr, .bufferMemoryBarrierCount = 0, .pBufferMemoryBarriers = nullptr, .imageMemoryBarrierCount = 1, .pImageMemoryBarriers = &acquireToRenderBarrier, }; renderToPresentBarrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = nullptr, .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, .srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, .dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, .dstAccessMask = VK_ACCESS_2_NONE, .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .subresourceRange = subresourceRange, }; renderToPresentDependency = { .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .pNext = nullptr, .dependencyFlags = 0, .memoryBarrierCount = 0, .pMemoryBarriers = nullptr, .bufferMemoryBarrierCount = 0, .pBufferMemoryBarriers = nullptr, .imageMemoryBarrierCount = 1, .pImageMemoryBarriers = &renderToPresentBarrier, }; } return true; } void MiscData::destroy( RenderDevice const& renderDevice ) { VkDevice const device = renderDevice.device; 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 ); }