You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-06 12:20:30 +00:00
Porting cubemap compute shaders to raster for the mobile renderer
This commit is contained in:
@@ -313,12 +313,16 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
|
||||
coefficient_buffer = RID();
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers) {
|
||||
void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
|
||||
//recreate radiance and all data
|
||||
|
||||
int mipmaps = p_mipmaps;
|
||||
uint32_t w = p_size, h = p_size;
|
||||
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
if (p_use_array) {
|
||||
int num_layers = p_low_quality ? 8 : p_roughness_layers;
|
||||
|
||||
@@ -377,9 +381,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
||||
}
|
||||
|
||||
radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP);
|
||||
|
||||
RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap");
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.format = p_texture_format;
|
||||
tf.width = 64; // Always 64x64
|
||||
tf.height = 64;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
|
||||
@@ -388,6 +392,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
|
||||
{
|
||||
uint32_t mmw = 64;
|
||||
uint32_t mmh = 64;
|
||||
@@ -397,6 +402,18 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
||||
mm.size.width = mmw;
|
||||
mm.size.height = mmh;
|
||||
mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP);
|
||||
RD::get_singleton()->set_resource_name(mm.view, "Downsampled Radiance Cubemap Mip " + itos(j) + " ");
|
||||
if (prefer_raster_effects) {
|
||||
// we need a framebuffer for each side of our cubemap
|
||||
|
||||
for (int k = 0; k < 6; k++) {
|
||||
mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), downsampled_radiance_cubemap, k, j);
|
||||
RD::get_singleton()->set_resource_name(mm.view, "Downsampled Radiance Cubemap Mip: " + itos(j) + " Face: " + itos(k) + " ");
|
||||
Vector<RID> fbtex;
|
||||
fbtex.push_back(mm.views[k]);
|
||||
mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex);
|
||||
}
|
||||
}
|
||||
|
||||
mmw = MAX(1, mmw >> 1);
|
||||
mmh = MAX(1, mmh >> 1);
|
||||
@@ -405,50 +422,128 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) {
|
||||
p_storage->get_effects()->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
|
||||
p_storage->get_effects()->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
|
||||
}
|
||||
|
||||
Vector<RID> views;
|
||||
if (p_use_arrays) {
|
||||
for (int i = 1; i < layers.size(); i++) {
|
||||
views.push_back(layers[i].views[0]);
|
||||
if (prefer_raster_effects) {
|
||||
RD::get_singleton()->draw_command_begin_label("Downsample radiance map");
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size);
|
||||
}
|
||||
|
||||
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size);
|
||||
}
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
|
||||
|
||||
if (p_use_arrays) {
|
||||
RD::get_singleton()->draw_command_begin_label("filter radiance map into array heads");
|
||||
for (int i = 0; i < layers.size(); i++) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[i].mipmaps[0].framebuffers[k], k, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RD::get_singleton()->draw_command_begin_label("filter radiance map into mipmaps directly");
|
||||
for (int j = 0; j < layers[0].mipmaps.size(); j++) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[0].mipmaps[j].framebuffers[k], k, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label(); // Filter radiance
|
||||
} else {
|
||||
for (int i = 1; i < layers[0].views.size(); i++) {
|
||||
views.push_back(layers[0].views[i]);
|
||||
}
|
||||
}
|
||||
effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
|
||||
|
||||
p_storage->get_effects()->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
|
||||
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
|
||||
effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
|
||||
}
|
||||
|
||||
Vector<RID> views;
|
||||
if (p_use_arrays) {
|
||||
for (int i = 1; i < layers.size(); i++) {
|
||||
views.push_back(layers[i].views[0]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 1; i < layers[0].views.size(); i++) {
|
||||
views.push_back(layers[0].views[i]);
|
||||
}
|
||||
}
|
||||
|
||||
effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
|
||||
if (p_use_arrays) {
|
||||
//render directly to the layers
|
||||
p_storage->get_effects()->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
// Need to ask clayjohn but p_cube_side is set to 10, looks like in the compute shader we're doing all 6 sides in one call
|
||||
// here we need to do them one by one so ignoring p_cube_side
|
||||
if (p_use_arrays) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_roughness_raster(
|
||||
radiance_base_cubemap,
|
||||
layers[p_base_layer].mipmaps[0].framebuffers[k],
|
||||
k,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers.size() - 1.0),
|
||||
layers[p_base_layer].mipmaps[0].size.x);
|
||||
}
|
||||
} else {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
effects->cubemap_roughness_raster(
|
||||
layers[0].views[p_base_layer - 1],
|
||||
layers[0].mipmaps[p_base_layer].framebuffers[k],
|
||||
k,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
|
||||
layers[0].mipmaps[p_base_layer].size.x);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p_storage->get_effects()->cubemap_roughness(
|
||||
layers[0].views[p_base_layer - 1],
|
||||
layers[0].views[p_base_layer],
|
||||
p_cube_side,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
|
||||
layers[0].mipmaps[p_base_layer].size.x);
|
||||
if (p_use_arrays) {
|
||||
//render directly to the layers
|
||||
effects->cubemap_roughness(radiance_base_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
|
||||
} else {
|
||||
effects->cubemap_roughness(
|
||||
layers[0].views[p_base_layer - 1],
|
||||
layers[0].views[p_base_layer],
|
||||
p_cube_side,
|
||||
p_sky_ggx_samples_quality,
|
||||
float(p_base_layer) / (layers[0].mipmaps.size() - 1.0),
|
||||
layers[0].mipmaps[p_base_layer].size.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) {
|
||||
EffectsRD *effects = p_storage->get_effects();
|
||||
ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
|
||||
bool prefer_raster_effects = effects->get_prefer_raster_effects();
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Update Radiance Cubemap Array Mipmaps");
|
||||
for (int i = p_start; i < p_end; i++) {
|
||||
for (int j = 0; j < layers[i].views.size() - 1; j++) {
|
||||
RID view = layers[i].views[j];
|
||||
RID texture = layers[i].views[j + 1];
|
||||
Size2i size = layers[i].mipmaps[j + 1].size;
|
||||
p_storage->get_effects()->cubemap_downsample(view, texture, size);
|
||||
if (prefer_raster_effects) {
|
||||
for (int k = 0; k < 6; k++) {
|
||||
RID framebuffer = layers[i].mipmaps[j + 1].framebuffers[k];
|
||||
effects->cubemap_downsample_raster(view, framebuffer, k, size);
|
||||
}
|
||||
} else {
|
||||
RID texture = layers[i].views[j + 1];
|
||||
effects->cubemap_downsample(view, texture, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -902,6 +997,10 @@ void sky() {
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
|
||||
texture_format = p_texture_format;
|
||||
}
|
||||
|
||||
RendererSceneSkyRD::~RendererSceneSkyRD() {
|
||||
// TODO cleanup anything created in init...
|
||||
|
||||
@@ -1170,6 +1269,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
||||
cm = correction * cm;
|
||||
|
||||
if (shader_data->uses_quarter_res) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap");
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
|
||||
|
||||
Vector<Color> clear_colors;
|
||||
@@ -1185,9 +1285,11 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
if (shader_data->uses_half_res) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Sky to Half Res Cubemap");
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES];
|
||||
|
||||
Vector<Color> clear_colors;
|
||||
@@ -1203,11 +1305,13 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
RD::DrawListID cubemap_draw_list;
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP];
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap");
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Transform3D local_view;
|
||||
local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
|
||||
@@ -1217,6 +1321,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
||||
if (sky_mode == RS::SKY_MODE_REALTIME) {
|
||||
sky->reflection.create_reflection_fast_filter(storage, sky_use_cubemap_array);
|
||||
@@ -1393,7 +1498,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
||||
//array (higher quality, 6 times more memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = layers * 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.format = texture_format;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
|
||||
tf.mipmaps = mipmaps;
|
||||
tf.width = w;
|
||||
@@ -1402,13 +1507,13 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
||||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
sky->reflection.update_reflection_data(sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
|
||||
sky->reflection.update_reflection_data(storage, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
|
||||
|
||||
} else {
|
||||
//regular cubemap, lower quality (aliasing, less memory)
|
||||
RD::TextureFormat tf;
|
||||
tf.array_layers = 6;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.format = texture_format;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
|
||||
tf.mipmaps = MIN(mipmaps, layers);
|
||||
tf.width = w;
|
||||
@@ -1417,7 +1522,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
||||
|
||||
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers);
|
||||
sky->reflection.update_reflection_data(storage, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
|
||||
}
|
||||
texture_set_dirty = true;
|
||||
}
|
||||
@@ -1425,7 +1530,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
||||
// Create subpass buffers if they haven't been created already
|
||||
if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
|
||||
RD::TextureFormat tformat;
|
||||
tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tformat.format = texture_format;
|
||||
tformat.width = sky->screen_size.x / 2;
|
||||
tformat.height = sky->screen_size.y / 2;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
@@ -1440,7 +1545,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
|
||||
|
||||
if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) {
|
||||
RD::TextureFormat tformat;
|
||||
tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tformat.format = texture_format;
|
||||
tformat.width = sky->screen_size.x / 4;
|
||||
tformat.height = sky->screen_size.y / 4;
|
||||
tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
Reference in New Issue
Block a user