Adding Variable Rate Shading support to Godot

Improve GI renderer and add VRS support
Implement render device has_feature and move subgroup settings to limit_get
This commit is contained in:
Bastiaan Olij 2022-02-11 22:33:54 +11:00
parent e3a8ab68ce
commit d139131aab
44 changed files with 1574 additions and 466 deletions

View file

@ -29,7 +29,7 @@
/*************************************************************************/
#include "xr_interface.h"
// #include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_compositor.h"
void XRInterface::_bind_methods() {
ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode")));
@ -114,7 +114,12 @@ void XRInterface::set_primary(bool p_primary) {
XRInterface::XRInterface() {}
XRInterface::~XRInterface() {}
XRInterface::~XRInterface() {
if (vrs.vrs_texture.is_valid()) {
RS::get_singleton()->free(vrs.vrs_texture);
vrs.vrs_texture = RID();
}
}
// query if this interface supports this play area mode
bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
@ -151,6 +156,85 @@ int XRInterface::get_camera_feed_id() {
return 0;
}
RID XRInterface::get_vrs_texture() {
// Default logic will return a standard VRS image based on our target size and default projections.
// Note that this only gets called if VRS is supported on the hardware.
Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard.
int view_count = get_view_count();
Size2 target_size = get_render_target_size();
real_t aspect = target_size.x / target_size.y; // is this y/x ?
Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y));
real_t radius = vrs_size.length() * 0.5;
Size2 vrs_sizei = vrs_size;
if (vrs.size != vrs_sizei) {
const uint8_t densities[] = {
0, // 1x1
1, // 1x2
// 4, // 2x1
5, // 2x2
6, // 2x4
// 9, // 4x2
10, // 4x4
};
// out with the old
if (vrs.vrs_texture.is_valid()) {
RS::get_singleton()->free(vrs.vrs_texture);
vrs.vrs_texture = RID();
}
// in with the new
Vector<Ref<Image>> images;
vrs.size = vrs_sizei;
for (int i = 0; i < view_count && i < 2; i++) {
PackedByteArray data;
data.resize(vrs_sizei.x * vrs_sizei.y);
uint8_t *data_ptr = data.ptrw();
// Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result...
CameraMatrix cm = get_projection_for_view(i, aspect, 0.1, 1000.0);
Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0));
Vector2i view_center;
view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5);
view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5);
int d = 0;
for (int y = 0; y < vrs_sizei.y; y++) {
for (int x = 0; x < vrs_sizei.x; x++) {
Vector2 offset = Vector2(x - view_center.x, y - view_center.y);
offset.y *= aspect;
real_t distance = offset.length();
int idx = round(5.0 * distance / radius);
if (idx > 4) {
idx = 4;
}
uint8_t density = densities[idx];
data_ptr[d++] = density;
}
}
Ref<Image> image;
image.instantiate();
image->create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data);
images.push_back(image);
}
if (images.size() == 1) {
vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
} else {
vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
}
}
return vrs.vrs_texture;
}
/** these are optional, so we want dummies **/
PackedStringArray XRInterface::get_suggested_tracker_names() const {
PackedStringArray arr;

View file

@ -120,6 +120,7 @@ public:
virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
virtual RID get_vrs_texture(); /* obtain VRS texture */
// note, external color/depth/vrs texture support will be added here soon.
@ -133,6 +134,12 @@ public:
XRInterface();
~XRInterface();
private:
struct VRSData {
RID vrs_texture;
Size2i size;
} vrs;
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);

View file

@ -50,6 +50,7 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_camera_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_vrs_texture);
GDVIRTUAL_BIND(_process);
GDVIRTUAL_BIND(_pre_render);
@ -273,6 +274,15 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub
return CameraMatrix();
}
RID XRInterfaceExtension::get_vrs_texture() {
RID vrs_texture;
if (GDVIRTUAL_CALL(_get_vrs_texture, vrs_texture)) {
return vrs_texture;
} else {
return XRInterface::get_vrs_texture();
}
}
void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) {
BlitToScreen blit;

View file

@ -101,12 +101,14 @@ public:
virtual Transform3D get_camera_transform() override;
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override;
virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override;
virtual RID get_vrs_texture() override;
GDVIRTUAL0R(Size2, _get_render_target_size);
GDVIRTUAL0R(uint32_t, _get_view_count);
GDVIRTUAL0R(Transform3D, _get_camera_transform);
GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &);
GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double);
GDVIRTUAL0R(RID, _get_vrs_texture);
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);