@ -36,6 +36,13 @@ using Tegra::Engines::ShaderType;
namespace {
// C++20's using enum
constexpr auto eUniformBuffer = vk : : DescriptorType : : eUniformBuffer ;
constexpr auto eStorageBuffer = vk : : DescriptorType : : eStorageBuffer ;
constexpr auto eUniformTexelBuffer = vk : : DescriptorType : : eUniformTexelBuffer ;
constexpr auto eCombinedImageSampler = vk : : DescriptorType : : eCombinedImageSampler ;
constexpr auto eStorageImage = vk : : DescriptorType : : eStorageImage ;
constexpr VideoCommon : : Shader : : CompilerSettings compiler_settings {
VideoCommon : : Shader : : CompileDepth : : FullDecompile } ;
@ -119,23 +126,32 @@ ShaderType GetShaderType(Maxwell::ShaderProgram program) {
}
}
template < vk : : DescriptorType descriptor_type , class Container >
void AddBindings ( std : : vector < vk : : DescriptorSetLayoutBinding > & bindings , u32 & binding ,
vk : : ShaderStageFlags stage_flags , const Container & container ) {
const u32 num_entries = static_cast < u32 > ( std : : size ( container ) ) ;
for ( std : : size_t i = 0 ; i < num_entries ; + + i ) {
u32 count = 1 ;
if constexpr ( descriptor_type = = eCombinedImageSampler ) {
// Combined image samplers can be arrayed.
count = container [ i ] . Size ( ) ;
}
bindings . emplace_back ( binding + + , descriptor_type , count , stage_flags , nullptr ) ;
}
}
u32 FillDescriptorLayout ( const ShaderEntries & entries ,
std : : vector < vk : : DescriptorSetLayoutBinding > & bindings ,
Maxwell : : ShaderProgram program_type , u32 base_binding ) {
const ShaderType stage = GetStageFromProgram ( program_type ) ;
const vk : : ShaderStageFlags stage_flags = MaxwellToVK : : ShaderStage ( stage ) ;
const vk : : ShaderStageFlags flags = MaxwellToVK : : ShaderStage ( stage ) ;
u32 binding = base_binding ;
const auto AddBindings = [ & ] ( vk : : DescriptorType descriptor_type , std : : size_t num_entries ) {
for ( std : : size_t i = 0 ; i < num_entries ; + + i ) {
bindings . emplace_back ( binding + + , descriptor_type , 1 , stage_flags , nullptr ) ;
}
} ;
AddBindings ( vk : : DescriptorType : : eUniformBuffer , entries . const_buffers . size ( ) ) ;
AddBindings ( vk : : DescriptorType : : eStorageBuffer , entries . global_buffers . size ( ) ) ;
AddBindings ( vk : : DescriptorType : : eUniformTexelBuffer , entries . texel_buffers . size ( ) ) ;
AddBindings ( vk : : DescriptorType : : eCombinedImageSampler , entries . samplers . size ( ) ) ;
AddBindings ( vk : : DescriptorType : : eStorageImage , entries . images . size ( ) ) ;
AddBindings < eUniformBuffer > ( bindings , binding , flags , entries . const_buffers ) ;
AddBindings < eStorageBuffer > ( bindings , binding , flags , entries . global_buffers ) ;
AddBindings < eUniformTexelBuffer > ( bindings , binding , flags , entries . texel_buffers ) ;
AddBindings < eCombinedImageSampler > ( bindings , binding , flags , entries . samplers ) ;
AddBindings < eStorageImage > ( bindings , binding , flags , entries . images ) ;
return binding ;
}
@ -361,32 +377,45 @@ VKPipelineCache::DecompileShaders(const GraphicsPipelineCacheKey& key) {
return { std : : move ( program ) , std : : move ( bindings ) } ;
}
void FillDescriptorUpdateTemplateEntries (
const VKDevice & device , const ShaderEntries & entries , u32 & binding , u32 & offset ,
std : : vector < vk : : DescriptorUpdateTemplateEntry > & template_entries ) {
static constexpr auto entry_size = static_cast < u32 > ( sizeof ( DescriptorUpdateEntry ) ) ;
const auto AddEntry = [ & ] ( vk : : DescriptorType descriptor_type , std : : size_t count_ ) {
const u32 count = static_cast < u32 > ( count_ ) ;
if ( descriptor_type = = vk : : DescriptorType : : eUniformTexelBuffer & &
device . GetDriverID ( ) = = vk : : DriverIdKHR : : eNvidiaProprietary ) {
// Nvidia has a bug where updating multiple uniform texels at once causes the driver to
// crash.
for ( u32 i = 0 ; i < count ; + + i ) {
template_entries . emplace_back ( binding + i , 0 , 1 , descriptor_type ,
offset + i * entry_size , entry_size ) ;
}
} else if ( count ! = 0 ) {
template_entries . emplace_back ( binding , 0 , count , descriptor_type , offset , entry_size ) ;
template < vk : : DescriptorType descriptor_type , class Container >
void AddEntry ( std : : vector < vk : : DescriptorUpdateTemplateEntry > & template_entries , u32 & binding ,
u32 & offset , const Container & container ) {
static constexpr u32 entry_size = static_cast < u32 > ( sizeof ( DescriptorUpdateEntry ) ) ;
const u32 count = static_cast < u32 > ( std : : size ( container ) ) ;
if constexpr ( descriptor_type = = eCombinedImageSampler ) {
for ( u32 i = 0 ; i < count ; + + i ) {
const u32 num_samplers = container [ i ] . Size ( ) ;
template_entries . emplace_back ( binding , 0 , num_samplers , descriptor_type , offset ,
entry_size ) ;
+ + binding ;
offset + = num_samplers * entry_size ;
}
offset + = count * entry_size ;
binding + = count ;
} ;
return ;
}
AddEntry ( vk : : DescriptorType : : eUniformBuffer , entries . const_buffers . size ( ) ) ;
AddEntry ( vk : : DescriptorType : : eStorageBuffer , entries . global_buffers . size ( ) ) ;
AddEntry ( vk : : DescriptorType : : eUniformTexelBuffer , entries . texel_buffers . size ( ) ) ;
AddEntry ( vk : : DescriptorType : : eCombinedImageSampler , entries . samplers . size ( ) ) ;
AddEntry ( vk : : DescriptorType : : eStorageImage , entries . images . size ( ) ) ;
if constexpr ( descriptor_type = = eUniformTexelBuffer ) {
// Nvidia has a bug where updating multiple uniform texels at once causes the driver to
// crash.
for ( u32 i = 0 ; i < count ; + + i ) {
template_entries . emplace_back ( binding + i , 0 , 1 , descriptor_type ,
offset + i * entry_size , entry_size ) ;
}
} else if ( count > 0 ) {
template_entries . emplace_back ( binding , 0 , count , descriptor_type , offset , entry_size ) ;
}
offset + = count * entry_size ;
binding + = count ;
}
void FillDescriptorUpdateTemplateEntries (
const ShaderEntries & entries , u32 & binding , u32 & offset ,
std : : vector < vk : : DescriptorUpdateTemplateEntry > & template_entries ) {
AddEntry < eUniformBuffer > ( template_entries , offset , binding , entries . const_buffers ) ;
AddEntry < eStorageBuffer > ( template_entries , offset , binding , entries . global_buffers ) ;
AddEntry < eUniformTexelBuffer > ( template_entries , offset , binding , entries . texel_buffers ) ;
AddEntry < eCombinedImageSampler > ( template_entries , offset , binding , entries . samplers ) ;
AddEntry < eStorageImage > ( template_entries , offset , binding , entries . images ) ;
}
} // namespace Vulkan