GPU: Refactor API for Clearing Storage Buffers
The previous API for clearing storage buffers was following the OpenGL api. OpenGL has many options to support for data conversions, striding and sizzling. Metal and Vulkan don't have these features and we have to deal it ourselves. Blender internally only uses a tiny subset for what is possible in OpenGL. Making the current API to difficult to implement on our future platforms as we had to implement all cases, most even not used at all. By changing the API we make future development easier as we only need to implement what we are actually using. **New API** `GPU_storagebuf_clear(GPUStorageBuf* ssbo, uint32_t clear_value)` Related issue: #105492 Pull Request: blender/blender#105521
This commit is contained in:
@@ -836,8 +836,7 @@ void ShadowModule::end_sync()
|
|||||||
tilemap_pool.tiles_data.clear_to_zero();
|
tilemap_pool.tiles_data.clear_to_zero();
|
||||||
|
|
||||||
/* Clear cached page buffer. */
|
/* Clear cached page buffer. */
|
||||||
int2 data = {-1, -1};
|
GPU_storagebuf_clear(pages_cached_data_, -1);
|
||||||
GPU_storagebuf_clear(pages_cached_data_, GPU_RG32I, GPU_DATA_INT, &data);
|
|
||||||
|
|
||||||
/* Reset info to match new state. */
|
/* Reset info to match new state. */
|
||||||
pages_infos_data_.page_free_count = shadow_page_len_;
|
pages_infos_data_.page_free_count = shadow_page_len_;
|
||||||
|
|||||||
@@ -220,14 +220,14 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds,
|
|||||||
uint words_len = (view_len_ == 1) ? divide_ceil_u(resource_len, 32) :
|
uint words_len = (view_len_ == 1) ? divide_ceil_u(resource_len, 32) :
|
||||||
resource_len * word_per_draw;
|
resource_len * word_per_draw;
|
||||||
words_len = ceil_to_multiple_u(max_ii(1, words_len), 4);
|
words_len = ceil_to_multiple_u(max_ii(1, words_len), 4);
|
||||||
uint32_t data = 0xFFFFFFFFu;
|
const uint32_t data = 0xFFFFFFFFu;
|
||||||
|
|
||||||
if (current_pass_type_ == ShadowPass::PASS) {
|
if (current_pass_type_ == ShadowPass::PASS) {
|
||||||
/* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
|
/* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
|
||||||
pass_visibility_buf_.resize(words_len);
|
pass_visibility_buf_.resize(words_len);
|
||||||
GPU_storagebuf_clear(pass_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
|
GPU_storagebuf_clear(pass_visibility_buf_, data);
|
||||||
fail_visibility_buf_.resize(words_len);
|
fail_visibility_buf_.resize(words_len);
|
||||||
GPU_storagebuf_clear(fail_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
|
GPU_storagebuf_clear(fail_visibility_buf_, data);
|
||||||
}
|
}
|
||||||
else if (current_pass_type_ == ShadowPass::FAIL) {
|
else if (current_pass_type_ == ShadowPass::FAIL) {
|
||||||
/* Already computed in the ShadowPass::PASS */
|
/* Already computed in the ShadowPass::PASS */
|
||||||
@@ -236,7 +236,7 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
visibility_buf_.resize(words_len);
|
visibility_buf_.resize(words_len);
|
||||||
GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
|
GPU_storagebuf_clear(visibility_buf_, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_visibility_) {
|
if (do_visibility_) {
|
||||||
|
|||||||
@@ -280,8 +280,8 @@ void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool d
|
|||||||
/* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
|
/* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
|
||||||
visibility_buf_.resize(words_len);
|
visibility_buf_.resize(words_len);
|
||||||
|
|
||||||
uint32_t data = 0xFFFFFFFFu;
|
const uint32_t data = 0xFFFFFFFFu;
|
||||||
GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
|
GPU_storagebuf_clear(visibility_buf_, data);
|
||||||
|
|
||||||
if (do_visibility_) {
|
if (do_visibility_) {
|
||||||
GPUShader *shader = DRW_shader_draw_visibility_compute_get();
|
GPUShader *shader = DRW_shader_draw_visibility_compute_get();
|
||||||
|
|||||||
@@ -39,12 +39,14 @@ void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot);
|
|||||||
void GPU_storagebuf_unbind(GPUStorageBuf *ssbo);
|
void GPU_storagebuf_unbind(GPUStorageBuf *ssbo);
|
||||||
void GPU_storagebuf_unbind_all(void);
|
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);
|
void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the content of the buffer using the given #clear_value. #clear_value will be used as a
|
||||||
|
* repeatable pattern of 32bits.
|
||||||
|
*/
|
||||||
|
void GPU_storagebuf_clear(GPUStorageBuf *ssbo, uint32_t clear_value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read back content of the buffer to CPU for inspection.
|
* Read back content of the buffer to CPU for inspection.
|
||||||
* Slow! Only use for inspection / debugging.
|
* Slow! Only use for inspection / debugging.
|
||||||
|
|||||||
@@ -89,18 +89,14 @@ void GPU_storagebuf_unbind_all()
|
|||||||
/* FIXME */
|
/* 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)
|
void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo)
|
||||||
{
|
{
|
||||||
uint32_t data = 0u;
|
GPU_storagebuf_clear(ssbo, 0);
|
||||||
GPU_storagebuf_clear(ssbo, GPU_R32UI, GPU_DATA_UINT, &data);
|
}
|
||||||
|
|
||||||
|
void GPU_storagebuf_clear(GPUStorageBuf *ssbo, uint32_t clear_value)
|
||||||
|
{
|
||||||
|
unwrap(ssbo)->clear(clear_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_storagebuf_copy_sub_from_vertbuf(
|
void GPU_storagebuf_copy_sub_from_vertbuf(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "BLI_span.hh"
|
||||||
#include "BLI_sys_types.h"
|
#include "BLI_sys_types.h"
|
||||||
|
|
||||||
struct GPUStorageBuf;
|
struct GPUStorageBuf;
|
||||||
@@ -42,9 +43,7 @@ class StorageBuf {
|
|||||||
virtual void update(const void *data) = 0;
|
virtual void update(const void *data) = 0;
|
||||||
virtual void bind(int slot) = 0;
|
virtual void bind(int slot) = 0;
|
||||||
virtual void unbind() = 0;
|
virtual void unbind() = 0;
|
||||||
virtual void clear(eGPUTextureFormat internal_format,
|
virtual void clear(uint32_t clear_value) = 0;
|
||||||
eGPUDataFormat data_format,
|
|
||||||
void *data) = 0;
|
|
||||||
virtual void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) = 0;
|
virtual void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) = 0;
|
||||||
virtual void read(void *data) = 0;
|
virtual void read(void *data) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -117,27 +117,20 @@ void GLStorageBuf::unbind()
|
|||||||
slot_ = 0;
|
slot_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLStorageBuf::clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data)
|
void GLStorageBuf::clear(uint32_t clear_value)
|
||||||
{
|
{
|
||||||
if (ssbo_id_ == 0) {
|
if (ssbo_id_ == 0) {
|
||||||
this->init();
|
this->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GLContext::direct_state_access_support) {
|
if (GLContext::direct_state_access_support) {
|
||||||
glClearNamedBufferData(ssbo_id_,
|
glClearNamedBufferData(ssbo_id_, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, &clear_value);
|
||||||
to_gl_internal_format(internal_format),
|
|
||||||
to_gl_data_format(internal_format),
|
|
||||||
to_gl(data_format),
|
|
||||||
data);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* WATCH(@fclem): This should be ok since we only use clear outside of drawing functions. */
|
/* WATCH(@fclem): This should be ok since we only use clear outside of drawing functions. */
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_id_);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_id_);
|
||||||
glClearBufferData(GL_SHADER_STORAGE_BUFFER,
|
glClearBufferData(
|
||||||
to_gl_internal_format(internal_format),
|
GL_SHADER_STORAGE_BUFFER, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, &clear_value);
|
||||||
to_gl_data_format(internal_format),
|
|
||||||
to_gl(data_format),
|
|
||||||
data);
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class GLStorageBuf : public StorageBuf {
|
|||||||
void update(const void *data) override;
|
void update(const void *data) override;
|
||||||
void bind(int slot) override;
|
void bind(int slot) override;
|
||||||
void unbind() override;
|
void unbind() override;
|
||||||
void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override;
|
void clear(uint32_t clear_value) override;
|
||||||
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
|
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
|
||||||
void read(void *data) override;
|
void read(void *data) override;
|
||||||
|
|
||||||
|
|||||||
@@ -43,11 +43,10 @@ void VKStorageBuffer::unbind()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKStorageBuffer::clear(eGPUTextureFormat /*internal_format*/,
|
void VKStorageBuffer::clear(uint32_t /*clear_value*/)
|
||||||
eGPUDataFormat /*data_format*/,
|
|
||||||
void * /*data*/)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKStorageBuffer::copy_sub(VertBuf * /*src*/,
|
void VKStorageBuffer::copy_sub(VertBuf * /*src*/,
|
||||||
uint /*dst_offset*/,
|
uint /*dst_offset*/,
|
||||||
uint /*src_offset*/,
|
uint /*src_offset*/,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class VKStorageBuffer : public StorageBuf {
|
|||||||
void update(const void *data) override;
|
void update(const void *data) override;
|
||||||
void bind(int slot) override;
|
void bind(int slot) override;
|
||||||
void unbind() override;
|
void unbind() override;
|
||||||
void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override;
|
void clear(uint32_t clear_value) override;
|
||||||
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
|
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override;
|
||||||
void read(void *data) override;
|
void read(void *data) override;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user