Archived
1
Fork 0

Last changes to make Vulkan backend work

Now it renders with IBL and shadows off! yay!
This commit is contained in:
redstrate 2020-09-30 19:18:17 -04:00
parent 9a49c127d4
commit b3ecbab352
11 changed files with 207 additions and 67 deletions

View file

@ -316,7 +316,7 @@ public:
/// If physics should upate. This is a control indepentent of the pause state.
bool update_physics = true;
#if defined(PLATFORM_TVOS) || defined(PLATFORM_IOS)
#if defined(PLATFORM_TVOS) || defined(PLATFORM_IOS) || defined(PLATFORM_WINDOWS)
bool debug_enabled = true;
#else
bool debug_enabled = false;

View file

@ -120,7 +120,9 @@ enum class GFXBindingType {
StorageBuffer,
StorageImage,
PushConstant,
Texture
Texture,
Sampler,
SampledImage
};
enum class GFXTextureType {

View file

@ -42,6 +42,9 @@ public:
void copy_texture(GFXTexture* from, GFXTexture* to) override;
void copy_texture(GFXTexture* from, GFXBuffer* to) override;
// sampler operations
GFXSampler* create_sampler(const GFXSamplerCreateInfo& info) override;
// framebuffer operations
GFXFramebuffer* create_framebuffer(const GFXFramebufferCreateInfo& info) override;
@ -115,4 +118,5 @@ private:
std::array<BoundShaderBuffer, 25> boundShaderBuffers;
std::array<GFXTexture*, 25> boundTextures;
std::array<GFXSampler*, 25> boundSamplers;
};

View file

