Merge bf3983c318
into 171a69757f
This commit is contained in:
commit
7e439b75ad
|
@ -547,6 +547,21 @@
|
||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="texture_create_from_extension">
|
||||||
|
<return type="RID" />
|
||||||
|
<argument index="0" name="type" type="int" enum="RenderingDevice.TextureType" />
|
||||||
|
<argument index="1" name="format" type="int" enum="RenderingDevice.DataFormat" />
|
||||||
|
<argument index="2" name="samples" type="int" enum="RenderingDevice.TextureSamples" />
|
||||||
|
<argument index="3" name="flags" type="int" />
|
||||||
|
<argument index="4" name="image" type="int" />
|
||||||
|
<argument index="5" name="width" type="int" />
|
||||||
|
<argument index="6" name="height" type="int" />
|
||||||
|
<argument index="7" name="depth" type="int" />
|
||||||
|
<argument index="8" name="layers" type="int" />
|
||||||
|
<description>
|
||||||
|
Create a texture object based an image handle already created within an GDNative extension.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="texture_create_shared">
|
<method name="texture_create_shared">
|
||||||
<return type="RID" />
|
<return type="RID" />
|
||||||
<argument index="0" name="view" type="RDTextureView" />
|
<argument index="0" name="view" type="RDTextureView" />
|
||||||
|
|
|
@ -36,6 +36,16 @@
|
||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="_get_external_color_texture" qualifiers="virtual">
|
||||||
|
<return type="RID" />
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
|
<method name="_get_external_depth_texture" qualifiers="virtual">
|
||||||
|
<return type="RID" />
|
||||||
|
<description>
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="_get_name" qualifiers="virtual const">
|
<method name="_get_name" qualifiers="virtual const">
|
||||||
<return type="StringName" />
|
<return type="StringName" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -3622,6 +3622,12 @@ RID RasterizerStorageGLES3::render_target_create() {
|
||||||
return render_target_owner.make_rid(rt);
|
return render_target_owner.make_rid(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerStorageGLES3::render_target_update(RID p_render_target) {
|
||||||
|
// TODO need to look into if this applies here and how to implement it.
|
||||||
|
// The idea here is not to create the textures and framebuffer until we need it for the first time.
|
||||||
|
// Especially when XR is used we may end up creating things multiple times and then not using it.
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) {
|
void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) {
|
||||||
#ifdef OPENGL_DISABLE_RENDER_TARGETS
|
#ifdef OPENGL_DISABLE_RENDER_TARGETS
|
||||||
return;
|
return;
|
||||||
|
@ -3671,113 +3677,14 @@ RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
|
void RasterizerStorageGLES3::render_target_set_external_textures(RID p_render_target, RID p_color, RID p_depth) {
|
||||||
#ifdef OPENGL_DISABLE_RENDER_TARGETS
|
#ifdef OPENGL_DISABLE_RENDER_TARGETS
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
// TODO re-implement this once stereo support has been added
|
||||||
ERR_FAIL_COND(!rt);
|
|
||||||
|
|
||||||
if (p_texture_id == 0) {
|
return;
|
||||||
if (rt->external.fbo != 0) {
|
|
||||||
// free this
|
|
||||||
glDeleteFramebuffers(1, &rt->external.fbo);
|
|
||||||
|
|
||||||
// and this
|
|
||||||
if (rt->external.depth != 0) {
|
|
||||||
glDeleteRenderbuffers(1, &rt->external.depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clean up our texture
|
|
||||||
Texture *t = texture_owner.get_or_null(rt->external.texture);
|
|
||||||
t->alloc_height = 0;
|
|
||||||
t->alloc_width = 0;
|
|
||||||
t->width = 0;
|
|
||||||
t->height = 0;
|
|
||||||
t->active = false;
|
|
||||||
texture_owner.free(rt->external.texture);
|
|
||||||
memdelete(t);
|
|
||||||
|
|
||||||
rt->external.fbo = 0;
|
|
||||||
rt->external.color = 0;
|
|
||||||
rt->external.depth = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Texture *t;
|
|
||||||
|
|
||||||
if (rt->external.fbo == 0) {
|
|
||||||
// create our fbo
|
|
||||||
glGenFramebuffers(1, &rt->external.fbo);
|
|
||||||
bind_framebuffer(rt->external.fbo);
|
|
||||||
|
|
||||||
// allocate a texture
|
|
||||||
t = memnew(Texture);
|
|
||||||
|
|
||||||
t->type = RenderingDevice::TEXTURE_TYPE_2D;
|
|
||||||
t->flags = 0;
|
|
||||||
t->width = 0;
|
|
||||||
t->height = 0;
|
|
||||||
t->alloc_height = 0;
|
|
||||||
t->alloc_width = 0;
|
|
||||||
t->format = Image::FORMAT_RGBA8;
|
|
||||||
t->target = GL_TEXTURE_2D;
|
|
||||||
t->gl_format_cache = 0;
|
|
||||||
t->gl_internal_format_cache = 0;
|
|
||||||
t->gl_type_cache = 0;
|
|
||||||
t->data_size = 0;
|
|
||||||
t->compressed = false;
|
|
||||||
t->srgb = false;
|
|
||||||
t->total_data_size = 0;
|
|
||||||
t->ignore_mipmaps = false;
|
|
||||||
t->mipmaps = 1;
|
|
||||||
t->active = true;
|
|
||||||
t->tex_id = 0;
|
|
||||||
t->render_target = rt;
|
|
||||||
|
|
||||||
rt->external.texture = texture_owner.make_rid(t);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// bind our frame buffer
|
|
||||||
bind_framebuffer(rt->external.fbo);
|
|
||||||
|
|
||||||
// find our texture
|
|
||||||
t = texture_owner.get_or_null(rt->external.texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set our texture
|
|
||||||
t->tex_id = p_texture_id;
|
|
||||||
rt->external.color = p_texture_id;
|
|
||||||
|
|
||||||
// size shouldn't be different
|
|
||||||
t->width = rt->width;
|
|
||||||
t->height = rt->height;
|
|
||||||
t->alloc_height = rt->width;
|
|
||||||
t->alloc_width = rt->height;
|
|
||||||
|
|
||||||
// Switch our texture on our frame buffer
|
|
||||||
{
|
|
||||||
// set our texture as the destination for our framebuffer
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
|
|
||||||
|
|
||||||
// seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
|
|
||||||
if (config.support_depth_texture) {
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
|
|
||||||
} else {
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check status and unbind
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
||||||
bind_framebuffer_system();
|
|
||||||
|
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
|
||||||
printf("framebuffer fail, status: %x\n", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
|
void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
|
||||||
|
|
|
@ -1256,10 +1256,11 @@ public:
|
||||||
void _set_current_render_target(RID p_render_target);
|
void _set_current_render_target(RID p_render_target);
|
||||||
|
|
||||||
RID render_target_create() override;
|
RID render_target_create() override;
|
||||||
|
void render_target_update(RID p_render_target) override;
|
||||||
void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
|
void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
|
||||||
void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
|
void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
|
||||||
RID render_target_get_texture(RID p_render_target) override;
|
RID render_target_get_texture(RID p_render_target) override;
|
||||||
void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
|
void render_target_set_external_textures(RID p_render_target, RID p_color, RID p_depth) override;
|
||||||
|
|
||||||
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
|
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
|
||||||
bool render_target_was_used(RID p_render_target) override;
|
bool render_target_was_used(RID p_render_target) override;
|
||||||
|
|
|
@ -2170,6 +2170,125 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers) {
|
||||||
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
|
// This method creates a texture object using a VkImage created by an extension.
|
||||||
|
VkImage image = (VkImage) p_image;
|
||||||
|
|
||||||
|
Texture texture;
|
||||||
|
texture.image = image;
|
||||||
|
// if we leave texture.allocation as a nullptr, would that be enough to detect we don't "own" the image?
|
||||||
|
// also leave texture.allocation_info alone
|
||||||
|
// we'll set texture.view later on
|
||||||
|
texture.type = p_type;
|
||||||
|
texture.format = p_format;
|
||||||
|
texture.samples = p_samples;
|
||||||
|
texture.width = p_width;
|
||||||
|
texture.height = p_height;
|
||||||
|
texture.depth = p_depth;
|
||||||
|
texture.layers = p_layers;
|
||||||
|
texture.mipmaps = 0; // maybe make this settable too?
|
||||||
|
texture.usage_flags = p_flags;
|
||||||
|
texture.base_mipmap = 0;
|
||||||
|
texture.base_layer = 0;
|
||||||
|
|
||||||
|
// Do we need to do something with texture.allowed_shared_formats?
|
||||||
|
|
||||||
|
// Do we need to do something with texture.layout ?
|
||||||
|
|
||||||
|
if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||||
|
texture.read_aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
texture.barrier_aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
|
||||||
|
// if (format_has_stencil(p_format.format)) {
|
||||||
|
// texture.barrier_aspect_mask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
texture.read_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
texture.barrier_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a view for us to use
|
||||||
|
|
||||||
|
VkImageViewCreateInfo image_view_create_info;
|
||||||
|
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
image_view_create_info.pNext = nullptr;
|
||||||
|
image_view_create_info.flags = 0;
|
||||||
|
image_view_create_info.image = texture.image;
|
||||||
|
|
||||||
|
static const VkImageViewType view_types[TEXTURE_TYPE_MAX] = {
|
||||||
|
VK_IMAGE_VIEW_TYPE_1D,
|
||||||
|
VK_IMAGE_VIEW_TYPE_2D,
|
||||||
|
VK_IMAGE_VIEW_TYPE_3D,
|
||||||
|
VK_IMAGE_VIEW_TYPE_CUBE,
|
||||||
|
VK_IMAGE_VIEW_TYPE_1D_ARRAY,
|
||||||
|
VK_IMAGE_VIEW_TYPE_2D_ARRAY,
|
||||||
|
VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
|
||||||
|
};
|
||||||
|
|
||||||
|
image_view_create_info.viewType = view_types[texture.type];
|
||||||
|
image_view_create_info.format = vulkan_formats[texture.format];
|
||||||
|
|
||||||
|
static const VkComponentSwizzle component_swizzles[TEXTURE_SWIZZLE_MAX] = {
|
||||||
|
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
VK_COMPONENT_SWIZZLE_ZERO,
|
||||||
|
VK_COMPONENT_SWIZZLE_ONE,
|
||||||
|
VK_COMPONENT_SWIZZLE_R,
|
||||||
|
VK_COMPONENT_SWIZZLE_G,
|
||||||
|
VK_COMPONENT_SWIZZLE_B,
|
||||||
|
VK_COMPONENT_SWIZZLE_A
|
||||||
|
};
|
||||||
|
|
||||||
|
// hardcode for now, mayb make this settable from outside..
|
||||||
|
image_view_create_info.components.r = component_swizzles[TEXTURE_SWIZZLE_R];
|
||||||
|
image_view_create_info.components.g = component_swizzles[TEXTURE_SWIZZLE_G];
|
||||||
|
image_view_create_info.components.b = component_swizzles[TEXTURE_SWIZZLE_B];
|
||||||
|
image_view_create_info.components.a = component_swizzles[TEXTURE_SWIZZLE_A];
|
||||||
|
|
||||||
|
image_view_create_info.subresourceRange.baseMipLevel = 0;
|
||||||
|
image_view_create_info.subresourceRange.levelCount = texture.mipmaps;
|
||||||
|
image_view_create_info.subresourceRange.baseArrayLayer = 0;
|
||||||
|
image_view_create_info.subresourceRange.layerCount = texture.layers;
|
||||||
|
if (texture.usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
|
||||||
|
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
} else {
|
||||||
|
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult err = vkCreateImageView(device, &image_view_create_info, nullptr, &texture.view);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
// vmaDestroyImage(allocator, texture.image, texture.allocation);
|
||||||
|
ERR_FAIL_V_MSG(RID(), "vkCreateImageView failed with error " + itos(err) + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
//barrier to set layout
|
||||||
|
{
|
||||||
|
VkImageMemoryBarrier image_memory_barrier;
|
||||||
|
image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
image_memory_barrier.pNext = nullptr;
|
||||||
|
image_memory_barrier.srcAccessMask = 0;
|
||||||
|
image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
|
image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
image_memory_barrier.newLayout = texture.layout;
|
||||||
|
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
image_memory_barrier.image = texture.image;
|
||||||
|
image_memory_barrier.subresourceRange.aspectMask = texture.barrier_aspect_mask;
|
||||||
|
image_memory_barrier.subresourceRange.baseMipLevel = 0;
|
||||||
|
image_memory_barrier.subresourceRange.levelCount = texture.mipmaps;
|
||||||
|
image_memory_barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
|
image_memory_barrier.subresourceRange.layerCount = texture.layers;
|
||||||
|
|
||||||
|
vkCmdPipelineBarrier(frames[frame].setup_command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
RID id = texture_owner.make_rid(texture);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type) {
|
RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
|
@ -8714,7 +8833,7 @@ void RenderingDeviceVulkan::_free_pending_resources(int p_frame) {
|
||||||
WARN_PRINT("Deleted a texture while it was bound..");
|
WARN_PRINT("Deleted a texture while it was bound..");
|
||||||
}
|
}
|
||||||
vkDestroyImageView(device, texture->view, nullptr);
|
vkDestroyImageView(device, texture->view, nullptr);
|
||||||
if (texture->owner.is_null()) {
|
if (texture->owner.is_null() && texture->allocation != nullptr) {
|
||||||
//actually owns the image and the allocation too
|
//actually owns the image and the allocation too
|
||||||
image_memory -= texture->allocation_info.size;
|
image_memory -= texture->allocation_info.size;
|
||||||
vmaDestroyImage(allocator, texture->image, texture->allocation);
|
vmaDestroyImage(allocator, texture->image, texture->allocation);
|
||||||
|
|
|
@ -1036,6 +1036,7 @@ class RenderingDeviceVulkan : public RenderingDevice {
|
||||||
public:
|
public:
|
||||||
virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>());
|
virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>());
|
||||||
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture);
|
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture);
|
||||||
|
virtual RID texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers);
|
||||||
|
|
||||||
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
|
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D);
|
||||||
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
|
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
|
||||||
|
|
|
@ -339,6 +339,25 @@ Error VulkanContext::_initialize_extensions() {
|
||||||
if (!strcmp(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, instance_extensions[i].extensionName)) {
|
if (!strcmp(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, instance_extensions[i].extensionName)) {
|
||||||
extension_names[enabled_extension_count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
|
extension_names[enabled_extension_count++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Need to switch these, they are needed for OpenXR
|
||||||
|
|
||||||
|
if (!strcmp(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, instance_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, instance_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WINDOWS_ENABLED
|
||||||
|
if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// END TODO
|
||||||
|
|
||||||
if (enabled_extension_count >= MAX_EXTENSIONS) {
|
if (enabled_extension_count >= MAX_EXTENSIONS) {
|
||||||
free(instance_extensions);
|
free(instance_extensions);
|
||||||
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
|
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
|
||||||
|
@ -784,6 +803,33 @@ Error VulkanContext::_create_physical_device() {
|
||||||
// if multiview is supported, enable it
|
// if multiview is supported, enable it
|
||||||
extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME;
|
extension_names[enabled_extension_count++] = VK_KHR_MULTIVIEW_EXTENSION_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Need to switch these, tehy are needed for OpenXR (or do we just enable them anyway?)
|
||||||
|
if (!strcmp(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
if (!strcmp(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
if (!strcmp(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
if (!strcmp(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
if (!strcmp(VK_EXT_DEBUG_MARKER_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_EXT_DEBUG_MARKER_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
#ifdef WINDOWS_ENABLED
|
||||||
|
if (!strcmp(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
if (!strcmp(VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME, device_extensions[i].extensionName)) {
|
||||||
|
extension_names[enabled_extension_count++] = VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// END TODO
|
||||||
|
|
||||||
if (enabled_extension_count >= MAX_EXTENSIONS) {
|
if (enabled_extension_count >= MAX_EXTENSIONS) {
|
||||||
free(device_extensions);
|
free(device_extensions);
|
||||||
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
|
ERR_FAIL_V_MSG(ERR_BUG, "Enabled extension count reaches MAX_EXTENSIONS, BUG");
|
||||||
|
|
438
modules/gdnative/xr/xr_interface_gdnative.cpp
Normal file
438
modules/gdnative/xr/xr_interface_gdnative.cpp
Normal file
|
@ -0,0 +1,438 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* xr_interface_gdnative.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "xr_interface_gdnative.h"
|
||||||
|
#include "core/input/input.h"
|
||||||
|
#include "servers/rendering/rendering_server_globals.h"
|
||||||
|
#include "servers/xr/xr_positional_tracker.h"
|
||||||
|
|
||||||
|
void XRInterfaceGDNative::_bind_methods() {
|
||||||
|
ADD_PROPERTY_DEFAULT("interface_is_initialized", false);
|
||||||
|
ADD_PROPERTY_DEFAULT("ar_is_anchor_detection_enabled", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
XRInterfaceGDNative::XRInterfaceGDNative() {
|
||||||
|
print_verbose("Construct gdnative interface\n");
|
||||||
|
|
||||||
|
// we won't have our data pointer until our library gets set
|
||||||
|
data = nullptr;
|
||||||
|
|
||||||
|
interface = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRInterfaceGDNative::~XRInterfaceGDNative() {
|
||||||
|
print_verbose("Destruct gdnative interface\n");
|
||||||
|
|
||||||
|
if (interface != nullptr && is_initialized()) {
|
||||||
|
uninitialize();
|
||||||
|
};
|
||||||
|
|
||||||
|
// cleanup after ourselves
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XRInterfaceGDNative::cleanup() {
|
||||||
|
if (interface != nullptr) {
|
||||||
|
interface->destructor(data);
|
||||||
|
data = nullptr;
|
||||||
|
interface = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XRInterfaceGDNative::set_interface(const godot_xr_interface_gdnative *p_interface) {
|
||||||
|
// this should only be called once, just being paranoid..
|
||||||
|
if (interface) {
|
||||||
|
cleanup();
|
||||||
|
interface = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// validate
|
||||||
|
ERR_FAIL_NULL(p_interface);
|
||||||
|
ERR_FAIL_COND_MSG(p_interface->version.major < 4, "This is an incompatible GDNative XR plugin.");
|
||||||
|
|
||||||
|
// bind to our interface
|
||||||
|
interface = p_interface;
|
||||||
|
|
||||||
|
// Now we do our constructing...
|
||||||
|
data = interface->constructor((godot_object *)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringName XRInterfaceGDNative::get_name() const {
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, StringName());
|
||||||
|
|
||||||
|
godot_string result = interface->get_name(data);
|
||||||
|
|
||||||
|
StringName name = *(String *)&result;
|
||||||
|
|
||||||
|
godot_string_destroy(&result);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int XRInterfaceGDNative::get_capabilities() const {
|
||||||
|
int capabilities;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, 0); // 0 = None
|
||||||
|
|
||||||
|
capabilities = interface->get_capabilities(data);
|
||||||
|
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XRInterfaceGDNative::get_anchor_detection_is_enabled() const {
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, false);
|
||||||
|
|
||||||
|
return interface->get_anchor_detection_is_enabled(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) {
|
||||||
|
ERR_FAIL_COND(interface == nullptr);
|
||||||
|
|
||||||
|
interface->set_anchor_detection_is_enabled(data, p_enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
int XRInterfaceGDNative::get_camera_feed_id() {
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, 0);
|
||||||
|
|
||||||
|
return (unsigned int)interface->get_camera_feed_id(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t XRInterfaceGDNative::get_view_count() {
|
||||||
|
uint32_t view_count;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, 1);
|
||||||
|
|
||||||
|
view_count = interface->get_view_count(data);
|
||||||
|
|
||||||
|
return view_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XRInterfaceGDNative::is_initialized() const {
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, false);
|
||||||
|
|
||||||
|
return interface->is_initialized(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XRInterfaceGDNative::initialize() {
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, false);
|
||||||
|
|
||||||
|
bool initialized = interface->initialize(data);
|
||||||
|
|
||||||
|
if (initialized) {
|
||||||
|
// if we successfully initialize our interface and we don't have a primary interface yet, this becomes our primary interface
|
||||||
|
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
if ((xr_server != nullptr) && (xr_server->get_primary_interface() == nullptr)) {
|
||||||
|
xr_server->set_primary_interface(this);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XRInterfaceGDNative::uninitialize() {
|
||||||
|
ERR_FAIL_COND(interface == nullptr);
|
||||||
|
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
if (xr_server != nullptr) {
|
||||||
|
// Whatever happens, make sure this is no longer our primary interface
|
||||||
|
xr_server->clear_primary_interface_if(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface->uninitialize(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size2 XRInterfaceGDNative::get_render_targetsize() {
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, Size2());
|
||||||
|
|
||||||
|
godot_vector2 result = interface->get_render_targetsize(data);
|
||||||
|
Vector2 *vec = (Vector2 *)&result;
|
||||||
|
|
||||||
|
return *vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3D XRInterfaceGDNative::get_camera_transform() {
|
||||||
|
Transform3D *ret;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, Transform3D());
|
||||||
|
|
||||||
|
godot_transform3d t = interface->get_camera_transform(data);
|
||||||
|
|
||||||
|
ret = (Transform3D *)&t;
|
||||||
|
|
||||||
|
return *ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform3D XRInterfaceGDNative::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
|
||||||
|
Transform3D *ret;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, Transform3D());
|
||||||
|
|
||||||
|
godot_transform3d t = interface->get_transform_for_view(data, (int)p_view, (godot_transform3d *)&p_cam_transform);
|
||||||
|
|
||||||
|
ret = (Transform3D *)&t;
|
||||||
|
|
||||||
|
return *ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraMatrix XRInterfaceGDNative::get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
|
||||||
|
CameraMatrix cm;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, CameraMatrix());
|
||||||
|
|
||||||
|
interface->fill_projection_for_view(data, (godot_real_t *)cm.matrix, (godot_int)p_view, p_aspect, p_z_near, p_z_far);
|
||||||
|
|
||||||
|
return cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<BlitToScreen> XRInterfaceGDNative::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
|
||||||
|
// possibly move this as a member variable and add a callback to populate?
|
||||||
|
Vector<BlitToScreen> blit_to_screen;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(interface == nullptr, blit_to_screen);
|
||||||
|
|
||||||
|
// must implement
|
||||||
|
interface->commit_views(data, (godot_rid *)&p_render_target, (godot_rect2 *)&p_screen_rect);
|
||||||
|
|
||||||
|
return blit_to_screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XRInterfaceGDNative::process() {
|
||||||
|
ERR_FAIL_COND(interface == nullptr);
|
||||||
|
|
||||||
|
interface->process(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XRInterfaceGDNative::notification(int p_what) {
|
||||||
|
ERR_FAIL_COND(interface == nullptr);
|
||||||
|
|
||||||
|
interface->notification(data, p_what);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// some helper callbacks
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
void GDAPI godot_xr_register_interface(const godot_xr_interface_gdnative *p_interface) {
|
||||||
|
// Must be on a version 4 plugin
|
||||||
|
ERR_FAIL_COND_MSG(p_interface->version.major < 4, "GDNative XR interfaces build for Godot 3.x are not supported.");
|
||||||
|
|
||||||
|
Ref<XRInterfaceGDNative> new_interface;
|
||||||
|
new_interface.instantiate();
|
||||||
|
new_interface->set_interface((const godot_xr_interface_gdnative *)p_interface);
|
||||||
|
XRServer::get_singleton()->add_interface(new_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_real_t GDAPI godot_xr_get_worldscale() {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
ERR_FAIL_NULL_V(xr_server, 1.0);
|
||||||
|
|
||||||
|
return xr_server->get_world_scale();
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_transform3d GDAPI godot_xr_get_reference_frame() {
|
||||||
|
godot_transform3d reference_frame;
|
||||||
|
Transform3D *reference_frame_ptr = (Transform3D *)&reference_frame;
|
||||||
|
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
if (xr_server != nullptr) {
|
||||||
|
*reference_frame_ptr = xr_server->get_reference_frame();
|
||||||
|
} else {
|
||||||
|
memnew_placement(&reference_frame, Transform3D);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reference_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDAPI godot_xr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect) {
|
||||||
|
// blits out our texture as is, handy for preview display of one of the eyes that is already rendered with lens distortion on an external HMD
|
||||||
|
XRInterface::Eyes eye = (XRInterface::Eyes)p_eye;
|
||||||
|
#if 0
|
||||||
|
RID *render_target = (RID *)p_render_target;
|
||||||
|
#endif
|
||||||
|
Rect2 screen_rect = *(Rect2 *)p_rect;
|
||||||
|
|
||||||
|
if (eye == XRInterface::EYE_LEFT) {
|
||||||
|
screen_rect.size.x /= 2.0;
|
||||||
|
} else if (p_eye == XRInterface::EYE_RIGHT) {
|
||||||
|
screen_rect.size.x /= 2.0;
|
||||||
|
screen_rect.position.x += screen_rect.size.x;
|
||||||
|
}
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#warning this needs to be redone
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
RSG::rasterizer->blit_render_target_to_screen(*render_target, screen_rect, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int GDAPI godot_xr_get_texid(godot_rid *p_render_target) {
|
||||||
|
// In order to send off our textures to display on our hardware we need the opengl texture ID instead of the render target RID
|
||||||
|
// This is a handy function to expose that.
|
||||||
|
#if 0
|
||||||
|
RID *render_target = (RID *)p_render_target;
|
||||||
|
|
||||||
|
RID eye_texture = RSG::storage->render_target_get_texture(*render_target);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#warning need to obtain this ID again
|
||||||
|
#endif
|
||||||
|
uint32_t texid = 0; //RS::get_singleton()->texture_get_texid(eye_texture);
|
||||||
|
|
||||||
|
return texid;
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_int GDAPI godot_xr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
ERR_FAIL_NULL_V(xr_server, 0);
|
||||||
|
|
||||||
|
Input *input = Input::get_singleton();
|
||||||
|
ERR_FAIL_NULL_V(input, 0);
|
||||||
|
|
||||||
|
Ref<XRPositionalTracker> new_tracker;
|
||||||
|
new_tracker.instantiate();
|
||||||
|
new_tracker->set_tracker_name(p_device_name);
|
||||||
|
new_tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER);
|
||||||
|
if (p_hand == 1) {
|
||||||
|
new_tracker->set_tracker_hand(XRPositionalTracker::TRACKER_HAND_LEFT);
|
||||||
|
} else if (p_hand == 2) {
|
||||||
|
new_tracker->set_tracker_hand(XRPositionalTracker::TRACKER_HAND_RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// also register as joystick...
|
||||||
|
int joyid = input->get_unused_joy_id();
|
||||||
|
if (joyid != -1) {
|
||||||
|
new_tracker->set_joy_id(joyid);
|
||||||
|
input->joy_connection_changed(joyid, true, p_device_name, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_tracks_orientation) {
|
||||||
|
Basis orientation;
|
||||||
|
new_tracker->set_orientation(orientation);
|
||||||
|
}
|
||||||
|
if (p_tracks_position) {
|
||||||
|
Vector3 position;
|
||||||
|
new_tracker->set_position(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add our tracker to our server and remember its pointer
|
||||||
|
xr_server->add_tracker(new_tracker);
|
||||||
|
|
||||||
|
// note, this ID is only unique within controllers!
|
||||||
|
return new_tracker->get_tracker_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDAPI godot_xr_remove_controller(godot_int p_controller_id) {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
ERR_FAIL_NULL(xr_server);
|
||||||
|
|
||||||
|
Input *input = Input::get_singleton();
|
||||||
|
ERR_FAIL_NULL(input);
|
||||||
|
|
||||||
|
Ref<XRPositionalTracker> remove_tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
|
||||||
|
if (remove_tracker.is_valid()) {
|
||||||
|
// unset our joystick if applicable
|
||||||
|
int joyid = remove_tracker->get_joy_id();
|
||||||
|
if (joyid != -1) {
|
||||||
|
input->joy_connection_changed(joyid, false, "", "");
|
||||||
|
remove_tracker->set_joy_id(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove our tracker from our server
|
||||||
|
xr_server->remove_tracker(remove_tracker);
|
||||||
|
remove_tracker.unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform3d *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
ERR_FAIL_NULL(xr_server);
|
||||||
|
|
||||||
|
Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
|
||||||
|
if (tracker.is_valid()) {
|
||||||
|
Transform3D *transform = (Transform3D *)p_transform;
|
||||||
|
if (p_tracks_orientation) {
|
||||||
|
tracker->set_orientation(transform->basis);
|
||||||
|
}
|
||||||
|
if (p_tracks_position) {
|
||||||
|
tracker->set_rw_position(transform->origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed) {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
ERR_FAIL_NULL(xr_server);
|
||||||
|
|
||||||
|
Input *input = Input::get_singleton();
|
||||||
|
ERR_FAIL_NULL(input);
|
||||||
|
|
||||||
|
Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
|
||||||
|
if (tracker.is_valid()) {
|
||||||
|
int joyid = tracker->get_joy_id();
|
||||||
|
if (joyid != -1) {
|
||||||
|
input->joy_button(joyid, (JoyButton)p_button, p_is_pressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real_t p_value, godot_bool p_can_be_negative) {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
ERR_FAIL_NULL(xr_server);
|
||||||
|
|
||||||
|
Input *input = Input::get_singleton();
|
||||||
|
ERR_FAIL_NULL(input);
|
||||||
|
|
||||||
|
Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
|
||||||
|
if (tracker.is_valid()) {
|
||||||
|
int joyid = tracker->get_joy_id();
|
||||||
|
if (joyid != -1) {
|
||||||
|
Input::JoyAxisValue jx;
|
||||||
|
jx.min = p_can_be_negative ? -1 : 0;
|
||||||
|
jx.value = p_value;
|
||||||
|
input->joy_axis(joyid, (JoyAxis)p_axis, jx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
godot_real_t GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id) {
|
||||||
|
XRServer *xr_server = XRServer::get_singleton();
|
||||||
|
ERR_FAIL_NULL_V(xr_server, 0.0);
|
||||||
|
|
||||||
|
Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
|
||||||
|
if (tracker.is_valid()) {
|
||||||
|
return tracker->get_rumble();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -659,10 +659,11 @@ public:
|
||||||
/* RENDER TARGET */
|
/* RENDER TARGET */
|
||||||
|
|
||||||
RID render_target_create() override { return RID(); }
|
RID render_target_create() override { return RID(); }
|
||||||
|
void render_target_update(RID p_render_target) override {}
|
||||||
void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
|
void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
|
||||||
void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
|
void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
|
||||||
RID render_target_get_texture(RID p_render_target) override { return RID(); }
|
RID render_target_get_texture(RID p_render_target) override { return RID(); }
|
||||||
void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
|
void render_target_set_external_textures(RID p_render_target, RID p_color, RID p_depth) override {}
|
||||||
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
|
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
|
||||||
bool render_target_was_used(RID p_render_target) override { return false; }
|
bool render_target_was_used(RID p_render_target) override { return false; }
|
||||||
void render_target_set_as_unused(RID p_render_target) override {}
|
void render_target_set_as_unused(RID p_render_target) override {}
|
||||||
|
|
|
@ -7467,6 +7467,20 @@ AABB RendererStorageRD::lightmap_get_aabb(RID p_lightmap) const {
|
||||||
|
|
||||||
/* RENDER TARGET API */
|
/* RENDER TARGET API */
|
||||||
|
|
||||||
|
void RendererStorageRD::_mark_render_target_dirty(RenderTarget *rt) {
|
||||||
|
if (rt->texture.is_null()) {
|
||||||
|
//create a placeholder until updated
|
||||||
|
rt->texture = texture_allocate();
|
||||||
|
texture_2d_placeholder_initialize(rt->texture);
|
||||||
|
Texture *tex = texture_owner.get_or_null(rt->texture);
|
||||||
|
tex->is_render_target = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_clear_render_target(rt);
|
||||||
|
|
||||||
|
rt->is_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
void RendererStorageRD::_clear_render_target(RenderTarget *rt) {
|
void RendererStorageRD::_clear_render_target(RenderTarget *rt) {
|
||||||
//free in reverse dependency order
|
//free in reverse dependency order
|
||||||
if (rt->framebuffer.is_valid()) {
|
if (rt->framebuffer.is_valid()) {
|
||||||
|
@ -7509,81 +7523,137 @@ void RendererStorageRD::_update_render_target(RenderTarget *rt) {
|
||||||
if (rt->size.width == 0 || rt->size.height == 0) {
|
if (rt->size.width == 0 || rt->size.height == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//until we implement support for HDR monitors (and render target is attached to screen), this is enough.
|
|
||||||
rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
|
||||||
rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
|
|
||||||
rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
|
|
||||||
|
|
||||||
RD::TextureFormat rd_format;
|
if (rt->external_color.is_null()) {
|
||||||
RD::TextureView rd_view;
|
//until we implement support for HDR monitors (and render target is attached to screen), this is enough.
|
||||||
{ //attempt register
|
rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
|
||||||
rd_format.format = rt->color_format;
|
rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
|
||||||
rd_format.width = rt->size.width;
|
rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
|
||||||
rd_format.height = rt->size.height;
|
|
||||||
rd_format.depth = 1;
|
|
||||||
rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
|
|
||||||
rd_format.mipmaps = 1;
|
|
||||||
if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
|
|
||||||
rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
|
||||||
} else {
|
|
||||||
rd_format.texture_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_COPY_FROM_BIT;
|
|
||||||
rd_format.shareable_formats.push_back(rt->color_format);
|
|
||||||
rd_format.shareable_formats.push_back(rt->color_format_srgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
|
RD::TextureFormat rd_format;
|
||||||
ERR_FAIL_COND(rt->color.is_null());
|
RD::TextureView rd_view;
|
||||||
|
{ //attempt register
|
||||||
Vector<RID> fb_textures;
|
rd_format.format = rt->color_format;
|
||||||
fb_textures.push_back(rt->color);
|
rd_format.width = rt->size.width;
|
||||||
rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
|
rd_format.height = rt->size.height;
|
||||||
if (rt->framebuffer.is_null()) {
|
rd_format.depth = 1;
|
||||||
_clear_render_target(rt);
|
rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
|
||||||
ERR_FAIL_COND(rt->framebuffer.is_null());
|
rd_format.mipmaps = 1;
|
||||||
}
|
if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
|
||||||
|
rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||||
{ //update texture
|
} else {
|
||||||
|
rd_format.texture_type = RD::TEXTURE_TYPE_2D;
|
||||||
Texture *tex = texture_owner.get_or_null(rt->texture);
|
}
|
||||||
|
rd_format.samples = RD::TEXTURE_SAMPLES_1;
|
||||||
//free existing textures
|
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
|
||||||
if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
|
rd_format.shareable_formats.push_back(rt->color_format);
|
||||||
RD::get_singleton()->free(tex->rd_texture);
|
rd_format.shareable_formats.push_back(rt->color_format_srgb);
|
||||||
}
|
|
||||||
if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
|
|
||||||
RD::get_singleton()->free(tex->rd_texture_srgb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tex->rd_texture = RID();
|
rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
|
||||||
tex->rd_texture_srgb = RID();
|
ERR_FAIL_COND(rt->color.is_null());
|
||||||
|
|
||||||
//create shared textures to the color buffer,
|
Vector<RID> fb_textures;
|
||||||
//so transparent can be supported
|
fb_textures.push_back(rt->color);
|
||||||
RD::TextureView view;
|
rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
|
||||||
view.format_override = rt->color_format;
|
if (rt->framebuffer.is_null()) {
|
||||||
if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
|
_clear_render_target(rt);
|
||||||
view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
ERR_FAIL_COND(rt->framebuffer.is_null());
|
||||||
}
|
}
|
||||||
tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
|
|
||||||
if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
|
|
||||||
view.format_override = rt->color_format_srgb;
|
|
||||||
tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
|
|
||||||
}
|
|
||||||
tex->rd_view = view;
|
|
||||||
tex->width = rt->size.width;
|
|
||||||
tex->height = rt->size.height;
|
|
||||||
tex->width_2d = rt->size.width;
|
|
||||||
tex->height_2d = rt->size.height;
|
|
||||||
tex->rd_format = rt->color_format;
|
|
||||||
tex->rd_format_srgb = rt->color_format_srgb;
|
|
||||||
tex->format = rt->image_format;
|
|
||||||
|
|
||||||
Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
|
{ //update texture
|
||||||
for (int i = 0; i < proxies.size(); i++) {
|
|
||||||
texture_proxy_update(proxies[i], rt->texture);
|
Texture *tex = texture_owner.get_or_null(rt->texture);
|
||||||
|
|
||||||
|
//free existing textures
|
||||||
|
if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
|
||||||
|
RD::get_singleton()->free(tex->rd_texture);
|
||||||
|
}
|
||||||
|
if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
|
||||||
|
RD::get_singleton()->free(tex->rd_texture_srgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->rd_texture = RID();
|
||||||
|
tex->rd_texture_srgb = RID();
|
||||||
|
|
||||||
|
//create shared textures to the color buffer,
|
||||||
|
//so transparent can be supported
|
||||||
|
RD::TextureView view;
|
||||||
|
view.format_override = rt->color_format;
|
||||||
|
if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
|
||||||
|
view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||||
|
}
|
||||||
|
tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
|
||||||
|
if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
|
||||||
|
view.format_override = rt->color_format_srgb;
|
||||||
|
tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
|
||||||
|
}
|
||||||
|
tex->rd_view = view;
|
||||||
|
tex->width = rt->size.width;
|
||||||
|
tex->height = rt->size.height;
|
||||||
|
tex->width_2d = rt->size.width;
|
||||||
|
tex->height_2d = rt->size.height;
|
||||||
|
tex->rd_format = rt->color_format;
|
||||||
|
tex->rd_format_srgb = rt->color_format_srgb;
|
||||||
|
tex->format = rt->image_format;
|
||||||
|
|
||||||
|
Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
|
||||||
|
for (int i = 0; i < proxies.size(); i++) {
|
||||||
|
texture_proxy_update(proxies[i], rt->texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// use our external texture
|
||||||
|
|
||||||
|
Vector<RID> fb_textures;
|
||||||
|
fb_textures.push_back(rt->external_color);
|
||||||
|
rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
|
||||||
|
if (rt->framebuffer.is_null()) {
|
||||||
|
_clear_render_target(rt);
|
||||||
|
ERR_FAIL_COND(rt->framebuffer.is_null());
|
||||||
|
}
|
||||||
|
|
||||||
|
{ //update texture
|
||||||
|
// TODO change this to get color info from our external texture instead...
|
||||||
|
|
||||||
|
Texture *tex = texture_owner.get_or_null(rt->texture);
|
||||||
|
|
||||||
|
//free existing textures
|
||||||
|
if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
|
||||||
|
RD::get_singleton()->free(tex->rd_texture);
|
||||||
|
}
|
||||||
|
if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
|
||||||
|
RD::get_singleton()->free(tex->rd_texture_srgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->rd_texture = RID();
|
||||||
|
tex->rd_texture_srgb = RID();
|
||||||
|
|
||||||
|
//create shared textures to the color buffer,
|
||||||
|
//so transparent can be supported
|
||||||
|
RD::TextureView view;
|
||||||
|
view.format_override = rt->color_format;
|
||||||
|
if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
|
||||||
|
view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
|
||||||
|
}
|
||||||
|
tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->external_color);
|
||||||
|
if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
|
||||||
|
view.format_override = rt->color_format_srgb;
|
||||||
|
tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->external_color);
|
||||||
|
}
|
||||||
|
tex->rd_view = view;
|
||||||
|
tex->width = rt->size.width;
|
||||||
|
tex->height = rt->size.height;
|
||||||
|
tex->width_2d = rt->size.width;
|
||||||
|
tex->height_2d = rt->size.height;
|
||||||
|
tex->rd_format = rt->color_format;
|
||||||
|
tex->rd_format_srgb = rt->color_format_srgb;
|
||||||
|
tex->format = rt->image_format;
|
||||||
|
|
||||||
|
Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
|
||||||
|
for (int i = 0; i < proxies.size(); i++) {
|
||||||
|
texture_proxy_update(proxies[i], rt->texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7645,10 +7715,20 @@ RID RendererStorageRD::render_target_create() {
|
||||||
for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
|
for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
|
||||||
render_target.flags[i] = false;
|
render_target.flags[i] = false;
|
||||||
}
|
}
|
||||||
_update_render_target(&render_target);
|
_mark_render_target_dirty(&render_target);
|
||||||
return render_target_owner.make_rid(render_target);
|
return render_target_owner.make_rid(render_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RendererStorageRD::render_target_update(RID p_render_target) {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_COND(!rt);
|
||||||
|
|
||||||
|
if (rt->is_dirty) {
|
||||||
|
_update_render_target(rt);
|
||||||
|
rt->is_dirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) {
|
void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) {
|
||||||
//unused for this render target
|
//unused for this render target
|
||||||
}
|
}
|
||||||
|
@ -7660,7 +7740,7 @@ void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width,
|
||||||
rt->size.x = p_width;
|
rt->size.x = p_width;
|
||||||
rt->size.y = p_height;
|
rt->size.y = p_height;
|
||||||
rt->view_count = p_view_count;
|
rt->view_count = p_view_count;
|
||||||
_update_render_target(rt);
|
_mark_render_target_dirty(rt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7671,14 +7751,22 @@ RID RendererStorageRD::render_target_get_texture(RID p_render_target) {
|
||||||
return rt->texture;
|
return rt->texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererStorageRD::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
|
void RendererStorageRD::render_target_set_external_textures(RID p_render_target, RID p_color, RID p_depth) {
|
||||||
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
|
ERR_FAIL_COND(!rt);
|
||||||
|
|
||||||
|
if (rt->external_color != p_color || rt->external_depth != p_depth) {
|
||||||
|
rt->external_color = p_color;
|
||||||
|
rt->external_depth = p_depth;
|
||||||
|
_mark_render_target_dirty(rt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
|
void RendererStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
|
||||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||||
ERR_FAIL_COND(!rt);
|
ERR_FAIL_COND(!rt);
|
||||||
rt->flags[p_flag] = p_value;
|
rt->flags[p_flag] = p_value;
|
||||||
_update_render_target(rt);
|
_mark_render_target_dirty(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RendererStorageRD::render_target_was_used(RID p_render_target) {
|
bool RendererStorageRD::render_target_was_used(RID p_render_target) {
|
||||||
|
|
|
@ -1152,6 +1152,7 @@ private:
|
||||||
/* RENDER TARGET */
|
/* RENDER TARGET */
|
||||||
|
|
||||||
struct RenderTarget {
|
struct RenderTarget {
|
||||||
|
bool is_dirty = true;
|
||||||
Size2i size;
|
Size2i size;
|
||||||
uint32_t view_count;
|
uint32_t view_count;
|
||||||
RID framebuffer;
|
RID framebuffer;
|
||||||
|
@ -1170,6 +1171,9 @@ private:
|
||||||
RID backbuffer_fb;
|
RID backbuffer_fb;
|
||||||
RID backbuffer_mipmap0;
|
RID backbuffer_mipmap0;
|
||||||
|
|
||||||
|
RID external_color; // used for XR
|
||||||
|
RID external_depth;
|
||||||
|
|
||||||
struct BackbufferMipmap {
|
struct BackbufferMipmap {
|
||||||
RID mipmap;
|
RID mipmap;
|
||||||
RID mipmap_copy;
|
RID mipmap_copy;
|
||||||
|
@ -1200,6 +1204,7 @@ private:
|
||||||
|
|
||||||
mutable RID_Owner<RenderTarget> render_target_owner;
|
mutable RID_Owner<RenderTarget> render_target_owner;
|
||||||
|
|
||||||
|
void _mark_render_target_dirty(RenderTarget *rt);
|
||||||
void _clear_render_target(RenderTarget *rt);
|
void _clear_render_target(RenderTarget *rt);
|
||||||
void _update_render_target(RenderTarget *rt);
|
void _update_render_target(RenderTarget *rt);
|
||||||
void _create_render_target_backbuffer(RenderTarget *rt);
|
void _create_render_target_backbuffer(RenderTarget *rt);
|
||||||
|
@ -2326,10 +2331,11 @@ public:
|
||||||
/* RENDER TARGET API */
|
/* RENDER TARGET API */
|
||||||
|
|
||||||
RID render_target_create();
|
RID render_target_create();
|
||||||
|
void render_target_update(RID p_render_target);
|
||||||
void render_target_set_position(RID p_render_target, int p_x, int p_y);
|
void render_target_set_position(RID p_render_target, int p_x, int p_y);
|
||||||
void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count);
|
void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count);
|
||||||
RID render_target_get_texture(RID p_render_target);
|
RID render_target_get_texture(RID p_render_target);
|
||||||
void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
|
void render_target_set_external_textures(RID p_render_target, RID p_color, RID p_depth);
|
||||||
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
|
void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
|
||||||
bool render_target_was_used(RID p_render_target);
|
bool render_target_was_used(RID p_render_target);
|
||||||
void render_target_set_as_unused(RID p_render_target);
|
void render_target_set_as_unused(RID p_render_target);
|
||||||
|
|
|
@ -588,10 +588,11 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual RID render_target_create() = 0;
|
virtual RID render_target_create() = 0;
|
||||||
|
virtual void render_target_update(RID p_render_target) = 0;
|
||||||
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
|
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
|
||||||
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
|
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
|
||||||
virtual RID render_target_get_texture(RID p_render_target) = 0;
|
virtual RID render_target_get_texture(RID p_render_target) = 0;
|
||||||
virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
|
virtual void render_target_set_external_textures(RID p_render_target, RID p_color, RID p_depth) = 0;
|
||||||
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
|
virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
|
||||||
virtual bool render_target_was_used(RID p_render_target) = 0;
|
virtual bool render_target_was_used(RID p_render_target) = 0;
|
||||||
virtual void render_target_set_as_unused(RID p_render_target) = 0;
|
virtual void render_target_set_as_unused(RID p_render_target) = 0;
|
||||||
|
|
|
@ -573,9 +573,11 @@ void RendererViewport::draw_viewports() {
|
||||||
uint32_t view_count = xr_interface->get_view_count();
|
uint32_t view_count = xr_interface->get_view_count();
|
||||||
RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
|
RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
|
||||||
|
|
||||||
// check for an external texture destination (disabled for now, not yet supported)
|
// check for an external texture destination
|
||||||
// RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
|
RSG::storage->render_target_set_external_textures(vp->render_target, xr_interface->get_external_color_texture(), xr_interface->get_external_depth_texture());
|
||||||
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
|
|
||||||
|
// (Re)create our RT if needed
|
||||||
|
RSG::storage->render_target_update(vp->render_target);
|
||||||
|
|
||||||
// render...
|
// render...
|
||||||
RSG::scene->set_debug_draw_mode(vp->debug_draw);
|
RSG::scene->set_debug_draw_mode(vp->debug_draw);
|
||||||
|
@ -583,8 +585,6 @@ void RendererViewport::draw_viewports() {
|
||||||
// and draw viewport
|
// and draw viewport
|
||||||
_draw_viewport(vp);
|
_draw_viewport(vp);
|
||||||
|
|
||||||
// measure
|
|
||||||
|
|
||||||
// commit our eyes
|
// commit our eyes
|
||||||
Vector<BlitToScreen> blits = xr_interface->commit_views(vp->render_target, vp->viewport_to_screen_rect);
|
Vector<BlitToScreen> blits = xr_interface->commit_views(vp->render_target, vp->viewport_to_screen_rect);
|
||||||
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) {
|
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) {
|
||||||
|
@ -600,7 +600,14 @@ void RendererViewport::draw_viewports() {
|
||||||
// and for our frame timing, mark when we've finished committing our eyes
|
// and for our frame timing, mark when we've finished committing our eyes
|
||||||
XRServer::get_singleton()->_mark_commit();
|
XRServer::get_singleton()->_mark_commit();
|
||||||
} else {
|
} else {
|
||||||
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
|
// clear our external texture if set
|
||||||
|
RSG::storage->render_target_set_external_textures(vp->render_target, RID(), RID());
|
||||||
|
|
||||||
|
// @TODO check if our viewport is full screen and is set to output to our display,
|
||||||
|
// if so we should create an RT that uses our current swap image (maybe set that as our external texture?)
|
||||||
|
|
||||||
|
// (Re)create our RT if needed
|
||||||
|
RSG::storage->render_target_update(vp->render_target);
|
||||||
|
|
||||||
RSG::scene->set_debug_draw_mode(vp->debug_draw);
|
RSG::scene->set_debug_draw_mode(vp->debug_draw);
|
||||||
|
|
||||||
|
|
|
@ -361,6 +361,7 @@ void RenderingDevice::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array()));
|
ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array()));
|
||||||
ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared);
|
ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared);
|
||||||
ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(TEXTURE_SLICE_2D));
|
ClassDB::bind_method(D_METHOD("texture_create_shared_from_slice", "view", "with_texture", "layer", "mipmap", "slice_type"), &RenderingDevice::_texture_create_shared_from_slice, DEFVAL(TEXTURE_SLICE_2D));
|
||||||
|
ClassDB::bind_method(D_METHOD("texture_create_from_extension", "type", "format", "samples", "flags", "image", "width", "height", "depth", "layers"), &RenderingDevice::texture_create_from_extension);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL));
|
ClassDB::bind_method(D_METHOD("texture_update", "texture", "layer", "data", "post_barrier"), &RenderingDevice::texture_update, DEFVAL(BARRIER_MASK_ALL));
|
||||||
ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data);
|
ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "layer"), &RenderingDevice::texture_get_data);
|
||||||
|
|
|
@ -496,6 +496,7 @@ public:
|
||||||
|
|
||||||
virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>()) = 0;
|
virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector<Vector<uint8_t>> &p_data = Vector<Vector<uint8_t>>()) = 0;
|
||||||
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0;
|
virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0;
|
||||||
|
virtual RID texture_create_from_extension(TextureType p_type, DataFormat p_format, TextureSamples p_samples, uint64_t p_flags, uint64_t p_image, uint64_t p_width, uint64_t p_height, uint64_t p_depth, uint64_t p_layers) = 0;
|
||||||
|
|
||||||
enum TextureSliceType {
|
enum TextureSliceType {
|
||||||
TEXTURE_SLICE_2D,
|
TEXTURE_SLICE_2D,
|
||||||
|
|
|
@ -137,7 +137,17 @@ PackedVector3Array XRInterface::get_play_area() const {
|
||||||
// Note implementation is responsible for applying our reference frame and world scale to the raw data.
|
// Note implementation is responsible for applying our reference frame and world scale to the raw data.
|
||||||
// `play_area_changed` should be emitted if play area data is available and either the reference frame or world scale changes.
|
// `play_area_changed` should be emitted if play area data is available and either the reference frame or world scale changes.
|
||||||
return PackedVector3Array();
|
return PackedVector3Array();
|
||||||
};
|
}
|
||||||
|
|
||||||
|
// optional render to external color texture which enhances performance on those platforms that require us to submit our end result into special textures.
|
||||||
|
RID XRInterface::get_external_color_texture() {
|
||||||
|
return RID();
|
||||||
|
}
|
||||||
|
|
||||||
|
// optional render to external depth texture which enhances performance on those platforms that require us to submit our end result into special textures.
|
||||||
|
RID XRInterface::get_external_depth_texture() {
|
||||||
|
return RID();
|
||||||
|
}
|
||||||
|
|
||||||
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
|
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
|
||||||
bool XRInterface::get_anchor_detection_is_enabled() const {
|
bool XRInterface::get_anchor_detection_is_enabled() const {
|
||||||
|
|
|
@ -125,6 +125,8 @@ public:
|
||||||
|
|
||||||
// note, external color/depth/vrs texture support will be added here soon.
|
// note, external color/depth/vrs texture support will be added here soon.
|
||||||
|
|
||||||
|
virtual RID get_external_color_texture(); /* if applicable return external color texture to render to */
|
||||||
|
virtual RID get_external_depth_texture(); /* if applicable return external depth texture to render to */
|
||||||
virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* commit rendered views to the XR interface */
|
virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* commit rendered views to the XR interface */
|
||||||
|
|
||||||
virtual void process() = 0;
|
virtual void process() = 0;
|
||||||
|
|
|
@ -52,6 +52,8 @@ void XRInterfaceExtension::_bind_methods() {
|
||||||
GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
|
GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform");
|
||||||
GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
|
GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far");
|
||||||
|
|
||||||
|
GDVIRTUAL_BIND(_get_external_color_texture);
|
||||||
|
GDVIRTUAL_BIND(_get_external_depth_texture);
|
||||||
GDVIRTUAL_BIND(_commit_views, "render_target", "screen_rect");
|
GDVIRTUAL_BIND(_commit_views, "render_target", "screen_rect");
|
||||||
|
|
||||||
GDVIRTUAL_BIND(_process);
|
GDVIRTUAL_BIND(_process);
|
||||||
|
@ -333,3 +335,25 @@ RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) {
|
||||||
return rd_scene->render_buffers_get_depth_texture(????????????);
|
return rd_scene->render_buffers_get_depth_texture(????????????);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// optional render to external color texture which enhances performance on those platforms that require us to submit our end result into special textures.
|
||||||
|
RID XRInterfaceExtension::get_external_color_texture() {
|
||||||
|
RID texture;
|
||||||
|
|
||||||
|
if (GDVIRTUAL_CALL(_get_external_color_texture, texture)) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RID();
|
||||||
|
};
|
||||||
|
|
||||||
|
// optional render to external depth texture which enhances performance on those platforms that require us to submit our end result into special textures.
|
||||||
|
RID XRInterfaceExtension::get_external_depth_texture() {
|
||||||
|
RID texture;
|
||||||
|
|
||||||
|
if (GDVIRTUAL_CALL(_get_external_depth_texture, texture)) {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RID();
|
||||||
|
};
|
||||||
|
|
|
@ -108,8 +108,13 @@ public:
|
||||||
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
|
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
|
||||||
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
|
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
|
||||||
|
|
||||||
|
virtual RID get_external_color_texture(); /* if applicable return external color texture to render to */
|
||||||
|
virtual RID get_external_depth_texture(); /* if applicable return external depth texture to render to */
|
||||||
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
|
void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0);
|
||||||
virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
|
virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
|
||||||
|
|
||||||
|
GDVIRTUAL0R(RID, _get_external_color_texture);
|
||||||
|
GDVIRTUAL0R(RID, _get_external_depth_texture);
|
||||||
GDVIRTUAL2(_commit_views, RID, const Rect2 &);
|
GDVIRTUAL2(_commit_views, RID, const Rect2 &);
|
||||||
|
|
||||||
virtual void process() override;
|
virtual void process() override;
|
||||||
|
|
Loading…
Reference in a new issue