Vulkan: Add Support For Texture Buffers #108193
|
@ -566,6 +566,7 @@ set(GLSL_SRC
|
|||
|
||||
set(GLSL_SRC_TEST
|
||||
tests/shaders/gpu_math_test.glsl
|
||||
tests/shaders/gpu_buffer_texture_test.glsl
|
||||
tests/shaders/gpu_compute_1d_test.glsl
|
||||
tests/shaders/gpu_compute_2d_test.glsl
|
||||
tests/shaders/gpu_compute_ibo_test.glsl
|
||||
|
@ -847,6 +848,7 @@ if(WITH_GTESTS)
|
|||
set(TEST_SRC
|
||||
tests/gpu_testing.cc
|
||||
|
||||
tests/buffer_texture_test.cc
|
||||
tests/framebuffer_test.cc
|
||||
tests/immediate_test.cc
|
||||
tests/index_buffer_test.cc
|
||||
|
|
|
@ -85,6 +85,13 @@ GPU_SHADER_CREATE_INFO(gpu_push_constants_512bytes_test)
|
|||
.push_constant(Type::FLOAT, "filler3", 64)
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_buffer_texture_test)
|
||||
.local_group_size(1)
|
||||
.sampler(0, ImageType::FLOAT_BUFFER, "bufferTexture")
|
||||
.storage_buf(0, Qualifier::WRITE, "float", "data_out[]")
|
||||
.compute_source("gpu_buffer_texture_test.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_shadow_test)
|
||||
.fragment_source("eevee_shadow_test.glsl")
|
||||
.additional_info("gpu_shader_test")
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
#include "GPU_capabilities.h"
|
||||
#include "GPU_compute.h"
|
||||
#include "GPU_vertex_buffer.h"
|
||||
#include "GPU_vertex_format.h"
|
||||
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "gpu_testing.hh"
|
||||
|
||||
namespace blender::gpu::tests {
|
||||
|
||||
static constexpr int Size = 256;
|
||||
Jeroen-Bakker marked this conversation as resolved
|
||||
|
||||
static void test_buffer_texture()
|
||||
{
|
||||
if (!GPU_compute_shader_support() && !GPU_shader_storage_buffer_objects_support()) {
|
||||
/* We can't test as a the platform does not support compute shaders. */
|
||||
std::cout << "Skipping compute shader test: platform not supported";
|
||||
GTEST_SKIP();
|
||||
}
|
||||
|
||||
/* Build compute shader. */
|
||||
GPUShader *shader = GPU_shader_create_from_info_name("gpu_buffer_texture_test");
|
||||
EXPECT_NE(shader, nullptr);
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
/* Vertex buffer. */
|
||||
GPUVertFormat format = {};
|
||||
uint value_pos = GPU_vertformat_attr_add(&format, "value", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
GPUVertBuf *vertex_buffer = GPU_vertbuf_create_with_format_ex(
|
||||
&format, GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY);
|
||||
float4 value = float4(42.42, 23.23, 1.0, -1.0);
|
||||
GPU_vertbuf_data_alloc(vertex_buffer, 4);
|
||||
GPU_vertbuf_attr_fill(vertex_buffer, value_pos, &value);
|
||||
GPU_vertbuf_bind_as_texture(vertex_buffer,
|
||||
GPU_shader_get_sampler_binding(shader, "bufferTexture"));
|
||||
|
||||
/* Construct SSBO. */
|
||||
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
|
||||
4 * sizeof(float), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
|
||||
GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo_binding(shader, "data_out"));
|
||||
|
||||
/* Dispatch compute task. */
|
||||
GPU_compute_dispatch(shader, 4, 1, 1);
|
||||
|
||||
/* Check if compute has been done. */
|
||||
GPU_memory_barrier(GPU_BARRIER_BUFFER_UPDATE);
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
Jeroen Bakker
commented
storage buffer storage buffer
|
||||
|
||||
/* Download the index buffer. */
|
||||
float4 read_data;
|
||||
GPU_storagebuf_read(ssbo, read_data);
|
||||
EXPECT_EQ(read_data, value);
|
||||
|
||||
/* Cleanup. */
|
||||
GPU_shader_unbind();
|
||||
GPU_storagebuf_free(ssbo);
|
||||
GPU_vertbuf_discard(vertex_buffer);
|
||||
GPU_shader_free(shader);
|
||||
}
|
||||
|
||||
GPU_TEST(buffer_texture)
|
||||
|
||||
} // namespace blender::gpu::tests
|
|
@ -0,0 +1,6 @@
|
|||
void main()
|
||||
{
|
||||
int index = int(gl_GlobalInvocationID.x);
|
||||
float value = texelFetch(bufferTexture, index).r;
|
||||
data_out[index] = value;
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#include "vk_pixel_buffer.hh"
|
||||
#include "vk_query.hh"
|
||||
#include "vk_shader.hh"
|
||||
#include "vk_state_manager.hh"
|
||||
#include "vk_storage_buffer.hh"
|
||||
#include "vk_texture.hh"
|
||||
#include "vk_uniform_buffer.hh"
|
||||
|
@ -64,6 +65,7 @@ void VKBackend::samplers_update() {}
|
|||
void VKBackend::compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len)
|
||||
{
|
||||
VKContext &context = *VKContext::get();
|
||||
context.state_manager_get().apply_bindings();
|
||||
context.bind_compute_pipeline();
|
||||
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||
command_buffer.dispatch(groups_x_len, groups_y_len, groups_z_len);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "vk_context.hh"
|
||||
#include "vk_index_buffer.hh"
|
||||
#include "vk_state_manager.hh"
|
||||
#include "vk_vertex_attribute_object.hh"
|
||||
#include "vk_vertex_buffer.hh"
|
||||
|
||||
|
@ -22,7 +23,9 @@ void VKBatch::draw(int vertex_first, int vertex_count, int instance_first, int i
|
|||
|
||||
/* Finalize graphics pipeline */
|
||||
VKContext &context = *VKContext::get();
|
||||
context.state_manager->apply_state();
|
||||
VKStateManager &state_manager = context.state_manager_get();
|
||||
state_manager.apply_state();
|
||||
state_manager.apply_bindings();
|
||||
VKVertexAttributeObject vao;
|
||||
vao.update_bindings(context, *this);
|
||||
context.bind_graphics_pipeline(prim_type, vao);
|
||||
|
|
|
@ -94,6 +94,15 @@ void VKDescriptorSetTracker::bind(VKTexture &texture,
|
|||
binding.vk_sampler = sampler.vk_handle();
|
||||
}
|
||||
|
||||
void VKDescriptorSetTracker::bind(VKVertexBuffer &vertex_buffer,
|
||||
const VKDescriptorSet::Location location)
|
||||
{
|
||||
Binding &binding = ensure_location(location);
|
||||
binding.type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
binding.vk_buffer_view = vertex_buffer.vk_buffer_view_get();
|
||||
binding.buffer_size = vertex_buffer.size_alloc_get();
|
||||
}
|
||||
|
||||
VKDescriptorSetTracker::Binding &VKDescriptorSetTracker::ensure_location(
|
||||
const VKDescriptorSet::Location location)
|
||||
{
|
||||
|
@ -115,8 +124,10 @@ void VKDescriptorSetTracker::update(VKContext &context)
|
|||
tracked_resource_for(context, !bindings_.is_empty());
|
||||
std::unique_ptr<VKDescriptorSet> &descriptor_set = active_descriptor_set();
|
||||
VkDescriptorSet vk_descriptor_set = descriptor_set->vk_handle();
|
||||
BLI_assert(vk_descriptor_set != VK_NULL_HANDLE);
|
||||
|
||||
Vector<VkDescriptorBufferInfo> buffer_infos;
|
||||
buffer_infos.reserve(16);
|
||||
Vector<VkWriteDescriptorSet> descriptor_writes;
|
||||
|
||||
for (const Binding &binding : bindings_) {
|
||||
|
@ -138,7 +149,22 @@ void VKDescriptorSetTracker::update(VKContext &context)
|
|||
descriptor_writes.append(write_descriptor);
|
||||
}
|
||||
|
||||
for (const Binding &binding : bindings_) {
|
||||
if (!binding.is_texel_buffer()) {
|
||||
continue;
|
||||
}
|
||||
VkWriteDescriptorSet write_descriptor = {};
|
||||
write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
write_descriptor.dstSet = vk_descriptor_set;
|
||||
write_descriptor.dstBinding = binding.location;
|
||||
write_descriptor.descriptorCount = 1;
|
||||
write_descriptor.descriptorType = binding.type;
|
||||
write_descriptor.pTexelBufferView = &binding.vk_buffer_view;
|
||||
descriptor_writes.append(write_descriptor);
|
||||
}
|
||||
|
||||
Vector<VkDescriptorImageInfo> image_infos;
|
||||
image_infos.reserve(16);
|
||||
for (const Binding &binding : bindings_) {
|
||||
if (!binding.is_image()) {
|
||||
continue;
|
||||
|
@ -161,9 +187,6 @@ void VKDescriptorSetTracker::update(VKContext &context)
|
|||
descriptor_writes.append(write_descriptor);
|
||||
}
|
||||
|
||||
BLI_assert_msg(image_infos.size() + buffer_infos.size() == descriptor_writes.size(),
|
||||
"Not all changes have been converted to a write descriptor. Check "
|
||||
"`Binding::is_buffer` and `Binding::is_image`.");
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vkUpdateDescriptorSets(
|
||||
device.device_get(), descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
||||
|
|
|
@ -83,12 +83,14 @@ class VKDescriptorSet : NonCopyable {
|
|||
VKDescriptorSet(VkDescriptorPool vk_descriptor_pool, VkDescriptorSet vk_descriptor_set)
|
||||
: vk_descriptor_pool_(vk_descriptor_pool), vk_descriptor_set_(vk_descriptor_set)
|
||||
{
|
||||
BLI_assert(vk_descriptor_set_ != VK_NULL_HANDLE);
|
||||
}
|
||||
VKDescriptorSet(VKDescriptorSet &&other);
|
||||
virtual ~VKDescriptorSet();
|
||||
|
||||
VKDescriptorSet &operator=(VKDescriptorSet &&other)
|
||||
{
|
||||
BLI_assert(other.vk_descriptor_set_ != VK_NULL_HANDLE);
|
||||
vk_descriptor_set_ = other.vk_descriptor_set_;
|
||||
vk_descriptor_pool_ = other.vk_descriptor_pool_;
|
||||
other.mark_freed();
|
||||
|
@ -118,6 +120,8 @@ class VKDescriptorSetTracker : protected VKResourceTracker<VKDescriptorSet> {
|
|||
VkBuffer vk_buffer = VK_NULL_HANDLE;
|
||||
VkDeviceSize buffer_size = 0;
|
||||
|
||||
VkBufferView vk_buffer_view = VK_NULL_HANDLE;
|
||||
|
||||
VKTexture *texture = nullptr;
|
||||
VkSampler vk_sampler = VK_NULL_HANDLE;
|
||||
|
||||
|
@ -131,6 +135,11 @@ class VKDescriptorSetTracker : protected VKResourceTracker<VKDescriptorSet> {
|
|||
return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
}
|
||||
|
||||
bool is_texel_buffer() const
|
||||
{
|
||||
return ELEM(type, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
|
||||
}
|
||||
|
||||
bool is_image() const
|
||||
{
|
||||
return ELEM(type,
|
||||
|
@ -157,7 +166,8 @@ class VKDescriptorSetTracker : protected VKResourceTracker<VKDescriptorSet> {
|
|||
/* TODO: bind as image */
|
||||
void image_bind(VKTexture &texture, VKDescriptorSet::Location location);
|
||||
void bind(VKTexture &texture, VKDescriptorSet::Location location, VKSampler &sampler);
|
||||
|
||||
/* Bind as uniform texel buffer. */
|
||||
void bind(VKVertexBuffer &vertex_buffer, VKDescriptorSet::Location location);
|
||||
/**
|
||||
* Some shaders don't need any descriptor sets so we don't need to bind them.
|
||||
*
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "vk_immediate.hh"
|
||||
#include "vk_data_conversion.hh"
|
||||
#include "vk_state_manager.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
||||
|
@ -47,7 +48,9 @@ void VKImmediate::end()
|
|||
|
||||
VKContext &context = *VKContext::get();
|
||||
BLI_assert(context.shader == unwrap(shader));
|
||||
context.state_manager->apply_state();
|
||||
VKStateManager &state_manager = context.state_manager_get();
|
||||
state_manager.apply_state();
|
||||
state_manager.apply_bindings();
|
||||
vertex_attributes_.update_bindings(*this);
|
||||
context.bind_graphics_pipeline(prim_type, vertex_attributes_);
|
||||
vertex_attributes_.bind(context);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "vk_pipeline.hh"
|
||||
#include "vk_shader.hh"
|
||||
#include "vk_texture.hh"
|
||||
#include "vk_vertex_buffer.hh"
|
||||
|
||||
#include "GPU_capabilities.h"
|
||||
|
||||
|
@ -21,8 +22,8 @@ VKStateManager::VKStateManager()
|
|||
constexpr int max_bindings = 16;
|
||||
image_bindings_ = Array<ImageBinding>(max_bindings);
|
||||
image_bindings_.fill(ImageBinding());
|
||||
texture_bindings_ = Array<ImageBinding>(max_bindings);
|
||||
texture_bindings_.fill(ImageBinding());
|
||||
texture_bindings_ = Array<TextureBinding>(max_bindings);
|
||||
texture_bindings_.fill(TextureBinding());
|
||||
uniform_buffer_bindings_ = Array<UniformBufferBinding>(max_bindings);
|
||||
uniform_buffer_bindings_.fill(UniformBufferBinding());
|
||||
}
|
||||
|
@ -34,29 +35,35 @@ void VKStateManager::apply_state()
|
|||
VKShader &shader = unwrap(*context.shader);
|
||||
VKPipeline &pipeline = shader.pipeline_get();
|
||||
pipeline.state_manager_get().set_state(state, mutable_state);
|
||||
|
||||
for (int binding : IndexRange(image_bindings_.size())) {
|
||||
if (image_bindings_[binding].texture == nullptr) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
void VKStateManager::apply_bindings()
|
||||
{
|
||||
VKContext &context = *VKContext::get();
|
||||
if (context.shader) {
|
||||
for (int binding : IndexRange(image_bindings_.size())) {
|
||||
if (image_bindings_[binding].texture) {
|
||||
image_bindings_[binding].texture->image_bind(binding);
|
||||
}
|
||||
|
||||
for (int binding : IndexRange(image_bindings_.size())) {
|
||||
if (texture_bindings_[binding].texture == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int binding : IndexRange(texture_bindings_.size())) {
|
||||
if (texture_bindings_[binding].texture) {
|
||||
texture_bindings_[binding].texture->bind(binding, sampler_);
|
||||
}
|
||||
else if (texture_bindings_[binding].vertex_buffer) {
|
||||
texture_bindings_[binding].vertex_buffer->bind(binding);
|
||||
}
|
||||
}
|
||||
|
||||
for (int binding : IndexRange(uniform_buffer_bindings_.size())) {
|
||||
if (uniform_buffer_bindings_[binding].buffer == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (uniform_buffer_bindings_[binding].buffer) {
|
||||
uniform_buffer_bindings_[binding].buffer->bind(
|
||||
binding, shader::ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VKStateManager::force_state()
|
||||
|
@ -81,12 +88,13 @@ void VKStateManager::texture_bind(Texture *tex, GPUSamplerState /*sampler*/, int
|
|||
{
|
||||
VKTexture *texture = unwrap(tex);
|
||||
texture_bindings_[unit].texture = texture;
|
||||
texture_bindings_[unit].vertex_buffer = nullptr;
|
||||
}
|
||||
|
||||
void VKStateManager::texture_unbind(Texture *tex)
|
||||
{
|
||||
VKTexture *texture = unwrap(tex);
|
||||
for (ImageBinding &binding : texture_bindings_) {
|
||||
for (TextureBinding &binding : texture_bindings_) {
|
||||
if (binding.texture == texture) {
|
||||
binding.texture = nullptr;
|
||||
}
|
||||
|
@ -95,11 +103,9 @@ void VKStateManager::texture_unbind(Texture *tex)
|
|||
|
||||
void VKStateManager::texture_unbind_all()
|
||||
{
|
||||
for (ImageBinding &binding : texture_bindings_) {
|
||||
if (binding.texture != nullptr) {
|
||||
for (TextureBinding &binding : texture_bindings_) {
|
||||
binding.texture = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VKStateManager::image_bind(Texture *tex, int binding)
|
||||
|
@ -120,11 +126,9 @@ void VKStateManager::image_unbind(Texture *tex)
|
|||
|
||||
void VKStateManager::image_unbind_all()
|
||||
{
|
||||
for (ImageBinding &binding : texture_bindings_) {
|
||||
if (binding.texture != nullptr) {
|
||||
for (TextureBinding &binding : texture_bindings_) {
|
||||
binding.texture = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VKStateManager::uniform_buffer_bind(VKUniformBuffer *uniform_buffer, int slot)
|
||||
|
@ -141,6 +145,22 @@ void VKStateManager::uniform_buffer_unbind(VKUniformBuffer *uniform_buffer)
|
|||
}
|
||||
}
|
||||
|
||||
void VKStateManager::texel_buffer_bind(VKVertexBuffer *vertex_buffer, int slot)
|
||||
{
|
||||
texture_bindings_[slot].vertex_buffer = vertex_buffer;
|
||||
texture_bindings_[slot].texture = nullptr;
|
||||
}
|
||||
|
||||
void VKStateManager::texel_buffer_unbind(VKVertexBuffer *vertex_buffer)
|
||||
{
|
||||
for (TextureBinding &binding : texture_bindings_) {
|
||||
if (binding.vertex_buffer == vertex_buffer) {
|
||||
binding.vertex_buffer = nullptr;
|
||||
binding.texture = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VKStateManager::texture_unpack_row_length_set(uint len)
|
||||
{
|
||||
texture_unpack_row_length_ = len;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
namespace blender::gpu {
|
||||
class VKTexture;
|
||||
class VKUniformBuffer;
|
||||
class VKVertexBuffer;
|
||||
|
||||
class VKStateManager : public StateManager {
|
||||
/* Dummy sampler for now.*/
|
||||
|
@ -23,6 +24,11 @@ class VKStateManager : public StateManager {
|
|||
|
||||
uint texture_unpack_row_length_ = 0;
|
||||
|
||||
struct TextureBinding {
|
||||
VKTexture *texture = nullptr;
|
||||
/* bufferTextures and samplers share the same namespace. */
|
||||
VKVertexBuffer *vertex_buffer = nullptr;
|
||||
};
|
||||
struct ImageBinding {
|
||||
VKTexture *texture = nullptr;
|
||||
};
|
||||
|
@ -30,7 +36,7 @@ class VKStateManager : public StateManager {
|
|||
VKUniformBuffer *buffer = nullptr;
|
||||
};
|
||||
Array<ImageBinding> image_bindings_;
|
||||
Array<ImageBinding> texture_bindings_;
|
||||
Array<TextureBinding> texture_bindings_;
|
||||
Array<UniformBufferBinding> uniform_buffer_bindings_;
|
||||
|
||||
public:
|
||||
|
@ -41,6 +47,9 @@ class VKStateManager : public StateManager {
|
|||
|
||||
void issue_barrier(eGPUBarrier barrier_bits) override;
|
||||
|
||||
/** Apply resources to the bindings of the active shader.*/
|
||||
void apply_bindings();
|
||||
|
||||
void texture_bind(Texture *tex, GPUSamplerState sampler, int unit) override;
|
||||
void texture_unbind(Texture *tex) override;
|
||||
void texture_unbind_all() override;
|
||||
|
@ -52,6 +61,9 @@ class VKStateManager : public StateManager {
|
|||
void uniform_buffer_bind(VKUniformBuffer *uniform_buffer, int slot);
|
||||
void uniform_buffer_unbind(VKUniformBuffer *uniform_buffer);
|
||||
|
||||
void texel_buffer_bind(VKVertexBuffer *vertex_buffer, int slot);
|
||||
void texel_buffer_unbind(VKVertexBuffer *vertex_buffer);
|
||||
|
||||
void texture_unpack_row_length_set(uint len) override;
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "vk_shader.hh"
|
||||
#include "vk_shader_interface.hh"
|
||||
#include "vk_state_manager.hh"
|
||||
#include "vk_vertex_buffer.hh"
|
||||
|
||||
#include "BLI_math_vector.hh"
|
||||
|
||||
|
@ -174,9 +175,29 @@ bool VKTexture::init_internal()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool VKTexture::init_internal(GPUVertBuf * /*vbo*/)
|
||||
bool VKTexture::init_internal(GPUVertBuf *vbo)
|
||||
{
|
||||
if (!allocate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VKVertexBuffer *vertex_buffer = unwrap(unwrap(vbo));
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageExtent.width = w_;
|
||||
region.imageExtent.height = 1;
|
||||
region.imageExtent.depth = 1;
|
||||
region.imageSubresource.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
|
||||
VKContext &context = *VKContext::get();
|
||||
layout_ensure(context, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||
command_buffer.copy(*this, vertex_buffer->buffer_, Span<VkBufferImageCopy>(®ion, 1));
|
||||
command_buffer.submit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VKTexture::init_internal(GPUTexture * /*src*/,
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "vk_data_conversion.hh"
|
||||
#include "vk_memory.hh"
|
||||
#include "vk_shader.hh"
|
||||
#include "vk_shader_interface.hh"
|
||||
#include "vk_state_manager.hh"
|
||||
#include "vk_vertex_buffer.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
@ -35,9 +37,44 @@ void VKVertexBuffer::bind_as_ssbo(uint binding)
|
|||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, *location);
|
||||
}
|
||||
|
||||
void VKVertexBuffer::bind_as_texture(uint /*binding*/)
|
||||
void VKVertexBuffer::bind_as_texture(uint binding)
|
||||
{
|
||||
NOT_YET_IMPLEMENTED
|
||||
VKContext &context = *VKContext::get();
|
||||
VKStateManager &state_manager = context.state_manager_get();
|
||||
state_manager.texel_buffer_bind(this, binding);
|
||||
should_unbind_ = true;
|
||||
}
|
||||
|
||||
void VKVertexBuffer::bind(uint binding)
|
||||
{
|
||||
VKContext &context = *VKContext::get();
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const std::optional<VKDescriptorSet::Location> location =
|
||||
shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::SAMPLER, binding);
|
||||
if (!location) {
|
||||
return;
|
||||
}
|
||||
|
||||
upload_data();
|
||||
|
||||
if (vk_buffer_view_ == VK_NULL_HANDLE) {
|
||||
VkBufferViewCreateInfo buffer_view_info = {};
|
||||
eGPUTextureFormat texture_format = to_texture_format(&format);
|
||||
|
||||
buffer_view_info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
|
||||
buffer_view_info.buffer = buffer_.vk_handle();
|
||||
buffer_view_info.format = to_vk_format(texture_format);
|
||||
buffer_view_info.range = buffer_.size_in_bytes();
|
||||
|
||||
VK_ALLOCATION_CALLBACKS;
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vkCreateBufferView(
|
||||
device.device_get(), &buffer_view_info, vk_allocation_callbacks, &vk_buffer_view_);
|
||||
}
|
||||
|
||||
shader->pipeline_get().descriptor_set_get().bind(*this, *location);
|
||||
}
|
||||
|
||||
void VKVertexBuffer::wrap_handle(uint64_t /*handle*/)
|
||||
|
@ -81,6 +118,18 @@ void VKVertexBuffer::resize_data()
|
|||
|
||||
void VKVertexBuffer::release_data()
|
||||
{
|
||||
if (should_unbind_) {
|
||||
VKContext &context = *VKContext::get();
|
||||
context.state_manager_get().texel_buffer_unbind(this);
|
||||
}
|
||||
|
||||
if (vk_buffer_view_ != VK_NULL_HANDLE) {
|
||||
VK_ALLOCATION_CALLBACKS;
|
||||
const VKDevice &device = VKBackend::get().device_get();
|
||||
vkDestroyBufferView(device.device_get(), vk_buffer_view_, vk_allocation_callbacks);
|
||||
vk_buffer_view_ = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(data);
|
||||
}
|
||||
|
||||
|
@ -105,6 +154,9 @@ void VKVertexBuffer::upload_data()
|
|||
if (!buffer_.is_allocated()) {
|
||||
allocate();
|
||||
}
|
||||
if (!ELEM(usage_, GPU_USAGE_STATIC, GPU_USAGE_STREAM, GPU_USAGE_DYNAMIC)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flag & GPU_VERTBUF_DATA_DIRTY) {
|
||||
void *data_to_upload = data;
|
||||
|
@ -133,8 +185,10 @@ void VKVertexBuffer::allocate()
|
|||
{
|
||||
buffer_.create(size_alloc_get(),
|
||||
usage_,
|
||||
static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
|
||||
static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT));
|
||||
debug::object_label(buffer_.vk_handle(), "VertexBuffer");
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,16 @@ namespace blender::gpu {
|
|||
|
||||
class VKVertexBuffer : public VertBuf {
|
||||
VKBuffer buffer_;
|
||||
bool should_unbind_ = false;
|
||||
/** When a vertex buffer is used as a UNIFORM_TEXEL_BUFFER the buffer requires a buffer view. */
|
||||
VkBufferView vk_buffer_view_ = VK_NULL_HANDLE;
|
||||
|
||||
public:
|
||||
~VKVertexBuffer();
|
||||
|
||||
void bind_as_ssbo(uint binding) override;
|
||||
void bind_as_texture(uint binding) override;
|
||||
void bind(uint binding);
|
||||
void wrap_handle(uint64_t handle) override;
|
||||
|
||||
void update_sub(uint start, uint len, const void *data) override;
|
||||
|
@ -32,6 +36,12 @@ class VKVertexBuffer : public VertBuf {
|
|||
return buffer_.vk_handle();
|
||||
}
|
||||
|
||||
VkBufferView vk_buffer_view_get() const
|
||||
{
|
||||
BLI_assert(vk_buffer_view_ != VK_NULL_HANDLE);
|
||||
return vk_buffer_view_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void acquire_data() override;
|
||||
void resize_data() override;
|
||||
|
@ -42,6 +52,9 @@ class VKVertexBuffer : public VertBuf {
|
|||
private:
|
||||
void allocate();
|
||||
void *convert() const;
|
||||
|
||||
/* VKTexture requires access to `buffer_` to convert a vertex buffer to a texture.*/
|
||||
friend class VKTexture;
|
||||
};
|
||||
|
||||
static inline VKVertexBuffer *unwrap(VertBuf *vertex_buffer)
|
||||
|
|
Loading…
Reference in New Issue
Remove unused const