Add Sampler
- Add DescriptorSet and DescriptorPool abstractions to support Samplers
This commit is contained in:
@@ -168,11 +168,13 @@
|
||||
<ClInclude Include="src\Buffer.h" />
|
||||
<ClInclude Include="src\Common.h" />
|
||||
<ClInclude Include="src\DebugMessenger.h" />
|
||||
<ClInclude Include="src\DescriptorSet.h" />
|
||||
<ClInclude Include="src\DescriptorPool.h" />
|
||||
<ClInclude Include="src\FileSystem.h" />
|
||||
<ClInclude Include="src\Framebuffer.h" />
|
||||
<ClInclude Include="src\IndexBuffer.h" />
|
||||
<ClInclude Include="src\Pipeline.h" />
|
||||
<ClInclude Include="src\PipelineCreator.h" />
|
||||
<ClInclude Include="src\Sampler.h" />
|
||||
<ClInclude Include="src\UniformBuffer.h" />
|
||||
<ClInclude Include="src\Instance.h" />
|
||||
<ClInclude Include="src\QueueFamilies.h" />
|
||||
|
||||
@@ -74,7 +74,13 @@
|
||||
<ClInclude Include="src\VertexDescriptor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Framebuffer.h">
|
||||
<ClInclude Include="src\Sampler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\DescriptorSet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\DescriptorPool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
glslc res/shaders/shader.vert -o res/shaders/vert.spv
|
||||
glslc res/shaders/shader.frag -o res/shaders/frag.spv
|
||||
pause
|
||||
Binary file not shown.
@@ -1,8 +1,12 @@
|
||||
#version 450
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D texSampler;
|
||||
|
||||
layout(location = 0) in vec3 fragColor;
|
||||
layout(location = 1) in vec2 fragTexCoord;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(fragColor, 1.0);
|
||||
outColor = vec4(fragColor, 1.0) * texture(texSampler, fragTexCoord);
|
||||
}
|
||||
|
||||
@@ -10,10 +10,13 @@ layout(set = 0, binding = 0) uniform SceneUniformBufferObject
|
||||
|
||||
layout(location = 0) in vec2 inPosition;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
layout(location = 2) in vec2 inTexCoord;
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
layout(location = 1) out vec2 fragTexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPosition.x, 0.0, inPosition.y, 1.0);
|
||||
fragColor = inColor;
|
||||
fragTexCoord = inTexCoord;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 421 KiB |
+3
-15
@@ -36,7 +36,7 @@ public:
|
||||
VkMemoryAllocateInfo allocateInfo{};
|
||||
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocateInfo.allocationSize = memoryRequirements.size;
|
||||
allocateInfo.memoryTypeIndex = FindMemoryType(instance, memoryRequirements.memoryTypeBits, properties);
|
||||
allocateInfo.memoryTypeIndex = instance.FindMemoryType(memoryRequirements.memoryTypeBits, properties);
|
||||
|
||||
CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, &memory), "Failed to allocate buffer memory");
|
||||
|
||||
@@ -85,10 +85,11 @@ public:
|
||||
CopyBuffer(instance, stagingBuffer, *this, offset, size);
|
||||
}
|
||||
|
||||
void Map()
|
||||
void* Map()
|
||||
{
|
||||
CP_ASSERT(mappedData == nullptr, "Mapping an already mapped buffer");
|
||||
vkMapMemory(instance.GetDevice(), memory, 0, size * count, 0, &mappedData);
|
||||
return mappedData;
|
||||
}
|
||||
|
||||
void Unmap()
|
||||
@@ -166,17 +167,4 @@ public:
|
||||
|
||||
vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), 1, &commandBuffer);
|
||||
}
|
||||
|
||||
private:
|
||||
static uint32_t FindMemoryType(Instance& instance, uint32_t typeFilter, VkMemoryPropertyFlags properties)
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(instance.GetPhysicalDevice(), &memoryProperties);
|
||||
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i)
|
||||
{
|
||||
if ((typeFilter & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
return i;
|
||||
}
|
||||
throw std::runtime_error("Failed to find suitable memory type");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "Instance.h"
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
class DescriptorPool final
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorPool);
|
||||
private:
|
||||
Instance& instance;
|
||||
|
||||
VkDescriptorPool descriptorPool;
|
||||
static const int DESCRIPTOR_SET_COUNT = 100;
|
||||
public:
|
||||
DescriptorPool(Instance& instance)
|
||||
: instance{instance}
|
||||
{
|
||||
std::vector<VkDescriptorPoolSize> poolSizes{2};
|
||||
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
poolSizes[0].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
|
||||
|
||||
poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
poolSizes[1].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
|
||||
|
||||
VkDescriptorPoolCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
createInfo.poolSizeCount = poolSizes.size();
|
||||
createInfo.pPoolSizes = poolSizes.data();
|
||||
createInfo.maxSets = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight();
|
||||
|
||||
CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "Failed to initialize descriptor pool");
|
||||
}
|
||||
|
||||
~DescriptorPool()
|
||||
{
|
||||
vkDestroyDescriptorPool(instance.GetDevice(), descriptorPool, nullptr);
|
||||
}
|
||||
|
||||
std::vector<VkDescriptorSet> AllocateDescriptorSets(VkDescriptorSetLayout descriptorSetLayout)
|
||||
{
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
std::vector<VkDescriptorSetLayout> layouts{static_cast<size_t>(instance.GetMaxFramesInFlight()), descriptorSetLayout};
|
||||
VkDescriptorSetAllocateInfo allocateInfo{};
|
||||
allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocateInfo.descriptorPool = descriptorPool;
|
||||
allocateInfo.descriptorSetCount = instance.GetMaxFramesInFlight();
|
||||
allocateInfo.pSetLayouts = layouts.data();
|
||||
|
||||
descriptorSets.resize(instance.GetMaxFramesInFlight());
|
||||
CP_VK_ASSERT(vkAllocateDescriptorSets(instance.GetDevice(), &allocateInfo, descriptorSets.data()), "Failed to allocate descriptor sets");
|
||||
|
||||
return descriptorSets;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "DescriptorPool.h"
|
||||
#include "Sampler.h"
|
||||
#include "UniformBuffer.h"
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
class DescriptorSet
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorSet);
|
||||
private:
|
||||
Instance& instance;
|
||||
DescriptorPool& descriptorPool;
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
|
||||
public:
|
||||
DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout)
|
||||
: instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout}
|
||||
{
|
||||
descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout);
|
||||
}
|
||||
|
||||
void AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding)
|
||||
{
|
||||
for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
|
||||
VkDescriptorBufferInfo bufferInfo = uniformBuffer.GetDescriptorBufferInfo(i);
|
||||
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSets[i];
|
||||
descriptorWrite.dstBinding = binding;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
descriptorWrite.pBufferInfo = &bufferInfo;
|
||||
descriptorWrite.pImageInfo = nullptr;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void AddSampler(const Sampler& sampler, uint32_t binding)
|
||||
{
|
||||
VkDescriptorImageInfo imageInfo = sampler.GetDescriptorImageInfo();
|
||||
for (auto&& descriptorSet : descriptorSets) {
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSet;
|
||||
descriptorWrite.dstBinding = binding;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
descriptorWrite.pBufferInfo = nullptr;
|
||||
descriptorWrite.pImageInfo = &imageInfo;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
VkDescriptorSet GetHandle() const
|
||||
{
|
||||
return descriptorSets[instance.GetFlightIndex()];
|
||||
}
|
||||
};
|
||||
+15
-1
@@ -157,6 +157,19 @@ public:
|
||||
return *swapChain;
|
||||
}
|
||||
|
||||
// TODO: Create Device class and move this there
|
||||
uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
|
||||
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i)
|
||||
{
|
||||
if ((typeFilter & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
return i;
|
||||
}
|
||||
throw std::runtime_error("Failed to find suitable memory type");
|
||||
}
|
||||
|
||||
private:
|
||||
void InitializeWindow(const std::string& applicationName)
|
||||
{
|
||||
@@ -277,6 +290,7 @@ private:
|
||||
std::vector<const char*> deviceExtensions = GetRequiredDeviceExtensions();
|
||||
VkPhysicalDeviceFeatures deviceFeatures{};
|
||||
deviceFeatures.fillModeNonSolid = VK_TRUE;
|
||||
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||
VkDeviceCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
createInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||
@@ -380,7 +394,7 @@ private:
|
||||
|
||||
VkPhysicalDeviceFeatures deviceFeatures;
|
||||
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
|
||||
if (!deviceFeatures.fillModeNonSolid)
|
||||
if (!deviceFeatures.fillModeNonSolid || !deviceFeatures.samplerAnisotropy)
|
||||
return false;
|
||||
|
||||
QueueFamiliesQuery query{surface, device};
|
||||
|
||||
+29
-53
@@ -15,8 +15,7 @@ class Pipeline
|
||||
private:
|
||||
Instance& instance;
|
||||
|
||||
VkDescriptorSetLayout vertexDescriptorSetLayout;
|
||||
VkDescriptorSetLayout fragmentDescriptorSetLayout;
|
||||
std::vector<VkDescriptorSetLayout> descriptorSetLayouts{};
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkPipeline graphicsPipeline;
|
||||
|
||||
@@ -24,7 +23,7 @@ public:
|
||||
Pipeline(Instance& instance, PipelineCreator creator)
|
||||
: instance{instance}
|
||||
{
|
||||
InitializeDescriptorSetLayouts(creator);
|
||||
InitializeDescriptorSetLayout(creator);
|
||||
InitializePipeline(creator);
|
||||
}
|
||||
|
||||
@@ -32,8 +31,10 @@ public:
|
||||
{
|
||||
vkDestroyPipeline(instance.GetDevice(), graphicsPipeline, nullptr);
|
||||
vkDestroyPipelineLayout(instance.GetDevice(), pipelineLayout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(instance.GetDevice(), vertexDescriptorSetLayout, nullptr);
|
||||
vkDestroyDescriptorSetLayout(instance.GetDevice(), fragmentDescriptorSetLayout, nullptr);
|
||||
for (auto&& descriptorSetLayout : descriptorSetLayouts)
|
||||
{
|
||||
vkDestroyDescriptorSetLayout(instance.GetDevice(), descriptorSetLayout, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Bind(VkCommandBuffer commandBuffer)
|
||||
@@ -59,21 +60,32 @@ public:
|
||||
return pipelineLayout;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout GetVertexDescriptorSetLayout()
|
||||
VkDescriptorSetLayout GetDescriptorSetLayout(uint32_t setIndex) const
|
||||
{
|
||||
return vertexDescriptorSetLayout;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout GetFragmentDescriptorSetLayout()
|
||||
{
|
||||
return fragmentDescriptorSetLayout;
|
||||
return descriptorSetLayouts[setIndex];
|
||||
}
|
||||
|
||||
private:
|
||||
void InitializeDescriptorSetLayouts(const PipelineCreator& creator)
|
||||
void InitializeDescriptorSetLayout(const PipelineCreator& creator)
|
||||
{
|
||||
vertexDescriptorSetLayout = InitializeDescriptorSetLayouts(creator.vertexDescriptorSetLayouts, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
fragmentDescriptorSetLayout = InitializeDescriptorSetLayouts(creator.fragmentDescriptorSetLayouts, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
descriptorSetLayouts.resize(creator.descriptorSetLayouts.size());
|
||||
int i = 0;
|
||||
for (auto&& binding : creator.descriptorSetLayouts)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding layoutBinding{};
|
||||
layoutBinding.binding = 0;
|
||||
layoutBinding.descriptorType = binding.second.type;
|
||||
layoutBinding.descriptorCount = 1;
|
||||
layoutBinding.stageFlags = binding.second.flags;
|
||||
layoutBinding.pImmutableSamplers = nullptr;
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
createInfo.bindingCount = 1;
|
||||
createInfo.pBindings = &layoutBinding;
|
||||
|
||||
CP_VK_ASSERT(vkCreateDescriptorSetLayout(instance.GetDevice(), &createInfo, nullptr, &descriptorSetLayouts[i++]), "Failed to initialize descriptor set layout");
|
||||
}
|
||||
}
|
||||
|
||||
void InitializePipeline(const PipelineCreator& creator)
|
||||
@@ -185,13 +197,10 @@ private:
|
||||
colorBlendCreateInfo.blendConstants[2] = 0.0f;
|
||||
colorBlendCreateInfo.blendConstants[3] = 0.0f;
|
||||
|
||||
std::vector<VkDescriptorSetLayout> layouts{};
|
||||
if (vertexDescriptorSetLayout != VK_NULL_HANDLE) layouts.emplace_back(vertexDescriptorSetLayout);
|
||||
if (fragmentDescriptorSetLayout != VK_NULL_HANDLE) layouts.emplace_back(fragmentDescriptorSetLayout );
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{};
|
||||
pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutCreateInfo.setLayoutCount = layouts.size();
|
||||
pipelineLayoutCreateInfo.pSetLayouts = layouts.data();
|
||||
pipelineLayoutCreateInfo.setLayoutCount = descriptorSetLayouts.size();
|
||||
pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts.data();
|
||||
pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
|
||||
pipelineLayoutCreateInfo.pPushConstantRanges = nullptr;
|
||||
|
||||
@@ -234,37 +243,4 @@ private:
|
||||
return shaderModule;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout InitializeDescriptorSetLayouts(const std::set<uint32_t>& bindings, VkShaderStageFlags flags)
|
||||
{
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings{bindings.size()};
|
||||
|
||||
int i = 0;
|
||||
for (auto&& binding : bindings)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding layoutBinding{};
|
||||
layoutBinding.binding = binding;
|
||||
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
layoutBinding.descriptorCount = 1;
|
||||
layoutBinding.stageFlags = flags;
|
||||
layoutBinding.pImmutableSamplers = nullptr;
|
||||
descriptorSetLayoutBindings[i++] = layoutBinding;
|
||||
}
|
||||
|
||||
if (!descriptorSetLayoutBindings.empty())
|
||||
{
|
||||
VkDescriptorSetLayoutCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
createInfo.bindingCount = descriptorSetLayoutBindings.size();
|
||||
createInfo.pBindings = descriptorSetLayoutBindings.data();
|
||||
|
||||
CP_VK_ASSERT(vkCreateDescriptorSetLayout(instance.GetDevice(), &createInfo, nullptr, &descriptorSetLayout), "Failed to initialize descriptor set layout");
|
||||
|
||||
return descriptorSetLayout;
|
||||
}
|
||||
else
|
||||
{
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -6,10 +6,14 @@
|
||||
|
||||
class PipelineCreator
|
||||
{
|
||||
struct DescriptorSetLayout
|
||||
{
|
||||
VkDescriptorType type;
|
||||
VkShaderStageFlags flags;
|
||||
};
|
||||
friend class Pipeline;
|
||||
private:
|
||||
std::set<uint32_t> vertexDescriptorSetLayouts{};
|
||||
std::set<uint32_t> fragmentDescriptorSetLayouts{};
|
||||
std::map<uint32_t, DescriptorSetLayout> descriptorSetLayouts{};
|
||||
|
||||
std::string vertexShader;
|
||||
std::string fragmentShader;
|
||||
@@ -29,15 +33,9 @@ public:
|
||||
vertexDescriptor = descriptor;
|
||||
}
|
||||
|
||||
void AddVertexDescriptorSetLayoutBinding(uint32_t binding)
|
||||
void AddDescriptorSetLayoutBinding(uint32_t set, VkDescriptorType type, VkShaderStageFlags stageFlags)
|
||||
{
|
||||
CP_ASSERT(binding == 0, "Currently only support uniforms with binding = 0");
|
||||
vertexDescriptorSetLayouts.emplace(binding);
|
||||
}
|
||||
|
||||
void AddFragmentDescriptorSetLayoutBinding(uint32_t binding)
|
||||
{
|
||||
fragmentDescriptorSetLayouts.emplace(binding);
|
||||
descriptorSetLayouts.emplace(set, DescriptorSetLayout{type, stageFlags});
|
||||
}
|
||||
|
||||
void SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "Instance.h"
|
||||
#include "Pipeline.h"
|
||||
|
||||
class Sampler
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(Sampler);
|
||||
private:
|
||||
Instance& instance;
|
||||
VkImageView imageView;
|
||||
|
||||
VkSampler textureSampler;
|
||||
public:
|
||||
Sampler(Instance& instance, VkImageView imageView)
|
||||
: instance{instance}, imageView{imageView}
|
||||
{
|
||||
InitializeSampler(imageView);
|
||||
}
|
||||
|
||||
~Sampler()
|
||||
{
|
||||
vkDestroySampler(instance.GetDevice(), textureSampler, nullptr);
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo GetDescriptorImageInfo() const
|
||||
{
|
||||
VkDescriptorImageInfo imageInfo{};
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
imageInfo.imageView = imageView;
|
||||
imageInfo.sampler = textureSampler;
|
||||
|
||||
return imageInfo;
|
||||
}
|
||||
private:
|
||||
void InitializeSampler(VkImageView imageView)
|
||||
{
|
||||
VkPhysicalDeviceProperties properties{};
|
||||
vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties);
|
||||
|
||||
VkSamplerCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
createInfo.magFilter = VK_FILTER_LINEAR;
|
||||
createInfo.minFilter = VK_FILTER_LINEAR;
|
||||
createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
createInfo.anisotropyEnable = VK_TRUE;
|
||||
createInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
|
||||
createInfo.unnormalizedCoordinates = VK_FALSE;
|
||||
createInfo.compareEnable = VK_FALSE;
|
||||
createInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
createInfo.mipLodBias = 0.0f;
|
||||
createInfo.minLod = 0.0f;
|
||||
createInfo.maxLod = 0.0f;
|
||||
|
||||
CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &textureSampler), "Failed to initialize texture sampler");
|
||||
}
|
||||
};
|
||||
@@ -5,84 +5,28 @@
|
||||
#include "Pipeline.h"
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
template <typename T>
|
||||
class UniformBuffer : public Buffer
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(UniformBuffer);
|
||||
private:
|
||||
Pipeline& pipeline;
|
||||
|
||||
VkDescriptorPool descriptorPool;
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
|
||||
public:
|
||||
UniformBuffer(Instance& instance, Pipeline& pipeline, uint32_t binding, VkDescriptorSetLayout layout)
|
||||
: Buffer{instance, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, sizeof(T), instance.GetMaxFramesInFlight()}, pipeline{pipeline}
|
||||
{
|
||||
InitializeDescriptorPool();
|
||||
InitializeDescriptorSet(binding, layout);
|
||||
}
|
||||
|
||||
~UniformBuffer() override
|
||||
{
|
||||
vkDestroyDescriptorPool(instance.GetDevice(), descriptorPool, nullptr);
|
||||
}
|
||||
UniformBuffer(Instance& instance, VkDeviceSize size)
|
||||
: Buffer{instance, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size, instance.GetMaxFramesInFlight()}
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
void Update(const T& t)
|
||||
{
|
||||
CP_ASSERT(sizeof(T) == Buffer::GetSize(), "Template size is not the same as buffer size %u != %u", sizeof(T), Buffer::GetSize());
|
||||
Buffer::Update((void*)&t, instance.GetFlightIndex());
|
||||
}
|
||||
|
||||
void Bind(VkCommandBuffer commandBuffer) const
|
||||
{
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetPipelineLayout(), 0, 1, &descriptorSets[instance.GetFlightIndex()], 0, nullptr);
|
||||
// vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetPipelineLayout(), 0, 1, &descriptorSets[instance.GetFlightIndex()], 0, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
void InitializeDescriptorPool()
|
||||
{
|
||||
VkDescriptorPoolSize poolSize{};
|
||||
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
poolSize.descriptorCount = instance.GetMaxFramesInFlight();
|
||||
|
||||
VkDescriptorPoolCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
createInfo.poolSizeCount = 1;
|
||||
createInfo.pPoolSizes = &poolSize;
|
||||
createInfo.maxSets = instance.GetMaxFramesInFlight();
|
||||
|
||||
CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "Failed to initialize descriptor pool");
|
||||
}
|
||||
|
||||
void InitializeDescriptorSet(uint32_t binding, VkDescriptorSetLayout layout)
|
||||
{
|
||||
std::vector<VkDescriptorSetLayout> layouts{static_cast<size_t>(instance.GetMaxFramesInFlight()), layout};
|
||||
VkDescriptorSetAllocateInfo allocateInfo{};
|
||||
allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocateInfo.descriptorPool = descriptorPool;
|
||||
allocateInfo.descriptorSetCount = instance.GetMaxFramesInFlight();
|
||||
allocateInfo.pSetLayouts = layouts.data();
|
||||
|
||||
descriptorSets.resize(instance.GetMaxFramesInFlight());
|
||||
CP_VK_ASSERT(vkAllocateDescriptorSets(instance.GetDevice(), &allocateInfo, descriptorSets.data()), "Failed to allocate descriptor sets");
|
||||
for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
|
||||
VkDescriptorBufferInfo bufferInfo = GetDescriptorBufferInfo(i);
|
||||
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSets[i];
|
||||
descriptorWrite.dstBinding = binding;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
descriptorWrite.pBufferInfo = &bufferInfo;
|
||||
descriptorWrite.pImageInfo = nullptr;
|
||||
descriptorWrite.pTexelBufferView = nullptr;
|
||||
vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
VkDescriptorBufferInfo GetDescriptorBufferInfo(int index)
|
||||
VkDescriptorBufferInfo GetDescriptorBufferInfo(int index) const
|
||||
{
|
||||
VkDescriptorBufferInfo bufferInfo{};
|
||||
bufferInfo.buffer = handle;
|
||||
|
||||
+2
-28
@@ -7,41 +7,15 @@
|
||||
struct Vertex {
|
||||
glm::vec2 pos;
|
||||
glm::vec3 color;
|
||||
glm::vec2 texCoord;
|
||||
|
||||
static VertexDescriptor GetDescriptor()
|
||||
{
|
||||
VertexDescriptor descriptor{};
|
||||
descriptor.AddAttribute<Vertex>(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, pos));
|
||||
descriptor.AddAttribute<Vertex>(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color));
|
||||
descriptor.AddAttribute<Vertex>(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoord));
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
static VkVertexInputBindingDescription GetBindingDescription()
|
||||
{
|
||||
VkVertexInputBindingDescription description{};
|
||||
|
||||
description.binding = 0;
|
||||
description.stride = sizeof(Vertex);
|
||||
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
static std::vector<VkVertexInputAttributeDescription> GetAttributeDescriptions()
|
||||
{
|
||||
std::vector<VkVertexInputAttributeDescription> descriptions{2};
|
||||
|
||||
descriptions[0].binding = 0;
|
||||
descriptions[0].location = 0;
|
||||
descriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
|
||||
descriptions[0].offset = offsetof(Vertex, pos);
|
||||
|
||||
descriptions[1].binding = 0;
|
||||
descriptions[1].location = 1;
|
||||
descriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
descriptions[1].offset = offsetof(Vertex, color);
|
||||
|
||||
return descriptions;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+223
-21
@@ -5,8 +5,11 @@
|
||||
#include "Instance.h"
|
||||
#include "Timer.h"
|
||||
#include "UniformBuffer.h"
|
||||
#include "Sampler.h"
|
||||
#include "Vertex.h"
|
||||
#include "Pipeline.h"
|
||||
#include "DescriptorPool.h"
|
||||
#include "DescriptorSet.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <iostream>
|
||||
@@ -14,29 +17,16 @@
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <glm/glm.hpp>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb/stb_image.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <chrono>
|
||||
|
||||
const std::vector<Vertex> vertices = {
|
||||
Vertex{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
Vertex{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
Vertex{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||
Vertex{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}}
|
||||
};
|
||||
|
||||
const std::vector<glm::vec2> positions = {
|
||||
{-0.5f, -0.5f},
|
||||
{0.5f, -0.5f},
|
||||
{0.5f, 0.5f},
|
||||
{-0.5f, 0.5f}
|
||||
};
|
||||
|
||||
const std::vector<glm::vec3> colors = {
|
||||
glm::vec3{1.0f, 0.0f, 0.0f},
|
||||
glm::vec3{0.0f, 1.0f, 0.0f},
|
||||
glm::vec3{0.0f, 0.0f, 1.0f},
|
||||
glm::vec3{1.0f, 1.0f, 1.0f}
|
||||
Vertex{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
|
||||
Vertex{{ 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
|
||||
Vertex{{ 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
|
||||
Vertex{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}
|
||||
};
|
||||
|
||||
const std::vector<uint16_t> indices = {
|
||||
@@ -58,15 +48,27 @@ private:
|
||||
std::unique_ptr<Pipeline> graphicsPipeline;
|
||||
std::unique_ptr<VertexBuffer> vertexBuffer;
|
||||
std::unique_ptr<IndexBuffer> indexBuffer;
|
||||
std::unique_ptr<UniformBuffer<ShaderUniform>> shaderUniformBuffer;
|
||||
std::unique_ptr<UniformBuffer> shaderUniformBuffer;
|
||||
std::unique_ptr<Sampler> sampler;
|
||||
std::unique_ptr<DescriptorPool> descriptorPool;
|
||||
std::unique_ptr<DescriptorSet> uniformDescriptorSet;
|
||||
std::unique_ptr<DescriptorSet> samplerDescriptorSet;
|
||||
std::vector<VkCommandBuffer> commandBuffers;
|
||||
|
||||
VkImage textureImage;
|
||||
VkDeviceMemory textureImageMemory;
|
||||
VkImageView textureImageView;
|
||||
|
||||
public:
|
||||
Application()
|
||||
{
|
||||
InitializeInstance();
|
||||
InitializeGraphicsPipeline();
|
||||
InitializeTextureImage();
|
||||
InitializeTextureImageView();
|
||||
InitializeTextureSampler();
|
||||
InitializeUniformBuffer();
|
||||
InitializeDescriptorSets();
|
||||
InitializeVertexBuffer();
|
||||
InitializeIndexBuffer();
|
||||
InitializeCommandBuffers();
|
||||
@@ -75,6 +77,9 @@ public:
|
||||
~Application()
|
||||
{
|
||||
vkDeviceWaitIdle(instance->GetDevice());
|
||||
vkDestroyImage(instance->GetDevice(), textureImage, nullptr);
|
||||
vkFreeMemory(instance->GetDevice(), textureImageMemory, nullptr);
|
||||
vkDestroyImageView(instance->GetDevice(), textureImageView, nullptr);
|
||||
}
|
||||
|
||||
Application(Application&&) = delete;
|
||||
@@ -100,15 +105,207 @@ private:
|
||||
instance = std::make_unique<Instance>("Vulkan Tutorial");
|
||||
}
|
||||
|
||||
void InitializeTextureImage()
|
||||
{
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
int texChannels;
|
||||
stbi_uc* pixels = stbi_load("res/textures/texture.png", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
|
||||
|
||||
CP_ASSERT(pixels, "Failed to load texture image");
|
||||
|
||||
VkDeviceSize bufferSize = texWidth * texHeight * 4;
|
||||
Buffer stagingBuffer{*instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
|
||||
void* data = stagingBuffer.Map();
|
||||
memcpy(data, pixels, bufferSize);
|
||||
stagingBuffer.Unmap();
|
||||
stbi_image_free(pixels);
|
||||
|
||||
VkImageCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
createInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
createInfo.extent.width = texWidth;
|
||||
createInfo.extent.height = texHeight;
|
||||
createInfo.extent.depth = 1;
|
||||
createInfo.mipLevels = 1;
|
||||
createInfo.arrayLayers = 1;
|
||||
createInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
createInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
createInfo.flags = 0;
|
||||
|
||||
CP_VK_ASSERT(vkCreateImage(instance->GetDevice(), &createInfo, nullptr, &textureImage), "Failed to initialize texture image");
|
||||
|
||||
VkMemoryRequirements memoryRequirements;
|
||||
vkGetImageMemoryRequirements(instance->GetDevice(), textureImage, &memoryRequirements);
|
||||
|
||||
VkMemoryAllocateInfo allocateInfo{};
|
||||
allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocateInfo.allocationSize = memoryRequirements.size;
|
||||
allocateInfo.memoryTypeIndex = instance->FindMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
|
||||
CP_VK_ASSERT(vkAllocateMemory(instance->GetDevice(), &allocateInfo, nullptr, &textureImageMemory), "Failed to initiallizse texture image memory");
|
||||
|
||||
vkBindImageMemory(instance->GetDevice(), textureImage, textureImageMemory, 0);
|
||||
|
||||
TransitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
CopyBufferToImage(stagingBuffer, textureImage, texWidth, texHeight);
|
||||
TransitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
void InitializeTextureImageView()
|
||||
{
|
||||
textureImageView = CreateImageView();
|
||||
}
|
||||
|
||||
void InitializeTextureSampler()
|
||||
{
|
||||
sampler = std::make_unique<Sampler>(*instance, textureImageView);
|
||||
}
|
||||
|
||||
VkImageView CreateImageView()
|
||||
{
|
||||
VkImageView imageView;
|
||||
VkImageViewCreateInfo createInfo{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
createInfo.image = textureImage;
|
||||
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
createInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
createInfo.subresourceRange.baseMipLevel = 0;
|
||||
createInfo.subresourceRange.levelCount = 1;
|
||||
createInfo.subresourceRange.baseArrayLayer = 0;
|
||||
createInfo.subresourceRange.layerCount = 1;
|
||||
CP_VK_ASSERT(vkCreateImageView(instance->GetDevice(), &createInfo, nullptr, &imageView), "Failed to initialize ImageView");
|
||||
|
||||
return imageView;
|
||||
}
|
||||
|
||||
void TransitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout)
|
||||
{
|
||||
VkCommandBuffer commandBuffer = BeginSingleUseCommandBuffer();
|
||||
|
||||
VkImageMemoryBarrier barrier{};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.oldLayout = oldLayout;
|
||||
barrier.newLayout = newLayout;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.baseMipLevel = 0;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = 0;
|
||||
|
||||
VkPipelineStageFlags srcStage;
|
||||
VkPipelineStageFlags dstStage;
|
||||
|
||||
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
} else {
|
||||
throw std::invalid_argument("Unsupported layout transition");
|
||||
}
|
||||
|
||||
vkCmdPipelineBarrier(commandBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
|
||||
EndSinglelUseCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
void CopyBufferToImage(const Buffer& buffer, VkImage image, uint32_t width, uint32_t height)
|
||||
{
|
||||
|
||||
VkCommandBuffer commandBuffer = BeginSingleUseCommandBuffer();
|
||||
|
||||
VkBufferImageCopy region{};
|
||||
region.bufferOffset = 0;
|
||||
region.bufferRowLength = 0;
|
||||
region.bufferImageHeight = 0;
|
||||
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
|
||||
region.imageOffset = {0, 0, 0};
|
||||
region.imageExtent = {width, height, 1};
|
||||
|
||||
vkCmdCopyBufferToImage(commandBuffer, buffer.GetHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
EndSinglelUseCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
VkCommandBuffer BeginSingleUseCommandBuffer()
|
||||
{
|
||||
VkCommandBufferAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
allocInfo.commandPool = instance->GetCommandPool();
|
||||
allocInfo.commandBufferCount = 1;
|
||||
|
||||
VkCommandBuffer commandBuffer;
|
||||
vkAllocateCommandBuffers(instance->GetDevice(), &allocInfo, &commandBuffer);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
|
||||
vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
||||
return commandBuffer;
|
||||
}
|
||||
|
||||
void EndSinglelUseCommandBuffer(VkCommandBuffer commandBuffer)
|
||||
{
|
||||
vkEndCommandBuffer(commandBuffer);
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &commandBuffer;
|
||||
|
||||
vkQueueSubmit(instance->GetGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(instance->GetGraphicsQueue());
|
||||
|
||||
vkFreeCommandBuffers(instance->GetDevice(), instance->GetCommandPool(), 1, &commandBuffer);
|
||||
|
||||
}
|
||||
|
||||
void InitializeUniformBuffer()
|
||||
{
|
||||
shaderUniformBuffer = std::make_unique<UniformBuffer<ShaderUniform>>(*instance, *graphicsPipeline, 0, graphicsPipeline->GetVertexDescriptorSetLayout());
|
||||
shaderUniformBuffer = std::make_unique<UniformBuffer>(*instance, sizeof(ShaderUniform));
|
||||
}
|
||||
|
||||
void InitializeDescriptorSets()
|
||||
{
|
||||
descriptorPool = std::make_unique<DescriptorPool>(*instance);
|
||||
|
||||
uniformDescriptorSet = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
|
||||
uniformDescriptorSet->AddUniform(*shaderUniformBuffer, 0);
|
||||
|
||||
samplerDescriptorSet = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(1));
|
||||
samplerDescriptorSet->AddSampler(*sampler, 0);
|
||||
}
|
||||
|
||||
void InitializeGraphicsPipeline()
|
||||
{
|
||||
PipelineCreator creator{"res/shaders/vert.spv", "res/shaders/frag.spv"};
|
||||
creator.AddVertexDescriptorSetLayoutBinding(0);
|
||||
creator.AddDescriptorSetLayoutBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
creator.AddDescriptorSetLayoutBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
creator.SetVertexDescriptor(Vertex::GetDescriptor());
|
||||
creator.SetCullMode(VK_CULL_MODE_NONE);
|
||||
graphicsPipeline = std::make_unique<Pipeline>(*instance, creator);
|
||||
@@ -171,6 +368,11 @@ private:
|
||||
indexBuffer->Bind(commandBuffer);
|
||||
shaderUniformBuffer->Bind(commandBuffer);
|
||||
|
||||
std::vector<VkDescriptorSet> sets{uniformDescriptorSet->GetHandle(), samplerDescriptorSet->GetHandle()};
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline->GetPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr);
|
||||
// Replace the two lines above with this somehow:
|
||||
// graphicsPipeline->BindDescriptorSets(uniformDescriptorSet, samplerDescriptorSet);
|
||||
|
||||
indexBuffer->Draw(commandBuffer);
|
||||
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
||||
Reference in New Issue
Block a user