Get descriptor sets working

This commit is contained in:
bailwillharr 2023-03-13 01:19:32 +00:00
parent 2bb75f4683
commit bbf582d85f
8 changed files with 210 additions and 42 deletions

View File

@ -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;
};
} }

View File

@ -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);

View File

@ -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;
}; };

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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");
} }
@ -541,6 +551,8 @@ namespace engine {
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] = {};
@ -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{
@ -631,10 +643,27 @@ 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);
@ -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;
@ -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)
{ {
@ -1149,7 +1259,8 @@ namespace engine {
if (mipmapSetting == gfx::MipmapSetting::OFF) { if (mipmapSetting == gfx::MipmapSetting::OFF) {
out->mipLevels = 1; out->mipLevels = 1;
} else { }
else {
out->mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1; out->mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1;
} }
@ -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;

View File

@ -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()

View File

@ -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);