Add layer slice support to render device and render buffers
This commit is contained in:
parent
0a9e6e478e
commit
093289364f
@ -2294,7 +2294,7 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
|
|||||||
return id;
|
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, uint32_t p_mipmaps, 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, uint32_t p_mipmaps, TextureSliceType p_slice_type, uint32_t p_layers) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
Texture *src_texture = texture_owner.get_or_null(p_with_texture);
|
Texture *src_texture = texture_owner.get_or_null(p_with_texture);
|
||||||
@ -2322,7 +2322,11 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
|
|||||||
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, src_texture->layers, RID());
|
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, src_texture->layers, RID());
|
||||||
|
|
||||||
int slice_layers = 1;
|
int slice_layers = 1;
|
||||||
if (p_slice_type == TEXTURE_SLICE_2D_ARRAY) {
|
if (p_layers != 0) {
|
||||||
|
ERR_FAIL_COND_V_MSG(p_layers > 1 && p_slice_type != TEXTURE_SLICE_2D_ARRAY, RID(), "layer slicing only supported for 2D arrays");
|
||||||
|
ERR_FAIL_COND_V_MSG(p_layer + p_layers > src_texture->layers, RID(), "layer slice is out of bounds");
|
||||||
|
slice_layers = p_layers;
|
||||||
|
} else if (p_slice_type == TEXTURE_SLICE_2D_ARRAY) {
|
||||||
ERR_FAIL_COND_V_MSG(p_layer != 0, RID(), "layer must be 0 when obtaining a 2D array mipmap slice");
|
ERR_FAIL_COND_V_MSG(p_layer != 0, RID(), "layer must be 0 when obtaining a 2D array mipmap slice");
|
||||||
slice_layers = src_texture->layers;
|
slice_layers = src_texture->layers;
|
||||||
} else if (p_slice_type == TEXTURE_SLICE_CUBEMAP) {
|
} else if (p_slice_type == TEXTURE_SLICE_CUBEMAP) {
|
||||||
|
@ -1047,7 +1047,7 @@ public:
|
|||||||
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_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, uint32_t p_mipmaps = 1, 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, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D, uint32_t p_layers = 0);
|
||||||
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
|
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS);
|
||||||
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer);
|
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer);
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
|
|||||||
for (int i = 1; i < mipmaps; i++) {
|
for (int i = 1; i < mipmaps; i++) {
|
||||||
RID source = dest;
|
RID source = dest;
|
||||||
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
|
dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
|
||||||
Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
|
Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, i);
|
||||||
|
|
||||||
if (can_use_storage) {
|
if (can_use_storage) {
|
||||||
copy_effects->make_mipmap(source, dest, msize);
|
copy_effects->make_mipmap(source, dest, msize);
|
||||||
@ -448,7 +448,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||||||
float luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
float luminance_multiplier = _render_buffers_get_luminance_multiplier();
|
||||||
for (uint32_t l = 0; l < rb->get_view_count(); l++) {
|
for (uint32_t l = 0; l < rb->get_view_count(); l++) {
|
||||||
for (int i = 0; i < (max_glow_level + 1); i++) {
|
for (int i = 0; i < (max_glow_level + 1); i++) {
|
||||||
Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
|
Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, i);
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
RID luminance_texture;
|
RID luminance_texture;
|
||||||
@ -502,7 +502,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||||||
tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i];
|
tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
|
Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0);
|
||||||
tonemap.glow_texture_size.x = msize.width;
|
tonemap.glow_texture_size.x = msize.width;
|
||||||
tonemap.glow_texture_size.y = msize.height;
|
tonemap.glow_texture_size.y = msize.height;
|
||||||
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
|
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
|
||||||
|
@ -50,25 +50,19 @@ void RenderSceneBuffersRD::_bind_methods() {
|
|||||||
// ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture);
|
// ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture);
|
||||||
ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
|
ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
|
||||||
// ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format);
|
// ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format);
|
||||||
ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice);
|
ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap", "layers", "mipmaps"), &RenderSceneBuffersRD::get_texture_slice);
|
||||||
ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
|
ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
|
||||||
ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
|
ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
|
void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
|
||||||
ERR_FAIL_COND(p_named_texture.texture.is_null());
|
ERR_FAIL_COND(p_named_texture.texture.is_null());
|
||||||
|
|
||||||
uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps;
|
p_named_texture.sizes.resize(p_named_texture.format.mipmaps);
|
||||||
p_named_texture.sizes.resize(size);
|
|
||||||
|
|
||||||
Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
|
Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
|
||||||
|
|
||||||
for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
|
for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
|
||||||
for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) {
|
p_named_texture.sizes.ptrw()[mipmap] = mipmap_size;
|
||||||
uint32_t index = layer * p_named_texture.format.mipmaps + mipmap;
|
|
||||||
|
|
||||||
p_named_texture.sizes.ptrw()[index] = mipmap_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
mipmap_size.width = MAX(1, mipmap_size.width >> 1);
|
mipmap_size.width = MAX(1, mipmap_size.width >> 1);
|
||||||
mipmap_size.height = MAX(1, mipmap_size.height >> 1);
|
mipmap_size.height = MAX(1, mipmap_size.height >> 1);
|
||||||
@ -324,7 +318,7 @@ const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringNam
|
|||||||
return named_textures[key].format;
|
return named_textures[key].format;
|
||||||
}
|
}
|
||||||
|
|
||||||
RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
|
RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers, const uint32_t p_mipmaps) {
|
||||||
NTKey key(p_context, p_texture_name);
|
NTKey key(p_context, p_texture_name);
|
||||||
|
|
||||||
// check if this is a known texture
|
// check if this is a known texture
|
||||||
@ -334,36 +328,41 @@ RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const S
|
|||||||
|
|
||||||
// check if we're in bounds
|
// check if we're in bounds
|
||||||
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
|
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
|
||||||
|
ERR_FAIL_COND_V(p_layers == 0, RID());
|
||||||
|
ERR_FAIL_COND_V(p_layer + p_layers > named_texture.format.array_layers, RID());
|
||||||
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
|
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
|
||||||
|
ERR_FAIL_COND_V(p_mipmaps == 0, RID());
|
||||||
|
ERR_FAIL_COND_V(p_mipmap + p_mipmaps > named_texture.format.mipmaps, RID());
|
||||||
|
|
||||||
// if we don't have multiple layers or mipmaps, we can just return our texture as is
|
// asking the whole thing? just return the original
|
||||||
if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) {
|
if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps) {
|
||||||
return named_texture.texture;
|
return named_texture.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get our index and make sure we have enough entries in our slices vector
|
// see if we have this
|
||||||
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
|
NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps);
|
||||||
while (named_texture.slices.size() <= int(index)) {
|
if (named_texture.slices.has(slice_key)) {
|
||||||
named_texture.slices.push_back(RID());
|
return named_texture.slices[slice_key];
|
||||||
}
|
}
|
||||||
|
|
||||||
// create our slice if we don't have it already
|
// create our slice
|
||||||
if (named_texture.slices[index].is_null()) {
|
RID &slice = named_texture.slices[slice_key];
|
||||||
named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap);
|
slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap, p_mipmaps, p_layers > 1 ? RD::TEXTURE_SLICE_2D_ARRAY : RD::TEXTURE_SLICE_2D, p_layers);
|
||||||
|
|
||||||
Array arr;
|
Array arr;
|
||||||
arr.push_back(p_context);
|
arr.push_back(p_context);
|
||||||
arr.push_back(p_texture_name);
|
arr.push_back(p_texture_name);
|
||||||
arr.push_back(itos(p_layer));
|
arr.push_back(itos(p_layer));
|
||||||
arr.push_back(itos(p_mipmap));
|
arr.push_back(itos(p_layers));
|
||||||
RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr));
|
arr.push_back(itos(p_mipmap));
|
||||||
}
|
arr.push_back(itos(p_mipmaps));
|
||||||
|
RD::get_singleton()->set_resource_name(slice, String("RenderBuffer {0}/{1}, layer {2}/{3}, mipmap {4}/{5}").format(arr));
|
||||||
|
|
||||||
// and return our slice
|
// and return our slice
|
||||||
return named_texture.slices[index];
|
return slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
|
Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap) {
|
||||||
NTKey key(p_context, p_texture_name);
|
NTKey key(p_context, p_texture_name);
|
||||||
|
|
||||||
// check if this is a known texture
|
// check if this is a known texture
|
||||||
@ -372,14 +371,10 @@ Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context,
|
|||||||
ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
|
ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
|
||||||
|
|
||||||
// check if we're in bounds
|
// check if we're in bounds
|
||||||
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i());
|
|
||||||
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
|
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
|
||||||
|
|
||||||
// get our index
|
// return our size
|
||||||
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
|
return named_texture.sizes[p_mipmap];
|
||||||
|
|
||||||
// and return our size
|
|
||||||
return named_texture.sizes[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
|
void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
|
||||||
|
@ -93,7 +93,6 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t hash(const NTKey &p_val) {
|
static uint32_t hash(const NTKey &p_val) {
|
||||||
// FIXME, properly hash two stringnames together
|
|
||||||
uint32_t h = p_val.context.hash();
|
uint32_t h = p_val.context.hash();
|
||||||
h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
|
h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
|
||||||
return hash_fmix32(h);
|
return hash_fmix32(h);
|
||||||
@ -106,6 +105,33 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NTSliceKey {
|
||||||
|
uint32_t layer;
|
||||||
|
uint32_t layers;
|
||||||
|
uint32_t mipmap;
|
||||||
|
uint32_t mipmaps;
|
||||||
|
|
||||||
|
bool operator==(const NTSliceKey &p_val) const {
|
||||||
|
return (layer == p_val.layer) && (layers == p_val.layers) && (mipmap == p_val.mipmap) && (mipmaps == p_val.mipmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t hash(const NTSliceKey &p_val) {
|
||||||
|
uint32_t h = hash_murmur3_one_32(p_val.layer);
|
||||||
|
h = hash_murmur3_one_32(p_val.layers, h);
|
||||||
|
h = hash_murmur3_one_32(p_val.mipmap, h);
|
||||||
|
h = hash_murmur3_one_32(p_val.mipmaps, h);
|
||||||
|
return hash_fmix32(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSliceKey() {}
|
||||||
|
NTSliceKey(uint32_t p_layer, uint32_t p_layers, uint32_t p_mipmap, uint32_t p_mipmaps) {
|
||||||
|
layer = p_layer;
|
||||||
|
layers = p_layers;
|
||||||
|
mipmap = p_mipmap;
|
||||||
|
mipmaps = p_mipmaps;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct NamedTexture {
|
struct NamedTexture {
|
||||||
// Cache the data used to create our texture
|
// Cache the data used to create our texture
|
||||||
RD::TextureFormat format;
|
RD::TextureFormat format;
|
||||||
@ -113,7 +139,7 @@ private:
|
|||||||
|
|
||||||
// Our texture objects, slices are lazy (i.e. only created when requested).
|
// Our texture objects, slices are lazy (i.e. only created when requested).
|
||||||
RID texture;
|
RID texture;
|
||||||
Vector<RID> slices;
|
mutable HashMap<NTSliceKey, RID, NTSliceKey> slices;
|
||||||
Vector<Size2i> sizes;
|
Vector<Size2i> sizes;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -154,8 +180,8 @@ public:
|
|||||||
RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
|
RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
|
||||||
RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
|
RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
|
||||||
const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
|
const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
|
||||||
RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
|
RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap, const uint32_t p_layers = 1, const uint32_t p_mipmaps = 1);
|
||||||
Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
|
Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_mipmap);
|
||||||
|
|
||||||
void clear_context(const StringName &p_context);
|
void clear_context(const StringName &p_context);
|
||||||
|
|
||||||
|
@ -530,7 +530,7 @@ public:
|
|||||||
TEXTURE_SLICE_2D_ARRAY,
|
TEXTURE_SLICE_2D_ARRAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0;
|
virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, uint32_t p_mipmaps = 1, TextureSliceType p_slice_type = TEXTURE_SLICE_2D, uint32_t p_layers = 0) = 0;
|
||||||
|
|
||||||
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
|
virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector<uint8_t> &p_data, BitField<BarrierMask> p_post_barrier = BARRIER_MASK_ALL_BARRIERS) = 0;
|
||||||
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush
|
virtual Vector<uint8_t> texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush
|
||||||
|
Loading…
Reference in New Issue
Block a user