Vulkan: Clearing Storage Buffers #105487

Merged
Jeroen Bakker merged 94 commits from Jeroen-Bakker/blender:vulkan-storage-buffer-clear into main 2023-03-17 13:48:50 +01:00
11 changed files with 68 additions and 42 deletions
Showing only changes of commit 96af333650 - Show all commits

View File

@ -233,7 +233,7 @@ void MotionBlurModule::render(View &view, GPUTexture **input_tx, GPUTexture **ou
tiles_tx_.acquire(tiles_extent, GPU_RGBA16F);
GPU_storagebuf_clear_to_zero(tile_indirection_buf_);
tile_indirection_buf_.clear_to_zero();
inst_.manager->submit(motion_blur_ps_, view);

View File

@ -834,17 +834,17 @@ void ShadowModule::end_sync()
/* Clear tile-map clip buffer. */
union {
ShadowTileMapClip clip;
int4 i;
uint4 i;
} u;
u.clip.clip_near_stored = 0.0f;
u.clip.clip_far_stored = 0.0f;
u.clip.clip_near = int(0xFF7FFFFFu ^ 0x7FFFFFFFu); /* floatBitsToOrderedInt(-FLT_MAX) */
u.clip.clip_far = 0x7F7FFFFF; /* floatBitsToOrderedInt(FLT_MAX) */
GPU_storagebuf_clear(tilemap_pool.tilemaps_clip, GPU_RGBA32I, GPU_DATA_INT, &u.i);
u.clip.clip_near = 0xFF7FFFFFu ^ 0x7FFFFFFFu; /* floatBitsToOrderedInt(-FLT_MAX) */
u.clip.clip_far = 0x7F7FFFFF; /* floatBitsToOrderedInt(FLT_MAX) */
GPU_storagebuf_clear_uint(tilemap_pool.tilemaps_clip, u.i, 4);
/* Clear cached page buffer. */
int2 data = {-1, -1};
GPU_storagebuf_clear(pages_cached_data_, GPU_RG32I, GPU_DATA_INT, &data);
GPU_storagebuf_clear_int(pages_cached_data_, data, 2);
/* Reset info to match new state. */
pages_infos_data_.page_free_count = shadow_page_len_;

View File

@ -225,9 +225,9 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds,
if (current_pass_type_ == ShadowPass::PASS) {
/* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
pass_visibility_buf_.resize(words_len);
GPU_storagebuf_clear(pass_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(pass_visibility_buf_, &data, 1);
fail_visibility_buf_.resize(words_len);
GPU_storagebuf_clear(fail_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(fail_visibility_buf_, &data, 1);
}
else if (current_pass_type_ == ShadowPass::FAIL) {
/* Already computed in the ShadowPass::PASS */
@ -236,7 +236,7 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds,
}
else {
visibility_buf_.resize(words_len);
GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(visibility_buf_, &data, 1);
}
if (do_visibility_) {

View File

@ -281,7 +281,7 @@ void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool d
visibility_buf_.resize(words_len);
uint32_t data = 0xFFFFFFFFu;
GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(visibility_buf_, &data, 1);
if (do_visibility_) {
GPUShader *shader = DRW_shader_draw_visibility_compute_get();

View File

@ -39,12 +39,24 @@ void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot);
void GPU_storagebuf_unbind(GPUStorageBuf *ssbo);
void GPU_storagebuf_unbind_all(void);
void GPU_storagebuf_clear(GPUStorageBuf *ssbo,
eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data);
void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo);
/**
* Clear the content of the buffer using the given #clear_data. #clear_data will be used as a
* repeatable pattern.
*
* NOTE: clear_data_len must be in range 1 to 4 (inclusive).
*/
void GPU_storagebuf_clear_uint(GPUStorageBuf *ssbo, uint32_t *clear_data, uint8_t clear_data_len);
/**
* Clear the content of the buffer using the given #clear_data. #clear_data will be used as a
* repeatable pattern.
*
* NOTE: clear_data_len must be in range 1 to 4 (inclusive).
*/
void GPU_storagebuf_clear_int(GPUStorageBuf *ssbo, int32_t *clear_data, uint8_t clear_data_len);
/**
* Read back content of the buffer to CPU for inspection.
* Slow! Only use for inspection / debugging.

View File

@ -89,18 +89,22 @@ void GPU_storagebuf_unbind_all()
/* FIXME */
}
void GPU_storagebuf_clear(GPUStorageBuf *ssbo,
eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data)
{
unwrap(ssbo)->clear(internal_format, data_format, data);
}
void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo)
{
uint32_t data = 0u;
GPU_storagebuf_clear(ssbo, GPU_R32UI, GPU_DATA_UINT, &data);
GPU_storagebuf_clear_uint(ssbo, &data, 1);
}
void GPU_storagebuf_clear_int(GPUStorageBuf *ssbo, int32_t *clear_data, uint8_t clear_data_len)
{
uint32_t *clear_data_uint = static_cast<uint32_t *>(static_cast<void *>(clear_data));
GPU_storagebuf_clear_uint(ssbo, clear_data_uint, clear_data_len);
}
void GPU_storagebuf_clear_uint(GPUStorageBuf *ssbo, uint32_t *clear_data, uint8_t clear_data_len)
{
BLI_assert(clear_data_len >= 1 && clear_data_len <= 4);
unwrap(ssbo)->clear(blender::Span<uint32_t>(clear_data, clear_data_len));
}
void GPU_storagebuf_copy_sub_from_vertbuf(

View File

@ -7,6 +7,7 @@
#pragma once
#include "BLI_span.hh"
#include "BLI_sys_types.h"
struct GPUStorageBuf;
@ -42,9 +43,7 @@ class StorageBuf {
virtual void update(const void *data) = 0;
virtual void bind(int slot) = 0;
virtual void unbind() = 0;
virtual void clear(eGPUTextureFormat internal_format,
eGPUDataFormat data_format,
void *data) = 0;
virtual void clear(Span<uint32_t> data) = 0;
virtual void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) = 0;
virtual void read(void *data) = 0;
};

