Custom material support seems complete.

This commit is contained in:
Juan Linietsky 2019-07-27 10:23:24 -03:00
parent 8bbbb97336
commit 0586e18449
53 changed files with 1339 additions and 205 deletions

View file

@ -1215,7 +1215,7 @@ void Image::flip_x() {
}
}
int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps) {
int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps, int *r_mm_width, int *r_mm_height) {
int size = 0;
int w = p_width;
@ -1242,6 +1242,13 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &
size += s;
if (r_mm_width) {
*r_mm_width = bw;
}
if (r_mm_height) {
*r_mm_height = bh;
}
if (p_mipmaps >= 0 && mm == p_mipmaps)
break;
@ -1914,6 +1921,13 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format
return mm;
}
Size2i Image::get_image_mipmap_size(int p_width, int p_height, Format p_format, int p_mipmap) {
int mm;
Size2i ret;
_get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap, &ret.x, &ret.y);
return ret;
}
int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) {
if (p_mipmap <= 0) {

View file

@ -177,7 +177,7 @@ private:
_FORCE_INLINE_ void _get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const; //get where the mipmap begins in data
static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1);
static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = NULL, int *r_mm_height = NULL);
bool _can_modify(Format p_format) const;
_FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel);
@ -290,6 +290,7 @@ public:
static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false);
static int get_image_required_mipmaps(int p_width, int p_height, Format p_format);
static Size2i get_image_mipmap_size(int p_width, int p_height, Format p_format, int p_mipmap);
static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap);
enum CompressMode {

View file

@ -35,7 +35,7 @@
#include "core/rid_owner.h"
#include "core/self_list.h"
#include "scene/resources/mesh.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
class RasterizerSceneDummy : public RasterizerScene {

View file

@ -32,7 +32,7 @@
#define RASTERIZERCANVASGLES2_H
#include "rasterizer_storage_gles2.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "shaders/canvas.glsl.gen.h"
#include "shaders/lens_distorted.glsl.gen.h"

View file

@ -34,7 +34,7 @@
#include "rasterizer_canvas_gles2.h"
#include "rasterizer_scene_gles2.h"
#include "rasterizer_storage_gles2.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
class RasterizerGLES2 : public Rasterizer {

View file

@ -33,7 +33,7 @@
#include "core/pool_vector.h"
#include "core/self_list.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/shader_language.h"
#include "shader_compiler_gles2.h"
#include "shader_gles2.h"

View file

@ -32,7 +32,7 @@
#define RASTERIZERCANVASGLES3_H
#include "rasterizer_storage_gles3.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "shaders/canvas_shadow.glsl.gen.h"
#include "shaders/lens_distorted.glsl.gen.h"

View file

@ -34,7 +34,7 @@
#include "rasterizer_canvas_gles3.h"
#include "rasterizer_scene_gles3.h"
#include "rasterizer_storage_gles3.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
class RasterizerGLES3 : public Rasterizer {

View file

@ -32,7 +32,7 @@
#define RASTERIZERSTORAGEGLES3_H
#include "core/self_list.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/shader_language.h"
#include "shader_compiler_gles3.h"
#include "shader_gles3.h"

View file

@ -1009,6 +1009,7 @@ uint32_t RenderingDeviceVulkan::get_compressed_image_format_pixel_rshift(DataFor
uint32_t RenderingDeviceVulkan::get_image_format_required_size(DataFormat p_format, uint32_t p_width, uint32_t p_height, uint32_t p_depth, uint32_t p_mipmaps, uint32_t *r_blockw, uint32_t *r_blockh, uint32_t *r_depth) {
ERR_FAIL_COND_V(p_mipmaps == 0, 0);
uint32_t w = p_width;
uint32_t h = p_height;
uint32_t d = p_depth;
@ -1559,10 +1560,14 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
if (p_format.usage_bits & TEXTURE_USAGE_CAN_UPDATE_BIT) {
image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
if (p_format.usage_bits & TEXTURE_USAGE_CAN_RETRIEVE_BIT) {
if (p_format.usage_bits & TEXTURE_USAGE_CAN_COPY_FROM_BIT) {
image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
}
if (p_format.usage_bits & TEXTURE_USAGE_CAN_COPY_TO_BIT) {
image_create_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_create_info.queueFamilyIndexCount = 0;
image_create_info.pQueueFamilyIndices = NULL;
@ -1866,7 +1871,7 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
return id;
}
RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, int p_layer, int p_mipmap) {
RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap) {
Texture *src_texture = texture_owner.getornull(p_with_texture);
ERR_FAIL_COND_V(!src_texture, RID());
@ -1879,12 +1884,18 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
//create view
Texture texture = *src_texture;
ERR_FAIL_INDEX_V(p_mipmap, src_texture->mipmaps, RID());
uint32_t array_layer_multiplier = 1;
if (texture.type == TEXTURE_TYPE_CUBE_ARRAY || texture.type == TEXTURE_TYPE_CUBE) {
if (src_texture->type == TEXTURE_TYPE_CUBE_ARRAY || src_texture->type == TEXTURE_TYPE_CUBE) {
array_layer_multiplier = 6;
}
ERR_FAIL_INDEX_V(p_layer, src_texture->layers * array_layer_multiplier, RID());
Texture texture = *src_texture;
get_image_format_required_size(texture.format, texture.width, texture.height, texture.depth, p_mipmap + 1, &texture.width, &texture.height);
texture.mipmaps = 1;
texture.layers = 1;
VkImageViewCreateInfo image_view_create_info;
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@ -1928,7 +1939,6 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
image_view_create_info.components.b = component_swizzles[p_view.swizzle_b];
image_view_create_info.components.a = component_swizzles[p_view.swizzle_a];
ERR_FAIL_INDEX_V(p_mipmap, texture.mipmaps, RID());
image_view_create_info.subresourceRange.baseMipLevel = p_mipmap;
image_view_create_info.subresourceRange.levelCount = 1;
image_view_create_info.subresourceRange.layerCount = 1;
@ -2237,8 +2247,8 @@ PoolVector<uint8_t> RenderingDeviceVulkan::texture_get_data(RID p_texture, uint3
ERR_FAIL_COND_V_MSG(tex->bound, PoolVector<uint8_t>(),
"Texture can't be retrieved while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V_MSG(!(tex->usage_flags & TEXTURE_USAGE_CAN_RETRIEVE_BIT), PoolVector<uint8_t>(),
"Texture requires the TEXTURE_USAGE_CAN_RETRIEVE_BIT in order to be retrieved.");
ERR_FAIL_COND_V_MSG(!(tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), PoolVector<uint8_t>(),
"Texture requires the TEXTURE_USAGE_CAN_COPY_FROM_BIT in order to be retrieved.");
uint32_t layer_count = tex->layers;
if (tex->type == TEXTURE_TYPE_CUBE || tex->type == TEXTURE_TYPE_CUBE_ARRAY) {
@ -2428,6 +2438,173 @@ bool RenderingDeviceVulkan::texture_is_valid(RID p_texture) {
return texture_owner.owns(p_texture);
}
Error RenderingDeviceVulkan::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) {
Texture *src_tex = texture_owner.getornull(p_from_texture);
ERR_FAIL_COND_V(!src_tex, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_sync_with_draw && src_tex->bound, ERR_INVALID_PARAMETER,
"Source texture can't be copied while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V_MSG(!(src_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), ERR_INVALID_PARAMETER,
"Source texture requires the TEXTURE_USAGE_CAN_COPY_FROM_BIT in order to be retrieved.");
uint32_t src_layer_count = src_tex->layers;
uint32_t src_width, src_height, src_depth;
get_image_format_required_size(src_tex->format, src_tex->width, src_tex->height, src_tex->depth, p_src_mipmap + 1, &src_width, &src_height, &src_depth);
if (src_tex->type == TEXTURE_TYPE_CUBE || src_tex->type == TEXTURE_TYPE_CUBE_ARRAY) {
src_layer_count *= 6;
}
ERR_FAIL_COND_V(p_from.x < 0 || p_from.x + p_size.x > src_width, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_from.y < 0 || p_from.y + p_size.y > src_height, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_from.z < 0 || p_from.z + p_size.z > src_depth, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_src_mipmap >= src_tex->mipmaps, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_src_layer >= src_layer_count, ERR_INVALID_PARAMETER);
Texture *dst_tex = texture_owner.getornull(p_to_texture);
ERR_FAIL_COND_V(!dst_tex, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_sync_with_draw && dst_tex->bound, ERR_INVALID_PARAMETER,
"Destination texture can't be copied while a render pass that uses it is being created. Ensure render pass is finalized (and that it was created with RENDER_PASS_CONTENTS_FINISH) to unbind this texture.");
ERR_FAIL_COND_V_MSG(!(dst_tex->usage_flags & TEXTURE_USAGE_CAN_COPY_TO_BIT), ERR_INVALID_PARAMETER,
"Destination texture requires the TEXTURE_USAGE_CAN_COPY_TO_BIT in order to be retrieved.");
uint32_t dst_layer_count = dst_tex->layers;
uint32_t dst_width, dst_height, dst_depth;
get_image_format_required_size(dst_tex->format, dst_tex->width, dst_tex->height, dst_tex->depth, p_dst_mipmap + 1, &dst_width, &dst_height, &dst_depth);
if (dst_tex->type == TEXTURE_TYPE_CUBE || dst_tex->type == TEXTURE_TYPE_CUBE_ARRAY) {
dst_layer_count *= 6;
}
ERR_FAIL_COND_V(p_to.x < 0 || p_to.x + p_size.x > dst_width, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_to.y < 0 || p_to.y + p_size.y > dst_height, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_to.z < 0 || p_to.z + p_size.z > dst_depth, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_dst_mipmap >= dst_tex->mipmaps, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_dst_layer >= dst_layer_count, ERR_INVALID_PARAMETER);
VkCommandBuffer command_buffer = p_sync_with_draw ? frames[frame].draw_command_buffer : frames[frame].setup_command_buffer;
{
//PRE Copy the image
{ //Source
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = NULL;
image_memory_barrier.srcAccessMask = 0;
image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
image_memory_barrier.oldLayout = src_tex->unbound_layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = src_tex->image;
image_memory_barrier.subresourceRange.aspectMask = src_tex->aspect_mask;
image_memory_barrier.subresourceRange.baseMipLevel = p_src_mipmap;
image_memory_barrier.subresourceRange.levelCount = 1;
image_memory_barrier.subresourceRange.baseArrayLayer = p_src_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
}
{ //Dest
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = NULL;
image_memory_barrier.srcAccessMask = 0;
image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
image_memory_barrier.oldLayout = dst_tex->unbound_layout;
image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = dst_tex->image;
image_memory_barrier.subresourceRange.aspectMask = dst_tex->aspect_mask;
image_memory_barrier.subresourceRange.baseMipLevel = p_dst_mipmap;
image_memory_barrier.subresourceRange.levelCount = 1;
image_memory_barrier.subresourceRange.baseArrayLayer = p_dst_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
}
//COPY
{
VkImageCopy image_copy_region;
image_copy_region.srcSubresource.aspectMask = src_tex->aspect_mask;
image_copy_region.srcSubresource.baseArrayLayer = p_src_layer;
image_copy_region.srcSubresource.layerCount = 1;
image_copy_region.srcSubresource.mipLevel = p_src_mipmap;
image_copy_region.srcOffset.x = p_from.x;
image_copy_region.srcOffset.y = p_from.y;
image_copy_region.srcOffset.z = p_from.z;
image_copy_region.dstSubresource.aspectMask = src_tex->aspect_mask;
image_copy_region.dstSubresource.baseArrayLayer = p_dst_layer;
image_copy_region.dstSubresource.layerCount = 1;
image_copy_region.dstSubresource.mipLevel = p_dst_mipmap;
image_copy_region.dstOffset.x = p_to.x;
image_copy_region.dstOffset.y = p_to.y;
image_copy_region.dstOffset.z = p_to.z;
image_copy_region.extent.width = p_size.x;
image_copy_region.extent.height = p_size.y;
image_copy_region.extent.depth = p_size.z;
vkCmdCopyImage(command_buffer, src_tex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_tex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy_region);
}
// RESTORE LAYOUT for SRC and DST
{ //restore src
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = NULL;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
image_memory_barrier.newLayout = src_tex->unbound_layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = src_tex->image;
image_memory_barrier.subresourceRange.aspectMask = src_tex->aspect_mask;
image_memory_barrier.subresourceRange.baseMipLevel = p_src_mipmap;
image_memory_barrier.subresourceRange.levelCount = src_tex->mipmaps;
image_memory_barrier.subresourceRange.baseArrayLayer = p_src_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
}
{ //make dst readable
VkImageMemoryBarrier image_memory_barrier;
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
image_memory_barrier.pNext = NULL;
image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
image_memory_barrier.newLayout = dst_tex->unbound_layout;
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.image = dst_tex->image;
image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
image_memory_barrier.subresourceRange.baseMipLevel = p_src_mipmap;
image_memory_barrier.subresourceRange.levelCount = 1;
image_memory_barrier.subresourceRange.baseArrayLayer = p_src_layer;
image_memory_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &image_memory_barrier);
}
}
return OK;
}
bool RenderingDeviceVulkan::texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const {
ERR_FAIL_INDEX_V(p_format, DATA_FORMAT_MAX, false);
@ -3152,10 +3329,29 @@ static VkShaderStageFlagBits shader_stage_masks[RenderingDevice::SHADER_STAGE_MA
VK_SHADER_STAGE_COMPUTE_BIT,
};
bool RenderingDeviceVulkan::_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 RenderingDeviceVulkan::_shader_uniform_debug(RID p_shader, int p_set) {
String ret;
const Shader *shader = shader_owner.getornull(p_shader);
ERR_FAIL_COND_V(!shader, String());
for (int i = 0; i < shader->sets.size(); i++) {
if (p_set >= 0 && i != p_set) {
continue;
}
for (int j = 0; j < shader->sets[i].uniform_info.size(); j++) {
const UniformInfo &ui = shader->sets[i].uniform_info[j];
if (ret != String()) {
ret += "\n";
}
ret += "Set: " + itos(i) + " Binding: " + itos(ui.binding) + " Type: " + shader_uniform_names[ui.type] + " Length: " + itos(ui.length);
}
}
return ret;
}
bool RenderingDeviceVulkan::_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) {
VkDescriptorSetLayoutBinding layout_binding;
Shader::UniformInfo info;
UniformInfo info;
switch (reflection.getType()->getBasicType()) {
case glslang::EbtSampler: {
@ -3285,6 +3481,13 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
uint32_t set = reflection.getType()->getQualifier().hasSet() ? reflection.getType()->getQualifier().layoutSet : 0;
if (set >= MAX_UNIFORM_SETS) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").";
}
return false;
}
if (set >= limits.maxBoundDescriptorSets) {
if (r_error) {
*r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").";
@ -3366,7 +3569,7 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
//descriptor layouts
Vector<Vector<VkDescriptorSetLayoutBinding> > bindings;
Vector<Vector<Shader::UniformInfo> > uniform_info;
Vector<Vector<UniformInfo> > uniform_info;
Shader::PushConstant push_constant;
push_constant.push_constant_size = 0;
push_constant.push_constants_vk_stage = 0;
@ -3451,7 +3654,7 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
//obtain bindings for descriptor layout
program.mapIO();
program.buildReflection();
program.buildReflection(EShReflectionAllBlockVariables);
//program.dumpReflection();
for (int j = 0; j < program.getNumUniformVariables(); j++) {
@ -3579,17 +3782,23 @@ RID RenderingDeviceVulkan::shader_create_from_source(const Vector<ShaderStageSou
//sort and hash
set.uniform_info.sort();
uint32_t h = set.uniform_info.size() ? hash_djb2_one_32(0) : 0;
for (int j = 0; j < set.uniform_info.size(); j++) {
const Shader::UniformInfo &ui = set.uniform_info[j];
h = hash_djb2_one_32(ui.type, h);
h = hash_djb2_one_32(ui.binding, h);
h = hash_djb2_one_32(ui.length, h);
h = hash_djb2_one_32(ui.stages, h);
uint32_t format = 0; //no format, default
if (set.uniform_info.size()) {
//has data, needs an actual format;
UniformSetFormat usformat;
usformat.uniform_info = set.uniform_info;
Map<UniformSetFormat, uint32_t>::Element *E = uniform_set_format_cache.find(usformat);
if (E) {
format = E->get();
} else {
format = uniform_set_format_cache.size() + 1;
uniform_set_format_cache.insert(usformat, format);
}
}
shader.sets.push_back(set);
shader.set_hashes.push_back(h);
shader.set_formats.push_back(format);
}
}
@ -3873,7 +4082,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
const Uniform *uniforms = p_uniforms.ptr();
uint32_t set_uniform_count = set.uniform_info.size();
const Shader::UniformInfo *set_uniforms = set.uniform_info.ptr();
const UniformInfo *set_uniforms = set.uniform_info.ptr();
Vector<VkWriteDescriptorSet> writes;
DescriptorPoolKey pool_key;
@ -3886,7 +4095,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
Vector<RID> attachable_textures;
for (uint32_t i = 0; i < set_uniform_count; i++) {
const Shader::UniformInfo &set_uniform = set_uniforms[i];
const UniformInfo &set_uniform = set_uniforms[i];
int uniform_idx = -1;
for (int j = 0; j < (int)uniform_count; j++) {
if (uniforms[j].binding == set_uniform.binding) {
@ -4191,9 +4400,10 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
uniform_set.pool = pool;
uniform_set.pool_key = pool_key;
uniform_set.descriptor_set = descriptor_set;
uniform_set.pipeline_layout = shader->pipeline_layout;
uniform_set.hash = shader->set_hashes[p_shader_set];
uniform_set.format = shader->set_formats[p_shader_set];
uniform_set.attachable_textures = attachable_textures;
uniform_set.shader_set = p_shader_set;
uniform_set.shader_id = p_shader;
RID id = uniform_set_owner.make_rid(uniform_set);
//add dependencies
@ -4592,19 +4802,22 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
VkResult err = vkCreateGraphicsPipelines(device, NULL, 1, &graphics_pipeline_create_info, NULL, &pipeline.pipeline);
ERR_FAIL_COND_V(err, RID());
pipeline.dynamic_state = p_dynamic_state_flags;
pipeline.framebuffer_format = p_framebuffer_format;
pipeline.vertex_format = p_vertex_format;
pipeline.uses_restart_indices = input_assembly_create_info.primitiveRestartEnable;
pipeline.set_hashes = shader->set_hashes;
pipeline.push_constant_size = shader->push_constant.push_constant_size;
pipeline.set_formats = shader->set_formats;
pipeline.push_constant_stages = shader->push_constant.push_constants_vk_stage;
pipeline.pipeline_layout = shader->pipeline_layout;
pipeline.shader = p_shader;
pipeline.push_constant_size = shader->push_constant.push_constant_size;
#ifdef DEBUG_ENABLED
pipeline.validation.dynamic_state = p_dynamic_state_flags;
pipeline.validation.framebuffer_format = p_framebuffer_format;
pipeline.validation.vertex_format = p_vertex_format;
pipeline.validation.uses_restart_indices = input_assembly_create_info.primitiveRestartEnable;
static const uint32_t primitive_divisor[RENDER_PRIMITIVE_MAX] = {
1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1
};
pipeline.primitive_divisor = primitive_divisor[p_render_primitive];
pipeline.validation.primitive_divisor = primitive_divisor[p_render_primitive];
static const uint32_t primitive_minimum[RENDER_PRIMITIVE_MAX] = {
1,
2,
@ -4618,8 +4831,8 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
3,
1,
};
pipeline.primitive_minimum = primitive_minimum[p_render_primitive];
pipeline.validation.primitive_minimum = primitive_minimum[p_render_primitive];
#endif
//create ID to associate with this pipeline
RID id = pipeline_owner.make_rid(pipeline);
//now add aall the dependencies
@ -4756,6 +4969,8 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
Texture *texture = texture_owner.getornull(p_framebuffer->texture_ids[i]);
ERR_FAIL_COND_V(!texture, ERR_BUG);
attachments.push_back(texture->view);
ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG);
ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG);
}
framebuffer_create_info.attachmentCount = attachments.size();
framebuffer_create_info.pAttachments = attachments.ptr();
@ -5082,51 +5297,97 @@ void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RI
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
const RenderPipeline *pipeline = pipeline_owner.getornull(p_render_pipeline);
ERR_FAIL_COND(!pipeline);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND(pipeline->validation.framebuffer_format != dl->validation.framebuffer_format);
#endif
ERR_FAIL_COND(pipeline->framebuffer_format != dl->validation.framebuffer_format);
if (p_render_pipeline == dl->state.pipeline) {
return; //redundant state, return.
}
dl->state.pipeline = p_render_pipeline;
dl->state.pipeline_layout = pipeline->pipeline_layout;
vkCmdBindPipeline(dl->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
if (dl->state.pipeline_shader != pipeline->shader) {
// shader changed, so descriptor sets may become incompatible.
//go through ALL sets, and unbind them (and all those above) if the format is different
uint32_t pcount = pipeline->set_formats.size(); //formats count in this pipeline
dl->state.set_count = MAX(dl->state.set_count, pcount);
const uint32_t *pformats = pipeline->set_formats.ptr(); //pipeline set formats
bool sets_valid = true; //once invalid, all above become invalid
for (uint32_t i = 0; i < pcount; i++) {
//if a part of the format is different, invalidate it (and the rest)
if (!sets_valid || dl->state.sets[i].pipeline_expected_format != pformats[i]) {
dl->state.sets[i].bound = false;
dl->state.sets[i].pipeline_expected_format = pformats[i];
sets_valid = false;
}
}
for (uint32_t i = pcount; i < dl->state.set_count; i++) {
//unbind the ones above (not used) if exist
dl->state.sets[i].bound = false;
}
dl->state.set_count = pcount; //update set count
if (pipeline->push_constant_size) {
dl->state.pipeline_push_constant_stages = pipeline->push_constant_stages;
#ifdef DEBUG_ENABLED
dl->validation.pipeline_push_constant_suppplied = false;
#endif
}
}
#ifdef DEBUG_ENABLED
//update render pass pipeline info
dl->validation.pipeline_active = true;
dl->validation.pipeline_dynamic_state = pipeline->dynamic_state;
dl->validation.pipeline_vertex_format = pipeline->vertex_format;
dl->validation.pipeline_uses_restart_indices = pipeline->uses_restart_indices;
dl->validation.pipeline_primitive_divisor = pipeline->primitive_divisor;
dl->validation.pipeline_primitive_minimum = pipeline->primitive_minimum;
dl->validation.pipeline_set_hashes = pipeline->set_hashes;
dl->validation.pipeline_dynamic_state = pipeline->validation.dynamic_state;
dl->validation.pipeline_vertex_format = pipeline->validation.vertex_format;
dl->validation.pipeline_uses_restart_indices = pipeline->validation.uses_restart_indices;
dl->validation.pipeline_primitive_divisor = pipeline->validation.primitive_divisor;
dl->validation.pipeline_primitive_minimum = pipeline->validation.primitive_minimum;
dl->validation.pipeline_push_constant_size = pipeline->push_constant_size;
if (pipeline->push_constant_size) {
dl->validation.pipeline_push_constant_stages = pipeline->push_constant_stages;
dl->validation.pipeline_push_constant_suppplied = false;
dl->validation.pipeline_push_constant_layout = pipeline->pipeline_layout;
}
#endif
}
void RenderingDeviceVulkan::draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) {
ERR_FAIL_COND_MSG(p_index >= limits.maxBoundDescriptorSets,
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(p_index >= limits.maxBoundDescriptorSets || p_index > MAX_UNIFORM_SETS,
"Attempting to bind a descriptor set (" + itos(p_index) + ") greater than what the hardware supports (" + itos(limits.maxBoundDescriptorSets) + ").");
#endif
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
const UniformSet *uniform_set = uniform_set_owner.getornull(p_uniform_set);
ERR_FAIL_COND(!uniform_set);
if ((uint32_t)dl->validation.set_hashes.size() <= p_index) {
uint32_t csize = dl->validation.set_hashes.size();
uint32_t new_size = p_index + 1;
dl->validation.set_hashes.resize(new_size);
for (uint32_t i = csize; i < new_size; i++) {
dl->validation.set_hashes.write[i] = 0;
}
if (p_index > dl->state.set_count) {
dl->state.set_count = p_index;
}
dl->state.sets[p_index].descriptor_set = uniform_set->descriptor_set; //update set pointer
dl->state.sets[p_index].bound = false; //needs rebind
dl->state.sets[p_index].uniform_set_format = uniform_set->format;
dl->state.sets[p_index].uniform_set = p_uniform_set;
#ifdef DEBUG_ENABLED
{ //validate that textures bound are not attached as framebuffer bindings
uint32_t attachable_count = uniform_set->attachable_textures.size();
const RID *attachable_ptr = uniform_set->attachable_textures.ptr();
@ -5139,38 +5400,53 @@ void RenderingDeviceVulkan::draw_list_bind_uniform_set(DrawListID p_list, RID p_
}
}
}
dl->validation.set_hashes.write[p_index] = uniform_set->hash;
vkCmdBindDescriptorSets(dl->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, uniform_set->pipeline_layout, p_index, 1, &uniform_set->descriptor_set, 0, NULL);
#endif
}
void RenderingDeviceVulkan::draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) {
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
const VertexArray *vertex_array = vertex_array_owner.getornull(p_vertex_array);
ERR_FAIL_COND(!vertex_array);
if (dl->state.vertex_array == p_vertex_array) {
return; //already set
}
dl->state.vertex_array = p_vertex_array;
#ifdef DEBUG_ENABLED
dl->validation.vertex_format = vertex_array->description;
dl->validation.vertex_array_size = vertex_array->vertex_count;
dl->validation.vertex_max_instances_allowed = vertex_array->max_instances_allowed;
#endif
vkCmdBindVertexBuffers(dl->command_buffer, 0, vertex_array->buffers.size(), vertex_array->buffers.ptr(), vertex_array->offsets.ptr());
}
void RenderingDeviceVulkan::draw_list_bind_index_array(DrawListID p_list, RID p_index_array) {
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
const IndexArray *index_array = index_array_owner.getornull(p_index_array);
ERR_FAIL_COND(!index_array);
if (dl->state.index_array == p_index_array) {
return; //already set
}
dl->state.index_array = p_index_array;
#ifdef DEBUG_ENABLED
dl->validation.index_array_size = index_array->indices;
dl->validation.index_array_max_index = index_array->max_index;
dl->validation.index_array_offset = index_array->offset;
#endif
vkCmdBindIndexBuffer(dl->command_buffer, index_array->buffer, index_array->offset, index_array->index_type);
}
@ -5187,10 +5463,15 @@ void RenderingDeviceVulkan::draw_list_set_push_constant(DrawListID p_list, void
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(p_data_size != dl->validation.pipeline_push_constant_size,
"This render pipeline requires (" + itos(dl->validation.pipeline_push_constant_size) + ") bytes of push constant data, supplied: (" + itos(p_data_size) + ")");
vkCmdPushConstants(dl->command_buffer, dl->validation.pipeline_push_constant_layout, dl->validation.pipeline_push_constant_stages, 0, p_data_size, p_data);
#endif
vkCmdPushConstants(dl->command_buffer, dl->state.pipeline_layout, dl->state.pipeline_push_constant_stages, 0, p_data_size, p_data);
dl->validation.pipeline_push_constant_suppplied = true;
}
@ -5198,8 +5479,11 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.pipeline_active,
"No render pipeline was set before attempting to draw.");
if (dl->validation.pipeline_vertex_format != INVALID_ID) {
@ -5219,30 +5503,39 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
ERR_FAIL_COND_MSG(!dl->validation.pipeline_push_constant_suppplied,
"The shader in this pipeline requires a push constant to be set before drawing, but it's not present.");
}
//compare hashes
if (dl->validation.pipeline_set_hashes.size()) {
ERR_FAIL_COND_MSG(dl->validation.pipeline_set_hashes.size() > dl->validation.set_hashes.size(),
"Render pipeline requires uniform sets which were not set at the time of drawing.");
uint32_t hash_count = dl->validation.pipeline_set_hashes.size();
const uint32_t *phashes = dl->validation.pipeline_set_hashes.ptr();
const uint32_t *shashes = dl->validation.set_hashes.ptr();
#endif
for (uint32_t i = 0; i < hash_count; i++) {
if (phashes[i] == 0) {
continue; //not used by pipeline, no need to check
}
if (phashes[i] != shashes[i]) {
if (shashes[i] == 0) {
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline");
} else {
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ") are not the same format as required by the pipeline shader.");
}
//Bind descriptor sets
for (uint32_t i = 0; i < dl->state.set_count; i++) {
if (dl->state.sets[i].pipeline_expected_format == 0) {
continue; //nothing expected by this pipeline
}
#ifdef DEBUG_ENABLED
if (dl->state.sets[i].pipeline_expected_format != dl->state.sets[i].uniform_set_format) {
if (dl->state.sets[i].uniform_set_format == 0) {
ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline");
} else if (uniform_set_owner.owns(dl->state.sets[i].uniform_set)) {
UniformSet *us = uniform_set_owner.getornull(dl->state.sets[i].uniform_set);
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(dl->state.pipeline_shader));
} else {
ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(dl->state.pipeline_shader));
}
}
#endif
if (!dl->state.sets[i].bound) {
//All good, see if this requires re-binding
vkCmdBindDescriptorSets(dl->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, dl->state.pipeline_layout, i, 1, &dl->state.sets[i].descriptor_set, 0, NULL);
dl->state.sets[i].bound = true;
}
}
if (p_use_indices) {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.index_array_size,
"Draw command requested indices, but no index buffer was set.");
if (dl->validation.pipeline_vertex_format != INVALID_ID) {
@ -5253,37 +5546,42 @@ void RenderingDeviceVulkan::draw_list_draw(DrawListID p_list, bool p_use_indices
ERR_FAIL_COND_MSG(dl->validation.pipeline_uses_restart_indices != dl->validation.index_buffer_uses_restart_indices,
"The usage of restart indices in index buffer does not match the render primitive in the pipeline.");
#endif
uint32_t to_draw = dl->validation.index_array_size;
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(to_draw < dl->validation.pipeline_primitive_minimum,
"Too few indices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(dl->validation.pipeline_primitive_minimum) + ").");
ERR_FAIL_COND_MSG((to_draw % dl->validation.pipeline_primitive_divisor) != 0,
"Index amount (" + itos(to_draw) + ") must be a multiple of the amount of indices required by the render primitive (" + itos(dl->validation.pipeline_primitive_divisor) + ").");
#endif
vkCmdDrawIndexed(dl->command_buffer, to_draw, p_instances, dl->validation.index_array_offset, 0, 0);
} else {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(dl->validation.pipeline_vertex_format == INVALID_ID,
"Draw command lacks indices, but pipeline format does not use vertices.");
#endif
uint32_t to_draw = dl->validation.vertex_array_size;
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(to_draw < dl->validation.pipeline_primitive_minimum,
"Too few vertices (" + itos(to_draw) + ") for the render primitive set in the render pipeline (" + itos(dl->validation.pipeline_primitive_minimum) + ").");
ERR_FAIL_COND_MSG((to_draw % dl->validation.pipeline_primitive_divisor) != 0,
"Vertex amount (" + itos(to_draw) + ") must be a multiple of the amount of vertices required by the render primitive (" + itos(dl->validation.pipeline_primitive_divisor) + ").");
#endif
vkCmdDraw(dl->command_buffer, to_draw, p_instances, 0, 0);
}
}
void RenderingDeviceVulkan::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) {
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
Rect2i rect = p_rect;
rect.position += dl->viewport.position;
@ -5303,7 +5601,9 @@ void RenderingDeviceVulkan::draw_list_enable_scissor(DrawListID p_list, const Re
void RenderingDeviceVulkan::draw_list_disable_scissor(DrawListID p_list) {
DrawList *dl = _get_draw_list_ptr(p_list);
ERR_FAIL_COND(!dl);
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified.");
#endif
VkRect2D scissor;
scissor.offset.x = dl->viewport.position.x;

View file

@ -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 ****/
/*********************/

View file

@ -591,7 +591,7 @@ def build_rd_header(filename):
out_file_class = out_file_base.replace(".glsl.gen.h", "").title().replace("_", "").replace(".", "") + "ShaderRD"
fd.write("\n\n")
fd.write("#include \"servers/visual/rasterizer/shader_rd.h\"\n\n\n")
fd.write("#include \"servers/visual/rasterizer_rd/shader_rd.h\"\n\n\n")
fd.write("class " + out_file_class + " : public ShaderRD {\n\n")
fd.write("public:\n\n")

View file

@ -39,7 +39,7 @@
#include "main/input_default.h"
//#include "power_android.h"
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
class GodotJavaWrapper;
class GodotIOJavaWrapper;

View file

@ -43,7 +43,7 @@
#include "ios.h"
#include "main/input_default.h"
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
class OSIPhone : public OS_Unix {

View file

@ -35,7 +35,7 @@
#include "drivers/unix/os_unix.h"
#include "main/input_default.h"
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include <emscripten/html5.h>

View file

@ -42,7 +42,7 @@
#include "main/input_default.h"
#include "power_osx.h"
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/visual_server_wrap_mt.h"
#include "servers/visual_server.h"

View file

@ -43,7 +43,7 @@
#include "platform/x11/power_x11.h"
#endif
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
#undef CursorShape

View file

@ -41,7 +41,7 @@
#include "main/input_default.h"
#include "power_uwp.h"
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
#include <fcntl.h>

View file

@ -43,7 +43,7 @@
#include "main/input_default.h"
#include "power_windows.h"
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
#ifdef XAUDIO2_ENABLED
#include "drivers/xaudio2/audio_driver_xaudio2.h"

View file

@ -37,7 +37,7 @@
//#include "drivers/gles3/rasterizer_gles3.h"
#include "errno.h"
#include "key_mapping_x11.h"
#include "servers/visual/rasterizer/rasterizer_rd.h"
#include "servers/visual/rasterizer_rd/rasterizer_rd.h"
#include "servers/visual/visual_server_raster.h"
#include "servers/visual/visual_server_wrap_mt.h"

View file

@ -42,7 +42,7 @@
#include "main/input_default.h"
#include "power_x11.h"
#include "servers/audio_server.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
//#include "servers/visual/visual_server_wrap_mt.h"
#include "drivers/vulkan/rendering_device_vulkan.h"

View file

@ -4,4 +4,4 @@ Import('env')
env.add_source_files(env.servers_sources, "*.cpp")
SConscript("rasterizer/SCsub")
SConscript("rasterizer_rd/SCsub")

View file

@ -0,0 +1,142 @@
#include "effects_rd.h"
RID EffectsRD::_get_uniform_set_from_texture(RID p_texture) {
if (texture_to_uniform_set_cache.has(p_texture)) {
RID uniform_set = texture_to_uniform_set_cache[p_texture];
if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
return uniform_set;
}
}
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
u.binding = 0;
u.ids.push_back(default_sampler);
u.ids.push_back(p_texture);
uniforms.push_back(u);
//any thing with the same configuration (one texture in binding 0 for set 0), is good
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blur.shader.version_get_shader(blur.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
return uniform_set;
}
void EffectsRD::copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
if (p_region != Rect2()) {
blur.push_constant.flags = BLUR_FLAG_USE_BLUR_SECTION;
blur.push_constant.section[0] = p_region.position.x;
blur.push_constant.section[1] = p_region.position.y;
blur.push_constant.section[2] = p_region.size.width;
blur.push_constant.section[3] = p_region.size.height;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region) {
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
uint32_t base_flags = 0;
if (p_region != Rect2()) {
base_flags = BLUR_FLAG_USE_BLUR_SECTION;
blur.push_constant.section[0] = p_region.position.x;
blur.push_constant.section[1] = p_region.position.y;
blur.push_constant.section[2] = p_region.size.width;
blur.push_constant.section[3] = p_region.size.height;
}
blur.push_constant.pixel_size[0] = p_pixel_size.x;
blur.push_constant.pixel_size[1] = p_pixel_size.y;
//HORIZONTAL
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL;
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
//VERTICAL
draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
blur.push_constant.flags = base_flags;
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
EffectsRD::EffectsRD() {
// Initialize blur
Vector<String> blur_modes;
blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n");
blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n");
blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n");
blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n");
blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n");
blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n#define DOF_NEAR_BLUR_MERGE\n");
blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n#define DOF_NEAR_BLUR_MERGE\n");
blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n#define DOF_NEAR_BLUR_MERGE\n");
blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_LOW\n");
blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_MEDIUM\n");
blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_HIGH\n");
blur_modes.push_back("\n#define MODE_SSAO_MERGE\n");
blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n");
blur.shader.initialize(blur_modes);
zeromem(&blur.push_constant, sizeof(BlurPushConstant));
blur.shader_version = blur.shader.version_create();
for (int i = 0; i < BLUR_MODE_MAX; i++) {
blur.pipelines[i].setup(blur.shader.version_get_shader(blur.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
}
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.max_lod = 0;
default_sampler = RD::get_singleton()->sampler_create(sampler);
{ //create index array for copy shaders
PoolVector<uint8_t> pv;
pv.resize(6 * 4);
{
PoolVector<uint8_t>::Write w = pv.write();
int *p32 = (int *)w.ptr();
p32[0] = 0;
p32[1] = 1;
p32[2] = 2;
p32[3] = 0;
p32[4] = 2;
p32[5] = 3;
}
index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6);
}
}
EffectsRD::~EffectsRD() {
}

View file

@ -0,0 +1,87 @@
#ifndef EFFECTS_RD_H
#define EFFECTS_RD_H
#include "render_pipeline_vertex_format_cache_rd.h"
#include "shaders/blur.glsl.gen.h"
class EffectsRD {
enum BlurMode {
BLUR_MODE_GAUSSIAN_BLUR,
BLUR_MODE_GAUSSIAN_GLOW,
BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
BLUR_MODE_DOF_NEAR_LOW,
BLUR_MODE_DOF_NEAR_MEDIUM,
BLUR_MODE_DOF_NEAR_HIGH,
BLUR_MODE_DOF_NEAR_MERGE_LOW,
BLUR_MODE_DOF_NEAR_MERGE_MEDIUM,
BLUR_MODE_DOF_NEAR_MERGE_HIGH,
BLUR_MODE_DOF_FAR_LOW,
BLUR_MODE_DOF_FAR_MEDIUM,
BLUR_MODE_DOF_FAR_HIGH,
BLUR_MODE_SSAO_MERGE,
BLUR_MODE_SIMPLY_COPY,
BLUR_MODE_MAX,
};
enum {
BLUR_FLAG_HORIZONTAL = (1 << 0),
BLUR_FLAG_USE_BLUR_SECTION = (1 << 1),
BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4)
};
struct BlurPushConstant {
float section[4];
float pixel_size[2];
uint32_t flags;
uint32_t pad;
//glow
float glow_strength;
float glow_bloom;
float glow_hdr_threshold;
float glow_hdr_scale;
float glow_exposure;
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
//dof
float dof_begin;
float dof_end;
float dof_radius;
float dof_pad;
float dof_dir[2];
float camera_z_far;
float camera_z_near;
float ssao_color[4];
};
struct Blur {
BlurPushConstant push_constant;
BlurShaderRD shader;
RID shader_version;
RenderPipelineVertexFormatCacheRD pipelines[BLUR_MODE_MAX];
} blur;
RID default_sampler;
RID index_buffer;
RID index_array;
Map<RID, RID> texture_to_uniform_set_cache;
RID _get_uniform_set_from_texture(RID p_texture);
public:
void copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
EffectsRD();
~EffectsRD();
};
#endif // EFFECTS_RD_H

View file

@ -1303,7 +1303,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_
}
}
void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights) {
void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set) {
Item *current_clip = NULL;
@ -1323,6 +1323,9 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP_COLOR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, clear_colors);
if (p_screen_uniform_set.is_valid()) {
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_screen_uniform_set, 3);
}
RID prev_material;
PipelineVariants *pipeline_variants = &shader.pipeline_variants;
@ -1348,18 +1351,16 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
if (ci->material != prev_material) {
MaterialData *material_data;
MaterialData *material_data = NULL;
if (ci->material.is_valid()) {
material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
print_line("has material data");
}
if (material_data) {
if (material_data->shader_data->version.is_valid()) {
if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) {
pipeline_variants = &material_data->shader_data->pipeline_variants;
if (material_data->uniform_set.is_valid()) {
print_line("bound uniform set");
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, 1);
}
} else {
@ -1370,7 +1371,6 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count,
}
}
print_line("go render");
_render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants);
prev_material = ci->material;
@ -1410,6 +1410,10 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
state_buffer.canvas_modulate[2] = p_modulate.b;
state_buffer.canvas_modulate[3] = p_modulate.a;
Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
state_buffer.time = state.time;
RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true);
}
@ -1480,6 +1484,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
Item *ci = p_item_list;
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
RID screen_uniform_set;
while (ci) {
@ -1493,19 +1498,27 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
}
}
if (!material_screen_texture_found && ci->material.is_valid()) {
if (ci->material.is_valid()) {
MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D);
if (md->shader_data->uses_screen_texture) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
if (md && md->shader_data->valid && md->shader_data->uses_screen_texture) {
if (!material_screen_texture_found) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
}
if (screen_uniform_set.is_null()) {
RID backbuffer_shader = shader.canvas_shader.version_get_shader(md->shader_data->version, 0); //any version is fine
screen_uniform_set = storage->render_target_get_back_buffer_uniform_set(p_to_render_target, backbuffer_shader);
}
}
}
if (backbuffer_copy) {
//render anything pending, including clearing if no items
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set);
item_count = 0;
storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect);
backbuffer_copy = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
}
@ -1513,7 +1526,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
items[item_count++] = ci;
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set);
//then reset
item_count = 0;
}
@ -1771,7 +1784,6 @@ void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, VS::Canv
void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
//compile
print_line("shader set code?");
code = p_code;
valid = false;
ubo_size = 0;
@ -1787,7 +1799,7 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
int light_mode = LIGHT_MODE_NORMAL;
int blend_mode = BLEND_MODE_MIX;
bool uses_screen_texture = false;
uses_screen_texture = false;
ShaderCompilerRD::IdentifierActions actions;
@ -1833,6 +1845,7 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) {
print_line("\n**light_code:\n" + gen_code.light);
#endif
canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines);
ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
ubo_offsets = gen_code.uniform_offsets;
@ -2304,6 +2317,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
actions.base_texture_binding_index = 2;
actions.texture_layout_set = 1;
actions.base_uniform_string = "material.";
actions.default_filter = ShaderLanguage::FILTER_LINEAR;
actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
shader.compiler.initialize(actions);
}

