summaryrefslogtreecommitdiff
path: root/drivers/vulkan/rendering_device_vulkan.h
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-07-27 10:23:24 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-02-11 11:53:29 +0100
commit0586e184490fd132f99acb1a67c788959cfdbade (patch)
tree194972ba608705445c9ee084f908e183a9792760 /drivers/vulkan/rendering_device_vulkan.h
parent8bbbb973361f367a4888629c571fb6f43581269d (diff)
Custom material support seems complete.
Diffstat (limited to 'drivers/vulkan/rendering_device_vulkan.h')
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h171
1 files changed, 133 insertions, 38 deletions
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 3b7477c54d..2420e62aab 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -385,6 +385,74 @@ class RenderingDeviceVulkan : public RenderingDevice {
/**** SHADER ****/
/****************/
+ // Vulkan specifies a really complex behavior for the application
+ // in order to tell when descriptor sets need to be re-bound (or not).
+ // "When binding a descriptor set (see Descriptor Set Binding) to set
+ // number N, if the previously bound descriptor sets for sets zero
+ // through N-1 were all bound using compatible pipeline layouts,
+ // then performing this binding does not disturb any of the lower numbered sets.
+ // If, additionally, the previous bound descriptor set for set N was
+ // bound using a pipeline layout compatible for set N, then the bindings
+ // in sets numbered greater than N are also not disturbed."
+ // As a result, we need to figure out quickly when something is no longer "compatible".
+ // in order to avoid costly rebinds.
+
+ enum {
+ MAX_UNIFORM_SETS = 16
+ };
+
+ struct UniformInfo {
+ UniformType type;
+ int binding;
+ uint32_t stages;
+ int length; //size of arrays (in total elements), or ubos (in bytes * total elements)
+
+ bool operator!=(const UniformInfo &p_info) const {
+ return (binding != p_info.binding || type != p_info.type || stages != p_info.stages || length != p_info.length);
+ }
+
+ bool operator<(const UniformInfo &p_info) const {
+ if (binding != p_info.binding) {
+ return binding < p_info.binding;
+ }
+ if (type != p_info.type) {
+ return type < p_info.type;
+ }
+ if (stages != p_info.stages) {
+ return stages < p_info.stages;
+ }
+ return length < p_info.length;
+ }
+ };
+
+ struct UniformSetFormat {
+ Vector<UniformInfo> uniform_info;
+ bool operator<(const UniformSetFormat &p_format) const {
+ uint32_t size = uniform_info.size();
+ uint32_t psize = p_format.uniform_info.size();
+
+ if (size != psize) {
+ return size < psize;
+ }
+
+ const UniformInfo *infoptr = uniform_info.ptr();
+ const UniformInfo *pinfoptr = p_format.uniform_info.ptr();
+
+ for (uint32_t i = 0; i < size; i++) {
+ if (infoptr[i] != pinfoptr[i]) {
+ return infoptr[i] < pinfoptr[i];
+ }
+ }
+
+ return false;
+ }
+ };
+
+ // Always grows, never shrinks, ensuring unique IDs, but we assume
+ // the amount of formats will never be a problem, as the amount of shaders
+ // in a game is limited.
+ Map<UniformSetFormat, uint32_t> uniform_set_format_cache;
+
// Shaders in Vulkan are just pretty much
// precompiled blocks of SPIR-V bytecode. They
// are most likely not really compiled to host
@@ -402,25 +470,6 @@ class RenderingDeviceVulkan : public RenderingDevice {
struct Shader {
- struct UniformInfo {
- UniformType type;
- int binding;
- uint32_t stages;
- int length; //size of arrays (in total elements), or ubos (in bytes * total elements)
- bool operator<(const UniformInfo &p_info) const {
- if (type != p_info.type) {
- return type < p_info.type;
- }
- if (binding != p_info.binding) {
- return binding < p_info.binding;
- }
- if (stages != p_info.stages) {
- return stages < p_info.stages;
- }
- return length < p_info.length;
- }
- };
-
struct Set {
Vector<UniformInfo> uniform_info;
@@ -439,12 +488,13 @@ class RenderingDeviceVulkan : public RenderingDevice {
int max_output;
Vector<Set> sets;
- Vector<uint32_t> set_hashes;
+ Vector<uint32_t> set_formats;
Vector<VkPipelineShaderStageCreateInfo> pipeline_stages;
VkPipelineLayout pipeline_layout;
};
- bool _uniform_add_binding(Vector<Vector<VkDescriptorSetLayoutBinding> > &bindings, Vector<Vector<Shader::UniformInfo> > &uniform_infos, const glslang::TObjectReflection &reflection, RenderingDevice::ShaderStage p_stage, Shader::PushConstant &push_constant, String *r_error);
+ String _shader_uniform_debug(RID p_shader, int p_set = -1);
+ bool _uniform_add_binding(Vector<Vector<VkDescriptorSetLayoutBinding> > &bindings, Vector<Vector<UniformInfo> > &uniform_infos, const glslang::TObjectReflection &reflection, RenderingDevice::ShaderStage p_stage, Shader::PushConstant &push_constant, String *r_error);
RID_Owner<Shader> shader_owner;
@@ -530,12 +580,13 @@ class RenderingDeviceVulkan : public RenderingDevice {
// the above restriction is not too serious.
struct UniformSet {
- uint32_t hash;
+ uint32_t format;
RID shader_id;
+ uint32_t shader_set;
DescriptorPool *pool;
DescriptorPoolKey pool_key;
VkDescriptorSet descriptor_set;
- VkPipelineLayout pipeline_layout; //not owned, inherited from shader
+ //VkPipelineLayout pipeline_layout; //not owned, inherited from shader
Vector<RID> attachable_textures; //used for validation
};
@@ -558,18 +609,23 @@ class RenderingDeviceVulkan : public RenderingDevice {
struct RenderPipeline {
//Cached values for validation
- FramebufferFormatID framebuffer_format;
- uint32_t dynamic_state;
- VertexFormatID vertex_format;
- bool uses_restart_indices;
- uint32_t primitive_minimum;
- uint32_t primitive_divisor;
- Vector<uint32_t> set_hashes;
- uint32_t push_constant_size;
- uint32_t push_constant_stages;
+#ifdef DEBUG_ENABLED
+ struct Validation {
+ FramebufferFormatID framebuffer_format;
+ uint32_t dynamic_state;
+ VertexFormatID vertex_format;
+ bool uses_restart_indices;
+ uint32_t primitive_minimum;
+ uint32_t primitive_divisor;
+ } validation;
+#endif
//Actual pipeline
+ RID shader;
+ Vector<uint32_t> set_formats;
VkPipelineLayout pipeline_layout; // not owned, needed for push constants
VkPipeline pipeline;
+ uint32_t push_constant_size;
+ uint32_t push_constant_stages;
};
RID_Owner<RenderPipeline> pipeline_owner;
@@ -600,6 +656,39 @@ class RenderingDeviceVulkan : public RenderingDevice {
VkCommandBuffer command_buffer; //if persistent, this is owned, otherwise it's shared with the ringbuffer
Rect2i viewport;
+
+ struct SetState {
+ uint32_t pipeline_expected_format;
+ uint32_t uniform_set_format;
+ VkDescriptorSet descriptor_set;
+ RID uniform_set;
+ bool bound;
+ SetState() {
+ bound = false;
+ pipeline_expected_format = 0;
+ uniform_set_format = 0;
+ descriptor_set = VK_NULL_HANDLE;
+ }
+ };
+
+ struct State {
+ SetState sets[MAX_UNIFORM_SETS];
+ uint32_t set_count;
+ RID pipeline;
+ RID pipeline_shader;
+ VkPipelineLayout pipeline_layout;
+ RID vertex_array;
+ RID index_array;
+ uint32_t pipeline_push_constant_stages;
+
+ State() {
+ set_count = 0;
+ pipeline_layout = VK_NULL_HANDLE;
+ pipeline_push_constant_stages = 0;
+ }
+ } state;
+#ifdef DEBUG_ENABLED
+
struct Validation {
bool active; //means command buffer was not closes, so you can keep adding things
FramebufferFormatID framebuffer_format;
@@ -612,18 +701,20 @@ class RenderingDeviceVulkan : public RenderingDevice {
uint32_t index_array_size; //0 if index buffer not set
uint32_t index_array_max_index;
uint32_t index_array_offset;
- Vector<uint32_t> set_hashes;
+ Vector<uint32_t> set_formats;
+ Vector<bool> set_bound;
+ Vector<RID> set_rids;
//last pipeline set values
bool pipeline_active;
uint32_t pipeline_dynamic_state;
VertexFormatID pipeline_vertex_format;
+ RID pipeline_shader;
+ uint32_t invalid_set_from;
bool pipeline_uses_restart_indices;
uint32_t pipeline_primitive_divisor;
uint32_t pipeline_primitive_minimum;
- Vector<uint32_t> pipeline_set_hashes;
- VkPipelineLayout pipeline_push_constant_layout;
+ Vector<uint32_t> pipeline_set_formats;
uint32_t pipeline_push_constant_size;
- uint32_t pipeline_push_constant_stages;
bool pipeline_push_constant_suppplied;
Validation() {
@@ -636,6 +727,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
index_array_size = 0; //not sent
index_array_max_index = 0; //not set
index_buffer_uses_restart_indices = false;
+ invalid_set_from = 0;
//pipeline state initalize
pipeline_active = false;
@@ -643,10 +735,11 @@ class RenderingDeviceVulkan : public RenderingDevice {
pipeline_vertex_format = INVALID_ID;
pipeline_uses_restart_indices = false;
pipeline_push_constant_size = 0;
- pipeline_push_constant_stages = 0;
pipeline_push_constant_suppplied = false;
}
} validation;
+
+#endif
};
DrawList *draw_list; //one for regular draw lists, multiple for split.
@@ -715,7 +808,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
public:
virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<PoolVector<uint8_t> > &p_data = Vector<PoolVector<uint8_t> >());
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture);
- virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, int p_layer, int p_mipmap);
+ virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap);
virtual Error texture_update(RID p_texture, uint32_t p_layer, const PoolVector<uint8_t> &p_data, bool p_sync_with_draw = false);
virtual PoolVector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer);
@@ -723,6 +816,8 @@ public:
virtual bool texture_is_shared(RID p_texture);
virtual bool texture_is_valid(RID p_texture);
+ virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false);
+
/*********************/
/**** FRAMEBUFFER ****/
/*********************/