You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-22 15:06:45 +00:00
Implement Framebuffer Subpass support
* Required for better optimizing mobile platforms * Will be used by the Vulkan mobile renderer.
This commit is contained in:
@@ -234,12 +234,87 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
|
||||
struct FramebufferFormatKey {
|
||||
Vector<AttachmentFormat> attachments;
|
||||
Vector<FramebufferPass> passes;
|
||||
uint32_t view_count = 1;
|
||||
bool operator<(const FramebufferFormatKey &p_key) const {
|
||||
if (view_count != p_key.view_count) {
|
||||
return view_count < p_key.view_count;
|
||||
}
|
||||
|
||||
uint32_t pass_size = passes.size();
|
||||
uint32_t key_pass_size = p_key.passes.size();
|
||||
if (pass_size != key_pass_size) {
|
||||
return pass_size < key_pass_size;
|
||||
}
|
||||
const FramebufferPass *pass_ptr = passes.ptr();
|
||||
const FramebufferPass *key_pass_ptr = p_key.passes.ptr();
|
||||
|
||||
for (uint32_t i = 0; i < pass_size; i++) {
|
||||
{ //compare color attachments
|
||||
uint32_t attachment_size = pass_ptr[i].color_attachments.size();
|
||||
uint32_t key_attachment_size = key_pass_ptr[i].color_attachments.size();
|
||||
if (attachment_size != key_attachment_size) {
|
||||
return attachment_size < key_attachment_size;
|
||||
}
|
||||
const int32_t *pass_attachment_ptr = pass_ptr[i].color_attachments.ptr();
|
||||
const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].color_attachments.ptr();
|
||||
|
||||
for (uint32_t j = 0; j < attachment_size; j++) {
|
||||
if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {
|
||||
return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
{ //compare input attachments
|
||||
uint32_t attachment_size = pass_ptr[i].input_attachments.size();
|
||||
uint32_t key_attachment_size = key_pass_ptr[i].input_attachments.size();
|
||||
if (attachment_size != key_attachment_size) {
|
||||
return attachment_size < key_attachment_size;
|
||||
}
|
||||
const int32_t *pass_attachment_ptr = pass_ptr[i].input_attachments.ptr();
|
||||
const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].input_attachments.ptr();
|
||||
|
||||
for (uint32_t j = 0; j < attachment_size; j++) {
|
||||
if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {
|
||||
return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
{ //compare resolve attachments
|
||||
uint32_t attachment_size = pass_ptr[i].resolve_attachments.size();
|
||||
uint32_t key_attachment_size = key_pass_ptr[i].resolve_attachments.size();
|
||||
if (attachment_size != key_attachment_size) {
|
||||
return attachment_size < key_attachment_size;
|
||||
}
|
||||
const int32_t *pass_attachment_ptr = pass_ptr[i].resolve_attachments.ptr();
|
||||
const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].resolve_attachments.ptr();
|
||||
|
||||
for (uint32_t j = 0; j < attachment_size; j++) {
|
||||
if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {
|
||||
return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
{ //compare preserve attachments
|
||||
uint32_t attachment_size = pass_ptr[i].preserve_attachments.size();
|
||||
uint32_t key_attachment_size = key_pass_ptr[i].preserve_attachments.size();
|
||||
if (attachment_size != key_attachment_size) {
|
||||
return attachment_size < key_attachment_size;
|
||||
}
|
||||
const int32_t *pass_attachment_ptr = pass_ptr[i].preserve_attachments.ptr();
|
||||
const int32_t *key_pass_attachment_ptr = key_pass_ptr[i].preserve_attachments.ptr();
|
||||
|
||||
for (uint32_t j = 0; j < attachment_size; j++) {
|
||||
if (pass_attachment_ptr[j] != key_pass_attachment_ptr[j]) {
|
||||
return pass_attachment_ptr[j] < key_pass_attachment_ptr[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pass_ptr[i].depth_attachment != key_pass_ptr[i].depth_attachment) {
|
||||
return pass_ptr[i].depth_attachment < key_pass_ptr[i].depth_attachment;
|
||||
}
|
||||
}
|
||||
|
||||
int as = attachments.size();
|
||||
int bs = p_key.attachments.size();
|
||||
if (as != bs) {
|
||||
@@ -266,16 +341,14 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
}
|
||||
};
|
||||
|
||||
VkRenderPass _render_pass_create(const Vector<AttachmentFormat> &p_format, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depthcolor_action, int *r_color_attachment_count = nullptr, uint32_t p_view_count = 1);
|
||||
|
||||
VkRenderPass _render_pass_create(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, InitialAction p_initial_action, FinalAction p_final_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, uint32_t p_view_count = 1, Vector<TextureSamples> *r_samples = nullptr);
|
||||
// This is a cache and it's never freed, it ensures
|
||||
// IDs for a given format are always unique.
|
||||
Map<FramebufferFormatKey, FramebufferFormatID> framebuffer_format_cache;
|
||||
struct FramebufferFormat {
|
||||
const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E;
|
||||
VkRenderPass render_pass = VK_NULL_HANDLE; //here for constructing shaders, never used, see section (7.2. Render Pass Compatibility from Vulkan spec)
|
||||
int color_attachments = 0; //used for pipeline validation
|
||||
TextureSamples samples;
|
||||
Vector<TextureSamples> pass_samples;
|
||||
uint32_t view_count = 1; // number of views
|
||||
};
|
||||
|
||||
@@ -289,6 +362,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
InitialAction initial_depth_action;
|
||||
FinalAction final_depth_action;
|
||||
uint32_t view_count;
|
||||
|
||||
bool operator<(const VersionKey &p_key) const {
|
||||
if (initial_color_action == p_key.initial_color_action) {
|
||||
if (final_color_action == p_key.final_color_action) {
|
||||
@@ -316,6 +390,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
struct Version {
|
||||
VkFramebuffer framebuffer = VK_NULL_HANDLE;
|
||||
VkRenderPass render_pass = VK_NULL_HANDLE; //this one is owned
|
||||
uint32_t subpass_count = 1;
|
||||
};
|
||||
|
||||
Map<VersionKey, Version> framebuffers;
|
||||
@@ -536,7 +611,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
};
|
||||
|
||||
uint32_t vertex_input_mask = 0; //inputs used, this is mostly for validation
|
||||
int fragment_outputs = 0;
|
||||
uint32_t fragment_output_mask = 0;
|
||||
|
||||
struct PushConstant {
|
||||
uint32_t push_constant_size = 0;
|
||||
@@ -680,6 +755,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
#ifdef DEBUG_ENABLED
|
||||
struct Validation {
|
||||
FramebufferFormatID framebuffer_format = 0;
|
||||
uint32_t render_pass = 0;
|
||||
uint32_t dynamic_state = 0;
|
||||
VertexFormatID vertex_format = 0;
|
||||
bool uses_restart_indices = false;
|
||||
@@ -735,6 +811,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
struct DrawList {
|
||||
VkCommandBuffer command_buffer = VK_NULL_HANDLE; // If persistent, this is owned, otherwise it's shared with the ringbuffer.
|
||||
Rect2i viewport;
|
||||
bool viewport_set = false;
|
||||
|
||||
struct SetState {
|
||||
uint32_t pipeline_expected_format = 0;
|
||||
@@ -758,7 +835,6 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
#ifdef DEBUG_ENABLED
|
||||
struct Validation {
|
||||
bool active = true; // Means command buffer was not closed, so you can keep adding things.
|
||||
FramebufferFormatID framebuffer_format = INVALID_ID;
|
||||
// Actual render pass values.
|
||||
uint32_t dynamic_state = 0;
|
||||
VertexFormatID vertex_format = INVALID_ID;
|
||||
@@ -794,7 +870,15 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
};
|
||||
|
||||
DrawList *draw_list = nullptr; // One for regular draw lists, multiple for split.
|
||||
uint32_t draw_list_subpass_count = 0;
|
||||
uint32_t draw_list_count = 0;
|
||||
VkRenderPass draw_list_render_pass;
|
||||
VkFramebuffer draw_list_vkframebuffer;
|
||||
#ifdef DEBUG_ENABLED
|
||||
FramebufferFormatID draw_list_framebuffer_format = INVALID_ID;
|
||||
#endif
|
||||
uint32_t draw_list_current_subpass = 0;
|
||||
|
||||
bool draw_list_split = false;
|
||||
Vector<RID> draw_list_bound_textures;
|
||||
Vector<RID> draw_list_storage_textures;
|
||||
@@ -802,10 +886,12 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||
bool draw_list_unbind_depth_textures = false;
|
||||
|
||||
void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil);
|
||||
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass);
|
||||
Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass, uint32_t *r_subpass_count);
|
||||
Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures);
|
||||
_FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id);
|
||||
Buffer *_get_buffer_from_owner(RID p_buffer, VkPipelineStageFlags &dst_stage_mask, VkAccessFlags &dst_access, uint32_t p_post_barrier);
|
||||
Error _draw_list_allocate(const Rect2i &p_viewport, uint32_t p_splits, uint32_t p_subpass);
|
||||
void _draw_list_free(Rect2i *r_last_viewport = nullptr);
|
||||
|
||||
/**********************/
|
||||
/**** COMPUTE LIST ****/
|
||||
@@ -951,10 +1037,12 @@ public:
|
||||
/*********************/
|
||||
|
||||
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1);
|
||||
virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1);
|
||||
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1);
|
||||
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format);
|
||||
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0);
|
||||
|
||||
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
|
||||
virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
|
||||
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID);
|
||||
|
||||
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer);
|
||||
@@ -1005,7 +1093,7 @@ public:
|
||||
/**** RENDER PIPELINE ****/
|
||||
/*************************/
|
||||
|
||||
virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0);
|
||||
virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0);
|
||||
virtual bool render_pipeline_is_valid(RID p_pipeline);
|
||||
|
||||
/**************************/
|
||||
@@ -1044,6 +1132,9 @@ public:
|
||||
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect);
|
||||
virtual void draw_list_disable_scissor(DrawListID p_list);
|
||||
|
||||
virtual DrawListID draw_list_switch_to_next_pass();
|
||||
virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids);
|
||||
|
||||
virtual void draw_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL);
|
||||
|
||||
/***********************/
|
||||
|
||||
Reference in New Issue
Block a user