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 {
|
||||
Sampled = 1,
|
||||
Attachment = 2,
|
||||
ShaderWrite = 3,
|
||||
Transfer = 4
|
||||
Sampled = 0,
|
||||
Attachment = 1,
|
||||
ShaderWrite = 2,
|
||||
TransferSrc = 4,
|
||||
TransferDst = 8,
|
||||
Storage = 16
|
||||
};
|
||||
|
||||
inline GFXTextureUsage operator|(const GFXTextureUsage a, const GFXTextureUsage b) {
|
||||
|
@ -201,10 +203,7 @@ struct GFXGraphicsPipelineCreateInfo {
|
|||
struct GFXComputePipelineCreateInfo {
|
||||
std::string label; // only used for debug
|
||||
|
||||
struct Shaders {
|
||||
std::string_view compute_path;
|
||||
ShaderSource compute_src;
|
||||
} shaders;
|
||||
ShaderSource compute_src;
|
||||
|
||||
struct ShaderBindings {
|
||||
std::vector<GFXPushConstant> push_constants;
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
|
||||
// pipeline operations
|
||||
GFXPipeline* create_graphics_pipeline(const GFXGraphicsPipelineCreateInfo& info) override;
|
||||
GFXPipeline* create_compute_pipeline(const GFXComputePipelineCreateInfo& info) override;
|
||||
|
||||
// misc operations
|
||||
GFXSize get_alignment(const GFXSize size) override;
|
||||
|
|
|
@ -341,21 +341,31 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
|
|||
VkImageTiling imageTiling;
|
||||
imageTiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
|
||||
VkImageUsageFlags imageUsage = 0;
|
||||
if ((info.usage & GFXTextureUsage::Attachment) == GFXTextureUsage::Attachment) {
|
||||
if (info.format == GFXPixelFormat::DEPTH_32F) {
|
||||
imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
}
|
||||
else {
|
||||
imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
}
|
||||
const auto check_flag = [](const GFXTextureUsage usage, const GFXTextureUsage flag) {
|
||||
return (usage & flag) == flag;
|
||||
};
|
||||
|
||||
if((info.usage & GFXTextureUsage::Transfer) == GFXTextureUsage::Transfer)
|
||||
imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
VkImageUsageFlags imageUsage = 0;
|
||||
if(check_flag(info.usage, GFXTextureUsage::Attachment)) {
|
||||
if (info.format == GFXPixelFormat::DEPTH_32F) {
|
||||
imageUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
else {
|
||||
imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_flag(info.usage, GFXTextureUsage::Sampled))
|
||||
imageUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
|
||||
if(check_flag(info.usage, GFXTextureUsage::TransferSrc))
|
||||
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;
|
||||
if (info.format == GFXPixelFormat::DEPTH_32F)
|
||||
|
@ -396,7 +406,20 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
|
|||
texture->height = info.height;
|
||||
texture->format = imageFormat;
|
||||
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
|
||||
VkMemoryRequirements memRequirements;
|
||||
|
@ -420,7 +443,7 @@ GFXTexture* GFXVulkan::create_texture(const GFXTextureCreateInfo& info) {
|
|||
|
||||
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
|
||||
VkImageViewCreateInfo viewInfo = {};
|
||||
|
@ -997,6 +1020,121 @@ GFXPipeline* GFXVulkan::create_graphics_pipeline(const GFXGraphicsPipelineCreate
|
|||
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) {
|
||||
VkPhysicalDeviceProperties properties;
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &properties);
|
||||
|
@ -1057,8 +1195,9 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
|||
VkRenderPass currentRenderPass = VK_NULL_HANDLE;
|
||||
GFXVulkanPipeline* currentPipeline = nullptr;
|
||||
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)
|
||||
return false;
|
||||
|
||||
|
@ -1070,7 +1209,7 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
|||
if (descriptor_set == VK_NULL_HANDLE)
|
||||
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);
|
||||
}
|
||||
|
@ -1174,8 +1313,23 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
|||
resetDescriptorState();
|
||||
lastDescriptorHash = 0;
|
||||
}
|
||||
|
||||
is_compute = false;
|
||||
}
|
||||
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:
|
||||
{
|
||||
VkBuffer buffer = ((GFXVulkanBuffer*)command.data.set_vertex_buffer.buffer)->handle;
|
||||
|
@ -1194,8 +1348,12 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
|||
break;
|
||||
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)
|
||||
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;
|
||||
case GFXCommandType::BindShaderBuffer:
|
||||
|
@ -1297,6 +1455,12 @@ void GFXVulkan::submit(GFXCommandBuffer* command_buffer, const int identifier) {
|
|||
}
|
||||
}
|
||||
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 = {};
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
imageInfo.imageView = vulkanTexture->view;
|
||||
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 = {};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = descriptorSet;
|
||||
descriptorWrite.dstBinding = i;
|
||||
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)) {
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
} 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;
|
||||
}
|
||||
|
||||
descriptorWrite.pImageInfo = &imageInfo;
|
||||
|
||||
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
|
||||
|
||||
i++;
|
||||
|
@ -1905,6 +2062,12 @@ void GFXVulkan::inlineTransitionImageLayout(VkCommandBuffer commandBuffer, VkIma
|
|||
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -1916,6 +2079,9 @@ void GFXVulkan::inlineTransitionImageLayout(VkCommandBuffer commandBuffer, VkIma
|
|||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
break;
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,4 @@ public:
|
|||
|
||||
// dynamic descriptor sets
|
||||
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.height = height;
|
||||
createInfo.format = GFXPixelFormat::RGBA8_UNORM;
|
||||
createInfo.usage = GFXTextureUsage::Sampled;
|
||||
createInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||
|
||||
font_texture = engine->get_gfx()->create_texture(createInfo);
|
||||
engine->get_gfx()->copy_texture(font_texture, pixels, width * height * 4);
|
||||
|
|
|
@ -314,19 +314,12 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
if(render_options.enable_depth_of_field && dof_pass != nullptr)
|
||||
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->end_render_pass();
|
||||
|
||||
// begin auto exposure
|
||||
|
||||
commandbuffer->set_compute_pipeline(histogram_pipeline);
|
||||
|
||||
commandbuffer->bind_texture(target.offscreenColorTexture, 0);
|
||||
|
@ -357,6 +350,18 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
|
||||
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);
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
|
@ -770,7 +775,7 @@ void renderer::create_dummy_texture() {
|
|||
createInfo.width = 1;
|
||||
createInfo.height = 1;
|
||||
createInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
createInfo.usage = GFXTextureUsage::Sampled;
|
||||
createInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||
|
||||
dummy_texture = gfx->create_texture(createInfo);
|
||||
|
||||
|
@ -787,13 +792,14 @@ void renderer::create_render_target_resources(RenderTarget& target) {
|
|||
textureInfo.width = extent.width;
|
||||
textureInfo.height = extent.height;
|
||||
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | GFXTextureUsage::Storage;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
target.offscreenColorTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
textureInfo.label = "Offscreen Depth";
|
||||
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
|
||||
target.offscreenDepthTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
@ -874,7 +880,7 @@ void renderer::create_font_texture() {
|
|||
textureInfo.width = font.width;
|
||||
textureInfo.height = font.height;
|
||||
textureInfo.format = GFXPixelFormat::R8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Sampled;
|
||||
textureInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||
|
||||
font_texture = gfx->create_texture(textureInfo);
|
||||
|
||||
|
@ -1000,17 +1006,23 @@ void renderer::generate_brdf() {
|
|||
|
||||
void renderer::create_histogram_resources() {
|
||||
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_y = 16;
|
||||
|
||||
create_info.shader_input.bindings = {
|
||||
{0, GFXBindingType::StorageImage},
|
||||
{1, GFXBindingType::StorageBuffer},
|
||||
{2, GFXBindingType::PushConstant}
|
||||
};
|
||||
|
||||
create_info.shader_input.push_constants = {
|
||||
{sizeof(Vector4), 0}
|
||||
};
|
||||
|
||||
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_y = 1;
|
||||
|
||||
|
@ -1023,7 +1035,7 @@ void renderer::create_histogram_resources() {
|
|||
texture_info.width = 1;
|
||||
texture_info.height = 1;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ SceneCapture::SceneCapture(GFX* gfx) {
|
|||
textureInfo.width = scene_cubemap_resolution;
|
||||
textureInfo.height = scene_cubemap_resolution;
|
||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Transfer;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc | GFXTextureUsage::Sampled;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
offscreenTexture = gfx->create_texture(textureInfo);
|
||||
|
@ -431,7 +431,7 @@ void SceneCapture::createIrradianceResources() {
|
|||
textureInfo.width = irradiance_cubemap_resolution;
|
||||
textureInfo.height = irradiance_cubemap_resolution;
|
||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Transfer;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
irradianceOffscreenTexture = gfx->create_texture(textureInfo);
|
||||
|
@ -486,7 +486,7 @@ void SceneCapture::createPrefilterResources() {
|
|||
textureInfo.width = scene_cubemap_resolution;
|
||||
textureInfo.height = scene_cubemap_resolution;
|
||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Transfer;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::TransferSrc;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
prefilteredOffscreenTexture = gfx->create_texture(textureInfo);
|
||||
|
|
|
@ -381,7 +381,7 @@ void ShadowPass::create_offscreen_resources() {
|
|||
textureInfo.width = render_options.shadow_resolution;
|
||||
textureInfo.height = render_options.shadow_resolution;
|
||||
textureInfo.format = GFXPixelFormat::R_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
offscreen_color_texture = gfx->create_texture(textureInfo);
|
||||
|
@ -391,7 +391,7 @@ void ShadowPass::create_offscreen_resources() {
|
|||
depthTextureInfo.width = render_options.shadow_resolution;
|
||||
depthTextureInfo.height = render_options.shadow_resolution;
|
||||
depthTextureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||
depthTextureInfo.usage = GFXTextureUsage::Attachment;
|
||||
depthTextureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
depthTextureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
offscreen_depth = gfx->create_texture(depthTextureInfo);
|
||||
|
|
|
@ -102,7 +102,7 @@ void SMAAPass::create_textures() {
|
|||
areaInfo.width = AREATEX_WIDTH;
|
||||
areaInfo.height = AREATEX_HEIGHT;
|
||||
areaInfo.format = GFXPixelFormat::R8G8_UNORM;
|
||||
areaInfo.usage = GFXTextureUsage::Sampled;
|
||||
areaInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||
areaInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
area_image = gfx->create_texture(areaInfo);
|
||||
|
@ -115,7 +115,7 @@ void SMAAPass::create_textures() {
|
|||
searchInfo.width = SEARCHTEX_WIDTH;
|
||||
searchInfo.height = SEARCHTEX_HEIGHT;
|
||||
searchInfo.format = GFXPixelFormat::R8_UNORM;
|
||||
searchInfo.usage = GFXTextureUsage::Sampled;
|
||||
searchInfo.usage = GFXTextureUsage::Sampled | GFXTextureUsage::TransferDst;
|
||||
searchInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
search_image = gfx->create_texture(searchInfo);
|
||||
|
|
Reference in a new issue