From f5eb12a5dedec55cfaf23dd124d59b64c0dd06a2 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Sat, 13 Apr 2024 23:51:38 +0200 Subject: [PATCH] Descriptor sets and refactoring --- .clang-format | 244 ++++++++ .vscode/settings.json | 4 + CMakeLists.txt | 8 +- external/dxc | Bin 771496 -> 0 bytes res/shaders/TextPass.slang | 20 +- src/Editor/main.cpp | 8 +- src/Engine/Graphics/Buffer.h | 196 +++--- src/Engine/Graphics/Descriptor.cpp | 143 ++--- src/Engine/Graphics/Descriptor.h | 141 ++--- src/Engine/Graphics/Enums.h | 235 +------ src/Engine/Graphics/Initializer.h | 6 +- src/Engine/Graphics/Metal/Buffer.h | 89 +-- src/Engine/Graphics/Metal/Buffer.mm | 99 ++- src/Engine/Graphics/Metal/CMakeLists.txt | 2 + src/Engine/Graphics/Metal/Descriptor.h | 59 +- src/Engine/Graphics/Metal/Descriptor.mm | 142 ++++- src/Engine/Graphics/Metal/Enums.h | 14 + src/Engine/Graphics/Metal/Enums.mm | 181 ++++++ src/Engine/Graphics/Metal/Graphics.mm | 26 +- src/Engine/Graphics/Metal/PipelineCache.h | 16 +- src/Engine/Graphics/Metal/PipelineCache.mm | 70 +++ src/Engine/Graphics/Metal/Resources.h | 14 + src/Engine/Graphics/Metal/Resources.mm | 30 +- src/Engine/Graphics/Metal/Shader.mm | 84 +-- src/Engine/Graphics/RenderTarget.h | 13 +- src/Engine/Graphics/Vulkan/Buffer.h | 230 ++++--- src/Engine/Graphics/Vulkan/Descriptor.cpp | 690 ++++++++++----------- src/Engine/Graphics/Vulkan/Descriptor.h | 196 +++--- src/Engine/Graphics/Vulkan/Enums.cpp | 87 ++- src/Engine/Graphics/Vulkan/PipelineCache.h | 2 +- vcpkg.json | 4 +- 31 files changed, 1688 insertions(+), 1365 deletions(-) create mode 100644 .clang-format delete mode 100755 external/dxc diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..dcf16f8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,244 @@ +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowBreakBeforeNoexceptSpecifier: Never +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +KeepEmptyLinesAtEOF: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/.vscode/settings.json b/.vscode/settings.json index 615e47b..fd5e29f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -160,4 +160,8 @@ }, "editor.tabSize": 2, "editor.detectIndentation": false, + "lldb.displayFormat": "auto", + "lldb.showDisassembly": "auto", + "lldb.dereferencePointers": true, + "lldb.consoleMode": "commands", } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f29ecd9..5e8a2d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,10 @@ find_package(Ktx CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED) find_package(fmt CONFIG REQUIRED) find_package(VulkanMemoryAllocator CONFIG REQUIRED) +find_package(spirv_cross_core CONFIG REQUIRED) +find_package(spirv_cross_glsl CONFIG REQUIRED) +find_package(spirv_cross_msl CONFIG REQUIRED) +find_package(glslang CONFIG REQUIRED) if(UNIX) find_package(Threads REQUIRED) @@ -74,8 +78,9 @@ target_link_libraries(Engine PUBLIC crcpp) target_link_libraries(Engine PUBLIC fmt::fmt) target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator) target_link_libraries(Engine PUBLIC shader-slang) +target_link_libraries(Engine PUBLIC spirv-cross-glsl spirv-cross-msl) +target_link_libraries(Engine PUBLIC glslang::glslang) if(APPLE) - target_link_libraries(Engine PUBLIC /usr/local/lib/libmetalirconverter.dylib) target_link_libraries(Engine PUBLIC metal) SET(CMAKE_OSX_DEPLOYMENT_TARGET 14.3) install(FILES @@ -133,7 +138,6 @@ if(WIN32) elseif(APPLE) add_custom_target(dll_copy ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_ROOT}bin/libslang.dylib $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXTERNAL_ROOT}/dxc $ COMMAND_EXPAND_LISTS DEPENDS Editor) else() diff --git a/external/dxc b/external/dxc deleted file mode 100755 index d1aa98b43774ce2051a55f0d48178f31365bb783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 771496 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

