yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
1b5679f95
master
1#pragma once 2 3#include <emscripten.h> 4#include <emscripten/val.h> 5#include <optional> 6#include <slang-com-ptr.h> 7#include <slang.h> 8#include <stdint.h> 9#include <string> 10#include <unordered_map> 11#include <vector> 12 13/** 14The web assembly binding here is designed to make javascript code as simple and native as possible. 15The big issue being handled here is lifetime management of objects created in the Slang API. 16 17The idea here is to make lifetime management as coarse grained as possible from the javascript side. 18Only two types of objects need to be explicitly deleted by javascript: GlobalSession and Session. 19 20All the remaining objects returned by member functions of Session will have their lifetime managed 21by the owning session in the C++ side. This way, the javascript code will never need to worry about 22freeing small objects like ComponentType, EntryPoint, Module, TypeLayoutReflection, 23VariableLayoutReflection, ProgramLayout etc. 24 25When a Session is no longer needed, the javascript code should explicitly delete it, this will allow 26us to free all the objects we allocated from the session in one single explicit call. 27 28By making explicit memory management as coarse grained as possible, we are making memory management 29efficient, simple, and less error prone. 30*/ 31 32namespace Slang 33{ 34class LanguageServerCore ; 35} 36 37namespace slang 38{ 39namespace wgsl 40{ 41 42class TypeLayoutReflection ; 43class TypeReflection ; 44class VariableLayoutReflection ; 45class VariableReflection ; 46class FunctionReflection ; 47class GenericReflection ; 48 49 50class Error 51{ 52public : 53// Can be 54// "USER": User did not call the API correctly 55// "INTERNAL": Slang failed due to a bug 56std ::string type ; 57std ::string message ; 58SlangResult result ; 59}; 60 61Error getLastError (); 62 63// returns mapping of codegen target from string to SlangCompileTarget 64// in the form of [{name: STRING, value: INT}, ...]. 65emscripten ::val getCompileTargets (); 66 67class DeclReflection 68{ 69public : 70std ::string getName (); 71slang ::DeclReflection ::Kind getKind (); 72uint32_t getChildrenCount (); 73slang ::wgsl ::DeclReflection * getChild (uint32_t index ); 74slang ::wgsl ::TypeReflection * getType (); 75slang ::wgsl ::VariableReflection * asVariable (); 76slang ::wgsl ::FunctionReflection * asFunction (); 77slang ::wgsl ::GenericReflection * asGeneric (); 78slang ::wgsl ::DeclReflection * getParent (); 79 80slang ::DeclReflection * interface ()const {return (slang ::DeclReflection * )this ; }; 81}; 82 83class GenericReflection 84{ 85 86public : 87std ::string getName (); 88slang ::wgsl ::DeclReflection * asDecl (); 89uint32_t getTypeParameterCount (); 90slang ::wgsl ::VariableReflection * getTypeParameter (unsigned index ); 91uint32_t getValueParameterCount (); 92slang ::wgsl ::VariableReflection * getValueParameter (unsigned index ); 93// uint32_t getTypeParameterConstraintCount(VariableReflection* typeParam); 94// slang::wgsl::TypeReflection* getTypeParameterConstraintType( 95// VariableReflection* typeParam, 96// unsigned index); 97slang ::wgsl ::DeclReflection * getInnerDecl (); 98SlangDeclKind getInnerKind (); 99slang ::wgsl ::GenericReflection * getOuterGenericContainer (); 100// TypeReflection* getConcreteType(slang::wgsl::VariableReflection* typeParam); 101// int64_t getConcreteIntVal(slang::wgsl::VariableReflection* valueParam); 102// GenericReflection* applySpecializations(slang::wgsl::GenericReflection* generic); 103 104slang ::GenericReflection * interface ()const {return (slang ::GenericReflection * )this ; }; 105}; 106 107class TypeReflection 108{ 109 110public : 111slang ::TypeReflection ::ScalarType getScalarType (); 112slang ::TypeReflection ::Kind getKind (); 113uint32_t getFieldCount (); 114slang ::wgsl ::VariableReflection * getFieldByIndex (uint32_t index ); 115 116slang ::TypeReflection * interface ()const {return (slang ::TypeReflection * )this ; }; 117}; 118 119 120class UserAttribute 121{ 122 123public : 124std ::string getName (); 125uint32_t getArgumentCount (); 126float getArgumentValueFloat (uint32_t index ); 127std ::string getArgumentValueString (uint32_t index ); 128slang ::wgsl ::TypeReflection * getArgumentType (uint32_t index ); 129slang ::UserAttribute * interface ()const {return (slang ::UserAttribute * )this ; }; 130}; 131 132 133class VariableReflection 134{ 135public : 136std ::string getName (); 137slang ::wgsl ::TypeReflection * getType (); 138Modifier * findModifier (Modifier ::ID id ); 139uint32_t getUserAttributeCount (); 140slang ::wgsl ::UserAttribute * getUserAttributeByIndex (uint32_t index ); 141// slang::wgsl::UserAttribute* findUserAttributeByName(SlangSession* globalSession, std::string 142// name); 143bool hasDefaultValue (); 144// slang::wgsl::GenericReflection* getGenericContainer(); 145// slang::wgsl::VariableReflection* applySpecializations(slang::wgsl::GenericReflection* 146// generic); 147slang ::VariableReflection * interface ()const {return (slang ::VariableReflection * )this ; } 148}; 149 150 151class TypeLayoutReflection 152{ 153public : 154BindingType getDescriptorSetDescriptorRangeType (uint32_t setIndex ,uint32_t rangeIndex ); 155slang ::TypeLayoutReflection * interface ()const {return (slang ::TypeLayoutReflection * )this ; } 156}; 157 158class VariableLayoutReflection 159{ 160public : 161std ::string getName (); 162slang ::wgsl ::TypeLayoutReflection * getTypeLayout (); 163uint32_t getBindingIndex (); 164 165slang ::VariableLayoutReflection * interface ()const 166 { 167return (slang ::VariableLayoutReflection * )this ; 168 } 169}; 170 171class EntryPointReflection 172{ 173 174public : 175struct ThreadGroupSize 176 { 177uint32_t x ; 178uint32_t y ; 179uint32_t z ; 180 }; 181 182ThreadGroupSize getComputeThreadGroupSize (); 183slang :: EntryPointReflection * interface () const { return (slang:: EntryPointReflection * )this; }; 184}; 185class FunctionReflection 186{ 187 188public : 189std :: string getName (); 190uint32_t getUserAttributeCount (); 191slang :: wgsl :: UserAttribute * getUserAttributeByIndex ( uint32_t index); 192slang :: FunctionReflection * interface () const { return (slang:: FunctionReflection * )this; }; 193}; 194 195class ProgramLayout 196{ 197public : 198uint32_t getParameterCount (); 199slang :: wgsl :: VariableLayoutReflection * getParameterByIndex ( uint32_t index); 200 201slang :: wgsl :: TypeLayoutReflection * getGlobalParamsTypeLayout (); 202 203slang :: wgsl ::EntryPointReflection * findEntryPointByName (std::string name); 204 205slang :: wgsl ::FunctionReflection * findFunctionByName (std::string name); 206 207slang :: ProgramLayout * interface () const { return (slang:: ProgramLayout * )this; } 208 209emscripten :: val toJsonObject (); 210}; 211 212class Session; 213class ComponentType 214{ 215public : 216IComponentType * m_interface; 217Session * m_session; 218 219public : 220ComponentType ( slang ::IComponentType * interface, Session * session) 221: m_interface (interface), m_session (session) 222{ 223} 224 225// Returns ComponentType or null. 226emscripten :: val link (); 227 228std :: string getEntryPointCode ( int entryPointIndex, int targetIndex); 229 230// Returns UInt8Array or null. 231emscripten :: val getEntryPointCodeBlob ( int entryPointIndex, int targetIndex); 232std :: string getTargetCode ( int targetIndex); 233 234// Returns UInt8Array or null. 235emscripten :: val getTargetCodeBlob ( int targetIndex); 236 237slang :: wgsl :: ProgramLayout * getLayout ( uint32_t targetIndex); 238 239slang :: IComponentType * interface () const { return m_interface; } 240 241// returns [{hash: HASH, string: STRING}, ...] 242emscripten :: val loadStrings (); 243}; 244 245class EntryPoint : public ComponentType 246{ 247public : 248EntryPoint ( slang ::IComponentType * interface, Session * session) 249: ComponentType (interface, session) 250{ 251} 252std :: string getName () const 253{ 254return entryPointInterface () -> getFunctionReflection () -> getName (); 255} 256 257private : 258slang :: IEntryPoint * entryPointInterface () const 259{ 260return static_cast < slang::IEntryPoint * >( interface ()); 261} 262}; 263 264class Module : public ComponentType 265{ 266public : 267Module ( slang ::IComponentType * interface, Session * session) 268: ComponentType (interface, session) 269{ 270} 271 272// Returns EntryPoint or null. 273emscripten :: val findEntryPointByName( const std ::string & name); 274 275// Returns EntryPoint or null. 276emscripten :: val findAndCheckEntryPoint( const std ::string & name, int stage); 277 278// Returns EntryPoint or null. 279emscripten :: val getDefinedEntryPoint ( int index); 280 281int getDefinedEntryPointCount (); 282 283slang :: IModule * moduleInterface () const { return static_cast < slang::IModule * >( interface ()); } 284}; 285 286class Session 287{ 288public : 289Session ( slang :: ISession * interface) 290: m_interface( interface ) 291{ 292} 293~ Session (); 294 295// Returns Module or null. 296emscripten :: val loadModuleFromSource( 297const std ::string & slangCode, 298const std ::string & name, 299const std ::string & path); 300 301// `components` is a javascript array of ComponentType/Module/EntryPoint objects. 302// Returns ComponentType or null. 303emscripten :: val createCompositeComponentType( emscripten :: val components); 304 305slang :: ISession * interface () const { return m_interface; } 306 307void addComponentType ( slang ::IComponentType * componentType) 308{ 309m_componentTypes. push_back (Slang::ComPtr < slang::IComponentType > (componentType)); 310} 311 312private : 313std ::vector < Slang::ComPtr < slang::IComponentType>> m_componentTypes; 314Slang ::ComPtr < slang::ISession > m_interface; 315}; 316 317class GlobalSession 318{ 319public : 320GlobalSession ( slang :: IGlobalSession * interface) 321: m_interface( interface ) 322{ 323} 324 325Session * createSession ( int compileTarget); 326 327slang :: IGlobalSession * interface () const { return m_interface; } 328 329private : 330Slang ::ComPtr < slang::IGlobalSession > m_interface; 331}; 332 333GlobalSession * createGlobalSession (); 334 335namespace lsp 336{ 337struct Position 338{ 339int line = -1 ; 340int character = -1 ; 341}; 342 343struct Range 344{ 345Position start ; 346Position end ; 347}; 348 349struct Location 350{ 351std :: string uri ; 352Range range ; 353}; 354 355struct TextEdit 356{ 357Range range ; 358std :: string text ; 359}; 360 361struct MarkupContent 362{ 363std :: string kind ; 364std :: string value ; 365}; 366 367struct Hover 368{ 369MarkupContent contents ; 370Range range ; 371}; 372 373struct CompletionItem 374{ 375std :: string label ; 376int kind ; 377std :: string detail ; 378std :: string data ; 379std :: optional < MarkupContent > documentation ; 380std :: optional < TextEdit > textEdit ; 381std :: optional < std ::vector < std::string>> commitCharacters; 382}; 383 384struct CompletionContext 385{ 386int triggerKind = 1 ; 387std :: string triggerCharacter ; 388}; 389 390struct ParameterInformation 391{ 392uint32_t label [ 2 ] = { 0 , 0 }; 393MarkupContent documentation ; 394}; 395 396struct SignatureInformation 397{ 398std :: string label ; 399MarkupContent documentation ; 400std :: vector < ParameterInformation > parameters ; 401}; 402 403struct SignatureHelp 404{ 405std :: vector < SignatureInformation > signatures ; 406uint32_t activeSignature = 0 ; 407uint32_t activeParameter = 0 ; 408}; 409 410struct DocumentSymbol 411{ 412std :: string name ; 413std :: string detail ; 414int kind = 0 ; 415Range range ; 416Range selectionRange ; 417std :: vector < DocumentSymbol > children ; 418}; 419 420struct Diagnostics 421{ 422std :: string code ; 423Range range ; 424std :: string message ; 425int severity ; 426}; 427 428class LanguageServer 429{ 430private : 431Slang :: LanguageServerCore * m_core = nullptr ; 432void init (); 433 434public : 435LanguageServer (); 436~ LanguageServer (); 437void didOpenTextDocument ( std ::string uri, std ::string text); 438void didCloseTextDocument ( std ::string uri); 439void didChangeTextDocument ( std ::string uri, const std ::vector < lsp::TextEdit >& changes); 440std ::optional < lsp::Hover > hover (std::string uri, lsp::Position position); 441std ::optional < std::vector < lsp::Location>> gotoDefinition ( 442std::string uri, 443lsp::Position position); 444std ::optional < std::vector < lsp::CompletionItem>> completion ( 445std::string uri, 446lsp::Position position, 447CompletionContext context); 448std ::optional < lsp::CompletionItem > completionResolve (lsp::CompletionItem args); 449std ::optional < std::vector < uint32_t>> semanticTokens (std::string uri); 450std ::optional < lsp::SignatureHelp > signatureHelp (std::string uri, lsp::Position position); 451std ::optional < std::vector < lsp::DocumentSymbol>> documentSymbol (std::string uri); 452std ::optional < std::vector < lsp::Diagnostics>> getDiagnostics (std::string uri); 453}; 454 455LanguageServer * createLanguageServer (); 456} // namespace lsp 457 458} // namespace wgsl 459} // namespace slang