2019-08-03 18:54:02 +03:00
/*
2021-01-15 02:53:49 +03:00
* Copyright 2011 - 2021 Branimir Karadzic . All rights reserved .
2019-08-03 18:54:02 +03:00
* License : https : //github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
# include "shaderc.h"
BX_PRAGMA_DIAGNOSTIC_PUSH ( )
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC ( 4100 ) // error C4100: 'inclusionDepth' : unreferenced formal parameter
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC ( 4265 ) // error C4265: 'spv::spirvbin_t': class has virtual functions, but destructor is not virtual
2020-06-21 01:14:54 +03:00
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC ( " -Wattributes " ) // warning: attribute ignored
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC ( " -Wdeprecated-declarations " ) // warning: ‘ MSLVertexAttr’ is deprecated
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC ( " -Wtype-limits " ) // warning: comparison of unsigned expression in ‘ < 0’ is always false
2019-08-03 18:54:02 +03:00
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC ( " -Wshadow " ) // warning: declaration of 'userData' shadows a member of 'glslang::TShader::Includer::IncludeResult'
# define ENABLE_OPT 1
# include <ShaderLang.h>
# include <ResourceLimits.h>
# include <SPIRV/SPVRemapper.h>
# include <SPIRV/GlslangToSpv.h>
# define SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
# include <spirv_msl.hpp>
# include <spirv_reflect.hpp>
# include <spirv-tools/optimizer.hpp>
BX_PRAGMA_DIAGNOSTIC_POP ( )
namespace bgfx
{
struct TinyStlAllocator
{
static void * static_allocate ( size_t _bytes ) ;
static void static_deallocate ( void * _ptr , size_t /*_bytes*/ ) ;
} ;
} // namespace bgfx
# define TINYSTL_ALLOCATOR bgfx::TinyStlAllocator
# include <tinystl/allocator.h>
# include <tinystl/string.h>
# include <tinystl/unordered_map.h>
# include <tinystl/vector.h>
namespace stl = tinystl ;
2021-04-21 17:45:03 +03:00
# include "../../src/shader.h"
2019-08-03 18:54:02 +03:00
namespace bgfx { namespace metal
{
const TBuiltInResource resourceLimits =
{
32 , // MaxLights
6 , // MaxClipPlanes
32 , // MaxTextureUnits
32 , // MaxTextureCoords
64 , // MaxVertexAttribs
4096 , // MaxVertexUniformComponents
64 , // MaxVaryingFloats
32 , // MaxVertexTextureImageUnits
80 , // MaxCombinedTextureImageUnits
32 , // MaxTextureImageUnits
4096 , // MaxFragmentUniformComponents
32 , // MaxDrawBuffers
128 , // MaxVertexUniformVectors
8 , // MaxVaryingVectors
16 , // MaxFragmentUniformVectors
16 , // MaxVertexOutputVectors
15 , // MaxFragmentInputVectors
- 8 , // MinProgramTexelOffset
7 , // MaxProgramTexelOffset
8 , // MaxClipDistances
65535 , // MaxComputeWorkGroupCountX
65535 , // MaxComputeWorkGroupCountY
65535 , // MaxComputeWorkGroupCountZ
1024 , // MaxComputeWorkGroupSizeX
1024 , // MaxComputeWorkGroupSizeY
64 , // MaxComputeWorkGroupSizeZ
1024 , // MaxComputeUniformComponents
16 , // MaxComputeTextureImageUnits
8 , // MaxComputeImageUniforms
8 , // MaxComputeAtomicCounters
1 , // MaxComputeAtomicCounterBuffers
60 , // MaxVaryingComponents
64 , // MaxVertexOutputComponents
64 , // MaxGeometryInputComponents
128 , // MaxGeometryOutputComponents
128 , // MaxFragmentInputComponents
8 , // MaxImageUnits
8 , // MaxCombinedImageUnitsAndFragmentOutputs
8 , // MaxCombinedShaderOutputResources
0 , // MaxImageSamples
0 , // MaxVertexImageUniforms
0 , // MaxTessControlImageUniforms
0 , // MaxTessEvaluationImageUniforms
0 , // MaxGeometryImageUniforms
8 , // MaxFragmentImageUniforms
8 , // MaxCombinedImageUniforms
16 , // MaxGeometryTextureImageUnits
256 , // MaxGeometryOutputVertices
1024 , // MaxGeometryTotalOutputComponents
1024 , // MaxGeometryUniformComponents
64 , // MaxGeometryVaryingComponents
128 , // MaxTessControlInputComponents
128 , // MaxTessControlOutputComponents
16 , // MaxTessControlTextureImageUnits
1024 , // MaxTessControlUniformComponents
4096 , // MaxTessControlTotalOutputComponents
128 , // MaxTessEvaluationInputComponents
128 , // MaxTessEvaluationOutputComponents
16 , // MaxTessEvaluationTextureImageUnits
1024 , // MaxTessEvaluationUniformComponents
120 , // MaxTessPatchComponents
32 , // MaxPatchVertices
64 , // MaxTessGenLevel
16 , // MaxViewports
0 , // MaxVertexAtomicCounters
0 , // MaxTessControlAtomicCounters
0 , // MaxTessEvaluationAtomicCounters
0 , // MaxGeometryAtomicCounters
8 , // MaxFragmentAtomicCounters
8 , // MaxCombinedAtomicCounters
1 , // MaxAtomicCounterBindings
0 , // MaxVertexAtomicCounterBuffers
0 , // MaxTessControlAtomicCounterBuffers
0 , // MaxTessEvaluationAtomicCounterBuffers
0 , // MaxGeometryAtomicCounterBuffers
1 , // MaxFragmentAtomicCounterBuffers
1 , // MaxCombinedAtomicCounterBuffers
16384 , // MaxAtomicCounterBufferSize
4 , // MaxTransformFeedbackBuffers
64 , // MaxTransformFeedbackInterleavedComponents
8 , // MaxCullDistances
8 , // MaxCombinedClipAndCullDistances
4 , // MaxSamples
2020-05-05 07:14:04 +03:00
0 , // maxMeshOutputVerticesNV
0 , // maxMeshOutputPrimitivesNV
0 , // maxMeshWorkGroupSizeX_NV
0 , // maxMeshWorkGroupSizeY_NV
0 , // maxMeshWorkGroupSizeZ_NV
0 , // maxTaskWorkGroupSizeX_NV
0 , // maxTaskWorkGroupSizeY_NV
0 , // maxTaskWorkGroupSizeZ_NV
2019-08-03 18:54:02 +03:00
0 , // maxMeshViewCountNV
2020-05-05 07:14:04 +03:00
0 , // maxDualSourceDrawBuffersEXT
2019-08-03 18:54:02 +03:00
{ // limits
true , // nonInductiveForLoops
true , // whileLoops
true , // doWhileLoops
true , // generalUniformIndexing
true , // generalAttributeMatrixVectorIndexing
true , // generalVaryingIndexing
true , // generalSamplerIndexing
true , // generalVariableIndexing
true , // generalConstantMatrixVectorIndexing
} ,
} ;
static EShLanguage getLang ( char _p )
{
switch ( _p )
{
case ' c ' : return EShLangCompute ;
case ' f ' : return EShLangFragment ;
case ' v ' : return EShLangVertex ;
default : return EShLangCount ;
}
}
static const char * s_attribName [ ] =
{
" a_position " ,
" a_normal " ,
" a_tangent " ,
" a_bitangent " ,
" a_color0 " ,
" a_color1 " ,
" a_color2 " ,
" a_color3 " ,
" a_indices " ,
" a_weight " ,
" a_texcoord0 " ,
" a_texcoord1 " ,
" a_texcoord2 " ,
" a_texcoord3 " ,
" a_texcoord4 " ,
" a_texcoord5 " ,
" a_texcoord6 " ,
" a_texcoord7 " ,
} ;
BX_STATIC_ASSERT ( bgfx : : Attrib : : Count = = BX_COUNTOF ( s_attribName ) ) ;
bgfx : : Attrib : : Enum toAttribEnum ( const bx : : StringView & _name )
{
for ( uint8_t ii = 0 ; ii < Attrib : : Count ; + + ii )
{
if ( 0 = = bx : : strCmp ( s_attribName [ ii ] , _name ) )
{
return bgfx : : Attrib : : Enum ( ii ) ;
}
}
return bgfx : : Attrib : : Count ;
}
2019-10-05 06:03:27 +03:00
static const char * s_samplerTypes [ ] =
{
" BgfxSampler2D " ,
" BgfxISampler2D " ,
" BgfxUSampler2D " ,
" BgfxSampler2DArray " ,
" BgfxSampler2DShadow " ,
" BgfxSampler2DArrayShadow " ,
" BgfxSampler3D " ,
" BgfxISampler3D " ,
" BgfxUSampler3D " ,
" BgfxSamplerCube " ,
" BgfxSamplerCubeShadow " ,
" BgfxSampler2DMS " ,
} ;
2019-08-03 18:54:02 +03:00
static uint16_t writeUniformArray ( bx : : WriterI * _writer , const UniformArray & uniforms , bool isFragmentShader )
{
uint16_t size = 0 ;
2021-10-26 05:26:38 +03:00
bx : : ErrorAssert err ;
2021-10-26 04:59:32 +03:00
2020-06-21 01:14:54 +03:00
uint16_t count = static_cast < uint16_t > ( uniforms . size ( ) ) ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , count , & err ) ;
2019-08-03 18:54:02 +03:00
2020-06-19 07:20:01 +03:00
uint32_t fragmentBit = isFragmentShader ? kUniformFragmentBit : 0 ;
2019-08-03 18:54:02 +03:00
for ( uint16_t ii = 0 ; ii < count ; + + ii )
{
const Uniform & un = uniforms [ ii ] ;
size + = un . regCount * 16 ;
uint8_t nameSize = ( uint8_t ) un . name . size ( ) ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , nameSize , & err ) ;
bx : : write ( _writer , un . name . c_str ( ) , nameSize , & err ) ;
bx : : write ( _writer , uint8_t ( un . type | fragmentBit ) , & err ) ;
bx : : write ( _writer , un . num , & err ) ;
bx : : write ( _writer , un . regIndex , & err ) ;
bx : : write ( _writer , un . regCount , & err ) ;
bx : : write ( _writer , un . texComponent , & err ) ;
bx : : write ( _writer , un . texDimension , & err ) ;
bx : : write ( _writer , un . texFormat , & err ) ;
2019-08-03 18:54:02 +03:00
BX_TRACE ( " %s, %s, %d, %d, %d "
, un . name . c_str ( )
, getUniformTypeName ( un . type )
, un . num
, un . regIndex
, un . regCount
) ;
}
return size ;
}
static bool compile ( const Options & _options , uint32_t _version , const std : : string & _code , bx : : WriterI * _writer , bool _firstPass )
{
BX_UNUSED ( _version ) ;
glslang : : InitializeProcess ( ) ;
EShLanguage stage = getLang ( _options . shaderType ) ;
if ( EShLangCount = = stage )
{
bx : : printf ( " Error: Unknown shader type '%c'. \n " , _options . shaderType ) ;
return false ;
}
2021-02-12 08:43:22 +03:00
glslang : : TProgram * program = new glslang : : TProgram ;
glslang : : TShader * shader = new glslang : : TShader ( stage ) ;
2019-08-03 18:54:02 +03:00
EShMessages messages = EShMessages ( 0
| EShMsgDefault
| EShMsgReadHlsl
| EShMsgVulkanRules
| EShMsgSpvRules
) ;
shader - > setEntryPoint ( " main " ) ;
2019-08-10 19:27:57 +03:00
shader - > setAutoMapBindings ( true ) ;
const int textureBindingOffset = 16 ;
shader - > setShiftBinding ( glslang : : EResTexture , textureBindingOffset ) ;
shader - > setShiftBinding ( glslang : : EResSampler , textureBindingOffset ) ;
shader - > setShiftBinding ( glslang : : EResImage , textureBindingOffset ) ;
2019-08-03 18:54:02 +03:00
const char * shaderStrings [ ] = { _code . c_str ( ) } ;
shader - > setStrings (
shaderStrings
, BX_COUNTOF ( shaderStrings )
) ;
bool compiled = shader - > parse ( & resourceLimits
, 110
, false
, messages
) ;
bool linked = false ;
bool validated = true ;
if ( ! compiled )
{
const char * log = shader - > getInfoLog ( ) ;
if ( NULL ! = log )
{
int32_t source = 0 ;
int32_t line = 0 ;
int32_t column = 0 ;
int32_t start = 0 ;
int32_t end = INT32_MAX ;
bx : : StringView err = bx : : strFind ( log , " ERROR: " ) ;
bool found = false ;
if ( ! err . isEmpty ( ) )
{
found = 2 = = sscanf ( err . getPtr ( ) , " ERROR: %u:%u: ' " , & source , & line ) ;
if ( found )
{
+ + line ;
}
}
if ( found )
{
start = bx : : uint32_imax ( 1 , line - 10 ) ;
end = start + 20 ;
}
printCode ( _code . c_str ( ) , line , start , end , column ) ;
bx : : printf ( " %s \n " , log ) ;
}
}
else
{
program - > addShader ( shader ) ;
linked = true
& & program - > link ( messages )
& & program - > mapIO ( )
;
if ( ! linked )
{
const char * log = program - > getInfoLog ( ) ;
if ( NULL ! = log )
{
bx : : printf ( " %s \n " , log ) ;
}
}
else
{
program - > buildReflection ( ) ;
if ( _firstPass )
{
// first time through, we just find unused uniforms and get rid of them
std : : string output ;
bx : : Error err ;
2020-06-21 01:14:54 +03:00
bx : : LineReader reader ( _code . c_str ( ) ) ;
while ( ! reader . isDone ( ) )
2019-08-03 18:54:02 +03:00
{
2020-06-21 01:14:54 +03:00
bx : : StringView strLine = reader . next ( ) ;
bx : : StringView str = strFind ( strLine , " uniform " ) ;
if ( ! str . isEmpty ( ) )
2019-08-03 18:54:02 +03:00
{
2020-08-17 07:08:01 +03:00
// If the line declares a uniform, merge all next
// lines until we encounter a semicolon.
bx : : StringView lineEnd = strFind ( strLine , " ; " ) ;
while ( lineEnd . isEmpty ( ) & & ! reader . isDone ( ) ) {
bx : : StringView nextLine = reader . next ( ) ;
strLine . set ( strLine . getPtr ( ) , nextLine . getTerm ( ) ) ;
lineEnd = strFind ( nextLine , " ; " ) ;
}
2020-06-21 01:14:54 +03:00
bool found = false ;
2019-08-03 18:54:02 +03:00
2020-06-21 01:14:54 +03:00
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( s_samplerTypes ) ; + + ii )
2019-08-03 18:54:02 +03:00
{
2020-06-21 01:14:54 +03:00
if ( ! bx : : findIdentifierMatch ( strLine , s_samplerTypes [ ii ] ) . isEmpty ( ) )
2019-08-03 18:54:02 +03:00
{
2020-06-21 01:14:54 +03:00
found = true ;
break ;
2019-08-03 18:54:02 +03:00
}
2020-06-21 01:14:54 +03:00
}
2019-10-05 19:52:04 +03:00
2020-06-21 01:14:54 +03:00
if ( ! found )
{
for ( int32_t ii = 0 , num = program - > getNumLiveUniformVariables ( ) ; ii < num ; + + ii )
2019-08-03 18:54:02 +03:00
{
2020-06-21 01:14:54 +03:00
// matching lines like: uniform u_name;
// we want to replace "uniform" with "static" so that it's no longer
// included in the uniform blob that the application must upload
// we can't just remove them, because unused functions might still reference
// them and cause a compile error when they're gone
if ( ! bx : : findIdentifierMatch ( strLine , program - > getUniformName ( ii ) ) . isEmpty ( ) )
2019-08-03 18:54:02 +03:00
{
2020-06-21 01:14:54 +03:00
found = true ;
break ;
2019-08-03 18:54:02 +03:00
}
}
}
2020-06-21 01:14:54 +03:00
if ( ! found )
{
output . append ( strLine . getPtr ( ) , str . getPtr ( ) ) ;
output + = " static " ;
output . append ( str . getTerm ( ) , strLine . getTerm ( ) ) ;
output + = " \n " ;
}
else
{
output . append ( strLine . getPtr ( ) , strLine . getTerm ( ) ) ;
output + = " \n " ;
}
}
else
{
output . append ( strLine . getPtr ( ) , strLine . getTerm ( ) ) ;
output + = " \n " ;
2019-08-03 18:54:02 +03:00
}
}
// recompile with the unused uniforms converted to statics
2021-02-12 08:43:22 +03:00
delete program ;
delete shader ;
2019-08-03 18:54:02 +03:00
return compile ( _options , _version , output . c_str ( ) , _writer , false ) ;
}
UniformArray uniforms ;
{
uint16_t count = ( uint16_t ) program - > getNumLiveUniformVariables ( ) ;
for ( uint16_t ii = 0 ; ii < count ; + + ii )
{
Uniform un ;
un . name = program - > getUniformName ( ii ) ;
un . num = uint8_t ( program - > getUniformArraySize ( ii ) ) ;
const uint32_t offset = program - > getUniformBufferOffset ( ii ) ;
un . regIndex = uint16_t ( offset ) ;
un . regCount = un . num ;
2020-06-21 01:14:54 +03:00
switch ( program - > getUniformType ( ii ) )
2019-08-03 18:54:02 +03:00
{
case 0x1404 : // GL_INT:
un . type = UniformType : : Sampler ;
break ;
case 0x8B52 : // GL_FLOAT_VEC4:
un . type = UniformType : : Vec4 ;
break ;
case 0x8B5B : // GL_FLOAT_MAT3:
un . type = UniformType : : Mat3 ;
un . regCount * = 3 ;
break ;
case 0x8B5C : // GL_FLOAT_MAT4:
un . type = UniformType : : Mat4 ;
un . regCount * = 4 ;
break ;
default :
un . type = UniformType : : End ;
break ;
}
uniforms . push_back ( un ) ;
}
}
if ( g_verbose )
{
program - > dumpReflection ( ) ;
}
BX_UNUSED ( spv : : MemorySemanticsAllMemory ) ;
glslang : : TIntermediate * intermediate = program - > getIntermediate ( stage ) ;
std : : vector < uint32_t > spirv ;
glslang : : SpvOptions options ;
options . disableOptimizer = false ;
glslang : : GlslangToSpv ( * intermediate , spirv , & options ) ;
spvtools : : Optimizer opt ( SPV_ENV_VULKAN_1_0 ) ;
auto print_msg_to_stderr = [ ] (
spv_message_level_t
, const char *
, const spv_position_t &
, const char * m
)
{
bx : : printf ( " Error: %s \n " , m ) ;
} ;
opt . SetMessageConsumer ( print_msg_to_stderr ) ;
opt . RegisterLegalizationPasses ( ) ;
2019-09-28 20:30:23 +03:00
spvtools : : ValidatorOptions validatorOptions ;
validatorOptions . SetBeforeHlslLegalization ( true ) ;
if ( ! opt . Run (
spirv . data ( )
, spirv . size ( )
, & spirv
, validatorOptions
, false
) )
2019-08-03 18:54:02 +03:00
{
compiled = false ;
}
else
{
2021-04-21 17:45:03 +03:00
if ( g_verbose )
{
glslang : : SpirvToolsDisassemble ( std : : cout , spirv , SPV_ENV_VULKAN_1_0 ) ;
}
2019-08-03 18:54:02 +03:00
spirv_cross : : CompilerReflection refl ( spirv ) ;
spirv_cross : : ShaderResources resourcesrefl = refl . get_shader_resources ( ) ;
// Loop through the separate_images, and extract the uniform names:
for ( auto & resource : resourcesrefl . separate_images )
{
std : : string name = refl . get_name ( resource . id ) ;
2021-04-21 06:18:49 +03:00
if ( name . size ( ) > 7 & & 0 = = bx : : strCmp ( name . c_str ( ) + name . length ( ) - 7 , " Texture " ) )
2019-08-03 18:54:02 +03:00
{
2021-04-21 06:18:49 +03:00
name = name . substr ( 0 , name . length ( ) - 7 ) ;
}
2019-08-03 18:54:02 +03:00
2021-04-21 06:18:49 +03:00
Uniform un ;
un . name = name ;
un . type = UniformType : : Sampler ;
2019-08-03 18:54:02 +03:00
2021-04-21 06:18:49 +03:00
un . num = 0 ; // needed?
un . regIndex = 0 ; // needed?
un . regCount = 0 ; // needed?
2019-08-03 18:54:02 +03:00
2021-04-21 06:18:49 +03:00
uniforms . push_back ( un ) ;
2019-08-03 18:54:02 +03:00
}
uint16_t size = writeUniformArray ( _writer , uniforms , _options . shaderType = = ' f ' ) ;
2021-10-26 04:59:32 +03:00
bx : : Error err ;
2020-06-21 01:14:54 +03:00
if ( _version = = BX_MAKEFOURCC ( ' M ' , ' T ' , ' L ' , 0 ) )
2019-08-03 18:54:02 +03:00
{
2020-06-21 01:14:54 +03:00
spirv_cross : : CompilerMSL msl ( std : : move ( spirv ) ) ;
2019-09-28 20:30:23 +03:00
2019-08-10 19:27:57 +03:00
auto executionModel = msl . get_execution_model ( ) ;
spirv_cross : : MSLResourceBinding newBinding ;
newBinding . stage = executionModel ;
2019-08-03 18:54:02 +03:00
spirv_cross : : ShaderResources resources = msl . get_shader_resources ( ) ;
spirv_cross : : SmallVector < spirv_cross : : EntryPoint > entryPoints = msl . get_entry_points_and_stages ( ) ;
2020-06-21 01:14:54 +03:00
if ( ! entryPoints . empty ( ) )
2019-08-03 18:54:02 +03:00
msl . rename_entry_point ( entryPoints [ 0 ] . name , " xlatMtlMain " , entryPoints [ 0 ] . execution_model ) ;
for ( auto & resource : resources . uniform_buffers )
{
2019-08-10 19:27:57 +03:00
unsigned set = msl . get_decoration ( resource . id , spv : : DecorationDescriptorSet ) ;
unsigned binding = msl . get_decoration ( resource . id , spv : : DecorationBinding ) ;
newBinding . desc_set = set ;
newBinding . binding = binding ;
newBinding . msl_buffer = 0 ;
msl . add_msl_resource_binding ( newBinding ) ;
2019-08-03 18:54:02 +03:00
msl . set_name ( resource . id , " _mtl_u " ) ;
}
for ( auto & resource : resources . storage_buffers )
{
2019-08-10 19:27:57 +03:00
unsigned set = msl . get_decoration ( resource . id , spv : : DecorationDescriptorSet ) ;
unsigned binding = msl . get_decoration ( resource . id , spv : : DecorationBinding ) ;
newBinding . desc_set = set ;
newBinding . binding = binding ;
newBinding . msl_buffer = binding + 1 ;
msl . add_msl_resource_binding ( newBinding ) ;
}
for ( auto & resource : resources . separate_samplers )
{
unsigned set = msl . get_decoration ( resource . id , spv : : DecorationDescriptorSet ) ;
unsigned binding = msl . get_decoration ( resource . id , spv : : DecorationBinding ) ;
newBinding . desc_set = set ;
newBinding . binding = binding ;
newBinding . msl_texture = binding - textureBindingOffset ;
newBinding . msl_sampler = binding - textureBindingOffset ;
msl . add_msl_resource_binding ( newBinding ) ;
2019-08-03 18:54:02 +03:00
}
for ( auto & resource : resources . separate_images )
{
std : : string name = msl . get_name ( resource . id ) ;
if ( name . size ( ) > 7 & & 0 = = bx : : strCmp ( name . c_str ( ) + name . length ( ) - 7 , " Texture " ) )
2020-06-21 01:14:54 +03:00
{
msl . set_name ( resource . id , name . substr ( 0 , name . length ( ) - 7 ) ) ;
}
2019-09-28 20:30:23 +03:00
2019-08-10 19:27:57 +03:00
unsigned set = msl . get_decoration ( resource . id , spv : : DecorationDescriptorSet ) ;
unsigned binding = msl . get_decoration ( resource . id , spv : : DecorationBinding ) ;
newBinding . desc_set = set ;
newBinding . binding = binding ;
newBinding . msl_texture = binding - textureBindingOffset ;
newBinding . msl_sampler = binding - textureBindingOffset ;
msl . add_msl_resource_binding ( newBinding ) ;
}
2019-09-28 20:30:23 +03:00
2019-08-10 19:27:57 +03:00
for ( auto & resource : resources . storage_images )
{
std : : string name = msl . get_name ( resource . id ) ;
2019-09-28 20:30:23 +03:00
2019-08-10 19:27:57 +03:00
unsigned set = msl . get_decoration ( resource . id , spv : : DecorationDescriptorSet ) ;
unsigned binding = msl . get_decoration ( resource . id , spv : : DecorationBinding ) ;
newBinding . desc_set = set ;
newBinding . binding = binding ;
newBinding . msl_texture = binding - textureBindingOffset ;
newBinding . msl_sampler = binding - textureBindingOffset ;
msl . add_msl_resource_binding ( newBinding ) ;
2019-08-03 18:54:02 +03:00
}
2019-09-28 20:30:23 +03:00
2019-08-03 18:54:02 +03:00
std : : string source = msl . compile ( ) ;
if ( ' c ' = = _options . shaderType )
{
for ( int i = 0 ; i < 3 ; + + i )
{
uint16_t dim = ( uint16_t ) msl . get_execution_mode_argument ( spv : : ExecutionMode : : ExecutionModeLocalSize , i ) ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , dim , & err ) ;
2019-08-03 18:54:02 +03:00
}
}
uint32_t shaderSize = ( uint32_t ) source . size ( ) ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , shaderSize , & err ) ;
bx : : write ( _writer , source . c_str ( ) , shaderSize , & err ) ;
2019-08-03 18:54:02 +03:00
uint8_t nul = 0 ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , nul , & err ) ;
2019-08-03 18:54:02 +03:00
}
else
{
uint32_t shaderSize = ( uint32_t ) spirv . size ( ) * sizeof ( uint32_t ) ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , shaderSize , & err ) ;
bx : : write ( _writer , spirv . data ( ) , shaderSize , & err ) ;
2019-08-03 18:54:02 +03:00
uint8_t nul = 0 ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , nul , & err ) ;
2019-08-03 18:54:02 +03:00
}
//
const uint8_t numAttr = ( uint8_t ) program - > getNumLiveAttributes ( ) ;
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , numAttr , & err ) ;
2019-08-03 18:54:02 +03:00
for ( uint8_t ii = 0 ; ii < numAttr ; + + ii )
{
bgfx : : Attrib : : Enum attr = toAttribEnum ( program - > getAttributeName ( ii ) ) ;
if ( bgfx : : Attrib : : Count ! = attr )
{
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , bgfx : : attribToId ( attr ) , & err ) ;
2019-08-03 18:54:02 +03:00
}
else
{
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , uint16_t ( UINT16_MAX ) , & err ) ;
2019-08-03 18:54:02 +03:00
}
}
2021-10-26 04:59:32 +03:00
bx : : write ( _writer , size , & err ) ;
2019-08-03 18:54:02 +03:00
}
}
}
delete program ;
delete shader ;
glslang : : FinalizeProcess ( ) ;
return compiled & & linked & & validated ;
}
} // namespace metal
bool compileMetalShader ( const Options & _options , uint32_t _version , const std : : string & _code , bx : : WriterI * _writer )
{
return metal : : compile ( _options , _version , _code , _writer , true ) ;
}
} // namespace bgfx