@NZkG4+4XP8MDxdO3a)hmat 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 )5s6E%9Bf8J(&pqnMb#SC94O471 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⪻Uhu_KX5!cGk3ofs-SG1U9SP|@(v&=H|g(=ujz=U8(+^UUiE z)6k)z!$U=OII)Nu86NTt4~>$1_VO83doVTt>g02&osX2u2mU0&;^mUO3*b$JcX@^r zKPB(sq2i>xM`WbWyIAx%9;_v?gR$#zOWwxSA{M%$ppySg!gEz!EF|GPL-~}$+nm8( z2~<%MC;#E0-jr~fHQO`SoM)H;Eq=GGCkkj$Z=%;oewlT#b8)+Ai8akmV~nyDLu71{ zV1CL()eu+er&-(!lH(Q;x4?gBxMPVsinwQ_!#$}9*DgPCClR-&#N`>xryO1xyj4x* zZ!Cj3RL22+9x60`ANL5>R?_7K>S7%Qh^K_l9(X zvuEgegLKX9{glueoh0ZlS`c&%c?;fhJ^}VaS5ViUX%mw%v6T^_iPOBZl3I1XxAI)VR5h_cT`Qa91mVRd>xZ|LcFFzRj zy$8&zn5d+~oS3ABms@D}6Qw>@g13nI;mxJ|Jzvk)|9vHvlT4sNBA)eQ4 z_AhY}YMjn1wfn0v{S`@#QT^4}{%SPu>+7$~Ol`-Ph#>vO{v)38TRy+AeZUfzugd(& z{xdEm8~!}&By%}IU2v~Uo1(^ zO-OPgNlqlm@K80M&2~~GIMdFJG?eaK+Y1L-K;;k70X@SGJuO{ToQ?pbMC^&S80Ym@ zBNH4G`YSky*Z7}Ml$OXjL^paOCTc-G%E}-4HoEbmH#jK32{m4{D}{^+ARbDmSf|^6 zcqtR*BQ^p#2^#+sU&@4-)UebQYJx{<{!VHZUB>Hb+SZcW4#r*)JN$EsUD^FYX+pm+ zQa9@YhKEW=n2cStslIoBlb;618KY03?h@_O_$w0rjL%Daik<3zm=_oKSCef8P=%EB z;{K6ehia(!oyMsEphiOsZx$a+78{-vuat}J0#f9Y2^-Ic5?^L3!1#+8VvX@@Kt_c2 z0Jfh`Emk$v6sgFGzn|OrQC0u6ap7QG$mn8RCYD)aoCn55nv1l5{Nk1B&8!IKqNL!bUsdG(t?H& zpa|!WC=?hp1FXOGSC`;IHRMKm?1Y?QHM%)7M>n7YgPCAU0H9g2gyZ~SK~6qI7@4jC zNmE2DVw02PW>oNHEE@zdk&b+w7Sh;k{+!U9oS?-2jqw|qh=iN}1ktk~Kgz=<_%FQ% zMFtTra-(yDdWXf|>2{Ccl!;QJ6Jqm+bPfhW<8_d5P|#Ct4k#1^d8q;?0-XpB=g+Ag zI3!0a{5h)Pe`6MnksBR=iiH$ZCl2@Wnfl3aWHngwDInZnD)3=#p z98Iro)btg0=7?I`=W6^m~7vhljp2eEzIjSQwPJq%nK+rn)Cmsn6KIG zH*vi-f|X)?z4mt_b-h+xMEWtL-^#s#fV9=4X>(4!+w)7A7=F@J@iLXP%Q2fY%eNhj zT|{|Wto!BBq(0+HU%HktJhVLOlw&8D8$aN_gUr1zbmU08?!3v9T8<*oLm_>}lur)E z&JsOH-{I(iK1Vtn)~lB`uG>bkZYytE0&z2q^rfUP`0`-vCEN*p7IhO}_c|+mAP5?sAAGokbW8I?-D)6sN2MPI3+aIh*yO1N&c zscZjHEv!F^M}j$+Mg36jdORUI*^t)WMud{rpU1V(wUmXUoA z=58`^o8zqXUrt!eIhzBdmo`uh#uD~6-ox!#nurnCv$MaDq-PLL4;5XSsyMMp{p4PJQ;vTE)U;C9zut{q)xl-h`rke<^lg{3m_u zDz<+kb^=&s#q4Fdc~3LWx8)bFlyNrUrAA$hEpt0Bk;*`RXA7(7XSRbN*~_XT?n>ew zC2&sliK29yC zy%s1=SPN`!z7`;TUp^zjSmUXS9g91)-A{-&bP3}T-A*C?X5!0QIE`*o_x3Jnp^c3a zEV#d7joE|Hsp3L;^)s-u^9qpBUw{NiHv~nfe@RpWrSoZKr!P?8-+Trfu+53N_ z-O2vfP$^SmKbG3Y&0g#PHtyKSrkQcTBgm$`ZDzmfL4Lu*SPrEQnwD{_>A)i?L>ZD9my z%Sl_v9md>4lEY|7r#`WZUEtJ$)7tU?ql!8(-#)&1A1>qHNW#jvYdKa95t@$`&Bpi^ zrj(_mw&z0S;8k!pb8u1{Zq|;vrM9DZ`W=#K%Cd+NBbswMjqJxHDH0SAw6c=LKp8B2_{>FiE)FczHU;Eee1^*1oJ{v_=}(yr@%`1%w1w~}^d5AM$5 zJ_PySNhg1Ak`@$T@7&?-+$4WvA86(_&g1RAsf4&axaYfG@}zI#Y{Q*@8IQ#$U@+|d zWfF0#iF72CR)o*2R9>Bx9O>&g_?}<6)$gJKLMNbNoZbIkBB# zooMfUxC@M19-(sodv*$M9K4zEFhl#1c$48RfXB3@kvAJ&1w5vxjl2qY%is-mc@lpm zyc&3!E>DQq`9}Dg<8iUuX~t!?ol76Mhp+>LO;4}$Q$l6lq;=x>v`TmS^ue8>N7u#r z$avSnIBRw=Qbtv0&Nq>?efx2LnSHJn(=ITR)1DkEN@h6wTdTk-E2@i~(p2|N_Bp80 zK2MHM>1A#t{mTK;RdRRy12OXE?faC_{$yR0_fFSB*i2^spcse|T__uOsb5dkEo1E| zp`D(D$@A0cCeKA+%micCd3CXWCzXXwYLB~auF;9bu*Zj0q^aQU_Tl!=WM|t;ouvP5 zU977x?DfFejq8EDLhOvNf27W7C{yy8;ctyJX9E+(PRD|=pF8EJ;$|IE#J;&)M^=;I z_ddTa_L%S+?Z+9{q;qdtzLqCLQ-RWUR+7Gw^zlAhY`+@bf(#NAWW+_nj_$DDP9PX_B~ zVepLRQv+`Sy!aS9%`ikGU&VJnBp#30;8Z*X@TRA?8@f+3$)Lx#U^mj=Yy_+HAAGk1H~meaaYsnDHPkNn zd*HKGZp&A~I3W8Kb?|q>|4{gib>Qv=%`=QQ5_(*bRlc)S@z1*0JL&7c**%A~Ef|1| zL6gB6JeBW_n0V6J<^JUT=iX_{%@~9%(#KVUw{9A90x4u89&2CeP~+D-YBLjtQD^T= zWbtspYvG)_*vrfjn$prA$IqP@!V)``QTgfG2Y8go zS~Y?r<5B?NqDNBKs>m(lM121~&3!A9+HFI=gI36QkP3ytBV$!5yuR?*ny???O@b%i zU6S(3BlRcWTN?rIabYypU(;I89i#3|9is$q9cimcTPkUJgjWMEm+wLS#^yM@z3@um zp)&iCcrtmP0*@(?{fIr}!kY>2r1W;4+RtUDHFIJKpyV-5@K!XHR{|!(TL5nd?xwcq z%yo=a@%|43;WnXdLKsMs+reE0MiJlfl0H(N5oYzcCXcO0wQwvmiY`hm0W0rW zci#uB_}c0^W1_vZl9oJ~cpHgVM7;HGyCa@-X6%7q(zFCCa?;o>u83VDTQ-zi#6`bG zHv>?k+juU)^Q#2+*>Sg&w}g%8>Ce^0zHg}=CYN_d+IGl2IKf%~*3h-I^YndVY8_^# z9kN}lonRHL<9n7ZVI|Kc_O&2asnl~{2H2f1@tr!{@(8aO-i{RBXm~X#yz%h1rtqe~ z+nmCa?~!gy;E8Q7ftT0kzl{HcSCS@6gyIpoYTzw_H^Ju6rlEV`sr7X+ugeo6d{1BY zM~EBmql7PZR{&q)zbXtGVchOGj(jm*_Y!Xe@hXXTRr7d%jmPUv*aX3=u8aMoS-i3F zXf$$XZMTrPxy1dg#I^>fDeoHaCxCzbq2W(T zha+vy$HCdUSNJ|@Oa125BX**7*59U6A8u}_&>17%bO2%S?C`~1hR&1sMtW{v0 zBv_4eG-sSRGd?t&8Y+~rbR%*1Z+6ESY-XDAtH!y*9>NX~77`pDX(M%R{0y7p$R0U{ zc0#-^>GhCeKirROLH1E#_Qe)Uv7rc9o?FjOu;WI1WPzWgSL2CvcwD&>ab%t_70kWV z(;nQO3&CvEiG3xUx zQa85>-nXOEl`nPvbz)k5ahFi!8w*|;x|jV7&*~QNlEx9nrZlEQ*KgPFjw1B6rK!Kh ztM>D63cSDKmVU(^Be`31oiWMogJ}NLvD0nIxGMcy556!k=AF9Oa5oK0i)qFmC9OqZw||6NvHF}) zg+7&A)CS?)9pah{=?MEJVZ+@puF{Z(>r4QUlAA^)a)UB8LKEm{Hz8MP#@qL3xYffg zIW97BP3D}YjL(#ext#@9?)`Bek9@ci$MqcqIkkV}yo5}Q5%#?x?tT#oNf6_L{*f~i zVo)~tBqoTCqC_qkE!1NXW_YMlb5+bPkvYHY))HXd!s#-;tr z`wn(|RTsM#x7&8p>{lB%CCu|>+tNOlSVr1WU)RN~^m3&1O~x1L+C~Z49sp;|H+8W= z>E~)GIOdlvl&4s*iU-rT@ZJIYe7kX+Zq!XGR(jolBUrP+D*Eofd`Bax?VGBFxtjf5 zib~q-fo*j$?V&9mc~<&*OKywiFI$*MmZ9%m$X5sEe)@p{OrSiU(Ze?{?+ENTajncn zL7I+nt$ni>qo#pj*JJue&cfKab%n84=(K~ov}<|Ru-2Mt{mV1me zNSYyVM4$&D942{4FpY%7v{jNc&(LX`DN+y>SE^vz&rT!bb7OIW+m=1__ESjFPE;dS(*3D1as0p=U$HI9CC5S!N#^E zSMHkjk>6^zkBnj3vTX(@@MT@>IB-4P52dW;Wi7M^DXKm0j6RP26xzfPVemxwjEA=l z-ibEH;Z1?3uy=btj1%)$W$^mK`@ul$zPtuWw-FD=CB|TJq?3Sin^D|SK*seNh~SEE(Ga~43~>ePHLgPDw6kvJS{ZF3fiAw%6nTzAEa$ddu-nV z=9=WazDHY7^cvQ3qSIA$sGDO=>lxu~hPM%3d`>64UGS>maV%;-!mEY16<*?*Tz~;# zC%iin;uXT1fL?#*@^Ybr;Z-K^BuFsj9WOiKC+02hd)WbRl0@R^!AIWxQljf)4Q@Zq ze(8tyeyPb8J5vh5%HvZ`ykc*C>_Xhq*VuQwphbAA2wTGYQWEC<%thS2%j=BE@fn~! zMbHf?QIPtxW z4 zrj}up>=7A%Xez@f+x`lMG2Zb`ogCsj_BT?dBDM|tu%)e$`q-_4b&n&TeOXcLm#c_k z#f5|w5pN_IvNz_r!-@9`JD6Q~BFX;7XyVAbd}MnfZUg7L4MEz%66C1CZrkCOM|f56 zcEOuzbDaI#jqp?_-Yp_Lu#@jCJNo{c7-R9Np`za<>s{msoWT67Z&RB}{f=&5!gmrL z-#-yKis9`@;7Pk34X*}Xd)$uRockuy_9wdWdr6pML)fh7|J=CxZQU;<-mWwlg1?fm zJ!!&3p3Q{qO^`=;yWIHF-N++lt%aA{uRgX-80gA))mC`p_mT4$l(rI{xL)oHZ+ZXv z#_vem<%hQ{g*O^rCA_d;^GJT<;VpsJO&H`i&ETy0q)A>;UUyfHY1|GJJ3YmfvxxAq zgm-qs$HEsql)xXCfMr3J^9|9`=x%TA6P@WVS|&~ocN$@fy4UfnWIFbGdUZVVk@FpbiB)`G%#=~162_?T9 zn(~u5LJw@LhOw_iV_Ta}iPxtyAC1oulJ?z=_tVc2O6~Q?B=BYi8EX*M^T?s#nRm2s zo>Dpr`PP9~(!M@6h{4QrAy(+vTcUjS_ihr`BagIjS#u3#lrrZPqn9rAu|LXq9X>T3 zX6oIH=UN!9Ckozp@J4s9k9{sWJSQz4<5=QS(_G)eblLuXQ5ARxdeq0}gY7v6yp(os zToG^FG&|x*J?|}+^HrxW^t5+mn8ufBr8_AiJb(?YIkGlg4L*H&)n&Lh%bv zO>h(2X+I-Rmi?Xj#`7WR-%8<4fOpWq)7;Kd>#(8)n<$p{xeTmA-aYsW-0}!-jo`x* zw>(0(!W$1SaUHS;-Z*%L5{XCR)xnD#UmqKyZI-=`jIhv|@DT556JB$94|%Uk%03pX zsSmdeRwY;q9%&n_17KA?SsyzteHl~hq-)xCMfsSbt75vN@~ZmS2dP+cXQ1iD8e4S2 zGMkai*7X$97C%QlrMHcgy?FDjv~sxToYi2he4h91rOM&-x2a_crNyE=Qg6BZTlhlT zV3mTk<3;+~^kqzy>%Ze6dViQNQ%6cewcb-h zQ!`HG(y;yYYrfsi*PHnYwZV=pXF7aq+29O_4PAq?5xz$bk1vd0iJ!9`V=*7Lf+s?5 zw$DHKlJ$iCY6|Xj)+Be6$${u>2IC+Pc8EzsHtY*uWpl_5COgH(bZ2Xsvm5(FMxy@> zHm5xZh#-h#Tx7ox!;uOU*<=P--WDU9)5x9phvbP~$9Jbc;t|Txw&O7VWpmFaA_*>oJjF*!O58-RXdZ0=#W5H~!Hsah za()LOwd!z;NA2uIK}ad@93Tlmq(`TeMJfOf+H;DJ0F)X@i3Ag9iYBE)CQ^%qlF&9s za&|dD14RnsYTJk?y;CaC94KS2ofWwuCLja@L&k`VM1tvJQ2>CELBx``ipU#cCfON~ zhx12hV`Tx^=uUJv{KWr>p{;ZSDGrTd~A~>A{F%y8g+<88UL_dl-)_uSoHttKm;ca zz~n)R`4dyR)($Wh*}@WX89Z_p8AKK6S9&_*9y?r$MTj&iB%z;xG1~FZbP9wW0z&Dq zJ87uoB2fhn)!{PEcOs&^@lI~^s}$`j`%mg*79UC|>OnWsHIor8dOlnABb;7OwEhYo zDwpnr1pHA%a&i7hF~PQ0(t(9wwoQ;J5wQ$Fg$J75x@W`{1V-~env;~qz{Ctu!V6BJ zsT&mQ+^EF`bSR;Az#W1jyv z8K3V-i^uqybjE5HwlLuD2Ses(^6u{O%j;uj3Ff6>HjeqsA(*EpofXQJo+9?J?A?II ztEa_+Bk%g2`Y3yHf^*XUz%h2FgRylsf`X1&S#RH2_JqMnx6VqQ)127Cy3pP$SO8w$ zQ}wZPMXrOz>F`qKpe@{6B9_#tymP#kb;${WxBXD?jE~dLLW*tu59auN&+7Wvi(q@6 z0q?)*pH25P>bG&GfHRdf&MLuK{J(G}r^S)-tplePoN6iGG;o^hKUH6UXu-s6edV$s zuVjt$2f_ROq2L*H|4m=x!1KM#yWo-4a|(F>RbR8ymQ(C?2Uonxz=`4h-(@sDO(&D! z^!OFi-dFgI0?Ky?IQ!D!$R6(ma3ZXe{)M{H968^UvQFcu(T7uHno8I*!Wcg6M|cb1RlmU%p>|{!UAc+ME<>mMFori3ViiC;r}d1rAN+fCgg{BzpAlcYWPOa-f8i*t@FdD~~|&bv@& z$M;z6`X}B3;{Ag(a%ay#c!ZoF1s6S56Mlg3cpdhJw*%gOc*jZ_rw?u3h6x(V$9Ep% z0(%@j*{4eBZ=3GVnBOGsB3 z=OXh`Cy$i9mK2%I0cq=&STb&m9Sh!8WKM4-yt?4zui&!W_@f1Zl~>^YnPlC z%whu(IfAwCif<%dWLv#+XWy})76i-_Ty)sgK<*^6?DgGX~!D?e(!ArItNuUzn4+rn<0qy`(Nm_$-w4JJ=hR z4k(>`N#|$gzO-{{l8Sxq0;}Z1rtv{+s21J`c=@;mpHm&X9YlVMEx#(=Xy?C{4!lgp3(?8CXny>+Mk%I~2Z_^3YiOW7ybS+)W7tXXNkbZ@{?{cbYm&wfAx9+Pl>K0&sfo z<~O_2@0q8b3v6wn4cgzO+6mUMPwQj-Q|&N*4x4n3^Qv?r$=0WRC#7#G=THA`x?jV6 zpG&0eN!^zaHi@v`|uM(?9KZ`c0|# zX>#!b>da7#uWb+UL?;u8yYb8V*hRP{F3n^bXRk7}V_g^74%Ds2({6IVLe~~H`N)uT z_SCG8n%%9d<-I`uabyB_yVee9>w-d7Kf%julq+kM1TGhy7`sMD;Hrkc*Z zxUFD~sjZJe_@0h~WzR$GdvOV`T%}^fo(5lt4Byws#B}5lUJ1Mr@I+4@mfb;RGE$H176xk-Z*qo*K|iUWqeHS%PvjdaTMEjHx8_- zdfJD`o@94TXX>J_*~HsPJWSqx#AfC9ws!oFw4$GC;&~eCV~ZtaqJ9$BdUKN%BzdZf zSig`iPux6$l?!h&ys5$f3!TYWz|~OaU6M{)oos6iH@&~3vyr4*Lpu8&RiX^&cba?O z^W0<+xPd)6nM0N$*Fvy%fo02xU*uZ`FQOWn-N&@cPgpKtbBLE@S9bYbySg$VE9}ZH z^Tm{(bU&7K$UIG6-GFlhp8~?l2($a|#`3hdMqQlF28zHL2aZoSICBbcob}9kZl_nF zonBAA@G#QmF#@ZFq!~<_n{hYQr?X$zbgph(n>>GV=7C#DyO6YWp>bVE{W*)7gjtL9 z-HHKg;~~VAdgv>Io561!Nje_k6~n6|eVivc9SyI_Y+g?iHj%JZgdK%j%Eii!D|(LI z%_gkOYKWaFVJ-9xDOG6O>pId^lJ1@Vk}maiw<3ET=|*|^%`8dBBl1PYGmn91Z}8go zU@x)kvi2pcl(2j|wp)I96X2N%ywUK+!%OT7$HN;3&yx^uii?-XD}y&SCEgNv@|%5$ zdC2eAjfUq+;Ck>G4Q6$WyLc$f!>NSR4&B+qehYBFC%G-j?*i_n4o)H5(F@Bx z?hO~Ca zhICtSOP=-|?NYb9B7$HKB~Grd!Fjh8aazLuWdgR{{z=!DbaorE+n21ouu(o^u}cQA zSiRW6V`$L9b>=kj`Firabozgrm+m01os{E7UU=NR%xlrz5W+?;$~#mfkX zBBVW#7TOalXZpVxjJ{yXZ)Dbn9lP~pIC3|&b9SHYJY>D#=yM(N4Mo0Aq?Jc>Tmx?e zyd0b3^zD1$je=+QXJFWOIo9{$The@Z)ta{K0%i!Y_tD zMi`BHh|g`^efrZ9dO^%jbUK}M<4M=fO*f4fU`d{mR|R1c2$M1iro0VE(p148m%^7Q z5^pPEV+f1OC%irIqe8czsiN>)`cH;nl$Fk;2;xuP}wDCQ{ESyj*yBDZJkB za#MK2;6+k+qu>Qnc;n#tQh4(Frk)huYO37`3v@uk~R@Uks>7<vZS*R;El6I=2%AV);=E-Iyb18)Wt4Go33fdc*`@7!-s)xJIN!FS zuHmgCd_3VDC47Su?(A4N;ky#US2qv$U`LX^gQS1V38%#(EexJmOlK>33DJ68p?4c< zx8cm7V&!$F{?`1-kT1KdtF`~_?&=Y3Zt1S48^^xcl{eOB-PBcmZJ7V=qQ5bYQ|ciz zva-9{YWnZ(uD&vT*K}7iJ^p9Ash2$FK9)QR`8`n27)^Z)pvmrOS`IPgPh0C3;Cb!qN+lYi}! zE1lJraIm_wS{^Z1bkWnY{nr+%=d*n~yQrG%Bi43N6*)dQPvrPlcTu0@m|F|=r#Vdf z<{T0Js*9SL8$MW|Zp|I3)JM7D`JL5Qxy+j0ZWn&LK<#PAChdz+Da!UJD*Qeg-qlI% zYad=wpz7Px%f6WxCEw5Tij=yegOu;l4(t?t(jiKb>N>z()-g)Cp6`hBtBz3$Ju{!2 zm*qzfbW+dfcUS7;{OIeQ)WQ6&jJ5^QCp)PX1^Z}L6@_MHp}t36ez~sD+*qjB%kShq z-_`qSS6$r|?x$VNFT3i!T^Vv_bu;hnrtj=#KGaQDbd&dBtm|&R++DBle!Nmw_b_Mo z(9?Th8UJ!@qx^uOKR2f7=)7#TRC}+@R-3i&-x2k#_U(zNMTYN_h}vNIuaBs&4FBt4 zb*Jgu9L5&1Hbm4bruVk6K4AJ^3#&PvoX5lJMUU^%uzJUn^)Lt?@BFZyYx(v^)C-nx zJ{-$GJFLpQ{=FgfjMscWq&Ir4-68e1*S9aCVqWjwh$_!89|-GZ8RlJK{Yb{yj7B~Y z?RFnJd&L(;zMbMM%ZvhhUnb6NnNd>j6=%6WIxnJD_;G&dkAhY!&dRJP1$r(E=f12c zrJ5eVxiS!?Xs?L#`#_Y^lm&6F2}U0at8L=EE)=B{<)MB`y&Q@n{`;Y6X!FCcc}+xr z9A-vzSH!$8qL)NyxX(q*7b1FXgfVkl#QR=E?}$*dQ?tz(*_a@$d~vqqF``kAFu{t?>A(gQ~`3t_kX|J=QZpb**K764EzY=6fMs zVR^TO^kbI!T1Y=(^`$6Q_H!ZijyJq8s6O?cs?>^%?1w|@K417h0rj|#_4-Yjwg95r zw=<(i@r5`S`=bc)xajs{e-ud$igRgJ6miyyn!n77BGZfjmRT8y9tf)E#QA<8`d(1| zC-4ATTof|z3+cOf)reA0h0W)}dQ}+ve?M$qAJJcg%^M>+7B+8>=xZW{agEWBjaJ`~ z;2S-#+NX9H)_fmUdD2rp^|*P4QrCF0@AIj8PxwC>YPNNzQtw#VOML20Z}{sBwaa^= zQuk#&W&@e)H7#R;Jo$ zgr3e+wT8JYQy(-$=9@gxs!a8Ohr+(?iIV6G4^ysttmqS&>M0BEr&bh@m<9JSZ}ja< z^|BZ4cit$V^D^MlC&GO@1MVzeluQ=O#^M{k=*mp>sSl&OB{NE<%Q8D-_?hOWO#Nym za_`GDzsuBLW=7&2hX{kZ-~^y8pfuG>8vRNHjcJ3*``v@ED@H6jlN)sx0s`lF!Q z={f4(LABV5;@)kU6+!*2WiAZrIo^pM1l3I$-bz9<2EQLv6~4FiV(iKv#q*xuPw+Ka z{hke~Ras_PQ2#s2oEg-gXQ9+b0+R8I^7f&x0#Wjv89Z63SA*v3LA^P66wNDW-Wt-^ zhs=2)JttI5Sjemi>CK^}G7Q(ljtZ?e)K$438R{k-e8x~8YV%n`f2>JzuMvIGP|p~w z)3zDrc0<2yU@morIm6U3qX{ThzRaWV^_&#l-A!HUUDZw9pndmsQ#-Y9OD}b&k-e|G zT5h&`t-G4$v0m(@w^-IY-PATqmJ8dwzH7UwyE1%LJ=J>|;ZM8M)8stXT|Js{t18RwU%_aTTU=MD9&cxEDAb$Ud2i{e-)-mJUZ_87XU*-Z>)Tn^b=5PXRzsow zGHSk2s1HP!A!S8gbW<<&OkUvCUTS?F%a*V5qEGZxb2bt4w`LI{!i%wq==lA(hG+S1Hb4@`M^==dA zb)BN=tFVd*g1-pDm&w>=`2I%K5;JU5=B!hyWrf_MGE?T7tH7W!YHME zwlF|xUoN~{snuQ0PrB-DUCsBp>bJXM5o$pXYhiDFUk`IhPyJ{Qv-U{6s)u)WPyI>{ ztGuUvtB19qr~aUaHNB_)q{q34*VCHWTff-zCiGF$%PQ-wKR?o(+FS2GlAN6pP}94o zSo%Y2y3W}+P`#q9S%XxWY1IuVV~6KTyr_2JarIp75Uf zDseJ=R}WO5XJoJItG@ABa|ft{zHOx1;+Isr{ezUcJu7Q(5$(^nyNGv9WIxhZ?GE_A z@274H`rqlN9tw7Pq#yli-}m~eS3;ES<#6=vzVxW4EA?O`_`xv@Orf`r(X+DsZyuwb z$@Z^0Ms3ROwBQ)EHs{!v`m6VjIOY3e)aqO_)=zKBHJ|FQ-^{fT>_55YcLQ`)JM+r{ zn4NFiKy^dZ|HT0HK-9l|fZ7x_A0D6=wYNSjQcK%s-8M+g$n(t~q@K+4JvTsY&KvyV zAoW^@f_sWoSx5if{nf)A{oJs9tE0K9uio9!T-jHD+3_Oce4Sr#-vD)2f%#~E^`C-* zZwILdJB1z?q_=j8%mA(PEBfleYHpz!8>kl*nvV|Bj~1Fw4bs(x=3RsIJB5XW&gyDz z>8o$+YQEf8KhV`&G(bPq)x2eZ{=BRC#sFR4)!Z;Zmvu8=7@!~M7FgC_?dX=xjokNp zSl9REmBj2#yxKGH#t`*(Pnyc~UeWIds>Qtm)Zx-z*vj@^QL63BUUbp-9vMX~&xi$m zc4U+iU)>w$qrIaPd%ZZn?Hxr+bNb+XwojB=t?3h>K6mv2c-~Rbw~kTw9!1!jM@856 zSD%UVj-#WL{?Vg}u;b_`%KGZ)0F}{jbO70|?>irRyQ9c_Vt{_4$b6?rzfxqrUZh_w zdKLS)eW3Z;Kz-*x#=n0LG`||CKOguvM)pDG7lZW2gJ|UQ2b(Vp(RU3tHw@7$2b<3f z(d!4B_YBc*4L0u>qIVBAZyKV%9c(TgqHh>tJ~l+p9kLeKO~;x~AE)b%HJ?9D&pysv zahzU!ocZ8!`tIX;H#VGD`LFda)BvRhwBKT>bF(*E>Q;T^dP|iVM^stredCO6mRe^1 zh*^S}i*ts@|AZy8lZP$6-E#u7dMir8hpo%#ti0w@ufE3{X+)RyG+h5!UT|_;`>BR1 z?b)E!d~NR2`Yz4IAH76V88tde*goAA)f(msLoYVW2Mv9Q}?&-BGKk)@ zO4HAY&g!W4<^*2uplWjhOY_w9BLes2sj?$5nKeg5DbDsI0u*8Q5dq}*`UuQtQEv3L zs9Kpzj9s}=a{gYN54MYv{hD_4v7fh#lGn88kD0SZ&6lEjZS+b?-rii(UO(3!6{}Sp z%(Wf#>JD_Dw{(&*SAK#@shd8!$C3Vrv?|V8pw)$e8@2j}dA-(CH521i znr}br)w-!RW94OrzQH&n{4MhcZQT-5YYpqukb23ug)DcN(Ul=J-Q!yxQp-L5{{+>` zo*?ttdQWskNIh%$nN?il?e;=YZSh*GnU8pV%u{D)_`VCO)fs+fB{doTMM2e&VSW?P zbA9IHLA}Ul-V)Sr`OLXNz1wGA$5h8>HUxB4X5h1sT9+9>hRrgYo$8m&Z;>hNOa3Sl z?C>)n&(D&q@0Z!^TUpVyLG`&f?+irA_%ZuUi-9P)e-n_QWmd?X8`85wLs@Kv%nw3( zYsh>%q~8jm8ueLNRtX2g=AwwcA!6PV(Q^~#wB>)(f4)tJs{^W1|52%%jqKVib)Rt| zpk|a`lziNbTpv&`n%6V0kpwpJJy z;@oJ4V83I+nCrO!XT8UqZRx2N8x8ka=A)K=z=||BHsEHpac4(BwI!Ej2 zy0`Ua&>CWG30fz#-xRb)2iF9x7j$TO(AuJp+a0u)n@m@&=ghtj!?A*U0@fSeP))#k zC?oPxzHg5_fOVsP$l8FlDC;*X1J=PT=7Ea>(KmwD%E0|5J#{$pU{rq= zuJJO*j#{rq)#j-6ZdAV+Masr8eCkMN43E>sF+8UIBQx*GRAnpDz5F^|D9* z+FI+;6Rf8^`d`+g9(|*>9`NY9wRM+AQ{4CyD{qGa7QSrwI}J$sZWun<7_PUulMu(0f|Ft^>H=(*u!^aQ|=mysXuA z`T`Lcf8ahH{an-M$fOs4HZ6&Dr}j4(Y6YtYw_HQ?k+XF0BaK>y)24OcW34~ZNb?_U zl^bfYVJ$QC5?M+(DePo|H(9ar;M3!yi2BqJjV$nV`ZS^*m3_Ag>*(!lkXUqjGrV0t zh^R`hj2JsJ`s|LduB#yB1OEQ+N7P$>`6-#TfxNdP>g~X2w$p+oA4k-Gf~Cv^LPx(F zQB%V|qX!D-y%kaKh3_FUdFR|}9}9XIvw}T0X84(G!Zq89JriJEH#L|uHBYS!W^Zq=UJOeAvOW}? z)1KY73m;;5&3+M1P0n5Vkv#R?5uEg`$qnMHZD-X*)wR*!wDx*QG_afa(ZI*;)v9RV zgZ8RAns-BcwbOR*jRtC?>gl}TraZkqFR3=rN4#%2`g_FIoumu{bT`-LBe$CRRxQ8k z`l@Ly_Nco()*~K$zb6UA(M8u2bME%Ad0XLOyKC439^RpbbvzAS1{u0D7>#Ud&V~y<}HSv+q8&|mCx4tT77irpruX^euvyTwANxv%6!P8 zJ)QKf#ZR4@_gc)U%%?29-XM#EMwHm|%_3~vjFRRp6NS$5M4zX7SQakTQCw@K z(C|Zw@?6pV5v^|5>^6w5%Cw%PU8~6c$g3XK!D})ot@*ZB|3?paG($aYWPjkL=>$La zs(Vaxi&x)gUIzbu&-h0&RJmo|pP`po=Hd+fh;8`tSLea?UqkFdRy~fZb!RHKpcJKj1U+KNy z(6jXs_ZoVkk$I1y?=p^zCt%NC>u>cvX4Z@&^joHPN4DN$dU2O~vgRG3U-fvu&C&09 zytsFH&c+t4tm||1tCmE++Uwn#t#9;7^o8CJu*>fI;`drgkM!SBUA-#?G|6|7*h^;=oqmD&2!EHCaavVMnc1iUxq=&gZES@8$6 z9?a4EgWg@)`s$Du_wGxAF^ti$3oREGucp1~IkhwRc z-w&C)Li)oH3S?dJbr=(Z#Tm4n)(4_Jo9kV_pzyOGZ``6XtbSnI@HNGOY5_|S8ILF@l8R5 zNgFZqbxw98*X}#JdFd2R%3-JUd~>GOf6lC6j^SOX_0_s36ItqBGl58GC-k@fpQIU} zkLu=KuJsw_ZCYPq&ewW!CO!Og%|t?9FRQ7Sw0Eo48=E?IyN}D(fsWo%-QPP#52gc- z>ySRCAn&(ou#E39-TU%i&hl`I6TZQt9x~=o4^NwZ+^?F^86I`e3^2US@JzPj`uhbL zA&##hlI>sNcP9*$#;jdhEtM6(`)01VpYr6-fPCo5zZUYiRcQ+M_RQn2hJ51>iEnxq z_3~Vn9e+dM_?MZ;EeqzpzFn*B!Mqtew7Mk}`T*aO5V$p=Tyd`n`=*if`*5^|y|0@i zJ^{Kr((w%v-{ce+gd%_ zA^#i5Cmr&?gv{%hzZX)~F)A_N?3lkBUqi?I4!`-I&DJ=Mo|E%NW^v(DH@CTsfr zMlxB_KmTO}d9}Zj&CNym>+n8Tl)oCXyD0x@$jt-tmypGC1M(ji=79X=kg|dKOCe7U z%)bxv`M~_UAWsg;{S@pCgB~W|?*<3HAlcnR+Lse_+p#$hquiy(GPAw?xX6wVwR-Tl z;5CS_a%jg}iLm)cIkSoI;g8rZ+i-la2KQ6Lj=G0GI~4Y z>Csujd~r1P_1)-Pac?*~_a;<+%daen@cFOo2(`Z=!m@Mh2=|Q1d4pq3#8>&bP(R=D>}{~%5{^orh)(AuzD(ajRZn z?8EWMZJMc*+JCz~`)j-}-k~}6n_I5KH{!dqoI!x$3 zX8aF6qPuQ@u2`;*e+fE!h4y_0y=8@t&Vs(VLf>Qv@}8CYVx|d?>tBd(?-Tm?RRr&Q zQU`ZIKYm7ceG>Y@Dt-J~=$Fsx;5*R8&*^UOLmybJ3+6&!TdjZd5On(*eab!1yVvUV z=>5}my7vma_r9nvy8~MNlK#z2;$N?ssC~R%N5%JUwVqrFee-1*BY1%^KP#t% zUs}01*Lrhr3#vOaa&HZ)X}%Ed`Eo4yqHmqXJv}J0RUV zeSY+!tSyFmQu{U;vYWHYU^j;uvK^MM7+UxQstm4KmtyyZII9dM;F31JbrJZM#;eD{ zE0?uA1>}?4;L*GF4XErZPXKp=tmVrr>t>6cT#NOPZ{ZRAxeRRixVaD*`Or9#W#ct$s zZ9OZ8q0QEO>{oU?Cd@4RC+ExFjJ1SLUt9K|-#o6YDP^I*REJ}Rep-JiZj&7<^_Xd` zF?E&MJdNy|6f0F6y3x>QHjrSWVNnlTX%Y0q@S5AnvRi)K4+N#!i zO>^0)m(E#NsXo}%MbWF&RZN+ruJW@ct6uOfh)!0Mg(rJYKW;a}U~{TnOzZnK^QZW{ zpgdc9JXV%Qu=r!ww_^|4a}BjcGvAl}9FJuMlHyS>ofUhcLqaz(hbrZqTU+e0EETEs z^5*g)hj)Yatxw#XB2)4kczVtkmYM&j>+VRIi(?y``M~yU3Yw0w#0I3 z4ZYFG*>C9gjBZIAW26lzrr6oR!K!l~Nz1(3wEWtaxHg4nW##C|A@Dp|**e@5PvrT( z=l?YDe;W8d4g8-5{{O3i((8-u!WGYS=tP%RxOB5i)hs8xC{EpUc4Geh^QDvG&LleV zBR0@@3Lh!9>C}G1ZMw##wugVdT~54FL!9uPF5U0aHOD&qc>M0w$@zs`|4ui*c)UI9 zop}3G_$6+B@pvuKsV=VHjW97K9fP$xi%;ZZM}C=|+|6gd;xLJaS&x!96+<1r%q;AK z%^x{_%Z*bw%<+5iOPrz;9DfFGMt)WH6UXnv-IGu8X^vmyVh2R2a~!{5GaXQc7d!qJ z`;3rKTL#oB`UEEL`<92j$!)=V)*~MignDn%^-nzTEEY*^p*5dYd zab?dd@o6n?KNpu%&!nfdxC33>+$7Z2_h-ksxb4~)cbJPCZDZUMUEKC8+KU0jatlb+V%j&X7Moo8d(Kstc%N@S<=&5+)@{pt29YZ zYjH1faoHkEdRmM77Z0k?unqd z1-CWWH@mn!(%`1B4$B)E?aX&%O_KPuR^E$8I=Hm~rS7WZKnw_gIL zI9rSRxQpArjd7oLak2#Ca&dpu#<&G8E_bw&p4RH2kBiIKi|jsZ=TJv4t;HSc;&R-b^t2YY#Kq+R zI_YUG?id%B>oG}BYjJ1i$Qf)XrXSlSrxbM2S zBf%4_U2W8_f9>L)kp{OlGH3L4S{iQwX(n%LaPwWC_-+t%lXqg>p!J~uqu#Z7l^*cx4&=i;{Yx#9UPZd;!lj(2g>og21B4-;M7wmvuf zn~U4l=Z06hxarOfTcd{_?)tE;&kav zw~O1-x#16$`92pn-MQfp#gu|Ab#c?38@2{_xr>|b+^{vctK9WKx^u(U;6Coko9^7O zHMq~XxP>WJB$%ziUF+g@O@o`lIxO#c7dPFxVQb`l)x}MBZg^M%rbOQA;`T`4w^qM- zZvUI^+%P4p!}4}_anqd}9u`naQ~_>D=(Jz!D;V@8YIAH%y3j z*vNxd>1#}xnXPi z;BGE%x^u%Hssl-Pq>G#G-0+9?4T9Ux#ck_z!?Rs`XzO#sF7A4>tvO|Dy7ku9=Z1Y;J+$??;i)ceTb~NxIWBHnpBpZ8anqd}w#Lrxc5&t0F!5;( zrrx*U;?r8(Di>GI4HKW%;;waZ)14b8=5x624K8lFbHl^MN{qkN#Z7l^m>BPH z-S4}&zeq_a`fZJlKX-9|nFcq7by(h77k6|@s@BLVP#$;waCRHxX1ln*YGd327x$bt z#_jFmj%j1uAujH()8MwI?uNU#=cd6;VI7wDOc(dOlvJ&eRiMsuamThX?!_+dZ`v65 zG8gx^ZH)U57x#B*a7D*IRL|30+|o3-DXhct&USInPf67pSp{mLi+e#E<1TS=FKhw# zhw8V|#T}OhH-&Xr-X~n#i&9dxR=>+#+>2Yl{h@mJr@PMjeHz>p)?s;{apfJKlB%_O zc*({6LmT66b#X6AgPX!SEbmSi_tKP9KeWE$Fl$}h32}x?TdUtqF76-G;HIz+%e&ph z{ZmS+*6QKkF7BK*#@+AY&P{{c8krBexbxZ=*E+^o$(OY;ZrH`0-^RF67x%_C#_i z7H7CraO0npphNPW>Ehm=5<8ChL**Xh;@;85xEHv%jB%l#-&gxRYGm|Ht0hz*#kY|NmCg6Uk5r#Y7^7K~facbCQH4Dh5du@|A>edsGP% zNm2}vN;FXkVUUD;B}twK>6@=2BqaLpb@ylG%yQ2;_u=gIeZ78v`_*loz3*P@eb(BK z=iGbGJQ%Uv8(_CMV!I<@_o0aGj)&ccBepvUc4tIv_W{^_Bx1X>VfWF9?Jj`bnMv%5 zqO`Iv!0uy0i^m1YOwwzxJ4+~MYxix~o$X^+6sMehA9m*m4L)B{oO1S4*nM1Ru-z)6 zJk{(v*qtjB*e=OT(ni>QLMXFcQJix27ubDLXt3Q(<4`Hz?o;Ra*v&K!yTfitfL-}r zP*F8$wjS)x7w>W$GCkkJVfU#3yP2GC3)p?y$8M(W)&X`G_}I-f4&7mQVSwFC;?Ng% z7x~x~#VKb8!tOIdBisIPE$l8%Vpo2rM^p*S4ujoiMJ+yGQJiviH0(YnG}vyY{b30G zEijXwkJ#>=INvvt*cC--W$%IAH-#3*K@_K)Er#8`N}|g~?U0TTxWx^Ul=n$FN%|V!P{LHz#7dn_#zc#CEsBu3UGrjqeWFts3$9 zRy*46PpU<1cMsUD9 z?A@@td%4oT+KA7a`-G_Gn|%^?b43ldM>1WTWa?emrMb(S*e=^lHzu25cTcZTbIf+V z=j$z_u@ThIa*nn0L#;IIrZOkjgWcL`+U4=*cg~GrcdsONIkx1#pT1DrnQaBTd+#i< z2OL+DnWWyZyN^)L~!Y^K8IIfSN=Zx1XJNyu9SgX1-tV1 z*_oavpTd{0o5ux^6xVF}+Gg0TA7EF!l~PuFzwR9iau1No35V_1_7W;8y>&?I<*&#xlG4%Ci`__hVg>->-5_`o+o&&pgg_8Y-hS( zC%Zv=id6UOWG9{U&wkxT>;ISidRRZpWWSzDpUY&wPIh_x`HhW#_UpF){$Jm(Q(s7B z&;EaHzn9=2}-+}+LU;k@;r}$=+n%ess2MJ}eS72Tw>E+#Ln`~&R4Z8=6nq_S3Z+bp4X4O*)65>z7RYXTSaz z*Du+eZz`WRaGcZO_+7uSt+49}j;EBVT)!~GE5mp}*Dqc>$&Q0;r*i$0%x2i!l=qrBtq8 zlG&xQpz{s7e(~B1vXSiEgFbIyyUFyz%Koo>-oPPW$tDvJCpXf$ehLv}C~b3)_`475lEPUyjE4ULsC{ z&ruYooIM40`w0!Qn@u_&c9Z>XpU;_PI-LHnD}T42j*Vn>2gB}V;>}FX(Q9HH>_+{& z{i(2Mxw#PEika+WT z*iH7mIX-8SWILVoDeUG5C9lm)>~4bHWZ#>Uw$rg+{e$Gq}OI9=i3W*lYMW_YdhWZ9RRyQ-H}8Wag599+%@HHr`FAVq?k`S`{g*OT z`@0=)$6M6jo6Cn?zwgau8s{FcE5A1<{TE>h&BkF@es3;YyHCJwo;U+(m-C{UZ*~>z z))zI{j+COBZ+08(Ci@)DYctjU#h|_LcP^8C4wsGHeAsQkAV{xG@m5ONZm@fZsGY6d zp|IP~$8IL~cF5F7*ge$8E}eHKX*%p4CX};{!wax0`;pgfrswQE)$>oX^IPF7Z4Nvlzk>~hup06Kr@H;1dpYwbj@SV`-Jn!eXi1#_ab6WVs1CVve}?z#aXIA9eHPw75#>!GckY+)em9h#0?GTH ze#no291O|(m#N6lge->SeaM^0Z-D#|lJ^r8TU);xK-PlfeL*AS&xSl1lGpdkke>*7 z6Xecy8vZ?n^2Z_b(0`U7zY=m8WPQB99{E2Ze}v@qZ`U^V{11Vw1Ig=HKJq;w+d(#f z{qvE(8S+XCublSuRgUR**&$%9h(T;65MEZRxPW>ss!iQzhQrATrrz`m+jB>f@IKq)pnunSMt6iF{y0lekcf#)_XS2529a5`{Xa} z;kcbMy>9vYDOv7Oh%@iwxE}dSOj*wFXD%(b6}Y@VWP8M{&zVT2<#qy>_mzwwZZ>Nm z*&!Q$PnLTIxV&HGdak+WfxB}b3^4ghFPf_|ov(uYy$IZ$`)hD{>}JX&GeO+#xQ^Pn zZwHtCCEZNfLEL#5zjQr7^@hdmJmQ)=5OL<~47eMk>rP_RxzIHhw=+xX5BcU5l!E*n z0xn;_upQDNZZ;{1I|5w3E@BS%tK_;|D_ADiwc~da`W0Vqu_bT&CfDbh{xZ3q<=zc{ z={k<;#nG=^`}+vEe0|7g&)jU*p&)Deo0U6_x^4t-4e@f z)XuKA@;*161N)q=Wv(A|y>J4!hjV2}*W51PHWpkOyX-IDdlpqfvqAoz3vLr(#mmij zzDnA$Z2MLN_XxwKYE#g!=za(LOM80S-^e|-DGE$M{?-BaNMXTs`yK+W+@rbXHUsx) zWq&(?EBlVOU%BYdXM=mJ@YlIEecw{FTqo@y^fWFTea4$;yMcZ=Y({eR}qZH+lUfrd%hzb^VTmxNE_c z&)}i)%RXkp^g9=_O81|iL7eIL@ZLoJdb!cDE%z003&5G?S$~E)xqHChw(zmo6K9^EIo|2|9MqrJ!(WOv+2{KVGS0NWN;d^@e+0L^ zF-ly%4)v~sRGvu+;#NnTI~c=c-`k&E#`!pKI|_%0N#`N&FNtayWbHUAd53ybEY?X_ z;Q5N$HCndi=E2`n1ebgzb~Y(_zp&hVa61bC$2r}xBg`bpTJGbB^Qoc+bB`0{*=H^H zB=~!pFet}w@|X!FkqsJ0XMx*Q=(t|@F9rAX6u5G4FI4`P4f6L|aJvaD?|hYM-wNW6 z1@{cWmF=6ZuVgNWdmp%G3U0FYO_v?Soel0;g6oZQCVe@~-v!`yr?{Ax_j4TYx*$#~ zrEHMDV{qTBhp;5uHxr+OxG%!ra}1Yk^SYm`edRqaajJjI265j9x2Mob#yv>X3Cjj? zH-dYvG2-=?)<19i(tGqu$LAn!)eh~9wOH&t^Gb!Aj?Y2dgTU=2xXI$2j<4iP5VsY$ zy;I<(<7*hVC%AnC*LC||2k!YPa?|lSD9)3?y?_GaNv_-XA#e)~GnM|FPTvah_X%(> zROY?_?nRy$)1m7)zYgxjf=lZH#hqX2#8;RSS-YRS9qUnF@viIjcNP4-1iooq4}Jx1 zKV|Mu;9hFD70s&z*ZZ#5{mLEfdemQVUAJ#-a4$og7c2RD5V)5s`+F?71C+V#!M(z8 zy~%a^o&oNaUZ^>C&Fus3Rm$AUz#XK_y%yZ7mAN;A`!8kgt>9jx%q;?Uurl`naIZC7 zS{L|x6t2h7TyTdNChaY>*5BvBy-u0?Cb&ZlS2NCQ!M$GD-*3RZL7BS^+#3Z~?sMp~ z$#hfD^+K&qcAqm$7|fxvRk)t<23woX040j|2BsW$p>!j#cKK4DL8(ZaZ+tD|1f) z_cmp2S8yjNbI$_zc4cl)aPLs&UJmY^hD&Q5e}3e8JsJjXkuvuVa3?Bri^081nfnyD zcPn#y_OSb$Nrvl9uKU$X@b?}s)Ev9!z5(uJW$tQl?^Wi00qzuKZo@NeznUtzuCI@3 zfqTC)_dCRSnlg6_xYL!n+rWLma5eAeR651>s|S_2HNY)a=I#UTLxSsao{Uwl5IY3i zhZVW>J>(<6ouSM<9^6L^*PC3%nfz@B?xS9)Id;u`y?eU^ai%i&32+}%=5|M%X9=$B z_2>d{XA5q!&-ZB_O(zB2zv>6>9AVIPzq$h4$CbI)fjd{3I||$-hk_)*Oa+;gS$+bTL|v!%G_R9f0qlc>+8WU(68PwT>4(n5`0g!3i8CK>p<_z zWK&8(*MpnEebZR-a$R4CR>1Gs-%{r83GNEPb>6-ncD;0HOkxz!Tms)dnLFZ zfx8_2*<>9h`#YfP!Ts1!Xui_ojsf=*a96-zUT>p!+WLDhxSuL>=YU%#9HaS))_!`? zJ>lq*_4iqDzYvCL?-4zdAeQ?&xL*mb+~;I+4ng~?Rp71@T#7CAE#}d2G|Bq=8Mt2y zqjEo)2|vi+P2jE<+-fFIZA|^k>o>4}kl#;Cio*juG#rnhlyK9|m`;FvjZ;tviQ^_p-~{^>;3~ zzX)TrCJ?iMD9=7?xzB_9t1w7R@;RH7e2uo;m%;r_07xgfo~W31)^eAFyG`hO_Z7rH zR=l5i)^a}r_jh5)+pn66_p-}c?ib*0H^#^>zMqqw?I3N-T@UUbK~*Dt&vG|``=_w& zx?lYU?he6qm$m*@KCPWa7zfEm-pBI1LHn#|ljYU|m*!GUZXUR1D_xH3-M7=8md;7O z!r~CLE*u4Jj^NVx_42|PslRXId@{J^tCR_UR^mPb%~yQA!2Hy0+nPcCb^^DGGWQH{ zs|qgpDE&26(n>-87J^$XgnNJ?M#;S#-0I5Q!Qk$q%)J@hU6r|G!L6apy$jskl)2Nu zt*OkN3GVL7+{NJT2`>Nr6nUS)yuEW>NOkfEnm676x0W)u1l-z!>s<%EzIu zWpMXW=I++j?sN7QT-WW}2;6;?xgEf*Be=Bgo1${Bu=Y&teY@W{58Qo~x$mK0?I*aj zzv6YD{LUl=_2+fq?k~9B{RVOQl@33MyA|BJ%G_#b-+F>u)i}m+=KUo5Ofr=eL6D;mm=B=IMDCk(; z*9+=bW57K`aJ~IG87sIA?YlwTN5E~U%v}oZp@QqWeLn{GFlBC~)9t$7NN`Oy(U($b z$Movh@w+>?hbwdIg43rp#EG8?lCEF4~mfc z0=UNtuHXEej?Y2#~=3fy#jrLK_7UrXJw zqcyn43$Cm7Wo|!ko2ST4$LAn_Zv(f5;JRvGn(@i!Y2cn9xUS;N+$X_3QJK3G+?Imt zdi}kksU1hH3|A-F_Wcb0o&+g;GQhFyzXbh3qCjNZ>2MA zoC`$zN`I*t(peLT9prBl$-if2lp&x?w#OvSLV(I_iVv+-M%Zp?GeI_?E5O1H~tImIfCoDUsc6(wtFgb8-RN* zxLcIQ?}^}^r_4PY++N`Rs^ssL;PzJLjsv%k;nJG79sYXvu{4%>95qUL74*3-!#J7_ z?)l2x`QTol%zX{qLS^oU;9jWA-30DM%G?Tg4#vgG+`Yi{>7>dxA#e1@1LukZ8=ve zbMwG0B4<6xd%Z8-^3)1GOnN+M&WFo_++{V%v} zz|B+Qo`Uu**u%y->fg0-cWnTFV&;c16z4wRwg>mHB>u84w_B=`;>@~DV3(Mbt^&7% zGIu<jb=uS2PS&?}v>95jC42e%uz+@GVG zC;j^K_u%#cw{lXCATL2KF$S(ORRP{ zFYo-!x?v3YKD95|q|`D4(+ z_mhnyUKe@`ZqJCh9OvG!%iK%Ay;#}b0fMXLZ(nfxD*Jo6;A;7M4Y-#Gf4%Dh_vdu` zbWnf3S#a6ksJMRp`F3#oDf@e$;A;6h0o+TK{hcDXTK+x;Zh!b&i202A6|IHTFKDjz z_Gyz%DRH0jR<^t69Xm?Fy(|frKksHH?X4Pnjf5O08%NCj5ZucJSNfPP)9;j+`xCeW z1lMo;cJVWqq&&#qn&;T--+_V~)jmg_4*S~(+@aw1MZcmpC3ZH6`vuwP54+550q*sJ zOTWWqJwKVsIgu_U$vqw18w8hGRx9)W{kVO>y-{$Z-aku!M}a#`a9#U51KgVgH>&>Z z7w1Lb-XgeBUzf=^zYlI4+=1xt$@b5D?y2^&pm}2xxWmC6q{NN&wDZ*na0i3y>id&C zZ|no^NM-Jk;Et_j=O=!ijJJL1m_P4MwQZ>$wJ-OHp<__cmqj zcyK2ua~}ftc4h8jaPLs&z60)^%G~wf-VN?BjI*fMg}4~Mzk@qTaJ};ejeUM)I&VmB zjdSh%Tng?eoR@d~rE|z61+7Q>g8Lr0W5LbDzf{hR*M(!iT_d<&e|e5g#jdwbkiVyc z`=#Jgzak#RI7;8y-^;-rUfbTooPapj^zfLQsx+#;iMgY}9U-{%yn<9Y-g>@3yusYr z;Eohr+HZL6$>T8le(y8)HE>56F4>-xWE@d>CMl?2eF5%hW$qu~j#1_waGss7ZdK;C z1b3|A(zO_mBiH@82e{*u{k;j?@yguU;NB*D-Edzaw4_V+Sy?-pFw{@w!aBxUY2aPLv(E(Uk9GWT6@?^Wjh1nv}NZmr&SzPeAD zn-A_(Wo`#>?^ovb26vh=_bPCwD|6%EKA_CK3)}~jaB2Oe&&ksH?vq^iWS-Z-dEgcc zuIu&ab#NaNT=JFHq-+w|kcs{M0NfeiPQmqH(0%VzpG)Dr4?GQanfo2MPl8*F_xU~p z@3Eq4W9IGvcb?$7Zr?rn*!j5x+(#n5?&db0CF0x!+^4~vi}$1Qm$@Z^dm6Y4z+Hg% zgZdTQl6_U?gYGj70(YS@cQUwZ43}cN82(a!raX;d?$hQltwjEk4N9dV&U61q+?T=q z0C8T9^Rj1|{r}t-RtSIBfV)93U1WjQWEf?fm?y;nG-RmVbieoI$DIZ4X2JFP$mg97 z)3};Qe%zPA{UHfgu19QxZH7tjzD~yZV{m^ITxwe{H;j?&{UGko;BGNoVr@tJC$p1D z8ONyF2s=;kys^gxHvh9Sw=uXmd)Yo;1Lu{AZz<{EcTepEH&=;U2ySKg%UtSH+^2SXq3vRA5cN(~RD080#cTZ*RE8x~r=6(!rZDsBj zaQ6~in%`(Gj5=|D-lNdYldpnX7vm_$0D1h(JUJTN<$_CXn`wV4*T^En{c1Y6Z-CoCsXspp z?wf+kd*`TqW`Ea!y8_(9;IH5QIi0Z-G>(1&_ie#Vwtr5CDVlX>mi^uLLOWl*3vLso z{(LmJtCYE&!F^9~UC$fmfV*0m+ZWvTmAO}gyGEINGq@ipb0>hiR+&2$+z*wx^T7Q` znY$F+kCnOag8PXw_cL%mRpxF2_cLYgc5utU&5w9J;u$+C2HbDJZJxwmy7!(*3fgb92KT>$n{1y${B+JCh}#+5Zv|JbznR23h)ztZu|&v~}d1$KEH4F`9J z;L7%8eLwrj$|=sQC%F^BjqP1tldq4meV#elq0|lj#_*i6ng1j1ZQxcA{_^z^_3LbW z_Vc&+f5d$W+_uJF>H|GT*!eoDenoBTP28WK2e+NzQhYepUcGdVxi5QlnEN)k?FE-~ zh?`9c;;sX?gEIGba62k<_q^ElqfW})M&O>J%sm<0&dS`g!97)(I}+S3%G`P2o~F!Q z18!Gk?(g89uFTz|uN}YLl(~n3dxqe;UXLyY_e^E(6mZW{=DrSYcV+JP;GV6_J?IkK zpL-~CyMlX;;nLow_Xv9)uKV+FaC<8I`z*NU3NHE1d%H~cSV7l=--3IdGWWoKwmo|( zbGw1tTX5xdH|j& zl`{7^a0e-K{{!yT%G}*AxBdBFg6n!6JPq7yl(_@I9jwfq2=29l>w4e55Zobx>v~_e z2Hfie*R{XDfjd-iUGJ~*2H0_Qz2Lfz^Qqw8Ah@pmy#d@C1=qE|CEyNI=B@(wCc$+* zPgWRc`_;{Y>v|j=3GOY*+)KcX3$E+m|4s#WxZt{O-&Np_5M0;oTkQ(luSP0!+kiVt za9y|W4d9LzT-WntF}P!tx&H?DR%PxsaK|ch8((Sr^EhShdEky0T-WPhF}SxWbJu}8 zL7Cg=D%-xd3$E+=`3i9FQ0C49_fBQ*kKh&wuIv81_aNK869w1x{M-TDyOg=Z!M$6V z`#iXll(|2Fdyn8&7oThJXI4@MeZCR&xyBw>+kQ1!aCb?O8}wOA5ceo>?-g9v{kaFY zQy2qgv;?uRR(c8gZqf!y6(?cgZrr9y7qTExHHkd+^<~E8*hXA7`WW8 zT>HBN+*u;duG{zU!L~oo7F^fa&-vjpv!F4^3 zV%OS!^`zjs_V-9|=LxQBfBS)3BDk){?*wq?8?JZ#b;4U^?+8^@o+FZx^V{o4XcObqm>YBR++~)bg8PLs_kM7{6kONy^8#?c5?t5qy8_&G%G|HO{aTs( zJGkqWxwWsi^W=Y&xkrGzL7CeQ+;5b*y}|vjGWS|=zg6bm0q#a+?xWytQsyoJ_d8|o z8gRc?=6(CxH8tGWSeywFcNDl=mAMaq`-|YZ z-q$???yt(+e}ns*GIu?=+XOe+{VTry_1@!<*Sy|*(Dm=1;O+o-Fz%ZX<5;he43EhU zrJ=CP_v?1Q(aw|m>|^iO48!|;t)I=`X(J|cJ}Is9#+GZUbfRRp1_?%)JHNhRWRA!97%& zdq22`DRbw7+en$a1l+@wxhueJtjzr!+$PH0P2e7(%>5nQBf%YudD8XgbajT=b?_Kv z?s4Fr0PY0%n`35rUX#4*O40?ur;yeK(xp@+*56aXJyDr^5xA|uo#e>hDZ<~Yz>S03 zceriusQMMhxj*dk{%SP1!rJ*FjaKG%0e6ft zcQClODs!iUJ64&y6x?yj+zsH47hKo#)!sMT{(PI@x}G=Mf;&N(dj+_+3$E)p-wy5_ z%G^2N-YK}Q+jkYXMatZ5;NESx)TYz0FOc77pzq6440s(khoQ;4znUfX8`W;H<7gTD zos0K*Pq$yFb^i*<&XM;U2ZH-1xFz6{PB!;8{LY5CEx~|3korBtU9k>;hxj%qgNtv4yxASw3GIwuqD=Tvwfm=nH z+Y;QW%G|EtR#WB{4DOJaehMMukj0RtkY$juYi<2J$O6bh$T(y%WGQ4BWNZlZAqyZ2 zA>)w6kfo4ikg@Ba4_N?N2pNYghAf3FgNzM@K4bx8A!Hn~7_t~k%%56{l{PpfQE;&NpT1+3x60OQV2)`mEPmhS4>8B)Pq@c6A7Se^G{;pa zzs9~#d%jxcRrI0FA8L+km{&4-erfZEnPajM+hFtbUgG_4 zY@U86YnG5$?0cK9X%1=r&i&2icSpY9cbm^O`JU#r`9#a#!yJ>3gZ{AZ?`e+7-_jbL z%>VY>$zDOO&6BTmzJvC(d5YEH=GCp1&6|%G6Y(fH#OCST$p1k{+I$^zO#YNMv-#HM znC!)y+k9JdT+O@+TiARXykFMR=G&QkLcf*Go8gyekNC+pPy1eKpOpnR-wpNi+SvU5 zCSTpW%G%mI{Y|GL^BQ!KjYmCmJl?!kcC_!4@72sJf0WJBx>(h`N^Z6J1I;nxQ~;8(Eu)A4?8C7VCP^4#{4(dN$w69Fx73c{YENIZm90L_^8bnm}81Z*}*nXea$;Q8=Jg$Jms5w!amx+v&nno*~R3&@x1?N>QNf0LX7r) z?~b#)boW;2pP}Wg1&?CjHd)^1;8B~pO_ui+c+|(-Cd>N{JQ_1@ljZ#c9__}d&n$V_ zO@HOu>y2A)>`d>lNj_4XC;3QYH;HDZ>d@xc9a zC3tbea+~aUSO;FhIj2C&`_N4HlFpBc}FuZPshKLm3iHmSD@oxZ)INT=WXpMi0k;Ly}s{tyB+T|-srVD zs_|x{=K0@_zpgJ}elhRR6uQ7Xz*TTo*96|Tj$unFTf)f zy*4=J{Qw?~Jq=!kJM8*E^O**(7I-wDY4Dc3h5dx#xlMMxJp}%dZ*G(29S$D#7q`js zjslN9BXOH7uQ_Sy#e8V$o}(qxF{k8v!1# zx2}2jfk*Qv`M24ze-DGl>$~grdmKEPKQ;QxEnRK@r1_J0uCJ%hn{Ih`n=i5uZ;PY$ z=zdH7Bg);B;KDPZ{QSz@o?!Rd9K1DoVRq}7WGH)|@OO^cl zLz%aCFWWy~Q}S=uJ9T+ioNsx{l>DpMLzhd$XSDD%F#M|XbN@V31_$nmpL zbn(BPU&b}F{&9bC-9O)gf81YO^ZHD*{^hs`VL6*Np1+~LXx*=S;w9@JU2jqwu83-W zF6SF%tbg^6u{^E&bzgL}Jib4_+OdBPjB={nb#k@kCptpPMLQrc%Lcx zH%*!MI__V8uH@fS@K1~P!Y6h=|F!Xt)(6+u)63zX7Viu2s+%7%l7AZ_S`WNyEgkdv zuob-hz~lQ_#HO?{Dt?aLPt?5EuJ2!iw;A@Cww5YHv|o;KgkqZG zxc#30(9WOy`E51FyiSNGe|}rTF|Rv#rzu^pXn()_68NVz{vJBq&L>*q?`qHZi*9Tu zvt-BnQ1EE{xlNXLD|l{MWZm-aRPHa@-^ZNn@sGxY>-(P%fJfs&gEtdAt@Y?}@OV9P z9nbmT@p|N%w*)+1k8&NaN3VcK_jjqkxaKVfkMHlg=DiOd-`{o3`v^R~zw4U!1$cCS zSEK#D0gvzRy7uoo@aQ>F8vgwV9zBOjgSQntdd`&w?>F%1_f;Ca%2VwAjGoh_!P^}? zdJdQduMT+h%qR_BeelffB^6#H@aUOUu_GKiBnm?++e5hmibp z&AS@BJSE=s;MG^+-2&c0;JF^}CEg714prjK0`D;J zYCFEZeG*Sv4Q z-Ujga{*r6nci{2;CD*(y;PL$>*Su}u z@%<&&ydB_a?O&?jXUCt`{-ri}TKks+z|-2lGy+d+|8hKdTKkvw;A!n&x`U^+f4KlW zt^LaY@U-?X*MX$iA(RY{e|`uZj=2!(RJX_e!^|CyzdZC+E2JmmiHrgw4ZRBEbmZH`%z5m zIJ#fQ--mAIX+I6#R>YHHNxZs_{o4i}u{3y>!;Z?@g<@_2B~ z8^M1s#IzOpcvwX3MQ!g*+n2|_cnM<@q5@Nj^uh+me;EXS=$O*5i2d6PUN`u+LHs?Gu@Uk3^Y?0x z*!^w~@Fu`MuMb5L@nTpXYJ=Akyh(yLC1T!hh-Yu5cpd=%;&j8#lQ^E;U$yb}yp_=* zx8E_~4OilI1#g5BuRnMrm3TLTH%f^&8NAU-ym{b_QR2M@-ekk0F)&y>k9ufCpU?4l z_yD}=;JN;L8sFmko6G!vj_3D?=QzWo_8W-# zi|4aJ5zl9p9<~0ASK{pt-tCCzToKO&5y$fg@a|CJy@vi$gm^B2Kiqz$5&PE`{!ImM zi`c&mj<~;^4&MDryh8A%DeAk|2|UY9oXB>pKmDnH|1ts-i}_D_okA6L*btm@9^`ie{U)IcOLxH;#G%# zE0p{@0{&_7HekHJt>oX2%Dg|o`?r#RRUfnCL5ue(=9hPr{Cj7Z^-qhp>0HZOrR3ks z7=K#4cj4cAO8$KV|Fn2}Vmz!i{?Y#W6I`$G{j9QxuaB<9cz9nap8LW-EnWlg)*zni zL_9Y{9M9vx`vAO+5!p9gpg11A7w-LM;{vNGs|9%Fqf)Z~#c=h=2 z?MBo;WD|4y9WcxGhXa&&=RR+Fqw)LV9P~$C|EfjYKTn2#(*Nl5_V)x18~@ckWrH+pG#r@}w}{!sKBwrF{0o^AU}4i`I;E{dmGc_U_-+w<}8_%1-qw%M~yA3=Ve;T~|z#|sj54;uf%P# zyx!pP^GX^-w4VR{+%4}i@U))KJ{UZHUddsO{Tm4$Kd;0!?@sW{&jVD}_c{1|KRrLh zn`mvK)FiU_+WvA6{G+dXYwTYp;`iF-c9sfn2K+O(UsTrjOYppHdR~d!WZQ2({Nv}9 zxPD&H>)`R<6W;9V`rWh^U9)@$9{)XI*ZZYS;PK!0b|{`m@c^t=*^XHG=Fr!uBQvh8;s)<1e)iQ8m(@4`QNUWrD3 z`2sw8UWo>;&N#b1Xg#mw2lz+ND{-4_`~41H69c1o#vG5oN{`!k9s!=~@mCwXBgr?X z$;R^_@QyMpif1*)@jMc|eDGYy^F;8DR^pul-Z4tNi@-Zpi8mO$rb@i=;2o#Ln+9Gp z@LXT7%mwdwCI8+8uelQM8}M2v#q$^NP5`f|tNmvMJAY2W^W9Da&)NM}@D2d4C3wvp z`&SLmqi$t*P7^-gtOMRj21e^qOIQAZ*95$im3Y^mY4;NaO1uVVSzc=;UI)apjS}w? z@Y*WzZU&E{s?k610lnNr6 zZ}|HYt2v%Nymk@uHgi0ccr~7|^Ghcs-r?YN!1I^*`hnXo>gQSY!S~%d(g!-8#Js4U zcgX#vHT*l($G?G5eg72eUpMf&`0zSK+&`}d?=qFGf1H25pbA5P)5s$xH!8;GUzG6H?&6@&VAD{N?ACZ5& z{>=vO0v}%Yh(3>C-aFtG`tSxujwGodPmfL zu^hXf&j;^nC0-lw{-wn01>QAEyaC`1R^n|(|GdudlFiqHBN~4^-j6uPuJ1#Yc(vwP z-pz(b`fblE25*$%dDG7QZbY9aar^ZGZ?qC`5O`yhcw@jT z!t+1n{v{r9f0+#4L?7O$hHI4k3Vl@Uf+m$ zoxvLe-ZaFI)+S2D5y!KiGH*C|x5B?!@Q33$H)8)LgLfNv{n1{`i~4!Sv%#AH-X!rn zfs%;*djY(O98c_D*uSWs_xnD0clq$5e%|j_;5}@3-o*Ybh&Y~Gz?&+KaOYA&r`innRgX<^L^r(7x8$Q z0Nz3oPj0^n5v_lG|7E%|Z$5a7l>A$+%=;3&XW(BAvHnHfepQ~b^O+X!2=EreKmLBC ztNz(tnRhdI&%(dO7~ih^dsLbC4tUSOzp;+{=N4sN-KXt%cwWiB0%hK%;4M+|Z-O#! z0eCMc`L|Y?w*$NvjeoR9TH<(qX}G|S2Q6MV@Lqy{OC9@ngEH?i@Jiv|3djDvtIYco zytNpA@_y@T`0Kqk%;cD_ANIxbH9qm-Mg6?dhTwhb!;AWPoUOq7!tlI__Y;ew`u#7y zKX|$_uP=CCD)~2DnfDNQUy1(0*S9qyx}N6iu~KE;m*B1UX}_rN7gShe*Q0MlJb64s z{dwH5^DS?a4{vS6^Vxpz?lrkNf8&v|nYzqdAj5@8|KpE@Iw%@T$T; zetsnLHbl&O3%r_!=S|Gp7%}ft@OJlUzo_?TTfwXE6VIso%N~Wcf0p{hb92P;+y~>~ zWhLG*;Ju>6>jK_eKD;dv$8!L9|Mubi8ZocJL$<%Xqr{8Dzmw))^kAG3~nt=C*4=*=j|5}1qARd6m@vI#&uMc>wm3Sk; zYoo;bc!=$v&-(D{L>$jK@b3j5UexQ~Qt(QBc(Wq=3RupPubFk*E3??9QYUa;q{J)$M<(%Q0Bb{-f-g|t?7mEhu8P0 z{rg6lR}p`oYlKq!9iYr>1>Q&{|2ir2dVn{|$G>V3-#>f2hh6{1`0)BhG~RiAzXbk` z^WpW6n78C?>)&|8qcPqR@#FD6Fk;@d@Nc4ze}f|CjRWs4CEj%K-tgfKj@Z9jZnN$8 zZy(;!h8UOZynN8o+s!y6Sb??>?d@ZpV(n3uD}_LnN=4+zj0 zFA?A0jr#hpK6rb8w-ozno?oKAes2ZdzVrtYJc)S|B97;2;O+0jD~gzR33vzi@Fqpf z8xCG$AKsLRc@Khjgb#08#JpF)i_ssr@Feap#S!y90k4q{?~#ak-?M+lH}Yv#MD{(Q zN*wb3CHDn8zYt4*Nv85FC^=%MHSZ|!=zPe(PaOMqx$w_5uN8Q_e{s$00v`W;U)Q`#z@zm+qy4n| z%Mj)MGFG|2aR1cmFZUmvd_PFzKiXuU=XkHD{i3xmty$hYpv0?MYR7wAiMKa+iN(k% z)5h~K=DFSwqWxMh&-nnf{&i)Z^8sji7ctNI0JOXz%*%7yS&VVZ8^b);IPmTQ&-L{m z`!^Ll=feU1^=oVA7w5wPyocdmWu^9;4PF%`-U9HdD)C+b&-wI%_B-iq+h3f!2i}|T zPiy?G22X4JeFUCXJl845^9SX4{&Rg4RZp_(?LXH?(Z=(i>!WDn`Oo!HwDJ7s`Y76X zYF{6<Z~1yt>-zSe>&>V}p&ft!TyI7j&!Je4wC1ysJJ-Lc{P445`^#P6xn6Dg z{-^f!`_E(T{Vej2Ui>^A8I|n)xACmd(elFXFGa=M2LHm=KlWexoqFE-w*$Pe`;k%k zS2)ealRoYsn{$1}M^wCB$5~#U5---o@(K(uC`IL89rzbFFtSg?ndsPK;2$%_Z_LZ*Yzx9w=yv7=xoFJ@+N_v7#Mzjzfjc-s4y z($Cu_Vo$!gO?G`BFv0GZ!uBuO&YyI3LVbq!yUzD7;9Ud%X#YYnb$$IlR+(1}9^YSb z?cdYNyf?th3u!;|c6JHZ?;k7kHiJjKlltchaes-QubAz8!1Hy^?RLD=Uz^b2O}LYJ zcKq?*E0>KG)%-FAJo1fR8-4bJlAnIw&S#H;NAsr!?|Ja(^BfJ{O7LjD*5G{x9^FsX z;B5kr`XBN9K3_3!WtnV$i51!LK%Y-*@N&W9_0P3`dEix7^6yyib^*`zcy9&XuHe;< z==rI}oJh96v<9z+c~_&qbOW!Z60Z+M#8Kd1-@LBr{8vHwwI3#t8BJ*7wX9UM5V1?V0j?+As5QXN)G2 z9S`4wx4$W)Jz>5N&+26JzvXQQudXqr(O+szwDV^@C0-tQ2Y?qee`XU+iXL5)H39Fy z5MFjH(zd)4!K?3@htG35f_IP-uSF}{Uk(PZrO$ZCdi=q^GvHqXCElgr9TLK$v6)pe zcUP%@-U4335M#vSS4h?5Z-aLmc!$EC-}qxz#(si#KX|8@4I$Yo@aZqfPdfEdiY28N z!0QZNJIB1w!8;YaPL6q%?y}>rz1i?mJb8c3?bIbAzK!ON9Zx@LdFO-I4fdJWJz`#c z_%{H&o`TmK`K;#`d_J8I-azmQ9rN0NcLjKT9rJpDcO`iJ9rFf&cNKU89rJDk?>=*Z zlx#c<0zdVcBza994^zOK0p4KY-_VG8^T2x>ykQa9mtL}eFM{_@2#?3Vw3BL{dGCR@ zG6fznGvzYxTkzgZftRW;$?7rhcktd%fft2;xp&+7`UCK|fAZ&#@re2l`_}}#wMx7W z;C-mX>jU0LO1z=qeXPWr2;L`3yvM-1$J}6|J~EcGTZn^^VJlz7thPnB5uEL7FymM@QNMtzC}Er3TeM&bACEy+RHznQ;;B5o1#Ib+(f%m%-?>X>(#NYE? z;L{(Ynm^wMZwq*f9rOMR-p@+B9pG(M;_Z8nonL-Y;xz@YviX38)}SR~Jd`3&{e@rY z%+p+#=j+bkRY`%zx|vAkod;gk5MCw>uMYFB1g{!+et&N%s_{1pyxj%Qdv0_b6|We) zUCak$)L+;?SG>jG<$|}|@%*w1ygkeZa^#=u`SXjZcDz&kh{yLMDIaaJ_sf3-k63ig zkni)n`)vCQc|&93_+zbq#M1C@#>e*i$^88@m+_2Msu24P@yvmL&3)o&-p(@FcvigM z#*@E)=9;%Fc+?+)+Apg9vJZIt{WCxRqT)3GPwV?(%=X%Gvi{wS_7i`8(*fJ^#)BvR9HukgxMsHf==*21CoFJ0-fOS7 z`$78tSr9Ml=cC~B@X3fLfB(#N|C|FJfB&qLPduaAFU<#!zklX8e@4Z74m|$;nQLCn zM{NJhGyNrKKM|FGOW|LACEg0~4pQRr^QHLvZm!$!Bly<<{?&GLzkv6H>%imhySe6l z2VO(?=QqF5e3xCa>%(^N==*L#Df{)x@^;1Z$PP2Gp!J>lQ+CPn_5-hxF-E*RpZSxn zXR=!(Ew2f9hlA%g9?aWWCd)ekyvD{F`B%fozo_Q3)4^*3o?ririgzw}M}U{(YP{q7 zw3mW+WQczh>#P#K|9K5~M;T*e)6c)Ccr&nHx|S};Jc;dh@##OFs;M1fzf=O=5GCG7 z#Pe1kUbl$+qia7(_kcH6iT61BCoVX-{kli&-wWW~kMF>8YxV?Hu++SLPHv+su z!Rs3_?-0au6nOn3vM=My@vIBpSnvi4{{|tS?fS>O=HT6HcyxX1`ukuVm3j9(YWwFD z#B+;y{>0#j+LPmX4*a`MDV`UC_b7Nn;SaSXrFg{tU8&65ZLV#<1!%vq@Q3G@2@&}h z!}C#Q;QMu2yc-bDZ{c4x>_55vYWVC&ZR@7-Kl~f7%$pA0MkW8|D)U|hZx?*uW+gpg2Huz8O%n6x zmWcW*_s=%q{Rg}$KK(PQ{pac6Z3y9s?wxj){VN3T*O2y08z2;zcO!Veh47-<4;F#9 zErcgdH|;F@_c(aJEAgHKZ+i$Ys(7vjuOfZm=t;bPnI^`gr%HN}f%h_akBI(1%g5hx#!|>IZ`bQ=e|aT@7ghUR2LE0S;YBsSTnFA#CEghD zUQ^;t18-RfFNH1r z$h_~sdn<$&RXn$Yw?c`RTWsgE-vv)LNmTyjfwx_WcO-a!gz%)l>E^k=6o9uYe*Z8x zqV-3f5A)6fuSN(js`k4Gyxl^0@_f_Hvwt^(S2Khcm46e!+XK83$L%*AyjtKbaLii- z-d^A>_Tf=HvxzCU-y7iV2i^*w=L_@oOS=7p>oe~|@b*{Y@!!*^2i}r^c=EYsBH2Iw zdm0BQ@%Zms9H_+0d(N&$^}#E39MARWFU`SQ>X`Q%c%|S4U5~ZNq@zHG`%9gNY&>5B z&+q`0(iWG}$C>znj3T z3*Jf}UN&n3ohS1qgI6yFUN&nI^A>=2Ab6{N{L3bmUjNMt9?I~>19|HQ{X;+>I&kL+K? z8Mgfzr@%Wi0^XmcmY0R86jkl_p>tlgylk(3!l9N|9X$R%NVs06H7sv;@aXsNK`Gn* zNuO>|pV<$*oFJHak9gTJEpPv`ZTn^Yd##Z3W&aL_f7zXTD9lu_{v8e;{r=r;vb^KK zqu;*=rR@E;ynn`fP?Xbo&&Kng@t#i1g6i6M{xjZfjG`Lv58q+uYkJ;AP$FJ-Oxu2& z$6DTRqpi#tWn~S>r6~UivMb8_K;8g(0wlkG7xE854&Tq(osax0knccl`P%;O_%q}; zK~@HLU&xU--+Lk3q5ML~V{f&bE0K@k`8Ky9za6s17+Wt7vKiz6=r=^YNsu!kpN3ou zxgL_^$NKy}$AjhG@QdTa=X*7{Jx;Rc z=Rv**xf1eA$kvF@sgM^zj)iC<=ba~7C#gsKQnE+&*j}fQ zdb~eBJ)|D*t9yjh;~4e{smHPD8&Z#b9uQKG_l^GwsmE=3y-z)g8~Z@9jH4bs7lvM( zxE{y(R*$_ru4E*=&%RRe9ikq+UtnHbkL}$PP>*9`)MC?;)T4etcD(&yMo2yG2XjK| zaX*+JQjcS}IHVrO=B1E&?DMjadfX4*4ynieV6{&@iU<2ZasC+fs1M{(0TS2acKcG; z^VVZusq7n3kMs-7i|kQ7wzoN;9>>H~kNuLQ9`ysV=j{i7hSa0_lq$d9E+O;G|Ma5s z@!I2lP$Q%s$FNpNJ&w(OA@$hj`XTkW9~>4^kNd$ah=GuU(RQ6lb#MZMRcH>T$cB8B&ki?c9)h+-`*-^*A<{hSX!9uMDZj?RITQJ#M#Q zKK1DQ`P?YZBa_rCFy&m2+iiS6J@$d@O-xdc+Kuda+iglnJ#M!LL+Ww6%?zo>?e;`S zJ&w(Skb3O%^C9)P-ChZ)$L;opPdz#>_JQKO67}fVo46jg+Xn&l*jLj3Ow=R&0`sCe z^kREo2h`)3nCh{ON$OEQAY0yk@KZ=V?g!gK>Ty4)u%;d1cP2V-FPCFjEu?$Ekb3m|L`nmE>e2Hf>D<_lYfz7LC~=&*9{X`aNImvrct}0=W2{d- zdfue>{O$~?$LBXWq#mE&^pJXdevkOn^Ij8BydD?zsLY#kKPW$LKSBM%=k4_?*PVrY z;ZtoBMcqcU;kOcU3hcyxFRz!s#O6z<+xp!eu(A+x5M&W#DP$RB>_J;U7m}fut+nS} z_Emc>O32`783>U?;!W+AV<0d&uVVAqyb8LB=83Ud0cS^S=jwir|-_yhM~Q zL-}%1J{IL=qP*w@8_!}suZQh<7eNl1Ve@gwBFJLMm5}U5U-%)gD6Jh!f`snle!TQo3moM_s z_i1ic+bK(-|E920eP<1O;OGBGKKk-|e9|79|3PrMTz-c|-jC&a6*eUAzcsi*h}_jj zpY|i(bH z_uqXL@y00VO&0p*F-<9@$D#ME&^M3ONGZJuy$^&we_jw~>&yP?*Zx2F==0|j zY|l^b@{R5P$3b#E^EIk+$s=52pJ{s`zz6#9p;K6;^?51HR!qdotokoIh2u}0<~75^WB z-s3`_p2M10^W)Z{-}(Opy_%csdDz;qSYvZQ{#VE||C!{ce>C(u3w?S{YC=Cw+Wz{J zp*LUX({oP~@h`Tc*pFZ7JA2-{LMCA5KYEU-xBcXL!twuY4&pEL>A9pfe#!X-7{8B} zwq;~Fna_Nb%KcE7{?SG+$750I^ZB>Nd3P7*e+=_O;xb~y+-mju2>s)Xexm<}=)VTN4~2d+=Eu!}Nq*;FWwYhigtWC|vE$7_D&y~R z=nWD2&7of*&-Nd=ALI7B<}=HmBlKIOsQ)4KHVgd|jDDj3$1LA({%Q1s<(~v;)Dr1L z^M5Mir`1%eKThbkH2SHGpQ%F6(qpk!%twLW{5==?^M#$0pkEn8zb9l<$Tmhl5&t}MV3O?reEuh*zOD7w z|1_(4{rA&9-AA9!D$#$6txZ4ui+uFkr^vq<`u7Su9he^v=D!NP4~2fm5PgpSIX~I> zp9jhD?_~57@h=YMzYINF>#zS$F^7rx$8DL6AM@XV{wl%mY}8WW?||MOTdW_J7K@!~ z4ifDbw!ZL=f0B>>X(9UTe=+oDKyv)M8vUUD&-!meZ>7+u-_-=g zkM*}fZ_l60$FCcof5`fE0rZ9m{WEszn*)<%`*Zw17J9aJEOw?jNc0~R_{INw=vUcV z{`}7}dfxW;<6kfInBSfCL-=<^b`F*ZVpV6@n`*-sNV?E z){ez`n*-`Uy#D&>&w`%h_c6M}57U1R`Y%B8_&*=|v5@h%5_+qJ{sl(AvU$ad=|6w} ze}&$5p|AX0a!9wB z{)@%r{UGMQ3cU}7eqW=LivA(ntpCSBCSc~jOH$Oo0D8lOem|q1=zqoLz$Cx(UkJTb zLjO{ulZan2Y5VKf``w;@Q%GAo7VB>gQqjK+dNYLnWhv_a3BBF6+w)-ls8^arM>|HpE){~zVg{|cj@V_sqX?@8#b68cxB$UpW^%PoK;B&Dm&E75*& z%Kd%(bN@dRdKU=&K}IKW{&CXw*B=GFBB6h^(Mg5>jL=KK%zyu4eH8eO|5ec6D(qYX z{R+j_fZzCeY=@2COOU|D217rr{i?>=Csb-do(g%bDXm7AuEmMBeaCMv)E@}BO9g9h zNQ(NoxDWjl^tV7>NBY!&#pY#_pa1)TcPON-9g7V$2dRwziO`!4$^Kt&^i%Qwedv87 z_%|4RI{mQrt6R~=>m*2{l1Mk2|5G{tKcH8=lC{I)!S?fKV%w6)FmY0W_*esNpkr{5TQ%^-RIGRmkW_K$g1-|znGxzOt)_@j+lD*PLv zcZ<*;lcN3u(0f?u-6AS?Go>wBlIVj(p1{-X6W4` z^lwj5e=hW168d*Qze3y`nB>=g_pWN=)&SDhj>YaY2jqX4{sqt*EcA(_pjkGB19iqN0T`o-oTNn-!EL2u9MHV$0%UUQIW z|6*I>*M1j3?;=Q^|E3tVMEgPCTKVgL=HGRMyWk2PXN& z@6cVW->o2R?O5!7bCBT2ZHb?LZ|L>+dD zjlZ9MJ?P~L{fAT3KMs1$h5n2XeV+f%fnK4|f5hllHLqBl{`>p>ncM#x=zTBrA2m8& z|NYu;w;DEnxsVB%`EO>5`VFCXjL?6~=vOwc3dQC>llfkaVt;=9pK4AE%su|F6EAjb9x|Tiblk-5jJ6|7)N(M(EE?QNL2n zLFou@fN^8S~%M=H)$qKYlOh^%wdJjD9Nd>oB!l z0y$skF9bhUoOs)J|FG$6tG`s}FJk?8u>Lma<>uNr*xIq!GtjRPqTd{PorM146!rT< zFD~?-O;P_o=*<-R&p|&de!oI5XOHs!KcAw07wBCg^p~V~{v|&8FQmwS3HqxA|HTk} zUcV0B)B1fJq)|(xm(2g(`Ok0s_J!V+Lcdh#`;DJxp!bf@f0^||_U}JHuWGIG?e|KG z`o}=8K_L!GF!@S0-?r{`2P-LvOy&UuJYjze3#n zXOiFf52)Qf@%|7<-oL+YO1=Aczw4KWq4%`VU!J1=J$qUHC(uuvjQQ^k^Gfu;koMmd z`UgO={+rNe|NZ*!+0eUC=)V=h=kYTe_fH=d`YTw!*c_N7@1OGiuQTTVXQ0oYKfY~r z67i3dwtxE_SI5ThWJp^(7W=n3NF{#fLvN7Kf5+%oHZP8!U;p_J^!_XKS290t4ovdX z{{wn^>}&nt{`aoYN%)^f+JC=(=J>aSURy|8I~H4I4ss|{O#l6zpO5=T{lULh=)Y%l z67kC;ZU5`9snDA)^j905gnpc~iBETg{z`oQ%Y`1-c;6g&@4v@lbVvTL#Qo=O=&ywQ z9deDS>W!a_Kl3Z@XXE~tWqb625#IAp*z#0j{i;6tYg5#(1^p(%&WA>y+OI;f`OhRd zewaTLdPPG2Bcl_f&++>hdY=jXkBz?9f4}(s0=?fL57^(v^Aqr6adTjjj34u_t842Y z0Xp31o2tFKlBC){m)X=FM{4Aq5pY``d6%PmpJ8xLcc6U{SDCDDD=NbQU4O? z9f&w4PR9KAWr+SwsDFddWBp;Goa^)ZoacIec9vtF8FXITglZhJ2(kpS6mlhG8RTZj zSTC#3{6Dbn$loPz-gZi&O7RR^zjUIND<8IUGh__!=R)Q|=0g@hc7tT@O4#FknaJnk z_u4C`;C!cASpqo-_TrGa)9^lI?sS_U1R00SgFf?%pkH#ot-l%X^LfQ^9>ovX_q#o4 zWwvn`#CG6!A2bDjcU$@)-I%tvgs}OR~(>5Q6EP^bCEP*VATnSkQ zxfwFHz}m@$%!AB_EP(6=SqM1@G7eb;SqxbMSqixlvJ7%FWNab$ka>{#kOh$4AO}Il zA&Vf3Axk04AY+JEE+of!wutj+BNV`+frQ|M7phf7p3O zhM*bxUkAt@ko_QsK#qZ&3^@~W5#%z+HIVBew?bAKZrfpR$cB*3AUiWsqwi*F$cFtTGyW$cB*3AUij zoD4Y=auMV*$Tg7bA-6(S84EsSL&#>3F{D9QPdLxA{|D_7hu1@{d_MVnQh^nGWXHB` zPsls0W7o4A(qg;!phH{_CkU31x0SLPjUijF+mN7)pU{hZhjJ7f)7 zFDk?;#fmBwB;LwP{BM6povi+z=KYGXny~`-e<ef$?ZI6?9ivVbKh*Au*3hojq*}aUWW43qWmY6=e$+k zP8GwYc;@3gPY0l(DW`rl3+GvY@)kbl*$#F}VTaGN1Ijmx@^ew1Kb|dHjjK#KamR}I z+?XieJI4D*w*N5f6bd^}ChG4M6#q#x%g5~}lsA8(d^xvQ zT$ER-Z0#(VSHAwfDBmv1o1lE-Q|0TQjPfo|moGmP<?_md3^%GbXH_3JDwUp^G& zbA`X-QJ%l3eEsQMUzC@iJoZfa`rJQji}F`dzf_cSzg;QH*PwpMtn&8l{@Z-}VR8BL z-%-D=D6d(?wo89eULWPdM0rz`mx}U^C~q>SJoj9bZx;0jqCDr>^7U^)dGE)|mrq3b z0#QB#<%8#zufNcgS1?ZqU;cVqa&YIf!rwIIG~T<-D@c@In&`*o_rg_e{i0>%>mQ8r zVo`nq%1cH087N;XxR;r7;+Af;+!HXbK8W)8PqzHn#5`r59s)Zh!v0oMo^1TmL-CW9 zSNAF3&!_xQpYoG^%6s~h5ArD==Tm;YPx<{mzZ08!3FBbJ@qI|6={|M!Mg`Juvu*97t&a*Ab%Y>bwC|@q@ zJc07DqW)JX?PB8gi^ z_;mrwmx}uLp?s|1zK8O~!p?5y#wgi8Ow{j)^8TWHILapoJ4;YLSCs#P@+qSHn7u8x zMA*Lq=Z!p>@x7mD&d%#B^LUsu@a zit<6C{%t7F7xmvj`DSsRRm}}`vcCl7+)vu0e6X-T66Hfh`O7HpBDgzH-bB=IWp30H zx2Y(<5#rg&c)L(@11)_W_%4>-7@?j`nBFbMx`7lu)JHXmmEVyk@K1rPCD3mu4 zc9x-hpr~K%Kx_Y3QQjHldBV=^D9;t;@1nepu(Ma5wO?11pNsOQ!p?M*_ZIcPK=~u0 zykUK7KQ77#puB-7FG2bLh`_W_a+(G-QVuNe@c43K6R?NAX)MK0i}@yM;ghOqGL$&nkYUg@0c0H5R`1Ea7vD zRh|nKKi;ChQSq{cA5{GN%E#DsFMO8ppS9?(R(w$D&G@=c@kI+i>)FC*-qL&1ieF>V z-=p|it32nPEqorZ@HZ-+(sG*eJgE5fiko^3JxBPQXW^ex{8Ee0v!5&USqr~b@kg{? zhW~4JhTGw5&k;WHyZU1E!Sv0amot81?4+-4;D5smjV z%MbS`{h40~(m$wpr-eW1Tq)1D?hMkOqj;yjhi&rRr1*kGzf193Ec}g(pBRf@87$|m zO5bepzen-C7XBN>4_f@6@;oa4iLw0~g#V87L=LTtH^mPBe6U^@D*g_Yzp2+1ipQ*c z->v)?e9x!>w|@ zhw&3*P1lGVx{FfIyA&^v4G3_){Q0HwIbiW=dcKtNCl=nW_+1u$sllywd9~u-x9WR~ z;&J7(Mv4>rn&J;ye16CHiLumi+P<*k>2q>i+I{YP!D%0YKI;`f_&llaqGpg+y!&Bk z$GEP4=NX4T&C2)h6>qiLQ@I%pOqvFl~EV!8$DvB?*2jz3U;tQ`Ayh-)d7Y+R{gpcVz z2N`dQ#Vt8Jyc}KJS+Dm~s7&iZ}g9%45dwuN6OVp3om) zDa2w=>k#=IyjSS=>3Hu`eEvIvr`AY<65~y=d8_39L`t#pw+$w#UHZd@Gi#Tk3Ck(Z^qG=6kj+li2q*k#j8aQhW?BfihOoF z8kEnA8HfK$%fCj)-76Kp-Ky7z6rZ%@^F77)S@@AJ5;+vC`gSNjZ`GILB}r~)T72HF z_&Y2nZI^)>i2VK;z zg?~@+l-A40^QdmA*SS{tyALY13#V;RD$lJJ{zt{{ zuqw>63@v>F^&nUjv!s!}*;(wJTA3Ekhc)`Ml6o1g-^Gd}} zvha^8e!sS_DJO+{5&y5M{0)9Wzu;M`T{bBG6N^7>ClQ}ftDJwQ_)Ql61I2%5@i_*= zocOG@=zA2OwD2n9&<`=`|E52GK>)sR=)Qu-e=YKNhmh)f5^gLq+)D)=0Lo zA;qs!J_dh{;wg*&?TR;9{C}l*w?%*YkmTEE;TI}?jm760#ZR&1d8gvPv-tc$@kI+i zXN%-}sl{i9;-eP*I~Bj(8ed;w9OJrI+QqEDVkzN&w^jaj#ZR&NPeJjYSp46o__-FJ z`xW1A;ZJ_CV}_yLQ4LGiN1|7VQDkEH8`1KLkc9hQ9eT5=mz{A`QQ z8x_CH>TjP{e51wZPl{))a>hp_-&u=(Lh&oD`o2f;M=bhpD}I%w2iA@X|J$s5dllbj z@p-A@Yb^ZZiZ5FH|4s4hE%}_WRr2k#%72OC^A`Sg#p4$KPl^|;d{=K1{tsCA3mC`x zx>@zoVbZ`g#hXtTd{OZaDWAKPkI@f5Q~V}N4$r($^1Z`q_w9-wu=@X775|pS|0{}L zX|>Dh?ZUro$>BW3PqOf7#xZ`+kb0T^{1JmcS#Yx+{Dtzl)vDJS7fHUiTIGC+;s-4` zU#Iw>RsL@%ev8!~o^-MB-*3q$srUmHpI0h=ipA&CieGP)^Y@D1V$~~tiRAk-OK!Uq zZ?*6bC_ZVG=ZA`4Z}C6nQsIBURnF~-zr*7H4#fv8`u&Q3%gT4{ON9SEi_b>IvlgE# z6>qlqEHVy1>La4(O+R^5@%Y1nn|1MDT_*X)wZ3arPwrNH&fb}9adMSqLpXIu0?Q+!tG&G1VZ^M*e?P{CJDcc{$-6>EmdCIu(>9*)ER(!kFuWnX+t>UJ=ey{jfEx9Epg#T?8ey!sBEdIYx z{C=xnbx#VPwHCft@t0Zc@_WVSEP0ORh0j67Pf|I2Qt>9`bG+hD+bQ&OR=zI-9u|lB zmI!=b1pbK#{BGd1j@W*y^phQ0o`)jn&3S=tD=yu{`R}ms!*>zG<6>nCKT+{H3xBTS zdoBEhz{BKV;{5kp^cy4Sw<`a^Ps35*`;Pd_n{8PYboxX2>A4}o>RU(XsBj|s4IQ@QHY|R}(`IvJq zSAI5#n{zIw{6i2o?X}(FW6nohW8p>)cUibO@37s<*T}hS;pY6pReIjf=%u3y63@K2 zXFUtxdm@HdEAX)XX5?_TRj=76hbPjJ;!A9@K(k5T6iI%Jf=UF zE&k>_&P|^S%KyM>Dd$a#LEN0LIq%LOZpLrc!p%6Hv+$RroO~Y2!sivg+rn>D{1FQ` z?Yqya*C&-e{`p`zzpVJAg?}ITVYqE5Wy$l`z$uPB{x{O@zdDS{9g8_rOSk)+#lHvi zRNreXd{pt;pQCE^%nl{6Qn$MShzW_wBN$7(DJPPaxmXF zDSn=XoAxbO_&%lIYvCVP{4NXsqT&x(xalWnTjvwM1A3aL=0B(QOefVd7JHEKQ)2t9 z_Kg+woWeQ1O!vnp@}F20IO#p}-m)2YbBx1Zq4)ck`T9+Y#}zkv!0IO#Gk$VxyW(eS zzE?!>zd8cn8-W`=@D8gyABdng<-g0KH+ud73tx!fW6niBWYI5zp7hlzUk#3TqX*8l zaH9uCE!><>%v$(2mH(`T{|q?EKmLRZSi+_qA7LD$=b2I-xDEMpW?ASDYP)nR-U&Rc z-Hn{DvGVOvJ{zrkClv3t@Ha;AzmDmfV$ID`&TgGAZjPWg6hMQ`lt z2Q2(^T%J>6DJ{RzSKm;4(!&2OBHxE2@FOn|m-BHE_}RdzUp-`%^8wXwYwrp6H#1K) zTevxI+iKx2h{*TF5%^>T{;CN4+6esC2>i|n{JseMHxc*|m2f#fBLZ)azy~7mu?YN% z2>jg<_{Ssge~iHIjlh2yfyb)ha(HS4{@e(BV+1}Hf!8ANH%H(%N8q1}!0(N~e-nW> z)xza)W(3|7fxkEc|3HNN-3a<}1imYR&s7ohH$~tdkHEhWf!`m2|1tvqQv`nGbhw;P zi@@U%_<0fdh6sFn1U?mkN7;=pjiA3e0^b{fzdr*1WCXq#fqxnJVR+SK-ntipW`(f% z`aaOpExLD~9-J3`$$U2jfpi8nGWJHGPhpiN#LGI&Sg&9{xABC-`$M@MHD6 z|IaNE_@d#{C+mfCb$;Kz8+=ybULC#vkC)G2_;%owZ){5PZB_d5+3&pOjG+HGOVeL+`TiH82cOuvvTkisKHYnSzq!BiNKHDW_}p`Y`Q8Vd_{3i=_}xms z`ik)KpA~_p2?w7YeNrAr*IDlZ{*=bz$8H5qa+rIc(4!{&`JM8K&r5k;tMxknrNY1a z*+TzRrQZph_#C7_EPU9^z~6rY{?t{+V}&OlV`u(U`IIjd{`e<<&U=}b=LX?(oZ>ry zvwSpPtyXLv_)}J$9NTEEBi^Tc;urTYhuS zc=;LO;Ipq?%46ht;w$McDx7z?TjXivy&gFC^S=w$tD<=9y@DHgzL{{;ckU>`&A9u- zoaEd50pagxIln=;e)s?RJ>e*4tX24&q(3HJrS;t>_%{`QDR8dWMZ(|6;Vr9Ne132+F_kfx*r+{<2P=FskTMm;1w-LR34gB|; zL=X9-dV3f*{bBqy!e_ts|7U2bcK~NOT)v)>r>~YDKB&04?^NN~4}tSIx=H9wKl!UG zh0lV@=QQPi0r1n%4^!%g=~O(c^m7Zs=Lp5;4gM^_P5=3@;`0`M4{+)KQs3iMKKHzq z?x;E0yZ1@i$G!!e>#O%s9Irn-;dO#9W+h+KUgs;mIm-zqq|F@JtWxPJHlIqdb}_z8rgpX`6X@Y$e=Miq}Qb~Ex8mBV`@_k1eR~rAHe`o&COaCBx$&92%1%%|n6g-`RVh5j6+e=Bh6C(Rk5|C5$;!yAQ9 zO!cbKOB2Au%Ku5ik?+EN-OTwbCrbwVi4Tptitz7K{`X#^^}0gJgJSUKQQ%bm@+Ohn z9g5%hrtp0K2%O7*iSXa1^yxPX|0W7-#^>d$jN`EusaRfM( zv*|vm*HK!Y4+9TtmwS}Y1A0%?vy}di5%g={D*VlT(?*ZA0jKtz(|i2RQ9jd(H%&?T zP5-}6@r6;T@8R0+p9TIDP3!;jq_+wG#n%X*6ZFUD5$-3{@8=tOz0caT;|+?(a>B>x zlTSwQ`JUnPF)63v^C)nVbN3m-XRZFQ4`5(KN?12+wlX`DI)FXddfRp{OO6>>J|9c3B+ZQex zT>_liG1Vsd8a=ZQcvyRVR_PDiEPPar#lA!I;M1)4aKBK?bHclXe|L}YKTGj-iq9V* z?b4+9dw~<5_)7)9OYtu$en96D)9y$AwaBMQ<)2deEx?ISS?6Wp7K^=(aHaA8c^7cj zZy%Lca`1+PVK&bhww3W>2cRf zz4lt|ej0GDS53-e^p9ikmk4gg-Fo0uFZ1q!q2HzWTvFQQmQ_-qr@dSF?^k_g>Xio0 zd^QUIFKGFD-Xrw;Ec@y*!j;DV=kf^rwaRBqL+XXjr{@gyP*Fo+7UsOK-4xHtDbvGkMZhs`4k>Gz$ zzCq}lCqzCU)t?iSU}lJlH3&t9we;`t&UHqMd0rt9CB-(l6fdV~W4%Z>3$DwOvden}Ab&=Uy-6&*=|W04F|+I**^I_}i4ee5LTe z?nwDzKX94{cj!AK%}W1U<#WK|v-X4G_3b1a`RTk$_D zZr)otN%5!M3jTDSQSTi$_=|yaKmS`P{~D#Q0q1snmW;2TXuo}{(#Lh28vFBB#pl$X zoLMD|ex&%kHD90gp>X*Z35Wd6yChH2^1LsCem`(3XVZ3RFXQJN{ct${Y2YO12P}R2 zE}|zs>Q5NfeD48H{8Ks}%^3N;;*0N=e6Lpe(>_A|5Pqt!_A&Bw#m@)M?Q7i^dLeMb zQ%U*HZo-kTd8g%R`s2;Oxm}(k?PcnF^n%dG-_y;MAJc~HBwW+_|7-xZoQ`rAa0dL2|h&vDAk@^j+Op%mKOFl#pm_isv}jO+(rD!{`r!$dy~@tM(LZnh0kF+ zPM><4@Soo(<9CnJzh3e9$A$h_<^LJN{Q}ePKZ?K~F?_WAM!%i#36W3JslxxytAx>& zipO+4_+;h(&%nd-eex%z{O0|w8<`MPxliQT zr9Yf=dw4m|15W%G+oj!a(Dt2+pno^vpf~TLDS7M;<!94NxeR){pz)!k@A#t!pHb; zKcM)53xxh6Wp>IPLT}!Ud#BkVdX(p2x6p4^KBs?H z_#bekJl84SqWD4G51Lmzqj=MErG23W`SX6o7q1n3O2_q2fK$HRHw(T?>7V!y($5cA z{rpVe)V>Sqe>U=e5pdq$QG4km<#U*3jMwdq+Y*LK5qxk z{q{vd|1XMvjOg{d|IZhcPh9Q2YxT!tKMy{%p1Mf*nDygd6yN_m!DrNuhGc!Vc=BX9hU#?guA5t`)ZQ!L1p%C z#Z#Ax+&Wgt4~t(A`q;K$eLwR>sfzxYykIUgaM+VReAX54(d@c;1LRQ{%zd57>+ zfn#3>&h$r1d7h#8uYi;MQyY32dEsI5!|%Q<^b30g|BBML;|tLre2J8^UGaA*zBnp) zr}DY`pM+0b{ZwsA{|IoB=bZX^jJ=WlD(IEQ|7QIb8*E(IP|-)W+UoEJVKeD*1yyMWVpZ`OT7(?7pKd?1I|8Y#~@t-x;- zj~^rTHT3Jg9-eO>aFSc<140ju{K+bQK<7L;1w_ z1^FMoU-&Gj9zIi(#(`72@741rXDEIlaFWjf?a#g1j;~Ta`_-@VJf*)`@tE3m&rUFcZgnT{C|FP!Br*bZ+-SU3r{~rw}tzHZX;?H<*ApL{-zM-4R&A7Nj z`7gdm%4z!fgUZLe3%yD+dE$4#-=Cp=KZ$UZf5*#(&pMUQ`38Tsln2uRe?APH+GU68 z)$c3*b)}C_3!i^dK7TfRv|UUYPWi6nyWi@c+Xz>l{y%>UoZ4l6a}UFBQU1R*_=w=9 zz0N|xs9w#wzx*R*c9G)dJ>@4V{s!P-?Q);e&(}l_KUMlue}Mjjbw{`EYn%SFk#O{@ zTP#0b33yn&<_JeQW2)!hru;vqc+>q-ukUJokAs04#%BxR;FD56-to%kgTSerXMb7R z#gy~gO21#}P5(^%tMDnSzxor(XRG4-e<0;K@+kS?YT(5Ge4W=$Qu+@l{hZEI6*G?m zr~cEV>uar6?3e>82lewPc`TuL`5ck|)yn^+iqGpl)KeAzl;U&KLjMfS;32}5#{XyV zhcZu@cdd%QCHD6@YjK7Pjfy$2nS+gHbh8NV6D_q|WYozlM^ zILYV0Iw}7Hihqi5(gTvOA_<;{0Y&r&?~ryeF0KLDKe#mqZ~3dgnr z59_xdjlh3MIP$gEk5B)F;Bz~qoG;f5&IL~8oPVFR3(ODxOcRd&7T+TD`NIT%#V>_E zrR(k|D*cVX!^(MpaPXhIRrt>;{S*Ezoc(l?C> z{hC$sL-E0I{_})`PwKrwZ_4~p#TPU#Xp`o<-{5~O^e@nSe;dL7m|qG1#gBJ0N z`+!ru7M~~mS>c$g^!q<4_#c)3-x99h{eM0Uoc4)!==@^z)vt&@wb!7O^KLEw!mp`6 zH^na1c)z2S*`2_NzFGCZ;gkJZc)s_7p5(TpDEyDmhX1|di`G0I|BcW$eMs8Z~32BaMClc)$<5vDt@i`=QDABZO;S{y(2r`uSH#dlmG@UnqXyW0LP_ivJ~o z&*}dz?Nzq?tDAvS`I~hfKSTKxfYZ9~fZiWs-_Bnw?f8Dh-|`>f^tS>(HiXYT5%_@!KF9w~+GYM`k>`N&OaLc2bhk=*o_U!3 zPytT;s#)#BBbEM@jANhIs_#3M|AC)NyL?$Ewx1FnQvR0TOTGuyepszE+kjL5SS|GWV>_mgRn=QEW4sE5MKa|!UU z{#FD|e42ZtJQpjU=|2fRw_Es|`Qp96sa^-R3H_^7ZVv;eeqPpl0JbZB^q;{8^ktnF zRE@>X1WtV7THh0uzE$x#OW)2YzQe-*Uh$@Dx|zfA+894ld|vl?&3yD{#k)62y_z-O zBOj)C`%_|bdagv_*pq>CJL)-|=jjg}ipO<-XIk-%z)7BqyM%x1Ve-Stj|iVRwYOI* z{U*iZR=r+FxYGFl>;+D8USs(c7nIMu#t$@Wq8~-@`2%ojmpN@0N9m7#RP@`t?#r0{ z{WjoX<=F_F^`zxix)K`rA>;=X~JA zzuOuYJC%N)%K7O^|1QN-mYnZ5^iPxaTC44K>VHZ*&Z|G|DP`^eOco_kI)}~Zg5>U znf{hIESyg-;V5UkL-Ku>TeG`A~S+%$G1oD`D_IK4d5iVMfJ}cJ@D%Y`Xg3J zc^0hl4=El$Tgv%Tt?w0t`vs%l-=*}i-O_(XR>==vP<+3||IdmyY5&pg5bIeT&VM`t ze49%V@HwdT%~rp978Z=e|H;b#1g-D+z=?lsQsi^i;qt?k zz^T7Ip#JJPrN2q(yETsPOIqPa6<<*O_FSbuhWvHlZ^uQ%72p3{$@e`LPk5sAtApoD`<|)vF906aA1;o-uOS@u zI;j2XGUfky<-bqkQSVj!)FUL{dDR1Eech$_!Yv|)E0umHaN=Lqb(xXpUZrnVKk%f| ze@f|XKmWaiD~j_5*K4;lW z&m-I~0R8?l;50AXZ_Nug8$Q-}|DEFYzUSFbqW;ztd$-=xV)Sz#a4P=}wI6<}6?hOh z_n#+8yBqrFU_v2$$405wIxS~EaFWm5dXbMgPqg}I!FLP@4)-#D7Jw64wKKDpRDDv{M8GJmn}W>bH(j->#Ac!4*RVAi{}Cl%lCZXG=3k_dBn(P z0ywo-%JMV6jrgFxO_qIlgW~)DUgUYK8VajXUz(@lmS5}m2syk!=@)dJ5?6WVBIx%3 zr*=Q6^Ox}pT??G*bwKUjIpy;aqSx>KKVK*Q;M1-0KUIJHt@4j)eYIP~j(v*c8@J9i zj{y&p^UEXfw?^O}B^>2hxJCMpnWuiJcvQJ%8uE5qlbitkrF^Qa2w5ycm^{HvAOnY6DBKJ&VM zT&wu7;<1;>IK^cR{CNd%Drcu|4xr|+U5Aji+{y+bs^am0mpAOTI$4hw* zs(<4Xn&@2MtWVmcJZ8Oclj3EozkNgbEWSqgmsbg+wI>Mw?k~x>c)I304xIR>bRBxU z=6eOv`wOn$-wvGG@g!?MTh7OG11E+d*Um`fnD*kk%!w`Nz`}sSR|A!Ty({X3| z|GmIT54>9E$CH)*_l8fK)E6zypJ$&8{%FUA8Nt7#_$9!@{1WrPo0Z1@=T_h(&;4tq z{5$l=FDrh)n!lcOij?zRoBq4ZBZOYkN=AJMM(Ja8(fZMWZ{c$1dX^pmeE-mLKe z8Rhe^^53WW!PKkySt z{A|I?J%Zn%?eziRVfyVKmA+Z^s*(TCfm3@ej7WLlR^rc^=YT)@=X^@||3URq>A8o+ znw7@?=M})Y-F5%>CHmw0fK&P7R=#&DeUlZR@N1=yDZN%JcHB84|GbV17{}jJ$x78;M1*gSgrK`2AulgDqX)kL-C`ZC;1+D zs_^-g%3-VG_Ij`aocJ%iQ0T#yKew+Fe24lIHY)#z6fax*@6PkX<(vdg<;?1MF?wt} zaH?-v`}2Lu{|Cee=T-9lcA9#)EtE-ex5;&FTH`;%U-nf); zyyvd>s~lAN8RcW&%XG8ii`Po~Zc+L>6`v~z{@05C8hF@v>~gfe>Sr+ipE1Sl_1cw$ zD^LHQn}Ab0rmS|kOZlX36FIbL`~Eh9&yy43{9~C)%~@B9xo&za@7B^2F?Yk@mi0Y@ zu3McRa|hf)eym!~S7z2_%H^1Q@knj3({=Nud@*0MNoUf9d^TOnxtZ|^ArG?3=F=0! zQni-PD6^rFn$zL-PZu+_e5vS8ri-iKq&AXplNS$l0<4uvg=$NDYc<#B<331|PIt5X?3T*8 zN}37;3H`6GR2S-$FV2*9<&vm{uTEP=;_em*bEM53xxlqsHk+@etJU1pSRrSc&J($l z@OsRU>o|$NI&Gylfoz6GT&Jx^lJD72Nl#6sE6JTBwa#&E_ivkzKvA+yQAP8!tT?SB>6zRp zI^%GzI$fwG(Iey3Bc*@ZEm4M4YTO1JdVAg6Y$jJmFHWOj94FQQbv8hW_C~1F&g8;; z(G1F}w)ddZGU1jhr3|D7ah6GMjO8ZsMd%L57T>D192#lL%@j%yEfh+&v+YM^S&FwvM{qA|lnV}^;2 z2JVflS{l=}G#0cagjHjoYH6%aV?kRRyJuUY;2Vq3SORp{iwB*y-ocT9KDTc+Gng;# z%2fosu#&IkQt3)s1}@f-)z3nUz)D;_9ll~3x%1ft`Sx= z!?|%%CxcGAkMCF|jSfg?hllo}2ZOWZSBF#Cv8}ay0sS7-ogVcznG#D(o``etP@*l< zweqx<5gK!Que)XIsJm%ks1JjmiY&T-6w_d$#ZE<&SqYW%lLonPy1ImrpoVdgtE`{S z7cg35tT1?Zke2bjm>HM>Gn)tg;X-egYCP2i@oX+rk||I$hDnV<3cWC%hTaG!@Ttq- z54AmInPij&Sq4>PDPWnDty`R)8p~BUoz6>p+zFXk7#zzN(Q^D1ia0n!wWE7fa}~#7 zR+~%N=|V0!1Br#xC0cW{lj&(_x9mU>jaD}y)&muetWKxod1 zwrZ|6MAk??GYZmy;&`dQRH3iQRDyLs7cE<7$TL(Zv$hcu4d&U@rkzt^#!O_zBxPS> ziMk6(dL+4J#BpO}FHx(hSO=Z>u2GtJT*rknN4Ix&ZK#x{%T*6ZOkm8h8qd>=0FqW% zO2teN>&WKDrZJO@m;9s&Hp|jeS$86X4lqeGc;NSr@}7xY(VaoSQYSxj3Y<0rwIY6VTTq^KLG;=l8x|MsPuN=AAav`6= zL^+eIV6eOBT9{91t~RAF()>D=F2ja3BPPOf>8h2~E?eKm##(Y`tW?gFvYu5K?4wS+ zHLUPG*=z-7M6S9`+b)IW1WMHK?-AGyFu&JNkB{dnsmVRC3)6)F=&@p3(8@g#56itD zET>TS5$;kWX);JyoP|#qDdq|*Cf}UK=$KtGxwKRm zd1qMJd#Y0dL!-&T6(`t`D`7-b_Jk$q3eCZE;E)t8p`EU;R7+Jb)nsZbPBJisuK(ic zTxhvkLbU?5u?~;0Y(movr}uCsn>G%IrAdUO zRaw(*cp{W;w35zXhz)HEOVkopyuRE_K9frpFQ3j$=T@G|YoZ8IgyseR!lWvJLnvXr zS`m4L>disewiPHqR#~Ak3{B=MBGg-$JVKMnsOu%I7*WVjJ(HX*V|K)H9|q2$q%&%F zbGo{#XLDazF+=k+gBNCeEW-wgxuAE+y8-PKuG&K z-U&m~vdvT12rr&aXIGrBm6itiiqj63iWAg2Dv0%^SvYAhr@gp$%jOVqg)e=~YR4=ZBC`%PcdUkzA-v+e zMcb^;*L8J+W zCL+6AX!5$Dx4A_7L+cCEl|v}}){)I>&-WI{(G{s3T0@P~_3RFTOS4qO>c5KoBTFA@ z0`}#m&{CtNjkyAx0|VGM%CN&BOnRXVEa4B6>oCIlX$@rn`SI!`r5k?zISiW!Jr%`3 z7Z6BgxE%@u zE!#r_TMn%js(@tybzv?)F$u43loGbf;58LH3pkrOGfiNTqv(uMn5v(T7dQ$wTJh2~H&mZ_zwQrJS`2!mWUyocIMyn^_q=yCNlqKi~_h1DjK z3DpL65q!tcm#EiLir2OaxjJ6+j?}P9%@>w!oKP-XbxRwIx$Gdiye`h7XCa%5Cl!nt zwH@;0)^f+qf;L1fZK2kx)j&Fr59i1QJ`-ligtG}Kk-0xUBG8`yYt+OTEIhQXvu z`--mVyx8um?QvF8DUS_AgE_^lbX?51wBt1fLm`ZfZPa>fFmR2C)3wqRb}PndFT_n} z!&WhEq1K8KPR~q6%#|d9b)estFdP~fc?FVDJ;hUxo94O4g?M=K39DJC1=CX*%VS+r z*^{c|GI_FK`r(kzvh5$G``c_zUXe&f-k>!7k#-(vVh$^lZBlrg>ixNDj9U1GjLHaO z6*-+yp|Wgf!SnAPR3q#k`^W+h&gw#bup9I@>W&5T{`9$ zX)@JYXPH$+huwjLeZlwoNh`I z&qGqm9id|HVfCp?C$uRBs1IsMG(hdG0)mh~Qoq9!n~qW&U7?foQru|0vBdAaleDsr%r3O0ESsRdII@1|El~Uhj2H`Vu<{Vo z5ZYjy5tx_Xme1`jmnyn(Z2mP+%;sigqz0hD^d9VUZ6EdRz6@>i{R2O7L_`ZVb+M~c z%<{f42QGvTS~wy&@Tp;Uw=X}Htj8fV{LCE=i8Uy~o`(2mb}Dn$p|zKtgy`SJ)4Ig( z`Ql(H8~wXTkAJtDc_agWuD^OV0hga5z+hD}2ivBW0jFES(G+GIi7D)nL}62K`T5IX zlSnpZUpSNtlXyKTnnaeTS*MRk8n%<6`}+&&iK?$K4K$pSER!jgmigF*qxL!qKJt2A z_^z^Sr}EGV<>bqa12v+Fe8xjGkyd{gZb~MyE!Ez18KLTAXZuB9Q}ucAXiHIX(R&N| zGMtRHbTPwSD10Znce+qmo@!uAeS;>n^qk|Cat-?o;xvz@s?YL6+oGvt@YIKBc%{t1F$B2D18MaVc)%mqG|0Vn>$X#xj#BSS^y! zDll1K??0N16(ZMJ^>9NKm>Vs6`=_hEma=QgWIna7O%+b&pGBg}R&RIMxzS`gPQ;JI zWcIw#pX$pM(WE3`zkF>vzk6^gI=?G=DLQQk${Ncy#9GeCxU%yVx=MOC=3$9R;~>G7 zP`V8{#INQvYO03T*KP~bw4wYUWg5~HZeYY5N+-LgIQqe+3Fm9ip~=}?W||hswxDf7 z?r^Gj0}9+G+yZw!mhZcX;gW=0<=#>SF>;uq5S`gGyg9UtOxT|yOS4ibRiZ1ygl0C> zpo(aYmO&Lw$g#6MwOTp@_jOS;yIpI}dbl)=;~B*Xs`@ZTs|*@ zIlk7OGD9i3X{aInz1yY?w01ym*_8dM{&ckl>uA#M7>$(v+ANhj3w%Z896^+OCO4Qa zPE5l#T8byjUDZkN^jMBJIYQ+rl)MR8-zZ;#Qk;(n34+;dMx$MK;i+B}6LZ2mZCg(~ z)Yz9VEc`khxcG7hH{lgrRY>L6CjNxNV!!tXpRDDqDir#R;*IcRDUj) z9ZP3+MU!ruF6>Gdee--Mskg3YwS=(uS`p^a(xl`AnxYAH2FtSLNh>DehDq&3!eA+# z?S*Rc!jF6{YtxS8H2gcH7udAiUVg^nIu9*_j00|kk*Ej^c_ zZHxg5ErZn%Cg^7+wE2>3Yc5R-zmP8?XjxinHTA+Vt-b2v3AGpJMiG6yg|-v@I>9D} z;y@Jt73|J#m{@IM895b+PqFnv12N*Oa{gvssu8{3?fctcO$NJ{(LGQ=#B z4VZHvj9KX4Y>rpnEjDMbsiBt}+9Z-#1}J-O$6*(THj2kth^wmF#kPy&Z25GFb3^bD zPv>5!l(h&6rzWDX8KZ$(L)ayd&|YCTP^X~va#^&Zfs|mbc~L*Fc~bTxY>W zOn7Kq$S^@|Ld(zH44J_6qj+5Zwo^2Hc=TE*z1OxfXYgq_Y=zU=%$3lOm(j2|WJgQe zrRk};WMe!dk>)%tHOR*+4-6JEFlhlJN6iz=-}djQxu83My6o_41v`PK6~uotsF8K` zfgYJ)5ZVj}4{U27JOYqT>iFF|e%%nBgT}1%W3V6(_#tw%0Txe!IwKAs)iGUx}7ZT?CoGhr!Xo2<*E-qj^rnb zxh$eH)n+9rX3*JjN;4zpDV9z_eT1ep-(h#rH@54mVSd2&VQJd$iVu$srSTm-``fvA zN=H>fh`|t^M9mT26K_yFp-KEoClGSV0t-!2@3mIUNpuqF!68AVp-H^%MIBP7c-+~5 z06U6FTRMsK$l%N&Q-NIajIh0 z?+R_m$x~20l?j|rLDU-AvwV993x?%j=j0`_72%8=)`(7ImgLgFDU8t?qEMzMCbeZl zb7Iq6tTss(^n{1kDX>H6`-d^DLUR(Ml2-HRt2GX?W{b=ytMEj!Lg!K@)d3_P3YmFA z6M5mnjnUxI((@8EhJS}9^7<={3+!uUD)}%#q$!Gf#Hs0PlbZ+Cuw~k zT6?)fc4Ya|#gm+N@s$Q{+M6SnPDEo6!<)_u`Qy)*PlRKCHAn*i^ccf1x1$=@69j8- zcB{i}N9Q_N4h7E1_7j_9OWp>nrzibG*G}aPs0QV_%{QV#Q(0zfAiyfLgq&AhDQ^)o z(VX)#!y`1WVVUz_UC@;0)vT^4LQ~ZT6>YLsaEjZEDIN57Do^k}ABY!3Op*Pe_3~1g zehY;j2zXsO73SNl@7!C^Y>q4;QgNJHiPx++u8WaHx9D+Rw&!&Ke#JcOg}OsL)K6+B z;|9~i#Pws_-0n!9t*R75lWpMZ;7pWh-R)Lyve0DGWZ5NjZfG)3KZTuv2o(v}%@oi0 z-U7?d&}3d)`zCy}1D(4dKNVaDODB^qGRDTG(+)LYPV22C*)*&x^~%B{%7+A(PDc8} z>%U~7p@SfrS{+xmB)z&(-x9y8*fQP;4$7_Jki-(b1R+GZG|qiRr&~IFIy9YEOlktJ zcH`v45Va~caYH%1bkT9cOXues-eVm7hEXnuBv+gcQCZ~Bp?0UM4_2H`wZ9y#ko&cw z>qo7w?UzNwP5l}uwhE%tq1h|-O*sGQ6fURjqqR-NsLh(TF-C}G@s zfsTsOqLHF=4AiKx!l4Ph?oD%74gZ4A$(`WMLHH%oRdiNfD>f9>OXyQ+_OYU+bCiMM zEi(&zd{$hjoY3}Q+dXFh7b4)ovMdahV5n!qi6dUftWQ^S)Mq?1AX&t{WRR)P&}m2+ z(gkF$;bjLO3KG|6c*<0+LR)TLmYDl|roDDMyPlk9-Qb~sm&ViWp%UVh7nUl!CTLSl z94rW};oIHBU1a)?ou}8DK5b>RN5H;qsHc_EBnqD93N5Xd(l>E<=NMs{@abPp8R~}) zIn5M2_!XU0#$s?Yw6R_6T)pxJW{|2*dFGHLZ25;veIW6N2aCP7E9h*Yj-7G#`4KrKDvBb|7?b}ms}%0PS*-7pLSaAijrMz z6v4ajIb2p=eIe!vy<^VExm#&yrG-cEM0 z1BuP3<)g+p1c?hi;b_1`@;ci^CZ@5!#97Rxiybvp;uJUSPA;8ThJ-1&IugvO;wpQZ zqt8Q1;^@PboOPs|l13Db3OWP>EMKJ`wCd{;wZIzHRf!dT#1Cbap^13gC0+ zV38hvNAA)bsQq^vd(1fFJYEIf!CRU`u(N6h3W+yp4_&jo_F-zZ^cO?RgB+^dtcdv8>ZU{`qE-m%z?g>O{)kG+fT$X4X zJ>2hW9$U|`RLpGb4?A40tJsVz$#A>YFD2o)Um1Xw&Ds&#Z37N9r`-$aP+TKJ#M{T0 zb2#lJ>JGd2MXR#NgTQsg6n%7^=9F=BbBnK*S@A9CAf=fa8pm^-bwt_}%j)UyS*zh} zy4MIkJHt~IyoZABg)_&|TBOr%4v!^iGUG&4HM(Rg#Df7iIvZWxa(m9(ta zc3b=n$B3V)!8;?nA@TK1@`jgMPnLg6<>8}e=Jv$m6`JblwZF1NK#)->%5Dh?V&7%U zByudmSl6IBE9zmHLE2?2(m)O)yl&-PYWZrG!}Z;32=P#}@MN@77HYd^eo=HpNQzfnKF`VN?oF((XS3X7^%FtXKz`W-?U3BL zGwCEI({yHNAUnGmFZg6<(Pi@M5CX0Yhgtv)CffPEkqa^J4Z$rrifgDwODGRLIf7Rv zcJHKwa0F>0yqJQAf%@!X2H&mCRYeM)5QXy~r}KMJ^NM)VAPT z8wKCi`2I_KqwqQ!pU>%(XJQf)E~Ss#Y1;olK^7#x@R)3`)DpgC=$zoW=qt8aq#-vB0e%Z{{?D~!{rxo%5Xu2ztb;!eO+jfmi=ErO3hE+V;#gF5(l*%}c|x+hDouXxYd(SYNBlV(9$ zBzB;-0;HP}pFca3bf#iHVR0dF))wW#!1VnKLACs^(cRcI<8MAm^1tow*Ba74NU$5W zL0!;$N3B?&SCc5g2$fJU$KOEhWJ?rlcwem@cby}iw@&9vo5Cgn7l2tyMXAl{sSz6I z)jd%5Q!~jnfc>1+vNSkRK^IgiR|qphR})f8S7Z2%-uL0(CJ`M2o9--tTTmh;QgSMPooY=N}rG~Spbz&y;9zIHE zcS3sD*t1~o22ZI$ot`fRvOtYQw$XfTcV5-Dm);z;2xbQrueW7bxOd^Sjl-*nb8=RW za7)mZm6`3lOgT_L$bmu*)Po%S0oDVV(3nYVT#wJ=tx32X`Fx&5VjN+?gn6+Uyu$Ft zbdW?A;T9&(C|Fq(N)z1<8HRsK_78W=xQvN;mIVnN&%?%kx&S8stZLt&u~u znE`r=xW)Nj_=>u@xE(2N;G$&C6-1zPBh-yU4s3DlOE6%vBflY#u~_6lN4oF^c%zZRx_akX}glgJ(<9Eo5p) z&ce|sg~yasEO9D4!w74cA8_p-?%AAllS6$j-tTlb3~hCj8(jf6_Q9LichOMK=7C=C zvBxd_{UgayceH0cZn1>k9Kw^F?(i56+~#oM$zyntlim)+lcEDOebAXj{5v^PYo#Y4 ztvSGO!8d9YcZf@T;8hcB-|3k67vYtdkZ|C}DC#apo* zEKaeYFcBukt4^1HRzW-__I-EZVs2POHN00#2WSw;OCzDiFR!6n(#x!aWAUW?-@)^&gJbwF9(fwZ zqq4E7F}M?UXR6Y4Zem?x9a*U8WGzqvkEyeb**(k1hFg)d-h!_f2{3rDVTg4J&n$Kk zHhG3_hpq{oHneL`p@4t#c&wVo&O%IIs)TTGI>|Is&8D_4Uap<4APNuH5u;!58-tId z#;DB_b;hrdIt#puyPp)R{=B8rfuqD(ysuip_68ntbW7t&*z!{`gr3qm4VwutO=TwZlhS8vx}XjR8( zGTDy9d9bIY8Kg*UY*#xi{Im|r(mRRgF+-Lt)bMTcBYo{0f}-L@HJU$>z{7vr#5TgX z_FN3|P<7pLK|N)KrN^7Y`e-Q*7E2V1*1>75pYo)rcu20z-LQ3_FO}lnYBKcXCOcHuxcgz1*A6Qg`5+nHi{3 z+-H(KJdMvW6HoF&bnYTA$Y6eq3txYZu(Kb}hhgQmhh7tdV#KzWdBKwF?sV}e)H7N- z3_S{d0yZIYHA;uosNos%|<7+@=5;G zCYrE#P`SDGOjmnrN6ziawx`|JOv{)%*43JE+Y+r~ZRz$*OKS^-^^8syJ6(0g1$$S7 zsGNA+C)L@P&tkGEW$>anm6PocZ*F}|QzK0jVrqe#r?%^cS-?o3dBd0q^nD1{ON6D+ z5p62)PvN!#*o7Jk4x0#UCZGqj@DO1u1Mh?Mu}aEH6q2#+ba`oMK#c zO;yL~HV7D$dHjZ?4qGSg*dA=LkxOr?8+K&R`T^Hj*CLijeNGDcx19FP>0LA_iT0ui z1M^9J7Ja;#&%lZW$1^wEt#dr_8Z*>8(J1s`4XPHr`lvD)3~KWtgK8j z>7QaL#mGu07H{nNrbVg{aiHN5X2VE@dGIV@%EI?<#Ls=sEF&O%qeVC24PmE!Bv0?H za))Pg41LdUzXsO~4!WkU8QNsQFbtd5Ggz>4u8I><*90&ujkRKQc(m@`ZA*4HWd#I3`34qvQQ?F)J|5U zEA1Uim>uDI%!&7=MoY2^CXGEh5T*pV18w5jp#$odR`ngQZ=iLnPHPhHcxSznh%%9Q zvwcgZP-&aM@F-?xXg+2A82Gh)4=y#u!lM4Oe+}zfFQKhlrZKs~IfWf3bR1qxk-Fhk zQee%L282#v^-E0G#`?y(3cZr%??eJ>D~BEpTg=6J%B%wiE*Rc~`O7KibD12u>O_TA z@cyd{yQr-;O^*&=FpMFAoHn@w7a&K@v!g!c!KaOQ&I;!QX7zP4tHZjDKqXQ0AeSZI zG>lSum>m9s0qD(vD#FsuMRX27c@0k-*&!$kBBte~a_L%VpBCso%#AcN>P%@VKNLNr`0!4pi>86qc@-#QJWj){MJd8n|w$l8q`GGol}{ zI;M?=C`&bZK-V=!eu7SHd8>++L=3CaVy3*ugUmw1XgsXAYm@DGhlO4l!M@0dE9I7D zLYvQv&x;SJXA+7NM;GtKCLTncXfdM_%a#(>JvIITE_NL*pv@Qhab06?FF62Gsm=ji z0I(Fh&=C+r2uHz8gCHY?5i)O})1q`86!4p_KtpT_cv99SXq(_M%q2e4P=>lULY=lA zJ@vi;zWb?kr6Z3gz6<%RG_;u*qFXew5=pXDdJ_Y~_zMq>7!fd#w~WTQPeKb|^5n%S z`m!xHqoPw41nWz_nA#S;YG zMA{$jRM~!!E!NSJdZ5$<_N;op&+ETShr`3>_vHE1IJ<3@Q@y0bsr7h}#_D5{3n`$L_`KPcXnNK*rsg9xV=wPS*Ms?kHE^(6iMsiN-?%s6 z&oZujP|(PzPYCVxy&EV!_+LENjG1mDedR3^aJHAK;}WaD3%#%**Mp3L}?}0&^Y3aFz(3p6W@)kSi1bBTwoc+s`-iWe4zmAFklUUyjGen1TgUrv}Dum zE$|UwqUmtl);Kl=(k*evZHZ^b#+^i4OT2B&D0U<2$JEJuzU_KbjkLS8Ttf45bC8#) z!D_{Rkg-~+tC8IbC<)KXW7m0Lpj#ZHBM!uj{RZ0b!Nc^P!0Rm@;;>7!vG12`QyL3c z5WsJ`JI&X(reMh@T4B7>Ar}e`BQsU0#8CB3?bLbv9UGz^9cgL9^rA5!9OQw=TVX^O zcVdermz5p3D!j`TYzves!A4bMwq=QhZeN_0tV11i$EoOb^IEn?B3;2w z*FZH8?KPO+MN2p8v`!Z-(s8$KWwgYPhOCD(V<(L7-T71o3&Ko_y4L8Zzdv>Q=M}1A zdMbK$3AhndC&(PuI*e5$E~G}#qpT&#CY`}rk_XHoi!4E_M`A?&HF{tIExvw_v<)ho zN_4pEFLF2b4E13jvVQ>o85ru{GQ7EGbYRO64WGc;q|f07fH8pSlvfuReOX+51Q(j! z8zg1Iq2cf5t8!dI+~V+q2A7j{vUZ)@aUL$=D&k9Bp~(81s6F({5HR z#*@oFff2M+yE{Tx8PTD{EF0wmgMPnv!i5iEm)TuRm=#prN9y0YVH-GwyU+DLAv%%< zA0H1$6H2PLqBDKMPg7so({_>B zm9Doxda1cr36T2!}^0<9?A>*|1 zLWcIbM@yn{y%vB)K<$_y&mJAa&gKRsz)h5ss!3I8!%J9K6tYT9zq09S=@CVeV^5;P zb7!sAb`_md40-b2Bh!$Q_CmC>dyowS`Bi#$lTXJrU(VbD-E~tz?i% zKq<{5JlBhL(}7>e=pskl`aOK2nWLAx0+tvO!B>pJ!xr$l=cvnx!!vAbG%hJXP733H zm+`-B=+fwb*Sow5w`Rxi=p4zhiv-F$IH{SPyuOmnG{;_Gg+;%Z2|0SaEIk#{dYRYK z=nZ7@dHd@5qd%nd7l;*@X2MasxXn?lAwAJz&KFYAmD>hr>#CC1~Sn zKp@~va27c*03d#u;@W4#!mE|>|$ z8XXr23CV$J1|tOjL#U80##>s)obk4}n@Dse+}5#{Hn*!Q?YN1yw$9FMX9n?4In{9N zZ1CxJ*7#m690ymg(M4LguQiuw@vT!4v}f>&)0spd?g%s!j05=J=(bAe@94$r@R$^s zMwDg9?G&#Is|wF^H=tpZSilFir+guO*ia3R=|iofg8KNUa03kNLJcr6zEsD`Y{d(J z;Y~Y-Xj3=tvNoWor~#O(ijkelK^X%(DJoDub*DcPwz`z2zLNz)iV7g&u_WC2!<(>( zqLtoKkpL@NwD^`#Q#eadP+`cK?6km2?kf~Vrpt6Q6%0>vfg&6m*rG$p$c@O+ zLuNO?Z1;P6WE?ytQL}VVG5$Cm6aINA(1-t9_R5!z`o*!o8CBuvO`h%>w%6griW?`E-VDd?Sd1Sr4C+z;8mY@V zxb+ISR+FqAyq3m>0XrCbCDK}U6{*oj_y8CB1$Q9zjMYQWeX4ybpxO_0myRYxSOqwg zMiWG9An?%W99Dx3Zq<$f8ScF2PySWY#RCJtEIdUJ^++@X&my|GR^6S))xijY!D>aP zC%>x$jyD^-GvNuf9W6+P5ftMhC zHj2=?eu_WGo0y1cgL$Q^Q=g|U%#lYvF!iP;oW9a}dek}?2t9Ctw_<7ZLt;wNP>W?9 zMG07sP{g#*9~DxFHqWoc@_ozS$9tT$b9=P+Fd zg+1K5kF%BH05t|w7OFJghzEmX+$oN6Y;0^NcDA(Jq#COVuEu-Ai{v&L5Ad(13*;za zCF{?YRyVXIsyXXa+6EPhu%# zVtU9cU>)b{aQWCA?@-X;BRO()akh|}VPB>O0J=IIc+IdOLqlv^ob+}Z5 z*1|Dxx&{QM-nbY1;`Kep@vAPce^(-% zadJ+sqchh|0_*6N1*}n=yn^lIU4%e5RK0)6R1oIY?sb+7W~?vE9NXOB(MC@BQawVS z18li29pmlJc%~!kcD2P(m-dcvcdRAX;*!49RovNn)H80)A@ zAxiSUTB03?TC=4oy|vL3zFSMv+XphWTA_Kgi#u9MdT~Mxj))ZY_hHU+`o>kMoOhUs z^0jrlNyY1&yk8ltb13qbLr2s^8mNkUBVCBH zlDM(-Iu5hRKbCGAAB%UoZBADkf{}6wh@-93jc2<$yD}~5xD%&KRqEQxbF`v;$>2Z) z6Q6+E$uUd5IWs;|&R1qeOQk{;Zi>1Ol((xaf7cT6+0k~JtbEAyGA02|#_*)B{(D#k zQf{9OO?4S5`P`9H9E&j;T!3{6S=%^0mu@NHx=lJz#oUh#rW(!^@`D~LalcT&M+XOl zIPI|EIBujNMg)Pm_)v@pbi;pRjEFx(B4CT;sb1uqjxbUDJ<;nPVF!VXCXsmyv)zhL z3YcR8m=NGIg@&8ObtE$mG^M;&A)y+1dP6s$?7YJy%P!gKhkb2}Ixv@Y;f!v6d{4k~ zU~?1F!WqmO#eHBIjY~k}8PNvAina4N7HN^*V$aIteGnX6*<b|r&L+?pb26ao?(*s?wrbY2cXNK+TyX7fXf;nQX>Q@*s6d%ML%o2JB zO%puefJm@;BbFCaq?s9h^wio*>_oKsbQ!Dh zy7w2VkB2`%2nhi|VJ>2zjm75$NpK7;w@1!4I2&Er0u~>bOli-876<68h`c~^Vu~!` z4OW;*=G=pK=7o>-<9-Tqy4%f%zVF}2fSDEH{aRvE))!FJ(F@-nU6tlJV_+Y_cZ1MW zw&2VK0#O0vVk^m&74&^*q%UfRt1o(oi+>8=;R3tR9WL2*(j6{{#5>f5bJ}h0aEPM? zN}b|wxrFvM7V2BS2ZJ|kBR8&eXe2k_uWVUueVf7-JA#n!bEzv^iLjDu0P=(9t)DBI zrX6Q9?v&#gtXaOV2R*lLzb-!&c><=UG1q#8-G2a$31#(P6=~+%P;^3K@*TQ3w0@@s z?g!jj*oi>@Wn$9;yOur=wnK67{rOqER+HW7P+RMru0<#xZksM%ijo*9Ux z%EeBqYZ!Kn!Us=p|MgV)?oMN^AY;0@N5g6SM^{mRK{OO*H5vq#S@3@;JmrutlBl~p zHDUu%DVuRi5-z%vIQOJKR2}9~!xb$%X@4m>g=iR0frOq3bsTlEdnb-Kc+TsEVdIjQ z=GLT+uE`0#?nN!mT?2b@{-ewk|6fmipE}XEbimpXb1-6MyO55e#wmn zf5@(w3rQBwg;J-68+1ZNO7d%G8BB)1wbAzXkR(5Xq z|0Bf~bScE$0qACOA>i8(77z`Quu$6KLXcQkYVoKTSZ^K(*aI*e$U)Wa`SSwdC&nwQ z{we#2MSY@-9?H=cFzEs6u*p_Ejsew!yRFCU+do%+*GRPcj=Q2)@u0QLwiBj!%(&EH z0}Bf)?4@o!2U&E{ieLbi^eoxy*5-p`iv>o*wwL1|+JWN6>6$utJSnQdX@x%PEn%4@ z(K}eUngu(RZb>V!b0j^JqtzJ#hv0XN(yq}>LOF18Lk&~2C;m82{)Ar&$S!mEDrbGy ziOT&tBQ-n^5Lw>nD)O<~QL?wuh2fdogc%2w8y)Z;_xDd~P8>Hem*pT3dmea4P50S+ zC%46i02epyBx2tXv1x9t;ovr!mAtQooVWTi*9CFhP{6<9-;oL1fn3^6Z`#Z6`F0$5 z{^aIGbA0(wo2>5D3Eqe5b-x6K29Dwecbw<1`vXjD4RvHQ19N;?c#wro5Z0;z2H<8m zXXK_~y_>?fkikIm;)NWEN)!iU2A)KC5VXzeTXj?xxhzkkETmDq7!&Lc!bzoCr;f^4 zua9LpQ3_pIFH69msR77PB*Enx-%f@bTJUse{rWLaj&Sqj(-XxKUJFAvr;sY$KQrNZ zwo{d4=83jcKX*tt&bra9C3v}|Ser`8{*Z~0ii#d_=mZ=DI6Z~aDL8qJu-V*IgEejFG_$yl~f-J>_rcsDhAlW1f=?vxlPsu#9n|aOuz=#8u(EyMXp4wFxiU66u2&)|8>c6S6g~FpmL>|n_%YFep4ykA+l6p9 z;~r7g)Ih$DCw;oEX6u%kccK?hSs~(L1t)ramsVn6@bHmOYBrrlVuz8BHeBBZy0lisVw`x41iSN0uia6Nm)WL-F$tmdA8! zC|izl5+(5LTx;-YI$RFV;utNBV7se0ldqJDdQj9ayOr)sa;X}Ja-dbz&hLcPi&Gfx zIPMWBNJIxJYnZfy3w{^8wNW?7VYs)~He%X;WHiHm+%JAvg_h%V~NtP=5RU{Hb4@?KW4Vf--; z|3kjRV2s0|-nU&hY(sVryGZZTEn8V*b?{b*m>2<#jVp0sqaX&7E&`e!$2Yf1r%!lc z5zr@(`z|Yvcx@ln3z1D~wm1tzKj^CK@8|=niM)T> z=^jqcff8}-pgJde&?#;_>OEY52=@R4FKEAEm?(!?^5?owE`Uy$yQjK)!|@$pOhq>` z$f=9eufpuFq$cq{@Qr466#7nVyJJ#S1MdKpu)3MZw)J?#{V;SEaUKMH%+!gDT_1T$ zy1rng4npLxA2zB!$Z2qd*OW*g_k@9hE>-;?%|%L-6f7+aBuMkXc!?L_wJVep)r<`W zU815nAWMdijjpl&wz znVV#{q>5SYw71_o?Y*Wf3UPzu4A?t!PFBp@ppA(M+ObUC&YkxFGrd2O03yh_NN&i_ zGYX|cvhgjDj?u@+;ROh2a}oIo3MC=@D&yDB>)WZsBvgs9>)kqe7zQ`dqj7V+ut>RO zS~^8Vc$tf-x;urC(-)49TT8Mm5`pu&vl-kxFnaZlDa0q#TWW#HJQt+<<~*G3W@B^! z(cmT_h_20J?3e6ZJgizGpfpoO8E76Zz$`;Y52MXsv*koFrLT(T9j_9NOe76=>IJfA)IKFD%Y?f+2yJ@CrgUsiMfO( z^n<`paY@%9a*$scfEi3zw~<_P=VGNOj#(y4G9OBZQbHn_i!c<6^vejY)dQwwPpZYN z#^hQc^ndkGuE=9G?jc)A<~Zc&!nLi}C=m^HXjweNzJ-44BPdwVu3doXxg^68w}~n@ zX-*0pyVd2Qxb#Y42AXPbN5ySsM7b#9NHp8X^@=%~F^f!rsz)v@=D`>un*u;x4x$*c6N&Fd4a65~kLyJM<2d+X0kVa;nxii(+ng}#t zab(@jZDp0izHy!I=R4EY!*RAylGe&aYK^imiHPAPpNdncfvpX?mgfSktUxve101#YxiAG5@?KUJy7KYRuPih7EGj0dZg^^;N4yJ-oXa-&ffAEPQ`EY3)GW5fHfN5-noOF{S{$hl>Cz%;c z0u`WA6(ES(*F7GU)Jfz7dKBnF;l6lA0suwMytqz`$JVb|LUTdk1<~qlLe-7^W`mh{0-MAJ`>VRYlDJ{aMBB>7P zoZ}}@tbv|>oHae_A7`E(r8wXsxy)+{uPvt=lCS+-gy~VrYevb*1yBuGH0Kxyg!QS_ zT{N!1bx^uP?=)a*u}ko=`?XWLg7>ov;tfel@@UAgGqpj0b(brzvR}ehysCkx#Gu03 zIR<(OXU{C|BBNYl0a+YSREr!t&{&_ory|=X%&icf`8m?2Sg25H^Q`Sf_jMrI&~B}I z@^B6V5fPV%7b}$nF-EnZ%~!M@a2H*K3mvI|>M!%;e2jjeHRIu>$DzDLrU^g4Udsr9 z6HB8(NIr-dMncdhSm0nzTv6_MRv=RHo-3z`YMLyjsmY(_;b*32NiZ8ZaY;T_%!Lxp zWC-USU{Gqma?PNIV;1U2LF|7jpo$=R*ceC}x9KYcnIEKr|;nZI$mtec`H%R-UL zS`AA-!C7GC56>mzmZ382MCu(xN>!cx;p)y@WfC3MiGhZ@!&`_#wcxc;Heqq;vQ%LZ z^$_%PrVz+X+*U`olCqi?j71q595wP5Sa3ug4~-FFVv@aHCR+w`Bd84h3w6oj+z1TD zFG6LI6HFPrB)5o_J?1v(uQSFnrdzU7fh*3CKYa_5y+b^Wr_v|D3|xfbB9hVyYp=Mt zScxoLRg!%;*HYxy>>hR_)J<7GJ39|$j1EHs3MqeO*W4ARYo15zt)kepO=|bR>%4Rf z(0KN*ZJ-sPTeXyPPVXR^VEKS(I$aNsEG7zW8kNmgsXGEU(ufnPG{bPX+v+5PbeN0= zDMT6&R%tfJX{$MD4V%rRKWS{2T(6o0Q!JBP^*$l18{uE~$lvMSmqO~%1R;}&ObN55V5eT-`!>CMTQl4bTv(5?;P|-HQ zaRX#*>e@;DRn(R`!kjJ!8%V~-Se4&7JgV1FmJWf9Tl>BJcPdx_M)`xw&f(P>I(Dl+ zWZkG-;=S@b0;UirnVbwQL(kSJhhLj6CK}a-WgATZD?sGXea@auw5TKOAf_!Y2k4b} zkkC1ks@#!cjN&mI_bgIz9<0Ne~C2Ys%J2#+68?TAJtIzk_17fu)J{D1r=bvc2Ev7{*OnI?HLtH@Y!&I&X(Ptl23 z{4PIvwGpp+^}JsunvuIq%bA70Rwdap%g5&mxdQ$nXl!x{u)YvahE|+0bLel z>?JsEioB5~9os7&K>$yUe(~F4s*(OILM1|{uBWc2!Ma%ji<(ZRUgT4{Go~@8TO3Yf z>14)O&G*B(Y^O%O%%C%EyD-Q&ehw>WgNjVJ%EnWvF}`A1(KhA_$*9Q5iMsiwsB0A# z4lAI`;0*i|)EPU;;1IT#!f>%taFF$!t`JJdS&vu8#Dx0;YWaB|iLD@D6qlBkGq+qE zN3cPpU7`=(Q_$!P`V%{3l91kWG8R(?7T~ESET$)lGO2b-LgrV$3*oh)C4eX;8-eXJhjC{3?BBM6MC&4cng5p+0 zfA#|}+nI8a_-ouHKkLNf9iq1y9;;TH{muwQw08$^9-5s-I%uM%c6HpU*9YTaV^kMi zw=Gsf+HX={!mV6|7M#1unEJS8p*JxMWK6dVu?5TzLF`=QDtnJI>r*c8)Ady^uSaS0 z?S%PoXz54SqjD!TtZ)EgshuIJTc!>Jqhn$2Gsl<>nw6zK4Za7K|XlAxUVgxeSODBLj5G4|~A=e8&VXc8iaB-$MJS7#0maLt17dMymE zM=7IubYwX%bUdxIYiI0ESV|T-G0@9?fGI+zy6Ui9ulMUHQ3%a;*uz6G0Y>8{5TJg) zT5UAi?K&~YHi1^;;#xkBA9vd^NSZW}w+)VoEqEB3Ib04RVQmyZhk$i~uy*h5t%~ol zMi4>2tRoWnsk^tPOg>%=)i-k~;o9jR{fp~GzaSKx* zu4qpNstWmjqdqs#<$V2OoPJ&!|Gjx1T5_09%4%o$E3_FJH6RyZmJk@k#>x>}%k>{h z7C;$rT^A@4$d5zUu>E=4t=VXa*!0`y zWLS)kZyjWi994FNfg$!Nbh%e!B+nxWM68^g^FocqObUUU6zr``nsVok5W$2?Cz|nr zc~nH&z%bU*V<=#+bVb#IZi|7&m_%=(f!C0(1N20~7&iP}tL_gFTmaQf%O;(gKm!N? zr2?4L?2IzKC&XsmD62~%lwM)Z$rC4zkx1+CX55Gpu|h?rK;VK$0fi87W6`a_$VUZc zC>4Pb1E7Y#>6hdhT`M|;`VQ3;Ss1rcRF=sP*$qCMI_RDb(_ErLxC!IrIt2_r(P5g3 zm+pp2a)qguH3KZgzbF$+z-(%Gz=Iys$k8yQ48YjbHd(1oI&$x&vv1>9jyYq)LbBZ=it?W!$*LX;eu_ySP zsudZQg2@#s3lD>2Iqstj9RP*&aIxe+bVxHndj%G;D14Sf5Fr!fnd6w0ahR-t(bAPz zPZBlr)pdQ(V>MC zC}~T?wFO%)LYA}RQ3GO27&%fJ?>=X1g#tYEw9cHu94!m~Z779@apl}Z0k{Mm5*q64 zz9Kno#(+3Kf#h@+Ot6~L4k|QyP#kO?Ka}2Cp05h#Rb*D7tp-(uyu_0gfug7u48En7 zl@2 zl9?ySd$T;#q`0=-c7-b<39lSugTCAaECj^)hYv){{&i>olX~Q+${FfilBSPl8@P9e zJ&I&q8WBe1)SQEkEBzJsI>A!*NX0E-AV6m$%r^3NVVPsJsT!`e1|4o25O&cr0YT4UKSy?!%rKGPB{P6d7|Oxe zT`d%UE;s71Gu@T79X;fjILJ{J)#h%!(Hf5W>1Z@=rwwqi(@vw6q^-$ryFY1;tF0yj z)z+troNPI>t0SfxRV{otA%@{=EN+NEhbVXhrP2p(EKFP83*b^1%7U3^ar2fYhctMB$@Q>*VKD)1F!<`VZ4FAETN=hXS@8L8J^FTUNOvW^bb7 zo9}3pnncp3DIkj-cyvxS%awc4O|^QApmZm1znG{Am->`-NAiYO=;^G0+yQm0tIquHsxQx_v%7`A}P^HjP)IZTj+&^C7dr1<>dL(+^jf!IgZaD$uW9qe)BVf_IB-tpBFTwnP zX(v<(XGxZdB1U($Uj5z@{8KB=y1(31M2pf;^!vbsGlH%XOLHYwsWa{AL=k6#Nl?4Y z)rI3d!d5e)?d8jE>EHybMr5*PkHdlQWYK_1e9m=(Fipc&D$xWvSfdFNspoa1(CAI9 z$-sOu0b;USny8PYMY$<3ybHXe>Vkx!f}C6mIOd3gP7j{0#;RX?6Qp27SSVlnSYYyu zZCw7C)(`@MIaC1|M9V@$sdPEZn@XRHEL@~h&rF&VIRV&@4_hyT^ zDfdW}2?~kUqqR8ylIh&eE-rbzwM*(#EKLnMKm3RrIV``foV^p>GzcCr2mq9vpqR}cH=k!^12Oy2KJT1X8ZrRPYpgqcZVCrbceQlQsg z;`2wdUty+1hr9<7i!&2ZxOP2nH`b0B_FJj)VPQx484dyZ`PvjC6$X~*80|;lNIfCL zwvoQMfAU%v9jw=Vt$V`99cJL;?}xJsHKybNBHR0H{G>SBJASOJ_!TE)S;%3{QX|}& zs&Z=pa&BbRl<{c_7jZL};gR5edH}rq5tS|oFonG=_AiFDCQ2@vG)OS5JKN|$<P`_%p8Vm4mBeS%80!w0N@f*@k95pZ!MqJELZT|*DR)?5rn;l`v+YU8^=nnW5B z^-#qf#T?9}J6}Xz^vtos?58DVoloF_7EhfWF`iNkA{20pOUW4w+1ix0yNU%@qtF4D z=40r7y?P0Q5GyIQwL}&l*I%S`#3+9LE{m1x;*y4TMJo!yS!9k_&j++cRD}lpD#%5O zMmR)>p70tCT)2OXh(fK2Oz`>YO)$&h0lqiBTr8dN16K*0QGnq!Re5MBSSs{LizJGG z4ltiIG&zjnrB+AA!A{n#OnFLz3NAx^ctglPe-}YyoPp<|q#xtl2*dgIo2Pc(DimnI z4KNu+#hlQXH=4^js_a0;9q1L_SC{&JX8#iZ>7ufOwQam}Z~kxxl{dh)UOhEm?H?Te zF?j>>8@=?(&gkhJ`_uQ;rT)T|9V0OMkm5H;?Dg5e{B?nfP&m2` z5k!wGJL9u-a*2$=^lXH-_7iqGg!YCw(^}^PtwFZdJ*9n?WYj&`zqvOa8atNL?9Zk{ z>}7!i;(t4G7J5Y44Wt(+@mzT^uiwLNehL46+3fE4r9JuU_$B?~_s#eAjoXH=Kfs4y z#XsBr!nD6I?Qet|ughEI-+o8m zd5yex_W0k>uPblkou_Ks-~H~M{BrlZ@>co#Kh<~pf9@lE{TV)d7M%af_xI%Im+$LV zKQ;~Q`P<{z_XpVQe}nd)KG61`@&~-`n)W<@-U@sE{Ee^g;~&4b`+Ik`hfkHtyEA#K z{Fo01FME93-d_J-;5W8E;6`}uE%(g3yj8yO>-x_2-^9Oc`@hC_JVm?z%CkLu!t0s* zzry|I=eoAT4@V{P{vc0==?J^v5!J=@#+U-?AaS3c49|1{vQ{*^uc-{GgQ{g1xg zm5qP&ZGCX7-|}twSN8ZHF6CfBu@hADfQB z@ynMzuHDaoo)X|neVZ=yux=k z_JVCcGRJ@SZ}iJ=;q8C0p*_Csm%K`Q?m_d)SN`f{`B> L-^nz{e60K*rKXg- diff --git a/res/shaders/TextPass.slang b/res/shaders/TextPass.slang index 5dfa838..17463b0 100644 --- a/res/shaders/TextPass.slang +++ b/res/shaders/TextPass.slang @@ -9,10 +9,18 @@ struct TextData float4 textColor; float scale; } -ParameterBlock glyphSampler; +struct GlyphSampler +{ + SamplerState s; +} +ParameterBlock glyphSampler; //layout(set = 1) //ShaderBuffer glyphData; -ParameterBuffer[]> pGlyphTextures; +struct GlyphTextures +{ + Texture2D[256] textures; +} +ParameterBlock pGlyphTextures; struct GlyphInstanceData { @@ -25,7 +33,7 @@ struct TextRender StructuredBuffer instances; TextData textData; } -ParameterBuffer pRender; +ParameterBlock pRender; struct VertexInput { @@ -56,9 +64,9 @@ VertexOutput vertexMain(VertexInput input) float4(xpos + w, ypos + h, 1, 0) }; float4 vertex = coordinates[input.vertexId]; - VertexStageOutput output; + VertexOutput output; output.texCoords = vertex.zw; - output.position = mul(viewData.projectionMatrix, float4(vertex.xy, 0, 1)); + output.position = mul(pViewParams.projectionMatrix, float4(vertex.xy, 0, 1)); output.glyphIndex = pRender.instances[input.instanceId].glyphIndex; return output; } @@ -70,5 +78,5 @@ float4 fragmentMain( uint glyphIndex : GLYPHINDEX ) : SV_Target { - return textData.textColor * pGlyphTextures[glyphIndex].Sample(glyphSampler, texCoords); + return pRender.textData.textColor * pGlyphTextures.textures[glyphIndex].Sample(glyphSampler.s, texCoords); } \ No newline at end of file diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index db01d8a..1b5402b 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -48,10 +48,10 @@ int main() #endif GraphicsInitializer initializer; graphics->init(initializer); - graphics->createComputeShader(ShaderCreateInfo { - .entryPoint = "cullLights", - .mainModule = "LightCulling", - .additionalModules = {"LightCulling"}, + graphics->createVertexShader(ShaderCreateInfo { + .entryPoint = "fragmentMain", + .mainModule = "TextPass", + .additionalModules = {"TextPass"}, .name = "Test", }); StaticMeshVertexData* vd = StaticMeshVertexData::getInstance(); diff --git a/src/Engine/Graphics/Buffer.h b/src/Engine/Graphics/Buffer.h index f4e732e..480c7e9 100644 --- a/src/Engine/Graphics/Buffer.h +++ b/src/Engine/Graphics/Buffer.h @@ -1,144 +1,114 @@ #pragma once #include "Resources.h" -namespace Seele -{ -namespace Gfx -{ -class Buffer : public QueueOwnedResource -{ +namespace Seele { +namespace Gfx { +class Buffer : public QueueOwnedResource { public: - Buffer(QueueFamilyMapping mapping, QueueType startQueueType); - virtual ~Buffer(); - virtual void beginFrame() = 0; + Buffer(QueueFamilyMapping mapping, QueueType startQueueType); + virtual ~Buffer(); + protected: - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(QueueType newOwner) = 0; }; -class VertexBuffer : public Buffer -{ +class VertexBuffer : public Buffer { public: - VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType); - virtual ~VertexBuffer(); - constexpr uint32 getNumVertices() const - { - return numVertices; - } - // Size of one vertex in bytes - constexpr uint32 getVertexSize() const - { - return vertexSize; - } + VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType); + virtual ~VertexBuffer(); + constexpr uint32 getNumVertices() const { return numVertices; } + // Size of one vertex in bytes + constexpr uint32 getVertexSize() const { return vertexSize; } + + virtual void updateRegion(DataSource update) = 0; + virtual void download(Array& buffer) = 0; - virtual void updateRegion(DataSource update) = 0; - virtual void download(Array& buffer) = 0; - virtual void beginFrame() = 0; protected: - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(QueueType newOwner) = 0; - virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, - SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; - uint32 numVertices; - uint32 vertexSize; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, + SePipelineStageFlags dstStage) = 0; + uint32 numVertices; + uint32 vertexSize; }; DEFINE_REF(VertexBuffer) -class IndexBuffer : public Buffer -{ +class IndexBuffer : public Buffer { public: - IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType index, QueueType startQueueType); - virtual ~IndexBuffer(); - constexpr uint64 getNumIndices() const - { - return numIndices; - } - constexpr Gfx::SeIndexType getIndexType() const - { - return indexType; - } + IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType index, QueueType startQueueType); + virtual ~IndexBuffer(); + constexpr uint64 getNumIndices() const { return numIndices; } + constexpr Gfx::SeIndexType getIndexType() const { return indexType; } + + virtual void download(Array& buffer) = 0; - virtual void download(Array& buffer) = 0; - virtual void beginFrame() = 0; protected: - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(QueueType newOwner) = 0; - virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, - SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; - Gfx::SeIndexType indexType; - uint64 numIndices; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, + SePipelineStageFlags dstStage) = 0; + Gfx::SeIndexType indexType; + uint64 numIndices; }; DEFINE_REF(IndexBuffer) DECLARE_REF(UniformBuffer) -class UniformBuffer : public Buffer -{ +class UniformBuffer : public Buffer { public: - UniformBuffer(QueueFamilyMapping mapping, const DataSource& sourceData); - virtual ~UniformBuffer(); - // returns true if an update was performed, false if the old contents == new contents - virtual bool updateContents(const DataSource& sourceData); - bool isDataEquals(PUniformBuffer other) - { - if (other == nullptr) - { - return false; - } - if (contents.size() != other->contents.size()) - { - return false; - } - if (std::memcmp(contents.data(), other->contents.data(), contents.size()) != 0) - { - return false; - } - return true; + UniformBuffer(QueueFamilyMapping mapping, const DataSource& sourceData); + virtual ~UniformBuffer(); + // returns true if an update was performed, false if the old contents == new contents + virtual bool updateContents(const DataSource& sourceData); + bool isDataEquals(PUniformBuffer other) { + if (other == nullptr) { + return false; } - virtual void beginFrame() = 0; + if (contents.size() != other->contents.size()) { + return false; + } + if (std::memcmp(contents.data(), other->contents.data(), contents.size()) != 0) { + return false; + } + return true; + } + protected: - Array contents; - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(QueueType newOwner) = 0; - virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, - SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; + Array contents; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, + SePipelineStageFlags dstStage) = 0; }; DEFINE_REF(UniformBuffer) -class ShaderBuffer : public Buffer -{ +class ShaderBuffer : public Buffer { public: - ShaderBuffer(QueueFamilyMapping mapping, uint32 numElements, const DataSource& bulkResourceData); - virtual ~ShaderBuffer(); - virtual bool updateContents(const DataSource& sourceData); - bool isDataEquals(ShaderBuffer* other) - { - if(other == nullptr) - { - return false; - } - if(contents.size() != other->contents.size()) - { - return false; - } - if(std::memcmp(contents.data(), other->contents.data(), contents.size()) != 0) - { - return false; - } - return true; + ShaderBuffer(QueueFamilyMapping mapping, uint32 numElements, const DataSource& bulkResourceData); + virtual ~ShaderBuffer(); + virtual bool updateContents(const DataSource& sourceData); + bool isDataEquals(ShaderBuffer* other) { + if (other == nullptr) { + return false; } - constexpr uint32 getNumElements() const - { - return numElements; + if (contents.size() != other->contents.size()) { + return false; } - virtual void beginFrame() = 0; + if (std::memcmp(contents.data(), other->contents.data(), contents.size()) != 0) { + return false; + } + return true; + } + constexpr uint32 getNumElements() const { return numElements; } + protected: - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(QueueType newOwner) = 0; - virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, - SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0; - - Array contents; - uint32 numElements; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(QueueType newOwner) = 0; + virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, SeAccessFlags dstAccess, + SePipelineStageFlags dstStage) = 0; + + Array contents; + uint32 numElements; }; DEFINE_REF(ShaderBuffer) -} -} \ No newline at end of file +} // namespace Gfx +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Descriptor.cpp b/src/Engine/Graphics/Descriptor.cpp index 0cf9030..7afc611 100644 --- a/src/Engine/Graphics/Descriptor.cpp +++ b/src/Engine/Graphics/Descriptor.cpp @@ -3,99 +3,70 @@ using namespace Seele; using namespace Seele::Gfx; -DescriptorPool::DescriptorPool() -{ +DescriptorLayout::DescriptorLayout(const std::string& name) : setIndex(0), name(name) {} + +DescriptorLayout::DescriptorLayout(const DescriptorLayout& other) { + descriptorBindings.resize(other.descriptorBindings.size()); + for (uint32 i = 0; i < descriptorBindings.size(); ++i) { + descriptorBindings[i] = other.descriptorBindings[i]; + } } -DescriptorPool::~DescriptorPool() -{ +DescriptorLayout& DescriptorLayout::operator=(const DescriptorLayout& other) { + if (this != &other) { + descriptorBindings.resize(other.descriptorBindings.size()); + for (uint32 i = 0; i < descriptorBindings.size(); ++i) { + descriptorBindings[i] = other.descriptorBindings[i]; + } + } + return *this; } -DescriptorLayout::DescriptorLayout(const std::string& name) - : setIndex(0) - , name(name) -{ +DescriptorLayout::~DescriptorLayout() {} + +void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, + SeDescriptorBindingFlags bindingFlags, SeShaderStageFlags shaderStages) { + if (descriptorBindings.size() <= bindingIndex) { + descriptorBindings.resize(bindingIndex + 1); + } + descriptorBindings[bindingIndex] = DescriptorBinding{ + .binding = bindingIndex, + .descriptorType = type, + .descriptorCount = arrayCount, + .bindingFlags = bindingFlags, + .shaderStages = shaderStages, + }; } -DescriptorLayout::DescriptorLayout(const DescriptorLayout& other) -{ - descriptorBindings.resize(other.descriptorBindings.size()); - for (uint32 i = 0; i < descriptorBindings.size(); ++i) - { - descriptorBindings[i] = other.descriptorBindings[i]; - } +PDescriptorSet DescriptorLayout::allocateDescriptorSet() { return pool->allocateDescriptorSet(); } + +void DescriptorLayout::reset() { pool->reset(); } + +DescriptorPool::DescriptorPool() {} + +DescriptorPool::~DescriptorPool() {} + +DescriptorSet::DescriptorSet(PDescriptorLayout layout) : layout(layout) {} + +DescriptorSet::~DescriptorSet() {} + +PipelineLayout::PipelineLayout() {} + +PipelineLayout::PipelineLayout(PPipelineLayout baseLayout) { + if (baseLayout != nullptr) { + descriptorSetLayouts = baseLayout->descriptorSetLayouts; + pushConstants = baseLayout->pushConstants; + } } -DescriptorLayout& DescriptorLayout::operator=(const DescriptorLayout& other) -{ - if (this != &other) - { - descriptorBindings.resize(other.descriptorBindings.size()); - for (uint32 i = 0; i < descriptorBindings.size(); ++i) - { - descriptorBindings[i] = other.descriptorBindings[i]; - } - } - return *this; +PipelineLayout::~PipelineLayout() {} + +void PipelineLayout::addDescriptorLayout(uint32 setIndex, PDescriptorLayout layout) { + if (descriptorSetLayouts.size() <= setIndex) { + descriptorSetLayouts.resize(setIndex + 1); + } + descriptorSetLayouts[setIndex] = layout; + layout->setIndex = setIndex; } -DescriptorLayout::~DescriptorLayout() -{ -} - -void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, SeDescriptorBindingFlags bindingFlags, SeShaderStageFlags shaderStages) -{ - if (descriptorBindings.size() <= bindingIndex) - { - descriptorBindings.resize(bindingIndex + 1); - } - descriptorBindings[bindingIndex] = DescriptorBinding{ - .binding = bindingIndex, - .descriptorType = type, - .descriptorCount = arrayCount, - .bindingFlags = bindingFlags, - .shaderStages = shaderStages, - }; -} - -PDescriptorSet DescriptorLayout::allocateDescriptorSet() -{ - return pool->allocateDescriptorSet(); -} - -void DescriptorLayout::reset() -{ - pool->reset(); -} - -PipelineLayout::PipelineLayout() -{ -} - -PipelineLayout::PipelineLayout(PPipelineLayout baseLayout) -{ - if (baseLayout != nullptr) - { - descriptorSetLayouts = baseLayout->descriptorSetLayouts; - pushConstants = baseLayout->pushConstants; - } -} - -PipelineLayout::~PipelineLayout() -{ -} - -void PipelineLayout::addDescriptorLayout(uint32 setIndex, PDescriptorLayout layout) -{ - if (descriptorSetLayouts.size() <= setIndex) - { - descriptorSetLayouts.resize(setIndex + 1); - } - descriptorSetLayouts[setIndex] = layout; - layout->setIndex = setIndex; -} - -void PipelineLayout::addPushConstants(const SePushConstantRange& pushConstant) -{ - pushConstants.add(pushConstant); -} +void PipelineLayout::addPushConstants(const SePushConstantRange& pushConstant) { pushConstants.add(pushConstant); } diff --git a/src/Engine/Graphics/Descriptor.h b/src/Engine/Graphics/Descriptor.h index 9fdff76..ca5e700 100644 --- a/src/Engine/Graphics/Descriptor.h +++ b/src/Engine/Graphics/Descriptor.h @@ -1,93 +1,96 @@ #pragma once #include "Enums.h" #include "Resources.h" +#include -namespace Seele -{ -namespace Gfx -{ -struct DescriptorBinding -{ - uint32 binding = 0; - SeDescriptorType descriptorType = SE_DESCRIPTOR_TYPE_MAX_ENUM; - uint32 descriptorCount = 0x7fff; - SeDescriptorBindingFlags bindingFlags = 0; - SeShaderStageFlags shaderStages = SE_SHADER_STAGE_ALL; +namespace Seele { +namespace Gfx { +struct DescriptorBinding { + uint32 binding = 0; + SeDescriptorType descriptorType = SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uint32 descriptorCount = 0x7fff; + SeDescriptorBindingFlags bindingFlags = 0; + SeShaderStageFlags shaderStages = SE_SHADER_STAGE_ALL; + Gfx::SeDescriptorAccessTypeFlags access = SE_DESCRIPTOR_ACCESS_READ_ONLY_BIT; }; -DEFINE_REF(DescriptorBinding) + +DECLARE_REF(DescriptorPool) +DECLARE_REF(DescriptorSet) +class DescriptorLayout { +public: + DescriptorLayout(const std::string& name); + DescriptorLayout(const DescriptorLayout& other); + DescriptorLayout& operator=(const DescriptorLayout& other); + virtual ~DescriptorLayout(); + void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, + SeDescriptorBindingFlags bindingFlags = 0, + SeShaderStageFlags shaderStages = SeShaderStageFlagBits::SE_SHADER_STAGE_ALL); + void reset(); + PDescriptorSet allocateDescriptorSet(); + virtual void create() = 0; + constexpr const Array& getBindings() const { return descriptorBindings; } + constexpr uint32 getSetIndex() const { return setIndex; } + constexpr void setSetIndex(uint32 _setIndex) { setIndex = _setIndex; } + constexpr uint32 getHash() const { return hash; } + +protected: + Array descriptorBindings; + ODescriptorPool pool; + uint32 setIndex; + std::string name; + uint32 hash = 0; + friend class PipelineLayout; + friend class DescriptorPool; +}; +DEFINE_REF(DescriptorLayout) DECLARE_REF(DescriptorSet) -class DescriptorPool -{ +class DescriptorPool { public: - DescriptorPool(); - virtual ~DescriptorPool(); - virtual PDescriptorSet allocateDescriptorSet() = 0; - virtual void reset() = 0; + DescriptorPool(); + virtual ~DescriptorPool(); + virtual PDescriptorSet allocateDescriptorSet() = 0; + virtual void reset() = 0; }; DEFINE_REF(DescriptorPool) DECLARE_REF(UniformBuffer) DECLARE_REF(ShaderBuffer) DECLARE_REF(Texture) DECLARE_REF(Sampler) -class DescriptorSet -{ +class DescriptorSet { public: - DescriptorSet() {} - virtual ~DescriptorSet() {} - virtual void writeChanges() = 0; - virtual void updateBuffer(uint32 binding, PUniformBuffer uniformBuffer) = 0; - virtual void updateBuffer(uint32 binding, PShaderBuffer ShaderBuffer) = 0; - virtual void updateSampler(uint32 binding, PSampler sampler) = 0; - virtual void updateTexture(uint32 binding, PTexture texture, PSampler samplerState = nullptr) = 0; - virtual void updateTextureArray(uint32_t binding, Array texture) = 0; - virtual bool operator<(PDescriptorSet other) = 0; + DescriptorSet(PDescriptorLayout layout); + virtual ~DescriptorSet(); + virtual void writeChanges() = 0; + virtual void updateBuffer(uint32 binding, PUniformBuffer uniformBuffer) = 0; + virtual void updateBuffer(uint32 binding, PShaderBuffer ShaderBuffer) = 0; + virtual void updateSampler(uint32 binding, PSampler sampler) = 0; + virtual void updateTexture(uint32 binding, PTexture texture, PSampler samplerState = nullptr) = 0; + virtual void updateTextureArray(uint32_t binding, Array texture) = 0; + bool operator<(PDescriptorSet other); - virtual uint32 getSetIndex() const = 0; + constexpr uint32 getSetIndex() const { return layout->getSetIndex(); } + +protected: + PDescriptorLayout layout; }; DEFINE_REF(DescriptorSet) -class DescriptorLayout -{ +class PipelineLayout { public: - DescriptorLayout(const std::string& name); - DescriptorLayout(const DescriptorLayout& other); - DescriptorLayout& operator=(const DescriptorLayout& other); - virtual ~DescriptorLayout(); - virtual void create() = 0; - virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, SeDescriptorBindingFlags bindingFlags = 0, SeShaderStageFlags shaderStages = SeShaderStageFlagBits::SE_SHADER_STAGE_ALL); - virtual void reset(); - virtual PDescriptorSet allocateDescriptorSet(); - constexpr const Array& getBindings() const { return descriptorBindings; } - constexpr uint32 getSetIndex() const { return setIndex; } - constexpr void setSetIndex(uint32 _setIndex) { setIndex = _setIndex; } + PipelineLayout(); + PipelineLayout(PPipelineLayout baseLayout); + virtual ~PipelineLayout(); + virtual void create() = 0; + void addDescriptorLayout(uint32 setIndex, PDescriptorLayout layout); + void addPushConstants(const SePushConstantRange& pushConstants); + constexpr uint32 getHash() const { return layoutHash; } protected: - Array descriptorBindings; - ODescriptorPool pool; - uint32 setIndex; - std::string name; - friend class PipelineLayout; - friend class DescriptorPool; -}; -DEFINE_REF(DescriptorLayout) -class PipelineLayout -{ -public: - PipelineLayout(); - PipelineLayout(PPipelineLayout baseLayout); - virtual ~PipelineLayout(); - virtual void create() = 0; - virtual void reset() = 0; - void addDescriptorLayout(uint32 setIndex, PDescriptorLayout layout); - void addPushConstants(const SePushConstantRange& pushConstants); - constexpr uint32 getHash() const { return layoutHash; } - -protected: - uint32 layoutHash; - Array descriptorSetLayouts; - Array pushConstants; + uint32 layoutHash = 0; + Array descriptorSetLayouts; + Array pushConstants; }; DEFINE_REF(PipelineLayout) -} -} +} // namespace Gfx +} // namespace Seele diff --git a/src/Engine/Graphics/Enums.h b/src/Engine/Graphics/Enums.h index 788b9f6..3ebe399 100644 --- a/src/Engine/Graphics/Enums.h +++ b/src/Engine/Graphics/Enums.h @@ -219,12 +219,6 @@ typedef enum SeResult SE_ERROR_NOT_PERMITTED_EXT = -1000174001, SE_ERROR_INVALID_DEVICE_ADDRESS_EXT = -1000244000, SE_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000, - SE_ERROR_OUT_OF_POOL_MEMORY_KHR = SE_ERROR_OUT_OF_POOL_MEMORY, - SE_ERROR_INVALID_EXTERNAL_HANDLE_KHR = SE_ERROR_INVALID_EXTERNAL_HANDLE, - SE_RESULT_BEGIN_RANGE = SE_ERROR_FRAGMENTED_POOL, - SE_RESULT_END_RANGE = SE_INCOMPLETE, - SE_RESULT_RANGE_SIZE = (SE_INCOMPLETE - SE_ERROR_FRAGMENTED_POOL + 1), - SE_RESULT_MAX_ENUM = 0x7FFFFFFF } SeResult; typedef enum SeStructureType @@ -602,76 +596,6 @@ typedef enum SeStructureType SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000, SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000, SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, - SE_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = SE_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, - SE_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, - SE_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = SE_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, - SE_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = SE_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, - SE_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = SE_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2, - SE_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = SE_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2, - SE_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR = SE_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, - SE_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO_KHR = SE_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO, - SE_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO_KHR = SE_STRUCTURE_TYPE_DEVICE_GROUP_COMMAND_BUFFER_BEGIN_INFO, - SE_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR = SE_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO, - SE_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR = SE_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO, - SE_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO_KHR = SE_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, - SE_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO_KHR = SE_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES, - SE_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, - SE_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR = SE_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, - SE_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR = SE_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, - SE_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, - SE_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, - SE_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR = SE_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, - SE_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR = SE_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, - SE_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, - SE_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, - SE_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = SE_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO, - SE_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = SE_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, - SE_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES, - SE_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO, - SE_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, - SE_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES, - SE_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = SE_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - SE_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = SE_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - SE_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = SE_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, - SE_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = SE_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, - SE_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = SE_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2, - SE_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = SE_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - SE_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = SE_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2, - SE_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR = SE_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO, - SE_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR = SE_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, - SE_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR = SE_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO, - SE_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR = SE_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES, - SE_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES_KHR = SE_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES, - SE_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR = SE_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, - SE_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR = SE_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES, - SE_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = SE_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT, - SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT = SE_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT, - SE_STRUCTURE_TYPE_BEGIN_RANGE = SE_STRUCTURE_TYPE_APPLICATION_INFO, - SE_STRUCTURE_TYPE_END_RANGE = SE_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, - SE_STRUCTURE_TYPE_RANGE_SIZE = (SE_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - SE_STRUCTURE_TYPE_APPLICATION_INFO + 1), - SE_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } SeStructureType; typedef enum SeSystemAllocationScope @@ -681,19 +605,11 @@ typedef enum SeSystemAllocationScope SE_SYSTEM_ALLOCATION_SCOPE_CACHE = 2, SE_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3, SE_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4, - SE_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = SE_SYSTEM_ALLOCATION_SCOPE_COMMAND, - SE_SYSTEM_ALLOCATION_SCOPE_END_RANGE = SE_SYSTEM_ALLOCATION_SCOPE_INSTANCE, - SE_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (SE_SYSTEM_ALLOCATION_SCOPE_INSTANCE - SE_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1), - SE_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF } SeSystemAllocationScope; typedef enum SeInternalAllocationType { SE_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0, - SE_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = SE_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - SE_INTERNAL_ALLOCATION_TYPE_END_RANGE = SE_INTERNAL_ALLOCATION_TYPE_EXECUTABLE, - SE_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (SE_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - SE_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1), - SE_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF } SeInternalAllocationType; typedef enum SeFormat @@ -939,10 +855,6 @@ typedef enum SeFormat SE_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011, SE_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012, SE_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013, - SE_FORMAT_BEGIN_RANGE = SE_FORMAT_UNDEFINED, - SE_FORMAT_END_RANGE = SE_FORMAT_ASTC_12x12_SRGB_BLOCK, - SE_FORMAT_RANGE_SIZE = (SE_FORMAT_ASTC_12x12_SRGB_BLOCK - SE_FORMAT_UNDEFINED + 1), - SE_FORMAT_MAX_ENUM = 0x7FFFFFFF } SeFormat; struct FormatCompatibilityInfo @@ -960,21 +872,12 @@ typedef enum SeImageType SE_IMAGE_TYPE_1D = 0, SE_IMAGE_TYPE_2D = 1, SE_IMAGE_TYPE_3D = 2, - SE_IMAGE_TYPE_BEGIN_RANGE = SE_IMAGE_TYPE_1D, - SE_IMAGE_TYPE_END_RANGE = SE_IMAGE_TYPE_3D, - SE_IMAGE_TYPE_RANGE_SIZE = (SE_IMAGE_TYPE_3D - SE_IMAGE_TYPE_1D + 1), - SE_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF } SeImageType; typedef enum SeImageTiling { SE_IMAGE_TILING_OPTIMAL = 0, SE_IMAGE_TILING_LINEAR = 1, - SE_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT = 1000158000, - SE_IMAGE_TILING_BEGIN_RANGE = SE_IMAGE_TILING_OPTIMAL, - SE_IMAGE_TILING_END_RANGE = SE_IMAGE_TILING_LINEAR, - SE_IMAGE_TILING_RANGE_SIZE = (SE_IMAGE_TILING_LINEAR - SE_IMAGE_TILING_OPTIMAL + 1), - SE_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF } SeImageTiling; typedef enum SePhysicalDeviceType @@ -984,10 +887,6 @@ typedef enum SePhysicalDeviceType SE_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2, SE_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3, SE_PHYSICAL_DEVICE_TYPE_CPU = 4, - SE_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = SE_PHYSICAL_DEVICE_TYPE_OTHER, - SE_PHYSICAL_DEVICE_TYPE_END_RANGE = SE_PHYSICAL_DEVICE_TYPE_CPU, - SE_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (SE_PHYSICAL_DEVICE_TYPE_CPU - SE_PHYSICAL_DEVICE_TYPE_OTHER + 1), - SE_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF } SePhysicalDeviceType; typedef enum SeQueryType @@ -998,20 +897,12 @@ typedef enum SeQueryType SE_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004, SE_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000, SE_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000, - SE_QUERY_TYPE_BEGIN_RANGE = SE_QUERY_TYPE_OCCLUSION, - SE_QUERY_TYPE_END_RANGE = SE_QUERY_TYPE_TIMESTAMP, - SE_QUERY_TYPE_RANGE_SIZE = (SE_QUERY_TYPE_TIMESTAMP - SE_QUERY_TYPE_OCCLUSION + 1), - SE_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF } SeQueryType; typedef enum SeSharingMode { SE_SHARING_MODE_EXCLUSIVE = 0, SE_SHARING_MODE_CONCURRENT = 1, - SE_SHARING_MODE_BEGIN_RANGE = SE_SHARING_MODE_EXCLUSIVE, - SE_SHARING_MODE_END_RANGE = SE_SHARING_MODE_CONCURRENT, - SE_SHARING_MODE_RANGE_SIZE = (SE_SHARING_MODE_CONCURRENT - SE_SHARING_MODE_EXCLUSIVE + 1), - SE_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF } SeSharingMode; typedef enum SeImageLayout @@ -1031,12 +922,6 @@ typedef enum SeImageLayout SE_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000, SE_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003, SE_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT = 1000218000, - SE_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = SE_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, - SE_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = SE_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, - SE_IMAGE_LAYOUT_BEGIN_RANGE = SE_IMAGE_LAYOUT_UNDEFINED, - SE_IMAGE_LAYOUT_END_RANGE = SE_IMAGE_LAYOUT_PREINITIALIZED, - SE_IMAGE_LAYOUT_RANGE_SIZE = (SE_IMAGE_LAYOUT_PREINITIALIZED - SE_IMAGE_LAYOUT_UNDEFINED + 1), - SE_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF } SeImageLayout; typedef enum SeImageViewType @@ -1048,10 +933,6 @@ typedef enum SeImageViewType SE_IMAGE_VIEW_TYPE_1D_ARRAY = 4, SE_IMAGE_VIEW_TYPE_2D_ARRAY = 5, SE_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6, - SE_IMAGE_VIEW_TYPE_BEGIN_RANGE = SE_IMAGE_VIEW_TYPE_1D, - SE_IMAGE_VIEW_TYPE_END_RANGE = SE_IMAGE_VIEW_TYPE_CUBE_ARRAY, - SE_IMAGE_VIEW_TYPE_RANGE_SIZE = (SE_IMAGE_VIEW_TYPE_CUBE_ARRAY - SE_IMAGE_VIEW_TYPE_1D + 1), - SE_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF } SeImageViewType; typedef enum SeComponentSwizzle @@ -1063,20 +944,12 @@ typedef enum SeComponentSwizzle SE_COMPONENT_SWIZZLE_G = 4, SE_COMPONENT_SWIZZLE_B = 5, SE_COMPONENT_SWIZZLE_A = 6, - SE_COMPONENT_SWIZZLE_BEGIN_RANGE = SE_COMPONENT_SWIZZLE_IDENTITY, - SE_COMPONENT_SWIZZLE_END_RANGE = SE_COMPONENT_SWIZZLE_A, - SE_COMPONENT_SWIZZLE_RANGE_SIZE = (SE_COMPONENT_SWIZZLE_A - SE_COMPONENT_SWIZZLE_IDENTITY + 1), - SE_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF } SeComponentSwizzle; typedef enum SeVertexInputRate { SE_VERTEX_INPUT_RATE_VERTEX = 0, SE_VERTEX_INPUT_RATE_INSTANCE = 1, - SE_VERTEX_INPUT_RATE_BEGIN_RANGE = SE_VERTEX_INPUT_RATE_VERTEX, - SE_VERTEX_INPUT_RATE_END_RANGE = SE_VERTEX_INPUT_RATE_INSTANCE, - SE_VERTEX_INPUT_RATE_RANGE_SIZE = (SE_VERTEX_INPUT_RATE_INSTANCE - SE_VERTEX_INPUT_RATE_VERTEX + 1), - SE_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF } SeVertexInputRate; typedef enum SePrimitiveTopology @@ -1092,10 +965,6 @@ typedef enum SePrimitiveTopology SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8, SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9, SE_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10, - SE_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = SE_PRIMITIVE_TOPOLOGY_POINT_LIST, - SE_PRIMITIVE_TOPOLOGY_END_RANGE = SE_PRIMITIVE_TOPOLOGY_PATCH_LIST, - SE_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (SE_PRIMITIVE_TOPOLOGY_PATCH_LIST - SE_PRIMITIVE_TOPOLOGY_POINT_LIST + 1), - SE_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF } SePrimitiveTopology; typedef enum SePolygonMode @@ -1104,20 +973,12 @@ typedef enum SePolygonMode SE_POLYGON_MODE_LINE = 1, SE_POLYGON_MODE_POINT = 2, SE_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000, - SE_POLYGON_MODE_BEGIN_RANGE = SE_POLYGON_MODE_FILL, - SE_POLYGON_MODE_END_RANGE = SE_POLYGON_MODE_POINT, - SE_POLYGON_MODE_RANGE_SIZE = (SE_POLYGON_MODE_POINT - SE_POLYGON_MODE_FILL + 1), - SE_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF } SePolygonMode; typedef enum SeFrontFace { SE_FRONT_FACE_COUNTER_CLOCKWISE = 0, SE_FRONT_FACE_CLOCKWISE = 1, - SE_FRONT_FACE_BEGIN_RANGE = SE_FRONT_FACE_COUNTER_CLOCKWISE, - SE_FRONT_FACE_END_RANGE = SE_FRONT_FACE_CLOCKWISE, - SE_FRONT_FACE_RANGE_SIZE = (SE_FRONT_FACE_CLOCKWISE - SE_FRONT_FACE_COUNTER_CLOCKWISE + 1), - SE_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF } SeFrontFace; typedef enum SeCompareOp @@ -1130,10 +991,6 @@ typedef enum SeCompareOp SE_COMPARE_OP_NOT_EQUAL = 5, SE_COMPARE_OP_GREATER_OR_EQUAL = 6, SE_COMPARE_OP_ALWAYS = 7, - SE_COMPARE_OP_BEGIN_RANGE = SE_COMPARE_OP_NEVER, - SE_COMPARE_OP_END_RANGE = SE_COMPARE_OP_ALWAYS, - SE_COMPARE_OP_RANGE_SIZE = (SE_COMPARE_OP_ALWAYS - SE_COMPARE_OP_NEVER + 1), - SE_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF } SeCompareOp; typedef enum SeStencilOp @@ -1146,10 +1003,6 @@ typedef enum SeStencilOp SE_STENCIL_OP_INVERT = 5, SE_STENCIL_OP_INCREMENT_AND_WRAP = 6, SE_STENCIL_OP_DECREMENT_AND_WRAP = 7, - SE_STENCIL_OP_BEGIN_RANGE = SE_STENCIL_OP_KEEP, - SE_STENCIL_OP_END_RANGE = SE_STENCIL_OP_DECREMENT_AND_WRAP, - SE_STENCIL_OP_RANGE_SIZE = (SE_STENCIL_OP_DECREMENT_AND_WRAP - SE_STENCIL_OP_KEEP + 1), - SE_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF } SeStencilOp; typedef enum SeLogicOp @@ -1170,10 +1023,6 @@ typedef enum SeLogicOp SE_LOGIC_OP_OR_INVERTED = 13, SE_LOGIC_OP_NAND = 14, SE_LOGIC_OP_SET = 15, - SE_LOGIC_OP_BEGIN_RANGE = SE_LOGIC_OP_CLEAR, - SE_LOGIC_OP_END_RANGE = SE_LOGIC_OP_SET, - SE_LOGIC_OP_RANGE_SIZE = (SE_LOGIC_OP_SET - SE_LOGIC_OP_CLEAR + 1), - SE_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF } SeLogicOp; typedef enum SeBlendFactor @@ -1197,10 +1046,6 @@ typedef enum SeBlendFactor SE_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16, SE_BLEND_FACTOR_SRC1_ALPHA = 17, SE_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18, - SE_BLEND_FACTOR_BEGIN_RANGE = SE_BLEND_FACTOR_ZERO, - SE_BLEND_FACTOR_END_RANGE = SE_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, - SE_BLEND_FACTOR_RANGE_SIZE = (SE_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - SE_BLEND_FACTOR_ZERO + 1), - SE_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF } SeBlendFactor; typedef enum SeBlendOp @@ -1256,10 +1101,6 @@ typedef enum SeBlendOp SE_BLEND_OP_RED_EXT = 1000148043, SE_BLEND_OP_GREEN_EXT = 1000148044, SE_BLEND_OP_BLUE_EXT = 1000148045, - SE_BLEND_OP_BEGIN_RANGE = SE_BLEND_OP_ADD, - SE_BLEND_OP_END_RANGE = SE_BLEND_OP_MAX, - SE_BLEND_OP_RANGE_SIZE = (SE_BLEND_OP_MAX - SE_BLEND_OP_ADD + 1), - SE_BLEND_OP_MAX_ENUM = 0x7FFFFFFF } SeBlendOp; typedef enum SeDynamicState @@ -1280,10 +1121,6 @@ typedef enum SeDynamicState SE_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006, SE_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001, SE_DYNAMIC_STATE_LINE_STIPPLE_EXT = 1000259000, - SE_DYNAMIC_STATE_BEGIN_RANGE = SE_DYNAMIC_STATE_VIEWPORT, - SE_DYNAMIC_STATE_END_RANGE = SE_DYNAMIC_STATE_STENCIL_REFERENCE, - SE_DYNAMIC_STATE_RANGE_SIZE = (SE_DYNAMIC_STATE_STENCIL_REFERENCE - SE_DYNAMIC_STATE_VIEWPORT + 1), - SE_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF } SeDynamicState; typedef enum SeFilter @@ -1291,21 +1128,12 @@ typedef enum SeFilter SE_FILTER_NEAREST = 0, SE_FILTER_LINEAR = 1, SE_FILTER_CUBIC_IMG = 1000015000, - SE_FILTER_CUBIC_EXT = SE_FILTER_CUBIC_IMG, - SE_FILTER_BEGIN_RANGE = SE_FILTER_NEAREST, - SE_FILTER_END_RANGE = SE_FILTER_LINEAR, - SE_FILTER_RANGE_SIZE = (SE_FILTER_LINEAR - SE_FILTER_NEAREST + 1), - SE_FILTER_MAX_ENUM = 0x7FFFFFFF } SeFilter; typedef enum SeSamplerMipmapMode { SE_SAMPLER_MIPMAP_MODE_NEAREST = 0, SE_SAMPLER_MIPMAP_MODE_LINEAR = 1, - SE_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = SE_SAMPLER_MIPMAP_MODE_NEAREST, - SE_SAMPLER_MIPMAP_MODE_END_RANGE = SE_SAMPLER_MIPMAP_MODE_LINEAR, - SE_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (SE_SAMPLER_MIPMAP_MODE_LINEAR - SE_SAMPLER_MIPMAP_MODE_NEAREST + 1), - SE_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF } SeSamplerMipmapMode; typedef enum SeSamplerAddressMode @@ -1315,11 +1143,6 @@ typedef enum SeSamplerAddressMode SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2, SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3, SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4, - SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR = SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, - SE_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = SE_SAMPLER_ADDRESS_MODE_REPEAT, - SE_SAMPLER_ADDRESS_MODE_END_RANGE = SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - SE_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER - SE_SAMPLER_ADDRESS_MODE_REPEAT + 1), - SE_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF } SeSamplerAddressMode; typedef enum SeBorderColor @@ -1330,10 +1153,6 @@ typedef enum SeBorderColor SE_BORDER_COLOR_INT_OPAQUE_BLACK = 3, SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4, SE_BORDER_COLOR_INT_OPAQUE_WHITE = 5, - SE_BORDER_COLOR_BEGIN_RANGE = SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - SE_BORDER_COLOR_END_RANGE = SE_BORDER_COLOR_INT_OPAQUE_WHITE, - SE_BORDER_COLOR_RANGE_SIZE = (SE_BORDER_COLOR_INT_OPAQUE_WHITE - SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1), - SE_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF } SeBorderColor; typedef enum SeDescriptorType @@ -1351,10 +1170,6 @@ typedef enum SeDescriptorType SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000, SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, - SE_DESCRIPTOR_TYPE_BEGIN_RANGE = SE_DESCRIPTOR_TYPE_SAMPLER, - SE_DESCRIPTOR_TYPE_END_RANGE = SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, - SE_DESCRIPTOR_TYPE_RANGE_SIZE = (SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - SE_DESCRIPTOR_TYPE_SAMPLER + 1), - SE_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF } SeDescriptorType; typedef enum SeDescriptorBindingFlagBits { @@ -1362,11 +1177,6 @@ typedef enum SeDescriptorBindingFlagBits { SE_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002, SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004, SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008, - SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, - SE_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = SE_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, - SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, - SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT, - SE_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } SeDescriptorBindingFlagBits; typedef SeFlags SeDescriptorBindingFlags; @@ -1375,20 +1185,12 @@ typedef enum SeAttachmentLoadOp SE_ATTACHMENT_LOAD_OP_LOAD = 0, SE_ATTACHMENT_LOAD_OP_CLEAR = 1, SE_ATTACHMENT_LOAD_OP_DONT_CARE = 2, - SE_ATTACHMENT_LOAD_OP_BEGIN_RANGE = SE_ATTACHMENT_LOAD_OP_LOAD, - SE_ATTACHMENT_LOAD_OP_END_RANGE = SE_ATTACHMENT_LOAD_OP_DONT_CARE, - SE_ATTACHMENT_LOAD_OP_RANGE_SIZE = (SE_ATTACHMENT_LOAD_OP_DONT_CARE - SE_ATTACHMENT_LOAD_OP_LOAD + 1), - SE_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF } SeAttachmentLoadOp; typedef enum SeAttachmentStoreOp { SE_ATTACHMENT_STORE_OP_STORE = 0, SE_ATTACHMENT_STORE_OP_DONT_CARE = 1, - SE_ATTACHMENT_STORE_OP_BEGIN_RANGE = SE_ATTACHMENT_STORE_OP_STORE, - SE_ATTACHMENT_STORE_OP_END_RANGE = SE_ATTACHMENT_STORE_OP_DONT_CARE, - SE_ATTACHMENT_STORE_OP_RANGE_SIZE = (SE_ATTACHMENT_STORE_OP_DONT_CARE - SE_ATTACHMENT_STORE_OP_STORE + 1), - SE_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF } SeAttachmentStoreOp; typedef enum SePipelineBindPoint @@ -1396,20 +1198,12 @@ typedef enum SePipelineBindPoint SE_PIPELINE_BIND_POINT_GRAPHICS = 0, SE_PIPELINE_BIND_POINT_COMPUTE = 1, SE_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000, - SE_PIPELINE_BIND_POINT_BEGIN_RANGE = SE_PIPELINE_BIND_POINT_GRAPHICS, - SE_PIPELINE_BIND_POINT_END_RANGE = SE_PIPELINE_BIND_POINT_COMPUTE, - SE_PIPELINE_BIND_POINT_RANGE_SIZE = (SE_PIPELINE_BIND_POINT_COMPUTE - SE_PIPELINE_BIND_POINT_GRAPHICS + 1), - SE_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF } SePipelineBindPoint; typedef enum SeCommandBufferLevel { SE_COMMAND_BUFFER_LEVEL_PRIMARY = 0, SE_COMMAND_BUFFER_LEVEL_SECONDARY = 1, - SE_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = SE_COMMAND_BUFFER_LEVEL_PRIMARY, - SE_COMMAND_BUFFER_LEVEL_END_RANGE = SE_COMMAND_BUFFER_LEVEL_SECONDARY, - SE_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (SE_COMMAND_BUFFER_LEVEL_SECONDARY - SE_COMMAND_BUFFER_LEVEL_PRIMARY + 1), - SE_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF } SeCommandBufferLevel; typedef enum SeIndexType @@ -1418,20 +1212,11 @@ typedef enum SeIndexType SE_INDEX_TYPE_UINT32 = 1, SE_INDEX_TYPE_NONE_NV = 1000165000, SE_INDEX_TYPE_UINT8_EXT = 1000265000, - SE_INDEX_TYPE_BEGIN_RANGE = SE_INDEX_TYPE_UINT16, - SE_INDEX_TYPE_END_RANGE = SE_INDEX_TYPE_UINT32, - SE_INDEX_TYPE_RANGE_SIZE = (SE_INDEX_TYPE_UINT32 - SE_INDEX_TYPE_UINT16 + 1), - SE_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF } SeIndexType; typedef enum SeSubpassContents { SE_SUBPASS_CONTENTS_INLINE = 0, - SE_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1, - SE_SUBPASS_CONTENTS_BEGIN_RANGE = SE_SUBPASS_CONTENTS_INLINE, - SE_SUBPASS_CONTENTS_END_RANGE = SE_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, - SE_SUBPASS_CONTENTS_RANGE_SIZE = (SE_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - SE_SUBPASS_CONTENTS_INLINE + 1), - SE_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF } SeSubpassContents; typedef enum SeObjectType @@ -1475,12 +1260,6 @@ typedef enum SeObjectType SE_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000, SE_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000, SE_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000, - SE_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = SE_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, - SE_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = SE_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION, - SE_OBJECT_TYPE_BEGIN_RANGE = SE_OBJECT_TYPE_UNKNOWN, - SE_OBJECT_TYPE_END_RANGE = SE_OBJECT_TYPE_COMMAND_POOL, - SE_OBJECT_TYPE_RANGE_SIZE = (SE_OBJECT_TYPE_COMMAND_POOL - SE_OBJECT_TYPE_UNKNOWN + 1), - SE_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF } SeObjectType; typedef enum SeVendorId @@ -1488,10 +1267,6 @@ typedef enum SeVendorId SE_VENDOR_ID_VIV = 0x10001, SE_VENDOR_ID_VSI = 0x10002, SE_VENDOR_ID_KAZAN = 0x10003, - SE_VENDOR_ID_BEGIN_RANGE = SE_VENDOR_ID_VIV, - SE_VENDOR_ID_END_RANGE = SE_VENDOR_ID_KAZAN, - SE_VENDOR_ID_RANGE_SIZE = (SE_VENDOR_ID_KAZAN - SE_VENDOR_ID_VIV + 1), - SE_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF } SeVendorId; typedef SeFlags SeInstanceCreateFlags; @@ -2027,5 +1802,15 @@ typedef union SeClearValue { SeClearDepthStencilValue depthStencil; } SeClearValue; + +typedef enum SeDescriptorAccessTypeFlagBits { + SE_DESCRIPTOR_ACCESS_READ_ONLY_BIT = 0x00000001, + SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT = 0x00000002, + SE_DESCRIPTOR_ACCESS_WRITE_ONLY_BIT = 0x00000004, +} SeDescriptorAccessTypeFlagBits; +typedef SeFlags SeDescriptorAccessTypeFlags; + + + } // namespace Gfx } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index d4707ff..e1c23c6 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -36,7 +36,7 @@ struct WindowCreateInfo int32 width; int32 height; const char *title; - Gfx::SeFormat preferredFormat = Gfx::SE_FORMAT_MAX_ENUM; + Gfx::SeFormat preferredFormat = Gfx::SE_FORMAT_B8G8R8A8_UNORM; void *windowHandle; }; struct ViewportCreateInfo @@ -178,8 +178,8 @@ struct DepthStencilState SeCompareOp depthCompareOp = Gfx::SE_COMPARE_OP_LESS; uint32 depthBoundsTestEnable = 0; uint32 stencilTestEnable = 0; - SeStencilOp front = Gfx::SE_STENCIL_OP_END_RANGE; - SeStencilOp back = Gfx::SE_STENCIL_OP_END_RANGE; + SeStencilOp front = Gfx::SE_STENCIL_OP_ZERO; + SeStencilOp back = Gfx::SE_STENCIL_OP_ZERO; float minDepthBounds; float maxDepthBounds; }; diff --git a/src/Engine/Graphics/Metal/Buffer.h b/src/Engine/Graphics/Metal/Buffer.h index a759e64..9be497a 100644 --- a/src/Engine/Graphics/Metal/Buffer.h +++ b/src/Engine/Graphics/Metal/Buffer.h @@ -7,65 +7,80 @@ namespace Seele { namespace Metal { DECLARE_REF(Graphics) -class Buffer -{ +class Buffer { public: - Buffer(PGraphics graphics, uint64 size, void* data, bool dynamic); + Buffer(PGraphics graphics, uint64 size, void *data, bool dynamic); virtual ~Buffer(); - MTL::Buffer* getHandle() const - { - return buffers[currentBuffer]; - } - uint64 getSize() const - { - return size; - } - void advanceBuffer() - { - currentBuffer = (currentBuffer + 1) % numBuffers; - } - void* map(bool writeOnly = true); - void* mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly); + MTL::Buffer *getHandle() const { return buffers[currentBuffer]; } + uint64 getSize() const { return size; } + void advanceBuffer() { currentBuffer = (currentBuffer + 1) % numBuffers; } + void *map(bool writeOnly = true); + void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly); void unmap(); -private: + +protected: PGraphics graphics; uint32 currentBuffer; uint64 size; - MTL::Buffer* buffers[Gfx::numFramesBuffered]; + MTL::Buffer *buffers[Gfx::numFramesBuffered]; uint32 numBuffers; }; DEFINE_REF(Buffer) -class VertexBuffer : public Gfx::VertexBuffer, public Buffer -{ +class VertexBuffer : public Gfx::VertexBuffer, public Buffer { public: - VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& createInfo); + VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &createInfo); virtual ~VertexBuffer(); -private: + virtual void updateRegion(DataSource update) override; + virtual void download(Array &buffer) override; + +protected: + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; }; DEFINE_REF(VertexBuffer) -class IndexBuffer : public Gfx::IndexBuffer, public Buffer -{ +class IndexBuffer : public Gfx::IndexBuffer, public Buffer { public: - IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& createInfo); + IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &createInfo); virtual ~IndexBuffer(); -private: + + virtual void download(Array &buffer) override; +protected: + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; }; DEFINE_REF(IndexBuffer) -class UniformBuffer : public Gfx::UniformBuffer, public Buffer -{ +DEFINE_REF(IndexBuffer) +class UniformBuffer : public Gfx::UniformBuffer, public Buffer { public: - UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo); + UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo); virtual ~UniformBuffer(); -private: + + virtual bool updateContents(const DataSource &sourceData) override; + +protected: + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; }; DEFINE_REF(UniformBuffer) -class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer -{ +class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer { public: - ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo); + ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &createInfo); virtual ~ShaderBuffer(); -private: + + virtual bool updateContents(const DataSource &sourceData) override; + +protected: + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override; }; DEFINE_REF(ShaderBuffer) -} -} \ No newline at end of file +} // namespace Metal +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Buffer.mm b/src/Engine/Graphics/Metal/Buffer.mm index caebf12..33b41c9 100644 --- a/src/Engine/Graphics/Metal/Buffer.mm +++ b/src/Engine/Graphics/Metal/Buffer.mm @@ -8,8 +8,7 @@ using namespace Seele; using namespace Seele::Metal; -Buffer::Buffer(PGraphics graphics, uint64 size, void *data, bool dynamic) - : graphics(graphics), size(size) { +Buffer::Buffer(PGraphics graphics, uint64 size, void* data, bool dynamic) : graphics(graphics), size(size) { if (dynamic) { numBuffers = Gfx::numFramesBuffered; } else { @@ -17,11 +16,9 @@ Buffer::Buffer(PGraphics graphics, uint64 size, void *data, bool dynamic) } for (size_t i = 0; i < numBuffers; ++i) { if (data != nullptr) { - buffers[i] = graphics->getDevice()->newBuffer( - data, size, MTL::ResourceOptionCPUCacheModeDefault); + buffers[i] = graphics->getDevice()->newBuffer(data, size, MTL::ResourceOptionCPUCacheModeDefault); } else { - buffers[i] = graphics->getDevice()->newBuffer( - size, MTL::ResourceOptionCPUCacheModeDefault); + buffers[i] = graphics->getDevice()->newBuffer(size, MTL::ResourceOptionCPUCacheModeDefault); } } } @@ -32,45 +29,83 @@ Buffer::~Buffer() { } } -void *Buffer::map(bool) { return getHandle()->contents(); } +void* Buffer::map(bool) { return getHandle()->contents(); } -void *Buffer::mapRegion(uint64 regionOffset, uint64, bool) { - return (char *)getHandle()->contents() + regionOffset; -} +void* Buffer::mapRegion(uint64 regionOffset, uint64, bool) { return (char*)getHandle()->contents() + regionOffset; } void unmap() {} -VertexBuffer::VertexBuffer(PGraphics graphics, - const VertexBufferCreateInfo &createInfo) - : Gfx::VertexBuffer(graphics->getFamilyMapping(), createInfo.numVertices, - createInfo.vertexSize, createInfo.sourceData.owner), - Seele::Metal::Buffer(graphics, createInfo.sourceData.size, - createInfo.sourceData.data, false) {} +VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo& createInfo) + : Gfx::VertexBuffer(graphics->getFamilyMapping(), createInfo.numVertices, createInfo.vertexSize, + createInfo.sourceData.owner), + Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, false) {} VertexBuffer::~VertexBuffer() {} -IndexBuffer::IndexBuffer(PGraphics graphics, - const IndexBufferCreateInfo &createInfo) - : Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo.sourceData.size, - createInfo.indexType, createInfo.sourceData.owner), - Seele::Metal::Buffer(graphics, createInfo.sourceData.size, - createInfo.sourceData.data, false) {} +void VertexBuffer::updateRegion(DataSource update) { + void* data = getHandle()->contents(); + std::memcpy((char*)data + update.offset, update.data, update.size); +} + +void VertexBuffer::download(Array& buffer) { + void* data = getHandle()->contents(); + buffer.resize(size); + std::memcpy(buffer.data(), data, size); +} + +void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; } + +void VertexBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {} + +IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& createInfo) + : Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo.sourceData.size, createInfo.indexType, + createInfo.sourceData.owner), + Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, false) {} IndexBuffer::~IndexBuffer() {} -UniformBuffer::UniformBuffer(PGraphics graphics, - const UniformBufferCreateInfo &createInfo) +void IndexBuffer::download(Array& buffer) { + void* data = getHandle()->contents(); + buffer.resize(size); + std::memcpy(buffer.data(), data, size); +} +void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; } + +void IndexBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {} + +UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo& createInfo) : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.sourceData), - Seele::Metal::Buffer(graphics, createInfo.sourceData.size, - createInfo.sourceData.data, createInfo.dynamic) {} + Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, createInfo.dynamic) {} UniformBuffer::~UniformBuffer() {} -ShaderBuffer::ShaderBuffer(PGraphics graphics, - const ShaderBufferCreateInfo &createInfo) - : Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo.numElements, - createInfo.sourceData), - Seele::Metal::Buffer(graphics, createInfo.sourceData.size, - createInfo.sourceData.data, createInfo.dynamic) {} +bool UniformBuffer::updateContents(const DataSource& sourceData) { + void* data = getHandle()->contents(); + std::memcpy((char*)data + sourceData.offset, sourceData.data, sourceData.size); + return true; +} + +void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; } + +void UniformBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {} + +ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo) + : Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo.numElements, createInfo.sourceData), + Seele::Metal::Buffer(graphics, createInfo.sourceData.size, createInfo.sourceData.data, createInfo.dynamic) {} ShaderBuffer::~ShaderBuffer() {} + +bool ShaderBuffer::updateContents(const DataSource& sourceData) { + void* data = getHandle()->contents(); + std::memcpy((char*)data + sourceData.offset, sourceData.data, sourceData.size); + return true; +} + +void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { currentOwner = newOwner; } + + +void ShaderBuffer::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {} \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/CMakeLists.txt b/src/Engine/Graphics/Metal/CMakeLists.txt index e9b54ab..f1a977f 100644 --- a/src/Engine/Graphics/Metal/CMakeLists.txt +++ b/src/Engine/Graphics/Metal/CMakeLists.txt @@ -12,6 +12,8 @@ target_sources(Engine Graphics.mm Pipeline.h Pipeline.mm + PipelineCache.h + PipelineCache.mm PrivateImpl.mm RenderPass.h RenderPass.mm diff --git a/src/Engine/Graphics/Metal/Descriptor.h b/src/Engine/Graphics/Metal/Descriptor.h index 9018bab..1dcd5c3 100644 --- a/src/Engine/Graphics/Metal/Descriptor.h +++ b/src/Engine/Graphics/Metal/Descriptor.h @@ -8,64 +8,75 @@ namespace Seele { namespace Metal { DECLARE_REF(Graphics) -DECLARE_REF(DescriptorPool) class DescriptorLayout : public Gfx::DescriptorLayout { public: - DescriptorLayout(PGraphics graphics, const std::string &name); + DescriptorLayout(PGraphics graphics, const std::string& name); virtual ~DescriptorLayout(); virtual void create() override; - NS::Array* getArguments() const - { - return arguments; - } + + NS::Array* getArguments() const { return arguments; } + private: PGraphics graphics; NS::Array* arguments; }; -class PipelineLayout : public Gfx::PipelineLayout { +DEFINE_REF(DescriptorLayout) + +DECLARE_REF(DescriptorSet) +class DescriptorPool : public Gfx::DescriptorPool { public: - PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout) - : Gfx::PipelineLayout(baseLayout), graphics(graphics) {} + DescriptorPool(PGraphics graphics, PDescriptorLayout layout); + virtual ~DescriptorPool(); + virtual Gfx::PDescriptorSet allocateDescriptorSet() override; + virtual void reset() override; + constexpr NS::Array* getArguments() const { return layout->getArguments(); } + constexpr PDescriptorLayout getLayout() const { return layout; } private: PGraphics graphics; + PDescriptorLayout layout; + Array allocatedSets; }; -DEFINE_REF(PipelineLayout) +DEFINE_REF(DescriptorPool) class DescriptorSet : public Gfx::DescriptorSet { public: DescriptorSet(PGraphics graphics, PDescriptorPool owner); virtual ~DescriptorSet(); virtual void writeChanges(); - virtual void updateBuffer(uint32_t binding, - Gfx::PUniformBuffer uniformBuffer); + virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer); virtual void updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer); virtual void updateSampler(uint32_t binding, Gfx::PSampler samplerState); - virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, - Gfx::PSampler sampler = nullptr); - virtual void updateTextureArray(uint32_t binding, - Array texture); + virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr); + virtual void updateTextureArray(uint32_t binding, Array texture); virtual bool operator<(Gfx::PDescriptorSet other); + constexpr bool isCurrentlyBound() const { return bindCount > 0; } + constexpr bool isCurrentlyInUse() const { return currentlyInUse; } + constexpr void bind() { bindCount++; } + constexpr void unbind() { bindCount--; } + constexpr void allocate() { currentlyInUse = true; } + constexpr void free() { currentlyInUse = false; } + private: PGraphics graphics; PDescriptorPool owner; MTL::Buffer* buffer; MTL::ArgumentEncoder* encoder; + uint32 bindCount; + bool currentlyInUse; }; DEFINE_REF(DescriptorSet) -class DescriptorPool : public Gfx::DescriptorPool { +class PipelineLayout : public Gfx::PipelineLayout { public: - DescriptorPool(PGraphics graphics, DescriptorLayout& layout); - virtual ~DescriptorPool(); - NS::Array* getArguments() const - { - return layout.getArguments(); - } + PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout); + virtual ~PipelineLayout(); + virtual void create() override; + private: PGraphics graphics; - DescriptorLayout& layout; }; +DEFINE_REF(PipelineLayout) } // namespace Metal } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Descriptor.mm b/src/Engine/Graphics/Metal/Descriptor.mm index 2c20fa6..d17cc8d 100644 --- a/src/Engine/Graphics/Metal/Descriptor.mm +++ b/src/Engine/Graphics/Metal/Descriptor.mm @@ -1,28 +1,128 @@ #include "Descriptor.h" -#include "Graphics.h" +#include "Buffer.h" +#include "Enums.h" +#include "Graphics/Initializer.h" +#include "Texture.h" using namespace Seele; using namespace Seele::Metal; -DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner) - : graphics(graphics) - , owner(owner) -{ - encoder = graphics->getDevice()->newArgumentEncoder(owner->getArguments()); -} -DescriptorSet::~DescriptorSet() -{ -} -void DescriptorSet::writeChanges() -{ +DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name) + : Gfx::DescriptorLayout(name), graphics(graphics) {} + +DescriptorLayout::~DescriptorLayout() {} + +void DescriptorLayout::create() { + Array descriptors; + for (size_t i = 0; i < descriptorBindings.size(); ++i) { + const auto& binding = descriptorBindings[i]; + auto desc = MTL::ArgumentDescriptor::alloc()->init(); + desc->setAccess(cast(binding.access)); + desc->setArrayLength(binding.descriptorCount); + MTL::DataType dataType; + switch (binding.descriptorType) { + case Gfx::SE_DESCRIPTOR_TYPE_SAMPLER: + case Gfx::SE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case Gfx::SE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + dataType = MTL::DataTypeTexture; + break; + case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + case Gfx::SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT: + dataType = MTL::DataTypeStruct; + break; + case Gfx::SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV: + dataType = MTL::DataTypePrimitiveAccelerationStructure; + break; + default: + throw std::logic_error("Nooo"); + } + desc->setDataType(dataType); + descriptors.add(desc); + } + arguments = NS::Array::array(descriptors.data(), descriptors.size()); } - void DescriptorSet::updateBuffer(uint32_t binding, - Gfx::PUniformBuffer uniformBuffer){} - void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer){} - void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState){} - void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, - Gfx::PSampler sampler){} - void DescriptorSet::updateTextureArray(uint32_t binding, - Array texture){} - bool DescriptorSet::operator<(Gfx::PDescriptorSet other){return this < other.getHandle();} +DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) {} + +DescriptorPool::~DescriptorPool() {} + +Gfx::PDescriptorSet DescriptorPool::allocateDescriptorSet() { + for (uint32 setIndex = 0; setIndex < allocatedSets.size(); ++setIndex) { + if (allocatedSets[setIndex]->isCurrentlyBound() || allocatedSets[setIndex]->isCurrentlyInUse()) { + // Currently in use, skip + continue; + } + allocatedSets[setIndex]->allocate(); + + // Found set, stop searching + return PDescriptorSet(allocatedSets[setIndex]); + } + allocatedSets.add(new DescriptorSet(graphics, this)); + return PDescriptorSet(allocatedSets.back()); +} + +void DescriptorPool::reset() { + for (auto& set : allocatedSets) { + set->free(); + } +} + +DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner) + : Gfx::DescriptorSet(owner->getLayout()), graphics(graphics), owner(owner), bindCount(0), currentlyInUse(false) { + encoder = graphics->getDevice()->newArgumentEncoder(owner->getArguments()); + buffer = graphics->getDevice()->newBuffer(encoder->encodedLength(), MTL::ResourceOptionCPUCacheModeDefault); + encoder->setArgumentBuffer(buffer, 0); +} + +DescriptorSet::~DescriptorSet() {} + +void DescriptorSet::writeChanges() {} + +void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) { + PUniformBuffer metalBuffer = uniformBuffer.cast(); + encoder->setBuffer(metalBuffer->getHandle(), 0, binding); +} +void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer) { + PShaderBuffer metalBuffer = uniformBuffer.cast(); + encoder->setBuffer(metalBuffer->getHandle(), 0, binding); +} +void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) { + PSampler sampler = samplerState.cast(); + encoder->setSamplerState(sampler->getHandle(), binding); +} +void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) { + PTextureBase base = texture.cast(); + PSampler sampler = samplerState.cast(); + encoder->setTexture(base->getTexture(), binding); + encoder->setSamplerState(sampler->getHandle(), binding); +} + +void DescriptorSet::updateTextureArray(uint32_t binding, Array array) { + for (auto& t : array) { + PTextureBase metalTexture = t.cast(); + encoder->setTexture(metalTexture->getTexture(), binding++); + } +} + +bool DescriptorSet::operator<(Gfx::PDescriptorSet other) { return this < other.getHandle(); } + +PipelineLayout::PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout) + : Gfx::PipelineLayout(baseLayout), graphics(graphics) {} + +PipelineLayout::~PipelineLayout(){} + +void PipelineLayout::create() +{ + for(auto& set : descriptorSetLayouts) + { + uint32 setHash = set->getHash(); + layoutHash = CRC::Calculate(&setHash, sizeof(uint32), CRC::CRC_32(), layoutHash); + } +} \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Enums.h b/src/Engine/Graphics/Metal/Enums.h index ec7492a..31b600b 100644 --- a/src/Engine/Graphics/Metal/Enums.h +++ b/src/Engine/Graphics/Metal/Enums.h @@ -1,5 +1,7 @@ #pragma once #include "Graphics/Enums.h" +#include "Metal/MTLDepthStencil.hpp" +#include "Metal/MTLSampler.hpp" #include "Resources.h" namespace Seele @@ -12,5 +14,17 @@ MTL::LoadAction cast(Gfx::SeAttachmentLoadOp loadOp); Gfx::SeAttachmentLoadOp cast(MTL::LoadAction loadOp); MTL::StoreAction cast(Gfx::SeAttachmentStoreOp storeOp); Gfx::SeAttachmentStoreOp cast(MTL::StoreAction storeOp); +MTL::BindingAccess cast(Gfx::SeDescriptorAccessTypeFlags access); +Gfx::SeDescriptorAccessTypeFlags cast(MTL::BindingAccess access); +MTL::SamplerBorderColor cast(Gfx::SeBorderColor color); +Gfx::SeBorderColor cast(MTL::SamplerBorderColor color); +MTL::CompareFunction cast(Gfx::SeCompareOp compare); +Gfx::SeCompareOp cast(MTL::CompareFunction compare); +MTL::SamplerMinMagFilter cast(Gfx::SeFilter filter); +Gfx::SeFilter cast(MTL::SamplerMinMagFilter filter); +MTL::SamplerMipFilter cast(Gfx::SeSamplerMipmapMode filter); +Gfx::SeSamplerMipmapMode cast(MTL::SamplerMipFilter filter); +MTL::SamplerAddressMode cast(Gfx::SeSamplerAddressMode mode); +Gfx::SeSamplerAddressMode cast(MTL::SamplerAddressMode mode); } } \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Enums.mm b/src/Engine/Graphics/Metal/Enums.mm index 7e67260..5aff205 100644 --- a/src/Engine/Graphics/Metal/Enums.mm +++ b/src/Engine/Graphics/Metal/Enums.mm @@ -1,5 +1,8 @@ #include "Enums.h" #include "Graphics/Enums.h" +#include "Metal/MTLArgument.hpp" +#include "Metal/MTLDepthStencil.hpp" +#include "Metal/MTLSampler.hpp" #include using namespace Seele; @@ -587,3 +590,181 @@ Gfx::SeAttachmentStoreOp Seele::Metal::cast(MTL::StoreAction storeOp) { throw std::logic_error("Not implemented"); } } + +MTL::BindingAccess Seele::Metal::cast(Gfx::SeDescriptorAccessTypeFlags access) { + switch (access) { + case Gfx::SE_DESCRIPTOR_ACCESS_READ_ONLY_BIT: + return MTL::ArgumentAccessReadOnly; + case Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT: + return MTL::ArgumentAccessReadWrite; + case Gfx::SE_DESCRIPTOR_ACCESS_WRITE_ONLY_BIT: + return MTL::ArgumentAccessWriteOnly; + default: + throw std::logic_error("Not implemented"); + } +} + +Gfx::SeDescriptorAccessTypeFlags Seele::Metal::cast(MTL::BindingAccess access) { + switch (access) { + case MTL::ArgumentAccessReadOnly: + return Gfx::SE_DESCRIPTOR_ACCESS_READ_ONLY_BIT; + case MTL::ArgumentAccessReadWrite: + return Gfx::SE_DESCRIPTOR_ACCESS_READ_WRITE_BIT; + case MTL::ArgumentAccessWriteOnly: + return Gfx::SE_DESCRIPTOR_ACCESS_WRITE_ONLY_BIT; + default: + throw std::logic_error("Not implemented"); + } +} + +MTL::SamplerBorderColor Seele::Metal::cast(Gfx::SeBorderColor color) { + switch (color) { + case Gfx::SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: + return MTL::SamplerBorderColorTransparentBlack; + case Gfx::SE_BORDER_COLOR_INT_TRANSPARENT_BLACK: + return MTL::SamplerBorderColorTransparentBlack; + case Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_BLACK: + return MTL::SamplerBorderColorOpaqueBlack; + case Gfx::SE_BORDER_COLOR_INT_OPAQUE_BLACK: + return MTL::SamplerBorderColorOpaqueBlack; + case Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE: + return MTL::SamplerBorderColorOpaqueWhite; + case Gfx::SE_BORDER_COLOR_INT_OPAQUE_WHITE: + return MTL::SamplerBorderColorOpaqueWhite; + default: + throw std::logic_error("Not implemented"); + } +} + +Gfx::SeBorderColor Seele::Metal::cast(MTL::SamplerBorderColor color) { + switch (color) { + case MTL::SamplerBorderColorTransparentBlack: + return Gfx::SE_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + case MTL::SamplerBorderColorOpaqueBlack: + return Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_BLACK; + case MTL::SamplerBorderColorOpaqueWhite: + return Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + default: + throw std::logic_error("Not implemented"); + } +} + +MTL::CompareFunction Seele::Metal::cast(Gfx::SeCompareOp compare) { + switch (compare) { + case Gfx::SE_COMPARE_OP_NEVER: + return MTL::CompareFunctionNever; + case Gfx::SE_COMPARE_OP_LESS: + return MTL::CompareFunctionLess; + case Gfx::SE_COMPARE_OP_EQUAL: + return MTL::CompareFunctionEqual; + case Gfx::SE_COMPARE_OP_LESS_OR_EQUAL: + return MTL::CompareFunctionLessEqual; + case Gfx::SE_COMPARE_OP_GREATER: + return MTL::CompareFunctionGreater; + case Gfx::SE_COMPARE_OP_NOT_EQUAL: + return MTL::CompareFunctionNotEqual; + case Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL: + return MTL::CompareFunctionGreaterEqual; + case Gfx::SE_COMPARE_OP_ALWAYS: + return MTL::CompareFunctionAlways; + default: + throw std::logic_error("Not implemented"); + } +} + +Gfx::SeCompareOp Seele::Metal::cast(MTL::CompareFunction compare) { + switch (compare) { + case MTL::CompareFunctionNever: + return Gfx::SE_COMPARE_OP_NEVER; + case MTL::CompareFunctionLess: + return Gfx::SE_COMPARE_OP_LESS; + case MTL::CompareFunctionEqual: + return Gfx::SE_COMPARE_OP_EQUAL; + case MTL::CompareFunctionLessEqual: + return Gfx::SE_COMPARE_OP_LESS_OR_EQUAL; + case MTL::CompareFunctionGreater: + return Gfx::SE_COMPARE_OP_GREATER; + case MTL::CompareFunctionNotEqual: + return Gfx::SE_COMPARE_OP_NOT_EQUAL; + case MTL::CompareFunctionGreaterEqual: + return Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL; + case MTL::CompareFunctionAlways: + return Gfx::SE_COMPARE_OP_ALWAYS; + } +} + +MTL::SamplerMinMagFilter Seele::Metal::cast(Gfx::SeFilter filter) { + switch (filter) { + case Gfx::SE_FILTER_NEAREST: + return MTL::SamplerMinMagFilterNearest; + case Gfx::SE_FILTER_LINEAR: + return MTL::SamplerMinMagFilterLinear; + case Gfx::SE_FILTER_CUBIC_IMG: + return MTL::SamplerMinMagFilterLinear; + default: + throw std::logic_error("Not implemented"); + } +} + +Gfx::SeFilter Seele::Metal::cast(MTL::SamplerMinMagFilter filter) { + switch (filter) { + case MTL::SamplerMinMagFilterNearest: + return Gfx::SE_FILTER_NEAREST; + case MTL::SamplerMinMagFilterLinear: + return Gfx::SE_FILTER_LINEAR; + } +} + +MTL::SamplerMipFilter Seele::Metal::cast(Gfx::SeSamplerMipmapMode filter) { + switch (filter) { + case Seele::Gfx::SE_SAMPLER_MIPMAP_MODE_NEAREST: + return MTL::SamplerMipFilterNearest; + case Seele::Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR: + return MTL::SamplerMipFilterLinear; + default: + throw std::logic_error("Not implemented"); + } +} + +Gfx::SeSamplerMipmapMode Seele::Metal::cast(MTL::SamplerMipFilter filter) { + switch (filter) { + case MTL::SamplerMipFilterNotMipmapped: + return Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR; + case MTL::SamplerMipFilterNearest: + return Gfx::SE_SAMPLER_MIPMAP_MODE_NEAREST; + case MTL::SamplerMipFilterLinear: + return Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR; + } +} + +MTL::SamplerAddressMode Seele::Metal::cast(Gfx::SeSamplerAddressMode mode) { + switch (mode) { + case Gfx::SE_SAMPLER_ADDRESS_MODE_REPEAT: + return MTL::SamplerAddressModeRepeat; + case Gfx::SE_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: + return MTL::SamplerAddressModeMirrorRepeat; + case Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: + return MTL::SamplerAddressModeMirrorClampToEdge; + case Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: + return MTL::SamplerAddressModeClampToBorderColor; + case Gfx::SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: + return MTL::SamplerAddressModeMirrorClampToEdge; + } +} + +Gfx::SeSamplerAddressMode Seele::Metal::cast(MTL::SamplerAddressMode mode) { + switch (mode) { + case MTL::SamplerAddressModeClampToEdge: + return Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + case MTL::SamplerAddressModeMirrorClampToEdge: + return Gfx::SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; + case MTL::SamplerAddressModeRepeat: + return Gfx::SE_SAMPLER_ADDRESS_MODE_REPEAT; + case MTL::SamplerAddressModeMirrorRepeat: + return Gfx::SE_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + case MTL::SamplerAddressModeClampToZero: + return Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + case MTL::SamplerAddressModeClampToBorderColor: + return Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + } +} diff --git a/src/Engine/Graphics/Metal/Graphics.mm b/src/Engine/Graphics/Metal/Graphics.mm index 255d43d..460b00d 100644 --- a/src/Engine/Graphics/Metal/Graphics.mm +++ b/src/Engine/Graphics/Metal/Graphics.mm @@ -1,8 +1,10 @@ #include "Graphics.h" -#include "Graphics/Metal/Shader.h" +#include "Graphics/Initializer.h" +#include "Shader.h" #include "RenderPass.h" #include "Command.h" #include "Window.h" +#include "Buffer.h" using namespace Seele; using namespace Seele::Metal; @@ -82,22 +84,22 @@ Gfx::OTextureCube Graphics::createTextureCube(const TextureCreateInfo &createInf Gfx::OUniformBuffer Graphics::createUniformBuffer(const UniformBufferCreateInfo &bulkData) { - + return new UniformBuffer(this, bulkData); } Gfx::OShaderBuffer Graphics::createShaderBuffer(const ShaderBufferCreateInfo &bulkData) { - + return new ShaderBuffer(this, bulkData); } Gfx::OVertexBuffer Graphics::createVertexBuffer(const VertexBufferCreateInfo &bulkData) { - + return new VertexBuffer(this, bulkData); } Gfx::OIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkData) { - + return new IndexBuffer(this, bulkData); } Gfx::ORenderCommand Graphics::createRenderCommand(const std::string& name) @@ -112,11 +114,15 @@ Gfx::OComputeCommand Graphics::createComputeCommand(const std::string& name) Gfx::OVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo) { - + OVertexShader result = new VertexShader(this); + result->create(createInfo); + return result; } Gfx::OFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo) { - + OFragmentShader result = new FragmentShader(this); + result->create(createInfo); + return result; } Gfx::OComputeShader Graphics::createComputeShader(const ShaderCreateInfo& createInfo) { @@ -133,12 +139,16 @@ Gfx::OMeshShader Graphics::createMeshShader(const ShaderCreateInfo& createInfo) } Gfx::OTaskShader Graphics::createTaskShader(const ShaderCreateInfo& createInfo) { - + OTaskShader result = new TaskShader(this); + result->create(createInfo); + return result; } + Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo createInfo) { } + Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(Gfx::MeshPipelineCreateInfo createInfo) { diff --git a/src/Engine/Graphics/Metal/PipelineCache.h b/src/Engine/Graphics/Metal/PipelineCache.h index 1aabf25..189eee2 100644 --- a/src/Engine/Graphics/Metal/PipelineCache.h +++ b/src/Engine/Graphics/Metal/PipelineCache.h @@ -1,11 +1,23 @@ #pragma once -#include "Graphics/Pipeline.h" +#include "Graphics/Initializer.h" +#include "Pipeline.h" namespace Seele { namespace Metal { class PipelineCache { - +public: + PipelineCache(PGraphics graphics, const std::string& cacheFilePath); + ~PipelineCache(); + PGraphicsPipeline createPipeline(Gfx::LegacyPipelineCreateInfo createInfo); + PGraphicsPipeline createPipeline(Gfx::MeshPipelineCreateInfo createInfo); + PComputePipeline createPipeline(Gfx::ComputePipelineCreateInfo createInfo); +private: + PGraphics graphics; + Map graphicsPipelines; + Map computePipeline; + std::string cacheFile; }; +DEFINE_REF(PipelineCache) } } \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/PipelineCache.mm b/src/Engine/Graphics/Metal/PipelineCache.mm index e69de29..578b4ce 100644 --- a/src/Engine/Graphics/Metal/PipelineCache.mm +++ b/src/Engine/Graphics/Metal/PipelineCache.mm @@ -0,0 +1,70 @@ +#include "PipelineCache.h" +#include "Descriptor.h" +#include "Graphics.h" +#include "Shader.h" +#include "Graphics/Descriptor.h" +#include "Graphics/Enums.h" +#include "Metal/MTLRenderPipeline.hpp" +#include "Metal/MTLVertexDescriptor.hpp" + +using namespace Seele; +using namespace Seele::Metal; + +PipelineCache::PipelineCache(PGraphics graphics, const std::string& name) : graphics(graphics), cacheFile(name) {} + +PipelineCache::~PipelineCache() {} + +PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo createInfo) { + PPipelineLayout layout = Gfx::PPipelineLayout(createInfo.pipelineLayout).cast(); + uint32 hash = layout->getHash(); + MTL::RenderPipelineDescriptor* pipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init(); + + MTL::VertexDescriptor* vertexDescriptor = MTL::VertexDescriptor::alloc()->init(); + + MTL::VertexAttributeDescriptorArray* attributes = vertexDescriptor->attributes(); + + const auto& vertexInfo = createInfo.vertexInput->getInfo(); + + for (size_t attr = 0; attr < vertexInfo.attributes.size(); ++attr) { + MTL::VertexAttributeDescriptor* attribute = MTL::VertexAttributeDescriptor::alloc()->init(); + attribute->setBufferIndex(vertexInfo.attributes[attr].binding); + switch (vertexInfo.attributes[attr].format) { + case Gfx::SE_FORMAT_R32G32B32_SFLOAT: + attribute->setFormat(MTL::VertexFormatFloat3); + break; + default: + throw std::logic_error("TODO"); + } + attribute->setOffset(vertexInfo.attributes[attr].offset); + attributes->setObject(attribute, attr); + } + + MTL::VertexBufferLayoutDescriptorArray* bufferLayout = vertexDescriptor->layouts(); + + for (size_t binding = 0; binding < vertexInfo.bindings.size(); ++binding) { + MTL::VertexBufferLayoutDescriptor* buffer = MTL::VertexBufferLayoutDescriptor::alloc()->init(); + buffer->setStride(vertexInfo.bindings[binding].stride); + buffer->setStepRate(1); + switch (vertexInfo.bindings[binding].inputRate) { + case Gfx::SE_VERTEX_INPUT_RATE_VERTEX: + buffer->setStepFunction(MTL::VertexStepFunctionPerVertex); + break; + case Gfx::SE_VERTEX_INPUT_RATE_INSTANCE: + buffer->setStepFunction(MTL::VertexStepFunctionPerInstance); + break; + } + bufferLayout->setObject(buffer, binding); + } + + pipelineDescriptor->setVertexDescriptor(vertexDescriptor); + + pipelineDescriptor->setVertexFunction(createInfo.vertexShader.cast()->getFunction()); + + + vertexDescriptor->release(); + pipelineDescriptor->release(); +} + +PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo createInfo) {} + +PComputePipeline PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo createInfo) {} diff --git a/src/Engine/Graphics/Metal/Resources.h b/src/Engine/Graphics/Metal/Resources.h index 88e46a7..53f781d 100644 --- a/src/Engine/Graphics/Metal/Resources.h +++ b/src/Engine/Graphics/Metal/Resources.h @@ -1,5 +1,6 @@ #pragma once #include "Graphics/Resources.h" +#include "Metal/MTLSampler.hpp" #include #include #include @@ -29,5 +30,18 @@ private: MTL::Event *handle; }; DEFINE_REF(Event) +class Sampler : public Gfx::Sampler +{ +public: + Sampler(PGraphics graphics, const SamplerCreateInfo& createInfo); + virtual ~Sampler(); + MTL::SamplerState* getHandle() const + { + return sampler; + } +private: + MTL::SamplerState* sampler; +}; +DEFINE_REF(Sampler) } // namespace Metal } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Resources.mm b/src/Engine/Graphics/Metal/Resources.mm index ffb2f80..c84577a 100644 --- a/src/Engine/Graphics/Metal/Resources.mm +++ b/src/Engine/Graphics/Metal/Resources.mm @@ -1,5 +1,7 @@ #include "Resources.h" #include "Graphics.h" +#include "Metal/MTLSampler.hpp" +#include "Enums.h" using namespace Seele; using namespace Seele::Metal; @@ -10,4 +12,30 @@ Fence::~Fence() { handle->release(); } Event::Event(PGraphics graphics) : handle(graphics->getDevice()->newEvent()) {} -Event::~Event() { handle->release(); } \ No newline at end of file +Event::~Event() { handle->release(); } + +Sampler::Sampler(PGraphics graphics, const SamplerCreateInfo& createInfo) +{ + MTL::SamplerDescriptor* desc = MTL::SamplerDescriptor::alloc()->init(); + desc->setBorderColor(cast(createInfo.borderColor)); + desc->setCompareFunction(cast(createInfo.compareOp)); + desc->setLodAverage(createInfo.mipLodBias); + desc->setLodMaxClamp(createInfo.maxLod); + desc->setLodMinClamp(createInfo.minLod); + desc->setMinFilter(cast(createInfo.minFilter)); + desc->setMagFilter(cast(createInfo.magFilter)); + desc->setMipFilter(cast(createInfo.mipmapMode)); + desc->setMaxAnisotropy(createInfo.maxAnisotropy); + desc->setNormalizedCoordinates(!createInfo.unnormalizedCoordinates); + desc->setRAddressMode(cast(createInfo.addressModeU)); + desc->setSAddressMode(cast(createInfo.addressModeV)); + desc->setTAddressMode(cast(createInfo.addressModeW)); + desc->setSupportArgumentBuffers(true); + sampler = graphics->getDevice()->newSamplerState(desc); + desc->release(); +} + +Sampler::~Sampler() +{ + sampler->release(); +} \ No newline at end of file diff --git a/src/Engine/Graphics/Metal/Shader.mm b/src/Engine/Graphics/Metal/Shader.mm index eba39e5..80a0a5f 100644 --- a/src/Engine/Graphics/Metal/Shader.mm +++ b/src/Engine/Graphics/Metal/Shader.mm @@ -1,10 +1,15 @@ #include "Shader.h" +#include "Foundation/NSError.hpp" +#include "Foundation/NSString.hpp" #include "Graphics.h" #include "Graphics/Enums.h" #include "Graphics/slang-compile.h" +#include "Metal/MTLDevice.hpp" +#include "Metal/MTLLibrary.hpp" #include -#include #include +#include +#include using namespace Seele; using namespace Seele::Metal; @@ -20,64 +25,27 @@ Shader::~Shader() { void Shader::create(const ShaderCreateInfo &createInfo) { Slang::ComPtr kernelBlob = - generateShader(createInfo, SLANG_DXIL); - thread_local IRCompiler *pCompiler = nullptr; - if (pCompiler == nullptr) { - pCompiler = IRCompilerCreate(); + generateShader(createInfo, SLANG_SPIRV); + spirv_cross::CompilerMSL comp((const uint32 *)kernelBlob->getBufferPointer(), + kernelBlob->getBufferSize() / 4); + auto options = comp.get_msl_options(); + options.argument_buffers = true; + options.argument_buffers_tier = + spirv_cross::CompilerMSL::Options::ArgumentBuffersTier::Tier2; + options.set_msl_version(3); + comp.set_msl_options(options); + std::string metalCode = comp.compile(); + NS::Error *error = nullptr; + MTL::CompileOptions *mtlOptions = MTL::CompileOptions::alloc()->init(); + + library = graphics->getDevice()->newLibrary( + NS::String::string(metalCode.c_str(), NS::ASCIIStringEncoding), + mtlOptions, &error); + if (error) { + std::cout << error->debugDescription() << std::endl; + assert(false); } - IRCompilerSetEntryPointName(pCompiler, "main"); - - IRObject *pDXIL = IRObjectCreateFromDXIL( - (const uint8 *)kernelBlob->getBufferPointer(), - kernelBlob->getBufferSize(), IRBytecodeOwnershipNone); - - // Compile DXIL to Metal IR: - IRError *pError = nullptr; - IRObject *pOutIR = - IRCompilerAllocCompileAndLink(pCompiler, NULL, pDXIL, &pError); - - if (!pOutIR) { - // Inspect pError to determine cause. - IRErrorDestroy(pError); - } - IRShaderStage irStage; - switch (stage) { - case Gfx::SE_SHADER_STAGE_VERTEX_BIT: irStage = IRShaderStageVertex; - case Gfx::SE_SHADER_STAGE_FRAGMENT_BIT: irStage = IRShaderStageFragment; - case Gfx::SE_SHADER_STAGE_COMPUTE_BIT: irStage = IRShaderStageCompute; - case Gfx::SE_SHADER_STAGE_TASK_BIT_NV: irStage = IRShaderStageAmplification; - case Gfx::SE_SHADER_STAGE_MESH_BIT_NV: irStage = IRShaderStageMesh; - } - // Retrieve Metallib: - IRMetalLibBinary *pMetallib = IRMetalLibBinaryCreate(); - IRObjectGetMetalLibBinary(pOutIR, irStage, pMetallib); - size_t metallibSize = IRMetalLibGetBytecodeSize(pMetallib); - uint8_t *metallib = new uint8_t[metallibSize]; - IRMetalLibGetBytecode(pMetallib, metallib); - - IRShaderReflection* reflection = IRShaderReflectionCreate(); - IRObjectGetReflection(pOutIR, irStage, reflection); - Array locations( - IRShaderReflectionGetResourceCount(reflection)); - IRShaderReflectionGetResourceLocations(reflection, locations.data()); - for(auto l : locations) - { - std::cout << "Resource " << l.resourceName << " Type " << l.resourceType << " size " << l.sizeBytes << " slot " << l.slot << " space " << l.space << " offset " << l.topLevelOffset << std::endl; - } - IRShaderReflectionDestroy(reflection); - - // Store the metallib to custom format or disk, or use to create a MTLLibrary. - NS::Error *__autoreleasing error = nil; - dispatch_data_t data = dispatch_data_create(metallib, metallibSize, - dispatch_get_main_queue(), NULL); - - library = graphics->getDevice()->newLibrary(data, &error); function = library->newFunction(NS::String::string("main", NS::ASCIIStringEncoding)); - - delete[] metallib; - IRMetalLibBinaryDestroy(pMetallib); - IRObjectDestroy(pDXIL); - IRObjectDestroy(pOutIR); - IRCompilerDestroy(pCompiler); + mtlOptions->release(); } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderTarget.h b/src/Engine/Graphics/RenderTarget.h index 0e27c6b..7fbe7d8 100644 --- a/src/Engine/Graphics/RenderTarget.h +++ b/src/Engine/Graphics/RenderTarget.h @@ -1,4 +1,5 @@ #pragma once +#include "Graphics/Enums.h" #include "Resources.h" #include "Texture.h" #include "Window.h" @@ -85,12 +86,12 @@ public: protected: PTexture2D texture = nullptr; PViewport viewport = nullptr; - SeImageLayout initialLayout = SE_IMAGE_LAYOUT_BEGIN_RANGE; - SeImageLayout finalLayout = SE_IMAGE_LAYOUT_BEGIN_RANGE; - SeAttachmentLoadOp loadOp = SE_ATTACHMENT_LOAD_OP_BEGIN_RANGE; - SeAttachmentStoreOp storeOp = SE_ATTACHMENT_STORE_OP_BEGIN_RANGE; - SeAttachmentLoadOp stencilLoadOp = SE_ATTACHMENT_LOAD_OP_BEGIN_RANGE; - SeAttachmentStoreOp stencilStoreOp = SE_ATTACHMENT_STORE_OP_BEGIN_RANGE; + SeImageLayout initialLayout = SE_IMAGE_LAYOUT_UNDEFINED; + SeImageLayout finalLayout = SE_IMAGE_LAYOUT_UNDEFINED; + SeAttachmentLoadOp loadOp = SE_ATTACHMENT_LOAD_OP_DONT_CARE; + SeAttachmentStoreOp storeOp = SE_ATTACHMENT_STORE_OP_DONT_CARE; + SeAttachmentLoadOp stencilLoadOp = SE_ATTACHMENT_LOAD_OP_DONT_CARE; + SeAttachmentStoreOp stencilStoreOp = SE_ATTACHMENT_STORE_OP_DONT_CARE; }; struct RenderTargetLayout diff --git a/src/Engine/Graphics/Vulkan/Buffer.h b/src/Engine/Graphics/Vulkan/Buffer.h index a30b1f7..bede959 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.h +++ b/src/Engine/Graphics/Vulkan/Buffer.h @@ -1,146 +1,134 @@ #pragma once -#include "Graphics/Buffer.h" #include "Graphics.h" +#include "Graphics/Buffer.h" -namespace Seele -{ -namespace Vulkan -{ -class Buffer -{ +namespace Seele { +namespace Vulkan { +class Buffer { public: - Buffer(PGraphics graphics, - uint64 size, - VkBufferUsageFlags usage, - Gfx::QueueType& queueType, - bool dynamic, - std::string name); - virtual ~Buffer(); - VkBuffer getHandle() const - { - return buffers[currentBuffer].buffer; - } - uint64 getSize() const - { - return size; - } - void advanceBuffer() - { - currentBuffer = (currentBuffer + 1) % numBuffers; - } - void *map(bool writeOnly = true); - void *mapRegion(uint64 regionOffset, uint64 regionSize, bool writeOnly = true); - void unmap(); + Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, + Gfx::QueueType &queueType, bool dynamic, std::string name); + virtual ~Buffer(); + VkBuffer getHandle() const { return buffers[currentBuffer].buffer; } + uint64 getSize() const { return size; } + void *map(bool writeOnly = true); + void *mapRegion(uint64 regionOffset, uint64 regionSize, + bool writeOnly = true); + void unmap(); protected: - struct BufferAllocation - { - VkBuffer buffer; - VmaAllocation allocation; - VmaAllocationInfo info; - VkMemoryPropertyFlags properties; - }; - PGraphics graphics; - uint32 currentBuffer; - uint64 size; - Gfx::QueueType& owner; - BufferAllocation buffers[Gfx::numFramesBuffered]; - uint32 numBuffers; - std::string name; + struct BufferAllocation { + VkBuffer buffer; + VmaAllocation allocation; + VmaAllocationInfo info; + VkMemoryPropertyFlags properties; + }; + PGraphics graphics; + uint32 currentBuffer; + uint64 size; + Gfx::QueueType &owner; + Array buffers; + uint32 numBuffers; + std::string name; - void executeOwnershipBarrier(Gfx::QueueType newOwner); - void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); - - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0; + void executeOwnershipBarrier(Gfx::QueueType newOwner); + void executePipelineBarrier(VkAccessFlags srcAccess, + VkPipelineStageFlags srcStage, + VkAccessFlags dstAccess, + VkPipelineStageFlags dstStage); - virtual VkAccessFlags getSourceAccessMask() = 0; - virtual VkAccessFlags getDestAccessMask() = 0; + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0; + + virtual VkAccessFlags getSourceAccessMask() = 0; + virtual VkAccessFlags getDestAccessMask() = 0; }; DEFINE_REF(Buffer) -class UniformBuffer : public Gfx::UniformBuffer, public Buffer -{ +class VertexBuffer : public Gfx::VertexBuffer, public Buffer { public: - UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &sourceData); - virtual ~UniformBuffer(); - virtual bool updateContents(const DataSource &sourceData) override; - - virtual void beginFrame() override; + VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &sourceData); + virtual ~VertexBuffer(); + + virtual void updateRegion(DataSource update) override; + virtual void download(Array &buffer) override; + protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; - virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override; + // Inherited via Vulkan::Buffer + virtual VkAccessFlags getSourceAccessMask() override; + virtual VkAccessFlags getDestAccessMask() override; + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, + Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, + Gfx::SePipelineStageFlags dstStage) override; +}; +DEFINE_REF(VertexBuffer) + +class IndexBuffer : public Gfx::IndexBuffer, public Buffer { +public: + IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &sourceData); + virtual ~IndexBuffer(); + + virtual void download(Array &buffer) override; + +protected: + // Inherited via Vulkan::Buffer + virtual VkAccessFlags getSourceAccessMask() override; + virtual VkAccessFlags getDestAccessMask() override; + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, + Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, + Gfx::SePipelineStageFlags dstStage) override; +}; +DEFINE_REF(IndexBuffer) +class UniformBuffer : public Gfx::UniformBuffer, public Buffer { +public: + UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &sourceData); + virtual ~UniformBuffer(); + virtual bool updateContents(const DataSource &sourceData) override; + +protected: + // Inherited via Vulkan::Buffer + virtual VkAccessFlags getSourceAccessMask() override; + virtual VkAccessFlags getDestAccessMask() override; + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, + Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, + Gfx::SePipelineStageFlags dstStage) override; private: }; DEFINE_REF(UniformBuffer) -class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer -{ +class ShaderBuffer : public Gfx::ShaderBuffer, public Buffer { public: - ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sourceData); - virtual ~ShaderBuffer(); - virtual bool updateContents(const DataSource &sourceData) override; - virtual void beginFrame() override; + ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &sourceData); + virtual ~ShaderBuffer(); + virtual bool updateContents(const DataSource &sourceData) override; protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; - virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override; + // Inherited via Vulkan::Buffer + virtual VkAccessFlags getSourceAccessMask() override; + virtual VkAccessFlags getDestAccessMask() override; + virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; + // Inherited via QueueOwnedResource + virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; + virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, + Gfx::SePipelineStageFlags srcStage, + Gfx::SeAccessFlags dstAccess, + Gfx::SePipelineStageFlags dstStage) override; + private: }; DEFINE_REF(ShaderBuffer) -class VertexBuffer : public Gfx::VertexBuffer, public Buffer -{ -public: - VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &sourceData); - virtual ~VertexBuffer(); - - virtual void updateRegion(DataSource update) override; - virtual void download(Array& buffer) override; - virtual void beginFrame() override; -protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; - virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override; -}; -DEFINE_REF(VertexBuffer) - -class IndexBuffer : public Gfx::IndexBuffer, public Buffer -{ -public: - IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &sourceData); - virtual ~IndexBuffer(); - - virtual void download(Array& buffer) override; - virtual void beginFrame() override; -protected: - // Inherited via Vulkan::Buffer - virtual VkAccessFlags getSourceAccessMask() override; - virtual VkAccessFlags getDestAccessMask() override; - virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) override; - // Inherited via QueueOwnedResource - virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override; - virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, - VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) override; -}; -DEFINE_REF(IndexBuffer) -} -} \ No newline at end of file +} // namespace Vulkan +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Descriptor.cpp b/src/Engine/Graphics/Vulkan/Descriptor.cpp index 34db576..9d07f85 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.cpp +++ b/src/Engine/Graphics/Vulkan/Descriptor.cpp @@ -1,433 +1,367 @@ #include "Descriptor.h" -#include "Graphics.h" -#include "Texture.h" #include "Buffer.h" #include "Command.h" +#include "Graphics.h" +#include "Texture.h" using namespace Seele; using namespace Seele::Vulkan; DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name) - : Gfx::DescriptorLayout(name) - , graphics(graphics) - , layoutHandle(VK_NULL_HANDLE) -{ -} -DescriptorLayout::~DescriptorLayout() -{ - if (layoutHandle != VK_NULL_HANDLE) - { - vkDestroyDescriptorSetLayout(graphics->getDevice(), layoutHandle, nullptr); - } + : Gfx::DescriptorLayout(name), graphics(graphics), layoutHandle(VK_NULL_HANDLE) {} + +DescriptorLayout::~DescriptorLayout() { + if (layoutHandle != VK_NULL_HANDLE) { + vkDestroyDescriptorSetLayout(graphics->getDevice(), layoutHandle, nullptr); + } } -void DescriptorLayout::create() -{ - if (layoutHandle != VK_NULL_HANDLE) - { - return; - } - bindings.resize(descriptorBindings.size()); - Array bindingFlags(descriptorBindings.size()); - for (size_t i = 0; i < descriptorBindings.size(); ++i) - { - const Gfx::DescriptorBinding &gfxBinding = descriptorBindings[i]; - bindings[i] = { - .binding = gfxBinding.binding, - .descriptorType = cast(gfxBinding.descriptorType), - .descriptorCount = gfxBinding.descriptorCount, - .stageFlags = gfxBinding.shaderStages, - .pImmutableSamplers = nullptr, - }; - bindingFlags[i] = gfxBinding.bindingFlags; - } - VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, - .pNext = nullptr, - .bindingCount = static_cast(bindingFlags.size()), - .pBindingFlags = bindingFlags.data(), +void DescriptorLayout::create() { + if (layoutHandle != VK_NULL_HANDLE) { + return; + } + bindings.resize(descriptorBindings.size()); + Array bindingFlags(descriptorBindings.size()); + for (size_t i = 0; i < descriptorBindings.size(); ++i) { + const Gfx::DescriptorBinding& gfxBinding = descriptorBindings[i]; + bindings[i] = { + .binding = gfxBinding.binding, + .descriptorType = cast(gfxBinding.descriptorType), + .descriptorCount = gfxBinding.descriptorCount, + .stageFlags = gfxBinding.shaderStages, + .pImmutableSamplers = nullptr, }; - VkDescriptorSetLayoutCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .pNext = &bindingFlagsInfo, - .flags = 0, - .bindingCount = (uint32)bindings.size(), - .pBindings = bindings.data(), - }; - VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle)); + bindingFlags[i] = gfxBinding.bindingFlags; + } + VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .pNext = nullptr, + .bindingCount = static_cast(bindingFlags.size()), + .pBindingFlags = bindingFlags.data(), + }; + VkDescriptorSetLayoutCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = &bindingFlagsInfo, + .flags = 0, + .bindingCount = (uint32)bindings.size(), + .pBindings = bindings.data(), + }; + VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle)); - pool = new DescriptorPool(graphics, *this); + pool = new DescriptorPool(graphics, this); - hash = CRC::Calculate(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size(), CRC::CRC_32()); + hash = CRC::Calculate(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size(), CRC::CRC_32()); } -PipelineLayout::~PipelineLayout() -{ -} +DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) { + for (uint32 i = 0; i < cachedHandles.size(); ++i) { + cachedHandles[i] = nullptr; + } -Map cachedLayouts; - -void PipelineLayout::create() -{ - vulkanDescriptorLayouts.resize(descriptorSetLayouts.size()); - for (size_t i = 0; i < descriptorSetLayouts.size(); ++i) - { - // There could be unused descriptor set indices - if(descriptorSetLayouts[i] == nullptr) - { - vulkanDescriptorLayouts[i] = VK_NULL_HANDLE; - continue; - } - PDescriptorLayout layout = descriptorSetLayouts[i].cast(); - layout->create(); - vulkanDescriptorLayouts[i] = layout->getHandle(); + uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM + std::memset(perTypeSizes, 0, sizeof(perTypeSizes)); + for (uint32 i = 0; i < layout->getBindings().size(); ++i) { + auto& binding = layout->getBindings()[i]; + int typeIndex = binding.descriptorType; + perTypeSizes[typeIndex] += 256; + } + Array poolSizes; + for (uint32 i = 0; i < VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; ++i) { + if (perTypeSizes[i] > 0) { + VkDescriptorPoolSize size; + size.descriptorCount = perTypeSizes[i]; + size.type = (VkDescriptorType)i; + poolSizes.add(size); } - - Array vkPushConstants(pushConstants.size()); - for (size_t i = 0; i < pushConstants.size(); i++) - { - vkPushConstants[i].offset = pushConstants[i].offset; - vkPushConstants[i].size = pushConstants[i].size; - vkPushConstants[i].stageFlags = (VkShaderStageFlagBits)pushConstants[i].stageFlags; - } - - VkPipelineLayoutCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .setLayoutCount = (uint32)vulkanDescriptorLayouts.size(), - .pSetLayouts = vulkanDescriptorLayouts.data(), - .pushConstantRangeCount = (uint32)vkPushConstants.size(), - .pPushConstantRanges = vkPushConstants.data(), - }; - - layoutHash = CRC::Calculate(createInfo.pPushConstantRanges, sizeof(VkPushConstantRange) * createInfo.pushConstantRangeCount, CRC::CRC_32()); - layoutHash = CRC::Calculate(createInfo.pSetLayouts, sizeof(VkDescriptorSetLayout) * createInfo.setLayoutCount, CRC::CRC_32(), layoutHash); - - if (cachedLayouts.contains(layoutHash)) - { - layoutHandle = cachedLayouts[layoutHash]; - return; - } - - VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle)); - cachedLayouts[layoutHash] = layoutHandle; + } + VkDescriptorPoolCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .maxSets = maxSets * Gfx::numFramesBuffered, + .poolSizeCount = (uint32)poolSizes.size(), + .pPoolSizes = poolSizes.data(), + }; + VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle)); } -void PipelineLayout::reset() -{ - vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr); - descriptorSetLayouts.clear(); - pushConstants.clear(); +DescriptorPool::~DescriptorPool() { + graphics->getDestructionManager()->queueDescriptorPool(graphics->getGraphicsCommands()->getCommands(), poolHandle); + if (nextAlloc) { + delete nextAlloc; + } } -DescriptorSet::~DescriptorSet() -{ -} - -void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) -{ - PUniformBuffer vulkanBuffer = uniformBuffer.cast(); - UniformBuffer* cachedBuffer = reinterpret_cast(cachedData[binding]); - if(vulkanBuffer->isDataEquals(cachedBuffer)) - { - //std::cout << "uniform data equal, skip" << std::endl; - return; +Gfx::PDescriptorSet DescriptorPool::allocateDescriptorSet() { + VkDescriptorSetLayout layoutHandle = layout->getHandle(); + VkDescriptorSetVariableDescriptorCountAllocateInfo setCounts = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, + .pNext = nullptr, + .descriptorSetCount = 1, + }; + VkDescriptorSetAllocateInfo allocInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .pNext = nullptr, + .descriptorPool = poolHandle, + .descriptorSetCount = 1, + .pSetLayouts = &layoutHandle, + }; + uint32 counts = 0; + for (const auto& binding : layout->bindings) { + if (binding.descriptorCount > 0) { + counts = binding.descriptorCount; } - bufferInfos.add(VkDescriptorBufferInfo{ - .buffer = vulkanBuffer->getHandle(), - .offset = 0, - .range = vulkanBuffer->getSize(), - }); + } + if (layout->bindings.size() > 0) { + setCounts.pDescriptorCounts = &counts; + allocInfo.pNext = &setCounts; + } + for (uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex) { + if (cachedHandles[setIndex] == nullptr) { + cachedHandles[setIndex] = new DescriptorSet(graphics, this); + } + if (cachedHandles[setIndex]->isCurrentlyBound() || cachedHandles[setIndex]->isCurrentlyInUse()) { + // Currently in use, skip + continue; + } + if (cachedHandles[setIndex]->getHandle() == VK_NULL_HANDLE) { + // If it hasnt been initialized, allocate it + VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &cachedHandles[setIndex]->setHandle)); + } + cachedHandles[setIndex]->allocate(); - writeDescriptors.add(VkWriteDescriptorSet{ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = setHandle, - .dstBinding = binding, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pBufferInfo = &bufferInfos.back(), - }); + PDescriptorSet vulkanSet = cachedHandles[setIndex]; + vulkanSet->cachedData.resize(layout->bindings.size()); + // Not really pretty, but this way the set knows which ones are valid + std::memset(vulkanSet->cachedData.data(), 0, sizeof(void*) * vulkanSet->cachedData.size()); - cachedData[binding] = vulkanBuffer.getHandle(); + // Found set, stop searching + return vulkanSet; + } + if (nextAlloc == nullptr) { + nextAlloc = new DescriptorPool(graphics, layout); + } + // std::cout << "Out of descriptors, forwarding" << std::endl; + return nextAlloc->allocateDescriptorSet(); + // throw std::logic_error("Out of descriptor sets"); } -void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuffer) -{ - PShaderBuffer vulkanBuffer = shaderBuffer.cast(); - ShaderBuffer* cachedBuffer = reinterpret_cast(cachedData[binding]); - if(vulkanBuffer.getHandle() == cachedBuffer) - { - return; +void DescriptorPool::reset() { + for (uint32 i = 0; i < cachedHandles.size(); ++i) { + if (cachedHandles[i] == nullptr) { + return; } - - bufferInfos.add(VkDescriptorBufferInfo{ - .buffer = vulkanBuffer->getHandle(), - .offset = 0, - .range = vulkanBuffer->getSize(), - }); - - writeDescriptors.add(VkWriteDescriptorSet{ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = setHandle, - .dstBinding = binding, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .pBufferInfo = &bufferInfos.back(), - }); - - cachedData[binding] = vulkanBuffer.getHandle(); + cachedHandles[i]->free(); + } + if (nextAlloc != nullptr) { + nextAlloc->reset(); + } } -void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) -{ - PSampler vulkanSampler = samplerState.cast(); - Sampler* cachedSampler = reinterpret_cast(cachedData[binding]); - if(vulkanSampler.getHandle() == cachedSampler) - { - return; - } +DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner) + : Gfx::DescriptorSet(owner->getLayout()), setHandle(VK_NULL_HANDLE), graphics(graphics), owner(owner), bindCount(0), + currentlyInUse(false) {} +DescriptorSet::~DescriptorSet() {} + +void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) { + PUniformBuffer vulkanBuffer = uniformBuffer.cast(); + UniformBuffer* cachedBuffer = reinterpret_cast(cachedData[binding]); + if (vulkanBuffer->isDataEquals(cachedBuffer)) { + // std::cout << "uniform data equal, skip" << std::endl; + return; + } + bufferInfos.add(VkDescriptorBufferInfo{ + .buffer = vulkanBuffer->getHandle(), + .offset = 0, + .range = vulkanBuffer->getSize(), + }); + + writeDescriptors.add(VkWriteDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = setHandle, + .dstBinding = binding, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pBufferInfo = &bufferInfos.back(), + }); + + cachedData[binding] = vulkanBuffer.getHandle(); +} + +void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PShaderBuffer shaderBuffer) { + PShaderBuffer vulkanBuffer = shaderBuffer.cast(); + ShaderBuffer* cachedBuffer = reinterpret_cast(cachedData[binding]); + if (vulkanBuffer.getHandle() == cachedBuffer) { + return; + } + + bufferInfos.add(VkDescriptorBufferInfo{ + .buffer = vulkanBuffer->getHandle(), + .offset = 0, + .range = vulkanBuffer->getSize(), + }); + + writeDescriptors.add(VkWriteDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = setHandle, + .dstBinding = binding, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = &bufferInfos.back(), + }); + + cachedData[binding] = vulkanBuffer.getHandle(); +} + +void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState) { + PSampler vulkanSampler = samplerState.cast(); + Sampler* cachedSampler = reinterpret_cast(cachedData[binding]); + if (vulkanSampler.getHandle() == cachedSampler) { + return; + } + imageInfos.add(VkDescriptorImageInfo{ + .sampler = vulkanSampler->sampler, + .imageView = VK_NULL_HANDLE, + .imageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + }); + + writeDescriptors.add(VkWriteDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = setHandle, + .dstBinding = binding, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, + .pImageInfo = &imageInfos.back(), + }); + + cachedData[binding] = vulkanSampler.getHandle(); +} + +void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) { + TextureBase* vulkanTexture = texture.cast().getHandle(); + TextureBase* cachedTexture = reinterpret_cast(cachedData[binding]); + if (vulkanTexture == cachedTexture) { + return; + } + // It is assumed that the image is in the correct layout + imageInfos.add(VkDescriptorImageInfo{ + .sampler = samplerState != nullptr ? samplerState.cast()->sampler : VK_NULL_HANDLE, + .imageView = vulkanTexture->getView(), + .imageLayout = cast(vulkanTexture->getLayout()), + }); + VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + if (samplerState != nullptr) { + descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + } else if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) { + descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + } + writeDescriptors.add(VkWriteDescriptorSet{ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = setHandle, + .dstBinding = binding, + .dstArrayElement = 0, + .descriptorCount = 1, + .descriptorType = descriptorType, + .pImageInfo = &imageInfos.back(), + }); + + cachedData[binding] = vulkanTexture; +} +void DescriptorSet::updateTextureArray(uint32_t binding, Array textures) { + // maybe make this a parameter? + uint32 arrayElement = 0; + for (auto& gfxTexture : textures) { + TextureBase* vulkanTexture = gfxTexture.cast().getHandle(); imageInfos.add(VkDescriptorImageInfo{ - .sampler = vulkanSampler->sampler, - .imageView = VK_NULL_HANDLE, - .imageLayout = VK_IMAGE_LAYOUT_UNDEFINED, - }); - - writeDescriptors.add(VkWriteDescriptorSet{ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = setHandle, - .dstBinding = binding, - .dstArrayElement = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, - .pImageInfo = &imageInfos.back(), - }); - - cachedData[binding] = vulkanSampler.getHandle(); -} - -void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) -{ - TextureBase* vulkanTexture = texture.cast().getHandle(); - TextureBase* cachedTexture = reinterpret_cast(cachedData[binding]); - if(vulkanTexture == cachedTexture) - { - return; - } - //It is assumed that the image is in the correct layout - imageInfos.add(VkDescriptorImageInfo{ - .sampler = samplerState != nullptr ? samplerState.cast()->sampler : VK_NULL_HANDLE, + .sampler = VK_NULL_HANDLE, .imageView = vulkanTexture->getView(), .imageLayout = cast(vulkanTexture->getLayout()), }); + VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - if(samplerState != nullptr) - { - descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - } - else if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) - { - descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) { + descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; } writeDescriptors.add(VkWriteDescriptorSet{ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = nullptr, .dstSet = setHandle, .dstBinding = binding, - .dstArrayElement = 0, + .dstArrayElement = arrayElement++, .descriptorCount = 1, .descriptorType = descriptorType, .pImageInfo = &imageInfos.back(), - }); - - cachedData[binding] = vulkanTexture; -} -void DescriptorSet::updateTextureArray(uint32_t binding, Array textures) -{ - // maybe make this a parameter? - uint32 arrayElement = 0; - for(auto& gfxTexture : textures) - { - TextureBase* vulkanTexture = gfxTexture.cast().getHandle(); - imageInfos.add(VkDescriptorImageInfo{ - .sampler = VK_NULL_HANDLE, - .imageView = vulkanTexture->getView(), - .imageLayout = cast(vulkanTexture->getLayout()), - }); - - VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) - { - descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - } - writeDescriptors.add(VkWriteDescriptorSet{ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = setHandle, - .dstBinding = binding, - .dstArrayElement = arrayElement++, - .descriptorCount = 1, - .descriptorType = descriptorType, - .pImageInfo = &imageInfos.back(), - }); - } + }); + } } -bool DescriptorSet::operator<(Gfx::PDescriptorSet other) -{ - PDescriptorSet otherSet = other.cast(); - return this < otherSet.getHandle(); +void DescriptorSet::writeChanges() { + if (writeDescriptors.size() > 0) { + if (isCurrentlyBound()) { + std::cout << "Descriptor currently bound, allocate a new one instead" << std::endl; + assert(!isCurrentlyBound()); + } + vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); + writeDescriptors.clear(); + imageInfos.clear(); + bufferInfos.clear(); + } } -uint32 DescriptorSet::getSetIndex() const -{ - return owner->getLayout().getSetIndex(); -} +PipelineLayout::PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout) + : Gfx::PipelineLayout(baseLayout), graphics(graphics), layoutHandle(VK_NULL_HANDLE) {} -void DescriptorSet::writeChanges() -{ - if (writeDescriptors.size() > 0) - { - if(isCurrentlyBound()) - { - std::cout << "Descriptor currently bound, allocate a new one instead" << std::endl; - assert(!isCurrentlyBound()); - } - vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); - writeDescriptors.clear(); - imageInfos.clear(); - bufferInfos.clear(); - } -} +PipelineLayout::~PipelineLayout() {} -DescriptorPool::DescriptorPool(PGraphics graphics, DescriptorLayout &layout) - : graphics(graphics) - , layout(layout) -{ - for(uint32 i = 0; i < cachedHandles.size(); ++i) - { - cachedHandles[i] = nullptr; - } +Map cachedLayouts; - uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM - std::memset(perTypeSizes, 0, sizeof(perTypeSizes)); - for (uint32 i = 0; i < layout.getBindings().size(); ++i) - { - auto &binding = layout.getBindings()[i]; - int typeIndex = binding.descriptorType; - perTypeSizes[typeIndex] += 256; +void PipelineLayout::create() { + vulkanDescriptorLayouts.resize(descriptorSetLayouts.size()); + for (size_t i = 0; i < descriptorSetLayouts.size(); ++i) { + // There could be unused descriptor set indices + if (descriptorSetLayouts[i] == nullptr) { + vulkanDescriptorLayouts[i] = VK_NULL_HANDLE; + continue; } - Array poolSizes; - for (uint32 i = 0; i < VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; ++i) - { - if (perTypeSizes[i] > 0) - { - VkDescriptorPoolSize size; - size.descriptorCount = perTypeSizes[i]; - size.type = (VkDescriptorType)i; - poolSizes.add(size); - } - } - VkDescriptorPoolCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .maxSets = maxSets * Gfx::numFramesBuffered, - .poolSizeCount = (uint32)poolSizes.size(), - .pPoolSizes = poolSizes.data(), - }; - VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle)); -} + PDescriptorLayout layout = descriptorSetLayouts[i].cast(); + layout->create(); + vulkanDescriptorLayouts[i] = layout->getHandle(); + } -DescriptorPool::~DescriptorPool() -{ - graphics->getDestructionManager()->queueDescriptorPool(graphics->getGraphicsCommands()->getCommands(), poolHandle); - if(nextAlloc) - { - delete nextAlloc; - } -} + Array vkPushConstants(pushConstants.size()); + for (size_t i = 0; i < pushConstants.size(); i++) { + vkPushConstants[i].offset = pushConstants[i].offset; + vkPushConstants[i].size = pushConstants[i].size; + vkPushConstants[i].stageFlags = (VkShaderStageFlagBits)pushConstants[i].stageFlags; + } -Gfx::PDescriptorSet DescriptorPool::allocateDescriptorSet() -{ - VkDescriptorSetLayout layoutHandle = layout.getHandle(); - VkDescriptorSetVariableDescriptorCountAllocateInfo setCounts = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, - .pNext = nullptr, - .descriptorSetCount = 1, - }; - VkDescriptorSetAllocateInfo allocInfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pNext = nullptr, - .descriptorPool = poolHandle, - .descriptorSetCount = 1, - .pSetLayouts = &layoutHandle, - }; - uint32 counts = 0; - for(const auto& binding : layout.bindings) - { - if(binding.descriptorCount > 0) - { - counts = binding.descriptorCount; - } - } - if (layout.bindings.size() > 0) - { - setCounts.pDescriptorCounts = &counts; - allocInfo.pNext = &setCounts; - } - for(uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex) - { - if(cachedHandles[setIndex] == nullptr) - { - cachedHandles[setIndex] = new DescriptorSet(graphics, this); - } - if(cachedHandles[setIndex]->isCurrentlyBound() || cachedHandles[setIndex]->isCurrentlyInUse()) - { - // Currently in use, skip - continue; - } - if(cachedHandles[setIndex]->getHandle() == VK_NULL_HANDLE) - { - //If it hasnt been initialized, allocate it - VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &cachedHandles[setIndex]->setHandle)); - } - cachedHandles[setIndex]->allocate(); - - PDescriptorSet vulkanSet = cachedHandles[setIndex]; - vulkanSet->cachedData.resize(layout.bindings.size()); - // Not really pretty, but this way the set knows which ones are valid - std::memset(vulkanSet->cachedData.data(), 0, sizeof(void*) * vulkanSet->cachedData.size()); - - //Found set, stop searching - return vulkanSet; - } - if(nextAlloc == nullptr) - { - nextAlloc = new DescriptorPool(graphics, layout); - } - //std::cout << "Out of descriptors, forwarding" << std::endl; - return nextAlloc->allocateDescriptorSet(); - //throw std::logic_error("Out of descriptor sets"); -} + VkPipelineLayoutCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .setLayoutCount = (uint32)vulkanDescriptorLayouts.size(), + .pSetLayouts = vulkanDescriptorLayouts.data(), + .pushConstantRangeCount = (uint32)vkPushConstants.size(), + .pPushConstantRanges = vkPushConstants.data(), + }; -void DescriptorPool::reset() -{ - for(uint32 i = 0; i < cachedHandles.size(); ++i) - { - if(cachedHandles[i] == nullptr) - { - return; - } - cachedHandles[i]->free(); - } - if(nextAlloc != nullptr) - { - nextAlloc->reset(); - } + layoutHash = CRC::Calculate(createInfo.pPushConstantRanges, + sizeof(VkPushConstantRange) * createInfo.pushConstantRangeCount, CRC::CRC_32()); + layoutHash = CRC::Calculate(createInfo.pSetLayouts, sizeof(VkDescriptorSetLayout) * createInfo.setLayoutCount, + CRC::CRC_32(), layoutHash); + + if (cachedLayouts.contains(layoutHash)) { + layoutHandle = cachedLayouts[layoutHash]; + return; + } + + VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle)); + cachedLayouts[layoutHash] = layoutHandle; } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Descriptor.h b/src/Engine/Graphics/Vulkan/Descriptor.h index c5bd0c5..cdad028 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.h +++ b/src/Engine/Graphics/Vulkan/Descriptor.h @@ -1,150 +1,100 @@ #pragma once +#include "Containers/List.h" #include "Enums.h" #include "Graphics/Descriptor.h" -#include "Containers/List.h" #include "Resources.h" -namespace Seele -{ -namespace Vulkan -{ +namespace Seele { +namespace Vulkan { DECLARE_REF(Graphics) -class DescriptorLayout : public Gfx::DescriptorLayout -{ +class DescriptorLayout : public Gfx::DescriptorLayout { public: - DescriptorLayout(PGraphics graphics, const std::string& name); - virtual ~DescriptorLayout(); - virtual void create() override; - constexpr VkDescriptorSetLayout getHandle() const - { - return layoutHandle; - } + DescriptorLayout(PGraphics graphics, const std::string& name); + virtual ~DescriptorLayout(); + virtual void create() override; + constexpr VkDescriptorSetLayout getHandle() const { return layoutHandle; } + private: - uint32 hash; - PGraphics graphics; - Array bindings; - VkDescriptorSetLayout layoutHandle; - friend class DescriptorPool; + PGraphics graphics; + Array bindings; + VkDescriptorSetLayout layoutHandle; + friend class DescriptorPool; }; DEFINE_REF(DescriptorLayout) -class PipelineLayout : public Gfx::PipelineLayout -{ + +DECLARE_REF(DescriptorSet) +class DescriptorPool : public Gfx::DescriptorPool { public: - PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout) - : Gfx::PipelineLayout(baseLayout) - , graphics(graphics) - , layoutHandle(VK_NULL_HANDLE) - {} - virtual ~PipelineLayout(); - virtual void create(); - virtual void reset(); - constexpr VkPipelineLayout getHandle() const - { - return layoutHandle; - } + DescriptorPool(PGraphics graphics, PDescriptorLayout layout); + virtual ~DescriptorPool(); + virtual Gfx::PDescriptorSet allocateDescriptorSet() override; + virtual void reset() override; + + constexpr VkDescriptorPool getHandle() const { return poolHandle; } + constexpr PDescriptorLayout getLayout() const { return layout; } private: - Array vulkanDescriptorLayouts; - PGraphics graphics; - VkPipelineLayout layoutHandle; + PGraphics graphics; + PDescriptorLayout layout; + const static int maxSets = 64; + StaticArray cachedHandles; + VkDescriptorPool poolHandle; + DescriptorPool* nextAlloc = nullptr; }; -DEFINE_REF(PipelineLayout) +DEFINE_REF(DescriptorPool) -class DescriptorSet : public Gfx::DescriptorSet -{ +class DescriptorSet : public Gfx::DescriptorSet { public: - DescriptorSet(PGraphics graphics, PDescriptorPool owner) - : setHandle(VK_NULL_HANDLE) - , graphics(graphics) - , owner(owner) - , bindCount(0) - , currentlyInUse(false) - { - } - virtual ~DescriptorSet(); - virtual void writeChanges(); - virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer); - virtual void updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer); - virtual void updateSampler(uint32_t binding, Gfx::PSampler samplerState); - virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr); - virtual void updateTextureArray(uint32_t binding, Array texture); - virtual bool operator<(Gfx::PDescriptorSet other); - - constexpr bool isCurrentlyBound() const - { - return bindCount > 0; - } - constexpr bool isCurrentlyInUse() const - { - return currentlyInUse; - } - constexpr void bind() - { - bindCount++; - } - constexpr void unbind() - { - bindCount--; - } - constexpr void allocate() - { - currentlyInUse = true; - } - constexpr void free() - { - currentlyInUse = false; - } - constexpr VkDescriptorSet getHandle() const - { - return setHandle; - } - virtual uint32 getSetIndex() const; + DescriptorSet(PGraphics graphics, PDescriptorPool owner); + virtual ~DescriptorSet(); + virtual void writeChanges() override; + virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) override; + virtual void updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer) override; + virtual void updateSampler(uint32_t binding, Gfx::PSampler samplerState) override; + virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr) override; + virtual void updateTextureArray(uint32_t binding, Array texture) override; + + constexpr bool isCurrentlyBound() const { return bindCount > 0; } + constexpr bool isCurrentlyInUse() const { return currentlyInUse; } + constexpr void bind() { bindCount++; } + constexpr void unbind() { bindCount--; } + constexpr void allocate() { currentlyInUse = true; } + constexpr void free() { currentlyInUse = false; } + constexpr VkDescriptorSet getHandle() const { return setHandle; } private: - List imageInfos; - List bufferInfos; - Array writeDescriptors; - // contains the previously bound resources at every binding - // since the layout is fixed, trying to bind a texture to a buffer - // would not work anyways, so casts should be safe - Array cachedData; - VkDescriptorSet setHandle; - PGraphics graphics; - PDescriptorPool owner; - uint32 bindCount; - bool currentlyInUse; - friend class DescriptorPool; - friend class Command; - friend class RenderCommand; - friend class ComputeCommand; + List imageInfos; + List bufferInfos; + Array writeDescriptors; + // contains the previously bound resources at every binding + // since the layout is fixed, trying to bind a texture to a buffer + // would not work anyways, so casts should be safe + Array cachedData; + VkDescriptorSet setHandle; + PGraphics graphics; + PDescriptorPool owner; + uint32 bindCount; + bool currentlyInUse; + friend class DescriptorPool; + friend class Command; + friend class RenderCommand; + friend class ComputeCommand; }; DEFINE_REF(DescriptorSet) -class DescriptorPool : public Gfx::DescriptorPool -{ +class PipelineLayout : public Gfx::PipelineLayout { public: - DescriptorPool(PGraphics graphics, DescriptorLayout &layout); - virtual ~DescriptorPool(); - virtual Gfx::PDescriptorSet allocateDescriptorSet() override; - virtual void reset() override; - - constexpr VkDescriptorPool getHandle() const - { - return poolHandle; - } - constexpr DescriptorLayout& getLayout() const - { - return layout; - } + PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout); + virtual ~PipelineLayout(); + virtual void create(); + constexpr VkPipelineLayout getHandle() const { return layoutHandle; } private: - PGraphics graphics; - DescriptorLayout &layout; - const static int maxSets = 64; - StaticArray cachedHandles; - VkDescriptorPool poolHandle; - DescriptorPool* nextAlloc = nullptr; + Array vulkanDescriptorLayouts; + PGraphics graphics; + VkPipelineLayout layoutHandle; }; -DEFINE_REF(DescriptorPool) +DEFINE_REF(PipelineLayout) + } // namespace Vulkan } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/Enums.cpp b/src/Engine/Graphics/Vulkan/Enums.cpp index e7b3d4b..40d9a6a 100644 --- a/src/Engine/Graphics/Vulkan/Enums.cpp +++ b/src/Engine/Graphics/Vulkan/Enums.cpp @@ -1,4 +1,5 @@ #include "Enums.h" +#include using namespace Seele; using namespace Seele::Vulkan; @@ -76,9 +77,8 @@ Seele::Gfx::SeDescriptorType Seele::Vulkan::cast(const VkDescriptorType &descrip return SE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV; #endif default: - break; + throw std::logic_error("Not implemented"); } - return SE_DESCRIPTOR_TYPE_MAX_ENUM; } VkShaderStageFlagBits Seele::Vulkan::cast(const Seele::Gfx::SeShaderStageFlagBits &stage) @@ -120,10 +120,9 @@ VkShaderStageFlagBits Seele::Vulkan::cast(const Seele::Gfx::SeShaderStageFlagBit case SE_SHADER_STAGE_MESH_BIT_NV: return VK_SHADER_STAGE_MESH_BIT_NV; #endif - default: - break; + default: throw std::logic_error("Not implemented"); + } - return VK_SHADER_STAGE_ALL; } Seele::Gfx::SeShaderStageFlagBits Seele::Vulkan::cast(const VkShaderStageFlagBits &stage) @@ -164,10 +163,10 @@ Seele::Gfx::SeShaderStageFlagBits Seele::Vulkan::cast(const VkShaderStageFlagBit case VK_SHADER_STAGE_MESH_BIT_NV: return SE_SHADER_STAGE_MESH_BIT_NV; #endif - default: - break; + default: throw std::logic_error("Not implemented"); + } - return SE_SHADER_STAGE_ALL; + } VkFormat Seele::Vulkan::cast(const Seele::Gfx::SeFormat &format) @@ -1090,8 +1089,8 @@ Seele::Gfx::SeFormat Seele::Vulkan::cast(const VkFormat &format) return SE_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG; case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: return SE_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG; - default: - return SE_FORMAT_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } @@ -1129,8 +1128,8 @@ VkImageLayout Seele::Vulkan::cast(const Gfx::SeImageLayout &imageLayout) return VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV; case SE_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT: return VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT; - default: - return VK_IMAGE_LAYOUT_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } Gfx::SeImageLayout Seele::Vulkan::cast(const VkImageLayout &imageLayout) @@ -1167,8 +1166,8 @@ Gfx::SeImageLayout Seele::Vulkan::cast(const VkImageLayout &imageLayout) return SE_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV; case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT: return SE_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT; - default: - return SE_IMAGE_LAYOUT_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } VkAttachmentStoreOp Seele::Vulkan::cast(const Gfx::SeAttachmentStoreOp &storeOp) @@ -1179,8 +1178,8 @@ VkAttachmentStoreOp Seele::Vulkan::cast(const Gfx::SeAttachmentStoreOp &storeOp) return VK_ATTACHMENT_STORE_OP_STORE; case SE_ATTACHMENT_STORE_OP_DONT_CARE: return VK_ATTACHMENT_STORE_OP_DONT_CARE; - default: - return VK_ATTACHMENT_STORE_OP_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } Gfx::SeAttachmentStoreOp Seele::Vulkan::cast(const VkAttachmentStoreOp &storeOp) @@ -1191,8 +1190,8 @@ Gfx::SeAttachmentStoreOp Seele::Vulkan::cast(const VkAttachmentStoreOp &storeOp) return SE_ATTACHMENT_STORE_OP_STORE; case VK_ATTACHMENT_STORE_OP_DONT_CARE: return SE_ATTACHMENT_STORE_OP_DONT_CARE; - default: - return SE_ATTACHMENT_STORE_OP_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } VkAttachmentLoadOp Seele::Vulkan::cast(const Gfx::SeAttachmentLoadOp &loadOp) @@ -1205,8 +1204,8 @@ VkAttachmentLoadOp Seele::Vulkan::cast(const Gfx::SeAttachmentLoadOp &loadOp) return VK_ATTACHMENT_LOAD_OP_CLEAR; case SE_ATTACHMENT_LOAD_OP_DONT_CARE: return VK_ATTACHMENT_LOAD_OP_DONT_CARE; - default: - return VK_ATTACHMENT_LOAD_OP_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } Gfx::SeAttachmentLoadOp Seele::Vulkan::cast(const VkAttachmentLoadOp &loadOp) @@ -1219,8 +1218,8 @@ Gfx::SeAttachmentLoadOp Seele::Vulkan::cast(const VkAttachmentLoadOp &loadOp) return SE_ATTACHMENT_LOAD_OP_CLEAR; case VK_ATTACHMENT_LOAD_OP_DONT_CARE: return SE_ATTACHMENT_LOAD_OP_DONT_CARE; - default: - return SE_ATTACHMENT_LOAD_OP_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } @@ -1244,8 +1243,8 @@ Gfx::SeIndexType Seele::Vulkan::cast(const VkIndexType &indexType) return Gfx::SE_INDEX_TYPE_UINT16; case VK_INDEX_TYPE_UINT32: return Gfx::SE_INDEX_TYPE_UINT32; - default: - return Gfx::SE_INDEX_TYPE_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } @@ -1305,8 +1304,8 @@ Gfx::SePrimitiveTopology Seele::Vulkan::cast(const VkPrimitiveTopology &topology return SE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: return SE_PRIMITIVE_TOPOLOGY_PATCH_LIST; - default: - return SE_PRIMITIVE_TOPOLOGY_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } @@ -1334,8 +1333,8 @@ Gfx::SePolygonMode Seele::Vulkan::cast(const VkPolygonMode &mode) return SE_POLYGON_MODE_LINE; case VK_POLYGON_MODE_POINT: return SE_POLYGON_MODE_POINT; - default: - return SE_POLYGON_MODE_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } VkCompareOp Seele::Vulkan::cast(const Gfx::SeCompareOp &op) @@ -1358,8 +1357,8 @@ VkCompareOp Seele::Vulkan::cast(const Gfx::SeCompareOp &op) return VK_COMPARE_OP_GREATER_OR_EQUAL; case SE_COMPARE_OP_ALWAYS: return VK_COMPARE_OP_ALWAYS; - default: - return VK_COMPARE_OP_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op) @@ -1382,8 +1381,8 @@ Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op) return SE_COMPARE_OP_GREATER_OR_EQUAL; case VK_COMPARE_OP_ALWAYS: return SE_COMPARE_OP_ALWAYS; - default: - return SE_COMPARE_OP_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } @@ -1455,8 +1454,8 @@ Gfx::SeSamplerAddressMode Seele::Vulkan::cast(const VkSamplerAddressMode &mode) return SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return SE_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; - default: - return SE_SAMPLER_ADDRESS_MODE_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } VkBorderColor Seele::Vulkan::cast(const Gfx::SeBorderColor &color) @@ -1495,8 +1494,8 @@ Gfx::SeBorderColor Seele::Vulkan::cast(const VkBorderColor &color) return SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE; case VK_BORDER_COLOR_INT_OPAQUE_WHITE: return SE_BORDER_COLOR_INT_OPAQUE_WHITE; - default: - return SE_BORDER_COLOR_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } @@ -1510,8 +1509,8 @@ VkFilter Seele::Vulkan::cast(const Gfx::SeFilter &filter) return VK_FILTER_LINEAR; case SE_FILTER_CUBIC_IMG: return VK_FILTER_CUBIC_IMG; - default: - return VK_FILTER_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } Gfx::SeFilter Seele::Vulkan::cast(const VkFilter &filter) @@ -1524,8 +1523,8 @@ Gfx::SeFilter Seele::Vulkan::cast(const VkFilter &filter) return SE_FILTER_LINEAR; case VK_FILTER_CUBIC_IMG: return SE_FILTER_CUBIC_IMG; - default: - return SE_FILTER_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } @@ -1537,8 +1536,8 @@ VkSamplerMipmapMode Seele::Vulkan::cast(const Gfx::SeSamplerMipmapMode &filter) return VK_SAMPLER_MIPMAP_MODE_NEAREST; case SE_SAMPLER_MIPMAP_MODE_LINEAR: return VK_SAMPLER_MIPMAP_MODE_LINEAR; - default: - return VK_SAMPLER_MIPMAP_MODE_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } Gfx::SeSamplerMipmapMode Seele::Vulkan::cast(const VkSamplerMipmapMode &filter) @@ -1549,8 +1548,8 @@ Gfx::SeSamplerMipmapMode Seele::Vulkan::cast(const VkSamplerMipmapMode &filter) return SE_SAMPLER_MIPMAP_MODE_NEAREST; case VK_SAMPLER_MIPMAP_MODE_LINEAR: return SE_SAMPLER_MIPMAP_MODE_LINEAR; - default: - return SE_SAMPLER_MIPMAP_MODE_MAX_ENUM; + default: throw std::logic_error("Not implemented"); + } } VkAccessFlagBits Seele::Vulkan::cast(const Gfx::SeAccessFlagBits &flags) diff --git a/src/Engine/Graphics/Vulkan/PipelineCache.h b/src/Engine/Graphics/Vulkan/PipelineCache.h index 2f2b3e9..e6bbfc0 100644 --- a/src/Engine/Graphics/Vulkan/PipelineCache.h +++ b/src/Engine/Graphics/Vulkan/PipelineCache.h @@ -14,7 +14,7 @@ public: PGraphicsPipeline createPipeline(Gfx::MeshPipelineCreateInfo createInfo); PComputePipeline createPipeline(Gfx::ComputePipelineCreateInfo createInfo); private: - std::map graphicsPipelines; + Map graphicsPipelines; Map computePipelines; std::mutex cacheLock; VkPipelineCache cache; diff --git a/vcpkg.json b/vcpkg.json index d023adf..e07c93c 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -12,6 +12,8 @@ "fmt", "gtest", "vulkan-memory-allocator", - "shader-slang" + "shader-slang", + "spirv-cross", + "glslang" ] } \ No newline at end of file