Vulkan: Push constants #104880
|
@ -16,6 +16,8 @@
|
||||||
# include <vulkan/vulkan.h>
|
# include <vulkan/vulkan.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "vk_mem_alloc.h"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,8 +42,8 @@ class VKBuffer {
|
||||||
bool update(VKContext &context, const void *data);
|
bool update(VKContext &context, const void *data);
|
||||||
// TODO: add partial_update (update_sub)
|
// TODO: add partial_update (update_sub)
|
||||||
bool free(VKContext &context);
|
bool free(VKContext &context);
|
||||||
bool map(VKContext &context, void **r_mapped_memory)const;
|
bool map(VKContext &context, void **r_mapped_memory) const;
|
||||||
void unmap(VKContext &context)const ;
|
void unmap(VKContext &context) const;
|
||||||
|
|
||||||
int64_t size_in_bytes() const
|
int64_t size_in_bytes() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vk_command_buffer.hh"
|
#include "vk_command_buffer.hh"
|
||||||
|
#include "vk_buffer.hh"
|
||||||
#include "vk_context.hh"
|
#include "vk_context.hh"
|
||||||
#include "vk_memory.hh"
|
#include "vk_memory.hh"
|
||||||
|
#include "vk_texture.hh"
|
||||||
|
|
||||||
#include "BLI_assert.h"
|
#include "BLI_assert.h"
|
||||||
|
|
||||||
|
@ -68,6 +70,47 @@ void VKCommandBuffer::bind(const VKDescriptorSet &descriptor_set,
|
||||||
vk_command_buffer_, bind_point, vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, 0);
|
vk_command_buffer_, bind_point, vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VKCommandBuffer::copy(VKBuffer &dst_buffer,
|
||||||
|
VKTexture &src_texture,
|
||||||
|
Span<VkBufferImageCopy> regions)
|
||||||
|
{
|
||||||
|
vkCmdCopyImageToBuffer(vk_command_buffer_,
|
||||||
|
src_texture.vk_image_handle(),
|
||||||
|
VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
dst_buffer.vk_handle(),
|
||||||
|
regions.size(),
|
||||||
|
regions.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VKCommandBuffer::pipeline_barrier(VkPipelineStageFlags source_stages,
|
||||||
|
VkPipelineStageFlags destination_stages)
|
||||||
|
{
|
||||||
|
vkCmdPipelineBarrier(vk_command_buffer_,
|
||||||
|
source_stages,
|
||||||
|
destination_stages,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VKCommandBuffer::pipeline_barrier(Span<VkImageMemoryBarrier> image_memory_barriers)
|
||||||
|
{
|
||||||
|
vkCmdPipelineBarrier(vk_command_buffer_,
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
|
VK_DEPENDENCY_BY_REGION_BIT,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
image_memory_barriers.size(),
|
||||||
|
image_memory_barriers.data());
|
||||||
|
}
|
||||||
|
|
||||||
void VKCommandBuffer::dispatch(int groups_x_len, int groups_y_len, int groups_z_len)
|
void VKCommandBuffer::dispatch(int groups_x_len, int groups_y_len, int groups_z_len)
|
||||||
{
|
{
|
||||||
vkCmdDispatch(vk_command_buffer_, groups_x_len, groups_y_len, groups_z_len);
|
vkCmdDispatch(vk_command_buffer_, groups_x_len, groups_y_len, groups_z_len);
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "vk_pipeline.hh"
|
#include "vk_pipeline.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
class VKBuffer;
|
||||||
|
class VKTexture;
|
||||||
|
|
||||||
/** Command buffer to keep track of the life-time of a command buffer.*/
|
/** Command buffer to keep track of the life-time of a command buffer.*/
|
||||||
class VKCommandBuffer : NonCopyable, NonMovable {
|
class VKCommandBuffer : NonCopyable, NonMovable {
|
||||||
|
@ -37,6 +39,11 @@ class VKCommandBuffer : NonCopyable, NonMovable {
|
||||||
const VkPipelineLayout vk_pipeline_layout,
|
const VkPipelineLayout vk_pipeline_layout,
|
||||||
VkPipelineBindPoint bind_point);
|
VkPipelineBindPoint bind_point);
|
||||||
void dispatch(int groups_x_len, int groups_y_len, int groups_z_len);
|
void dispatch(int groups_x_len, int groups_y_len, int groups_z_len);
|
||||||
|
/* Copy the contents of a texture mip level to the dst buffer.*/
|
||||||
|
void copy(VKBuffer &dst_buffer, VKTexture &src_texture, Span<VkBufferImageCopy> regions);
|
||||||
|
void pipeline_barrier(VkPipelineStageFlags source_stages,
|
||||||
|
VkPipelineStageFlags destination_stages);
|
||||||
|
void pipeline_barrier(Span<VkImageMemoryBarrier> image_memory_barriers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop recording commands, encode + send the recordings to Vulkan, wait for the until the
|
* Stop recording commands, encode + send the recordings to Vulkan, wait for the until the
|
||||||
|
|
|
@ -79,10 +79,12 @@ void VKContext::end_frame()
|
||||||
|
|
||||||
void VKContext::flush()
|
void VKContext::flush()
|
||||||
{
|
{
|
||||||
|
command_buffer_.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKContext::finish()
|
void VKContext::finish()
|
||||||
{
|
{
|
||||||
|
command_buffer_.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKContext::memory_statistics_get(int * /*total_mem*/, int * /*free_mem*/)
|
void VKContext::memory_statistics_get(int * /*total_mem*/, int * /*free_mem*/)
|
||||||
|
|
|
@ -56,6 +56,9 @@ void VKDescriptorSet::bind_as_ssbo(VKIndexBuffer &buffer, int location)
|
||||||
|
|
||||||
void VKDescriptorSet::image_bind(VKTexture &texture, int location)
|
void VKDescriptorSet::image_bind(VKTexture &texture, int location)
|
||||||
{
|
{
|
||||||
|
Binding &binding = ensure_location(location);
|
||||||
|
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
|
binding.vk_image_view = texture.vk_image_view_handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
VKDescriptorSet::Binding &VKDescriptorSet::ensure_location(int location)
|
VKDescriptorSet::Binding &VKDescriptorSet::ensure_location(int location)
|
||||||
|
@ -66,9 +69,7 @@ VKDescriptorSet::Binding &VKDescriptorSet::ensure_location(int location)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Binding binding;
|
Binding binding = {};
|
||||||
binding.vk_buffer = VK_NULL_HANDLE;
|
|
||||||
binding.buffer_size = 0;
|
|
||||||
binding.location = location;
|
binding.location = location;
|
||||||
bindings_.append(binding);
|
bindings_.append(binding);
|
||||||
return bindings_.last();
|
return bindings_.last();
|
||||||
|
@ -78,7 +79,11 @@ void VKDescriptorSet::update(VkDevice vk_device)
|
||||||
{
|
{
|
||||||
Vector<VkDescriptorBufferInfo> buffer_infos;
|
Vector<VkDescriptorBufferInfo> buffer_infos;
|
||||||
Vector<VkWriteDescriptorSet> descriptor_writes;
|
Vector<VkWriteDescriptorSet> descriptor_writes;
|
||||||
|
|
||||||
for (const Binding &binding : bindings_) {
|
for (const Binding &binding : bindings_) {
|
||||||
|
if (!binding.is_buffer()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
VkDescriptorBufferInfo buffer_info = {};
|
VkDescriptorBufferInfo buffer_info = {};
|
||||||
buffer_info.buffer = binding.vk_buffer;
|
buffer_info.buffer = binding.vk_buffer;
|
||||||
buffer_info.range = binding.buffer_size;
|
buffer_info.range = binding.buffer_size;
|
||||||
|
@ -91,7 +96,26 @@ void VKDescriptorSet::update(VkDevice vk_device)
|
||||||
write_descriptor.descriptorCount = 1;
|
write_descriptor.descriptorCount = 1;
|
||||||
write_descriptor.descriptorType = binding.type;
|
write_descriptor.descriptorType = binding.type;
|
||||||
write_descriptor.pBufferInfo = &buffer_infos.last();
|
write_descriptor.pBufferInfo = &buffer_infos.last();
|
||||||
|
descriptor_writes.append(write_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<VkDescriptorImageInfo> image_infos;
|
||||||
|
for (const Binding &binding : bindings_) {
|
||||||
|
if (!binding.is_image()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VkDescriptorImageInfo image_info = {};
|
||||||
|
image_info.imageView = binding.vk_image_view;
|
||||||
|
image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
image_infos.append(image_info);
|
||||||
|
|
||||||
|
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.pImageInfo = &image_infos.last();
|
||||||
descriptor_writes.append(write_descriptor);
|
descriptor_writes.append(write_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,23 @@ class VKTexture;
|
||||||
|
|
||||||
class VKDescriptorSet : NonCopyable {
|
class VKDescriptorSet : NonCopyable {
|
||||||
struct Binding {
|
struct Binding {
|
||||||
int location;
|
int location = -1;
|
||||||
VkDescriptorType type;
|
VkDescriptorType type;
|
||||||
|
|
||||||
VkBuffer vk_buffer = VK_NULL_HANDLE;
|
VkBuffer vk_buffer = VK_NULL_HANDLE;
|
||||||
VkDeviceSize buffer_size;
|
VkDeviceSize buffer_size = 0;
|
||||||
|
|
||||||
|
VkImageView vk_image_view = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
bool is_buffer() const
|
||||||
|
{
|
||||||
|
return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_image() const
|
||||||
|
{
|
||||||
|
return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorPool vk_descriptor_pool_ = VK_NULL_HANDLE;
|
VkDescriptorPool vk_descriptor_pool_ = VK_NULL_HANDLE;
|
||||||
|
|
|
@ -19,6 +19,11 @@ void VKStateManager::force_state()
|
||||||
|
|
||||||
void VKStateManager::issue_barrier(eGPUBarrier /*barrier_bits*/)
|
void VKStateManager::issue_barrier(eGPUBarrier /*barrier_bits*/)
|
||||||
{
|
{
|
||||||
|
VKContext &context = *VKContext::get();
|
||||||
|
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||||
|
/* TODO: Pipeline barriers should be added. We might be able to extract it from
|
||||||
|
* the actual pipeline, later on, but for now we submit the work as barrier. */
|
||||||
|
command_buffer.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKStateManager::texture_bind(Texture * /*tex*/, eGPUSamplerState /*sampler*/, int /*unit*/)
|
void VKStateManager::texture_bind(Texture * /*tex*/, eGPUSamplerState /*sampler*/, int /*unit*/)
|
||||||
|
|
|
@ -7,15 +7,81 @@
|
||||||
|
|
||||||
#include "vk_texture.hh"
|
#include "vk_texture.hh"
|
||||||
|
|
||||||
|
#include "vk_buffer.hh"
|
||||||
#include "vk_context.hh"
|
#include "vk_context.hh"
|
||||||
|
#include "vk_memory.hh"
|
||||||
#include "vk_shader.hh"
|
#include "vk_shader.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
|
static VkImageAspectFlagBits to_vk_image_aspect_flag_bits(const eGPUTextureFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case GPU_RGBA32F:
|
||||||
|
case GPU_RGBA8UI:
|
||||||
|
case GPU_RGBA8I:
|
||||||
|
case GPU_RGBA8:
|
||||||
|
case GPU_RGBA32UI:
|
||||||
|
case GPU_RGBA32I:
|
||||||
|
case GPU_RGBA16UI:
|
||||||
|
case GPU_RGBA16I:
|
||||||
|
case GPU_RGBA16F:
|
||||||
|
case GPU_RGBA16:
|
||||||
|
case GPU_RG8UI:
|
||||||
|
case GPU_RG8I:
|
||||||
|
case GPU_RG8:
|
||||||
|
case GPU_RG32UI:
|
||||||
|
case GPU_RG32I:
|
||||||
|
case GPU_RG32F:
|
||||||
|
case GPU_RG16UI:
|
||||||
|
case GPU_RG16I:
|
||||||
|
case GPU_RG16F:
|
||||||
|
case GPU_RG16:
|
||||||
|
case GPU_R8UI:
|
||||||
|
case GPU_R8I:
|
||||||
|
case GPU_R8:
|
||||||
|
case GPU_R32UI:
|
||||||
|
case GPU_R32I:
|
||||||
|
case GPU_R32F:
|
||||||
|
case GPU_R16UI:
|
||||||
|
case GPU_R16I:
|
||||||
|
case GPU_R16F:
|
||||||
|
case GPU_R16:
|
||||||
|
case GPU_RGB10_A2:
|
||||||
|
case GPU_R11F_G11F_B10F:
|
||||||
|
case GPU_SRGB8_A8:
|
||||||
|
case GPU_RGB16F:
|
||||||
|
case GPU_SRGB8_A8_DXT1:
|
||||||
|
case GPU_SRGB8_A8_DXT3:
|
||||||
|
case GPU_SRGB8_A8_DXT5:
|
||||||
|
case GPU_RGBA8_DXT1:
|
||||||
|
case GPU_RGBA8_DXT3:
|
||||||
|
case GPU_RGBA8_DXT5:
|
||||||
|
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
|
||||||
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
|
case GPU_DEPTH24_STENCIL8:
|
||||||
|
return static_cast<VkImageAspectFlagBits>(VK_IMAGE_ASPECT_DEPTH_BIT |
|
||||||
|
VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||||
|
|
||||||
|
case GPU_DEPTH_COMPONENT24:
|
||||||
|
case GPU_DEPTH_COMPONENT16:
|
||||||
|
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
|
||||||
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
|
/* Not supported by Vulkan*/
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
return static_cast<VkImageAspectFlagBits>(0);
|
||||||
|
}
|
||||||
|
|
||||||
VKTexture::~VKTexture()
|
VKTexture::~VKTexture()
|
||||||
{
|
{
|
||||||
|
VK_ALLOCATION_CALLBACKS
|
||||||
|
|
||||||
VKContext &context = *VKContext::get();
|
VKContext &context = *VKContext::get();
|
||||||
vmaDestroyImage(context.mem_allocator_get(), vk_image_, allocation_);
|
vmaDestroyImage(context.mem_allocator_get(), vk_image_, allocation_);
|
||||||
|
vkDestroyImageView(context.device_get(), vk_image_view_, vk_allocation_callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::generate_mipmap()
|
void VKTexture::generate_mipmap()
|
||||||
|
@ -42,9 +108,49 @@ void VKTexture::mip_range_set(int /*min*/, int /*max*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void *VKTexture::read(int /*mip*/, eGPUDataFormat /*format*/)
|
void *VKTexture::read(int mip, eGPUDataFormat format)
|
||||||
{
|
{
|
||||||
return nullptr;
|
/* Vulkan images cannot be directly mapped to host memory and requires a staging buffer.*/
|
||||||
|
VKContext &context = *VKContext::get();
|
||||||
|
VKBuffer staging_buffer;
|
||||||
|
|
||||||
|
/* NOTE: mip_size_get() won't override any dimension that is equal to 0. */
|
||||||
|
int extent[3] = {1, 1, 1};
|
||||||
|
mip_size_get(mip, extent);
|
||||||
|
size_t sample_len = extent[0] * extent[1] * extent[2];
|
||||||
|
/* NOTE: to_bytesize returns number of bits. */
|
||||||
|
size_t device_memory_size = sample_len * to_component_len(format_) * to_bytesize(format_) / 8;
|
||||||
|
/* NOTE: to_bytesize returns number of bytes here. */
|
||||||
|
size_t host_memory_size = sample_len * to_bytesize(format_, format);
|
||||||
|
|
||||||
|
staging_buffer.create(
|
||||||
|
context, device_memory_size, GPU_USAGE_DEVICE_ONLY, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
|
||||||
|
|
||||||
|
VkBufferImageCopy region = {};
|
||||||
|
region.imageExtent.width = extent[0];
|
||||||
|
region.imageExtent.height = extent[1];
|
||||||
|
region.imageExtent.depth = extent[2];
|
||||||
|
region.imageSubresource.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||||
|
region.imageSubresource.mipLevel = mip;
|
||||||
|
region.imageSubresource.layerCount = 1;
|
||||||
|
|
||||||
|
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||||
|
command_buffer.copy(staging_buffer, *this, Span<VkBufferImageCopy>(®ion, 1));
|
||||||
|
command_buffer.submit();
|
||||||
|
|
||||||
|
void *mapped_data;
|
||||||
|
staging_buffer.map(context, &mapped_data);
|
||||||
|
|
||||||
|
void *data = MEM_mallocN(host_memory_size, __func__);
|
||||||
|
|
||||||
|
/* TODO: add conversion when data format is different.*/
|
||||||
|
BLI_assert_msg(device_memory_size == host_memory_size,
|
||||||
|
"Memory data conversions not implemented yet");
|
||||||
|
|
||||||
|
memcpy(data, mapped_data, host_memory_size);
|
||||||
|
staging_buffer.unmap(context);
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::update_sub(int /*mip*/,
|
void VKTexture::update_sub(int /*mip*/,
|
||||||
|
@ -103,12 +209,11 @@ static VkFormat to_vk_format(const eGPUTextureFormat format)
|
||||||
case GPU_R16F:
|
case GPU_R16F:
|
||||||
case GPU_R16:
|
case GPU_R16:
|
||||||
|
|
||||||
/*
|
|
||||||
case GPU_RGB10_A2:
|
case GPU_RGB10_A2:
|
||||||
case GPU_R11F_G11F_B10F:
|
case GPU_R11F_G11F_B10F:
|
||||||
case GPU_DEPTH32F_STENCIL8:
|
case GPU_DEPTH32F_STENCIL8:
|
||||||
case GPU_DEPTH24_STENCIL8:
|
case GPU_DEPTH24_STENCIL8:
|
||||||
case GPU_SRGB8_A8:*/
|
case GPU_SRGB8_A8:
|
||||||
|
|
||||||
/* Texture only format */
|
/* Texture only format */
|
||||||
case GPU_RGB16F:
|
case GPU_RGB16F:
|
||||||
|
@ -125,7 +230,6 @@ static VkFormat to_vk_format(const eGPUTextureFormat format)
|
||||||
case GPU_DEPTH_COMPONENT32F:
|
case GPU_DEPTH_COMPONENT32F:
|
||||||
case GPU_DEPTH_COMPONENT24:
|
case GPU_DEPTH_COMPONENT24:
|
||||||
case GPU_DEPTH_COMPONENT16:
|
case GPU_DEPTH_COMPONENT16:
|
||||||
default:
|
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
}
|
}
|
||||||
return VK_FORMAT_UNDEFINED;
|
return VK_FORMAT_UNDEFINED;
|
||||||
|
@ -152,23 +256,66 @@ bool VKTexture::is_allocated()
|
||||||
return vk_image_ != VK_NULL_HANDLE && allocation_ != VK_NULL_HANDLE;
|
return vk_image_ != VK_NULL_HANDLE && allocation_ != VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VkImageViewType to_vk_image_view_type(const eGPUTextureType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case GPU_TEXTURE_1D:
|
||||||
|
case GPU_TEXTURE_BUFFER:
|
||||||
|
return VK_IMAGE_VIEW_TYPE_1D;
|
||||||
|
case GPU_TEXTURE_2D:
|
||||||
|
return VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
case GPU_TEXTURE_3D:
|
||||||
|
return VK_IMAGE_VIEW_TYPE_3D;
|
||||||
|
case GPU_TEXTURE_CUBE:
|
||||||
|
return VK_IMAGE_VIEW_TYPE_CUBE;
|
||||||
|
case GPU_TEXTURE_1D_ARRAY:
|
||||||
|
return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
|
||||||
|
case GPU_TEXTURE_2D_ARRAY:
|
||||||
|
return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||||
|
case GPU_TEXTURE_CUBE_ARRAY:
|
||||||
|
return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
|
||||||
|
|
||||||
|
case GPU_TEXTURE_ARRAY:
|
||||||
|
/* GPU_TEXTURE_ARRAY should always be used together with 1D, 2D, or CUBE*/
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VK_IMAGE_VIEW_TYPE_1D;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VkComponentMapping to_vk_component_mapping(const eGPUTextureFormat /*format*/)
|
||||||
|
{
|
||||||
|
/* TODO: this should map to OpenGL defaults based on the eGPUTextureFormat*/
|
||||||
|
VkComponentMapping component_mapping;
|
||||||
|
component_mapping.r = VK_COMPONENT_SWIZZLE_R;
|
||||||
|
component_mapping.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
|
component_mapping.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
|
component_mapping.a = VK_COMPONENT_SWIZZLE_A;
|
||||||
|
return component_mapping;
|
||||||
|
}
|
||||||
|
|
||||||
bool VKTexture::allocate()
|
bool VKTexture::allocate()
|
||||||
{
|
{
|
||||||
BLI_assert(!is_allocated());
|
BLI_assert(!is_allocated());
|
||||||
|
|
||||||
VKContext &context = *VKContext::get();
|
VKContext &context = *VKContext::get();
|
||||||
VkImageCreateInfo imgCreateInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
VkImageCreateInfo image_info = {};
|
||||||
imgCreateInfo.imageType = VK_IMAGE_TYPE_1D;
|
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
imgCreateInfo.extent.width = width_get();
|
image_info.imageType = VK_IMAGE_TYPE_1D;
|
||||||
imgCreateInfo.extent.height = 1;
|
image_info.extent.width = width_get();
|
||||||
imgCreateInfo.extent.depth = 1;
|
image_info.extent.height = 1;
|
||||||
imgCreateInfo.mipLevels = 1;
|
image_info.extent.depth = 1;
|
||||||
imgCreateInfo.arrayLayers = 1;
|
image_info.mipLevels = 1;
|
||||||
imgCreateInfo.format = to_vk_format(format_);
|
image_info.arrayLayers = 1;
|
||||||
imgCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
|
image_info.format = to_vk_format(format_);
|
||||||
imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
image_info.tiling = VK_IMAGE_TILING_LINEAR;
|
||||||
imgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
|
/* TODO: PREINITIALIZED should be for device only textures. Others should use
|
||||||
imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
* VK_IMAGE_LAYOUT_UNDEFINED and upload its content.*/
|
||||||
|
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
|
VK_IMAGE_USAGE_STORAGE_BIT;
|
||||||
|
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||||
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
||||||
|
@ -177,7 +324,7 @@ bool VKTexture::allocate()
|
||||||
allocCreateInfo.priority = 1.0f;
|
allocCreateInfo.priority = 1.0f;
|
||||||
|
|
||||||
VkResult result = vmaCreateImage(context.mem_allocator_get(),
|
VkResult result = vmaCreateImage(context.mem_allocator_get(),
|
||||||
&imgCreateInfo,
|
&image_info,
|
||||||
&allocCreateInfo,
|
&allocCreateInfo,
|
||||||
&vk_image_,
|
&vk_image_,
|
||||||
&allocation_,
|
&allocation_,
|
||||||
|
@ -185,7 +332,32 @@ bool VKTexture::allocate()
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
/* Promote image to the correct layout.*/
|
||||||
|
VkImageMemoryBarrier barrier{};
|
||||||
|
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
barrier.image = vk_image_;
|
||||||
|
barrier.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||||
|
barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||||
|
barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||||
|
context.command_buffer_get().pipeline_barrier(Span<VkImageMemoryBarrier>(&barrier, 1));
|
||||||
|
|
||||||
|
VK_ALLOCATION_CALLBACKS
|
||||||
|
VkImageViewCreateInfo image_view_info = {};
|
||||||
|
image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
image_view_info.image = vk_image_;
|
||||||
|
image_view_info.viewType = to_vk_image_view_type(type_);
|
||||||
|
image_view_info.format = to_vk_format(format_);
|
||||||
|
image_view_info.components = to_vk_component_mapping(format_);
|
||||||
|
image_view_info.subresourceRange.aspectMask = to_vk_image_aspect_flag_bits(format_);
|
||||||
|
image_view_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||||
|
image_view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||||
|
|
||||||
|
result = vkCreateImageView(
|
||||||
|
context.device_get(), &image_view_info, vk_allocation_callbacks, &vk_image_view_);
|
||||||
|
return result == VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKTexture::image_bind(int location)
|
void VKTexture::image_bind(int location)
|
||||||
|
|
|
@ -10,10 +10,13 @@
|
||||||
#include "gpu_texture_private.hh"
|
#include "gpu_texture_private.hh"
|
||||||
#include "vk_context.hh"
|
#include "vk_context.hh"
|
||||||
|
|
||||||
|
#include "vk_mem_alloc.h"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
class VKTexture : public Texture {
|
class VKTexture : public Texture {
|
||||||
VkImage vk_image_ = VK_NULL_HANDLE;
|
VkImage vk_image_ = VK_NULL_HANDLE;
|
||||||
|
VkImageView vk_image_view_ = VK_NULL_HANDLE;
|
||||||
VmaAllocation allocation_ = VK_NULL_HANDLE;
|
VmaAllocation allocation_ = VK_NULL_HANDLE;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -40,6 +43,14 @@ class VKTexture : public Texture {
|
||||||
uint gl_bindcode_get() const override;
|
uint gl_bindcode_get() const override;
|
||||||
|
|
||||||
void image_bind(int location);
|
void image_bind(int location);
|
||||||
|
VkImage vk_image_handle() const
|
||||||
|
{
|
||||||
|
return vk_image_;
|
||||||
|
}
|
||||||
|
VkImageView vk_image_view_handle() const
|
||||||
|
{
|
||||||
|
return vk_image_view_;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool init_internal() override;
|
bool init_internal() override;
|
||||||
|
@ -54,6 +65,8 @@ class VKTexture : public Texture {
|
||||||
* on the device.
|
* on the device.
|
||||||
*/
|
*/
|
||||||
bool allocate();
|
bool allocate();
|
||||||
|
|
||||||
|
VkImageViewType vk_image_view_type() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline VKTexture *unwrap(Texture *tex)
|
static inline VKTexture *unwrap(Texture *tex)
|
||||||
|
|
Loading…
Reference in New Issue