View File

@ -117,27 +117,39 @@ void GLStorageBuf::unbind()
slot_ = 0;
}
void GLStorageBuf::clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data)
void GLStorageBuf::clear(Span<uint32_t> data)
{
if (ssbo_id_ == 0) {
this->init();
}
GLenum internal_format = GL_R32UI;
GLenum format = GL_RED;
if (data.size() == 1) {
internal_format = GL_R32UI;
format = GL_RED;
}
else if (data.size() == 2) {
internal_format = GL_RG32UI;
format = GL_RG;
}
else if (data.size() == 3) {
internal_format = GL_RGB32UI;
format = GL_RGB;
}
else if (data.size() == 4) {
internal_format = GL_RGBA32UI;
format = GL_RGBA;
}
if (GLContext::direct_state_access_support) {
glClearNamedBufferData(ssbo_id_,
to_gl_internal_format(internal_format),
to_gl_data_format(internal_format),
to_gl(data_format),
data);
glClearNamedBufferData(ssbo_id_, internal_format, format, GL_UNSIGNED_INT, data.data());
}
else {
/* WATCH(@fclem): This should be ok since we only use clear outside of drawing functions. */
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_id_);
glClearBufferData(GL_SHADER_STORAGE_BUFFER,
to_gl_internal_format(internal_format),
to_gl_data_format(internal_format),
to_gl(data_format),
data);
glClearBufferData(
GL_SHADER_STORAGE_BUFFER, internal_format, format, GL_UNSIGNED_INT, data.data());
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
}

View File

@ -33,7 +33,7 @@ class GLStorageBuf : public StorageBuf {
void update(const void *data) override;
void bind(int slot) override;
void unbind() override;
void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override;
void clear(Span<uint32_t> data) override;
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
void read(void *data) override;

View File

@ -43,11 +43,10 @@ void VKStorageBuffer::unbind()
{
}
void VKStorageBuffer::clear(eGPUTextureFormat /*internal_format*/,
eGPUDataFormat /*data_format*/,
void * /*data*/)
void VKStorageBuffer::clear(Span<uint32_t> /*data*/)
{
}
void VKStorageBuffer::copy_sub(VertBuf * /*src*/,
uint /*dst_offset*/,
uint /*src_offset*/,

View File

@ -30,7 +30,7 @@ class VKStorageBuffer : public StorageBuf {
void update(const void *data) override;
void bind(int slot) override;
void unbind() override;
void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override;
void clear(Span<uint32_t> data) override;
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
void read(void *data) override;