diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index fb9d3dbbb2..f4d9de79d3 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -202,7 +202,8 @@ void EmitGetIndirectBranchVariable(EmitContext&) { } Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) { + if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8 && + ctx.profile.support_uniform_and_storage_buffer_8bit) { const Id load{GetCbuf(ctx, ctx.U8, &UniformDefinitions::U8, sizeof(u8), binding, offset, ctx.load_const_func_u8)}; return ctx.OpUConvert(ctx.U32[1], load); @@ -219,7 +220,8 @@ Id EmitGetCbufU8(EmitContext& ctx, const IR::Value& binding, const IR::Value& of } Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8) { + if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int8 && + ctx.profile.support_uniform_and_storage_buffer_8bit) { const Id load{GetCbuf(ctx, ctx.S8, &UniformDefinitions::S8, sizeof(s8), binding, offset, ctx.load_const_func_u8)}; return ctx.OpSConvert(ctx.U32[1], load); @@ -236,7 +238,8 @@ Id EmitGetCbufS8(EmitContext& ctx, const IR::Value& binding, const IR::Value& of } Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) { + if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16 && + ctx.profile.support_uniform_and_storage_buffer_16bit) { const Id load{GetCbuf(ctx, ctx.U16, &UniformDefinitions::U16, sizeof(u16), binding, offset, ctx.load_const_func_u16)}; return ctx.OpUConvert(ctx.U32[1], load); @@ -253,7 +256,8 @@ Id EmitGetCbufU16(EmitContext& ctx, const IR::Value& binding, const IR::Value& o } Id EmitGetCbufS16(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) { - if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16) { + if (ctx.profile.support_descriptor_aliasing && ctx.profile.support_int16 && + ctx.profile.support_uniform_and_storage_buffer_16bit) { const Id load{GetCbuf(ctx, ctx.S16, &UniformDefinitions::S16, sizeof(s16), binding, offset, ctx.load_const_func_u16)}; return ctx.OpSConvert(ctx.U32[1], load); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index c5c6b2655a..b1bed263a6 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -1134,7 +1134,7 @@ void EmitContext::DefineConstantBuffers(const Info& info, u32& binding) { } } if (True(types & IR::Type::U16)) { - if (profile.support_int16) { + if (profile.support_int16 && profile.support_uniform_and_storage_buffer_16bit) { DefineConstBuffers(*this, info, &UniformDefinitions::U16, binding, U16, 'u', sizeof(u16)); DefineConstBuffers(*this, info, &UniformDefinitions::S16, binding, S16, 's', @@ -1196,10 +1196,18 @@ void EmitContext::DefineConstantBufferIndirectFunctions(const Info& info) { IR::Type types{info.used_indirect_cbuf_types}; bool supports_aliasing = profile.support_descriptor_aliasing; if (supports_aliasing && True(types & IR::Type::U8)) { - load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); + if (profile.support_int8 && profile.support_uniform_and_storage_buffer_8bit) { + load_const_func_u8 = make_accessor(U8, &UniformDefinitions::U8); + } else { + types |= IR::Type::U32; + } } if (supports_aliasing && True(types & IR::Type::U16)) { - load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16); + if (profile.support_int16 && profile.support_uniform_and_storage_buffer_16bit) { + load_const_func_u16 = make_accessor(U16, &UniformDefinitions::U16); + } else { + types |= IR::Type::U32; + } } if (supports_aliasing && True(types & IR::Type::F32)) { load_const_func_f32 = make_accessor(F32[1], &UniformDefinitions::F32); diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 4e200d5120..e95778a0de 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -17,6 +17,7 @@ struct Profile { bool support_int8{}; bool support_uniform_and_storage_buffer_8bit{}; bool support_int16{}; + bool support_uniform_and_storage_buffer_16bit{}; bool support_int64{}; bool support_vertex_instance_id{}; bool support_float_controls{}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 74caf044cb..903b97db6a 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -386,6 +386,8 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, .support_uniform_and_storage_buffer_8bit = device.IsUniformAndStorageBuffer8BitAccessSupported(), .support_int16 = device.IsShaderInt16Supported(), + .support_uniform_and_storage_buffer_16bit = + device.IsUniformAndStorageBuffer16BitAccessSupported(), .support_int64 = device.IsShaderInt64Supported(), .support_vertex_instance_id = false, .support_float_controls = device.IsKhrShaderFloatControlsSupported(), diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 457cd3286e..5b6c3da57d 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -387,11 +387,16 @@ FN_MAX_LIMIT_LIST return features.shader_float16_int8.shaderInt8; } - /// Returns true if the device allows 8-bit integer members + /// Returns true if the device allows 8-bit integer members in uniform/storage buffers. bool IsUniformAndStorageBuffer8BitAccessSupported() const { return features.bit8_storage.uniformAndStorageBuffer8BitAccess; } + /// Returns true if the device allows 16-bit integer members in uniform/storage buffers. + bool IsUniformAndStorageBuffer16BitAccessSupported() const { + return features.bit16_storage.uniformAndStorageBuffer16BitAccess; + } + /// Returns true if the device supports binding multisample images as storage images. bool IsStorageImageMultisampleSupported() const { return features.features.shaderStorageImageMultisample;