View file

@ -1,13 +1,13 @@
#ifndef RASTERIZER_CANVAS_RD_H
#define RASTERIZER_CANVAS_RD_H
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer/render_pipeline_vertex_format_cache_rd.h"
#include "servers/visual/rasterizer/shader_compiler_rd.h"
#include "servers/visual/rasterizer/shaders/canvas.glsl.gen.h"
#include "servers/visual/rasterizer/shaders/canvas_occlusion.glsl.gen.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
#include "servers/visual/rendering_device.h"
#include "servers/visual/rasterizer_rd/shader_compiler_rd.h"
#include "servers/visual/rasterizer_rd/shaders/canvas.glsl.gen.h"
#include "servers/visual/rasterizer_rd/shaders/canvas_occlusion.glsl.gen.h"
class RasterizerCanvasRD : public RasterizerCanvas {
@ -382,8 +382,10 @@ class RasterizerCanvasRD : public RasterizerCanvas {
float screen_transform[16];
float canvas_normal_transform[16];
float canvas_modulate[4];
float screen_pixel_size[2];
float time;
float pad[3];
float pad;
//uint32_t light_count;
//uint32_t pad[3];
};
@ -433,7 +435,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags);
void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights);
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);

View file

@ -2,10 +2,10 @@
#define RASTERIZER_RD_H
#include "core/os/os.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer/rasterizer_canvas_rd.h"
#include "servers/visual/rasterizer/rasterizer_scene_forward_rd.h"
#include "servers/visual/rasterizer/rasterizer_storage_rd.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/rasterizer_rd/rasterizer_canvas_rd.h"
#include "servers/visual/rasterizer_rd/rasterizer_scene_forward_rd.h"
#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h"
class RasterizerRD : public Rasterizer {
protected:
RasterizerCanvasRD *canvas;

View file

@ -1,7 +1,7 @@
#ifndef RASTERIZER_SCENE_FORWARD_RD_H
#define RASTERIZER_SCENE_FORWARD_RD_H
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
class RasterizerSceneForwardRD : public RasterizerScene {
public:

View file

@ -507,7 +507,7 @@ RID RasterizerStorageRD::texture_2d_create(const Ref<Image> &p_image) {
rd_format.mipmaps = texture.mipmaps;
rd_format.type = texture.rd_type;
rd_format.samples = RD::TEXTURE_SAMPLES_1;
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_RETRIEVE_BIT;
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
rd_format.shareable_formats.push_back(texture.rd_format);
rd_format.shareable_formats.push_back(texture.rd_format_srgb);
@ -792,7 +792,6 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) {
Shader *shader = shader_owner.getornull(p_shader);
ERR_FAIL_COND(!shader);
print_line("yey set code?");
shader->code = p_code;
String mode_string = ShaderLanguage::get_shader_type(p_code);
@ -1662,6 +1661,21 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) {
RD::get_singleton()->free(rt->color);
}
if (rt->backbuffer.is_valid()) {
RD::get_singleton()->free(rt->backbuffer);
rt->backbuffer = RID();
rt->backbuffer_fb = RID();
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
//just erase copies, since the rest are erased by dependency
RD::get_singleton()->free(rt->backbuffer_mipmaps[i].mipmap_copy);
}
rt->backbuffer_mipmaps.clear();
if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) {
RD::get_singleton()->free(rt->backbuffer_uniform_set);
}
rt->backbuffer_uniform_set = RID();
}
rt->framebuffer = RID();
rt->color = RID();
}
@ -1696,7 +1710,7 @@ void RasterizerStorageRD::_update_render_target(RenderTarget *rt) {
rd_format.mipmaps = 1;
rd_format.type = RD::TEXTURE_TYPE_2D;
rd_format.samples = RD::TEXTURE_SAMPLES_1;
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_RETRIEVE_BIT;
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
rd_format.shareable_formats.push_back(rt->color_format);
rd_format.shareable_formats.push_back(rt->color_format_srgb);
}
@ -1755,6 +1769,56 @@ void RasterizerStorageRD::_update_render_target(RenderTarget *rt) {
}
}
void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
ERR_FAIL_COND(rt->backbuffer.is_valid());
uint32_t mipmaps_required = Image::get_image_required_mipmaps(rt->size.width, rt->size.height, Image::FORMAT_RGBA8);
RD::TextureFormat tf;
tf.format = rt->color_format;
tf.width = rt->size.width;
tf.height = rt->size.height;
tf.type = RD::TEXTURE_TYPE_2D;
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
tf.mipmaps = mipmaps_required;
rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
{
Vector<RID> backbuffer_att;
RID backbuffer_fb_tex = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
backbuffer_att.push_back(backbuffer_fb_tex);
rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(backbuffer_att);
}
//create mipmaps
for (uint32_t i = 1; i < mipmaps_required; i++) {
RenderTarget::BackbufferMipmap mm;
{
mm.mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
Vector<RID> mm_fb_at;
mm_fb_at.push_back(mm.mipmap);
mm.mipmap_fb = RD::get_singleton()->framebuffer_create(mm_fb_at);
}
{
Size2 mm_size = Image::get_image_mipmap_size(tf.width, tf.height, Image::FORMAT_RGBA8, i);
RD::TextureFormat mmtf = tf;
mmtf.width = mm_size.width;
mmtf.height = mm_size.height;
mmtf.mipmaps = 1;
mm.mipmap_copy = RD::get_singleton()->texture_create(mmtf, RD::TextureView());
Vector<RID> mm_fb_at;
mm_fb_at.push_back(mm.mipmap_copy);
mm.mipmap_copy_fb = RD::get_singleton()->framebuffer_create(mm_fb_at);
}
rt->backbuffer_mipmaps.push_back(mm);
}
}
RID RasterizerStorageRD::render_target_create() {
RenderTarget render_target;
@ -1866,6 +1930,65 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) {
rt->clear_requested = false;
}
void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
}
Rect2i region = p_region;
Rect2 blur_region;
if (region == Rect2i()) {
region.size = rt->size;
} else {
blur_region = region;
blur_region.position /= rt->size;
blur_region.size /= rt->size;
}
//single texture copy for backbuffer
RD::get_singleton()->texture_copy(rt->color, rt->backbuffer, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
//effects.copy(rt->color, rt->backbuffer_fb, blur_region);
//then mipmap blur
RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
Vector2 pixel_size = Vector2(1.0 / rt->size.width, 1.0 / rt->size.height);
for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
pixel_size *= 2.0; //go halfway
const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
effects.gaussian_blur(prev_texture, mm.mipmap_copy_fb, mm.mipmap_copy, mm.mipmap_fb, pixel_size, blur_region);
prev_texture = mm.mipmap;
}
}
RID RasterizerStorageRD::render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader) {
RenderTarget *rt = render_target_owner.getornull(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
if (!rt->backbuffer.is_valid()) {
_create_render_target_backbuffer(rt);
}
if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) {
return rt->backbuffer_uniform_set; //if still valid, return/reuse it.
}
//create otherwise
Vector<RD::Uniform> uniforms;
RD::Uniform u;
u.type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
u.ids.push_back(rt->backbuffer);
uniforms.push_back(u);
rt->backbuffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, 3);
ERR_FAIL_COND_V(!rt->backbuffer_uniform_set.is_valid(), RID());
return rt->backbuffer_uniform_set;
}
void RasterizerStorageRD::update_dirty_resources() {
_update_queued_materials();
}
@ -1930,6 +2053,10 @@ bool RasterizerStorageRD::free(RID p_rid) {
return true;
}
EffectsRD *RasterizerStorageRD::get_effects() {
return &effects;
}
RasterizerStorageRD::RasterizerStorageRD() {
material_update_list = NULL;

View file

@ -2,9 +2,11 @@
#define RASTERIZER_STORAGE_RD_H
#include "core/rid_owner.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer/shader_compiler_rd.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual/rasterizer_rd/effects_rd.h"
#include "servers/visual/rendering_device.h"
#include "servers/visual/rasterizer_rd/shader_compiler_rd.h"
class RasterizerStorageRD : public RasterizerStorage {
public:
enum ShaderType {
@ -168,6 +170,19 @@ private:
bool flags[RENDER_TARGET_FLAG_MAX];
RID backbuffer; //used for effects
RID backbuffer_fb;
struct BackbufferMipmap {
RID mipmap;
RID mipmap_fb;
RID mipmap_copy;
RID mipmap_copy_fb;
};
Vector<BackbufferMipmap> backbuffer_mipmaps;
RID backbuffer_uniform_set;
//texture generated for this owner (nor RD).
RID texture;
bool was_used;
@ -181,6 +196,11 @@ private:
void _clear_render_target(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
void _create_render_target_backbuffer(RenderTarget *rt);
/* EFFECTS */
EffectsRD effects;
public:
/* TEXTURE API */
@ -687,6 +707,8 @@ public:
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
bool render_target_was_used(RID p_render_target);
void render_target_set_as_unused(RID p_render_target);
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region);
RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color);
virtual bool render_target_is_clear_requested(RID p_render_target);
@ -723,6 +745,8 @@ public:
static RasterizerStorage *base_singleton;
EffectsRD *get_effects();
RasterizerStorageRD();
~RasterizerStorageRD();
};

View file

@ -10,7 +10,7 @@ RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_ve
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].vertex_id = p_vertex_format_id;
versions[version_count].pipeline = pipeline;
version_count++;
return pipeline;
@ -33,6 +33,7 @@ void RenderPipelineVertexFormatCacheRD::_clear() {
void RenderPipelineVertexFormatCacheRD::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) {
ERR_FAIL_COND(p_shader.is_null());
_clear();
shader = p_shader;
render_primitive = p_primitive;
rasterization_state = p_rasterization_state;

View file

@ -681,6 +681,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
sampler_name = actions.custom_samplers[texture_uniform];
} else {
if (shader->uniforms.has(texture_uniform)) {
print_line("shader from texture uniform " + itos(shader->uniforms[texture_uniform].filter) + ", " + itos(shader->uniforms[texture_uniform].repeat));
sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat);
} else {
bool found = false;

View file

@ -303,6 +303,17 @@ void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const S
}
}
bool ShaderRD::version_is_valid(RID p_version) {
Version *version = version_owner.getornull(p_version);
ERR_FAIL_COND_V(!version, false);
if (version->dirty) {
_compile_version(version);
}
return version->valid;
}
bool ShaderRD::version_free(RID p_version) {
if (version_owner.owns(p_version)) {

View file

@ -113,6 +113,8 @@ public:
return version->variants[p_variant];
}
bool version_is_valid(RID p_version);
bool version_free(RID p_version);
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");

View file

@ -5,3 +5,4 @@ Import('env')
if 'RD_GLSL' in env['BUILDERS']:
env.RD_GLSL('canvas.glsl');
env.RD_GLSL('canvas_occlusion.glsl');
env.RD_GLSL('blur.glsl');

View file

@ -0,0 +1,274 @@
/* clang-format off */
[vertex]
/* clang-format on */
#version 450
/* clang-format off */
VERSION_DEFINES
/* clang-format on */
#include "blur_inc.glsl"
layout(location =0) out vec2 uv_interp;
void main() {
vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));
uv_interp = base_arr[gl_VertexIndex];
if (bool(blur.flags&FLAG_USE_BLUR_SECTION)) {
uv_interp = blur.section.xy + uv_interp * blur.section.zw;
}
gl_Position = vec4( uv_interp *2.0 - 1.0, 0.0, 1.0);
}
/* clang-format off */
[fragment]
/* clang-format on */
#version 450
/* clang-format off */
VERSION_DEFINES
/* clang-format on */
#include "blur_inc.glsl"
layout(location =0) in vec2 uv_interp;
layout( set=0, binding=0 ) uniform sampler2D source_color;
#ifdef MODE_SSAO_MERGE
layout( set=1, binding=0 ) uniform sampler2D source_ssao;
#endif
#ifdef GLOW_USE_AUTO_EXPOSURE
layout( set=1, binding=0 ) uniform sampler2D source_auto_exposure;
#endif
layout(location = 0) out vec4 frag_color;
//DOF
#if defined(MODE_DOF_FAR_BLUR) || defined(MODE_DOF_NEAR_BLUR)
layout( set=1, binding=0 ) uniform sampler2D dof_source_depth;
#ifdef DOF_NEAR_BLUR_MERGE
layout( set=2, binding=0 ) uniform sampler2D source_dof_original;
#endif
#ifdef DOF_QUALITY_LOW
const int dof_kernel_size = 5;
const int dof_kernel_from = 2;
const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
#endif
#ifdef DOF_QUALITY_MEDIUM
const int dof_kernel_size = 11;
const int dof_kernel_from = 5;
const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
#endif
#ifdef DOF_QUALITY_HIGH
const int dof_kernel_size = 21;
const int dof_kernel_from = 10;
const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
#endif
#endif
void main() {
#ifdef MODE_GAUSSIAN_BLUR
//Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
if (bool(blur.flags&FLAG_HORIZONTAL)) {
vec2 pix_size = blur.pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
frag_color = color;
} else {
vec2 pix_size = blur.pixel_size;
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
frag_color = color;
}
#endif
#ifdef MODE_GAUSSIAN_GLOW
//Glow uses larger sigma 1 for a more rounded blur effect
if (bool(blur.flags&FLAG_HORIZONTAL)) {
vec2 pix_size = blur.pixel_size;
pix_size *= 0.5; //reading from larger buffer, so use more samples
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.165569;
color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.140367;
color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.106595;
color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.165569;
color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.140367;
color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.106595;
color *= blur.glow_strength;
frag_color = color;
} else {
vec2 pix_size = blur.pixel_size;
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.233062;
color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.122581;
color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.233062;
color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.122581;
color *= blur.glow_strength;
frag_color = color;
}
if (bool(blur.flags&FLAG_GLOW_FIRST_PASS)) {
#ifdef GLOW_USE_AUTO_EXPOSURE
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
#endif
frag_color *= blur.glow_exposure;
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
}
#endif
#ifdef MODE_DOF_FAR_BLUR
vec4 color_accum = vec4(0.0);
float depth = texture(dof_source_depth, uv_interp, 0.0).r;
depth = depth * 2.0 - 1.0;
if (bool(blur.flags&FLAG_USE_ORTHOGONAL_PROJECTION)) {
depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
} else {
depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
}
float amount = smoothstep(blur.dof_begin, blur.dof_end, depth);
float k_accum = 0.0;
for (int i = 0; i < dof_kernel_size; i++) {
int int_ofs = i - dof_kernel_from;
vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius;
float tap_k = dof_kernel[i];
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
tap_depth = tap_depth * 2.0 - 1.0;
if (bool(blur.flags&FLAG_USE_ORTHOGONAL_PROJECTION)) {
tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
} else {
tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
}
float tap_amount = mix(smoothstep(blur.dof_begin, blur.dof_end, tap_depth), 1.0, int_ofs == 0);
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k;
k_accum += tap_k * tap_amount;
color_accum += tap_color * tap_amount;
}
if (k_accum > 0.0) {
color_accum /= k_accum;
}
frag_color = color_accum; ///k_accum;
#endif
#ifdef MODE_DOF_NEAR_BLUR
vec4 color_accum = vec4(0.0);
float max_accum = 0.0;
for (int i = 0; i < dof_kernel_size; i++) {
int int_ofs = i - dof_kernel_from;
vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * blur.dof_radius;
float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from));
float tap_k = dof_kernel[i];
vec4 tap_color = texture(source_color, tap_uv, 0.0);
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
tap_depth = tap_depth * 2.0 - 1.0;
if (bool(blur.flags&FLAG_USE_ORTHOGONAL_PROJECTION)) {
tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
} else {
tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
}
float tap_amount = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
if (bool(blur.flags&FLAG_DOF_NEAR_FIRST_TAP)) {
tap_color.a = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
}
max_accum = max(max_accum, tap_amount * ofs_influence);
color_accum += tap_color * tap_k;
}
color_accum.a = max(color_accum.a, sqrt(max_accum));
#ifdef DOF_NEAR_BLUR_MERGE
{
vec4 original = texture(source_dof_original, uv_interp, 0.0);
color_accum = mix(original, color_accum, color_accum.a);
}
#endif
if (bool(blur.flags&FLAG_DOF_NEAR_FIRST_TAP)) {
frag_color = color_accum;
}
#endif
#ifdef MODE_SIMPLE_COPY
vec4 color = texture(source_color, uv_interp, 0.0);
frag_color = color;
#endif
#ifdef MODE_SSAO_MERGE
vec4 color = texture(source_color, uv_interp, 0.0);
float ssao = texture(source_ssao, uv_interp, 0.0).r;
frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0);
#endif
}

