Vulkan: Fix image bind space collision

EEVEE Eval light shader could still make a collision between
texture and image bind space making rendering glitch
when not using `--debug-gpu`. The problem was that the bind space
wasn't aware of the offset that the shader interface was using.

Pull Request: https://projects.blender.org/blender/blender/pulls/124140
This commit is contained in:
Jeroen Bakker
2024-07-04 10:41:43 +02:00
parent d51dee85f7
commit b6c078a28f
4 changed files with 20 additions and 15 deletions

View File

@@ -85,11 +85,22 @@ class VKBindableResource {
void unbind_from_all_contexts();
};
/**
* Offset when searching for bindings.
*
* When shaders combine images and samplers, the images have to be offset to find the correct
* shader input. Both textures and images are stored in the uniform list and their ID can be
* overlapping.
*/
static constexpr int BIND_SPACE_IMAGE_OFFSET = 512;
/**
* Blender binds resources at context level (VKStateManager). The bindings are organized in
* namespaces.
*/
template<shader::ShaderCreateInfo::Resource::BindType BindType> class VKBindSpace {
template<shader::ShaderCreateInfo::Resource::BindType BindType, int BindOffset = 0>
class VKBindSpace {
static constexpr int offset = BindOffset;
class ResourceBinding {
public:
int binding;
@@ -103,10 +114,11 @@ template<shader::ShaderCreateInfo::Resource::BindType BindType> class VKBindSpac
/**
* Register a binding to this namespace.
*/
void bind(int binding,
void bind(int binding_,
VKBindableResource &resource,
const GPUSamplerState sampler_state = GPUSamplerState::default_sampler())
{
int binding = binding_ >= offset ? binding_ : binding_ + offset;
for (ResourceBinding &bind : bindings_) {
if (bind.binding == binding) {
bind.resource = &resource;

View File

@@ -16,7 +16,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
{
static char PUSH_CONSTANTS_FALLBACK_NAME[] = "push_constants_fallback";
static size_t PUSH_CONSTANTS_FALLBACK_NAME_LEN = strlen(PUSH_CONSTANTS_FALLBACK_NAME);
static char SUBPASS_FALLBACK_NAME[] = "gpu_sybpass_img_0";
static char SUBPASS_FALLBACK_NAME[] = "gpu_subpass_img_0";
static size_t SUBPASS_FALLBACK_NAME_LEN = strlen(SUBPASS_FALLBACK_NAME);
using namespace blender::gpu::shader;
@@ -113,7 +113,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
}
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset);
input->location = input->binding = res.slot + image_offset;
input->location = input->binding = res.slot + BIND_SPACE_IMAGE_OFFSET;
input++;
}
}
@@ -395,7 +395,8 @@ const ShaderInput *VKShaderInterface::shader_input_get(
/* Not really nice, but the binding namespace between OpenGL and Vulkan don't match. To fix
* this we need to check if one of both cases return a binding.
*/
return texture_get((binding >= image_offset) ? binding : binding + image_offset);
return texture_get((binding >= BIND_SPACE_IMAGE_OFFSET) ? binding :
binding + BIND_SPACE_IMAGE_OFFSET);
case shader::ShaderCreateInfo::Resource::BindType::SAMPLER:
return texture_get(binding);
case shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER:

View File

@@ -34,15 +34,6 @@ class VKShaderInterface : public ShaderInterface {
shader::BuiltinBits shader_builtins_;
public:
/**
* Offset when searching for a shader input based on a binding number.
*
* When shaders combine images and samplers, the images have to be offset to find the correct
* shader input. Both textures and images are stored in the uniform list and their ID can be
* overlapping.
*/
static constexpr uint32_t image_offset = 512;
VKShaderInterface() = default;
void init(const shader::ShaderCreateInfo &info);

View File

@@ -28,7 +28,8 @@ class VKStateManager : public StateManager {
uint texture_unpack_row_length_ = 0;
VKBindSpace<shader::ShaderCreateInfo::Resource::BindType::SAMPLER> textures_;
VKBindSpace<shader::ShaderCreateInfo::Resource::BindType::IMAGE> images_;
VKBindSpace<shader::ShaderCreateInfo::Resource::BindType::IMAGE, BIND_SPACE_IMAGE_OFFSET>
images_;
VKBindSpace<shader::ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER> uniform_buffers_;
VKBindSpace<shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER> storage_buffers_;