Add compute pipeline support for Vulkan
* Image transition layouts are not handled correctly yet, so auto exposure does not work * Image usage and guessed image layout is redone to remove some errors
This commit is contained in:
parent
0d75b4f47e
commit
ee2771f45f
9 changed files with 244 additions and 73 deletions
|
@ -38,10 +38,12 @@ enum class GFXVertexFormat : int {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class GFXTextureUsage : int {
|
enum class GFXTextureUsage : int {
|
||||||
Sampled = 1,
|
Sampled = 0,
|
||||||
Attachment = 2,
|
Attachment = 1,
|
||||||
ShaderWrite = 3,
|
ShaderWrite = 2,
|
||||||
Transfer = 4
|
TransferSrc = 4,
|
||||||
|
TransferDst = 8,
|
||||||
|
Storage = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
inline GFXTextureUsage operator|(const GFXTextureUsage a, const GFXTextureUsage b) {
|
inline GFXTextureUsage operator|(const GFXTextureUsage a, const GFXTextureUsage b) {
|
||||||
|
@ -200,12 +202,9 @@ struct GFXGraphicsPipelineCreateInfo {
|
||||||
|
|
||||||
struct GFXComputePipelineCreateInfo {
|
struct GFXComputePipelineCreateInfo {
|
||||||
std::string label; // only used for debug
|
std::string label; // only used for debug
|
||||||
|
|
||||||
struct Shaders {
|
ShaderSource compute_src;
|
||||||
std::string_view compute_path;
|
|
||||||
ShaderSource compute_src;
|
|
||||||
} shaders;
|
|
||||||
|
|
||||||
struct ShaderBindings {
|
struct ShaderBindings {
|
||||||
std::vector<GFXPushConstant> push_constants;
|
std::vector<GFXPushConstant> push_constants;
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ public:
|
||||||
|
|
||||||
// pipeline operations
|
// pipeline operations
|
||||||
GFXPipeline* create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) override;
|
GFXPipeline* create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) override;
|
||||||
|
GFXPipeline* create_compute_pipeline(const GFXComputePipelineCreateInfo& info) override;
|
||||||
|
|
||||||
// misc operations
|
// misc operations
|
||||||
GFXSize get_alignment(const GFXSize size) override;
|
GFXSize get_alignment(const GFXSize size) override;
|
||||||
|
|
|
@ -341,21 +341,31 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
|
||||||
VkImageTiling imageTiling;
|
VkImageTiling imageTiling;
|
||||||
imageTiling = VK_IMAGE_TILING_OPTIMAL;
|
imageTiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
|
||||||
|
const auto check_flag = [](const GFXTextureUsage usage, const GFXTextureUsage flag) {
|
||||||
|
return (usage & flag) == flag;
|
||||||
|
};
|
||||||
|
|
||||||
VkImageUsageFlags imageUsage = 0;
|
VkImageUsageFlags imageUsage = 0;
|
||||||
if ((info.usage & GFXTextureUsage::Attachment) == GFXTextureUsage::Attachment) {
|
if(check_flag(info.usage, GFXTextureUsage::Attachment)) {
|
||||||
if (info.format == GFXPixelFormat::DEPTH_32F) {
|
if (info.format == GFXPixelFormat::DEPTH_32F) {
|
||||||
imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
imageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
if(check_flag(info.usage, GFXTextureUsage::Sampled))
|
||||||
}
|
imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
|
||||||
if((info.usage & GFXTextureUsage::Transfer) == GFXTextureUsage::Transfer)
|
if(check_flag(info.usage, GFXTextureUsage::TransferSrc))
|
||||||
imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
|
||||||
|
if(check_flag(info.usage, GFXTextureUsage::TransferDst))
|
||||||
|
imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
||||||
|
if(check_flag(info.usage, GFXTextureUsage::Storage))
|
||||||
|
imageUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||||
|
|
||||||
VkImageAspectFlagBits imageAspect;
|
VkImageAspectFlagBits imageAspect;
|
||||||
if (info.format == GFXPixelFormat::DEPTH_32F)
|
if (info.format == GFXPixelFormat::DEPTH_32F)
|
||||||
|
@ -396,7 +406,20 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
|
||||||
texture->height = info.height;
|
texture->height = info.height;
|
||||||
texture->format = imageFormat;
|
texture->format = imageFormat;
|
||||||
texture->aspect = imageAspect;
|
texture->aspect = imageAspect;
|
||||||
texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
|
if(check_flag(info.usage, GFXTextureUsage::Attachment) && !check_flag(info.usage, GFXTextureUsage::Sampled)) {
|
||||||
|
if (info.format == GFXPixelFormat::DEPTH_32F) {
|
||||||
|
texture->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
} else {
|
||||||
|
texture->layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
}
|
||||||
|
} else if(check_flag(info.usage, GFXTextureUsage::Storage) && check_flag(info.usage, GFXTextureUsage::ShaderWrite)) {
|
||||||
|
texture->layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
} else if(check_flag(info.usage, GFXTextureUsage::Sampled)) {
|
||||||
|
texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
} else {
|
||||||
|
texture->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate memory
|
// allocate memory
|
||||||
VkMemoryRequirements memRequirements;
|
VkMemoryRequirements memRequirements;
|
||||||
|
@ -420,7 +443,7 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
|
||||||
|
|
||||||
texture->range = range;
|
texture->range = range;
|
||||||
|
|
||||||
transitionImageLayout(texture->handle, imageFormat, imageAspect, range, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
transitionImageLayout(texture->handle, imageFormat, imageAspect, range, VK_IMAGE_LAYOUT_UNDEFINED, texture->layout);
|
||||||
|
|
||||||
// create image view
|
// create image view
|
||||||
VkImageViewCreateInfo viewInfo = {};
|
VkImageViewCreateInfo viewInfo = {};
|
||||||
|
@ -997,6 +1020,121 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GFXPipeline* GFXVulkan::create_compute_pipeline(const GFXComputePipelineCreateInfo& info) {
|
||||||
|
GFXVulkanPipeline* pipeline = new GFXVulkanPipeline();
|
||||||
|
|
||||||
|
vkDeviceWaitIdle(device);
|
||||||
|
|
||||||
|
VkShaderModule compute_module = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
const bool use_shader_source = !info.compute_src.is_path();
|
||||||
|
|
||||||
|
if (use_shader_source) {
|
||||||
|
auto shader_vector = info.compute_src.as_bytecode();
|
||||||
|
|
||||||
|
compute_module = createShaderModule(shader_vector.data(), shader_vector.size() * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto shader = file::open(file::internal_domain / (info.compute_src.as_path().string()), true);
|
||||||
|
shader->read_all();
|
||||||
|
|
||||||
|
compute_module = createShaderModule(shader->cast_data<uint32_t>(), shader->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!use_shader_source)
|
||||||
|
name_object(device, VK_OBJECT_TYPE_SHADER_MODULE, (uint64_t)compute_module, info.compute_src.as_path().string());
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo shaderStageInfo = {};
|
||||||
|
shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
shaderStageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
|
shaderStageInfo.module = compute_module;
|
||||||
|
shaderStageInfo.pName = "main";
|
||||||
|
|
||||||
|
// create push constants
|
||||||
|
std::vector<VkPushConstantRange> pushConstants;
|
||||||
|
for (auto& pushConstant : info.shader_input.push_constants) {
|
||||||
|
VkPushConstantRange range;
|
||||||
|
range.offset = pushConstant.offset;
|
||||||
|
range.size = pushConstant.size;
|
||||||
|
range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
|
|
||||||
|
pushConstants.push_back(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create descriptor layout
|
||||||
|
std::vector<VkDescriptorSetLayoutBinding> layoutBindings;
|
||||||
|
for (auto& binding : info.shader_input.bindings) {
|
||||||
|
// ignore push constants
|
||||||
|
if (binding.type == GFXBindingType::PushConstant)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
|
switch (binding.type) {
|
||||||
|
case GFXBindingType::StorageBuffer:
|
||||||
|
descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
|
break;
|
||||||
|
case GFXBindingType::Texture:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutBinding layoutBinding = {};
|
||||||
|
layoutBinding.binding = binding.binding;
|
||||||
|
layoutBinding.descriptorType = descriptorType;
|
||||||
|
layoutBinding.descriptorCount = 1;
|
||||||
|
layoutBinding.stageFlags = VK_SHADER_STAGE_ALL;
|
||||||
|
|
||||||
|
layoutBindings.push_back(layoutBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo layoutCreateInfo = {};
|
||||||
|
layoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||||
|
layoutCreateInfo.bindingCount = static_cast<uint32_t>(layoutBindings.size());
|
||||||
|
layoutCreateInfo.pBindings = layoutBindings.data();
|
||||||
|
|
||||||
|
vkCreateDescriptorSetLayout(device, &layoutCreateInfo, nullptr, &pipeline->descriptorLayout);
|
||||||
|
|
||||||
|
// create layout
|
||||||
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
|
||||||
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
pipelineLayoutInfo.pushConstantRangeCount = static_cast<uint32_t>(pushConstants.size());
|
||||||
|
pipelineLayoutInfo.pPushConstantRanges = pushConstants.data();
|
||||||
|
pipelineLayoutInfo.pSetLayouts = &pipeline->descriptorLayout;
|
||||||
|
pipelineLayoutInfo.setLayoutCount = 1;
|
||||||
|
|
||||||
|
vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipeline->layout);
|
||||||
|
|
||||||
|
// create pipeline
|
||||||
|
VkComputePipelineCreateInfo pipelineInfo = {};
|
||||||
|
pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||||
|
pipelineInfo.stage = shaderStageInfo;
|
||||||
|
pipelineInfo.layout = pipeline->layout;
|
||||||
|
|
||||||
|
vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline->handle);
|
||||||
|
|
||||||
|
pipeline->label = info.label;
|
||||||
|
|
||||||
|
name_object(device, VK_OBJECT_TYPE_PIPELINE, (uint64_t)pipeline->handle, pipeline->label);
|
||||||
|
name_object(device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)pipeline->layout, pipeline->label);
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
GFXSize GFXVulkan::get_alignment(GFXSize size) {
|
GFXSize GFXVulkan::get_alignment(GFXSize size) {
|
||||||
VkPhysicalDeviceProperties properties;
|
VkPhysicalDeviceProperties properties;
|
||||||
vkGetPhysicalDeviceProperties(physicalDevice, &properties);
|
vkGetPhysicalDeviceProperties(physicalDevice, &properties);
|
||||||
|
@ -1057,8 +1195,9 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
||||||
VkRenderPass currentRenderPass = VK_NULL_HANDLE;
|
VkRenderPass currentRenderPass = VK_NULL_HANDLE;
|
||||||
GFXVulkanPipeline* currentPipeline = nullptr;
|
GFXVulkanPipeline* currentPipeline = nullptr;
|
||||||
uint64_t lastDescriptorHash = 0;
|
uint64_t lastDescriptorHash = 0;
|
||||||
|
bool is_compute = false;
|
||||||
|
|
||||||
const auto try_bind_descriptor = [cmd, this, ¤tPipeline, &lastDescriptorHash]() -> bool {
|
const auto try_bind_descriptor = [cmd, this, ¤tPipeline, &lastDescriptorHash, &is_compute]() -> bool {
|
||||||
if(currentPipeline == nullptr)
|
if(currentPipeline == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1070,7 +1209,7 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
||||||
if (descriptor_set == VK_NULL_HANDLE)
|
if (descriptor_set == VK_NULL_HANDLE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->layout, 0, 1, &descriptor_set, 0, nullptr);
|
vkCmdBindDescriptorSets(cmd, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->layout, 0, 1, &descriptor_set, 0, nullptr);
|
||||||
|
|
||||||
lastDescriptorHash = getDescriptorHash(currentPipeline);
|
lastDescriptorHash = getDescriptorHash(currentPipeline);
|
||||||
}
|
}
|
||||||
|
@ -1174,8 +1313,23 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
||||||
resetDescriptorState();
|
resetDescriptorState();
|
||||||
lastDescriptorHash = 0;
|
lastDescriptorHash = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_compute = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GFXCommandType::SetComputePipeline:
|
||||||
|
{
|
||||||
|
currentPipeline = (GFXVulkanPipeline*)command.data.set_compute_pipeline.pipeline;
|
||||||
|
if(currentPipeline != nullptr) {
|
||||||
|
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, currentPipeline->handle);
|
||||||
|
|
||||||
|
resetDescriptorState();
|
||||||
|
lastDescriptorHash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_compute = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case GFXCommandType::SetVertexBuffer:
|
case GFXCommandType::SetVertexBuffer:
|
||||||
{
|
{
|
||||||
VkBuffer buffer = ((GFXVulkanBuffer*)command.data.set_vertex_buffer.buffer)->handle;
|
VkBuffer buffer = ((GFXVulkanBuffer*)command.data.set_vertex_buffer.buffer)->handle;
|
||||||
|
@ -1194,8 +1348,12 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
||||||
break;
|
break;
|
||||||
case GFXCommandType::SetPushConstant:
|
case GFXCommandType::SetPushConstant:
|
||||||
{
|
{
|
||||||
|
VkShaderStageFlags applicableStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
if(is_compute)
|
||||||
|
applicableStages = VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
|
|
||||||
if(currentPipeline != nullptr)
|
if(currentPipeline != nullptr)
|
||||||
vkCmdPushConstants(cmd, 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());
|
vkCmdPushConstants(cmd, currentPipeline->layout, applicableStages , 0, command.data.set_push_constant.size, command.data.set_push_constant.bytes.data());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GFXCommandType::BindShaderBuffer:
|
case GFXCommandType::BindShaderBuffer:
|
||||||
|
@ -1297,6 +1455,12 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GFXCommandType::Dispatch:
|
||||||
|
{
|
||||||
|
if(try_bind_descriptor())
|
||||||
|
vkCmdDispatch(cmd, command.data.dispatch.group_count_x, command.data.dispatch.group_count_y, command.data.dispatch.group_count_z);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1783,33 +1947,26 @@ void GFXVulkan::cacheDescriptorState(GFXVulkanPipeline* pipeline, VkDescriptorSe
|
||||||
|
|
||||||
VkDescriptorImageInfo imageInfo = {};
|
VkDescriptorImageInfo imageInfo = {};
|
||||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
imageInfo.imageView = vulkanTexture->view;
|
imageInfo.imageView = vulkanTexture->view;
|
||||||
imageInfo.sampler = vulkanTexture->sampler;
|
imageInfo.sampler = vulkanTexture->sampler;
|
||||||
|
|
||||||
//if (imageInfo.imageLayout != vulkanTexture->layout) {
|
|
||||||
GFXVulkanPipeline::ExpectedTransisition trans;
|
|
||||||
trans.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
trans.newLayout = imageInfo.imageLayout;
|
|
||||||
|
|
||||||
pipeline->expectedTransisitions[vulkanTexture] = trans;
|
|
||||||
//}
|
|
||||||
|
|
||||||
VkWriteDescriptorSet descriptorWrite = {};
|
VkWriteDescriptorSet descriptorWrite = {};
|
||||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
descriptorWrite.dstSet = descriptorSet;
|
descriptorWrite.dstSet = descriptorSet;
|
||||||
descriptorWrite.dstBinding = i;
|
descriptorWrite.dstBinding = i;
|
||||||
descriptorWrite.descriptorCount = 1;
|
descriptorWrite.descriptorCount = 1;
|
||||||
descriptorWrite.pImageInfo = &imageInfo;
|
|
||||||
|
|
||||||
if (utility::contains(pipeline->bindings_marked_as_storage_images, i)) {
|
if (utility::contains(pipeline->bindings_marked_as_storage_images, i)) {
|
||||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
} else if (utility::contains(pipeline->bindings_marked_as_sampled_images, i)) {
|
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
} else if (utility::contains(pipeline->bindings_marked_as_sampled_images, i)) {
|
||||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||||
} else {
|
} else {
|
||||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descriptorWrite.pImageInfo = &imageInfo;
|
||||||
|
|
||||||
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
|
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
@ -1905,6 +2062,12 @@ void GFXVulkan::inlineTransitionImageLayout(VkCommandBuffer commandBuffer, VkIma
|
||||||
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
break;
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_GENERAL:
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1916,6 +2079,9 @@ void GFXVulkan::inlineTransitionImageLayout(VkCommandBuffer commandBuffer, VkIma
|
||||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
break;
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_GENERAL:
|
||||||
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,4 @@ public:
|
||||||
|
|
||||||
// dynamic descriptor sets
|
// dynamic descriptor sets
|
||||||
std::map<uint64_t, VkDescriptorSet> cachedDescriptorSets;
|
std::map<uint64_t, VkDescriptorSet> cachedDescriptorSets;
|
||||||
|
|
||||||
struct ExpectedTransisition {
|
|
||||||
VkImageLayout oldLayout;
|
|
||||||
VkImageLayout newLayout;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<GFXVulkanTexture*, ExpectedTransisition> expectedTransisitions;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -180,7 +180,7 @@ void ImGuiPass::create_font_texture() {
|
||||||
createInfo.width = width;
|
createInfo.width = width;
|
||||||
createInfo.height = height;
|
createInfo.height = height;
|
||||||
createInfo.format = GFXPixelFormat::RGBA8_UNORM;
|
createInfo.format = GFXPixelFormat::RGBA8_UNORM;
|
||||||
createInfo.usage = GFXTextureUsage::Sampled;
|
createInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||||
|
|
||||||
font_texture = engine->get_gfx()->create_texture(createInfo);
|
font_texture = engine->get_gfx()->create_texture(createInfo);
|
||||||
engine->get_gfx()->copy_texture(font_texture, pixels, width * height * 4);
|
engine->get_gfx()->copy_texture(font_texture, pixels, width * height * 4);
|
||||||
|
|
|
@ -313,19 +313,12 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
||||||
|
|
||||||
if(render_options.enable_depth_of_field && dof_pass != nullptr)
|
if(render_options.enable_depth_of_field && dof_pass != nullptr)
|
||||||
dof_pass->render(commandbuffer, *scene);
|
dof_pass->render(commandbuffer, *scene);
|
||||||
|
|
||||||
beginInfo.framebuffer = nullptr;
|
|
||||||
beginInfo.render_pass = nullptr;
|
|
||||||
|
|
||||||
commandbuffer->set_render_pass(beginInfo);
|
|
||||||
|
|
||||||
Viewport viewport = {};
|
|
||||||
viewport.width = static_cast<float>(render_extent.width);
|
|
||||||
viewport.height = static_cast<float>(render_extent.height);
|
|
||||||
|
|
||||||
commandbuffer->set_viewport(viewport);
|
|
||||||
|
|
||||||
commandbuffer->push_group("Post Processing");
|
commandbuffer->push_group("Post Processing");
|
||||||
|
|
||||||
|
commandbuffer->end_render_pass();
|
||||||
|
|
||||||
|
// begin auto exposure
|
||||||
|
|
||||||
commandbuffer->set_compute_pipeline(histogram_pipeline);
|
commandbuffer->set_compute_pipeline(histogram_pipeline);
|
||||||
|
|
||||||
|
@ -357,6 +350,18 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
||||||
|
|
||||||
commandbuffer->dispatch(1, 1, 1);
|
commandbuffer->dispatch(1, 1, 1);
|
||||||
|
|
||||||
|
// continue post processing
|
||||||
|
beginInfo.framebuffer = nullptr;
|
||||||
|
beginInfo.render_pass = nullptr;
|
||||||
|
|
||||||
|
commandbuffer->set_render_pass(beginInfo);
|
||||||
|
|
||||||
|
Viewport viewport = {};
|
||||||
|
viewport.width = static_cast<float>(render_extent.width);
|
||||||
|
viewport.height = static_cast<float>(render_extent.height);
|
||||||
|
|
||||||
|
commandbuffer->set_viewport(viewport);
|
||||||
|
|
||||||
commandbuffer->set_graphics_pipeline(post_pipeline);
|
commandbuffer->set_graphics_pipeline(post_pipeline);
|
||||||
|
|
||||||
if(render_options.enable_depth_of_field)
|
if(render_options.enable_depth_of_field)
|
||||||
|
@ -770,7 +775,7 @@ void renderer::create_dummy_texture() {
|
||||||
createInfo.width = 1;
|
createInfo.width = 1;
|
||||||
createInfo.height = 1;
|
createInfo.height = 1;
|
||||||
createInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
createInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||||
createInfo.usage = GFXTextureUsage::Sampled;
|
createInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||||
|
|
||||||
dummy_texture = gfx->create_texture(createInfo);
|
dummy_texture = gfx->create_texture(createInfo);
|
||||||
|
|
||||||
|
@ -787,13 +792,14 @@ void renderer::create_render_target_resources(RenderTarget& target) {
|
||||||
textureInfo.width = extent.width;
|
textureInfo.width = extent.width;
|
||||||
textureInfo.height = extent.height;
|
textureInfo.height = extent.height;
|
||||||
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
||||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | GFXTextureUsage::Storage;
|
||||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
target.offscreenColorTexture = gfx->create_texture(textureInfo);
|
target.offscreenColorTexture = gfx->create_texture(textureInfo);
|
||||||
|
|
||||||
textureInfo.label = "Offscreen Depth";
|
textureInfo.label = "Offscreen Depth";
|
||||||
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||||
|
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||||
|
|
||||||
target.offscreenDepthTexture = gfx->create_texture(textureInfo);
|
target.offscreenDepthTexture = gfx->create_texture(textureInfo);
|
||||||
|
|
||||||
|
@ -874,7 +880,7 @@ void renderer::create_font_texture() {
|
||||||
textureInfo.width = font.width;
|
textureInfo.width = font.width;
|
||||||
textureInfo.height = font.height;
|
textureInfo.height = font.height;
|
||||||
textureInfo.format = GFXPixelFormat::R8_UNORM;
|
textureInfo.format = GFXPixelFormat::R8_UNORM;
|
||||||
textureInfo.usage = GFXTextureUsage::Sampled;
|
textureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||||
|
|
||||||
font_texture = gfx->create_texture(textureInfo);
|
font_texture = gfx->create_texture(textureInfo);
|
||||||
|
|
||||||
|
@ -1000,17 +1006,23 @@ void renderer::generate_brdf() {
|
||||||
|
|
||||||
void renderer::create_histogram_resources() {
|
void renderer::create_histogram_resources() {
|
||||||
GFXComputePipelineCreateInfo create_info = {};
|
GFXComputePipelineCreateInfo create_info = {};
|
||||||
create_info.shaders.compute_path = "histogram.comp";
|
create_info.compute_src = ShaderSource(file::Path("histogram.comp"));
|
||||||
create_info.workgroup_size_x = 16;
|
create_info.workgroup_size_x = 16;
|
||||||
create_info.workgroup_size_y = 16;
|
create_info.workgroup_size_y = 16;
|
||||||
|
|
||||||
create_info.shader_input.bindings = {
|
create_info.shader_input.bindings = {
|
||||||
|
{0, GFXBindingType::StorageImage},
|
||||||
|
{1, GFXBindingType::StorageBuffer},
|
||||||
{2, GFXBindingType::PushConstant}
|
{2, GFXBindingType::PushConstant}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
create_info.shader_input.push_constants = {
|
||||||
|
{sizeof(Vector4), 0}
|
||||||
|
};
|
||||||
|
|
||||||
histogram_pipeline = gfx->create_compute_pipeline(create_info);
|
histogram_pipeline = gfx->create_compute_pipeline(create_info);
|
||||||
|
|
||||||
create_info.shaders.compute_path = "histogram-average.comp";
|
create_info.compute_src = ShaderSource(file::Path("histogram-average.comp"));
|
||||||
create_info.workgroup_size_x = 256;
|
create_info.workgroup_size_x = 256;
|
||||||
create_info.workgroup_size_y = 1;
|
create_info.workgroup_size_y = 1;
|
||||||
|
|
||||||
|
@ -1023,7 +1035,7 @@ void renderer::create_histogram_resources() {
|
||||||
texture_info.width = 1;
|
texture_info.width = 1;
|
||||||
texture_info.height = 1;
|
texture_info.height = 1;
|
||||||
texture_info.format = GFXPixelFormat::R_16F;
|
texture_info.format = GFXPixelFormat::R_16F;
|
||||||
texture_info.usage = GFXTextureUsage::Sampled | GFXTextureUsage::ShaderWrite;
|
texture_info.usage = GFXTextureUsage::Sampled | GFXTextureUsage::ShaderWrite | GFXTextureUsage::Storage;
|
||||||
|
|
||||||
average_luminance_texture = gfx->create_texture(texture_info);
|
average_luminance_texture = gfx->create_texture(texture_info);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ SceneCapture::SceneCapture(GFX* gfx) {
|
||||||
textureInfo.width = scene_cubemap_resolution;
|
textureInfo.width = scene_cubemap_resolution;
|
||||||
textureInfo.height = scene_cubemap_resolution;
|
textureInfo.height = scene_cubemap_resolution;
|
||||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Transfer;
|
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc | GFXTextureUsage::Sampled;
|
||||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
offscreenTexture = gfx->create_texture(textureInfo);
|
offscreenTexture = gfx->create_texture(textureInfo);
|
||||||
|
@ -431,7 +431,7 @@ void SceneCapture::createIrradianceResources() {
|
||||||
textureInfo.width = irradiance_cubemap_resolution;
|
textureInfo.width = irradiance_cubemap_resolution;
|
||||||
textureInfo.height = irradiance_cubemap_resolution;
|
textureInfo.height = irradiance_cubemap_resolution;
|
||||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Transfer;
|
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc;
|
||||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
irradianceOffscreenTexture = gfx->create_texture(textureInfo);
|
irradianceOffscreenTexture = gfx->create_texture(textureInfo);
|
||||||
|
@ -486,7 +486,7 @@ void SceneCapture::createPrefilterResources() {
|
||||||
textureInfo.width = scene_cubemap_resolution;
|
textureInfo.width = scene_cubemap_resolution;
|
||||||
textureInfo.height = scene_cubemap_resolution;
|
textureInfo.height = scene_cubemap_resolution;
|
||||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Transfer;
|
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc;
|
||||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
prefilteredOffscreenTexture = gfx->create_texture(textureInfo);
|
prefilteredOffscreenTexture = gfx->create_texture(textureInfo);
|
||||||
|
|
|
@ -381,9 +381,9 @@ void ShadowPass::create_offscreen_resources() {
|
||||||
textureInfo.width = render_options.shadow_resolution;
|
textureInfo.width = render_options.shadow_resolution;
|
||||||
textureInfo.height = render_options.shadow_resolution;
|
textureInfo.height = render_options.shadow_resolution;
|
||||||
textureInfo.format = GFXPixelFormat::R_32F;
|
textureInfo.format = GFXPixelFormat::R_32F;
|
||||||
textureInfo.usage = GFXTextureUsage::Attachment;
|
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
offscreen_color_texture = gfx->create_texture(textureInfo);
|
offscreen_color_texture = gfx->create_texture(textureInfo);
|
||||||
|
|
||||||
GFXTextureCreateInfo depthTextureInfo = {};
|
GFXTextureCreateInfo depthTextureInfo = {};
|
||||||
|
@ -391,7 +391,7 @@ void ShadowPass::create_offscreen_resources() {
|
||||||
depthTextureInfo.width = render_options.shadow_resolution;
|
depthTextureInfo.width = render_options.shadow_resolution;
|
||||||
depthTextureInfo.height = render_options.shadow_resolution;
|
depthTextureInfo.height = render_options.shadow_resolution;
|
||||||
depthTextureInfo.format = GFXPixelFormat::DEPTH_32F;
|
depthTextureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||||
depthTextureInfo.usage = GFXTextureUsage::Attachment;
|
depthTextureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||||
depthTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
depthTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
offscreen_depth = gfx->create_texture(depthTextureInfo);
|
offscreen_depth = gfx->create_texture(depthTextureInfo);
|
||||||
|
|
|
@ -102,7 +102,7 @@ void SMAAPass::create_textures() {
|
||||||
areaInfo.width = AREATEX_WIDTH;
|
areaInfo.width = AREATEX_WIDTH;
|
||||||
areaInfo.height = AREATEX_HEIGHT;
|
areaInfo.height = AREATEX_HEIGHT;
|
||||||
areaInfo.format = GFXPixelFormat::R8G8_UNORM;
|
areaInfo.format = GFXPixelFormat::R8G8_UNORM;
|
||||||
areaInfo.usage = GFXTextureUsage::Sampled;
|
areaInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||||
areaInfo.samplingMode = SamplingMode::ClampToEdge;
|
areaInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
area_image = gfx->create_texture(areaInfo);
|
area_image = gfx->create_texture(areaInfo);
|
||||||
|
@ -115,7 +115,7 @@ void SMAAPass::create_textures() {
|
||||||
searchInfo.width = SEARCHTEX_WIDTH;
|
searchInfo.width = SEARCHTEX_WIDTH;
|
||||||
searchInfo.height = SEARCHTEX_HEIGHT;
|
searchInfo.height = SEARCHTEX_HEIGHT;
|
||||||
searchInfo.format = GFXPixelFormat::R8_UNORM;
|
searchInfo.format = GFXPixelFormat::R8_UNORM;
|
||||||
searchInfo.usage = GFXTextureUsage::Sampled;
|
searchInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||||
searchInfo.samplingMode = SamplingMode::ClampToEdge;
|
searchInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||||
|
|
||||||
search_image = gfx->create_texture(searchInfo);
|
search_image = gfx->create_texture(searchInfo);
|
||||||
|
|
Reference in a new issue