diff options
author | dan sinclair <dj2@everburning.com> | 2019-03-07 18:04:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-07 18:04:37 -0500 |
commit | d9e823e5ab380fcf417452581721ad9c3bdcf60b (patch) | |
tree | 55a555e7e08ac044abbc230e904b7369ef8ce6ca /src | |
parent | 0d744484eba498e30ad02cfb91b35426df470ece (diff) | |
download | amber-d9e823e5ab380fcf417452581721ad9c3bdcf60b.tar.gz |
[vulkan] Support multiple colour attachments. (#340)
This CL updates the vulkan engine to allow having multiple image
attachments. Currently the frontend code just works with the first image
attachment.
Diffstat (limited to 'src')
-rw-r--r-- | src/amber.cc | 4 | ||||
-rw-r--r-- | src/dawn/engine_dawn.cc | 4 | ||||
-rw-r--r-- | src/dawn/engine_dawn.h | 8 | ||||
-rw-r--r-- | src/engine.h | 5 | ||||
-rw-r--r-- | src/executor.cc | 2 | ||||
-rw-r--r-- | src/executor_test.cc | 8 | ||||
-rw-r--r-- | src/pipeline.cc | 5 | ||||
-rw-r--r-- | src/vulkan/engine_vulkan.cc | 32 | ||||
-rw-r--r-- | src/vulkan/engine_vulkan.h | 3 | ||||
-rw-r--r-- | src/vulkan/frame_buffer.cc | 63 | ||||
-rw-r--r-- | src/vulkan/frame_buffer.h | 26 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.cc | 98 | ||||
-rw-r--r-- | src/vulkan/graphics_pipeline.h | 22 |
13 files changed, 150 insertions, 130 deletions
diff --git a/src/amber.cc b/src/amber.cc index 746f3ea..4b4da3f 100644 --- a/src/amber.cc +++ b/src/amber.cc @@ -131,13 +131,13 @@ amber::Result Amber::ExecuteWithShaderData(const amber::Recipe* recipe, for (BufferInfo& buffer_info : opts->extractions) { if (buffer_info.buffer_name == "framebuffer") { ResourceInfo info; - r = engine->GetFrameBufferInfo(pipeline, &info); + r = engine->GetFrameBufferInfo(pipeline, 0, &info); if (!r.IsSuccess()) break; buffer_info.width = info.image_info.width; buffer_info.height = info.image_info.height; - r = engine->GetFrameBuffer(pipeline, &(buffer_info.values)); + r = engine->GetFrameBuffer(pipeline, 0, &(buffer_info.values)); if (!r.IsSuccess()) break; diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index 1e47b02..b6f3773 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -448,7 +448,7 @@ Result EngineDawn::CreateFramebufferIfNeeded() { return {}; } -Result EngineDawn::GetFrameBufferInfo(Pipeline*, ResourceInfo* info) { +Result EngineDawn::GetFrameBufferInfo(Pipeline*, size_t, ResourceInfo* info) { assert(info); if (render_pipeline_info_.fb_data == nullptr) @@ -466,7 +466,7 @@ Result EngineDawn::GetFrameBufferInfo(Pipeline*, ResourceInfo* info) { return {}; } -Result EngineDawn::GetFrameBuffer(Pipeline*, std::vector<Value>*) { +Result EngineDawn::GetFrameBuffer(Pipeline*, size_t, std::vector<Value>*) { return Result("Dawn::GetFrameBuffer not implemented"); } diff --git a/src/dawn/engine_dawn.h b/src/dawn/engine_dawn.h index e115ac6..93e27af 100644 --- a/src/dawn/engine_dawn.h +++ b/src/dawn/engine_dawn.h @@ -60,8 +60,12 @@ class EngineDawn : public Engine { const PatchParameterVerticesCommand* cmd) override; Result DoBuffer(const BufferCommand* cmd) override; Result DoProcessCommands(Pipeline*) override; - Result GetFrameBufferInfo(Pipeline*, ResourceInfo* info) override; - Result GetFrameBuffer(Pipeline*, std::vector<Value>* values) override; + Result GetFrameBufferInfo(Pipeline*, + size_t attachment_idx, + ResourceInfo* info) override; + Result GetFrameBuffer(Pipeline*, + size_t attachment_idx, + std::vector<Value>* values) override; Result GetDescriptorInfo(Pipeline*, const uint32_t descriptor_set, const uint32_t binding, diff --git a/src/engine.h b/src/engine.h index 6b46c6e..5eea840 100644 --- a/src/engine.h +++ b/src/engine.h @@ -137,11 +137,14 @@ class Engine { /// the host address space. In particular, if we have run /// DoProcessCommands() and since then no graphics pipeline drawing /// commands have occurred e.g., DoClear, DoDrawArrays, DoDrawRect. - virtual Result GetFrameBufferInfo(Pipeline* pipeline, ResourceInfo* info) = 0; + virtual Result GetFrameBufferInfo(Pipeline* pipeline, + size_t attachment_idx, + ResourceInfo* info) = 0; /// Copy the content of the framebuffer into |values|, each value is a pixel /// in R8G8B8A8 format. virtual Result GetFrameBuffer(Pipeline* pipeline, + size_t attachment_idx, std::vector<Value>* values) = 0; /// Copy the contents of the resource bound to the given descriptor diff --git a/src/executor.cc b/src/executor.cc index 4823d6d..e5aba7d 100644 --- a/src/executor.cc +++ b/src/executor.cc @@ -80,7 +80,7 @@ Result Executor::Execute(Engine* engine, // This must come after processing commands because we require // the framebuffer data to be mapped into host memory and have // a valid host-side pointer. - r = engine->GetFrameBufferInfo(cmd->GetPipeline(), &info); + r = engine->GetFrameBufferInfo(cmd->GetPipeline(), 0, &info); if (!r.IsSuccess()) return r; assert(info.cpu_memory != nullptr); diff --git a/src/executor_test.cc b/src/executor_test.cc index f588c1b..e198bb5 100644 --- a/src/executor_test.cc +++ b/src/executor_test.cc @@ -160,8 +160,12 @@ class EngineStub : public Engine { } Result DoProcessCommands(Pipeline*) override { return {}; } - Result GetFrameBufferInfo(Pipeline*, ResourceInfo*) override { return {}; } - Result GetFrameBuffer(Pipeline*, std::vector<Value>*) override { return {}; } + Result GetFrameBufferInfo(Pipeline*, size_t, ResourceInfo*) override { + return {}; + } + Result GetFrameBuffer(Pipeline*, size_t, std::vector<Value>*) override { + return {}; + } Result GetDescriptorInfo(Pipeline*, const uint32_t, const uint32_t, diff --git a/src/pipeline.cc b/src/pipeline.cc index 3cae869..d45dc05 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -125,9 +125,6 @@ Result Pipeline::SetShaderType(const Shader* shader, ShaderType type) { } Result Pipeline::Validate() const { - if (color_attachments_.empty()) - return Result("PIPELINE missing color attachment"); - size_t fb_size = fb_width_ * fb_height_; for (const auto& attachment : color_attachments_) { if (attachment.buffer->GetSize() != fb_size) { @@ -147,6 +144,8 @@ Result Pipeline::Validate() const { } Result Pipeline::ValidateGraphics() const { + if (color_attachments_.empty()) + return Result("PIPELINE missing color attachment"); if (shaders_.empty()) return Result("graphics pipeline requires vertex and fragment shaders"); diff --git a/src/vulkan/engine_vulkan.cc b/src/vulkan/engine_vulkan.cc index 1321e31..85d569e 100644 --- a/src/vulkan/engine_vulkan.cc +++ b/src/vulkan/engine_vulkan.cc @@ -158,17 +158,6 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) { pipeline_map_[pipeline] = PipelineInfo(); auto& info = pipeline_map_[pipeline]; - // Set VK_FORMAT_B8G8R8A8_UNORM for color frame buffer by default. - info.color_frame_format.SetFormatType(kDefaultFramebufferFormat); - info.color_frame_format.AddComponent(FormatComponentType::kB, - FormatMode::kUNorm, 8); - info.color_frame_format.AddComponent(FormatComponentType::kG, - FormatMode::kUNorm, 8); - info.color_frame_format.AddComponent(FormatComponentType::kR, - FormatMode::kUNorm, 8); - info.color_frame_format.AddComponent(FormatComponentType::kA, - FormatMode::kUNorm, 8); - for (const auto& shader_info : pipeline->GetShaders()) { Result r = SetShader(pipeline, shader_info.GetShaderType(), shader_info.GetData()); @@ -178,7 +167,6 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) { for (const auto& colour_info : pipeline->GetColorAttachments()) { auto& fmt = colour_info.buffer->AsFormatBuffer()->GetFormat(); - info.color_frame_format = fmt; if (!VerifyFormatAvailable(fmt, colour_info.type)) return Result("Vulkan color attachment format is not supported"); } @@ -207,8 +195,7 @@ Result EngineVulkan::CreatePipeline(amber::Pipeline* pipeline) { } else { vk_pipeline = MakeUnique<GraphicsPipeline>( device_.get(), device_->GetPhysicalDeviceProperties(), - device_->GetPhysicalMemoryProperties(), - ToVkFormat(info.color_frame_format.GetFormatType()), + device_->GetPhysicalMemoryProperties(), pipeline->GetColorAttachments(), ToVkFormat(depth_buffer_format), engine_data.fence_timeout_ms, GetShaderStageInfo(pipeline)); @@ -423,50 +410,55 @@ Result EngineVulkan::DoProcessCommands(amber::Pipeline* pipeline) { } Result EngineVulkan::GetFrameBufferInfo(amber::Pipeline* pipeline, + size_t attachment_idx, ResourceInfo* resource_info) { if (!resource_info) return Result("Vulkan::GetFrameBufferInfo missing resource info"); auto& info = pipeline_map_[pipeline]; if (!info.vk_pipeline) - return Result("Vulkan::GetFrameBufferIfno missing pipeline"); + return Result("Vulkan::GetFrameBufferInfo missing pipeline"); if (!info.vk_pipeline->IsGraphics()) return Result("Vulkan::GetFrameBufferInfo for Non-Graphics Pipeline"); const auto graphics = info.vk_pipeline->AsGraphics(); const auto frame = graphics->GetFrame(); - const auto bytes_per_texel = info.color_frame_format.GetByteSize(); + const auto& fmt = frame->GetFormatForAttachment(attachment_idx); + const auto bytes_per_texel = fmt.GetByteSize(); resource_info->type = ResourceInfoType::kImage; resource_info->image_info.width = frame->GetWidth(); resource_info->image_info.height = frame->GetHeight(); resource_info->image_info.depth = 1U; resource_info->image_info.texel_stride = bytes_per_texel; - resource_info->image_info.texel_format = &info.color_frame_format; + resource_info->image_info.texel_format = &fmt; // When copying the image to the host buffer, we specify a row length of 0 // which results in tight packing of rows. So the row stride is the product // of the texel stride and the number of texels in a row. const auto row_stride = bytes_per_texel * frame->GetWidth(); resource_info->image_info.row_stride = row_stride; resource_info->size_in_bytes = row_stride * frame->GetHeight(); - resource_info->cpu_memory = frame->GetColorBufferPtr(); + resource_info->cpu_memory = frame->GetColorBufferPtr(attachment_idx); return {}; } Result EngineVulkan::GetFrameBuffer(amber::Pipeline* pipeline, + size_t attachment_idx, std::vector<Value>* values) { values->resize(0); ResourceInfo resource_info; - GetFrameBufferInfo(pipeline, &resource_info); + GetFrameBufferInfo(pipeline, attachment_idx, &resource_info); if (resource_info.type != ResourceInfoType::kImage) { return Result( "Vulkan:GetFrameBuffer() is invalid for non-image framebuffer"); } auto& info = pipeline_map_[pipeline]; + const auto frame = info.vk_pipeline->AsGraphics()->GetFrame(); + const auto& fmt = frame->GetFormatForAttachment(attachment_idx); // TODO(jaebaek): Support other formats - if (info.color_frame_format.GetFormatType() != kDefaultFramebufferFormat) + if (fmt.GetFormatType() != kDefaultFramebufferFormat) return Result("Vulkan::GetFrameBuffer Unsupported buffer format"); Value pixel; diff --git a/src/vulkan/engine_vulkan.h b/src/vulkan/engine_vulkan.h index 5af738a..e6bd079 100644 --- a/src/vulkan/engine_vulkan.h +++ b/src/vulkan/engine_vulkan.h @@ -59,8 +59,10 @@ class EngineVulkan : public Engine { Result DoBuffer(const BufferCommand* cmd) override; Result DoProcessCommands(amber::Pipeline* pipeline) override; Result GetFrameBufferInfo(amber::Pipeline* pipeline, + size_t attachment_idx, ResourceInfo* info) override; Result GetFrameBuffer(amber::Pipeline* pipeline, + size_t attachment_idx, std::vector<Value>* values) override; Result GetDescriptorInfo(amber::Pipeline* pipeline, const uint32_t descriptor_set, @@ -73,7 +75,6 @@ class EngineVulkan : public Engine { std::unique_ptr<VertexBuffer> vertex_buffer; std::unordered_map<ShaderType, VkShaderModule, CastHash<ShaderType>> shaders; - Format color_frame_format; }; std::vector<VkPipelineShaderStageCreateInfo> GetShaderStageInfo( diff --git a/src/vulkan/frame_buffer.cc b/src/vulkan/frame_buffer.cc index a3d3039..f32f0e3 100644 --- a/src/vulkan/frame_buffer.cc +++ b/src/vulkan/frame_buffer.cc @@ -26,27 +26,36 @@ namespace amber { namespace vulkan { -FrameBuffer::FrameBuffer(Device* device, uint32_t width, uint32_t height) - : device_(device), width_(width), height_(height) {} +FrameBuffer::FrameBuffer( + Device* device, + const std::vector<const amber::Pipeline::BufferInfo*>& color_attachments, + uint32_t width, + uint32_t height) + : device_(device), + color_attachments_(color_attachments), + width_(width), + height_(height) {} FrameBuffer::~FrameBuffer() = default; Result FrameBuffer::Initialize( VkRenderPass render_pass, - VkFormat color_format, VkFormat depth_format, const VkPhysicalDeviceMemoryProperties& properties) { std::vector<VkImageView> attachments; - if (color_format != VK_FORMAT_UNDEFINED) { - color_image_ = - MakeUnique<Image>(device_, color_format, VK_IMAGE_ASPECT_COLOR_BIT, - width_, height_, depth_, properties); - Result r = color_image_->Initialize(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + for (auto* info : color_attachments_) { + color_images_.push_back(MakeUnique<Image>( + device_, + ToVkFormat(info->buffer->AsFormatBuffer()->GetFormat().GetFormatType()), + VK_IMAGE_ASPECT_COLOR_BIT, width_, height_, depth_, properties)); + + Result r = color_images_.back()->Initialize( + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); if (!r.IsSuccess()) return r; - attachments.push_back(color_image_->GetVkImageView()); + + attachments.push_back(color_images_.back()->GetVkImageView()); } if (depth_format != VK_FORMAT_UNDEFINED) { @@ -57,6 +66,7 @@ Result FrameBuffer::Initialize( ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT), width_, height_, depth_, properties); + Result r = depth_image_->Initialize(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); @@ -100,12 +110,11 @@ Result FrameBuffer::ChangeFrameImageLayout(CommandBuffer* command, "from kInit"); } - if (color_image_) { - color_image_->ChangeLayout(command, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT); + for (auto& img : color_images_) { + img->ChangeLayout(command, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT); } if (depth_image_) { depth_image_->ChangeLayout( @@ -128,10 +137,10 @@ Result FrameBuffer::ChangeFrameImageLayout(CommandBuffer* command, ? VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT : VK_PIPELINE_STAGE_TRANSFER_BIT; - if (color_image_) { - color_image_->ChangeLayout( - command, old_layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - source_stage, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + for (auto& img : color_images_) { + img->ChangeLayout(command, old_layout, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, source_stage, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); } if (depth_image_) { depth_image_->ChangeLayout( @@ -148,12 +157,22 @@ void FrameBuffer::Shutdown() { nullptr); } - if (color_image_) - color_image_->Shutdown(); + for (auto& img : color_images_) + img->Shutdown(); if (depth_image_) depth_image_->Shutdown(); } +Result FrameBuffer::CopyColorImagesToHost(CommandBuffer* command) { + for (auto& img : color_images_) { + ChangeFrameImageLayout(command, FrameImageState::kProbe); + Result r = img->CopyToHost(command); + if (!r.IsSuccess()) + return r; + } + return {}; +} + } // namespace vulkan } // namespace amber diff --git a/src/vulkan/frame_buffer.h b/src/vulkan/frame_buffer.h index d4c2b2f..f420ea6 100644 --- a/src/vulkan/frame_buffer.h +++ b/src/vulkan/frame_buffer.h @@ -16,7 +16,9 @@ #define SRC_VULKAN_FRAME_BUFFER_H_ #include <memory> +#include <vector> +#include "src/pipeline.h" #include "src/vulkan/image.h" namespace amber { @@ -33,11 +35,14 @@ class Device; class FrameBuffer { public: - FrameBuffer(Device* device, uint32_t width, uint32_t height); + FrameBuffer( + Device* device, + const std::vector<const amber::Pipeline::BufferInfo*>& color_attachments, + uint32_t width, + uint32_t height); ~FrameBuffer(); Result Initialize(VkRenderPass render_pass, - VkFormat color_format, VkFormat depth_format, const VkPhysicalDeviceMemoryProperties& properties); void Shutdown(); @@ -45,26 +50,27 @@ class FrameBuffer { Result ChangeFrameImageLayout(CommandBuffer* command, FrameImageState layout); VkFramebuffer GetFrameBuffer() const { return frame_; } - const void* GetColorBufferPtr() const { - return color_image_->HostAccessibleMemoryPtr(); + const void* GetColorBufferPtr(size_t idx) const { + return color_images_[idx]->HostAccessibleMemoryPtr(); + } + + const Format& GetFormatForAttachment(size_t idx) const { + return color_attachments_[idx]->buffer->AsFormatBuffer()->GetFormat(); } - VkImage GetColorImage() const { return color_image_->GetVkImage(); } // Only record the command for copying the image that backs this // framebuffer to the host accessible buffer. The actual submission // of the command must be done later. - Result CopyColorImageToHost(CommandBuffer* command) { - ChangeFrameImageLayout(command, FrameImageState::kProbe); - return color_image_->CopyToHost(command); - } + Result CopyColorImagesToHost(CommandBuffer* command); uint32_t GetWidth() const { return width_; } uint32_t GetHeight() const { return height_; } private: Device* device_ = nullptr; + std::vector<const amber::Pipeline::BufferInfo*> color_attachments_; VkFramebuffer frame_ = VK_NULL_HANDLE; - std::unique_ptr<Image> color_image_; + std::vector<std::unique_ptr<Image>> color_images_; std::unique_ptr<Image> depth_image_; uint32_t width_ = 0; uint32_t height_ = 0; diff --git a/src/vulkan/graphics_pipeline.cc b/src/vulkan/graphics_pipeline.cc index 2a68978..1a36f86 100644 --- a/src/vulkan/graphics_pipeline.cc +++ b/src/vulkan/graphics_pipeline.cc @@ -352,7 +352,7 @@ GraphicsPipeline::GraphicsPipeline( Device* device, const VkPhysicalDeviceProperties& properties, const VkPhysicalDeviceMemoryProperties& memory_properties, - VkFormat color_format, + const std::vector<amber::Pipeline::BufferInfo>& color_buffers, VkFormat depth_stencil_format, uint32_t fence_timeout_ms, const std::vector<VkPipelineShaderStageCreateInfo>& shader_stage_info) @@ -362,8 +362,10 @@ GraphicsPipeline::GraphicsPipeline( memory_properties, fence_timeout_ms, shader_stage_info), - color_format_(color_format), - depth_stencil_format_(depth_stencil_format) {} + depth_stencil_format_(depth_stencil_format) { + for (const auto& info : color_buffers) + color_buffers_.push_back(&info); +} GraphicsPipeline::~GraphicsPipeline() = default; @@ -373,22 +375,26 @@ Result GraphicsPipeline::CreateRenderPass() { std::vector<VkAttachmentDescription> attachment_desc; - VkAttachmentReference color_refer = VkAttachmentReference(); + std::vector<VkAttachmentReference> color_refer; VkAttachmentReference depth_refer = VkAttachmentReference(); - if (color_format_ != VK_FORMAT_UNDEFINED) { + for (const auto* info : color_buffers_) { attachment_desc.push_back(kDefaultAttachmentDesc); - attachment_desc.back().format = color_format_; + attachment_desc.back().format = + ToVkFormat(info->buffer->AsFormatBuffer()->GetFormat().GetFormatType()); attachment_desc.back().initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachment_desc.back().finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - color_refer.attachment = static_cast<uint32_t>(attachment_desc.size() - 1); - color_refer.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + VkAttachmentReference ref = VkAttachmentReference(); + ref.attachment = static_cast<uint32_t>(attachment_desc.size() - 1); + ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + color_refer.push_back(ref); - subpass_desc.colorAttachmentCount = 1; - subpass_desc.pColorAttachments = &color_refer; + subpass_desc.colorAttachmentCount = + static_cast<uint32_t>(color_refer.size()); + subpass_desc.pColorAttachments = color_refer.data(); } if (depth_stencil_format_ != VK_FORMAT_UNDEFINED) { @@ -535,14 +541,11 @@ Result GraphicsPipeline::CreateVkGraphicsPipeline( input_assembly_info.primitiveRestartEnable = pipeline_data->GetEnablePrimitiveRestart(); - VkViewport viewport = {0, - 0, - static_cast<float>(frame_->GetWidth()), - static_cast<float>(frame_->GetHeight()), - 0, - 1}; + VkViewport viewport = { + 0, 0, static_cast<float>(frame_width_), static_cast<float>(frame_height_), + 0, 1}; - VkRect2D scissor = {{0, 0}, {frame_->GetWidth(), frame_->GetHeight()}}; + VkRect2D scissor = {{0, 0}, {frame_width_, frame_height_}}; VkPipelineViewportStateCreateInfo viewport_info = VkPipelineViewportStateCreateInfo(); @@ -620,17 +623,16 @@ Result GraphicsPipeline::CreateVkGraphicsPipeline( VkPipelineColorBlendStateCreateInfo colorblend_info = VkPipelineColorBlendStateCreateInfo(); VkPipelineColorBlendAttachmentState colorblend_attachment; - if (color_format_ != VK_FORMAT_UNDEFINED) { - colorblend_attachment = GetPipelineColorBlendAttachmentState(pipeline_data); - - colorblend_info.sType = - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorblend_info.logicOpEnable = pipeline_data->GetEnableLogicOp(); - colorblend_info.logicOp = ToVkLogicOp(pipeline_data->GetLogicOp()); - colorblend_info.attachmentCount = 1; - colorblend_info.pAttachments = &colorblend_attachment; - pipeline_info.pColorBlendState = &colorblend_info; - } + + colorblend_attachment = GetPipelineColorBlendAttachmentState(pipeline_data); + + colorblend_info.sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorblend_info.logicOpEnable = pipeline_data->GetEnableLogicOp(); + colorblend_info.logicOp = ToVkLogicOp(pipeline_data->GetLogicOp()); + colorblend_info.attachmentCount = 1; + colorblend_info.pAttachments = &colorblend_attachment; + pipeline_info.pColorBlendState = &colorblend_info; pipeline_info.layout = pipeline_layout; pipeline_info.renderPass = render_pass_; @@ -657,8 +659,8 @@ Result GraphicsPipeline::Initialize(uint32_t width, if (!r.IsSuccess()) return r; - frame_ = MakeUnique<FrameBuffer>(device_, width, height); - r = frame_->Initialize(render_pass_, color_format_, depth_stencil_format_, + frame_ = MakeUnique<FrameBuffer>(device_, color_buffers_, width, height); + r = frame_->Initialize(render_pass_, depth_stencil_format_, memory_properties_); if (!r.IsSuccess()) return r; @@ -742,11 +744,6 @@ void GraphicsPipeline::DeactivateRenderPassIfNeeded() { } Result GraphicsPipeline::SetClearColor(float r, float g, float b, float a) { - if (color_format_ == VK_FORMAT_UNDEFINED) { - return Result( - "Vulkan::ClearColorCommand No Color Buffer for FrameBuffer Exists"); - } - clear_color_r_ = r; clear_color_g_ = g; clear_color_b_ = b; @@ -777,29 +774,22 @@ Result GraphicsPipeline::SetClearDepth(float depth) { } Result GraphicsPipeline::Clear() { - if (color_format_ == VK_FORMAT_UNDEFINED && - depth_stencil_format_ == VK_FORMAT_UNDEFINED) { - return Result( - "Vulkan::ClearColorCommand No Color nor DepthStencil Buffer for " - "FrameBuffer Exists"); - } + VkClearValue colour_clear; + colour_clear.color = { + {clear_color_r_, clear_color_g_, clear_color_b_, clear_color_a_}}; - if (color_format_ != VK_FORMAT_UNDEFINED) { - VkClearValue clear_value; - clear_value.color = { - {clear_color_r_, clear_color_g_, clear_color_b_, clear_color_a_}}; - Result r = ClearBuffer(clear_value, VK_IMAGE_ASPECT_COLOR_BIT); - if (!r.IsSuccess()) - return r; - } + Result r = ClearBuffer(colour_clear, VK_IMAGE_ASPECT_COLOR_BIT); + if (!r.IsSuccess()) + return r; if (depth_stencil_format_ == VK_FORMAT_UNDEFINED) return {}; - VkClearValue clear_value; - clear_value.depthStencil = {clear_depth_, clear_stencil_}; + VkClearValue depth_clear; + depth_clear.depthStencil = {clear_depth_, clear_stencil_}; + return ClearBuffer( - clear_value, VkFormatHasStencilComponent(depth_stencil_format_) + depth_clear, VkFormatHasStencilComponent(depth_stencil_format_) ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT); } @@ -829,7 +819,7 @@ Result GraphicsPipeline::ClearBuffer(const VkClearValue& clear_value, DeactivateRenderPassIfNeeded(); - return frame_->CopyColorImageToHost(command_.get()); + return frame_->CopyColorImagesToHost(command_.get()); } Result GraphicsPipeline::Draw(const DrawArraysCommand* command, @@ -923,7 +913,7 @@ Result GraphicsPipeline::Draw(const DrawArraysCommand* command, DeactivateRenderPassIfNeeded(); - r = frame_->CopyColorImageToHost(command_.get()); + r = frame_->CopyColorImagesToHost(command_.get()); if (!r.IsSuccess()) return r; diff --git a/src/vulkan/graphics_pipeline.h b/src/vulkan/graphics_pipeline.h index 89bdd79..baeb897 100644 --- a/src/vulkan/graphics_pipeline.h +++ b/src/vulkan/graphics_pipeline.h @@ -23,6 +23,7 @@ #include "amber/vulkan_header.h" #include "src/buffer_data.h" #include "src/format.h" +#include "src/pipeline.h" #include "src/vulkan/frame_buffer.h" #include "src/vulkan/index_buffer.h" #include "src/vulkan/pipeline.h" @@ -38,13 +39,14 @@ class CommandPool; class GraphicsPipeline : public Pipeline { public: - GraphicsPipeline(Device* device, - const VkPhysicalDeviceProperties& properties, - const VkPhysicalDeviceMemoryProperties& memory_properties, - VkFormat color_format, - VkFormat depth_stencil_format, - uint32_t fence_timeout_ms, - const std::vector<VkPipelineShaderStageCreateInfo>&); + GraphicsPipeline( + Device* device, + const VkPhysicalDeviceProperties& properties, + const VkPhysicalDeviceMemoryProperties& memory_properties, + const std::vector<amber::Pipeline::BufferInfo>& color_buffers, + VkFormat depth_stencil_format, + uint32_t fence_timeout_ms, + const std::vector<VkPipelineShaderStageCreateInfo>&); ~GraphicsPipeline() override; Result Initialize(uint32_t width, @@ -57,8 +59,6 @@ class GraphicsPipeline : public Pipeline { Result Clear(); Result ClearBuffer(const VkClearValue& clear_value, VkImageAspectFlags aspect); - VkFormat GetColorFormat() const { return color_format_; } - VkFormat GetDepthStencilFormat() const { return depth_stencil_format_; } Result SetClearColor(float r, float g, float b, float a); Result SetClearStencil(uint32_t stencil); @@ -114,7 +114,9 @@ class GraphicsPipeline : public Pipeline { RenderPassState render_pass_state_ = RenderPassState::kInactive; std::unique_ptr<FrameBuffer> frame_; - VkFormat color_format_; + + // color buffers are owned by the amber::Pipeline. + std::vector<const amber::Pipeline::BufferInfo*> color_buffers_; VkFormat depth_stencil_format_; std::unique_ptr<IndexBuffer> index_buffer_; |