mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
Get descriptor sets working
This commit is contained in:
parent
2bb75f4683
commit
bbf582d85f
@ -7,6 +7,14 @@
|
|||||||
|
|
||||||
namespace engine::gfx {
|
namespace engine::gfx {
|
||||||
|
|
||||||
|
// handles (incomplete types)
|
||||||
|
struct Pipeline;
|
||||||
|
struct Buffer;
|
||||||
|
struct Texture;
|
||||||
|
struct DrawBuffer;
|
||||||
|
struct DescriptorSetLayout;
|
||||||
|
struct DescriptorSet;
|
||||||
|
|
||||||
enum class MSAALevel {
|
enum class MSAALevel {
|
||||||
MSAA_OFF,
|
MSAA_OFF,
|
||||||
MSAA_2X,
|
MSAA_2X,
|
||||||
@ -86,10 +94,13 @@ namespace engine::gfx {
|
|||||||
std::vector<VertexAttribDescription> attributeDescriptions;
|
std::vector<VertexAttribDescription> attributeDescriptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
// handles (incomplete types)
|
struct PipelineInfo {
|
||||||
struct Pipeline;
|
const char* vertShaderPath;
|
||||||
struct Buffer;
|
const char* fragShaderPath;
|
||||||
struct Texture;
|
gfx::VertexFormat vertexFormat;
|
||||||
struct DrawBuffer;
|
bool alphaBlending;
|
||||||
|
bool backfaceCulling;
|
||||||
|
std::vector<const DescriptorSetLayout*> descriptorSetLayouts;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,21 @@ namespace engine {
|
|||||||
void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer);
|
void cmdBindVertexBuffer(gfx::DrawBuffer* drawBuffer, uint32_t binding, const gfx::Buffer* buffer);
|
||||||
void cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer);
|
void cmdBindIndexBuffer(gfx::DrawBuffer* drawBuffer, const gfx::Buffer* buffer);
|
||||||
void cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
|
void cmdDrawIndexed(gfx::DrawBuffer* drawBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
|
||||||
//void cmdBindDescriptorSetTexture(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture);
|
void cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber);
|
||||||
//void cmdBindDescriptorSetBuffer(gfx::CommandBuffer* commandBuffer, uint32_t set, uint32_t binding, const gfx::Texture* texture);
|
|
||||||
|
|
||||||
// creates the equivalent of an OpenGL shader program & vertex attrib configuration
|
// creates the equivalent of an OpenGL shader program & vertex attrib configuration
|
||||||
gfx::Pipeline* createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling);
|
gfx::Pipeline* createPipeline(const gfx::PipelineInfo& info);
|
||||||
void destroyPipeline(const gfx::Pipeline* pipeline);
|
void destroyPipeline(const gfx::Pipeline* pipeline);
|
||||||
|
|
||||||
|
gfx::DescriptorSetLayout* createDescriptorSetLayout();
|
||||||
|
void destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout);
|
||||||
|
|
||||||
|
gfx::DescriptorSet* allocateDescriptorSet(const gfx::DescriptorSetLayout* layout);
|
||||||
|
void updateDescriptor(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Buffer* buffer);
|
||||||
|
|
||||||
void updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset);
|
void updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset);
|
||||||
|
|
||||||
|
// Tries to create it on the GPU. Cannot be directly updated by the CPU.
|
||||||
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
|
gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data);
|
||||||
void destroyBuffer(const gfx::Buffer* buffer);
|
void destroyBuffer(const gfx::Buffer* buffer);
|
||||||
|
|
||||||
|
@ -27,8 +27,13 @@ public:
|
|||||||
|
|
||||||
const gfx::Pipeline* getPipeline();
|
const gfx::Pipeline* getPipeline();
|
||||||
|
|
||||||
|
const gfx::DescriptorSet* getSetZero() { return m_setZero; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GFXDevice* const m_gfx;
|
GFXDevice* const m_gfx;
|
||||||
|
const gfx::DescriptorSetLayout* m_setZeroLayout;
|
||||||
|
const gfx::DescriptorSet* m_setZero;
|
||||||
|
const gfx::Buffer* m_setZeroBuffer;
|
||||||
const gfx::Pipeline* m_pipeline;
|
const gfx::Pipeline* m_pipeline;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 fragUV;
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
layout(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outColor = vec4(0.0, 0.0, 1.0, 1.0);
|
vec3 baseColor = vec3(fragUV, 0.0);
|
||||||
|
outColor = vec4(baseColor, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
|
layout(location = 2) in vec2 inUV;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 fragUV;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform MyUniform {
|
||||||
|
vec4 someValue;
|
||||||
|
} myUniform;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = vec4(inPosition, 1.0);
|
gl_Position = vec4(inPosition, 1.0);
|
||||||
|
fragUV = inUV * myUniform.someValue.xy;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ namespace engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// handles
|
// handles
|
||||||
|
|
||||||
struct gfx::Buffer {
|
struct gfx::Buffer {
|
||||||
gfx::BufferType type;
|
gfx::BufferType type;
|
||||||
VkBuffer buffer = VK_NULL_HANDLE;
|
VkBuffer buffer = VK_NULL_HANDLE;
|
||||||
@ -83,6 +83,14 @@ namespace engine {
|
|||||||
uint32_t imageIndex; // for swapchain present
|
uint32_t imageIndex; // for swapchain present
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gfx::DescriptorSetLayout {
|
||||||
|
VkDescriptorSetLayout layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gfx::DescriptorSet {
|
||||||
|
VkDescriptorSet set;
|
||||||
|
};
|
||||||
|
|
||||||
// enum converters
|
// enum converters
|
||||||
|
|
||||||
namespace vkinternal {
|
namespace vkinternal {
|
||||||
@ -107,6 +115,8 @@ namespace engine {
|
|||||||
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
case gfx::BufferType::INDEX:
|
case gfx::BufferType::INDEX:
|
||||||
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||||
|
case gfx::BufferType::UNIFORM:
|
||||||
|
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("This buffer type does not have usage bits");
|
throw std::runtime_error("This buffer type does not have usage bits");
|
||||||
}
|
}
|
||||||
@ -170,7 +180,7 @@ namespace engine {
|
|||||||
throw std::runtime_error("PREPROCESS ERR " + preprocessed.GetErrorMessage());
|
throw std::runtime_error("PREPROCESS ERR " + preprocessed.GetErrorMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string shaderStr{preprocessed.cbegin(), preprocessed.cend()};
|
std::string shaderStr{ preprocessed.cbegin(), preprocessed.cend() };
|
||||||
|
|
||||||
// compile
|
// compile
|
||||||
shaderc::SpvCompilationResult compiledShader = compiler.CompileGlslToSpv(shaderStr.c_str(), kind, filename, options);
|
shaderc::SpvCompilationResult compiledShader = compiler.CompileGlslToSpv(shaderStr.c_str(), kind, filename, options);
|
||||||
@ -363,7 +373,7 @@ namespace engine {
|
|||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -529,7 +539,7 @@ namespace engine {
|
|||||||
// class definitions
|
// class definitions
|
||||||
|
|
||||||
struct GFXDevice::Impl {
|
struct GFXDevice::Impl {
|
||||||
|
|
||||||
// device settings
|
// device settings
|
||||||
gfx::GraphicsSettings graphicsSettings;
|
gfx::GraphicsSettings graphicsSettings;
|
||||||
|
|
||||||
@ -540,13 +550,15 @@ namespace engine {
|
|||||||
VmaAllocator allocator{};
|
VmaAllocator allocator{};
|
||||||
SwapchainInfo swapchainInfo{};
|
SwapchainInfo swapchainInfo{};
|
||||||
Swapchain swapchain{};
|
Swapchain swapchain{};
|
||||||
|
|
||||||
|
VkDescriptorPool descriptorPool;
|
||||||
|
|
||||||
uint64_t FRAMECOUNT = 0;
|
uint64_t FRAMECOUNT = 0;
|
||||||
|
|
||||||
FrameData frameData[FRAMES_IN_FLIGHT] = {};
|
FrameData frameData[FRAMES_IN_FLIGHT] = {};
|
||||||
|
|
||||||
bool swapchainIsOutOfDate = false;
|
bool swapchainIsOutOfDate = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* window, gfx::GraphicsSettings settings)
|
GFXDevice::GFXDevice(const char* appName, const char* appVersion, SDL_Window* window, gfx::GraphicsSettings settings)
|
||||||
@ -600,7 +612,7 @@ namespace engine {
|
|||||||
pimpl->swapchainInfo.waitForPresent = pimpl->graphicsSettings.waitForPresent;
|
pimpl->swapchainInfo.waitForPresent = pimpl->graphicsSettings.waitForPresent;
|
||||||
createSwapchain(&pimpl->swapchain, pimpl->swapchainInfo);
|
createSwapchain(&pimpl->swapchain, pimpl->swapchainInfo);
|
||||||
|
|
||||||
/* the following is temporary setup */
|
/* make synchronisation primitives for rendering and allocate command buffers */
|
||||||
|
|
||||||
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
VkFenceCreateInfo fenceInfo{
|
VkFenceCreateInfo fenceInfo{
|
||||||
@ -630,18 +642,35 @@ namespace engine {
|
|||||||
};
|
};
|
||||||
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].drawBuf));
|
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].drawBuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create a global descriptor pool */
|
||||||
|
|
||||||
|
std::vector<VkDescriptorPoolSize> poolSizes{};
|
||||||
|
poolSizes.emplace_back(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 5); // purposely low limit
|
||||||
|
|
||||||
|
VkDescriptorPoolCreateInfo descriptorPoolInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
};
|
||||||
|
descriptorPoolInfo.flags = 0;
|
||||||
|
descriptorPoolInfo.maxSets = 5; // purposely low limit
|
||||||
|
descriptorPoolInfo.poolSizeCount = poolSizes.size();
|
||||||
|
descriptorPoolInfo.pPoolSizes = poolSizes.data();
|
||||||
|
VKCHECK(vkCreateDescriptorPool(pimpl->device.device, &descriptorPoolInfo, nullptr, &pimpl->descriptorPool));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXDevice::~GFXDevice()
|
GFXDevice::~GFXDevice()
|
||||||
{
|
{
|
||||||
|
vkDestroyDescriptorPool(pimpl->device.device, pimpl->descriptorPool, nullptr);
|
||||||
|
|
||||||
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
for (int i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->frameData[i].drawBuf);
|
vkFreeCommandBuffers(pimpl->device.device, pimpl->device.commandPools.draw, 1, &pimpl->frameData[i].drawBuf);
|
||||||
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].renderSemaphore, nullptr);
|
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].renderSemaphore, nullptr);
|
||||||
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].presentSemaphore, nullptr);
|
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].presentSemaphore, nullptr);
|
||||||
vkDestroyFence(pimpl->device.device, pimpl->frameData[i].renderFence, nullptr);
|
vkDestroyFence(pimpl->device.device, pimpl->frameData[i].renderFence, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroySwapchain(pimpl->swapchain);
|
destroySwapchain(pimpl->swapchain);
|
||||||
destroyAllocator(pimpl->allocator);
|
destroyAllocator(pimpl->allocator);
|
||||||
destroyDevice(pimpl->device);
|
destroyDevice(pimpl->device);
|
||||||
@ -649,7 +678,7 @@ namespace engine {
|
|||||||
destroyVulkanInstance(pimpl->instance);
|
destroyVulkanInstance(pimpl->instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::getViewportSize(uint32_t *w, uint32_t *h)
|
void GFXDevice::getViewportSize(uint32_t* w, uint32_t* h)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height);
|
SDL_Vulkan_GetDrawableSize(pimpl->window, &width, &height);
|
||||||
@ -833,28 +862,33 @@ namespace engine {
|
|||||||
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
vkCmdDrawIndexed(drawBuffer->frameData.drawBuf, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling)
|
void GFXDevice::cmdBindDescriptorSet(gfx::DrawBuffer* drawBuffer, const gfx::Pipeline* pipeline, const gfx::DescriptorSet* set, uint32_t setNumber)
|
||||||
|
{
|
||||||
|
vkCmdBindDescriptorSets(drawBuffer->frameData.drawBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, setNumber, 1, &set->set, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Pipeline* GFXDevice::createPipeline(const gfx::PipelineInfo& info)
|
||||||
{
|
{
|
||||||
|
|
||||||
[[maybe_unused]] VkResult res;
|
[[maybe_unused]] VkResult res;
|
||||||
|
|
||||||
gfx::Pipeline* pipeline = new gfx::Pipeline;
|
gfx::Pipeline* pipeline = new gfx::Pipeline;
|
||||||
|
|
||||||
auto vertShaderCode = util::readTextFile(vertShaderPath);
|
auto vertShaderCode = util::readTextFile(info.vertShaderPath);
|
||||||
auto fragShaderCode = util::readTextFile(fragShaderPath);
|
auto fragShaderCode = util::readTextFile(info.fragShaderPath);
|
||||||
|
|
||||||
VkShaderModule vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), vertShaderPath);
|
VkShaderModule vertShaderModule = compileShader(pimpl->device.device, shaderc_vertex_shader, vertShaderCode->data(), info.vertShaderPath);
|
||||||
VkShaderModule fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), fragShaderPath);
|
VkShaderModule fragShaderModule = compileShader(pimpl->device.device, shaderc_fragment_shader, fragShaderCode->data(), info.fragShaderPath);
|
||||||
|
|
||||||
// get vertex attrib layout:
|
// get vertex attrib layout:
|
||||||
VkVertexInputBindingDescription bindingDescription{ };
|
VkVertexInputBindingDescription bindingDescription{ };
|
||||||
bindingDescription.binding = 0;
|
bindingDescription.binding = 0;
|
||||||
bindingDescription.stride = vertexFormat.stride;
|
bindingDescription.stride = info.vertexFormat.stride;
|
||||||
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
|
||||||
std::vector<VkVertexInputAttributeDescription> attribDescs{};
|
std::vector<VkVertexInputAttributeDescription> attribDescs{};
|
||||||
attribDescs.reserve(vertexFormat.attributeDescriptions.size());
|
attribDescs.reserve(info.vertexFormat.attributeDescriptions.size());
|
||||||
for (const auto& desc : vertexFormat.attributeDescriptions) {
|
for (const auto& desc : info.vertexFormat.attributeDescriptions) {
|
||||||
VkVertexInputAttributeDescription vulkanAttribDesc{};
|
VkVertexInputAttributeDescription vulkanAttribDesc{};
|
||||||
vulkanAttribDesc.binding = 0;
|
vulkanAttribDesc.binding = 0;
|
||||||
vulkanAttribDesc.location = desc.location;
|
vulkanAttribDesc.location = desc.location;
|
||||||
@ -928,7 +962,7 @@ namespace engine {
|
|||||||
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||||
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
rasterizer.lineWidth = 1.0f;
|
rasterizer.lineWidth = 1.0f;
|
||||||
if (backfaceCulling == true) {
|
if (info.backfaceCulling == true) {
|
||||||
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -955,7 +989,7 @@ namespace engine {
|
|||||||
VK_COLOR_COMPONENT_G_BIT |
|
VK_COLOR_COMPONENT_G_BIT |
|
||||||
VK_COLOR_COMPONENT_B_BIT |
|
VK_COLOR_COMPONENT_B_BIT |
|
||||||
VK_COLOR_COMPONENT_A_BIT;
|
VK_COLOR_COMPONENT_A_BIT;
|
||||||
if (alphaBlending) {
|
if (info.alphaBlending) {
|
||||||
colorBlendAttachment.blendEnable = VK_TRUE;
|
colorBlendAttachment.blendEnable = VK_TRUE;
|
||||||
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
@ -967,7 +1001,7 @@ namespace engine {
|
|||||||
else {
|
else {
|
||||||
colorBlendAttachment.blendEnable = VK_FALSE;
|
colorBlendAttachment.blendEnable = VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipelineColorBlendStateCreateInfo colorBlending{};
|
VkPipelineColorBlendStateCreateInfo colorBlending{};
|
||||||
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||||
colorBlending.logicOpEnable = VK_FALSE;
|
colorBlending.logicOpEnable = VK_FALSE;
|
||||||
@ -996,10 +1030,15 @@ namespace engine {
|
|||||||
pushConstantRange.size = PUSH_CONSTANT_MAX_SIZE;
|
pushConstantRange.size = PUSH_CONSTANT_MAX_SIZE;
|
||||||
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
|
||||||
|
std::vector<VkDescriptorSetLayout> descriptorSetLayouts(info.descriptorSetLayouts.size());
|
||||||
|
for (size_t i = 0; i < descriptorSetLayouts.size(); i++) {
|
||||||
|
descriptorSetLayouts[i] = info.descriptorSetLayouts[i]->layout;
|
||||||
|
}
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo layoutInfo{};
|
VkPipelineLayoutCreateInfo layoutInfo{};
|
||||||
layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
layoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
layoutInfo.setLayoutCount = 0;
|
layoutInfo.setLayoutCount = descriptorSetLayouts.size();
|
||||||
layoutInfo.pSetLayouts = nullptr;
|
layoutInfo.pSetLayouts = descriptorSetLayouts.data();
|
||||||
layoutInfo.pushConstantRangeCount = 1;
|
layoutInfo.pushConstantRangeCount = 1;
|
||||||
layoutInfo.pPushConstantRanges = &pushConstantRange;
|
layoutInfo.pPushConstantRanges = &pushConstantRange;
|
||||||
|
|
||||||
@ -1036,13 +1075,84 @@ namespace engine {
|
|||||||
|
|
||||||
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
|
void GFXDevice::destroyPipeline(const gfx::Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
|
|
||||||
vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr);
|
vkDestroyPipeline(pimpl->device.device, pipeline->handle, nullptr);
|
||||||
vkDestroyPipelineLayout(pimpl->device.device, pipeline->layout, nullptr);
|
vkDestroyPipelineLayout(pimpl->device.device, pipeline->layout, nullptr);
|
||||||
|
|
||||||
delete pipeline;
|
delete pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx::DescriptorSetLayout* GFXDevice::createDescriptorSetLayout()
|
||||||
|
{
|
||||||
|
gfx::DescriptorSetLayout* out = new gfx::DescriptorSetLayout{};
|
||||||
|
|
||||||
|
std::vector<VkDescriptorSetLayoutBinding> bindings{};
|
||||||
|
bindings.push_back({});
|
||||||
|
bindings[0].binding = 0; // This should be as low as possible to avoid wasting memory
|
||||||
|
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
bindings[0].descriptorCount = 1; // if > 1, accessible as an array in the shader
|
||||||
|
bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; // only accessible in vertex
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo info{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||||
|
.pNext = nullptr
|
||||||
|
};
|
||||||
|
info.flags = 0;
|
||||||
|
info.bindingCount = bindings.size();
|
||||||
|
info.pBindings = bindings.data();
|
||||||
|
VKCHECK(vkCreateDescriptorSetLayout(pimpl->device.device, &info, nullptr, &out->layout));
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::destroyDescriptorSetLayout(const gfx::DescriptorSetLayout* layout)
|
||||||
|
{
|
||||||
|
vkDestroyDescriptorSetLayout(pimpl->device.device, layout->layout, nullptr);
|
||||||
|
delete layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::DescriptorSet* GFXDevice::allocateDescriptorSet(const gfx::DescriptorSetLayout* layout)
|
||||||
|
{
|
||||||
|
gfx::DescriptorSet* set = new gfx::DescriptorSet{};
|
||||||
|
|
||||||
|
VkDescriptorSetAllocateInfo allocInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.descriptorPool = pimpl->descriptorPool,
|
||||||
|
.descriptorSetCount = 1,
|
||||||
|
.pSetLayouts = &layout->layout
|
||||||
|
};
|
||||||
|
|
||||||
|
VkResult res;
|
||||||
|
res = vkAllocateDescriptorSets(pimpl->device.device, &allocInfo, &set->set);
|
||||||
|
if (res == VK_ERROR_FRAGMENTED_POOL) throw std::runtime_error("Descriptor pool is fragmented!");
|
||||||
|
if (res == VK_ERROR_OUT_OF_POOL_MEMORY) throw std::runtime_error("Descriptor pool is out of memory!");
|
||||||
|
VKCHECK(res);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GFXDevice::updateDescriptor(const gfx::DescriptorSet* set, uint32_t binding, const gfx::Buffer* buffer)
|
||||||
|
{
|
||||||
|
VkDescriptorBufferInfo bufferInfo{
|
||||||
|
.buffer = buffer->buffer,
|
||||||
|
.offset = 0,
|
||||||
|
.range = VK_WHOLE_SIZE
|
||||||
|
};
|
||||||
|
VkWriteDescriptorSet descriptorWrite{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.dstSet = set->set,
|
||||||
|
.dstBinding = binding,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.pImageInfo = nullptr,
|
||||||
|
.pBufferInfo = &bufferInfo,
|
||||||
|
.pTexelBufferView = nullptr
|
||||||
|
};
|
||||||
|
vkUpdateDescriptorSets(pimpl->device.device, 1, &descriptorWrite, 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void GFXDevice::updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset)
|
void GFXDevice::updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1059,7 +1169,7 @@ namespace engine {
|
|||||||
vmaUnmapMemory(pimpl->allocator, buffer->allocation);
|
vmaUnmapMemory(pimpl->allocator, buffer->allocation);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data)
|
gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data)
|
||||||
@ -1106,7 +1216,7 @@ namespace engine {
|
|||||||
gpuBufferInfo.usage = vkinternal::getBufferUsageFlag(type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
gpuBufferInfo.usage = vkinternal::getBufferUsageFlag(type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
gpuBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
gpuBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
gpuBufferInfo.flags = 0;
|
gpuBufferInfo.flags = 0;
|
||||||
|
|
||||||
VmaAllocationCreateInfo gpuAllocationInfo{};
|
VmaAllocationCreateInfo gpuAllocationInfo{};
|
||||||
gpuAllocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
gpuAllocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||||
gpuAllocationInfo.flags = 0;
|
gpuAllocationInfo.flags = 0;
|
||||||
@ -1149,8 +1259,9 @@ namespace engine {
|
|||||||
|
|
||||||
if (mipmapSetting == gfx::MipmapSetting::OFF) {
|
if (mipmapSetting == gfx::MipmapSetting::OFF) {
|
||||||
out->mipLevels = 1;
|
out->mipLevels = 1;
|
||||||
} else {
|
}
|
||||||
out->mipLevels = static_cast<uint32_t>(std::floor(std::log2( std::max(width, height) ))) + 1;
|
else {
|
||||||
|
out->mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first load image into staging buffer
|
// first load image into staging buffer
|
||||||
@ -1249,7 +1360,7 @@ namespace engine {
|
|||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1
|
.layerCount = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
res = vkCreateImageView(pimpl->device, &imageViewInfo, nullptr, &out->imageView);
|
res = vkCreateImageView(pimpl->device, &imageViewInfo, nullptr, &out->imageView);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
|
||||||
@ -1268,7 +1379,8 @@ namespace engine {
|
|||||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||||
if (useAnisotropy) {
|
if (useAnisotropy) {
|
||||||
samplerInfo.anisotropyEnable = VK_TRUE;
|
samplerInfo.anisotropyEnable = VK_TRUE;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
samplerInfo.anisotropyEnable = VK_FALSE;
|
samplerInfo.anisotropyEnable = VK_FALSE;
|
||||||
}
|
}
|
||||||
samplerInfo.maxAnisotropy = pimpl->maxSamplerAnisotropy;
|
samplerInfo.maxAnisotropy = pimpl->maxSamplerAnisotropy;
|
||||||
@ -1278,7 +1390,8 @@ namespace engine {
|
|||||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||||
if (mipmapSetting == gfx::MipmapSetting::LINEAR) {
|
if (mipmapSetting == gfx::MipmapSetting::LINEAR) {
|
||||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||||
}
|
}
|
||||||
samplerInfo.minLod = 0.0f;
|
samplerInfo.minLod = 0.0f;
|
||||||
|
@ -11,6 +11,9 @@ namespace engine::resources {
|
|||||||
Shader::Shader(GFXDevice* gfx, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace)
|
Shader::Shader(GFXDevice* gfx, const char* vertPath, const char* fragPath, const VertexParams& vertexParams, bool alphaBlending, bool cullBackFace)
|
||||||
: m_gfx(gfx)
|
: m_gfx(gfx)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
m_setZeroLayout = m_gfx->createDescriptorSetLayout();
|
||||||
|
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
uint32_t stride = 0;
|
uint32_t stride = 0;
|
||||||
gfx::VertexFormat vertFormat{};
|
gfx::VertexFormat vertFormat{};
|
||||||
@ -36,14 +39,32 @@ namespace engine::resources {
|
|||||||
}
|
}
|
||||||
vertFormat.stride = stride;
|
vertFormat.stride = stride;
|
||||||
|
|
||||||
m_pipeline = m_gfx->createPipeline(vertPath, fragPath, vertFormat, sizeof(glm::mat4) * 2, alphaBlending, cullBackFace);
|
gfx::PipelineInfo info{};
|
||||||
|
info.vertShaderPath = vertPath;
|
||||||
|
info.fragShaderPath = fragPath;
|
||||||
|
info.vertexFormat = vertFormat;
|
||||||
|
info.alphaBlending = alphaBlending;
|
||||||
|
info.backfaceCulling = cullBackFace;
|
||||||
|
info.descriptorSetLayouts.push_back(m_setZeroLayout);
|
||||||
|
|
||||||
|
m_pipeline = m_gfx->createPipeline(info);
|
||||||
|
|
||||||
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attributeDescriptions.size());
|
LOG_INFO("Loaded shader: {}, vertex attribs: {}", vertPath, vertFormat.attributeDescriptions.size());
|
||||||
|
|
||||||
|
/* allocate uniform descriptor set */
|
||||||
|
m_setZero = m_gfx->allocateDescriptorSet(m_setZeroLayout);
|
||||||
|
/* fill with data */
|
||||||
|
glm::vec4 myValue = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||||
|
m_setZeroBuffer = m_gfx->createBuffer(gfx::BufferType::UNIFORM, sizeof(glm::vec4), &myValue);
|
||||||
|
m_gfx->updateDescriptor(m_setZero, 0, m_setZeroBuffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::~Shader()
|
Shader::~Shader()
|
||||||
{
|
{
|
||||||
|
m_gfx->destroyBuffer(m_setZeroBuffer);
|
||||||
m_gfx->destroyPipeline(m_pipeline);
|
m_gfx->destroyPipeline(m_pipeline);
|
||||||
|
m_gfx->destroyDescriptorSetLayout(m_setZeroLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
const gfx::Pipeline* Shader::getPipeline()
|
const gfx::Pipeline* Shader::getPipeline()
|
||||||
|
@ -78,6 +78,7 @@ namespace engine {
|
|||||||
pushConsts.view = viewMatrix;
|
pushConsts.view = viewMatrix;
|
||||||
|
|
||||||
gfx->cmdBindPipeline(drawBuffer, r->material->getShader()->getPipeline());
|
gfx->cmdBindPipeline(drawBuffer, r->material->getShader()->getPipeline());
|
||||||
|
gfx->cmdBindDescriptorSet(drawBuffer, r->material->getShader()->getPipeline(), r->material->getShader()->getSetZero(), 0);
|
||||||
gfx->cmdBindVertexBuffer(drawBuffer, 0, r->mesh->getVB());
|
gfx->cmdBindVertexBuffer(drawBuffer, 0, r->mesh->getVB());
|
||||||
gfx->cmdBindIndexBuffer(drawBuffer, r->mesh->getIB());
|
gfx->cmdBindIndexBuffer(drawBuffer, r->mesh->getIB());
|
||||||
gfx->cmdDrawIndexed(drawBuffer, r->mesh->getCount(), 1, 0, 0, 0);
|
gfx->cmdDrawIndexed(drawBuffer, r->mesh->getCount(), 1, 0, 0, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user