View file

@ -0,0 +1,35 @@
#define FLAG_HORIZONTAL (1<<0)
#define FLAG_USE_BLUR_SECTION (1<<1)
#define FLAG_USE_ORTHOGONAL_PROJECTION (1<<2)
#define FLAG_DOF_NEAR_FIRST_TAP (1<<3)
#define FLAG_GLOW_FIRST_PASS (1<<4)
layout(push_constant, binding = 1, std430) uniform Blur {
vec4 section;
vec2 pixel_size;
uint flags;
uint pad;
//glow
float glow_strength;
float glow_bloom;
float glow_hdr_threshold;
float glow_hdr_scale;
float glow_exposure;
float glow_white;
float glow_luminance_cap;
float glow_auto_exposure_grey;
//dof
float dof_begin;
float dof_end;
float dof_radius;
float dof_pad;
vec2 dof_dir;
float camera_z_far;
float camera_z_near;
vec4 ssao_color;
} blur;

View file

@ -354,14 +354,8 @@ void main() {
#endif
#if !defined(COLOR_USED)
//default behavior, texture by color
color *= texture(sampler2D(color_texture,texture_sampler), uv);
#endif
uint light_count = (draw_data.flags>>FLAGS_LIGHT_COUNT_SHIFT)&0xF; //max 16 lights
@ -402,7 +396,7 @@ void main() {
#if defined(SCREEN_UV_USED)
vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size;
vec2 screen_uv = gl_FragCoord.xy * canvas_data.screen_pixel_size;
#else
vec2 screen_uv = vec2(0.0);
#endif

View file

@ -1,5 +1,5 @@
/* SET0: Draw Primitive */
#define M_PI 3.14159265359
@ -25,6 +25,14 @@
#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26)
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
// In vulkan, sets should always be ordered using the following logic:
// Lower Sets: Sets that change format and layout less often
// Higher sets: Sets that change format and layout very often
// This is because changing a set for another with a different layout or format,
// invalidates all the upper ones.
/* SET0: Draw Primitive */
layout(push_constant, binding = 0, std430) uniform DrawData {
vec2 world_x;
vec2 world_y;
@ -132,6 +140,6 @@ layout(set = 2, binding = 6) uniform sampler shadow_sampler;
#ifdef SCREEN_TEXTURE_USED
layout(set = 3, binding = 1) uniform texture2D screen_texture;
layout(set = 3, binding = 0) uniform texture2D screen_texture;
#endif

View file

@ -294,8 +294,9 @@ public:
TEXTURE_USAGE_STORAGE_ATOMIC_BIT = (1 << 4),
TEXTURE_USAGE_CPU_READ_BIT = (1 << 5),
TEXTURE_USAGE_CAN_UPDATE_BIT = (1 << 6),
TEXTURE_USAGE_CAN_RETRIEVE_BIT = (1 << 7),
TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT = (1 << 8),
TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7),
TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8),
TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT = (1 << 9),
};
enum TextureSwizzle {
@ -328,13 +329,12 @@ public:
depth = 1;
array_layers = 1;
mipmaps = 1;
type = TEXTURE_TYPE_1D;
type = TEXTURE_TYPE_2D;
samples = TEXTURE_SAMPLES_1;
usage_bits = 0;
}
};
struct TextureView {
DataFormat format_override;
TextureSwizzle swizzle_r;
@ -353,15 +353,16 @@ public:
virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<PoolVector<uint8_t> > &p_data = Vector<PoolVector<uint8_t> >()) = 0;
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0;
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture,int p_layer,int p_mipmap) = 0;
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap) = 0;
virtual Error texture_update(RID p_texture, uint32_t p_layer, const PoolVector<uint8_t> &p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the begining of the frame, unless sync with draw is used, which is used to mix updates with draw calls
virtual PoolVector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush
virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const = 0;
virtual bool texture_is_shared(RID p_texture) =0;
virtual bool texture_is_shared(RID p_texture) = 0;
virtual bool texture_is_valid(RID p_texture) = 0;
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) = 0;
/*********************/
/**** FRAMEBUFFER ****/
/*********************/
@ -371,9 +372,9 @@ public:
TextureSamples samples;
uint32_t usage_flags;
AttachmentFormat() {
format=DATA_FORMAT_R8G8B8A8_UNORM;
samples=TEXTURE_SAMPLES_1;
usage_flags=0;
format = DATA_FORMAT_R8G8B8A8_UNORM;
samples = TEXTURE_SAMPLES_1;
usage_flags = 0;
}
};
@ -381,7 +382,7 @@ 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) = 0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) =0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0;
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0;
@ -563,7 +564,7 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0;
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size,const void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the begining of the frame, unless sync with draw is used, which is used to mix updates with draw calls
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the begining of the frame, unless sync with draw is used, which is used to mix updates with draw calls
/*************************/
/**** RENDER PIPELINE ****/
@ -824,7 +825,7 @@ public:
};
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 bool render_pipeline_is_valid(RID p_pipeline) =0;
virtual bool render_pipeline_is_valid(RID p_pipeline) = 0;
/****************/
/**** SCREEN ****/
@ -874,7 +875,6 @@ public:
virtual void draw_list_end() = 0;
/***************/
/**** FREE! ****/
/***************/
@ -912,13 +912,13 @@ public:
LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES,
LIMIT_MAX_VERTEX_INPUT_BINDINGS,
LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE,
LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT ,
LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
};
virtual int limit_get(Limit p_limit) =0;
virtual int limit_get(Limit p_limit) = 0;
//methods below not exposed, used by RenderingDeviceRD
virtual void prepare_screen_for_drawing() =0;
virtual void prepare_screen_for_drawing() = 0;
virtual void finalize_frame() = 0;
virtual void advance_frame() = 0;