@ -11,8 +11,10 @@
#include "gfx_vulkan_texture.hpp"
#include "gfx_vulkan_framebuffer.hpp"
#include "gfx_vulkan_renderpass.hpp"
#include "gfx_vulkan_sampler.hpp"
#include "file.hpp"
#include "log.hpp"
#include "utility.hpp"
void* windowNativeHandle;
@ -289,6 +291,12 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
else
imageAspect = VK_IMAGE_ASPECT_COLOR_BIT;
int array_length = info.array_length;
if (info.type == GFXTextureType::Cubemap)
array_length = 6;
else if (info.type == GFXTextureType::CubemapArray)
array_length *= 6;
// create image
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@ -296,8 +304,8 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
imageInfo.extent.width = info.width;
imageInfo.extent.height = info.height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.mipLevels = info.mip_count;
imageInfo.arrayLayers = array_length;
imageInfo.format = imageFormat;
imageInfo.tiling = imageTiling;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@ -305,6 +313,9 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
if (info.type == GFXTextureType::Cubemap || info.type == GFXTextureType::CubemapArray)
imageInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
vkCreateImage(device, &imageInfo, nullptr, &texture->handle);
texture->layout = imageLayout;
@ -331,13 +342,27 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = texture->handle;
switch (info.type) {
case GFXTextureType::Single2D:
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
break;
case GFXTextureType::Array2D:
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
break;
case GFXTextureType::Cubemap:
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
break;
case GFXTextureType::CubemapArray:
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
break;
}
viewInfo.format = imageFormat;
viewInfo.subresourceRange.aspectMask = imageAspect;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.levelCount = info.mip_count;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
viewInfo.subresourceRange.layerCount = array_length;
vkCreateImageView(device, &viewInfo, nullptr, &texture->view);
@ -431,6 +456,31 @@ void GFXVulkan::copy_texture(GFXTexture* from, GFXBuffer* to) {
console::error(System::GFX, "Copy Texture->Buffer unimplemented!");
}
GFXSampler* GFXVulkan::create_sampler(const GFXSamplerCreateInfo& info) {
GFXVulkanSampler* sampler = new GFXVulkanSampler();
VkSamplerAddressMode samplerMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
if (info.samplingMode == SamplingMode::ClampToEdge)
samplerMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
VkSamplerCreateInfo samplerInfo = {};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.addressModeU = samplerMode;
samplerInfo.addressModeV = samplerMode;
samplerInfo.addressModeW = samplerMode;
samplerInfo.anisotropyEnable = VK_TRUE;
samplerInfo.maxAnisotropy = 16;
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
vkCreateSampler(device, &samplerInfo, nullptr, &sampler->sampler);
return sampler;
}
GFXFramebuffer* GFXVulkan::create_framebuffer(const GFXFramebufferCreateInfo& info) {
GFXVulkanFramebuffer* framebuffer = new GFXVulkanFramebuffer();
@ -694,7 +744,7 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
VkPushConstantRange range;
range.offset = pushConstant.offset;
range.size = pushConstant.size;
range.stageFlags = VK_SHADER_STAGE_ALL;
range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
pushConstants.push_back(range);
}
@ -715,7 +765,19 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
break;
case GFXBindingType::StorageImage:
{
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
pipeline->bindings_marked_as_storage_images.push_back(binding.binding);
}
break;
case GFXBindingType::SampledImage:
{
descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
pipeline->bindings_marked_as_sampled_images.push_back(binding.binding);
}
break;
case GFXBindingType::Sampler:
descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
break;
}
@ -772,6 +834,12 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline->handle);
name_object(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipeline->handle, std::string(info.shaders.vertex_path.data()) + std::string(info.shaders.fragment_path.data()));
name_object(device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)pipeline->layout, std::string(info.shaders.vertex_path.data()) + std::string(info.shaders.fragment_path.data()));
if (info.label.empty())
pipeline->label = std::string(info.shaders.vertex_path.data()) + std::string(info.shaders.fragment_path.data());
else
pipeline->label = info.label;
return pipeline;
}
@ -890,6 +958,8 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
renderPassInfo.pClearValues = clearColors.data();
vkCmdBeginRenderPass(commandBuffers[imageIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
currentPipeline = nullptr;
}
break;
case GFXCommandType::SetGraphicsPipeline:
@ -922,7 +992,7 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
case GFXCommandType::SetPushConstant:
{
if(currentPipeline != nullptr)
vkCmdPushConstants(commandBuffers[imageIndex], currentPipeline->layout, VK_SHADER_STAGE_ALL, 0, command.data.set_push_constant.size, command.data.set_push_constant.bytes.data());
vkCmdPushConstants(commandBuffers[imageIndex], currentPipeline->layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, command.data.set_push_constant.size, command.data.set_push_constant.bytes.data());
}
break;
case GFXCommandType::BindShaderBuffer:
@ -940,6 +1010,11 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
boundTextures[command.data.bind_texture.index] = command.data.bind_texture.texture;
}
break;
case GFXCommandType::BindSampler:
{
boundSamplers[command.data.bind_sampler.index] = command.data.bind_sampler.sampler;
}
break;
case GFXCommandType::Draw:
{
if (lastDescriptorHash != getDescriptorHash(currentPipeline)) {
@ -1368,6 +1443,9 @@ void GFXVulkan::resetDescriptorState() {
for (auto& texture : boundTextures)
texture = nullptr;
for (auto& sampler : boundSamplers)
sampler = nullptr;
}
void GFXVulkan::cacheDescriptorState(GFXVulkanPipeline* pipeline, VkDescriptorSetLayout layout) {
@ -1386,14 +1464,12 @@ void GFXVulkan::cacheDescriptorState(GFXVulkanPipeline* pipeline, VkDescriptorSe
vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet);
name_object(device, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)descriptorSet, pipeline->label);
// update set
int i = 0;
for (auto& buffer : boundShaderBuffers) {
if (buffer.buffer == nullptr) {
i++;
continue;
}
if (buffer.buffer != nullptr) {
GFXVulkanBuffer* vulkanBuffer = (GFXVulkanBuffer*)buffer.buffer;
VkDescriptorBufferInfo bufferInfo = {};
@ -1410,6 +1486,7 @@ void GFXVulkan::cacheDescriptorState(GFXVulkanPipeline* pipeline, VkDescriptorSe
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
}
i++;
}
@ -1437,10 +1514,42 @@ void GFXVulkan::cacheDescriptorState(GFXVulkanPipeline* pipeline, VkDescriptorSe
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSet;
descriptorWrite.dstBinding = i;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pImageInfo = &imageInfo;
if (utility::contains(pipeline->bindings_marked_as_storage_images, i)) {
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
} else if (utility::contains(pipeline->bindings_marked_as_sampled_images, i)) {
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
} else {
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
}
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
i++;
}
i = 0;
for (auto& sampler : boundSamplers) {
if (sampler == nullptr) {
i++;
continue;
}
GFXVulkanSampler* vulkanSampler = (GFXVulkanSampler*)sampler;
VkDescriptorImageInfo imageInfo = {};
imageInfo.sampler = vulkanSampler->sampler;
VkWriteDescriptorSet descriptorWrite = {};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSet;
descriptorWrite.dstBinding = i;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pImageInfo = &imageInfo;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
i++;
@ -1453,12 +1562,14 @@ uint64_t GFXVulkan::getDescriptorHash(GFXVulkanPipeline* pipeline) {
uint64_t hash = 0;
hash += (int64_t)pipeline;
int i = 0;
for (auto& buffer : boundShaderBuffers) {
if(buffer.buffer != nullptr)
hash += (uint64_t)buffer.buffer;
if (buffer.buffer != nullptr) {
hash += (uint64_t)buffer.buffer * (i + 1);
}
}
int i = 0;
i = 0;
for (auto& texture : boundTextures) {
if (texture != nullptr) {
hash += (uint64_t)texture * (i + 1);

View file

@ -6,11 +6,16 @@
class GFXVulkanPipeline : public GFXPipeline {
public:
std::string label;
VkPipeline handle;
VkPipelineLayout layout;
VkDescriptorSetLayout descriptorLayout;
std::vector<int> bindings_marked_as_storage_images;
std::vector<int> bindings_marked_as_sampled_images;
// dynamic descriptor sets
std::map<uint64_t, VkDescriptorSet> cachedDescriptorSets;
};

View file

@ -0,0 +1,10 @@
#pragma once
#include <vulkan/vulkan.h>
#include "gfx_sampler.hpp"
class GFXVulkanSampler: public GFXSampler {
public:
VkSampler sampler;
};

View file

@ -32,7 +32,7 @@ DoFPass::DoFPass(GFX* gfx, Renderer* renderer) : renderer(renderer) {
create_info.shaders.fragment_path = "dof.frag";
create_info.shader_input.bindings = {
{0, GFXBindingType::StorageImage},
{0, GFXBindingType::SampledImage},
{1, GFXBindingType::Texture},
{3, GFXBindingType::Texture},
{2, GFXBindingType::PushConstant}

View file

@ -37,6 +37,12 @@ GFXPipeline* MaterialCompiler::create_static_pipeline(GFXGraphicsPipelineCreateI
std::string vertex_path = createInfo.shaders.vertex_path.data();
vertex_path += ".glsl";
if (positions_only)
createInfo.label += "shadow ver";
if (cubemap)
createInfo.label += "cubemap ver";
createInfo.shaders.vertex_src = get_shader(vertex_path, false, cubemap);
createInfo.shaders.vertex_path = "";

View file

@ -479,17 +479,6 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
command_buffer->bind_shader_buffer(sceneBuffer, 0, 1, sizeof(SceneInformation));
command_buffer->bind_texture(scene.depthTexture, 2);
command_buffer->bind_texture(scene.pointLightArray, 3);
command_buffer->bind_sampler(shadow_pass->shadow_sampler, 4);
command_buffer->bind_sampler(shadow_pass->pcf_sampler, 5);
command_buffer->bind_texture(scene.spotLightArray, 6);
command_buffer->bind_texture(scene.irradianceCubeArray, 7);
command_buffer->bind_texture(scene.prefilteredCubeArray, 8);
command_buffer->bind_texture(brdfTexture, 9);
for(const auto& part : mesh.mesh->parts) {
const int material_index = part.material_override == -1 ? 0 : part.material_override;
@ -504,10 +493,20 @@ void Renderer::render_camera(GFXCommandBuffer* command_buffer, Scene& scene, Obj
command_buffer->set_graphics_pipeline(mesh.mesh->bones.empty() ? mesh.materials[material_index]->static_pipeline : mesh.materials[material_index]->skinned_pipeline);
command_buffer->bind_shader_buffer(sceneBuffer, 0, 1, sizeof(SceneInformation));
command_buffer->bind_texture(scene.depthTexture, 2);
command_buffer->bind_texture(scene.pointLightArray, 3);
command_buffer->bind_sampler(shadow_pass->shadow_sampler, 4);
command_buffer->bind_sampler(shadow_pass->pcf_sampler, 5);
command_buffer->bind_texture(scene.spotLightArray, 6);
command_buffer->bind_texture(scene.irradianceCubeArray, 7);
command_buffer->bind_texture(scene.prefilteredCubeArray, 8);
command_buffer->bind_texture(brdfTexture, 9);
if(!mesh.mesh->bones.empty())
command_buffer->bind_shader_buffer(part.bone_batrix_buffer, 0, 14, sizeof(Matrix4x4) * 128);
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
for(const auto& [index, texture] : mesh.materials[material_index]->bound_textures) {
@ -647,12 +646,6 @@ void Renderer::render_screen(GFXCommandBuffer *commandbuffer, ui::Screen* screen
if(!element.visible)
continue;
if(element.background.texture) {
commandbuffer->bind_texture(element.background.texture->handle, 2);
} else {
commandbuffer->bind_texture(dummyTexture, 2);
}
UIPushConstant pc;
pc.screenSize = windowSize;
@ -663,6 +656,13 @@ void Renderer::render_screen(GFXCommandBuffer *commandbuffer, ui::Screen* screen
commandbuffer->set_graphics_pipeline(generalPipeline);
}
if (element.background.texture) {
commandbuffer->bind_texture(element.background.texture->handle, 2);
}
else {
commandbuffer->bind_texture(dummyTexture, 2);
}
commandbuffer->set_push_constant(&pc, sizeof(UIPushConstant));
commandbuffer->bind_shader_buffer(screen->elements_buffer, 0, 0, sizeof(ElementInstance) * 50);
@ -727,11 +727,11 @@ void Renderer::create_mesh_pipeline(Material& material) {
pipelineInfo.shader_input.bindings = {
{1, GFXBindingType::StorageBuffer},
{0, GFXBindingType::PushConstant},
{2, GFXBindingType::Texture},
{3, GFXBindingType::Texture},
{4, GFXBindingType::Texture},
{5, GFXBindingType::Texture},
{6, GFXBindingType::Texture},
{2, GFXBindingType::SampledImage},
{3, GFXBindingType::SampledImage},
{4, GFXBindingType::Sampler},
{5, GFXBindingType::Sampler},
{6, GFXBindingType::SampledImage},
{7, GFXBindingType::Texture},
{8, GFXBindingType::Texture},
{9, GFXBindingType::Texture}

View file

@ -233,13 +233,6 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
command_buffer->bind_shader_buffer(sceneBuffer, 0, 1, sizeof(SceneInformation));
command_buffer->bind_texture(scene->depthTexture, 2);
command_buffer->bind_texture(scene->pointLightArray, 3);
command_buffer->bind_sampler(engine->get_renderer()->shadow_pass->shadow_sampler, 4);
command_buffer->bind_sampler(engine->get_renderer()->shadow_pass->pcf_sampler, 5);
command_buffer->bind_texture(scene->spotLightArray, 6);
if(mesh.mesh->bones.empty()) {
for (auto& part : mesh.mesh->parts) {
const int material_index = part.material_override == -1 ? 0 : part.material_override;
@ -255,6 +248,13 @@ void SceneCapture::render(GFXCommandBuffer* command_buffer, Scene* scene) {
command_buffer->set_graphics_pipeline(mesh.materials[material_index]->capture_pipeline);
command_buffer->bind_shader_buffer(sceneBuffer, 0, 1, sizeof(SceneInformation));
command_buffer->bind_texture(scene->depthTexture, 2);
command_buffer->bind_texture(scene->pointLightArray, 3);
command_buffer->bind_sampler(engine->get_renderer()->shadow_pass->shadow_sampler, 4);
command_buffer->bind_sampler(engine->get_renderer()->shadow_pass->pcf_sampler, 5);
command_buffer->bind_texture(scene->spotLightArray, 6);
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
for(auto& [index, texture] : mesh.materials[material_index]->bound_textures) {

View file

@ -117,8 +117,6 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
command_buffer->set_index_buffer(mesh.mesh->index_buffer, IndexType::UINT32);
command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(Vector3) * max_point_shadows);
PushConstant pc;
pc.mvp = light_matrix * model * scene.get<Transform>(obj).model;
pc.model = scene.get<Transform>(obj).model;
@ -136,6 +134,8 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
break;
}
command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(Vector3) * max_point_shadows);
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
command_buffer->set_depth_bias(1.25f, 0.00f, 1.75f);
@ -158,6 +158,8 @@ void ShadowPass::render_meshes(GFXCommandBuffer* command_buffer, Scene& scene, c
break;
}
command_buffer->bind_shader_buffer(point_location_buffer, 0, 2, sizeof(Vector3) * max_point_shadows);
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
command_buffer->set_vertex_buffer(mesh.mesh->bone_buffer, 0, bone_buffer_index);