Custom material support seems complete.
This commit is contained in:
parent
8bbbb97336
commit
0586e18449
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ****/
|
||||
/*********************/
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -4,4 +4,4 @@ Import('env')
|
|||
|
||||
env.add_source_files(env.servers_sources, "*.cpp")
|
||||
|
||||
SConscript("rasterizer/SCsub")
|
||||
SConscript("rasterizer_rd/SCsub")
|
||||
|
|
|
@ -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() {
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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 *¤t_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);
|
|
@ -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;
|
|
@ -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:
|
|
@ -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;
|
|
@ -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();
|
||||
};
|
|
@ -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;
|
|
@ -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;
|
|
@ -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)) {
|
|
@ -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 = "");
|
|
@ -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');
|
|
@ -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
|
||||
}
|
|
@ -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;
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#ifndef VISUALSERVERCANVAS_H
|
||||
#define VISUALSERVERCANVAS_H
|
||||
|
||||
#include "rasterizer/rasterizer.h"
|
||||
#include "rasterizer.h"
|
||||
#include "visual_server_viewport.h"
|
||||
|
||||
class VisualServerCanvas {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
Loading…
Reference in New Issue