View file

@ -31,7 +31,7 @@
#ifndef VISUALSERVERCANVAS_H
#define VISUALSERVERCANVAS_H
#include "rasterizer/rasterizer.h"
#include "rasterizer.h"
#include "visual_server_viewport.h"
class VisualServerCanvas {

View file

@ -31,7 +31,7 @@
#ifndef VISUAL_SERVER_GLOBALS_H
#define VISUAL_SERVER_GLOBALS_H
#include "rasterizer/rasterizer.h"
#include "rasterizer.h"
class VisualServerCanvas;
class VisualServerViewport;

View file

@ -32,7 +32,7 @@
#define VISUAL_SERVER_RASTER_H
#include "core/math/octree.h"
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
#include "visual_server_canvas.h"
#include "visual_server_globals.h"

View file

@ -31,7 +31,7 @@
#ifndef VISUALSERVERSCENE_H
#define VISUALSERVERSCENE_H
#include "servers/visual/rasterizer/rasterizer.h"
#include "servers/visual/rasterizer.h"
#include "core/math/geometry.h"
#include "core/math/octree.h"

View file

@ -33,7 +33,7 @@
#include "core/rid_owner.h"
#include "core/self_list.h"
#include "rasterizer/rasterizer.h"
#include "rasterizer.h"
#include "servers/arvr/arvr_interface.h"
#include "servers/visual_server.h"