Archived
1
Fork 0

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:
redstrate 2021-05-11 19:16:54 -04:00
parent 0d75b4f47e
commit ee2771f45f
9 changed files with 244 additions and 73 deletions

View file

@ -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) {
@ -201,10 +203,7 @@ 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;

View file

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

View file

@ -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;
VkImageUsageFlags imageUsage = 0; const auto check_flag = [](const GFXTextureUsage usage, const GFXTextureUsage flag) {
if ((info.usage & GFXTextureUsage::Attachment) == GFXTextureUsage::Attachment) { return (usage & flag) == flag;
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;
}
if((info.usage & GFXTextureUsage::Transfer) == GFXTextureUsage::Transfer) VkImageUsageFlags imageUsage = 0;
imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 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; 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, &currentPipeline, &lastDescriptorHash]() -> bool { const auto try_bind_descriptor = [cmd, this, &currentPipeline, &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;
} }

View file

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

View file

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

View file

@ -314,19 +314,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);
commandbuffer->bind_texture(target.offscreenColorTexture, 0); commandbuffer->bind_texture(target.offscreenColorTexture, 0);
@ -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);
} }

View file

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

View file

@ -381,7 +381,7 @@ 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);
@ -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);

View file

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