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;
|
||||
}
|
||||
|
||||
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_
|
||||
|
||||
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());
|
||||
|
||||
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");
|
||||
slice_layers = src_texture->layers;
|
||||
} 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_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 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++) {
|
||||
RID source = dest;
|
||||
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) {
|
||||
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();
|
||||
for (uint32_t l = 0; l < rb->get_view_count(); l++) {
|
||||
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) {
|
||||
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];
|
||||
}
|
||||
|
||||
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.y = msize.height;
|
||||
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("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_slice", "context", "name", "layer", "mipmap"), &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", "context", "name", "layer", "mipmap", "layers", "mipmaps"), &RenderSceneBuffersRD::get_texture_slice);
|
||||
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);
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
|
||||
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(size);
|
||||
p_named_texture.sizes.resize(p_named_texture.format.mipmaps);
|
||||
|
||||
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 layer = 0; layer < p_named_texture.format.array_layers; layer++) {
|
||||
uint32_t index = layer * p_named_texture.format.mipmaps + mipmap;
|
||||
|
||||
p_named_texture.sizes.ptrw()[index] = mipmap_size;
|
||||
}
|
||||
p_named_texture.sizes.ptrw()[mipmap] = mipmap_size;
|
||||
|
||||
mipmap_size.width = MAX(1, mipmap_size.width >> 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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
|
||||
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_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
|
||||
if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) {
|
||||
// asking the whole thing? just return the original
|
||||
if (p_layer == 0 && p_mipmap == 0 && named_texture.format.array_layers == p_layers && named_texture.format.mipmaps == p_mipmaps) {
|
||||
return named_texture.texture;
|
||||
}
|
||||
|
||||
// get our index and make sure we have enough entries in our slices vector
|
||||
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
|
||||
while (named_texture.slices.size() <= int(index)) {
|
||||
named_texture.slices.push_back(RID());
|
||||
// see if we have this
|
||||
NTSliceKey slice_key(p_layer, p_layers, p_mipmap, p_mipmaps);
|
||||
if (named_texture.slices.has(slice_key)) {
|
||||
return named_texture.slices[slice_key];
|
||||
}
|
||||
|
||||
// create our slice if we don't have it already
|
||||
if (named_texture.slices[index].is_null()) {
|
||||
named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap);
|
||||
// create our slice
|
||||
RID &slice = named_texture.slices[slice_key];
|
||||
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;
|
||||
arr.push_back(p_context);
|
||||
arr.push_back(p_texture_name);
|
||||
arr.push_back(itos(p_layer));
|
||||
arr.push_back(itos(p_mipmap));
|
||||
RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr));
|
||||
}
|
||||
Array arr;
|
||||
arr.push_back(p_context);
|
||||
arr.push_back(p_texture_name);
|
||||
arr.push_back(itos(p_layer));
|
||||
arr.push_back(itos(p_layers));
|
||||
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
|
||||
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);
|
||||
|
||||
// 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());
|
||||
|
||||
// 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());
|
||||
|
||||
// get our index
|
||||
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
|
||||
|
||||
// and return our size
|
||||
return named_texture.sizes[index];
|
||||
// return our size
|
||||
return named_texture.sizes[p_mipmap];
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
|
||||
|
|
|
@ -93,7 +93,6 @@ private:
|
|||
}
|
||||
|
||||
static uint32_t hash(const NTKey &p_val) {
|
||||
// FIXME, properly hash two stringnames together
|
||||
uint32_t h = p_val.context.hash();
|
||||
h = hash_murmur3_one_32(p_val.buffer_name.hash(), 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 {
|
||||
// Cache the data used to create our texture
|
||||
RD::TextureFormat format;
|
||||
|
@ -113,7 +139,7 @@ private:
|
|||
|
||||
// Our texture objects, slices are lazy (i.e. only created when requested).
|
||||
RID texture;
|
||||
Vector<RID> slices;
|
||||
mutable HashMap<NTSliceKey, RID, NTSliceKey> slices;
|
||||
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 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;
|
||||
RID get_texture_slice(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_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_mipmap);
|
||||
|
||||
void clear_context(const StringName &p_context);
|
||||
|
||||
|
|
|
@ -530,7 +530,7 @@ public:
|
|||
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 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