mirror of
https://github.com/godotengine/godot.git
synced 2024-12-02 09:02:45 +00:00
Merge pull request #49885 from reduz/implement-render-pass-support
Implement Framebuffer Subpass support
This commit is contained in:
commit
e4430771db
35
doc/classes/RDFramebufferPass.xml
Normal file
35
doc/classes/RDFramebufferPass.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="RDFramebufferPass" inherits="RefCounted" version="4.0">
|
||||
<brief_description>
|
||||
Framebuffer pass attachment description.
|
||||
</brief_description>
|
||||
<description>
|
||||
This class contains the list of attachment descriptions for a framebuffer pass. Each points with an index to a previously supplied list of texture attachments.
|
||||
Multipass framebuffers can optimize some configurations in mobile, on desktop they provide little to no advantage.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="color_attachments" type="PackedInt32Array" setter="set_color_attachments" getter="get_color_attachments" default="PackedInt32Array()">
|
||||
Color attachments in order starting from 0. If this attachment is not used by the shader, pass ATTACHMENT_UNUSED to skip.
|
||||
</member>
|
||||
<member name="depth_attachment" type="int" setter="set_depth_attachment" getter="get_depth_attachment" default="-1">
|
||||
Depth attachment. ATTACHMENT_UNUSED should be used if no depth buffer is required for this pass.
|
||||
</member>
|
||||
<member name="input_attachments" type="PackedInt32Array" setter="set_input_attachments" getter="get_input_attachments" default="PackedInt32Array()">
|
||||
Used for multipass framebuffers (more than one render pass). Converts an attachment to an input. Make sure to also supply it properly in the [RDUniform] for the uniform set.
|
||||
</member>
|
||||
<member name="preserve_attachments" type="PackedInt32Array" setter="set_preserve_attachments" getter="get_preserve_attachments" default="PackedInt32Array()">
|
||||
Attachments to preserve in this pass (otherwise they are erased).
|
||||
</member>
|
||||
<member name="resolve_attachments" type="PackedInt32Array" setter="set_resolve_attachments" getter="get_resolve_attachments" default="PackedInt32Array()">
|
||||
If the color attachments are multisampled, non-multisampled resolve attachments can be provided.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="ATTACHMENT_UNUSED" value="-1">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
@ -341,13 +341,29 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="draw_list_switch_to_next_pass">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="draw_list_switch_to_next_pass_split">
|
||||
<return type="PackedInt64Array">
|
||||
</return>
|
||||
<argument index="0" name="splits" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="framebuffer_create">
|
||||
<return type="RID">
|
||||
</return>
|
||||
<argument index="0" name="textures" type="Array">
|
||||
<argument index="0" name="textures" type="RID[]">
|
||||
</argument>
|
||||
<argument index="1" name="validate_with_format" type="int" default="-1">
|
||||
</argument>
|
||||
<argument index="2" name="view_count" type="int" default="1">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -363,11 +379,27 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="framebuffer_create_multipass">
|
||||
<return type="RID">
|
||||
</return>
|
||||
<argument index="0" name="textures" type="RID[]">
|
||||
</argument>
|
||||
<argument index="1" name="passes" type="RDFramebufferPass[]">
|
||||
</argument>
|
||||
<argument index="2" name="validate_with_format" type="int" default="-1">
|
||||
</argument>
|
||||
<argument index="3" name="view_count" type="int" default="1">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="framebuffer_format_create">
|
||||
<return type="int">
|
||||
</return>
|
||||
<argument index="0" name="attachments" type="RDAttachmentFormat[]">
|
||||
</argument>
|
||||
<argument index="1" name="view_count" type="int" default="1">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -379,11 +411,25 @@
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="framebuffer_format_create_multipass">
|
||||
<return type="int">
|
||||
</return>
|
||||
<argument index="0" name="attachments" type="RDAttachmentFormat[]">
|
||||
</argument>
|
||||
<argument index="1" name="passes" type="RDFramebufferPass[]">
|
||||
</argument>
|
||||
<argument index="2" name="view_count" type="int" default="1">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="framebuffer_format_get_texture_samples">
|
||||
<return type="int" enum="RenderingDevice.TextureSamples">
|
||||
</return>
|
||||
<argument index="0" name="format" type="int">
|
||||
</argument>
|
||||
<argument index="1" name="render_pass" type="int" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -524,6 +570,8 @@
|
||||
</argument>
|
||||
<argument index="8" name="dynamic_state_flags" type="int" default="0">
|
||||
</argument>
|
||||
<argument index="9" name="for_render_pass" type="int" default="0">
|
||||
</argument>
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
||||
/***********************/
|
||||
|
@ -194,6 +194,7 @@ void register_server_types() {
|
||||
ClassDB::register_class<RDTextureFormat>();
|
||||
ClassDB::register_class<RDTextureView>();
|
||||
ClassDB::register_class<RDAttachmentFormat>();
|
||||
ClassDB::register_class<RDFramebufferPass>();
|
||||
ClassDB::register_class<RDSamplerState>();
|
||||
ClassDB::register_class<RDVertexAttribute>();
|
||||
ClassDB::register_class<RDUniform>();
|
||||
|
@ -31,20 +31,21 @@
|
||||
#include "pipeline_cache_rd.h"
|
||||
#include "core/os/memory.h"
|
||||
|
||||
RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe) {
|
||||
RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass) {
|
||||
RD::PipelineMultisampleState multisample_state_version = multisample_state;
|
||||
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id);
|
||||
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id, p_render_pass);
|
||||
|
||||
RD::PipelineRasterizationState raster_state_version = rasterization_state;
|
||||
raster_state_version.wireframe = p_wireframe;
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags);
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass);
|
||||
ERR_FAIL_COND_V(pipeline.is_null(), RID());
|
||||
versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
|
||||
versions[version_count].framebuffer_id = p_framebuffer_format_id;
|
||||
versions[version_count].vertex_id = p_vertex_format_id;
|
||||
versions[version_count].wireframe = p_wireframe;
|
||||
versions[version_count].pipeline = pipeline;
|
||||
versions[version_count].render_pass = p_render_pass;
|
||||
version_count++;
|
||||
return pipeline;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ class PipelineCacheRD {
|
||||
struct Version {
|
||||
RD::VertexFormatID vertex_id;
|
||||
RD::FramebufferFormatID framebuffer_id;
|
||||
uint32_t render_pass;
|
||||
bool wireframe;
|
||||
RID pipeline;
|
||||
};
|
||||
@ -57,7 +58,7 @@ class PipelineCacheRD {
|
||||
Version *versions;
|
||||
uint32_t version_count;
|
||||
|
||||
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe);
|
||||
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass);
|
||||
|
||||
void _clear();
|
||||
|
||||
@ -65,7 +66,7 @@ public:
|
||||
void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0);
|
||||
void update_shader(RID p_shader);
|
||||
|
||||
_FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false) {
|
||||
_FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false, uint32_t p_render_pass = 0) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
|
||||
"Attempted to use an unused shader variant (shader is null),");
|
||||
@ -74,13 +75,13 @@ public:
|
||||
spin_lock.lock();
|
||||
RID result;
|
||||
for (uint32_t i = 0; i < version_count; i++) {
|
||||
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe) {
|
||||
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe && versions[i].render_pass == p_render_pass) {
|
||||
result = versions[i].pipeline;
|
||||
spin_lock.unlock();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe);
|
||||
result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe, p_render_pass);
|
||||
spin_lock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ RID RenderingDevice::_texture_create_shared_from_slice(const Ref<RDTextureView>
|
||||
return texture_create_shared_from_slice(p_view->base, p_with_texture, p_layer, p_mipmap, p_slice_type);
|
||||
}
|
||||
|
||||
RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments) {
|
||||
RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count) {
|
||||
Vector<AttachmentFormat> attachments;
|
||||
attachments.resize(p_attachments.size());
|
||||
|
||||
@ -107,12 +107,43 @@ RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create
|
||||
ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
|
||||
attachments.write[i] = af->base;
|
||||
}
|
||||
return framebuffer_format_create(attachments);
|
||||
return framebuffer_format_create(attachments, p_view_count);
|
||||
}
|
||||
|
||||
RID RenderingDevice::_framebuffer_create(const Array &p_textures, FramebufferFormatID p_format_check) {
|
||||
RenderingDevice::FramebufferFormatID RenderingDevice::_framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count) {
|
||||
Vector<AttachmentFormat> attachments;
|
||||
attachments.resize(p_attachments.size());
|
||||
|
||||
for (int i = 0; i < p_attachments.size(); i++) {
|
||||
Ref<RDAttachmentFormat> af = p_attachments[i];
|
||||
ERR_FAIL_COND_V(af.is_null(), INVALID_FORMAT_ID);
|
||||
attachments.write[i] = af->base;
|
||||
}
|
||||
|
||||
Vector<FramebufferPass> passes;
|
||||
for (int i = 0; i < p_passes.size(); i++) {
|
||||
Ref<RDFramebufferPass> pass = p_passes[i];
|
||||
ERR_CONTINUE(pass.is_null());
|
||||
passes.push_back(pass->base);
|
||||
}
|
||||
|
||||
return framebuffer_format_create_multipass(attachments, passes, p_view_count);
|
||||
}
|
||||
|
||||
RID RenderingDevice::_framebuffer_create(const TypedArray<RID> &p_textures, FramebufferFormatID p_format_check, uint32_t p_view_count) {
|
||||
Vector<RID> textures = Variant(p_textures);
|
||||
return framebuffer_create(textures, p_format_check);
|
||||
return framebuffer_create(textures, p_format_check, p_view_count);
|
||||
}
|
||||
|
||||
RID RenderingDevice::_framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check, uint32_t p_view_count) {
|
||||
Vector<RID> textures = Variant(p_textures);
|
||||
Vector<FramebufferPass> passes;
|
||||
for (int i = 0; i < p_passes.size(); i++) {
|
||||
Ref<RDFramebufferPass> pass = p_passes[i];
|
||||
ERR_CONTINUE(pass.is_null());
|
||||
passes.push_back(pass->base);
|
||||
}
|
||||
return framebuffer_create_multipass(textures, passes, p_format_check, p_view_count);
|
||||
}
|
||||
|
||||
RID RenderingDevice::_sampler_create(const Ref<RDSamplerState> &p_state) {
|
||||
@ -190,7 +221,7 @@ Error RenderingDevice::_buffer_update(RID p_buffer, uint32_t p_offset, uint32_t
|
||||
return buffer_update(p_buffer, p_offset, p_size, p_data.ptr(), p_post_barrier);
|
||||
}
|
||||
|
||||
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags) {
|
||||
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass) {
|
||||
PipelineRasterizationState rasterization_state;
|
||||
if (p_rasterization_state.is_valid()) {
|
||||
rasterization_state = p_rasterization_state->base;
|
||||
@ -221,7 +252,7 @@ RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p
|
||||
}
|
||||
}
|
||||
|
||||
return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags);
|
||||
return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags, p_for_render_pass);
|
||||
}
|
||||
|
||||
Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, 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_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) {
|
||||
@ -242,6 +273,22 @@ Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint3
|
||||
return split_ids;
|
||||
}
|
||||
|
||||
Vector<int64_t> RenderingDevice::_draw_list_switch_to_next_pass_split(uint32_t p_splits) {
|
||||
Vector<DrawListID> splits;
|
||||
splits.resize(p_splits);
|
||||
|
||||
Error err = draw_list_switch_to_next_pass_split(p_splits, splits.ptrw());
|
||||
ERR_FAIL_COND_V(err != OK, Vector<int64_t>());
|
||||
|
||||
Vector<int64_t> split_ids;
|
||||
split_ids.resize(splits.size());
|
||||
for (int i = 0; i < splits.size(); i++) {
|
||||
split_ids.write[i] = splits[i];
|
||||
}
|
||||
|
||||
return split_ids;
|
||||
}
|
||||
|
||||
void RenderingDevice::_draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size) {
|
||||
ERR_FAIL_COND((uint32_t)p_data.size() > p_data_size);
|
||||
draw_list_set_push_constant(p_list, p_data.ptr(), p_data_size);
|
||||
@ -269,10 +316,12 @@ void RenderingDevice::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("texture_clear", "texture", "color", "base_mipmap", "mipmap_count", "base_layer", "layer_count", "post_barrier"), &RenderingDevice::texture_clear, DEFVAL(BARRIER_MASK_ALL));
|
||||
ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "post_barrier"), &RenderingDevice::texture_resolve_multisample, DEFVAL(BARRIER_MASK_ALL));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments"), &RenderingDevice::_framebuffer_format_create);
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments", "view_count"), &RenderingDevice::_framebuffer_format_create, DEFVAL(1));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_create_multipass", "attachments", "passes", "view_count"), &RenderingDevice::_framebuffer_format_create_multipass, DEFVAL(1));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_create_empty", "samples"), &RenderingDevice::framebuffer_format_create_empty, DEFVAL(TEXTURE_SAMPLES_1));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format"), &RenderingDevice::framebuffer_format_get_texture_samples);
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format", "render_pass"), &RenderingDevice::framebuffer_format_get_texture_samples, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_create_multipass", "textures", "passes", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create_multipass, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID));
|
||||
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
|
||||
|
||||
@ -299,7 +348,7 @@ void RenderingDevice::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL));
|
||||
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags"), &RenderingDevice::_render_pipeline_create, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags", "for_render_pass"), &RenderingDevice::_render_pipeline_create, DEFVAL(0), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("render_pipeline_is_valid", "render_pipeline"), &RenderingDevice::render_pipeline_is_valid);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("compute_pipeline_create", "shader"), &RenderingDevice::compute_pipeline_create);
|
||||
@ -325,6 +374,9 @@ void RenderingDevice::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2i()));
|
||||
ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass);
|
||||
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass_split", "splits"), &RenderingDevice::_draw_list_switch_to_next_pass_split);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("draw_list_end", "post_barrier"), &RenderingDevice::draw_list_end, DEFVAL(BARRIER_MASK_ALL));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("compute_list_begin", "allow_draw_overlap"), &RenderingDevice::compute_list_begin, DEFVAL(false));
|
||||
|
@ -47,6 +47,7 @@ class RDPipelineRasterizationState;
|
||||
class RDPipelineMultisampleState;
|
||||
class RDPipelineDepthStencilState;
|
||||
class RDPipelineColorBlendState;
|
||||
class RDFramebufferPass;
|
||||
|
||||
class RenderingDevice : public Object {
|
||||
GDCLASS(RenderingDevice, Object)
|
||||
@ -517,10 +518,23 @@ public:
|
||||
|
||||
// This ID is warranted to be unique for the same formats, does not need to be freed
|
||||
virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format, uint32_t p_view_count = 1) = 0;
|
||||
struct FramebufferPass {
|
||||
enum {
|
||||
ATTACHMENT_UNUSED = -1
|
||||
};
|
||||
Vector<int32_t> color_attachments;
|
||||
Vector<int32_t> input_attachments;
|
||||
Vector<int32_t> resolve_attachments;
|
||||
Vector<int32_t> preserve_attachments;
|
||||
int32_t depth_attachment = ATTACHMENT_UNUSED;
|
||||
};
|
||||
|
||||
virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
|
||||
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0;
|
||||
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0;
|
||||
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0) = 0;
|
||||
|
||||
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
|
||||
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) = 0;
|
||||
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0;
|
||||
|
||||
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
|
||||
@ -962,7 +976,7 @@ public:
|
||||
};
|
||||
|
||||
virtual bool render_pipeline_is_valid(RID p_pipeline) = 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) = 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) = 0;
|
||||
|
||||
/**************************/
|
||||
/**** COMPUTE PIPELINE ****/
|
||||
@ -1018,6 +1032,9 @@ public:
|
||||
virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) = 0;
|
||||
virtual void draw_list_disable_scissor(DrawListID p_list) = 0;
|
||||
|
||||
virtual DrawListID draw_list_switch_to_next_pass() = 0;
|
||||
virtual Error draw_list_switch_to_next_pass_split(uint32_t p_splits, DrawListID *r_split_ids) = 0;
|
||||
|
||||
virtual void draw_list_end(uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
|
||||
|
||||
/***********************/
|
||||
@ -1134,8 +1151,10 @@ protected:
|
||||
RID _texture_create_shared(const Ref<RDTextureView> &p_view, RID p_with_texture);
|
||||
RID _texture_create_shared_from_slice(const Ref<RDTextureView> &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
|
||||
|
||||
FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments);
|
||||
RID _framebuffer_create(const Array &p_textures, FramebufferFormatID p_format_check = INVALID_ID);
|
||||
FramebufferFormatID _framebuffer_format_create(const TypedArray<RDAttachmentFormat> &p_attachments, uint32_t p_view_count);
|
||||
FramebufferFormatID _framebuffer_format_create_multipass(const TypedArray<RDAttachmentFormat> &p_attachments, const TypedArray<RDFramebufferPass> &p_passes, uint32_t p_view_count);
|
||||
RID _framebuffer_create(const TypedArray<RID> &p_textures, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
|
||||
RID _framebuffer_create_multipass(const TypedArray<RID> &p_textures, const TypedArray<RDFramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1);
|
||||
RID _sampler_create(const Ref<RDSamplerState> &p_state);
|
||||
VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats);
|
||||
RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers);
|
||||
@ -1146,11 +1165,12 @@ protected:
|
||||
|
||||
Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
|
||||
|
||||
RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0);
|
||||
RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0, uint32_t p_for_render_pass = 0);
|
||||
|
||||
Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, 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_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>());
|
||||
void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
|
||||
void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size);
|
||||
Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits);
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
|
||||
|
@ -128,6 +128,34 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
class RDFramebufferPass : public RefCounted {
|
||||
GDCLASS(RDFramebufferPass, RefCounted)
|
||||
friend class RenderingDevice;
|
||||
|
||||
RD::FramebufferPass base;
|
||||
|
||||
public:
|
||||
RD_SETGET(PackedInt32Array, color_attachments)
|
||||
RD_SETGET(PackedInt32Array, input_attachments)
|
||||
RD_SETGET(PackedInt32Array, resolve_attachments)
|
||||
RD_SETGET(PackedInt32Array, preserve_attachments)
|
||||
RD_SETGET(int32_t, depth_attachment)
|
||||
protected:
|
||||
enum {
|
||||
ATTACHMENT_UNUSED = -1
|
||||
};
|
||||
|
||||
static void _bind_methods() {
|
||||
RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, color_attachments);
|
||||
RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, input_attachments);
|
||||
RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, resolve_attachments);
|
||||
RD_BIND(Variant::PACKED_INT32_ARRAY, RDFramebufferPass, preserve_attachments);
|
||||
RD_BIND(Variant::INT, RDFramebufferPass, depth_attachment);
|
||||
|
||||
BIND_CONSTANT(ATTACHMENT_UNUSED);
|
||||
}
|
||||
};
|
||||
|
||||
class RDSamplerState : public RefCounted {
|
||||
GDCLASS(RDSamplerState, RefCounted)
|
||||
friend class RenderingDevice;
|
||||
|
Loading…
Reference in New Issue
Block a user