Repository: jbarczak/Pyramid Branch: master Commit: 397118665161 Files: 357 Total size: 2.6 MB Directory structure: gitextract_1e9qi61g/ ├── .gitattributes ├── .gitignore ├── .gitmodules ├── Distribute.bat ├── LICENSE.txt ├── README.md ├── shims/ │ └── atidxx_shim/ │ ├── ShimDLL.cpp │ ├── ShimDLL.sln │ ├── ShimDLL.vcxproj │ └── elf.h ├── src/ │ ├── App.config │ ├── Backends/ │ │ ├── AMDDriverBackend.cs │ │ ├── AMDDriverResultsPanel.Designer.cs │ │ ├── AMDDriverResultsPanel.cs │ │ ├── AMDDriverResultsPanel.resx │ │ ├── CodeXLAnalysisPanel.Designer.cs │ │ ├── CodeXLAnalysisPanel.cs │ │ ├── CodeXLAnalysisPanel.resx │ │ ├── CodeXLBackend.cs │ │ ├── CodeXLResultsPanel.Designer.cs │ │ ├── CodeXLResultsPanel.cs │ │ ├── CodeXLResultsPanel.resx │ │ ├── FXCBackend.cs │ │ ├── FXCResultsPanel.Designer.cs │ │ ├── FXCResultsPanel.cs │ │ ├── FXCResultsPanel.resx │ │ ├── GLSLOptimizerBackend.cs │ │ ├── GLSlangBackend.cs │ │ ├── GLSlangResultsPanel.Designer.cs │ │ ├── GLSlangResultsPanel.cs │ │ ├── GLSlangResultsPanel.resx │ │ ├── IBackend.cs │ │ ├── IntelShaderAnalyzerBackend.cs │ │ ├── IntelShaderAnalyzerResultsPanel.Designer.cs │ │ ├── IntelShaderAnalyzerResultsPanel.cs │ │ ├── IntelShaderAnalyzerResultsPanel.resx │ │ ├── MaliSCBackend.cs │ │ ├── MaliSCResultsPanel.Designer.cs │ │ ├── MaliSCResultsPanel.cs │ │ ├── MaliSCResultsPanel.resx │ │ ├── PVRResultsPanel.Designer.cs │ │ ├── PVRResultsPanel.cs │ │ ├── PVRResultsPanel.resx │ │ ├── PowerVRBackend.cs │ │ └── RGABackend.cs │ ├── GLSLOptimizer.cs │ ├── GLSLTypes.cs │ ├── GLSlang.cs │ ├── HLSLTypes.cs │ ├── IAMDDriver.cs │ ├── ICSharpCode.TextEditor/ │ │ └── Project/ │ │ ├── Configuration/ │ │ │ └── AssemblyInfo.cs │ │ ├── GlobalAssemblyInfo.cs │ │ ├── ICSharpCode.TextEditor.csproj │ │ ├── Resources/ │ │ │ ├── CPP-Mode.xshd │ │ │ ├── GLSL-Mode.xshd │ │ │ ├── HLSL-Mode.xshd │ │ │ ├── ICSharpCode.TextEditor.snk │ │ │ ├── Mode.xsd │ │ │ ├── RightArrow.cur │ │ │ └── SyntaxModes.xml │ │ └── Src/ │ │ ├── Actions/ │ │ │ ├── BookmarkActions.cs │ │ │ ├── CaretActions.cs │ │ │ ├── ClipBoardActions.cs │ │ │ ├── FindReplaceAction.cs │ │ │ ├── FoldActions.cs │ │ │ ├── FormatActions.cs │ │ │ ├── HomeEndActions.cs │ │ │ ├── IEditAction.cs │ │ │ ├── MiscActions.cs │ │ │ └── SelectionActions.cs │ │ ├── Document/ │ │ │ ├── AbstractSegment.cs │ │ │ ├── BookmarkManager/ │ │ │ │ ├── Bookmark.cs │ │ │ │ ├── BookmarkEventHandler.cs │ │ │ │ ├── BookmarkManager.cs │ │ │ │ └── BookmarkManagerMemento.cs │ │ │ ├── DefaultDocument.cs │ │ │ ├── DefaultTextEditorProperties.cs │ │ │ ├── DocumentEventArgs.cs │ │ │ ├── DocumentFactory.cs │ │ │ ├── FoldingStrategy/ │ │ │ │ ├── FoldMarker.cs │ │ │ │ ├── FoldingManager.cs │ │ │ │ ├── IFoldingStrategy.cs │ │ │ │ └── IndentFoldingStrategy.cs │ │ │ ├── FormattingStrategy/ │ │ │ │ ├── DefaultFormattingStrategy.cs │ │ │ │ └── IFormattingStrategy.cs │ │ │ ├── HighlightingStrategy/ │ │ │ │ ├── DefaultHighlightingStrategy.cs │ │ │ │ ├── FontContainer.cs │ │ │ │ ├── HighlightBackground.cs │ │ │ │ ├── HighlightColor.cs │ │ │ │ ├── HighlightInfo.cs │ │ │ │ ├── HighlightRuleSet.cs │ │ │ │ ├── HighlightingColorNotFoundException.cs │ │ │ │ ├── HighlightingDefinitionInvalidException.cs │ │ │ │ ├── HighlightingDefinitionParser.cs │ │ │ │ ├── HighlightingManager.cs │ │ │ │ ├── HighlightingStrategyFactory.cs │ │ │ │ ├── IHighlightingStrategy.cs │ │ │ │ ├── NextMarker.cs │ │ │ │ ├── PrevMarker.cs │ │ │ │ ├── Span.cs │ │ │ │ ├── SpanStack.cs │ │ │ │ ├── SyntaxModes/ │ │ │ │ │ ├── FileSyntaxModeProvider.cs │ │ │ │ │ ├── ISyntaxModeFileProvider.cs │ │ │ │ │ ├── ResourceSyntaxModeProvider.cs │ │ │ │ │ └── SyntaxMode.cs │ │ │ │ └── TextWord.cs │ │ │ ├── IDocument.cs │ │ │ ├── ISegment.cs │ │ │ ├── ITextEditorProperties.cs │ │ │ ├── LineManager/ │ │ │ │ ├── DeferredEventList.cs │ │ │ │ ├── LineManager.cs │ │ │ │ ├── LineManagerEventArgs.cs │ │ │ │ ├── LineSegment.cs │ │ │ │ └── LineSegmentTree.cs │ │ │ ├── MarkerStrategy/ │ │ │ │ ├── MarkerStrategy.cs │ │ │ │ └── TextMarker.cs │ │ │ ├── Selection/ │ │ │ │ ├── ColumnRange.cs │ │ │ │ ├── DefaultSelection.cs │ │ │ │ ├── ISelection.cs │ │ │ │ └── SelectionManager.cs │ │ │ ├── TextAnchor.cs │ │ │ ├── TextBufferStrategy/ │ │ │ │ ├── GapTextBufferStrategy.cs │ │ │ │ ├── ITextBufferStrategy.cs │ │ │ │ └── StringTextBufferStrategy.cs │ │ │ ├── TextLocation.cs │ │ │ └── TextUtilities.cs │ │ ├── Gui/ │ │ │ ├── AbstractMargin.cs │ │ │ ├── BracketHighlighter.cs │ │ │ ├── BrushRegistry.cs │ │ │ ├── Caret.cs │ │ │ ├── CompletionWindow/ │ │ │ │ ├── AbstractCompletionWindow.cs │ │ │ │ ├── CodeCompletionListView.cs │ │ │ │ ├── CodeCompletionWindow.cs │ │ │ │ ├── DeclarationViewWindow.cs │ │ │ │ ├── ICompletionData.cs │ │ │ │ └── ICompletionDataProvider.cs │ │ │ ├── DrawableLine.cs │ │ │ ├── FindReplaceForm/ │ │ │ │ ├── FindAndReplaceForm.Designer.cs │ │ │ │ ├── FindAndReplaceForm.cs │ │ │ │ └── FindAndReplaceForm.resx │ │ │ ├── FoldMargin.cs │ │ │ ├── GutterMargin.cs │ │ │ ├── HRuler.cs │ │ │ ├── IconBarMargin.cs │ │ │ ├── Ime.cs │ │ │ ├── InsightWindow/ │ │ │ │ ├── IInsightDataProvider.cs │ │ │ │ └── InsightWindow.cs │ │ │ ├── TextArea.cs │ │ │ ├── TextAreaClipboardHandler.cs │ │ │ ├── TextAreaControl.cs │ │ │ ├── TextAreaDragDropHandler.cs │ │ │ ├── TextAreaMouseHandler.cs │ │ │ ├── TextAreaUpdate.cs │ │ │ ├── TextEditorControl.cs │ │ │ ├── TextEditorControlBase.cs │ │ │ ├── TextView.cs │ │ │ └── ToolTipRequestEventArgs.cs │ │ ├── Undo/ │ │ │ ├── IUndoableOperation.cs │ │ │ ├── UndoQueue.cs │ │ │ ├── UndoStack.cs │ │ │ ├── UndoableDelete.cs │ │ │ ├── UndoableInsert.cs │ │ │ └── UndoableReplace.cs │ │ └── Util/ │ │ ├── AugmentableRedBlackTree.cs │ │ ├── CheckedList.cs │ │ ├── FileReader.cs │ │ ├── LoggingService.cs │ │ ├── LookupTable.cs │ │ ├── MouseWheelHandler.cs │ │ ├── RedBlackTreeIterator.cs │ │ ├── RtfWriter.cs │ │ ├── TextUtility.cs │ │ ├── TipPainter.cs │ │ ├── TipPainterTools.cs │ │ ├── TipSection.cs │ │ ├── TipSpacer.cs │ │ ├── TipSplitter.cs │ │ ├── TipText.cs │ │ └── WeakCollection.cs │ ├── IIncludeHandler.cs │ ├── IWrapper.cs │ ├── IncludeHandler.cs │ ├── LanguageTypes.cs │ ├── Languages/ │ │ ├── GLSLLanguage.cs │ │ ├── GLSLOptionsPanel.Designer.cs │ │ ├── GLSLOptionsPanel.cs │ │ ├── GLSLOptionsPanel.resx │ │ ├── HLSLLanguage.cs │ │ ├── HLSLOptionsPanel.Designer.cs │ │ ├── HLSLOptionsPanel.cs │ │ ├── HLSLOptionsPanel.resx │ │ ├── ICompileOptionsPanel.cs │ │ └── ILanguage.cs │ ├── MainUI/ │ │ ├── AboutBox.Designer.cs │ │ ├── AboutBox.cs │ │ ├── AboutBox.resx │ │ ├── MainForm.Designer.cs │ │ ├── MainForm.cs │ │ ├── MainForm.resx │ │ ├── OptionsScreen.Designer.cs │ │ ├── OptionsScreen.cs │ │ └── OptionsScreen.resx │ ├── Options.cs │ ├── Program.cs │ ├── Properties/ │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ └── Settings.settings │ ├── Pyramid.csproj │ ├── Pyramid.sln │ ├── PyramidTypes.csproj │ ├── SPIRV.cs │ ├── Scrutinizer/ │ │ ├── Analysis/ │ │ │ └── Algorithms.cs │ │ └── UI/ │ │ ├── CFGWidget.Designer.cs │ │ ├── CFGWidget.cs │ │ ├── CFGWidget.resx │ │ ├── InstructionWidget.Designer.cs │ │ ├── InstructionWidget.cs │ │ ├── InstructionWidget.resx │ │ ├── ParameterWidget.Designer.cs │ │ ├── ParameterWidget.cs │ │ ├── ScrutinizerForm.Designer.cs │ │ ├── ScrutinizerForm.cs │ │ └── ScrutinizerForm.resx │ ├── ScrutinizerTypes.cs │ └── Wrapper/ │ ├── AMDAsic_Impl.cpp │ ├── AMDAsic_Impl.h │ ├── AMDDriver_Impl.cpp │ ├── AMDDriver_Impl.h │ ├── AMDShader_Impl.cpp │ ├── AMDShader_Impl.h │ ├── D3DCompiler_Impl.cpp │ ├── D3DCompiler_Impl.h │ ├── DXILCompiler_Impl.cpp │ ├── DXILCompiler_Impl.h │ ├── GCN1Decoder.cpp │ ├── GCN1Decoder.h │ ├── GCN3Decoder.cpp │ ├── GCN3Decoder.h │ ├── GCNBufferedPrinter.h │ ├── GCNDecoder.cpp │ ├── GCNDecoder.h │ ├── GCNDisassembler.cpp │ ├── GCNDisassembler.h │ ├── GCNEnums.cpp │ ├── GCNEnums.h │ ├── GCNIsa.cpp │ ├── GCNIsa.h │ ├── GCNSimulator.cpp │ ├── GCNSimulator.h │ ├── GLSLOpt_Impl.cpp │ ├── GLSLOpt_Impl.h │ ├── GLSlang_Impl.cpp │ ├── GLSlang_Impl.h │ ├── GLSlang_Stubs.cpp │ ├── Scrutinizer_GCN.cpp │ ├── Scrutinizer_GCN.h │ ├── Utilities.h │ ├── Wrapper.cpp │ ├── Wrapper.vcxproj │ ├── Wrapper.vcxproj.filters │ ├── amd-codexl-analyzer/ │ │ ├── Common/ │ │ │ └── Src/ │ │ │ └── DeviceInfo/ │ │ │ ├── DeviceInfo.h │ │ │ ├── DeviceInfoUtils.cpp │ │ │ └── DeviceInfoUtils.h │ │ └── CommonProjects/ │ │ └── AMDTBackend/ │ │ └── Include/ │ │ └── Common/ │ │ ├── AmdDxGsaCompile.h │ │ └── asic_reg/ │ │ ├── atiid.h │ │ ├── ci_id.h │ │ ├── cz_id.h │ │ ├── evergreen_id.h │ │ ├── kv_id.h │ │ ├── northernisland_id.h │ │ ├── si_id.h │ │ ├── sumo_id.h │ │ ├── tn_id.h │ │ └── vi_id.h │ ├── dxc/ │ │ ├── HLSL/ │ │ │ ├── DXIL.h │ │ │ ├── DxilCBuffer.h │ │ │ ├── DxilCompType.h │ │ │ ├── DxilConstants.h │ │ │ ├── DxilContainer.h │ │ │ ├── DxilGenerationPass.h │ │ │ ├── DxilInstructions.h │ │ │ ├── DxilInterpolationMode.h │ │ │ ├── DxilMetadataHelper.h │ │ │ ├── DxilModule.h │ │ │ ├── DxilOperations.h │ │ │ ├── DxilPipelineStateValidation.h │ │ │ ├── DxilResource.h │ │ │ ├── DxilResourceBase.h │ │ │ ├── DxilRootSignature.h │ │ │ ├── DxilSampler.h │ │ │ ├── DxilSemantic.h │ │ │ ├── DxilShaderModel.h │ │ │ ├── DxilSigPoint.h │ │ │ ├── DxilSignature.h │ │ │ ├── DxilSignatureAllocator.h │ │ │ ├── DxilSignatureElement.h │ │ │ ├── DxilSpanAllocator.h │ │ │ ├── DxilTypeSystem.h │ │ │ ├── DxilValidation.h │ │ │ ├── HLMatrixLowerHelper.h │ │ │ ├── HLMatrixLowerPass.h │ │ │ ├── HLModule.h │ │ │ ├── HLOperationLower.h │ │ │ ├── HLOperationLowerExtension.h │ │ │ ├── HLOperations.h │ │ │ ├── HLResource.h │ │ │ ├── HLSLExtensionsCodegenHelper.h │ │ │ └── ReducibilityAnalysis.h │ │ ├── HlslIntrinsicOp.h │ │ ├── Support/ │ │ │ ├── CMakeLists.txt │ │ │ ├── DxcLangExtensionsHelper.h │ │ │ ├── ErrorCodes.h │ │ │ ├── FileIOHelper.h │ │ │ ├── Global.h │ │ │ ├── HLSLOptions.h │ │ │ ├── HLSLOptions.td │ │ │ ├── Unicode.h │ │ │ ├── WinIncludes.h │ │ │ ├── dxcapi.impl.h │ │ │ ├── dxcapi.use.h │ │ │ ├── exception.h │ │ │ └── microcom.h │ │ ├── Tracing/ │ │ │ ├── CMakeLists.txt │ │ │ └── dxcetw.man │ │ ├── dxcapi.h │ │ ├── dxcapi.internal.h │ │ ├── dxcisense.h │ │ └── dxctools.h │ └── elf.h └── test/ ├── ShadowMaps.txt ├── branches_test ├── cs_addreturntest ├── cs_append ├── cs_barrier_test ├── cs_cull ├── cs_raster.hlsl ├── cs_raycaster ├── cs_sepgauss ├── include/ │ ├── include_d.txt │ └── include_e.txt ├── include_a.txt ├── include_b.txt ├── include_root.txt ├── manual_trilerp ├── manual_trilerp_glsl ├── matthias_bug ├── mips ├── moblur_reduc ├── ps_lighting.txt ├── ps_lighting_normalmap ├── ps_ubershader ├── trivial_test_shaders.txt ├── trivial_vs_glsl ├── vs_rigid └── vs_skinning ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ bin/* binary ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.userosscache *.sln.docstates src/.vs/* # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ build/ bld/ [Bb]in/ [Oo]bj/ # Roslyn cache directories *.ide/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* #NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opensdf *.sdf *.cachefile # Visual Studio profiler *.psess *.vsp *.vspx # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding addin-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch _NCrunch_* .*crunch*.local.xml # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # TODO: Comment the next line if you want to checkin your web deploy settings # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ # If using the old MSBuild-Integrated Package Restore, uncomment this: #!**/packages/repositories.config # Windows Azure Build Output csx/ *.build.csdef # Windows Store app package directory AppPackages/ # Others sql/ *.Cache ClientBin/ [Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview *.pfx *.publishsettings node_modules/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ # ========================= # Operating System Files # ========================= # OSX # ========================= .DS_Store .AppleDouble .LSOverride # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk # Windows # ========================= # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk ================================================ FILE: .gitmodules ================================================ [submodule "src/Wrapper/glsl-optimizer"] path = src/Wrapper/glsl-optimizer url = https://github.com/jbarczak/glsl-optimizer [submodule "src/Wrapper/GLSlang"] path = src/Wrapper/GLSlang url = https://github.com/jbarczak/GLSlang ================================================ FILE: Distribute.bat ================================================ echo off mkdir Pyramid mkdir Pyramid\bin mkdir Pyramid\src mkdir Pyramid\src\Backends mkdir Pyramid\src\Languages mkdir Pyramid\src\MainUI mkdir Pyramid\src\Properties mkdir Pyramid\src\Wrapper mkdir Pyramid\src\Wrapper\glsl-optimizer mkdir Pyramid\src\Wrapper\GLSlang cp -r bin/* Pyramid/bin cp -r LICENSE.txt Pyramid/LICENSE.txt cp -r README.txt Pyramid/README.txt cp src/*.cs Pyramid/src cp src/*.resx Pyramid/src cp src/Backends/*.cs Pyramid/src/Backends cp src/Backends/*.resx Pyramid/src/Backends cp src/Languages/*.cs Pyramid/src/Languages cp src/Languages/*.resx Pyramid/src/Languages cp src/MainUI/*.cs Pyramid/src/MainUI cp src/MainUI/*.resx Pyramid/src/MainUI cp src/App.config Pyramid/src/App.config cp src/*.csproj Pyramid/src cp src/Pyramid.sln Pyramid/src/Pyramid.sln cp -r src/Properties/* Pyramid/src/Properties cp src/Wrapper/*.cpp Pyramid/src/Wrapper cp src/Wrapper/*.h Pyramid/src/Wrapper cp src/Wrapper/Wrapper.vcxproj Pyramid/src/Wrapper cp src/Wrapper/Wrapper.vcxproj.filters Pyramid/src/Wrapper cp -r src/Wrapper/glsl-optimizer Pyramid/src/Wrapper cp src/Wrapper/GLSlang/glslang_vs2013.vcxproj Pyramid/src/Wrapper/GLSlang/glslang_vs2013.vcxproj cp -r src/Wrapper/GLSlang/glslang Pyramid/src/Wrapper/GLSlang cp -r src/Wrapper/GLSlang/OGLCompilersDLL Pyramid/src/Wrapper/GLSlang cp -r src/Wrapper/GLSlang/tools Pyramid/src/Wrapper/GLSlang ================================================ FILE: LICENSE.txt ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: README.md ================================================ # Pyramid Pyramid is a free, open GUI tool for offline shader validation and analysis. The UI takes HLSL or GLSL as input, and runs them through various shader compilers and static analyzers. Here is Pyramid, showing HLSL shader compiled and disassembled for AMD's GCN, and a GLSL shader compiled and disassembled for PowerVR 6 *(click for full-size image)*: [![AMD GCN from HLSL](doc/ui-hlsl-amddxx-thumb.png)](doc/ui-hlsl-amddxx.png?raw=1) [![PowerVR disassembly from GLSL](doc/ui-glsl-powervr-thumb.png)](doc/ui-glsl-powervr.png?raw=1) Currently, Pyramid supports these tools: * HLSL: * Microsoft D3D compiler *(d3dcompiler_47)*: for showing D3D assembly. * AMD DXX driver *(Catalyst 14.9)*, used for GCN disassembly and [shader execution simulation](http://www.joshbarczak.com/blog/?p=823). * AMD [CodeXL analyzer](http://developer.amd.com/tools-and-sdks/opencl-zone/codexl/) *(version 1.5)*. * glslang HLSL front end (2017 January build) * [DXC] (https://github.com/microsoft/DirectXShadercompiler) * [Intel Shader Analyzer](http://github.com/GameTechDev/IntelShaderAnalyzer) * GLSL: * Khronos reference [glslang](https://github.com/KhronosGroup/glslang) validator *(2017 January build)*. * Imagination [PowerVR Rogue compiler](https://community.imgtec.com/developers/powervr/tools/pvrshadereditor/) *(version 3.4)*. * ARM [Mali offline compiler](http://malideveloper.arm.com/resources/tools/mali-offline-compiler/) *(version 4.6)*. * [glsl-optimizer](https://github.com/aras-p/glsl-optimizer) *(2015 November build)*. All the above tools are included under bin/ folder for convenience. These are all publicly available binaries, but I do not own them, maintain them, and am not responsible for them. If you like you can use the Options screen to point Pyramid at different versions of the tools. Pyramid is intended to eventually support arbitrary languages and glue together tools and disassemblers from all over the graphics world. IHVs: You want developers scrutinizing the ISA for your GPUs. You know you do :) I will work with you to incorporate your disassemblers into this tool. I am willing to jump through hoops to make this happen, just tell me what I need to do. ## Obtaining Pyramid The best way to obtain a copy is to ask github to download a zip of the repository. The `bin` directory will be updated periodically with an up to date binary. Pyramid is built against .NET framework 4.5 and runs on Windows. If you don't have it, you need to go get it. Otherwise, just put the contents of `bin` wherever you like, there is no installer. Pyramid will create a configuration file under `AppData\Local\Pyramid`. At runtime, it will also create and delete temporary files in this location. Apart from that, there are no other changes made to the system. In particular, there is no registry nonsense. Pyramid is distributed as is. There is no warranty of any kind. I will not guarantee timely support, but I will be happy to accept bug fixes, patches, or contributions. [License](LICENSE.txt) is GPL. You may send constructive feedback to: jbarcz1@gmail.com ## Building it Yourself Due to my use of submodules, downloading a zip will not get you the full source. The best way to obtain the full source is to install git, open a shell, and type: git clone --recurse https://github.com/jbarczak/Pyramid This will ensure that all of the submodules are downloaded. github does not include submodules when you download a zip. I use and recommend MSysGit: https://msysgit.github.io/ Pyramid was developed using VC++ 2013 express edition (Desktop). It runs correctly on my machine (Windows 8.1 with VC++ express installed). The build products will be copied from `src/bin` into `bin` on each compile. By default, Pyramid uses relative paths to look for all of the external binaries. For debugging, it's best to point the working directory at `bin` so that they will be found. Alternatively, you can use the options menu to replace the paths with absolutes. ================================================ FILE: shims/atidxx_shim/ShimDLL.cpp ================================================ #define _CRT_SECURE_NO_DEPRECATE #include #include #include #include #include "elf.h" #include #include "d3d11tokenizedprogramformat.hpp" struct esi_struct; struct edi_struct; #define CALL __cdecl typedef DWORD (CALL *COMPILE_SHADER)( esi_struct*, edi_struct* ); typedef void (CALL *FREE_SHADER) (void*); static FILE* g_pLog = 0; static COMPILE_SHADER g_pCompileShader = 0; static FREE_SHADER g_pFreeShader = 0; static HMODULE g_hAMDDriver = 0; static CRITICAL_SECTION g_Lock; class ScopedLock { public: ScopedLock() { EnterCriticalSection(&g_Lock); } ~ScopedLock() { LeaveCriticalSection(&g_Lock); } }; void Log( const char* Format, ... ) { va_list vl; va_start(vl,Format); int n = _vscprintf( Format, vl ); char* p = (char*) malloc( n+1 ); vsprintf(p,Format,vl); printf(p); OutputDebugStringA(p); if( g_pLog ) fprintf( g_pLog, p ); free(p); va_end(vl); } enum { INVALID_ARG = 0x80070057, UNSPECIFIED_ERROR = 0x80004005, }; struct esi_struct { DWORD d0; // esi Two dwords here that get passed into a call (pointer and size)? asic info? DWORD d1; // esi+4 DWORD* pShaderBlob; // esi+8 If this is zero, return error ... pointer to D3D bytecode? DWORD nShaderBlobLengthInBytes; // esi+10h. If this is non-zero, go to (53581b4e) (jumps over the esi+14h test) void * oddball; // esi+14h. If this is non-zero, error, but only if esi+10 is also DWORD mystery0; void Print( ) { Log( "esi_struct at: 0x%08x { 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x }\n", this, d0,d1,pShaderBlob,nShaderBlobLengthInBytes, oddball, mystery0 ); } }; struct edi_struct { DWORD size; // 12 Elf32_Ehdr* pHeader; DWORD nDataSize; void Print( ) { Log("edi_struct at (0x%08x): { 0x%08x 0x%08x 0x%08x }\n", this, size, pHeader,nDataSize ); } void PrintSections( ) { char* pHeaderBytes = (char*)pHeader; Elf32_Shdr* pSections = (Elf32_Shdr*) (pHeaderBytes + pHeader->e_shoff); Elf32_Shdr* pStringTable = pSections + pHeader->e_shstrndx; char* pElfStringTable = pHeaderBytes + pStringTable->sh_offset; for( DWORD i=0; ie_shnum; i++ ) { DWORD nString = pSections[i].sh_name; char* p = pElfStringTable + pSections[i].sh_name; char* pSectionData = pHeaderBytes + pSections[i].sh_offset; Log("ELF Section: %u named: %s (%u bytes)\n", i, p, pSections[i].sh_size ); } } void PrintGoryDetails( ) { char* pHeaderBytes = (char*)pHeader; Elf32_Shdr* pSections = (Elf32_Shdr*) (pHeaderBytes + pHeader->e_shoff); Elf32_Shdr* pStringTable = pSections + pHeader->e_shstrndx; char* pElfStringTable = pHeaderBytes + pStringTable->sh_offset; for( DWORD i=0; ie_shnum; i++ ) { DWORD nString = pSections[i].sh_name; char* p = pElfStringTable + pSections[i].sh_name; char* pSectionData = pHeaderBytes + pSections[i].sh_offset; Log("ELF Section: %u named: %s (%u bytes)\n", i, p, pSections[i].sh_size ); Log("********************\n"); if( pSections[i].sh_size % 4 == 0 ) { for( DWORD k=0; kd0, esi->d1); h = g_pCompileShader(esi,edi); return h; } __declspec(dllexport) void CALL AmdDxGsaFreeCompiledShader( void* p ) { ScopedLock l; if( g_pFreeShader ) g_pFreeShader(p); } } BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved ) { switch( fdwReason ) { case DLL_PROCESS_ATTACH: { InitializeCriticalSection(&g_Lock); g_pLog = fopen("ShimLog.txt", "a" ); if( !g_pLog ) Log("Failed to open log\n"); HMODULE hAMDDriver = LoadLibrary( "real_driver.dll" ); if( !hAMDDriver ) return UNSPECIFIED_ERROR; FARPROC pCompile = GetProcAddress( hAMDDriver, "AmdDxGsaCompileShader" ); FARPROC pFree = GetProcAddress( hAMDDriver, "AmdDxGsaFreeCompiledShader" ); if( !pCompile || !pFree ) { FreeLibrary(hAMDDriver); return FALSE; } g_pCompileShader = (COMPILE_SHADER) pCompile; g_pFreeShader = (FREE_SHADER) pFree; Log("**************************************************************************\n"); Log("Pyramid driver shim has loaded\n"); Log("Command line: %s\n", GetCommandLineA() ); } break; case DLL_PROCESS_DETACH: DeleteCriticalSection( &g_Lock ); if( g_hAMDDriver ) { FreeLibrary(g_hAMDDriver); g_pFreeShader=0; g_pCompileShader=0; g_hAMDDriver=0; Log("Pyramid driver shim has unloaded\n"); } if( g_pLog ) { fclose(g_pLog); g_pLog=0; } break; } return TRUE; } ================================================ FILE: shims/atidxx_shim/ShimDLL.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Windows Desktop VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShimDLL", "ShimDLL.vcxproj", "{FCD07E16-50F2-49AF-BF11-F50A9FBAA5AC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {FCD07E16-50F2-49AF-BF11-F50A9FBAA5AC}.Debug|Win32.ActiveCfg = Debug|Win32 {FCD07E16-50F2-49AF-BF11-F50A9FBAA5AC}.Debug|Win32.Build.0 = Debug|Win32 {FCD07E16-50F2-49AF-BF11-F50A9FBAA5AC}.Release|Win32.ActiveCfg = Release|Win32 {FCD07E16-50F2-49AF-BF11-F50A9FBAA5AC}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: shims/atidxx_shim/ShimDLL.vcxproj ================================================  Debug Win32 Release Win32 {FCD07E16-50F2-49AF-BF11-F50A9FBAA5AC} ShimDLL DynamicLibrary true v120 NotSet DynamicLibrary false v120 true NotSet atidxx32 C:\Users\jbarczak\Documents\Projects\Blog\reverse_engineering_gsa\bin atidxx32 Level3 Disabled true MultiThreadedDebug true Level3 MaxSpeed true true true MultiThreaded true true true ================================================ FILE: shims/atidxx_shim/elf.h ================================================ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #ifndef _SYS_ELF_H #define _SYS_ELF_H #include /* Type for a 16-bit quantity. */ typedef uint16_t Elf32_Half; typedef uint16_t Elf64_Half; /* Types for signed and unsigned 32-bit quantities. */ typedef uint32_t Elf32_Word; typedef int32_t Elf32_Sword; typedef uint32_t Elf64_Word; typedef int32_t Elf64_Sword; /* Types for signed and unsigned 64-bit quantities. */ typedef uint64_t Elf32_Xword; typedef int64_t Elf32_Sxword; typedef uint64_t Elf64_Xword; typedef int64_t Elf64_Sxword; /* Type of addresses. */ typedef uint32_t Elf32_Addr; typedef uint64_t Elf64_Addr; /* Type of file offsets. */ typedef uint32_t Elf32_Off; typedef uint64_t Elf64_Off; #ifdef __cplusplus extern "C" { #endif #define ELF32_FSZ_ADDR 4 #define ELF32_FSZ_HALF 2 #define ELF32_FSZ_OFF 4 #define ELF32_FSZ_SWORD 4 #define ELF32_FSZ_WORD 4 #define ELF64_FSZ_ADDR 8 #define ELF64_FSZ_HALF 2 #define ELF64_FSZ_OFF 8 #define ELF64_FSZ_SWORD 4 #define ELF64_FSZ_WORD 4 #define ELF64_FSZ_SXWORD 8 #define ELF64_FSZ_XWORD 8 /* * "Enumerations" below use ...NUM as the number of * values in the list. It should be 1 greater than the * highest "real" value. */ /* * ELF header */ #define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; /* ident bytes */ Elf32_Half e_type; /* file type */ Elf32_Half e_machine; /* target machine */ Elf32_Word e_version; /* file version */ Elf32_Addr e_entry; /* start address */ Elf32_Off e_phoff; /* phdr file offset */ Elf32_Off e_shoff; /* shdr file offset */ Elf32_Word e_flags; /* file flags */ Elf32_Half e_ehsize; /* sizeof ehdr */ Elf32_Half e_phentsize; /* sizeof phdr */ Elf32_Half e_phnum; /* number phdrs */ Elf32_Half e_shentsize; /* sizeof shdr */ Elf32_Half e_shnum; /* number shdrs */ Elf32_Half e_shstrndx; /* shdr string index */ } Elf32_Ehdr; #define EI_MAG0 0 /* e_ident[] indexes */ #define EI_MAG1 1 #define EI_MAG2 2 #define EI_MAG3 3 #define EI_CLASS 4 /* File class */ #define EI_DATA 5 /* Data encoding */ #define EI_VERSION 6 /* File version */ #define EI_OSABI 7 /* Operating system/ABI identification */ #define EI_ABIVERSION 8 /* ABI version */ #define EI_PAD 9 /* Start of padding bytes */ #define ELFMAG0 0x7f /* EI_MAG */ #define ELFMAG1 'E' #define ELFMAG2 'L' #define ELFMAG3 'F' #define ELFMAG "\177ELF" #define SELFMAG 4 #define ELFCLASSNONE 0 /* EI_CLASS */ #define ELFCLASS32 1 #define ELFCLASS64 2 #define ELFCLASSNUM 3 #define ELFDATANONE 0 /* EI_DATA */ #define ELFDATA2LSB 1 #define ELFDATA2MSB 2 #define ELFDATANUM 3 #define ET_NONE 0 /* e_type */ #define ET_REL 1 #define ET_EXEC 2 #define ET_DYN 3 #define ET_CORE 4 #define ET_NUM 5 #define ET_LOOS 0xfe00 /* OS specific range */ #define ET_LOSUNW 0xfeff #define ET_SUNWPSEUDO 0xfeff #define ET_HISUNW 0xfeff #define ET_HIOS 0xfeff #define ET_LOPROC 0xff00 /* processor specific range */ #define ET_HIPROC 0xffff #define ET_LOPROC 0xff00 /* processor specific range */ #define ET_HIPROC 0xffff #define EM_NONE 0 /* e_machine */ #define EM_M32 1 /* AT&T WE 32100 */ #define EM_SPARC 2 /* Sun SPARC */ #define EM_386 3 /* Intel 80386 */ #define EM_68K 4 /* Motorola 68000 */ #define EM_88K 5 /* Motorola 88000 */ #define EM_486 6 /* Intel 80486 */ #define EM_860 7 /* Intel i860 */ #define EM_MIPS 8 /* MIPS RS3000 Big-Endian */ #define EM_S370 9 /* IBM System/370 Processor */ #define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-Endian */ #define EM_RS6000 11 /* RS6000 */ #define EM_UNKNOWN12 12 #define EM_UNKNOWN13 13 #define EM_UNKNOWN14 14 #define EM_PA_RISC 15 /* PA-RISC */ #define EM_PARISC EM_PA_RISC /* Alias: GNU compatibility */ #define EM_nCUBE 16 /* nCUBE */ #define EM_VPP500 17 /* Fujitsu VPP500 */ #define EM_SPARC32PLUS 18 /* Sun SPARC 32+ */ #define EM_960 19 /* Intel 80960 */ #define EM_PPC 20 /* PowerPC */ #define EM_PPC64 21 /* 64-bit PowerPC */ #define EM_S390 22 /* IBM System/390 Processor */ #define EM_UNKNOWN22 EM_S390 /* Alias: Older published name */ #define EM_UNKNOWN23 23 #define EM_UNKNOWN24 24 #define EM_UNKNOWN25 25 #define EM_UNKNOWN26 26 #define EM_UNKNOWN27 27 #define EM_UNKNOWN28 28 #define EM_UNKNOWN29 29 #define EM_UNKNOWN30 30 #define EM_UNKNOWN31 31 #define EM_UNKNOWN32 32 #define EM_UNKNOWN33 33 #define EM_UNKNOWN34 34 #define EM_UNKNOWN35 35 #define EM_V800 36 /* NEX V800 */ #define EM_FR20 37 /* Fujitsu FR20 */ #define EM_RH32 38 /* TRW RH-32 */ #define EM_RCE 39 /* Motorola RCE */ #define EM_ARM 40 /* Advanced RISC Marchines ARM */ #define EM_ALPHA 41 /* Digital Alpha */ #define EM_SH 42 /* Hitachi SH */ #define EM_SPARCV9 43 /* Sun SPARC V9 (64-bit) */ #define EM_TRICORE 44 /* Siemens Tricore embedded processor */ #define EM_ARC 45 /* Argonaut RISC Core, */ /* Argonaut Technologies Inc. */ #define EM_H8_300 46 /* Hitachi H8/300 */ #define EM_H8_300H 47 /* Hitachi H8/300H */ #define EM_H8S 48 /* Hitachi H8S */ #define EM_H8_500 49 /* Hitachi H8/500 */ #define EM_IA_64 50 /* Intel IA64 */ #define EM_MIPS_X 51 /* Stanford MIPS-X */ #define EM_COLDFIRE 52 /* Motorola ColdFire */ #define EM_68HC12 53 /* Motorola M68HC12 */ #define EM_MMA 54 /* Fujitsu MMA Mulimedia Accelerator */ #define EM_PCP 55 /* Siemens PCP */ #define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ #define EM_NDR1 57 /* Denso NDR1 microprocessor */ #define EM_STARCORE 58 /* Motorola Star*Core processor */ #define EM_ME16 59 /* Toyota ME16 processor */ #define EM_ST100 60 /* STMicroelectronics ST100 processor */ #define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ */ /* embedded processor family */ #define EM_AMD64 62 /* AMDs x86-64 architecture */ #define EM_X86_64 EM_AMD64 /* (compatibility) */ #define EM_PDSP 63 /* Sony DSP Processor */ #define EM_UNKNOWN64 64 #define EM_UNKNOWN65 65 #define EM_FX66 66 /* Siemens FX66 microcontroller */ #define EM_ST9PLUS 67 /* STMicroelectronics ST9+8/16 bit */ /* microcontroller */ #define EM_ST7 68 /* STMicroelectronics ST7 8-bit */ /* microcontroller */ #define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ #define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ #define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ #define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ #define EM_SVX 73 /* Silicon Graphics SVx */ #define EM_ST19 74 /* STMicroelectronics ST19 8-bit */ /* microcontroller */ #define EM_VAX 75 /* Digital VAX */ #define EM_CRIS 76 /* Axis Communications 32-bit */ /* embedded processor */ #define EM_JAVELIN 77 /* Infineon Technologies 32-bit */ /* embedded processor */ #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ #define EM_MMIX 80 /* Donald Knuth's educational */ /* 64-bit processor */ #define EM_HUANY 81 /* Harvard University */ /* machine-independent */ /* object files */ #define EM_PRISM 82 /* SiTera Prism */ #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ #define EM_FR30 84 /* Fujitsu FR30 */ #define EM_D10V 85 /* Mitsubishi D10V */ #define EM_D30V 86 /* Mitsubishi D30V */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Mitsubishi M32R */ #define EM_MN10300 89 /* Matsushita MN10300 */ #define EM_MN10200 90 /* Matsushita MN10200 */ #define EM_PJ 91 /* picoJava */ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ #define EM_XTENSA 94 /* Tensilica Xtensa architecture */ #define EM_NUM 95 #define EV_NONE 0 /* e_version, EI_VERSION */ #define EV_CURRENT 1 #define EV_NUM 2 #define ELFOSABI_NONE 0 /* No extensions or unspecified */ #define ELFOSABI_SYSV ELFOSABI_NONE #define ELFOSABI_HPUX 1 /* Hewlett-Packard HP-UX */ #define ELFOSABI_NETBSD 2 /* NetBSD */ #define ELFOSABI_LINUX 3 /* Linux */ #define ELFOSABI_UNKNOWN4 4 #define ELFOSABI_UNKNOWN5 5 #define ELFOSABI_SOLARIS 6 /* Sun Solaris */ #define ELFOSABI_AIX 7 /* AIX */ #define ELFOSABI_IRIX 8 /* IRIX */ #define ELFOSABI_FREEBSD 9 /* FreeBSD */ #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX */ #define ELFOSABI_MODESTO 11 /* Novell Modesto */ #define ELFOSABI_OPENBSD 12 /* Open BSD */ #define ELFOSABI_OPENVMS 13 /* Open VMS */ #define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ #define ELFOSABI_AROS 15 /* Amiga Research OS */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* standalone (embedded) application */ /* * Program header */ typedef struct { Elf32_Word p_type; /* entry type */ Elf32_Off p_offset; /* file offset */ Elf32_Addr p_vaddr; /* virtual address */ Elf32_Addr p_paddr; /* physical address */ Elf32_Word p_filesz; /* file size */ Elf32_Word p_memsz; /* memory size */ Elf32_Word p_flags; /* entry flags */ Elf32_Word p_align; /* memory/file alignment */ } Elf32_Phdr; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Word p_type; /* entry type */ Elf64_Word p_flags; /* entry flags */ Elf64_Off p_offset; /* file offset */ Elf64_Addr p_vaddr; /* virtual address */ Elf64_Addr p_paddr; /* physical address */ Elf64_Xword p_filesz; /* file size */ Elf64_Xword p_memsz; /* memory size */ Elf64_Xword p_align; /* memory/file alignment */ } Elf64_Phdr; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #define PT_NULL 0 /* p_type */ #define PT_LOAD 1 #define PT_DYNAMIC 2 #define PT_INTERP 3 #define PT_NOTE 4 #define PT_SHLIB 5 #define PT_PHDR 6 #define PT_TLS 7 #define PT_NUM 8 #define PT_LOOS 0x60000000 /* OS specific range */ /* * Note: The amd64 psABI defines that the UNWIND program header * should reside in the OS specific range of the program * headers. */ #define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ #define PT_GNU_EH_FRAME PT_SUNW_UNWIND #define PT_LOSUNW 0x6ffffffa #define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ #define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ #define PT_SUNWDTRACE 0x6ffffffc /* private */ #define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ #define PT_HISUNW 0x6fffffff #define PT_HIOS 0x6fffffff #define PT_LOPROC 0x70000000 /* processor specific range */ #define PT_HIPROC 0x7fffffff #define PF_R 0x4 /* p_flags */ #define PF_W 0x2 #define PF_X 0x1 #define PF_MASKOS 0x0ff00000 /* OS specific values */ #define PF_MASKPROC 0xf0000000 /* processor specific values */ #define PF_SUNW_FAILURE 0x00100000 /* mapping absent due to failure */ #define PN_XNUM 0xffff /* extended program header index */ /* * Section header */ typedef struct { Elf32_Word sh_name; /* section name */ Elf32_Word sh_type; /* SHT_... */ Elf32_Word sh_flags; /* SHF_... */ Elf32_Addr sh_addr; /* virtual address */ Elf32_Off sh_offset; /* file offset */ Elf32_Word sh_size; /* section size */ Elf32_Word sh_link; /* misc info */ Elf32_Word sh_info; /* misc info */ Elf32_Word sh_addralign; /* memory alignment */ Elf32_Word sh_entsize; /* entry size if table */ } Elf32_Shdr; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Word sh_name; /* section name */ Elf64_Word sh_type; /* SHT_... */ Elf64_Xword sh_flags; /* SHF_... */ Elf64_Addr sh_addr; /* virtual address */ Elf64_Off sh_offset; /* file offset */ Elf64_Xword sh_size; /* section size */ Elf64_Word sh_link; /* misc info */ Elf64_Word sh_info; /* misc info */ Elf64_Xword sh_addralign; /* memory alignment */ Elf64_Xword sh_entsize; /* entry size if table */ } Elf64_Shdr; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #define SHT_NULL 0 /* sh_type */ #define SHT_PROGBITS 1 #define SHT_SYMTAB 2 #define SHT_STRTAB 3 #define SHT_RELA 4 #define SHT_HASH 5 #define SHT_DYNAMIC 6 #define SHT_NOTE 7 #define SHT_NOBITS 8 #define SHT_REL 9 #define SHT_SHLIB 10 #define SHT_DYNSYM 11 #define SHT_UNKNOWN12 12 #define SHT_UNKNOWN13 13 #define SHT_INIT_ARRAY 14 #define SHT_FINI_ARRAY 15 #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 #define SHT_NUM 19 /* Solaris ABI specific values */ #define SHT_LOOS 0x60000000 /* OS specific range */ #define SHT_LOSUNW 0x6ffffff1 #define SHT_SUNW_symsort 0x6ffffff1 #define SHT_SUNW_tlssort 0x6ffffff2 #define SHT_SUNW_LDYNSYM 0x6ffffff3 #define SHT_SUNW_dof 0x6ffffff4 #define SHT_SUNW_cap 0x6ffffff5 #define SHT_SUNW_SIGNATURE 0x6ffffff6 #define SHT_SUNW_ANNOTATE 0x6ffffff7 #define SHT_SUNW_DEBUGSTR 0x6ffffff8 #define SHT_SUNW_DEBUG 0x6ffffff9 #define SHT_SUNW_move 0x6ffffffa #define SHT_SUNW_COMDAT 0x6ffffffb #define SHT_SUNW_syminfo 0x6ffffffc #define SHT_SUNW_verdef 0x6ffffffd #define SHT_SUNW_verneed 0x6ffffffe #define SHT_SUNW_versym 0x6fffffff #define SHT_HISUNW 0x6fffffff #define SHT_HIOS 0x6fffffff /* GNU/Linux ABI specific values */ #define SHT_GNU_verdef 0x6ffffffd #define SHT_GNU_verneed 0x6ffffffe #define SHT_GNU_versym 0x6fffffff #define SHT_LOPROC 0x70000000 /* processor specific range */ #define SHT_HIPROC 0x7fffffff #define SHT_LOUSER 0x80000000 #define SHT_HIUSER 0xffffffff #define SHF_WRITE 0x01 /* sh_flags */ #define SHF_ALLOC 0x02 #define SHF_EXECINSTR 0x04 #define SHF_MERGE 0x10 #define SHF_STRINGS 0x20 #define SHF_INFO_LINK 0x40 #define SHF_LINK_ORDER 0x80 #define SHF_OS_NONCONFORMING 0x100 #define SHF_GROUP 0x200 #define SHF_TLS 0x400 #define SHF_MASKOS 0x0ff00000 /* OS specific values */ #define SHF_MASKPROC 0xf0000000 /* processor specific values */ #define SHN_UNDEF 0 /* special section numbers */ #define SHN_LORESERVE 0xff00 #define SHN_LOPROC 0xff00 /* processor specific range */ #define SHN_HIPROC 0xff1f #define SHN_LOOS 0xff20 /* OS specific range */ #define SHN_LOSUNW 0xff3f #define SHN_SUNW_IGNORE 0xff3f #define SHN_HISUNW 0xff3f #define SHN_HIOS 0xff3f #define SHN_ABS 0xfff1 #define SHN_COMMON 0xfff2 #if defined(__APPLE__) #define SHN_MACHO_64 0xfffd /* Mach-o_64 direct string access */ #define SHN_MACHO 0xfffe /* Mach-o direct string access */ #endif /* __APPLE__ */ #define SHN_XINDEX 0xffff /* extended sect index */ #define SHN_HIRESERVE 0xffff /* * Symbol table */ typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; /* bind, type: ELF_32_ST_... */ unsigned char st_other; Elf32_Half st_shndx; /* SHN_... */ } Elf32_Sym; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { #if !defined(__APPLE__) Elf64_Word st_name; #else Elf64_Sxword st_name; #endif /* __APPLE__ */ unsigned char st_info; /* bind, type: ELF_64_ST_... */ unsigned char st_other; Elf64_Half st_shndx; /* SHN_... */ Elf64_Addr st_value; Elf64_Xword st_size; } Elf64_Sym; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #define STN_UNDEF 0 /* * The macros compose and decompose values for S.st_info * * bind = ELF32_ST_BIND(S.st_info) * type = ELF32_ST_TYPE(S.st_info) * S.st_info = ELF32_ST_INFO(bind, type) */ #define ELF32_ST_BIND(info) ((info) >> 4) #define ELF32_ST_TYPE(info) ((info) & 0xf) #define ELF32_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf)) #define ELF64_ST_BIND(info) ((info) >> 4) #define ELF64_ST_TYPE(info) ((info) & 0xf) #define ELF64_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf)) #define STB_LOCAL 0 /* BIND */ #define STB_GLOBAL 1 #define STB_WEAK 2 #define STB_NUM 3 #define STB_LOPROC 13 /* processor specific range */ #define STB_HIPROC 15 #define STT_NOTYPE 0 /* TYPE */ #define STT_OBJECT 1 #define STT_FUNC 2 #define STT_SECTION 3 #define STT_FILE 4 #define STT_COMMON 5 #define STT_TLS 6 #define STT_NUM 7 #define STT_LOPROC 13 /* processor specific range */ #define STT_HIPROC 15 /* * The macros decompose values for S.st_other * * visibility = ELF32_ST_VISIBILITY(S.st_other) */ #define ELF32_ST_VISIBILITY(other) ((other)&0x7) #define ELF64_ST_VISIBILITY(other) ((other)&0x7) #define STV_DEFAULT 0 #define STV_INTERNAL 1 #define STV_HIDDEN 2 #define STV_PROTECTED 3 #define STV_EXPORTED 4 #define STV_SINGLETON 5 #define STV_ELIMINATE 6 #define STV_NUM 7 /* * Relocation */ typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; /* sym, type: ELF32_R_... */ } Elf32_Rel; typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; /* sym, type: ELF32_R_... */ Elf32_Sword r_addend; } Elf32_Rela; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; /* sym, type: ELF64_R_... */ } Elf64_Rel; typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; /* sym, type: ELF64_R_... */ Elf64_Sxword r_addend; } Elf64_Rela; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ /* * The macros compose and decompose values for Rel.r_info, Rela.f_info * * sym = ELF32_R_SYM(R.r_info) * type = ELF32_R_TYPE(R.r_info) * R.r_info = ELF32_R_INFO(sym, type) */ #define ELF32_R_SYM(info) ((info)>>8) #define ELF32_R_TYPE(info) ((unsigned char)(info)) #define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type)) #define ELF64_R_SYM(info) ((info)>>32) #define ELF64_R_TYPE(info) ((Elf64_Word)(info)) #define ELF64_R_INFO(sym, type) (((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(type)) /* * The r_info field is composed of two 32-bit components: the symbol * table index and the relocation type. The relocation type for SPARC V9 * is further decomposed into an 8-bit type identifier and a 24-bit type * dependent data field. For the existing Elf32 relocation types, * that data field is zero. */ #define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) #define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) #define ELF64_R_TYPE_INFO(data, type) \ (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) /* * Section Group Flags (SHT_GROUP) */ #define GRP_COMDAT 0x01 /* * Note entry header */ typedef struct { Elf32_Word n_namesz; /* length of note's name */ Elf32_Word n_descsz; /* length of note's "desc" */ Elf32_Word n_type; /* type of note */ } Elf32_Nhdr; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Word n_namesz; /* length of note's name */ Elf64_Word n_descsz; /* length of note's "desc" */ Elf64_Word n_type; /* type of note */ } Elf64_Nhdr; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ /* * Move entry */ #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf32_Lword m_value; /* symbol value */ Elf32_Word m_info; /* size + index */ Elf32_Word m_poffset; /* symbol offset */ Elf32_Half m_repeat; /* repeat count */ Elf32_Half m_stride; /* stride info */ } Elf32_Move; /* * The macros compose and decompose values for Move.r_info * * sym = ELF32_M_SYM(M.m_info) * size = ELF32_M_SIZE(M.m_info) * M.m_info = ELF32_M_INFO(sym, size) */ #define ELF32_M_SYM(info) ((info)>>8) #define ELF32_M_SIZE(info) ((unsigned char)(info)) #define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) typedef struct { Elf64_Lword m_value; /* symbol value */ Elf64_Xword m_info; /* size + index */ Elf64_Xword m_poffset; /* symbol offset */ Elf64_Half m_repeat; /* repeat count */ Elf64_Half m_stride; /* stride info */ } Elf64_Move; #define ELF64_M_SYM(info) ((info)>>8) #define ELF64_M_SIZE(info) ((unsigned char)(info)) #define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ /* * Hardware/Software capabilities entry */ #ifndef _ASM typedef struct { Elf32_Word c_tag; /* how to interpret value */ union { Elf32_Word c_val; Elf32_Addr c_ptr; } c_un; } Elf32_Cap; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Xword c_tag; /* how to interpret value */ union { Elf64_Xword c_val; Elf64_Addr c_ptr; } c_un; } Elf64_Cap; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #endif #define CA_SUNW_NULL 0 #define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ #define CA_SUNW_SF_1 2 /* first software capabilities entry */ /* * Define software capabilities (CA_SUNW_SF_1 values). Note, hardware * capabilities (CA_SUNW_HW_1 values) are taken directly from sys/auxv_$MACH.h. */ #define SF1_SUNW_FPKNWN 0x001 /* use/non-use of frame pointer is */ #define SF1_SUNW_FPUSED 0x002 /* known, and frame pointer is */ /* in use */ #define SF1_SUNW_MASK 0x003 /* known software capabilities mask */ /* * Known values for note entry types (e_type == ET_CORE) */ #define NT_PRSTATUS 1 /* prstatus_t */ #define NT_PRFPREG 2 /* prfpregset_t */ #define NT_PRPSINFO 3 /* prpsinfo_t */ #define NT_PRXREG 4 /* prxregset_t */ #define NT_PLATFORM 5 /* string from sysinfo(SI_PLATFORM) */ #define NT_AUXV 6 /* auxv_t array */ #define NT_GWINDOWS 7 /* gwindows_t SPARC only */ #define NT_ASRS 8 /* asrset_t SPARC V9 only */ #define NT_LDT 9 /* ssd array IA32 only */ #define NT_PSTATUS 10 /* pstatus_t */ #define NT_PSINFO 13 /* psinfo_t */ #define NT_PRCRED 14 /* prcred_t */ #define NT_UTSNAME 15 /* struct utsname */ #define NT_LWPSTATUS 16 /* lwpstatus_t */ #define NT_LWPSINFO 17 /* lwpsinfo_t */ #define NT_PRPRIV 18 /* prpriv_t */ #define NT_PRPRIVINFO 19 /* priv_impl_info_t */ #define NT_CONTENT 20 /* core_content_t */ #define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */ #define NT_NUM 21 #ifdef _KERNEL /* * The following routine checks the processor-specific * fields of an ELF header. */ int elfheadcheck(unsigned char, Elf32_Half, Elf32_Word); #endif #ifdef __cplusplus } #endif #if defined(ELF_TARGET_ALL) || defined(ELF_TARGET_SPARC) #include #endif #if defined(ELF_TARGET_ALL) || defined(ELF_TARGET_386) #if !defined(__APPLE__) #include #else /* is Apple Mac OS X */ #include "elf_386.h" /* In lieu of Solaris */ #endif /* __APPLE__ */ #endif #if defined(ELF_TARGET_ALL) || defined(ELF_TARGET_AMD64) #include #endif #endif /* _SYS_ELF_H */ ================================================ FILE: src/App.config ================================================ ================================================ FILE: src/Backends/AMDDriverBackend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid { class AMDDriverResultSet : IResultSet { private AMDDriverResultsPanel m_Results; private TextBox m_Analysis = new TextBox(); public string Name { get { return "AMDDXX"; } } public Control AnalysisPanel { get { return m_Analysis; } } public Control ResultsPanel { get { return m_Results; } } public AMDDriverResultSet( IDXShaderReflection reflection ) { m_Results = new AMDDriverResultsPanel(reflection); m_Analysis.Dock = DockStyle.Fill; m_Analysis.ReadOnly = true; m_Analysis.Multiline = true; m_Analysis.Font = new System.Drawing.Font("Lucida Console", 8); m_Results.AsicChanged += delegate(IAMDShader sh) { m_Analysis.Text = sh.PrintStats(); }; } public void Add( IAMDShader sh ) { m_Results.AddResult(sh); } } class AMDDriverBackendOptions : IBackendOptions { private List m_RequestedAsics; public AMDDriverBackendOptions(List requestedAsics) { m_RequestedAsics = (requestedAsics != null) ? requestedAsics : new List(); } public List Asics { get { return m_RequestedAsics; } } } class AMDDriverBackend : IBackend { private List m_SupportedAsics = new List(); private ID3DCompiler m_FXC = null; private IAMDDriver m_Driver = null; public string Name { get { return "AMDDXX"; } } public IEnumerable Asics { get { return m_SupportedAsics; } } public AMDDriverBackend( IAMDDriver driver, ID3DCompiler fxc ) { m_FXC = fxc; m_Driver = driver; if (m_Driver != null) { foreach (IAMDAsic asic in m_Driver.Asics) { m_SupportedAsics.Add(asic.Name); } } } private bool CompileForAsic(List asics, string asic) { if (asics == null || asics.Count == 0) return true; return asics.Contains(asic); } public IResultSet Compile(IShader shaderObj, IBackendOptions options) { if ( !(shaderObj is HLSLShader ) ) return null; HLSLShader shaderHLSL = shaderObj as HLSLShader; IHLSLOptions hlslOpts = shaderHLSL.CompileOptions; AMDDriverBackendOptions backendOptions = options as AMDDriverBackendOptions; string shader = shaderObj.Code; if (shaderHLSL.WasCompiledWithErrors) return null; try { // compile here if we must. Recycle existing blob if we can IDXShaderBlob blob = shaderHLSL.CompiledBlob; if ( blob == null ) { if (!shaderHLSL.Compile(m_FXC, null)) return null; blob = shaderHLSL.CompiledBlob; } if (!(blob is IDXBCShaderBlob)) return null; IDXBCShaderBlob dxcBlob = blob as IDXBCShaderBlob; IDXShaderReflection reflect = dxcBlob.Reflect(); IDXShaderBlob exe = dxcBlob.GetExecutableBlob(); if (exe == null) return null; byte[] bytes = exe.ReadBytes(); AMDDriverResultSet rs = new AMDDriverResultSet(reflect ); foreach (IAMDAsic a in m_Driver.Asics) { if (CompileForAsic(backendOptions.Asics, a.Name)) { IAMDShader sh = m_Driver.CompileDXBlob(a, bytes, reflect); rs.Add(sh); } } return rs; } catch( System.Exception ex ) { MessageBox.Show(ex.Message); return null; } } } } ================================================ FILE: src/Backends/AMDDriverResultsPanel.Designer.cs ================================================ namespace Pyramid { partial class AMDDriverResultsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.txtISA = new System.Windows.Forms.TextBox(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.txtHex = new System.Windows.Forms.TextBox(); this.tabPage3 = new System.Windows.Forms.TabPage(); this.txtEncodings = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.cmbAsic = new System.Windows.Forms.ComboBox(); this.btnScrutinize = new System.Windows.Forms.Button(); this.tabControl1.SuspendLayout(); this.tabPage2.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage3.SuspendLayout(); this.SuspendLayout(); // // tabControl1 // this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Bottom; this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage3); this.tabControl1.Location = new System.Drawing.Point(3, 38); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(320, 185); this.tabControl1.TabIndex = 5; // // tabPage2 // this.tabPage2.Controls.Add(this.txtISA); this.tabPage2.Location = new System.Drawing.Point(4, 4); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Size = new System.Drawing.Size(312, 159); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Asm"; this.tabPage2.UseVisualStyleBackColor = true; // // txtISA // this.txtISA.Dock = System.Windows.Forms.DockStyle.Fill; this.txtISA.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtISA.Location = new System.Drawing.Point(3, 3); this.txtISA.Multiline = true; this.txtISA.Name = "txtISA"; this.txtISA.ReadOnly = true; this.txtISA.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtISA.Size = new System.Drawing.Size(306, 153); this.txtISA.TabIndex = 0; // // tabPage1 // this.tabPage1.Controls.Add(this.txtHex); this.tabPage1.Location = new System.Drawing.Point(4, 4); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); this.tabPage1.Size = new System.Drawing.Size(312, 159); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "Hex"; this.tabPage1.UseVisualStyleBackColor = true; // // txtHex // this.txtHex.Dock = System.Windows.Forms.DockStyle.Fill; this.txtHex.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtHex.Location = new System.Drawing.Point(3, 3); this.txtHex.Multiline = true; this.txtHex.Name = "txtHex"; this.txtHex.ReadOnly = true; this.txtHex.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtHex.Size = new System.Drawing.Size(306, 153); this.txtHex.TabIndex = 0; // // tabPage3 // this.tabPage3.Controls.Add(this.txtEncodings); this.tabPage3.Location = new System.Drawing.Point(4, 4); this.tabPage3.Name = "tabPage3"; this.tabPage3.Padding = new System.Windows.Forms.Padding(3); this.tabPage3.Size = new System.Drawing.Size(312, 159); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "Encodings"; this.tabPage3.UseVisualStyleBackColor = true; // // txtEncodings // this.txtEncodings.Dock = System.Windows.Forms.DockStyle.Fill; this.txtEncodings.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtEncodings.Location = new System.Drawing.Point(3, 3); this.txtEncodings.Multiline = true; this.txtEncodings.Name = "txtEncodings"; this.txtEncodings.ReadOnly = true; this.txtEncodings.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtEncodings.Size = new System.Drawing.Size(306, 153); this.txtEncodings.TabIndex = 1; // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(8, 14); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(27, 13); this.label1.TabIndex = 4; this.label1.Text = "Asic"; // // cmbAsic // this.cmbAsic.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.cmbAsic.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbAsic.FormattingEnabled = true; this.cmbAsic.Location = new System.Drawing.Point(47, 11); this.cmbAsic.Name = "cmbAsic"; this.cmbAsic.Size = new System.Drawing.Size(199, 21); this.cmbAsic.TabIndex = 3; this.cmbAsic.SelectedIndexChanged += new System.EventHandler(this.cmbAsic_SelectedIndexChanged); // // btnScrutinize // this.btnScrutinize.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnScrutinize.Location = new System.Drawing.Point(252, 7); this.btnScrutinize.Name = "btnScrutinize"; this.btnScrutinize.Size = new System.Drawing.Size(64, 27); this.btnScrutinize.TabIndex = 7; this.btnScrutinize.Text = "Scrutinize"; this.btnScrutinize.UseVisualStyleBackColor = true; this.btnScrutinize.Click += new System.EventHandler(this.btnScrutinize_Click); // // AMDDriverResultsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.btnScrutinize); this.Controls.Add(this.tabControl1); this.Controls.Add(this.label1); this.Controls.Add(this.cmbAsic); this.Name = "AMDDriverResultsPanel"; this.Size = new System.Drawing.Size(326, 235); this.tabControl1.ResumeLayout(false); this.tabPage2.ResumeLayout(false); this.tabPage2.PerformLayout(); this.tabPage1.ResumeLayout(false); this.tabPage1.PerformLayout(); this.tabPage3.ResumeLayout(false); this.tabPage3.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.TextBox txtISA; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TextBox txtHex; private System.Windows.Forms.Label label1; private System.Windows.Forms.ComboBox cmbAsic; private System.Windows.Forms.TabPage tabPage3; private System.Windows.Forms.TextBox txtEncodings; private System.Windows.Forms.Button btnScrutinize; } } ================================================ FILE: src/Backends/AMDDriverResultsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid { public partial class AMDDriverResultsPanel : UserControl { private List m_Shaders = new List(); IDXShaderReflection m_DXReflection; public delegate void AsicChangedDelegate(IAMDShader shader); public event AsicChangedDelegate AsicChanged; public AMDDriverResultsPanel( IDXShaderReflection shader ) { InitializeComponent(); m_DXReflection = shader; btnScrutinize.Enabled = (shader.GetShaderType() == HLSLShaderType.VERTEX || shader.GetShaderType() == HLSLShaderType.PIXEL || shader.GetShaderType() == HLSLShaderType.COMPUTE ); } public void AddResult(IAMDShader shader) { m_Shaders.Add(shader); cmbAsic.Items.Add(shader.Asic.Name); if (cmbAsic.Items.Count == 1) cmbAsic.SelectedIndex = 0; } private string HexDump( IAMDShader sh ) { byte[] bytes = sh.ReadISABytes(); int nBytes = bytes.Length; StringBuilder str = new StringBuilder(); if (nBytes % 4 == 0) { for (int i = 0; i < nBytes; i += 4) { int n = bytes[i] | bytes[i + 1] << 8 | bytes[i + 2] << 16 | bytes[i + 3] << 24; str.AppendFormat("{0:X8} ", n); str.AppendLine(); } } else { for (int i = 0; i < nBytes; i++) { if (i % 8 == 0) str.AppendLine(); str.AppendFormat("{0:X2} ", bytes[i]); } } str.AppendLine(); return str.ToString(); } private void cmbAsic_SelectedIndexChanged(object sender, EventArgs e) { int i = cmbAsic.SelectedIndex; if (i >= 0 && i < m_Shaders.Count) { txtHex.Text = HexDump(m_Shaders[i]); txtEncodings.Text = m_Shaders[i].ListEncodings(); txtISA.Text = m_Shaders[i].Disassemble(); } else { txtHex.Text = ""; txtISA.Text = ""; } AsicChanged(m_Shaders[i]); } private void btnScrutinize_Click(object sender, EventArgs e) { int i = cmbAsic.SelectedIndex; if (i >= 0 && i < m_Shaders.Count) { IAMDShader sh = m_Shaders[cmbAsic.SelectedIndex]; Scrutinizer.IScrutinizer backend = sh.CreateScrutinizer(); List Ops = backend.BuildProgram(); List Fetch = backend.BuildDXFetchShader(m_DXReflection); Scrutinizer.UI.ScrutinizerForm f = new Scrutinizer.UI.ScrutinizerForm(Fetch, Ops, backend); f.ShowDialog(); } } } } ================================================ FILE: src/Backends/AMDDriverResultsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 True True True True True True ================================================ FILE: src/Backends/CodeXLAnalysisPanel.Designer.cs ================================================ namespace Pyramid { partial class CodeXLAnalysisPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.listView1 = new System.Windows.Forms.ListView(); this.Key = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.Value = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.SuspendLayout(); // // listView1 // this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.Key, this.Value}); this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; this.listView1.Location = new System.Drawing.Point(0, 0); this.listView1.Name = "listView1"; this.listView1.Size = new System.Drawing.Size(316, 225); this.listView1.TabIndex = 0; this.listView1.UseCompatibleStateImageBehavior = false; this.listView1.View = System.Windows.Forms.View.Details; // // Key // this.Key.Text = "Key"; this.Key.Width = 95; // // Value // this.Value.Text = "Value"; this.Value.Width = 98; // // AMDAnalysisPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.listView1); this.Name = "AMDAnalysisPanel"; this.Size = new System.Drawing.Size(316, 225); this.ResumeLayout(false); } #endregion private System.Windows.Forms.ListView listView1; private System.Windows.Forms.ColumnHeader Key; private System.Windows.Forms.ColumnHeader Value; } } ================================================ FILE: src/Backends/CodeXLAnalysisPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid { public partial class CodeXLAnalysisPanel : UserControl { private Dictionary>> m_DataSet = new Dictionary>>(); public CodeXLAnalysisPanel() { InitializeComponent(); } public void AddResult(string asic, Dictionary vals) { List> items = new List>(); items.Add(new KeyValuePair("Asic", asic)); items.AddRange(vals); m_DataSet.Add(asic, items); if (m_DataSet.Count == 1) PopulateListView(items); } public void SetAsic(string asic) { listView1.Items.Clear(); List> items; if (m_DataSet.TryGetValue(asic, out items)) PopulateListView(items); } private void PopulateListView(List> items) { foreach (KeyValuePair p in items) { string[] arr = new string[2]; //ahoy! arr[0] = p.Key; arr[1] = p.Value; listView1.Items.Add(new ListViewItem(arr)); } } } } ================================================ FILE: src/Backends/CodeXLAnalysisPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Backends/CodeXLBackend.cs ================================================  using System.Diagnostics; using System.Collections.Generic; using System.IO; using System; using System.Windows.Forms; namespace Pyramid { class CodeXLResultSet : IResultSet { private AMDResultsPanel m_ResultsPanel ; private CodeXLAnalysisPanel m_AnalysisPanel; public CodeXLResultSet() { m_ResultsPanel = new AMDResultsPanel(); m_AnalysisPanel = new CodeXLAnalysisPanel(); m_ResultsPanel.AsicChanged += delegate(string asic) { m_AnalysisPanel.SetAsic(asic); }; } public Control ResultsPanel { get { return m_ResultsPanel; } } public Control AnalysisPanel { get { return m_AnalysisPanel; } } public string Name { get { return "CodeXL"; } } public int ResultCount { get { return m_ResultsPanel.ResultCount; } } public void AddCompileResult( string asic, string il, string isa ) { m_ResultsPanel.AddResult(asic, il, isa); } public void AddAnalysisResult( string asic, Dictionary vals ) { m_AnalysisPanel.AddResult(asic, vals); } public void DisplayAsic(string asic) { m_AnalysisPanel.SetAsic(asic); m_ResultsPanel.SetAsic(asic); } } class CodeXLBackendOptions : IBackendOptions { private List m_RequestedAsics; public CodeXLBackendOptions(List requestedAsics) { m_RequestedAsics = (requestedAsics != null) ? requestedAsics : new List(); } public List Asics { get { return m_RequestedAsics; } } } class CodeXLBackend : IBackend { private List m_SupportedAsics = new List(); private string m_CodeXL = ""; private string m_D3DCompiler = ""; private string m_TempPath = ""; public string Name { get { return "CodeXL"; } } public IEnumerable Asics { get { return m_SupportedAsics; } } public static List GetSupportedAsics( string CodeXLPath, string d3dpath ) { // try to run CodeXLAnalyzer to get the asic list // -s "HLSL" --DXLocation s -l" string CommandLine = string.Format("-s \"HLSL\" --DXLocation {0} -l", d3dpath); List asics = new List(); ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = CommandLine; pi.FileName = CodeXLPath; pi.UseShellExecute = false; try { Process p = Process.Start(pi); p.WaitForExit(); while (!p.StandardOutput.EndOfStream) { string s = p.StandardOutput.ReadLine(); asics.Add(s.TrimEnd().TrimStart()); } // skip whatever text they're emitting, up to 'Devices:' while (!asics[0].Equals("Devices:")) asics.RemoveAt(0); asics.RemoveAt(0); // remove 'Devices' p.Close(); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't get CodeXL asic list", MessageBoxButtons.OK, MessageBoxIcon.Error); } return asics; } public CodeXLBackend( string CodeXLPath, string D3DCompilerPath, string TempPath ) { m_SupportedAsics = GetSupportedAsics(CodeXLPath, D3DCompilerPath); m_CodeXL = CodeXLPath; m_D3DCompiler = D3DCompilerPath; m_TempPath = TempPath; } private bool CompileForAsic( List asics, string asic ) { if (asics == null || asics.Count == 0) return true; return asics.Contains(asic); } public IResultSet Compile(IShader shader, IBackendOptions options) { if ( !(shader is HLSLShader) || !(options is CodeXLBackendOptions) ) return null; // TODO: Modify CodeXL backend so that it re-uses blob from // FXC backend where available. It'd be nice not to have to // have CodeXL recompile it for us HLSLShader shaderHLSL = shader as HLSLShader; IHLSLOptions hlslOpts = shaderHLSL.CompileOptions; CodeXLBackendOptions backendOptions = options as CodeXLBackendOptions; string text = shader.Code; if (shaderHLSL.WasCompiledWithErrors) return null; string tmpFile = Path.Combine(m_TempPath, "PYRAMID_amdcodexl"); try { StreamWriter stream = File.CreateText(tmpFile); stream.Write(text); stream.Close(); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't create temp file", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } string isaPath = Path.Combine(m_TempPath, "pyramid.isa"); string analysisPath = Path.Combine(m_TempPath, "analysis"); string CommandLine = "-s \"HLSL\""; CommandLine = String.Concat( CommandLine, String.Format( " -p {0}",hlslOpts.Target.ToString()) ); CommandLine = String.Concat( CommandLine, String.Format( " -f {0} ",hlslOpts.EntryPoint )); CommandLine = String.Concat( CommandLine, String.Format( " --DXLocation \"{0}\"",m_D3DCompiler )); CommandLine = String.Concat( CommandLine, String.Format( " --isa \"{0}\"",isaPath )); CommandLine = String.Concat( CommandLine, String.Format( " -a \"{0}\"",analysisPath )); CommandLine = String.Concat( CommandLine, String.Format( " --DXFlags {0} ",hlslOpts.GetD3DCompileFlagBits() )); CommandLine = String.Concat(CommandLine, tmpFile); foreach (string asic in m_SupportedAsics) { if (CompileForAsic(backendOptions.Asics, asic)) { CommandLine = String.Concat(CommandLine, " -c ", asic, " "); } } ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = CommandLine; pi.FileName = m_CodeXL; pi.UseShellExecute = false; string output; try { int TimeOut = 15000; // TODO: Put in options Process p = Process.Start(pi); output = p.StandardOutput.ReadToEnd(); if (p.WaitForExit(TimeOut)) { MessageBox.Show("CodeXL took more than 15 seconds"); } p.Close(); File.Delete(tmpFile); } catch( Exception e ) { MessageBox.Show(e.Message, "uh-oh, couldn't run CodeXL", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } // Compile results are emitted in one set of files per asic string defaultAsic = ""; CodeXLResultSet results = new CodeXLResultSet(); foreach (string asic in m_SupportedAsics) { if (!CompileForAsic(backendOptions.Asics, asic)) { continue; } if (defaultAsic == "") { defaultAsic = asic; } string isaFile = Path.Combine(m_TempPath, String.Format("{0}_pyramid.isa", asic)); try { string isa = File.ReadAllText(isaFile); results.AddCompileResult(asic, "CodeXL doesn't support IL output for HLSL", isa); File.Delete(isaFile); } catch (Exception ) { // may occur in the event of a compile error. } } // Analysis results are emitted in a big CSV file try { string[] lines = File.ReadAllLines(analysisPath); File.Delete(analysisPath); try { // first line is column names string columns = lines[0]; string[] cols = columns.Split(','); // first column is asic, remaining columns are fields we want to display for (int i = 1; i < lines.Length; i++) { string[] data = lines[i].Split(','); string asic = data[0]; Dictionary vals = new Dictionary(); for (int j = 1; j < cols.Length; j++) { if( !String.IsNullOrEmpty(data[j]) && !String.IsNullOrEmpty(cols[j])) vals.Add(cols[j], data[j]); } results.AddAnalysisResult(asic, vals); } } catch( Exception e ) { MessageBox.Show(e.Message, "uh-oh. Couldn't parse CodeXL analysis file. Did it change?", MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch( Exception ) { // compile error } if (results.ResultCount > 0) { results.DisplayAsic(defaultAsic); return results; } else return null; } } } ================================================ FILE: src/Backends/CodeXLResultsPanel.Designer.cs ================================================ namespace Pyramid { partial class AMDResultsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.cmbAsic = new System.Windows.Forms.ComboBox(); this.label1 = new System.Windows.Forms.Label(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.txtISA = new System.Windows.Forms.TextBox(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.txtIL = new System.Windows.Forms.TextBox(); this.tabPage3 = new System.Windows.Forms.TabPage(); this.txtLiveReg = new System.Windows.Forms.TextBox(); this.tabPage4 = new System.Windows.Forms.TabPage(); this.txtToolOutput = new System.Windows.Forms.TextBox(); this.tabControl1.SuspendLayout(); this.tabPage2.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage3.SuspendLayout(); this.tabPage4.SuspendLayout(); this.SuspendLayout(); // // cmbAsic // this.cmbAsic.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.cmbAsic.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbAsic.FormattingEnabled = true; this.cmbAsic.Location = new System.Drawing.Point(55, 8); this.cmbAsic.Name = "cmbAsic"; this.cmbAsic.Size = new System.Drawing.Size(166, 21); this.cmbAsic.TabIndex = 0; this.cmbAsic.SelectedIndexChanged += new System.EventHandler(this.cmbAsic_SelectedIndexChanged); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(16, 11); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(27, 13); this.label1.TabIndex = 1; this.label1.Text = "Asic"; // // tabControl1 // this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Bottom; this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage3); this.tabControl1.Controls.Add(this.tabPage4); this.tabControl1.Location = new System.Drawing.Point(3, 35); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(232, 186); this.tabControl1.TabIndex = 2; // // tabPage2 // this.tabPage2.Controls.Add(this.txtISA); this.tabPage2.Location = new System.Drawing.Point(4, 4); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Size = new System.Drawing.Size(224, 160); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "ISA"; this.tabPage2.UseVisualStyleBackColor = true; // // txtISA // this.txtISA.Dock = System.Windows.Forms.DockStyle.Fill; this.txtISA.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtISA.Location = new System.Drawing.Point(3, 3); this.txtISA.Multiline = true; this.txtISA.Name = "txtISA"; this.txtISA.ReadOnly = true; this.txtISA.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtISA.Size = new System.Drawing.Size(218, 154); this.txtISA.TabIndex = 0; // // tabPage1 // this.tabPage1.Controls.Add(this.txtIL); this.tabPage1.Location = new System.Drawing.Point(4, 4); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); this.tabPage1.Size = new System.Drawing.Size(224, 160); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "IL"; this.tabPage1.UseVisualStyleBackColor = true; // // txtIL // this.txtIL.Dock = System.Windows.Forms.DockStyle.Fill; this.txtIL.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtIL.Location = new System.Drawing.Point(3, 3); this.txtIL.Multiline = true; this.txtIL.Name = "txtIL"; this.txtIL.ReadOnly = true; this.txtIL.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtIL.Size = new System.Drawing.Size(218, 154); this.txtIL.TabIndex = 0; // // tabPage3 // this.tabPage3.Controls.Add(this.txtLiveReg); this.tabPage3.Location = new System.Drawing.Point(4, 4); this.tabPage3.Name = "tabPage3"; this.tabPage3.Padding = new System.Windows.Forms.Padding(3); this.tabPage3.Size = new System.Drawing.Size(224, 160); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "LiveReg"; this.tabPage3.UseVisualStyleBackColor = true; // // txtLiveReg // this.txtLiveReg.Dock = System.Windows.Forms.DockStyle.Fill; this.txtLiveReg.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtLiveReg.Location = new System.Drawing.Point(3, 3); this.txtLiveReg.Multiline = true; this.txtLiveReg.Name = "txtLiveReg"; this.txtLiveReg.ReadOnly = true; this.txtLiveReg.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtLiveReg.Size = new System.Drawing.Size(218, 154); this.txtLiveReg.TabIndex = 1; // // tabPage4 // this.tabPage4.Controls.Add(this.txtToolOutput); this.tabPage4.Location = new System.Drawing.Point(4, 4); this.tabPage4.Name = "tabPage4"; this.tabPage4.Padding = new System.Windows.Forms.Padding(3); this.tabPage4.Size = new System.Drawing.Size(224, 160); this.tabPage4.TabIndex = 3; this.tabPage4.Text = "Output"; this.tabPage4.UseVisualStyleBackColor = true; // // txtToolOutput // this.txtToolOutput.Dock = System.Windows.Forms.DockStyle.Fill; this.txtToolOutput.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtToolOutput.Location = new System.Drawing.Point(3, 3); this.txtToolOutput.Multiline = true; this.txtToolOutput.Name = "txtToolOutput"; this.txtToolOutput.ReadOnly = true; this.txtToolOutput.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtToolOutput.Size = new System.Drawing.Size(218, 154); this.txtToolOutput.TabIndex = 2; // // AMDResultsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.tabControl1); this.Controls.Add(this.label1); this.Controls.Add(this.cmbAsic); this.Name = "AMDResultsPanel"; this.Size = new System.Drawing.Size(238, 236); this.tabControl1.ResumeLayout(false); this.tabPage2.ResumeLayout(false); this.tabPage2.PerformLayout(); this.tabPage1.ResumeLayout(false); this.tabPage1.PerformLayout(); this.tabPage3.ResumeLayout(false); this.tabPage3.PerformLayout(); this.tabPage4.ResumeLayout(false); this.tabPage4.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.ComboBox cmbAsic; private System.Windows.Forms.Label label1; private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.TextBox txtIL; private System.Windows.Forms.TextBox txtISA; private System.Windows.Forms.TabPage tabPage3; private System.Windows.Forms.TextBox txtLiveReg; private System.Windows.Forms.TabPage tabPage4; private System.Windows.Forms.TextBox txtToolOutput; } } ================================================ FILE: src/Backends/CodeXLResultsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace Pyramid { public partial class AMDResultsPanel : UserControl { private List m_IL = new List(); private List m_ISA = new List(); private List m_LiveReg = new List(); public AMDResultsPanel() { InitializeComponent(); } public int ResultCount { get { return m_IL.Count; } } public delegate void AsicChangedDelegate( string asic ); public event AsicChangedDelegate AsicChanged; public void SetToolOutput( string output ) { txtToolOutput.Text = output; } public void AddResult(string Asic, string IL, string ISA) { m_IL.Add(IL); m_ISA.Add(ISA); m_LiveReg.Add(""); cmbAsic.Items.Add(Asic); if (cmbAsic.Items.Count == 1) cmbAsic.SelectedIndex = 0; } public void AddResult(string Asic, string IL, string ISA, string LiveReg) { m_IL.Add(IL); m_ISA.Add(ISA); m_LiveReg.Add(LiveReg); cmbAsic.Items.Add(Asic); if (cmbAsic.Items.Count == 1) cmbAsic.SelectedIndex = 0; } public void SetAsic(string name) { int index = cmbAsic.Items.IndexOf(name); if (index == -1) { txtIL.Text = ""; txtISA.Text = ""; txtLiveReg.Text = ""; return; } // invokes handler below indirectly cmbAsic.SelectedIndex = index; } private void cmbAsic_SelectedIndexChanged(object sender, EventArgs e) { txtIL.Text = m_IL[cmbAsic.SelectedIndex]; txtISA.Text = m_ISA[cmbAsic.SelectedIndex]; txtLiveReg.Text = m_LiveReg[cmbAsic.SelectedIndex]; if( AsicChanged != null ) AsicChanged((string)cmbAsic.SelectedItem); } } } ================================================ FILE: src/Backends/CodeXLResultsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 True True True True ================================================ FILE: src/Backends/FXCBackend.cs ================================================ using System; using System.Collections.Generic; using System.Windows.Forms; using System.Diagnostics; using System.IO; namespace Pyramid { class FXCResultSet : IResultSet { private FXCResultsPanel m_Panel = null; public FXCResultSet(HLSLShader shader) { m_Panel = new FXCResultsPanel(shader); } public string Name { get { return "D3DCompiler"; } } public Control AnalysisPanel { get { return null; } } public Control ResultsPanel { get { return m_Panel; } } }; class D3DCompilerBackend : IBackend { private ID3DCompiler m_Compiler; private IDXILCompiler m_DXIL; public string Name { get { return "D3DCompiler"; } } public D3DCompilerBackend( ID3DCompiler comp, IDXILCompiler dxil ) { m_Compiler = comp; m_DXIL = dxil; } public IResultSet Compile(IShader shader, IBackendOptions options) { if (!(shader is HLSLShader ) ) return null; HLSLShader hlsl = (HLSLShader)shader; IHLSLOptions hlslOpts = hlsl.CompileOptions; string text = hlsl.Code; if (!hlsl.WasCompiled) hlsl.Compile(m_Compiler, m_DXIL); if (!hlsl.RootSigWasCompiled) hlsl.CompileRootSignature(m_DXIL); return new FXCResultSet(hlsl); } } } ================================================ FILE: src/Backends/FXCResultsPanel.Designer.cs ================================================ namespace Pyramid { partial class FXCResultsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.tabControl1 = new System.Windows.Forms.TabControl(); this.asmPage = new System.Windows.Forms.TabPage(); this.txtASM = new System.Windows.Forms.TextBox(); this.hexPage = new System.Windows.Forms.TabPage(); this.txtHex = new System.Windows.Forms.TextBox(); this.messagesPage = new System.Windows.Forms.TabPage(); this.txtMessages = new System.Windows.Forms.TextBox(); this.rootSigPage = new System.Windows.Forms.TabPage(); this.exportPage = new System.Windows.Forms.TabPage(); this.txtRootSig = new System.Windows.Forms.TextBox(); this.btnExportBytecode = new System.Windows.Forms.Button(); this.btnExportRootSig = new System.Windows.Forms.Button(); this.btnExportCPP = new System.Windows.Forms.Button(); this.tabControl1.SuspendLayout(); this.asmPage.SuspendLayout(); this.hexPage.SuspendLayout(); this.messagesPage.SuspendLayout(); this.rootSigPage.SuspendLayout(); this.exportPage.SuspendLayout(); this.SuspendLayout(); // // tabControl1 // this.tabControl1.Controls.Add(this.asmPage); this.tabControl1.Controls.Add(this.hexPage); this.tabControl1.Controls.Add(this.messagesPage); this.tabControl1.Controls.Add(this.rootSigPage); this.tabControl1.Controls.Add(this.exportPage); this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl1.Location = new System.Drawing.Point(0, 0); this.tabControl1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(200, 185); this.tabControl1.TabIndex = 0; // // asmPage // this.asmPage.Controls.Add(this.txtASM); this.asmPage.Location = new System.Drawing.Point(4, 25); this.asmPage.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.asmPage.Name = "asmPage"; this.asmPage.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); this.asmPage.Size = new System.Drawing.Size(192, 156); this.asmPage.TabIndex = 0; this.asmPage.Text = "ASM"; this.asmPage.UseVisualStyleBackColor = true; // // txtASM // this.txtASM.Dock = System.Windows.Forms.DockStyle.Fill; this.txtASM.Location = new System.Drawing.Point(4, 4); this.txtASM.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.txtASM.Multiline = true; this.txtASM.Name = "txtASM"; this.txtASM.ReadOnly = true; this.txtASM.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtASM.Size = new System.Drawing.Size(184, 148); this.txtASM.TabIndex = 0; // // hexPage // this.hexPage.Controls.Add(this.txtHex); this.hexPage.Location = new System.Drawing.Point(4, 25); this.hexPage.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.hexPage.Name = "hexPage"; this.hexPage.Size = new System.Drawing.Size(192, 156); this.hexPage.TabIndex = 2; this.hexPage.Text = "Hex"; this.hexPage.UseVisualStyleBackColor = true; // // txtHex // this.txtHex.Dock = System.Windows.Forms.DockStyle.Fill; this.txtHex.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.txtHex.Location = new System.Drawing.Point(0, 0); this.txtHex.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.txtHex.Multiline = true; this.txtHex.Name = "txtHex"; this.txtHex.ReadOnly = true; this.txtHex.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtHex.Size = new System.Drawing.Size(192, 156); this.txtHex.TabIndex = 3; // // messagesPage // this.messagesPage.Controls.Add(this.txtMessages); this.messagesPage.Location = new System.Drawing.Point(4, 25); this.messagesPage.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.messagesPage.Name = "messagesPage"; this.messagesPage.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); this.messagesPage.Size = new System.Drawing.Size(192, 156); this.messagesPage.TabIndex = 1; this.messagesPage.Text = "Messages"; this.messagesPage.UseVisualStyleBackColor = true; // // txtMessages // this.txtMessages.Dock = System.Windows.Forms.DockStyle.Fill; this.txtMessages.Location = new System.Drawing.Point(4, 4); this.txtMessages.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.txtMessages.Multiline = true; this.txtMessages.Name = "txtMessages"; this.txtMessages.ReadOnly = true; this.txtMessages.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtMessages.Size = new System.Drawing.Size(184, 148); this.txtMessages.TabIndex = 1; // // rootSigPage // this.rootSigPage.Controls.Add(this.txtRootSig); this.rootSigPage.Location = new System.Drawing.Point(4, 25); this.rootSigPage.Name = "rootSigPage"; this.rootSigPage.Size = new System.Drawing.Size(192, 156); this.rootSigPage.TabIndex = 3; this.rootSigPage.Text = "RootSig"; this.rootSigPage.UseVisualStyleBackColor = true; // // exportPage // this.exportPage.Controls.Add(this.btnExportCPP); this.exportPage.Controls.Add(this.btnExportRootSig); this.exportPage.Controls.Add(this.btnExportBytecode); this.exportPage.Location = new System.Drawing.Point(4, 25); this.exportPage.Name = "exportPage"; this.exportPage.Size = new System.Drawing.Size(192, 156); this.exportPage.TabIndex = 4; this.exportPage.Text = "Export"; this.exportPage.UseVisualStyleBackColor = true; // // txtRootSig // this.txtRootSig.Dock = System.Windows.Forms.DockStyle.Fill; this.txtRootSig.Font = new System.Drawing.Font("Consolas", 8.5F); this.txtRootSig.Location = new System.Drawing.Point(0, 0); this.txtRootSig.Margin = new System.Windows.Forms.Padding(4); this.txtRootSig.Multiline = true; this.txtRootSig.Name = "txtRootSig"; this.txtRootSig.ReadOnly = true; this.txtRootSig.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtRootSig.Size = new System.Drawing.Size(192, 156); this.txtRootSig.TabIndex = 2; // // btnExportBytecode // this.btnExportBytecode.Location = new System.Drawing.Point(12, 18); this.btnExportBytecode.Name = "btnExportBytecode"; this.btnExportBytecode.Size = new System.Drawing.Size(134, 35); this.btnExportBytecode.TabIndex = 0; this.btnExportBytecode.Text = "Save Bytecode"; this.btnExportBytecode.UseVisualStyleBackColor = true; this.btnExportBytecode.Click += new System.EventHandler(this.btnExportBytecode_Click); // // btnExportRootSig // this.btnExportRootSig.Location = new System.Drawing.Point(12, 59); this.btnExportRootSig.Name = "btnExportRootSig"; this.btnExportRootSig.Size = new System.Drawing.Size(134, 35); this.btnExportRootSig.TabIndex = 1; this.btnExportRootSig.Text = "Save RootSig"; this.btnExportRootSig.UseVisualStyleBackColor = true; this.btnExportRootSig.Click += new System.EventHandler(this.btnExportRootSig_Click); // // btnExportCPP // this.btnExportCPP.Location = new System.Drawing.Point(12, 100); this.btnExportCPP.Name = "btnExportCPP"; this.btnExportCPP.Size = new System.Drawing.Size(134, 35); this.btnExportCPP.TabIndex = 2; this.btnExportCPP.Text = "Create .cpp File"; this.btnExportCPP.UseVisualStyleBackColor = true; this.btnExportCPP.Click += new System.EventHandler(this.btnExportCPP_Click); // // FXCResultsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.tabControl1); this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "FXCResultsPanel"; this.Size = new System.Drawing.Size(200, 185); this.tabControl1.ResumeLayout(false); this.asmPage.ResumeLayout(false); this.asmPage.PerformLayout(); this.hexPage.ResumeLayout(false); this.hexPage.PerformLayout(); this.messagesPage.ResumeLayout(false); this.messagesPage.PerformLayout(); this.rootSigPage.ResumeLayout(false); this.rootSigPage.PerformLayout(); this.exportPage.ResumeLayout(false); this.ResumeLayout(false); } #endregion private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage messagesPage; private System.Windows.Forms.TextBox txtASM; private System.Windows.Forms.TextBox txtMessages; private System.Windows.Forms.TabPage hexPage; private System.Windows.Forms.TextBox txtHex; private System.Windows.Forms.TabPage asmPage; private System.Windows.Forms.TabPage rootSigPage; private System.Windows.Forms.TextBox txtRootSig; private System.Windows.Forms.TabPage exportPage; private System.Windows.Forms.Button btnExportCPP; private System.Windows.Forms.Button btnExportRootSig; private System.Windows.Forms.Button btnExportBytecode; } } ================================================ FILE: src/Backends/FXCResultsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace Pyramid { public partial class FXCResultsPanel : UserControl { private IDXShaderBlob m_Shader; private IDXBlob m_RootSignature; private static void HexBumpBlob( StringBuilder str, byte[] bytes ) { int nBytes = bytes.Length; if (nBytes % 4 == 0) { for (int i = 0; i < nBytes; i += 4) { int n = bytes[i] | bytes[i + 1] << 8 | bytes[i + 2] << 16 | bytes[i + 3] << 24; char c0 = Convert.ToChar(bytes[i]); char c1 = Convert.ToChar(bytes[i+1]); char c2 = Convert.ToChar(bytes[i+2]); char c3 = Convert.ToChar(bytes[i+3]); c0 = (c0 < 0x20 || c0 > 127) ? '.' : c0; c1 = (c1 < 0x20 || c1 > 127) ? '.' : c1; c2 = (c2 < 0x20 || c2 > 127) ? '.' : c2; c3 = (c3 < 0x20 || c3 > 127) ? '.' : c3; str.AppendFormat("{0:X8} '{1} {2} {3} {4}' ", n, c0,c1,c2,c3 ); str.AppendLine(); } } else { for( int i=0; i= nBytes) break; str.AppendFormat("{0,-3}, ", bytes[i + j]); } str.AppendLine(); } str.Append("};"); str.AppendLine(); } private void btnExportCPP_Click(object sender, EventArgs e) { SaveFileDialog save = new SaveFileDialog(); if (save.ShowDialog() != DialogResult.Cancel) { StringBuilder str = new StringBuilder(); if ( m_Shader != null ) { str.Append("#if 0"); str.AppendLine(); str.Append(m_Shader.Disassemble()); str.AppendLine(); str.Append("#endif"); str.AppendLine(); byte[] byteCode = m_Shader.ReadBytes(); DeclareByteArray(str, byteCode, "Bytecode"); } if( m_RootSignature != null ) { byte[] byteCode = m_RootSignature.ReadBytes(); DeclareByteArray(str, byteCode, "RootSig"); } File.WriteAllText(save.FileName, str.ToString()); } } } } ================================================ FILE: src/Backends/FXCResultsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Backends/GLSLOptimizerBackend.cs ================================================ using System; using System.Collections.Generic; using System.Windows.Forms; namespace Pyramid { class GLSLOptimizerResultSet : IResultSet { private TextBox m_AnalysisPanel = new TextBox(); private TabControl m_ResultsPanel = new TabControl(); public GLSLOptimizerResultSet(GLSLOptimizer.IShader shader) { m_ResultsPanel.Dock = DockStyle.Fill; TabPage page; string AnalysisText=""; if( !shader.HadError ) { AnalysisText = String.Format("GLSLOptimizer stats:\r\nMathOps:\t{0}\r\nTextureOps:\t{1}\r\nFlowOps:\t{2}\r\n", shader.MathOps, shader.TextureOps, shader.ControlFlowOps); m_ResultsPanel.TabPages.Add("Optimized Output"); page = m_ResultsPanel.TabPages[m_ResultsPanel.TabPages.Count - 1]; TextBox txtOutput = new TextBox(); txtOutput.ReadOnly = true; txtOutput.Dock = DockStyle.Fill; txtOutput.Multiline = true; txtOutput.ScrollBars = ScrollBars.Both; txtOutput.Text = shader.Output.Replace("\n", Environment.NewLine) ; txtOutput.WordWrap = false; page.Controls.Add(txtOutput); m_ResultsPanel.TabPages.Add("Raw Output"); page = m_ResultsPanel.TabPages[m_ResultsPanel.TabPages.Count - 1]; TextBox txtRawOutput = new TextBox(); txtRawOutput.ReadOnly = true; txtRawOutput.Dock = DockStyle.Fill; txtRawOutput.Multiline = true; txtRawOutput.ScrollBars = ScrollBars.Both; txtRawOutput.Text = shader.RawOutput.Replace("\n",Environment.NewLine); txtRawOutput.WordWrap = false; page.Controls.Add(txtRawOutput); } m_ResultsPanel.TabPages.Add("Log"); page = m_ResultsPanel.TabPages[m_ResultsPanel.TabPages.Count - 1]; TextBox txtLog = new TextBox(); txtLog.ReadOnly = true; txtLog.Dock = DockStyle.Fill; txtLog.Multiline = true; txtLog.ScrollBars = ScrollBars.Both; txtLog.WordWrap = false; txtLog.Text = shader.Log.Replace("\n", Environment.NewLine); page.Controls.Add(txtLog); m_AnalysisPanel.ReadOnly = true; m_AnalysisPanel.Dock = DockStyle.Fill; m_AnalysisPanel.Text = AnalysisText; m_AnalysisPanel.Multiline = true; m_AnalysisPanel.Font = new System.Drawing.Font("Lucida Console", 8); } public string Name { get { return "GLSLOptimizer"; } } public Control AnalysisPanel { get { return m_AnalysisPanel; } } public Control ResultsPanel { get { return m_ResultsPanel; } } }; class GLSLOptimizerBackend : IBackend { private Dictionary m_Optimizers = new Dictionary(); public string Name { get { return "GLSLOptimizer"; } } public GLSLOptimizerBackend(IWrapper wrapper) { foreach( GLSLOptimizer.Target t in Enum.GetValues(typeof(GLSLOptimizer.Target))) m_Optimizers.Add( t, wrapper.CreateGLSLOptimizer(t)); } public IResultSet Compile(IShader shader, IBackendOptions options) { if ( !(shader is GLSLShader ) ) return null; GLSLShader sh = (GLSLShader)shader; IGLSLOptions glOpts = sh.CompileOptions; if (glOpts.OptimizerOptions == null) return null; GLSLOptimizer.IOptimizer optimizer = m_Optimizers[glOpts.OptimizerTarget]; return new GLSLOptimizerResultSet( optimizer.Optimize(sh.Code, glOpts.OptimizerOptions) ); } } } ================================================ FILE: src/Backends/GLSlangBackend.cs ================================================ using System; using System.Collections.Generic; using System.Windows.Forms; namespace Pyramid { class GLSlangBackend : IBackend { private GLSlang.ICompiler m_Compiler; private GLSlang.IConfig m_Config; private class GLSLangResultSet : IResultSet { private GLSlangResultsPanel m_Results = null; public string Name { get { return "GLSlang"; } } public Control AnalysisPanel { get { return null; } } public Control ResultsPanel { get { return m_Results; } } public GLSLangResultSet(GLSlang.IShader shader) { m_Results = new GLSlangResultsPanel(shader, shader.CompileSPIRV()); } } public string Name { get { return "GLSlang"; } } public GLSlangBackend( IWrapper wrapper, IIncludeHandler handler ) { m_Compiler = wrapper.CreateGLSlangCompiler(handler); m_Config = m_Compiler.CreateDefaultConfig(); } public IResultSet Compile(IShader shader, IBackendOptions options) { if (shader is GLSLShader) { GLSLShader sh = (GLSLShader)shader; IGLSLOptions glOpts = sh.CompileOptions; GLSlang.IShader result = m_Compiler.Compile(sh.Code, glOpts.ShaderType, m_Config, shader.SourceFilePath ); return new GLSLangResultSet(result); } else if( shader is HLSLShader ) { HLSLShader sh = (HLSLShader)shader; IHLSLOptions hlslOpts = sh.CompileOptions; GLSlang.IShader result = m_Compiler.CompileHLSL(sh.Code, hlslOpts, m_Config, shader.SourceFilePath ); return new GLSLangResultSet(result); } else { return null; } } } } ================================================ FILE: src/Backends/GLSlangResultsPanel.Designer.cs ================================================ namespace Pyramid { partial class GLSlangResultsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.textBox1 = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // textBox1 // this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox1.Location = new System.Drawing.Point(3, 2); this.textBox1.Multiline = true; this.textBox1.Name = "textBox1"; this.textBox1.ReadOnly = true; this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.textBox1.Size = new System.Drawing.Size(206, 152); this.textBox1.TabIndex = 0; this.textBox1.WordWrap = false; // // button1 // this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.button1.Location = new System.Drawing.Point(141, 158); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(66, 21); this.button1.TabIndex = 1; this.button1.Text = "Export"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // GLSlangResultsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.button1); this.Controls.Add(this.textBox1); this.Name = "GLSlangResultsPanel"; this.Size = new System.Drawing.Size(212, 183); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Button button1; } } ================================================ FILE: src/Backends/GLSlangResultsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid { public partial class GLSlangResultsPanel : UserControl { private GLSlang.IShader m_Shader; private SPIRV.IProgram m_SPIRV; public GLSlangResultsPanel(GLSlang.IShader shader, SPIRV.IProgram spirv) { InitializeComponent(); m_Shader = shader; m_SPIRV = spirv; if (spirv != null) { textBox1.Text = spirv.Disassemble(); button1.Enabled = true; } else { textBox1.Text = shader.InfoLog.Replace("\n", Environment.NewLine); button1.Enabled = false; } } private void button1_Click(object sender, EventArgs e) { SaveFileDialog sd = new SaveFileDialog(); sd.Title = "Export SPIRV Binary"; if( sd.ShowDialog() != DialogResult.Cancel ) { try { System.IO.File.WriteAllBytes(sd.FileName, m_SPIRV.GetBytes()); } catch (System.Exception ex) { MessageBox.Show(ex.Message); } } } } } ================================================ FILE: src/Backends/GLSlangResultsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Backends/IBackend.cs ================================================ using System; using System.Collections.Generic; using System.Windows.Forms; namespace Pyramid { public interface IResultSet { string Name { get; } Control AnalysisPanel { get; } Control ResultsPanel { get; } } public interface IBackendOptions { } public interface IBackend { string Name { get; } IResultSet Compile(IShader shader, IBackendOptions options); } } ================================================ FILE: src/Backends/IntelShaderAnalyzerBackend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Windows.Forms; using System.Diagnostics; namespace Pyramid { class IntelShaderAnalyzerResultSet : IResultSet { public string Name { get { return "IntelShaderAnalyzer"; } } public Control AnalysisPanel { get { return m_Analysis; } } public Control ResultsPanel { get { return m_Results; } } private TextBox m_Analysis = new TextBox(); private IntelShaderAnalyzerResultsPanel m_Results = null; public IntelShaderAnalyzerResultSet(IntelShaderAnalyzerResultsPanel panel ) { m_Results = panel; m_Analysis.Dock = DockStyle.Fill; m_Analysis.ReadOnly = true; m_Analysis.Multiline = true; m_Analysis.Font = new System.Drawing.Font("Lucida Console", 8); } } public class IntelShaderAnalyzerBackend : IBackend { private string m_ToolPath; private string m_TempPath; public IntelShaderAnalyzerBackend(Options PyramidOpts) { m_ToolPath = PyramidOpts.IntelShaderAnalyzerPath; m_TempPath = PyramidOpts.TempPath; } public string Name { get { return "IGC"; } } public List GetAsicList() { try { ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = false; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = "--list-asics"; pi.FileName = m_ToolPath; pi.UseShellExecute = false; Process p = Process.Start(pi); int pid = p.Id; // NOTE: Must read stdout before waiting for exit // If we don't, then the process will hang if some stdout buffer fills up // lame.... string stdout = p.StandardOutput.ReadToEnd(); p.WaitForExit(); p.Close(); string[] lines = stdout.Split( new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None ); List asics = new List(); foreach( string s in lines ) { string asic = s.Trim(); if (!string.IsNullOrEmpty(asic)) asics.Add(asic); } return asics; } catch( System.Exception ex ) { MessageBox.Show("Failed to get asic list from IntelShaderAnalyzer"); return new List(); } } public IResultSet Compile(IShader shader, IBackendOptions options) { if (shader.Language == Languages.HLSL) return CompileHLSL(shader as HLSLShader, options); else return null; } private IResultSet CompileHLSL(HLSLShader shader, IBackendOptions opts) { if (shader.CompiledBlob == null) return null; if (shader.CompiledBlob is IDXILShaderBlob && shader.CompiledRootSig == null) return null; try { List tempFilesToDelete = new List(); string byteCodeFile = Path.Combine(m_TempPath, "IGCShader"); string rootSigFile = Path.Combine(m_TempPath, "IGCRS"); File.WriteAllBytes( byteCodeFile, shader.CompiledBlob.ReadBytes() ); tempFilesToDelete.Add(byteCodeFile); if( shader.CompiledRootSig != null ) { File.WriteAllBytes(rootSigFile, shader.CompiledRootSig.ReadBytes()); tempFilesToDelete.Add(rootSigFile); } string commandline11 = ""; string commandline12 = ""; if (shader.CompiledBlob is IDXBCShaderBlob) { commandline11 = String.Format("--api dx11 \"{0}\"", byteCodeFile); commandline12 = String.Format("--api dx12 \"{0}\" --rootsig_file \"{1}\"", byteCodeFile, rootSigFile); } else { commandline12 = String.Format("--api dx12 \"{0}\" --rootsig_file \"{1}\"", byteCodeFile, rootSigFile); } List asics = GetAsicList(); foreach (string asic in asics) { commandline11 = String.Concat(commandline11, String.Format(" --asic {0} ", asic)); commandline12 = String.Concat(commandline12, String.Format(" --asic {0} ", asic)); } string isaDir11 = Path.Combine(m_TempPath, "IntelISA_11\\"); string isaDir12 = Path.Combine(m_TempPath, "IntelISA_12\\"); Directory.CreateDirectory(isaDir11); Directory.CreateDirectory(isaDir12); // NOTE: Extra \ is required because DOS command interpretter parses \" as a double quote commandline11 = String.Concat(commandline11, String.Format("--isa \"{0}\\\"", isaDir11)); commandline12 = String.Concat(commandline12, String.Format("--isa \"{0}\\\"", isaDir12)); string stdout = ""; List dx11Files = new List(); List dx12Files = new List(); // DX11 requires DXBC if( shader.CompiledBlob is IDXBCShaderBlob) { ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = false; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = commandline11; pi.FileName = m_ToolPath; pi.UseShellExecute = false; Process p = Process.Start(pi); int pid = p.Id; // NOTE: Must read stdout before waiting for exit // If we don't, then the process will hang if some stdout buffer fills up // lame.... stdout = String.Concat("DX11 COMMAND LINE:", commandline11, Environment.NewLine); stdout = String.Concat(stdout, p.StandardOutput.ReadToEnd()); p.WaitForExit(); p.Close(); foreach (string asic in asics) dx11Files.Add(String.Concat(isaDir11, asic, ".asm")); } // DX12 requires a root signature if( shader.CompiledRootSig != null ) { ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = false; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = commandline12; pi.FileName = m_ToolPath; pi.UseShellExecute = false; Process p = Process.Start(pi); int pid = p.Id; // NOTE: Must read stdout before waiting for exit // If we don't, then the process will hang if some stdout buffer fills up // lame.... stdout = String.Concat(stdout, string.Concat("DX12 COMMAND LINE: ", commandline12, Environment.NewLine)); stdout = String.Concat(stdout, Environment.NewLine); stdout = String.Concat(stdout, p.StandardOutput.ReadToEnd()); p.WaitForExit(); p.Close(); foreach (string asic in asics) dx12Files.Add(String.Concat(isaDir12, asic, ".asm")); } tempFilesToDelete.AddRange(dx11Files); tempFilesToDelete.AddRange(dx12Files); IntelShaderAnalyzerResultsPanel panel = new IntelShaderAnalyzerResultsPanel(stdout,asics); panel.AddResults("DX11", dx11Files); panel.AddResults("DX12", dx12Files); // cleanup the temp files foreach (string file in tempFilesToDelete) File.Delete(file); Directory.Delete(Path.Combine(m_TempPath, "IntelISA_11")); Directory.Delete(Path.Combine(m_TempPath, "IntelISA_12")); return new IntelShaderAnalyzerResultSet(panel); } catch (Exception ex) { MessageBox.Show(ex.Message, "uh-oh, Couldn't run IntelShaderAnalyzer", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } } }; } ================================================ FILE: src/Backends/IntelShaderAnalyzerResultsPanel.Designer.cs ================================================ namespace Pyramid { partial class IntelShaderAnalyzerResultsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.cmbOutputFile = new System.Windows.Forms.ComboBox(); this.cmbAPI = new System.Windows.Forms.ComboBox(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.txtAsm = new System.Windows.Forms.TextBox(); this.txtMessages = new System.Windows.Forms.TextBox(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage2.SuspendLayout(); this.SuspendLayout(); // // cmbOutputFile // this.cmbOutputFile.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbOutputFile.FormattingEnabled = true; this.cmbOutputFile.Location = new System.Drawing.Point(161, 19); this.cmbOutputFile.Margin = new System.Windows.Forms.Padding(4); this.cmbOutputFile.Name = "cmbOutputFile"; this.cmbOutputFile.Size = new System.Drawing.Size(250, 24); this.cmbOutputFile.TabIndex = 5; this.cmbOutputFile.SelectedIndexChanged += new System.EventHandler(this.cmbOutputFile_SelectedIndexChanged); // // cmbAPI // this.cmbAPI.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbAPI.FormattingEnabled = true; this.cmbAPI.Location = new System.Drawing.Point(35, 19); this.cmbAPI.Margin = new System.Windows.Forms.Padding(4); this.cmbAPI.Name = "cmbAPI"; this.cmbAPI.Size = new System.Drawing.Size(104, 24); this.cmbAPI.TabIndex = 6; this.cmbAPI.SelectedIndexChanged += new System.EventHandler(this.cmbAPI_SelectedIndexChanged); // // tabControl1 // this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Location = new System.Drawing.Point(3, 50); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(620, 409); this.tabControl1.TabIndex = 7; // // tabPage1 // this.tabPage1.Controls.Add(this.txtAsm); this.tabPage1.Location = new System.Drawing.Point(4, 25); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); this.tabPage1.Size = new System.Drawing.Size(612, 380); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "Asm"; this.tabPage1.UseVisualStyleBackColor = true; this.tabPage1.Click += new System.EventHandler(this.tabPage1_Click); // // tabPage2 // this.tabPage2.Controls.Add(this.txtMessages); this.tabPage2.Location = new System.Drawing.Point(4, 25); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Size = new System.Drawing.Size(612, 380); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Messages"; this.tabPage2.UseVisualStyleBackColor = true; // // txtAsm // this.txtAsm.Dock = System.Windows.Forms.DockStyle.Fill; this.txtAsm.Font = new System.Drawing.Font("Consolas", 9F); this.txtAsm.Location = new System.Drawing.Point(3, 3); this.txtAsm.Margin = new System.Windows.Forms.Padding(4); this.txtAsm.Multiline = true; this.txtAsm.Name = "txtAsm"; this.txtAsm.ReadOnly = true; this.txtAsm.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtAsm.Size = new System.Drawing.Size(606, 374); this.txtAsm.TabIndex = 5; this.txtAsm.WordWrap = false; // // txtMessages // this.txtMessages.Dock = System.Windows.Forms.DockStyle.Fill; this.txtMessages.Font = new System.Drawing.Font("Consolas", 9F); this.txtMessages.Location = new System.Drawing.Point(3, 3); this.txtMessages.Margin = new System.Windows.Forms.Padding(4); this.txtMessages.Multiline = true; this.txtMessages.Name = "txtMessages"; this.txtMessages.ReadOnly = true; this.txtMessages.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtMessages.Size = new System.Drawing.Size(606, 374); this.txtMessages.TabIndex = 6; // // IntelShaderAnalyzerResultsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.tabControl1); this.Controls.Add(this.cmbAPI); this.Controls.Add(this.cmbOutputFile); this.Name = "IntelShaderAnalyzerResultsPanel"; this.Size = new System.Drawing.Size(623, 462); this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); this.tabPage1.PerformLayout(); this.tabPage2.ResumeLayout(false); this.tabPage2.PerformLayout(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.ComboBox cmbOutputFile; private System.Windows.Forms.ComboBox cmbAPI; private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.TextBox txtAsm; private System.Windows.Forms.TextBox txtMessages; } } ================================================ FILE: src/Backends/IntelShaderAnalyzerResultsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace Pyramid { public partial class IntelShaderAnalyzerResultsPanel : UserControl { public IntelShaderAnalyzerResultsPanel( string stdout, List asics ) { InitializeComponent(); txtMessages.Text = stdout; tabPage1.Visible = false; foreach( string asic in asics ) cmbOutputFile.Items.Add(asic); cmbOutputFile.SelectedIndex = 0; } private Dictionary > m_APISets = new Dictionary>(); public void AddResults( string api, List files ) { if (files.Count == 0) return; Dictionary asicFiles = new Dictionary(); foreach( string path in files ) { string asic = Path.GetFileNameWithoutExtension(path); if (File.Exists(path)) { string asm = File.ReadAllText(path); asicFiles.Add(asic, asm); } } m_APISets.Add(api, asicFiles); cmbAPI.Items.Add(api); cmbAPI.SelectedIndex = 0; RefreshAsm(); } private void RefreshAsm() { txtAsm.Text = ""; if( cmbAPI.SelectedItem != null && cmbOutputFile.SelectedItem != null ) { Dictionary Files; if (m_APISets.TryGetValue((string)cmbAPI.SelectedItem, out Files)) { string text; if (Files.TryGetValue((string)cmbOutputFile.SelectedItem, out text)) { txtAsm.Text = text; } } } } private void tabPage1_Click(object sender, EventArgs e) { } private void cmbAPI_SelectedIndexChanged(object sender, EventArgs e) { RefreshAsm(); } private void cmbOutputFile_SelectedIndexChanged(object sender, EventArgs e) { RefreshAsm(); } } } ================================================ FILE: src/Backends/IntelShaderAnalyzerResultsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Backends/MaliSCBackend.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Diagnostics; using System.Windows.Forms; using System.Text.RegularExpressions; namespace Pyramid { public class MaliSCResultSet : IResultSet { public string Name { get { return "MaliSC"; } } public Control AnalysisPanel { get; private set; } public Control ResultsPanel { get; private set; } public MaliSCResultSet() { AnalysisPanel = null; ResultsPanel = new MaliSCResultsPanel(); } public void Add(string core, string output) { MaliSCResultsPanel rp = ResultsPanel as MaliSCResultsPanel; rp.AddResult(core, output); } } public class MaliSCBackend : IBackend { private string m_MaliRoot = ""; private string m_TempPath = ""; private List m_Asics = new List(); public MaliSCBackend(string MaliRoot, string TempPath) { m_MaliRoot = MaliRoot; m_TempPath = TempPath; // get asic list string CommandLine = string.Format("--help"); ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = true; pi.EnvironmentVariables.Add("MALICM_LOCATION", m_MaliRoot); pi.CreateNoWindow = true; pi.Arguments = CommandLine; pi.FileName = Path.Combine(MaliRoot, "malisc.exe"); pi.UseShellExecute = false; try { Process p = Process.Start(pi); p.WaitForExit(); // malisc frontend prints a giant help-text string. // amidst the noise, we'll find a list of supported cores // // We'll let them use defaults for driver revision and HW revision // because permuting over all that stuff is probably fruitless // string output = p.StandardOutput.ReadToEnd(); int idx = output.IndexOf("[-c <"); string trimmed = output.Substring(output.IndexOf("[-c")); trimmed = trimmed.Substring(0, trimmed.IndexOf("]")); trimmed = trimmed.Substring(trimmed.IndexOf("<")); trimmed = trimmed.Substring(0, trimmed.IndexOf(">")); trimmed = trimmed.Substring(1); string[] asics = trimmed.Split('|'); foreach (string s in asics) m_Asics.Add(s.Trim()); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't get MaliSC asic list", MessageBoxButtons.OK, MessageBoxIcon.Error); } } public string Name { get { return "MaliSC"; } } public IResultSet Compile(IShader sh, IBackendOptions options) { if (sh.Language != Languages.GLSL) return null; GLSLShader glShader = (GLSLShader)sh; IGLSLOptions glOpts = glShader.CompileOptions; string shader = glShader.Code; string shaderType = ""; switch( glOpts.ShaderType ) { case GLSLShaderType.VERTEX: shaderType = "--vertex"; break; case GLSLShaderType.FRAGMENT: shaderType = "--fragment"; break; case GLSLShaderType.COMPUTE: shaderType = "--compute"; break; default: return null; } string tmpFile = Path.Combine(m_TempPath, "PYRAMID_mali"); try { StreamWriter stream = File.CreateText(tmpFile); stream.Write(shader); stream.Close(); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't create temp file", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } MaliSCResultSet rs = new MaliSCResultSet(); try { foreach (string asic in m_Asics) { string commandline = String.Format("-V {0} -c {1} {2}", shaderType, asic, tmpFile); ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = true; pi.EnvironmentVariables.Add("MALICM_LOCATION", m_MaliRoot); pi.CreateNoWindow = true; pi.Arguments = commandline; pi.FileName = Path.Combine(m_MaliRoot, "malisc.exe"); pi.UseShellExecute = false; Process p = Process.Start(pi); string output = p.StandardOutput.ReadToEnd(); p.WaitForExit(); rs.Add(asic, output); } } catch (System.Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't run MaliSC", MessageBoxButtons.OK, MessageBoxIcon.Error); } File.Delete(tmpFile); return rs; } } } ================================================ FILE: src/Backends/MaliSCResultsPanel.Designer.cs ================================================ namespace Pyramid { partial class MaliSCResultsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.txtOutput = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.cmbCore = new System.Windows.Forms.ComboBox(); this.SuspendLayout(); // // txtOutput // this.txtOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtOutput.Location = new System.Drawing.Point(3, 32); this.txtOutput.Multiline = true; this.txtOutput.Name = "txtOutput"; this.txtOutput.ReadOnly = true; this.txtOutput.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtOutput.Size = new System.Drawing.Size(393, 283); this.txtOutput.TabIndex = 0; // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(8, 11); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(29, 13); this.label1.TabIndex = 1; this.label1.Text = "Core"; // // cmbCore // this.cmbCore.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbCore.FormattingEnabled = true; this.cmbCore.Location = new System.Drawing.Point(43, 5); this.cmbCore.Name = "cmbCore"; this.cmbCore.Size = new System.Drawing.Size(207, 21); this.cmbCore.TabIndex = 2; this.cmbCore.SelectedIndexChanged += new System.EventHandler(this.cmbCore_SelectedIndexChanged); // // MaliSCResultsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.cmbCore); this.Controls.Add(this.label1); this.Controls.Add(this.txtOutput); this.Name = "MaliSCResultsPanel"; this.Size = new System.Drawing.Size(399, 318); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TextBox txtOutput; private System.Windows.Forms.Label label1; private System.Windows.Forms.ComboBox cmbCore; } } ================================================ FILE: src/Backends/MaliSCResultsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid { public partial class MaliSCResultsPanel : UserControl { private List m_Cores = new List(); private List m_Output = new List(); public MaliSCResultsPanel() { InitializeComponent(); } public void AddResult(string core, string output) { m_Cores.Add(core); m_Output.Add(output); cmbCore.Items.Add(core); if (cmbCore.Items.Count == 1) cmbCore.SelectedIndex = 0; } private void cmbCore_SelectedIndexChanged(object sender, EventArgs e) { txtOutput.Text = m_Output[m_Cores.IndexOf(cmbCore.Text)]; } } } ================================================ FILE: src/Backends/MaliSCResultsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Backends/PVRResultsPanel.Designer.cs ================================================ namespace Pyramid { partial class PVRResultsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.cmbCompiler = new System.Windows.Forms.ComboBox(); this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabPage1 = new System.Windows.Forms.TabPage(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.txtASM = new System.Windows.Forms.TextBox(); this.txtOutput = new System.Windows.Forms.TextBox(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabPage2.SuspendLayout(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(5, 9); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(47, 13); this.label1.TabIndex = 0; this.label1.Text = "Compiler"; // // cmbCompiler // this.cmbCompiler.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.cmbCompiler.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbCompiler.FormattingEnabled = true; this.cmbCompiler.Location = new System.Drawing.Point(54, 5); this.cmbCompiler.Name = "cmbCompiler"; this.cmbCompiler.Size = new System.Drawing.Size(164, 21); this.cmbCompiler.TabIndex = 1; this.cmbCompiler.SelectedIndexChanged += new System.EventHandler(this.cmbCompiler_SelectedIndexChanged); // // tabControl1 // this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Bottom; this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tabControl1.Controls.Add(this.tabPage1); this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Location = new System.Drawing.Point(10, 31); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; this.tabControl1.Size = new System.Drawing.Size(207, 190); this.tabControl1.TabIndex = 2; // // tabPage1 // this.tabPage1.Controls.Add(this.txtASM); this.tabPage1.Location = new System.Drawing.Point(4, 4); this.tabPage1.Name = "tabPage1"; this.tabPage1.Padding = new System.Windows.Forms.Padding(3); this.tabPage1.Size = new System.Drawing.Size(199, 164); this.tabPage1.TabIndex = 0; this.tabPage1.Text = "ASM"; this.tabPage1.UseVisualStyleBackColor = true; // // tabPage2 // this.tabPage2.Controls.Add(this.txtOutput); this.tabPage2.Location = new System.Drawing.Point(4, 4); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); this.tabPage2.Size = new System.Drawing.Size(199, 164); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Output"; this.tabPage2.UseVisualStyleBackColor = true; // // txtASM // this.txtASM.Dock = System.Windows.Forms.DockStyle.Fill; this.txtASM.Location = new System.Drawing.Point(3, 3); this.txtASM.Multiline = true; this.txtASM.Name = "txtASM"; this.txtASM.ReadOnly = true; this.txtASM.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtASM.Size = new System.Drawing.Size(193, 158); this.txtASM.TabIndex = 0; // // txtOutput // this.txtOutput.Dock = System.Windows.Forms.DockStyle.Fill; this.txtOutput.Location = new System.Drawing.Point(3, 3); this.txtOutput.Multiline = true; this.txtOutput.Name = "txtOutput"; this.txtOutput.ReadOnly = true; this.txtOutput.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.txtOutput.Size = new System.Drawing.Size(193, 158); this.txtOutput.TabIndex = 1; // // PVRResultsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.tabControl1); this.Controls.Add(this.cmbCompiler); this.Controls.Add(this.label1); this.Name = "PVRResultsPanel"; this.Size = new System.Drawing.Size(228, 232); this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); this.tabPage1.PerformLayout(); this.tabPage2.ResumeLayout(false); this.tabPage2.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; private System.Windows.Forms.ComboBox cmbCompiler; private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; private System.Windows.Forms.TabPage tabPage2; private System.Windows.Forms.TextBox txtASM; private System.Windows.Forms.TextBox txtOutput; } } ================================================ FILE: src/Backends/PVRResultsPanel.cs ================================================ using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Windows.Forms; namespace Pyramid { public partial class PVRResultsPanel : UserControl { private List m_ASM = new List(); private List m_Output = new List(); public PVRResultsPanel() { InitializeComponent(); } public void AddResult( string compiler, string output, string asm ) { m_ASM.Add(asm); m_Output.Add( output ); cmbCompiler.Items.Add(compiler); if( cmbCompiler.Items.Count == 1 ) cmbCompiler.SelectedIndex = 0; } private void cmbCompiler_SelectedIndexChanged(object sender, EventArgs e) { txtASM.Text = m_ASM[cmbCompiler.SelectedIndex]; txtOutput.Text = m_Output[cmbCompiler.SelectedIndex]; } } } ================================================ FILE: src/Backends/PVRResultsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 True True ================================================ FILE: src/Backends/PowerVRBackend.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Diagnostics; using System.Windows.Forms; namespace Pyramid { class PVRResultSet : IResultSet { private PVRResultsPanel m_Results = new PVRResultsPanel(); public string Name { get { return "PowerVR"; } } public Control AnalysisPanel { get { return null; } } public Control ResultsPanel { get { return m_Results; } } public PVRResultsPanel PVRResultsPanel { get { return m_Results; } } }; class PowerVRBackend : IBackend { private List m_Compilers = new List(); private string m_TempPath; public string Name { get { return "PowerVR"; } } public PowerVRBackend( string CompilerDir, string tempDir ) { CompilerDir = Path.GetFullPath(CompilerDir); m_TempPath = tempDir; if (!Directory.Exists(CompilerDir)) { MessageBox.Show("PowerVR compiler directory doesn't exist", "uh-oh", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } foreach (string s in Directory.EnumerateFiles(CompilerDir)) { string ext = Path.GetExtension(s); if( ext.Equals(".exe") ) { ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = "-?"; pi.FileName = s; pi.UseShellExecute = false; try { Process p = Process.Start(pi); p.WaitForExit(); string output = p.StandardError.ReadToEnd(); if (!output.Contains("PVR GLSL-ES compiler for")) continue; if (!output.Contains("-disasm")) continue; m_Compilers.Add(s); } catch (System.Exception ) { continue; } } } } public IResultSet Compile(IShader sh, IBackendOptions options) { if (sh.Language != Languages.GLSL) return null; GLSLShader glShader = (GLSLShader)sh; IGLSLOptions glOpts = glShader.CompileOptions; string shader = glShader.Code; string shaderSwitch = ""; switch (glOpts.ShaderType) { case GLSLShaderType.VERTEX: shaderSwitch = "-v"; break; case GLSLShaderType.FRAGMENT: shaderSwitch = "-f"; break; case GLSLShaderType.COMPUTE: shaderSwitch = "-c"; break; default: return null; } string tmpFile = Path.Combine(m_TempPath, "PYRAMID_pvr"); string dummyOutputFile = Path.Combine(m_TempPath, "PYRAMID_pvr.out"); string disasmFile = Path.Combine(m_TempPath, "PYRAMID_pvr.disasm"); try { StreamWriter stream = File.CreateText(tmpFile); stream.Write(shader); stream.Close(); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't create temp file", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } string args = String.Format("{0} {1} {2} -disasm", tmpFile, dummyOutputFile, shaderSwitch); PVRResultSet rs = new PVRResultSet(); foreach (string s in m_Compilers) { ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = args; pi.FileName = s; pi.UseShellExecute = false; try { Process p= Process.Start(pi); string asm = "No Output"; string output = p.StandardError.ReadToEnd(); string compiler = Path.GetFileNameWithoutExtension(s); p.WaitForExit(); if (File.Exists(disasmFile)) { asm = File.ReadAllText(disasmFile); File.Delete(disasmFile); } rs.PVRResultsPanel.AddResult(compiler, output, asm); } catch (System.Exception) { continue; } } File.Delete(tmpFile); return rs; } } } ================================================ FILE: src/Backends/RGABackend.cs ================================================  using System.Diagnostics; using System.Collections.Generic; using System.IO; using System; using System.Windows.Forms; namespace Pyramid { class RGAResult { public string Isa { get; private set; } public string Il { get; private set; } public string Analysis { get; private set; } public string LiveReg { get; private set; } public string Asic { get; private set; } public RGAResult( string asic, string path ) { Asic = asic; string isaFile = Path.ChangeExtension(path, ".isa"); string analysisFile = Path.ChangeExtension(path, ".analysis"); string ilFile = Path.ChangeExtension(path, ".il"); string liveRegFile = Path.ChangeExtension(path, ".livereg"); if (File.Exists(isaFile)) { this.Isa = File.ReadAllText(isaFile); File.Delete(isaFile); } if (File.Exists(analysisFile)) { this.Analysis = File.ReadAllText(analysisFile); File.Delete(analysisFile); } if (File.Exists(ilFile)) { this.Il = File.ReadAllText(ilFile); File.Delete(ilFile); } if (File.Exists(liveRegFile)) { this.LiveReg = File.ReadAllText(liveRegFile); File.Delete(liveRegFile); } } } class GenericTextResultSet : IResultSet { public GenericTextResultSet(string name, string text) { Name = name; RichTextBox results = new RichTextBox(); results.Dock = DockStyle.Fill; results.ReadOnly = true; results.Multiline = true; results.Font = new System.Drawing.Font("Lucida Console", 8); results.Text = text; results.ScrollBars = RichTextBoxScrollBars.Both; ResultsPanel = results; } public Control ResultsPanel { get; private set; } public Control AnalysisPanel { get { return null; } } public string Name { get; private set; } } class RGAResultSet : IResultSet { private AMDResultsPanel m_ResultsPanel; private TextBox m_Analysis = new TextBox(); private Dictionary m_ResultMap = new Dictionary(); public RGAResultSet( string name, string toolOutput ) { m_ResultsPanel = new AMDResultsPanel(); m_ResultsPanel.SetToolOutput(toolOutput); m_Analysis.Dock = DockStyle.Fill; m_Analysis.ReadOnly = true; m_Analysis.Multiline = true; m_Analysis.Font = new System.Drawing.Font("Lucida Console", 8); m_Analysis.ScrollBars = ScrollBars.Both; m_ResultsPanel.AsicChanged += delegate(string asic) { m_Analysis.Text = m_ResultMap[asic].Analysis; }; Name = name; } public Control ResultsPanel { get { return m_ResultsPanel; } } public Control AnalysisPanel { get { return m_Analysis; } } public string Name { get; private set; } public int ResultCount { get { return m_ResultsPanel.ResultCount; } } public void AddCompileResult( RGAResult result ) { m_ResultMap.Add(result.Asic, result); m_ResultsPanel.AddResult(result.Asic, result.Il, result.Isa); } public void DisplayAsic(string asic) { m_ResultsPanel.SetAsic(asic); m_Analysis.Text = m_ResultMap[asic].Analysis; } } class RGABackendOptions : IBackendOptions { private Options m_Opts; public RGABackendOptions( Options opts ) { m_Opts = opts; } public bool ShouldCompileForAsic( string asic) { return !m_Opts.IsRGAAsicDisabled(asic); } } class RGABackend : IBackend { private List m_SupportedAsics = new List(); private string m_RGAPath = ""; private string m_TempPath = ""; private GLSlang.ICompiler m_GLSLang; private GLSlang.IConfig m_GLSLangConfig; public string Name { get { return "RGA_Vulkan"; } } public IEnumerable Asics { get { return m_SupportedAsics; } } public static List GetAsicList( string RGAPath ) { string CommandLine = string.Format("-s vulkan -l"); List asics = new List(); ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = true; pi.CreateNoWindow = true; pi.Arguments = CommandLine; pi.FileName = RGAPath; pi.UseShellExecute = false; try { Process p = Process.Start(pi); while (!p.StandardOutput.EndOfStream) { // Output is of the form: // //name (graphics ip) //\tproduct_name //\tproduct_name // .... // string s = p.StandardOutput.ReadLine(); if (s.Length == 0) continue; // blank line if (s[0] == '\t') continue; // indented product name // grab the asic name, ignore everything after int len = s.IndexOf(' '); if (len > 0) s = s.Substring(0, len); asics.Add(s); } p.WaitForExit(); p.Close(); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't get RGA asic list", MessageBoxButtons.OK, MessageBoxIcon.Error); } return asics; } public RGABackend(string RGAPath, string TempPath, IWrapper wrapper, IIncludeHandler handler ) { m_SupportedAsics = GetAsicList(RGAPath); m_RGAPath = RGAPath; m_TempPath = TempPath; m_GLSLang = wrapper.CreateGLSlangCompiler(handler); m_GLSLangConfig = m_GLSLang.CreateDefaultConfig(); } private string GetRGAShaderType(GLSLShaderType eShaderType) { string sType = ""; switch (eShaderType) { default: return ""; case GLSLShaderType.VERTEX: sType = "vert"; break; case GLSLShaderType.FRAGMENT: sType = "frag"; break; case GLSLShaderType.GEOMETRY: sType = "geom"; break; case GLSLShaderType.TESS_CONTROL: sType = "tesc"; break; case GLSLShaderType.TESS_EVALUATION: sType = "tese"; break; case GLSLShaderType.COMPUTE: sType = "comp"; break; } return sType; } GLSlang.IShader CompileShader( IShader shader ) { if (shader is HLSLShader) { // pass the shader through GLSLang's hlsl front end HLSLShader hlsl = shader as HLSLShader; return m_GLSLang.CompileHLSL(shader.Code, hlsl.CompileOptions, m_GLSLangConfig, shader.SourceFilePath); } else if( shader is GLSLShader ) { GLSLShader glsl = shader as GLSLShader; return m_GLSLang.Compile(shader.Code, glsl.CompileOptions.ShaderType, m_GLSLangConfig, glsl.SourceFilePath); } else { throw new System.Exception("Bad shader type?!?"); } } public IResultSet Compile(IShader shader, IBackendOptions options) { if( !(options is RGABackendOptions)) return null; if (!(shader is HLSLShader || shader is GLSLShader)) return null; RGABackendOptions backendOptions = options as RGABackendOptions; string tmpFile = Path.Combine(m_TempPath, "PYRAMID_amdrga"); // pass the shader through GLSLang's hlsl front end GLSlang.IShader glShader = CompileShader(shader); if (glShader.HasErrors) return new GenericTextResultSet(this.Name, glShader.InfoLog); string sType = GetRGAShaderType(glShader.ShaderType); // get the SPIR-V SPIRV.IProgram spirv = glShader.CompileSPIRV(); if (spirv == null) return new GenericTextResultSet(this.Name, "Error generating SPIR-V"); // dump the SPIR-V to disk try { File.WriteAllBytes(tmpFile, spirv.GetBytes()); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't create temp file", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } // send the SPIR-V to RGA string CommandLine = String.Format(" -s vulkan-spv {0}", tmpFile); string isaPath = Path.Combine(m_TempPath, "pyramid.isa"); string analysisPath = Path.Combine(m_TempPath, "pyramid.analysis"); string ilPath = Path.Combine(m_TempPath, "pyramid.il"); string liveRegPath = Path.Combine(m_TempPath, "pyramid.livereg"); CommandLine = String.Concat(CommandLine, String.Format(" --isa \"{0}\" ", isaPath)); CommandLine = String.Concat(CommandLine, String.Format(" -a \"{0}\" ", analysisPath)); CommandLine = String.Concat(CommandLine, String.Format(" --il \"{0}\" ", ilPath)); CommandLine = String.Concat(CommandLine, String.Format(" --livereg \"{0}\" ", liveRegPath)); List asicsToCompile = new List(); foreach (string asic in m_SupportedAsics) { if ( backendOptions.ShouldCompileForAsic(asic)) { asicsToCompile.Add(asic); CommandLine = String.Concat(CommandLine, " -c ", asic, " "); } } if (asicsToCompile.Count == 0) return null; string defaultAsic = asicsToCompile[0]; ProcessStartInfo pi = new ProcessStartInfo(); pi.RedirectStandardOutput = true; pi.RedirectStandardInput = true; pi.RedirectStandardError = false; pi.CreateNoWindow = true; pi.Arguments = CommandLine; pi.FileName = m_RGAPath; pi.UseShellExecute = false; string output; try { Process p = Process.Start(pi); output = p.StandardOutput.ReadToEnd(); int TIMEOUT = 60000; p.WaitForExit(TIMEOUT); p.Close(); File.Delete(tmpFile); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't run CodeXL", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } output = String.Format(@"Arguments: ---------- {0} Output: ------- {1}", CommandLine, output); // Compile results are emitted in one set of files per asic RGAResultSet results = new RGAResultSet(this.Name, output); foreach (string asic in asicsToCompile) { string path = Path.Combine( m_TempPath, String.Format("{0}_{1}_pyramid", asic, sType) ); try { RGAResult result = new RGAResult(asic, path); results.AddCompileResult(result); } catch (Exception ex) { // may occur on compile error } } if (results.ResultCount > 0) { results.DisplayAsic(defaultAsic); return results; } else return null; } } } ================================================ FILE: src/GLSLOptimizer.cs ================================================ using System; using System.Collections.Generic; namespace Pyramid { namespace GLSLOptimizer { public enum Target { OPENGL = 0, OPENGL_ES2 = 1, OPENGL_ES3 = 2 }; public enum ShaderType { VERTEX = 0, FRAGMENT = 1, }; public interface IOptions { ShaderType ShaderType { get; } uint MaxUnrollIterations { get; } } public interface IShader { bool HadError { get; } string Output { get; } string RawOutput { get; } string Log { get; } IEnumerable Inputs { get;} int MathOps { get; } int TextureOps { get; } int ControlFlowOps { get; } }; public interface IOptimizer { IShader Optimize(string text, IOptions opts); }; } } ================================================ FILE: src/GLSLTypes.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Pyramid { public enum GLSLShaderType { VERTEX = 0, FRAGMENT = 1, TESS_CONTROL = 2, TESS_EVALUATION = 3, GEOMETRY = 4, COMPUTE = 5, } public interface IGLSLOptions : ICompileOptions { GLSLShaderType ShaderType { get; } GLSLOptimizer.Target OptimizerTarget { get; } GLSLOptimizer.IOptions OptimizerOptions { get; } } public class GLSLShader : IShader { public GLSLShader(string code, IGLSLOptions opts, string path ) { CompileOptions = opts; Code = code; SourceFilePath = path; } public Languages Language { get { return Languages.GLSL; } } public IGLSLOptions CompileOptions { get; private set; } public string Code { get; private set; } public string SourceFilePath { get; private set; } }; } ================================================ FILE: src/GLSlang.cs ================================================ using System; using System.Collections.Generic; namespace Pyramid { namespace GLSlang { public interface IShader { GLSLShaderType ShaderType { get; } bool HasErrors { get; } string InfoLog { get; } string InfoDebugLog { get; } SPIRV.IProgram CompileSPIRV(); } public interface IConfig { } public interface ICompiler { IConfig CreateConfig(string text); IConfig CreateDefaultConfig(); IShader Compile(string text, GLSLShaderType eType, IConfig config, string filePath); IShader CompileHLSL(string text, IHLSLOptions opts, IConfig config, string filePath ); } } } ================================================ FILE: src/HLSLTypes.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Pyramid { public enum HLSLTarget { vs_3_0, vs_4_0, vs_4_1, vs_5_0, vs_5_1, vs_6_0, vs_6_1, vs_6_2, ps_3_0, ps_4_0, ps_4_1, ps_5_0, ps_5_1, ps_6_0, ps_6_1, ps_6_2, gs_4_0, gs_4_1, gs_5_0, gs_5_1, gs_6_0, gs_6_1, gs_6_2, hs_5_0, hs_5_1, hs_6_0, hs_6_1, hs_6_2, ds_5_0, ds_5_1, ds_6_0, ds_6_1, ds_6_2, cs_4_0, cs_4_1, cs_5_0, cs_5_1, cs_6_0, cs_6_1, cs_6_2, }; public enum RootSignatureTarget { rootsig_1_0, rootsig_1_1, } public enum HLSLOptimizationLevel { SKIP, LEVEL0, LEVEL1, LEVEL2, LEVEL3 }; public enum HLSLShaderType { VERTEX, PIXEL, GEOMETRY, DOMAIN, HULL, COMPUTE }; public interface IHLSLOptions : ICompileOptions { string EntryPoint { get; } HLSLTarget Target { get; } RootSignatureTarget RootSigTarget { get; } HLSLShaderType ShaderType { get; } HLSLOptimizationLevel OptimizationLevel { get; } bool Compatibility { get; } string RootSigMacro { get; } string GetFXCCommandLine(string shaderFile); uint GetD3DCompileFlagBits(); } public interface IDXShaderReflection { HLSLShaderType GetShaderType(); uint GetThreadsPerGroup(); }; public interface IDXBlob { byte[] ReadBytes(); } public interface IDXShaderBlob : IDXBlob { string Disassemble(); IDXBlob ExtractRootSignature(); } public interface IDXILShaderBlob : IDXShaderBlob { } public interface IDXBCShaderBlob : IDXShaderBlob { IDXBCShaderBlob GetSignatureBlob(); IDXBCShaderBlob GetExecutableBlob(); IDXBCShaderBlob Strip(); IDXShaderReflection Reflect(); } public class HLSLShader : IShader { public HLSLShader(string code, IHLSLOptions opts ,string path) { CompileOptions = opts; Code = code; WasCompiled = false; RootSigWasCompiled = false; RootSigHasError = false; SourceFilePath = path; } public Languages Language { get { return Languages.HLSL; } } public IHLSLOptions CompileOptions { get; private set; } public string Code { get; private set; } public IDXShaderBlob CompiledBlob { get; private set; } public string Messages { get; private set; } public string SourceFilePath { get; private set; } public bool CompileRootSignature( IDXILCompiler compiler ) { if( compiler != null ) { IDXBlob blob; string msg; RootSigHasError = !compiler.CompileRootSignature(this.Code, this.CompileOptions, this.SourceFilePath, out blob, out msg); RootSigMessages = msg; CompiledRootSig = blob; RootSigWasCompiled = true; return !RootSigHasError; } else { return false; } } public bool Compile( ID3DCompiler compiler, IDXILCompiler dxil ) { if( CompileOptions.Target.ToString()[3] == '6' ) { if (dxil == null) return false; IDXILShaderBlob blob; string msg; HasError = !dxil.Compile(this.Code, this.CompileOptions, this.SourceFilePath, out blob, out msg); WasCompiled = true; Messages = msg; CompiledBlob = blob; } else { if( compiler == null ) return false; IDXBCShaderBlob blob; string msg; HasError = !compiler.Compile(this.Code, this.CompileOptions, this.SourceFilePath, out blob, out msg); WasCompiled = true; Messages = msg; CompiledBlob = blob; } // check for embedded root signature and pull it out if there is one if( CompiledBlob != null ) { IDXBlob rs = CompiledBlob.ExtractRootSignature(); if (rs != null) { RootSigWasCompiled = true; RootSigHasError = false; CompiledRootSig = rs; } } return !HasError; } public IDXBlob CompiledRootSig { get; private set; } public bool RootSigWasCompiled { get; private set; } public bool RootSigHasError { get; private set; } public string RootSigMessages { get; private set; } public bool WasCompiled { get; private set; } public bool HasError { get; private set; } public bool WasCompiledWithErrors { get { return WasCompiled && HasError; } } }; public interface ID3DCompiler { bool CompileRootSignature(string text, IHLSLOptions opts, string fileName, out IDXBlob blob, out string Messages); bool Compile(string text, IHLSLOptions opts, string fileName, out IDXBCShaderBlob blob, out string Messages); }; public interface IDXILCompiler { bool CompileRootSignature(string text, IHLSLOptions opts, string fileName, out IDXBlob blob, out string Messages); bool Compile(string text, IHLSLOptions opts, string fileName, out IDXILShaderBlob blob, out string Messages); }; } ================================================ FILE: src/IAMDDriver.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Pyramid { public interface IAMDAsic { string Name { get; } }; public interface IAMDShader { IAMDAsic Asic { get; } byte[] ReadISABytes(); string Disassemble(); string ListEncodings(); string PrintStats( ); Scrutinizer.IScrutinizer CreateScrutinizer( ); }; public interface IAMDDriver { IEnumerable Asics { get; } /// /// Compile a DX shader blob and return the /// /// /// IAMDShader CompileDXBlob(IAMDAsic asic, byte[] blob, IDXShaderReflection reflect ); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Configuration/AssemblyInfo.cs ================================================ // // // // // $Revision: 1618 $ // using System; using System.Reflection; using System.Runtime.CompilerServices; [assembly: CLSCompliant(true)] [assembly: StringFreezing()] [assembly: AssemblyTitle("ICSharpCode.TextEditor")] [assembly: AssemblyDescription("A .NET text editor control")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] ================================================ FILE: src/ICSharpCode.TextEditor/Project/GlobalAssemblyInfo.cs ================================================ // // // // // $Revision: 1040 $ // ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // // // DO NOT EDIT GlobalAssemblyInfo.cs, it is recreated using AssemblyInfo.template whenever // // StartUp is compiled. // // // ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// using System.Reflection; [assembly: System.Runtime.InteropServices.ComVisible(false)] [assembly: AssemblyCompany("ic#code")] [assembly: AssemblyProduct("SharpDevelop")] [assembly: AssemblyCopyright("2000-2008 AlphaSierraPapa")] [assembly: AssemblyVersion(RevisionClass.FullVersion)] internal static class RevisionClass { public const string Major = "3"; public const string Minor = "0"; public const string Build = "0"; public const string Revision = "3437"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; } ================================================ FILE: src/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj ================================================  Debug AnyCPU 9.0.21022 2.0 {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} ICSharpCode.TextEditor Library 4 False False OnSuccessfulBuild Library true Resources\ICSharpCode.TextEditor.snk ICSharpCode.TextEditor False Auto 98041856 AnyCPU 4096 v4.0 3.5 False False True bin\Debug\ TRACE;DEBUG false -Microsoft.Design#CA1012;-Microsoft.Design#CA2210;-Microsoft.Design#CA1040;-Microsoft.Design#CA1005;-Microsoft.Design#CA1020;-Microsoft.Design#CA1021;-Microsoft.Design#CA1010;-Microsoft.Design#CA1011;-Microsoft.Design#CA1009;-Microsoft.Design#CA1050;-Microsoft.Design#CA1026;-Microsoft.Design#CA1019;-Microsoft.Design#CA1031;-Microsoft.Design#CA1047;-Microsoft.Design#CA1000;-Microsoft.Design#CA1048;-Microsoft.Design#CA1051;-Microsoft.Design#CA1002;-Microsoft.Design#CA1061;-Microsoft.Design#CA1006;-Microsoft.Design#CA1046;-Microsoft.Design#CA1045;-Microsoft.Design#CA1038;-Microsoft.Design#CA1008;-Microsoft.Design#CA1028;-Microsoft.Design#CA1004;-Microsoft.Design#CA1035;-Microsoft.Design#CA1063;-Microsoft.Design#CA1032;-Microsoft.Design#CA1023;-Microsoft.Design#CA1033;-Microsoft.Design#CA1039;-Microsoft.Design#CA1016;-Microsoft.Design#CA1014;-Microsoft.Design#CA1017;-Microsoft.Design#CA1018;-Microsoft.Design#CA1027;-Microsoft.Design#CA1059;-Microsoft.Design#CA1060;-Microsoft.Design#CA1034;-Microsoft.Design#CA1013;-Microsoft.Design#CA1036;-Microsoft.Design#CA1044;-Microsoft.Design#CA1041;-Microsoft.Design#CA1025;-Microsoft.Design#CA1052;-Microsoft.Design#CA1053;-Microsoft.Design#CA1057;-Microsoft.Design#CA1058;-Microsoft.Design#CA1001;-Microsoft.Design#CA1049;-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055;-Microsoft.Design#CA1030;-Microsoft.Design#CA1003;-Microsoft.Design#CA1007;-Microsoft.Design#CA1043;-Microsoft.Design#CA1024;-Microsoft.Design#CA1062;-Microsoft.Globalization#CA1301;-Microsoft.Globalization#CA1302;-Microsoft.Globalization#CA1303;-Microsoft.Globalization#CA1306;-Microsoft.Globalization#CA1304;-Microsoft.Globalization#CA1305;-Microsoft.Globalization#CA1300;-Microsoft.Mobility#CA1600;-Microsoft.Mobility#CA1601;-Microsoft.Naming#CA1718;-Microsoft.Naming#CA1720;-Microsoft.Naming#CA1700;-Microsoft.Naming#CA1712;-Microsoft.Naming#CA1713;-Microsoft.Naming#CA1709;-Microsoft.Naming#CA1708;-Microsoft.Naming#CA1715;-Microsoft.Naming#CA1710;-Microsoft.Naming#CA1707;-Microsoft.Naming#CA1722;-Microsoft.Naming#CA1711;-Microsoft.Naming#CA1716;-Microsoft.Naming#CA1705;-Microsoft.Naming#CA1725;-Microsoft.Naming#CA1719;-Microsoft.Naming#CA1721;-Microsoft.Naming#CA1706;-Microsoft.Naming#CA1724;-Microsoft.Naming#CA1726;-Microsoft.Performance#CA1809;-Microsoft.Performance#CA1811;-Microsoft.Performance#CA1812;-Microsoft.Performance#CA1807;-Microsoft.Performance#CA1813;-Microsoft.Performance#CA1823;-Microsoft.Performance#CA1816;-Microsoft.Performance#CA1817;-Microsoft.Performance#CA1800;-Microsoft.Performance#CA1818;-Microsoft.Performance#CA1805;-Microsoft.Performance#CA1810;-Microsoft.Performance#CA1822;-Microsoft.Performance#CA1815;-Microsoft.Performance#CA1814;-Microsoft.Performance#CA1819;-Microsoft.Performance#CA1804;-Microsoft.Performance#CA1820;-Microsoft.Performance#CA1802;-Microsoft.Security#CA2116;-Microsoft.Security#CA2117;-Microsoft.Security#CA2105;-Microsoft.Security#CA2115;-Microsoft.Security#CA2104;-Microsoft.Security#CA2122;-Microsoft.Security#CA2114;-Microsoft.Security#CA2123;-Microsoft.Security#CA2111;-Microsoft.Security#CA2108;-Microsoft.Security#CA2107;-Microsoft.Security#CA2103;-Microsoft.Security#CA2100;-Microsoft.Security#CA2118;-Microsoft.Security#CA2109;-Microsoft.Security#CA2119;-Microsoft.Security#CA2106;-Microsoft.Security#CA2112;-Microsoft.Security#CA2110;-Microsoft.Security#CA2120;-Microsoft.Security#CA2101;-Microsoft.Security#CA2121;-Microsoft.Security#CA2126;-Microsoft.Security#CA2124;-Microsoft.Usage#CA2209;-Microsoft.Usage#CA2236;-Microsoft.Usage#CA2227;-Microsoft.Usage#CA2213;-Microsoft.Usage#CA2216;-Microsoft.Usage#CA2215;-Microsoft.Usage#CA2214;-Microsoft.Usage#CA2222;-Microsoft.Usage#CA2202;-Microsoft.Usage#CA1806;-Microsoft.Usage#CA2217;-Microsoft.Usage#CA2212;-Microsoft.Usage#CA2219;-Microsoft.Usage#CA2201;-Microsoft.Usage#CA2228;-Microsoft.Usage#CA2221;-Microsoft.Usage#CA2220;-Microsoft.Usage#CA2240;-Microsoft.Usage#CA2229;-Microsoft.Usage#CA2238;-Microsoft.Usage#CA2207;-Microsoft.Usage#CA2208;-Microsoft.Usage#CA2235;-Microsoft.Usage#CA2237;-Microsoft.Usage#CA2232;-Microsoft.Usage#CA2223;-Microsoft.Usage#CA2211;-Microsoft.Usage#CA2233;-Microsoft.Usage#CA2225;-Microsoft.Usage#CA2226;-Microsoft.Usage#CA2231;-Microsoft.Usage#CA2224;-Microsoft.Usage#CA2218;-Microsoft.Usage#CA2234;-Microsoft.Usage#CA2241;-Microsoft.Usage#CA2239;-Microsoft.Usage#CA2200;-Microsoft.Usage#CA1801;-Microsoft.Usage#CA2205;-Microsoft.Usage#CA2230 2 true False False bin\Release\ False TRACE Full true None False Form FindAndReplaceForm.cs Form Form Form Component UserControl UserControl Component Form UserControl Component Designer FindAndReplaceForm.cs rem ..\src\Tools\UpdateAssemblyInfo\bin\Debug\UpdateAssemblyInfo.exe copy $(TargetPath) $(SolutionDir)\..\bin ================================================ FILE: src/ICSharpCode.TextEditor/Project/Resources/CPP-Mode.xshd ================================================ ~!%^*()-+=|\#/{}[]:;"'<> , .? # // /* */ " " ' ' ( ================================================ FILE: src/ICSharpCode.TextEditor/Project/Resources/GLSL-Mode.xshd ================================================ ~!%^*()-+=|\#/{}[]:;"'<> , .? # // /* */ " " ' ' ( ================================================ FILE: src/ICSharpCode.TextEditor/Project/Resources/HLSL-Mode.xshd ================================================ ~!%^*()-+=|\#/{}[]:;"'<> , .? # // /* */ " " ' ' ( ================================================ FILE: src/ICSharpCode.TextEditor/Project/Resources/Mode.xsd ================================================ This schema defines the syntax for mode definitions in SharpDevelop. The schema can be simplified quite a bit but it does the job as is. If you are using this file as a reference it is probably easiest to scroll to the botton to find the definition of the root element called SyntaxDefinition and then unwind the different type definitions and refernces. Note on coloring: Many tags define how some symbol should be colored. If a specific symbol can not be matched onto either a Span definition, Keyword, or a Digit/Number it will be rendered in the current default color. Which is the default color of the current span or the default color of the mode as a whole if no span has been entered. ================================================ FILE: src/ICSharpCode.TextEditor/Project/Resources/SyntaxModes.xml ================================================ ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/BookmarkActions.cs ================================================ // // // // // $Revision: 3272 $ // using System; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Actions { public class ToggleBookmark : AbstractEditAction { public override void Execute(TextArea textArea) { textArea.Document.BookmarkManager.ToggleMarkAt(textArea.Caret.Position); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, textArea.Caret.Line)); textArea.Document.CommitUpdate(); } } public class GotoPrevBookmark : AbstractEditAction { Predicate predicate = null; public GotoPrevBookmark(Predicate predicate) { this.predicate = predicate; } public override void Execute(TextArea textArea) { Bookmark mark = textArea.Document.BookmarkManager.GetPrevMark(textArea.Caret.Line, predicate); if (mark != null) { textArea.Caret.Position = mark.Location; textArea.SelectionManager.ClearSelection(); textArea.SetDesiredColumn(); } } } public class GotoNextBookmark : AbstractEditAction { Predicate predicate = null; public GotoNextBookmark(Predicate predicate) { this.predicate = predicate; } public override void Execute(TextArea textArea) { Bookmark mark = textArea.Document.BookmarkManager.GetNextMark(textArea.Caret.Line, predicate); if (mark != null) { textArea.Caret.Position = mark.Location; textArea.SelectionManager.ClearSelection(); textArea.SetDesiredColumn(); } } } public class ClearAllBookmarks : AbstractEditAction { Predicate predicate = null; public ClearAllBookmarks(Predicate predicate) { this.predicate = predicate; } public override void Execute(TextArea textArea) { textArea.Document.BookmarkManager.RemoveMarks(predicate); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); textArea.Document.CommitUpdate(); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/CaretActions.cs ================================================ // // // // // $Revision: 2681 $ // using System; using System.Collections.Generic; using System.Drawing; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Actions { public class CaretLeft : AbstractEditAction { public override void Execute(TextArea textArea) { TextLocation position = textArea.Caret.Position; List foldings = textArea.Document.FoldingManager.GetFoldedFoldingsWithEnd(position.Y); FoldMarker justBeforeCaret = null; foreach (FoldMarker fm in foldings) { if (fm.EndColumn == position.X) { justBeforeCaret = fm; break; // the first folding found is the folding with the smallest Startposition } } if (justBeforeCaret != null) { position.Y = justBeforeCaret.StartLine; position.X = justBeforeCaret.StartColumn; } else { if (position.X > 0) { --position.X; } else if (position.Y > 0) { LineSegment lineAbove = textArea.Document.GetLineSegment(position.Y - 1); position = new TextLocation(lineAbove.Length, position.Y - 1); } } textArea.Caret.Position = position; textArea.SetDesiredColumn(); } } public class CaretRight : AbstractEditAction { public override void Execute(TextArea textArea) { LineSegment curLine = textArea.Document.GetLineSegment(textArea.Caret.Line); TextLocation position = textArea.Caret.Position; List foldings = textArea.Document.FoldingManager.GetFoldedFoldingsWithStart(position.Y); FoldMarker justBehindCaret = null; foreach (FoldMarker fm in foldings) { if (fm.StartColumn == position.X) { justBehindCaret = fm; break; } } if (justBehindCaret != null) { position.Y = justBehindCaret.EndLine; position.X = justBehindCaret.EndColumn; } else { // no folding is interesting if (position.X < curLine.Length || textArea.TextEditorProperties.AllowCaretBeyondEOL) { ++position.X; } else if (position.Y + 1 < textArea.Document.TotalNumberOfLines) { ++position.Y; position.X = 0; } } textArea.Caret.Position = position; textArea.SetDesiredColumn(); } } public class CaretUp : AbstractEditAction { public override void Execute(TextArea textArea) { TextLocation position = textArea.Caret.Position; int lineNr = position.Y; int visualLine = textArea.Document.GetVisibleLine(lineNr); if (visualLine > 0) { Point pos = new Point(textArea.TextView.GetDrawingXPos(lineNr, position.X), textArea.TextView.DrawingPosition.Y + (visualLine - 1) * textArea.TextView.FontHeight - textArea.TextView.TextArea.VirtualTop.Y); textArea.Caret.Position = textArea.TextView.GetLogicalPosition(pos); textArea.SetCaretToDesiredColumn(); } // if (textArea.Caret.Line > 0) { // textArea.SetCaretToDesiredColumn(textArea.Caret.Line - 1); // } } } public class CaretDown : AbstractEditAction { public override void Execute(TextArea textArea) { TextLocation position = textArea.Caret.Position; int lineNr = position.Y; int visualLine = textArea.Document.GetVisibleLine(lineNr); if (visualLine < textArea.Document.GetVisibleLine(textArea.Document.TotalNumberOfLines)) { Point pos = new Point(textArea.TextView.GetDrawingXPos(lineNr, position.X), textArea.TextView.DrawingPosition.Y + (visualLine + 1) * textArea.TextView.FontHeight - textArea.TextView.TextArea.VirtualTop.Y); textArea.Caret.Position = textArea.TextView.GetLogicalPosition(pos); textArea.SetCaretToDesiredColumn(); } // if (textArea.Caret.Line + 1 < textArea.Document.TotalNumberOfLines) { // textArea.SetCaretToDesiredColumn(textArea.Caret.Line + 1); // } } } public class WordRight : CaretRight { public override void Execute(TextArea textArea) { LineSegment line = textArea.Document.GetLineSegment(textArea.Caret.Position.Y); TextLocation oldPos = textArea.Caret.Position; TextLocation newPos; if (textArea.Caret.Column >= line.Length) { newPos = new TextLocation(0, textArea.Caret.Line + 1); } else { int nextWordStart = TextUtilities.FindNextWordStart(textArea.Document, textArea.Caret.Offset); newPos = textArea.Document.OffsetToPosition(nextWordStart); } // handle fold markers List foldings = textArea.Document.FoldingManager.GetFoldingsFromPosition(newPos.Y, newPos.X); foreach (FoldMarker marker in foldings) { if (marker.IsFolded) { if (oldPos.X == marker.StartColumn && oldPos.Y == marker.StartLine) { newPos = new TextLocation(marker.EndColumn, marker.EndLine); } else { newPos = new TextLocation(marker.StartColumn, marker.StartLine); } break; } } textArea.Caret.Position = newPos; textArea.SetDesiredColumn(); } } public class WordLeft : CaretLeft { public override void Execute(TextArea textArea) { TextLocation oldPos = textArea.Caret.Position; if (textArea.Caret.Column == 0) { base.Execute(textArea); } else { LineSegment line = textArea.Document.GetLineSegment(textArea.Caret.Position.Y); int prevWordStart = TextUtilities.FindPrevWordStart(textArea.Document, textArea.Caret.Offset); TextLocation newPos = textArea.Document.OffsetToPosition(prevWordStart); // handle fold markers List foldings = textArea.Document.FoldingManager.GetFoldingsFromPosition(newPos.Y, newPos.X); foreach (FoldMarker marker in foldings) { if (marker.IsFolded) { if (oldPos.X == marker.EndColumn && oldPos.Y == marker.EndLine) { newPos = new TextLocation(marker.StartColumn, marker.StartLine); } else { newPos = new TextLocation(marker.EndColumn, marker.EndLine); } break; } } textArea.Caret.Position = newPos; textArea.SetDesiredColumn(); } } } public class ScrollLineUp : AbstractEditAction { public override void Execute(TextArea textArea) { textArea.AutoClearSelection = false; textArea.MotherTextAreaControl.VScrollBar.Value = Math.Max(textArea.MotherTextAreaControl.VScrollBar.Minimum, textArea.VirtualTop.Y - textArea.TextView.FontHeight); } } public class ScrollLineDown : AbstractEditAction { public override void Execute(TextArea textArea) { textArea.AutoClearSelection = false; textArea.MotherTextAreaControl.VScrollBar.Value = Math.Min(textArea.MotherTextAreaControl.VScrollBar.Maximum, textArea.VirtualTop.Y + textArea.TextView.FontHeight); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/ClipBoardActions.cs ================================================ // // // // // $Revision: 1965 $ // using System; namespace ICSharpCode.TextEditor.Actions { public class Cut : AbstractEditAction { public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } textArea.ClipboardHandler.Cut(null, null); } } public class Copy : AbstractEditAction { public override void Execute(TextArea textArea) { textArea.AutoClearSelection = false; textArea.ClipboardHandler.Copy(null, null); } } public class Paste : AbstractEditAction { public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } textArea.ClipboardHandler.Paste(null, null); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/FindReplaceAction.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ICSharpCode.TextEditor.Actions { public class FindReplaceAction : AbstractEditAction { public override void Execute(TextArea textArea) { ICSharpCode.TextEditor.FindAndReplaceForm frm = new FindAndReplaceForm(); frm.ShowFor(textArea.MotherTextEditorControl, false); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/FoldActions.cs ================================================ // // // // // $Revision: 2972 $ // using System; using System.Collections.Generic; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Actions { public class ToggleFolding : AbstractEditAction { public override void Execute(TextArea textArea) { List foldMarkers = textArea.Document.FoldingManager.GetFoldingsWithStart(textArea.Caret.Line); if (foldMarkers.Count != 0) { foreach (FoldMarker fm in foldMarkers) fm.IsFolded = !fm.IsFolded; } else { foldMarkers = textArea.Document.FoldingManager.GetFoldingsContainsLineNumber(textArea.Caret.Line); if (foldMarkers.Count != 0) { FoldMarker innerMost = foldMarkers[0]; for (int i = 1; i < foldMarkers.Count; i++) { if (new TextLocation(foldMarkers[i].StartColumn, foldMarkers[i].StartLine) > new TextLocation(innerMost.StartColumn, innerMost.StartLine)) { innerMost = foldMarkers[i]; } } innerMost.IsFolded = !innerMost.IsFolded; } } textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty); } } public class ToggleAllFoldings : AbstractEditAction { public override void Execute(TextArea textArea) { bool doFold = true; foreach (FoldMarker fm in textArea.Document.FoldingManager.FoldMarker) { if (fm.IsFolded) { doFold = false; break; } } foreach (FoldMarker fm in textArea.Document.FoldingManager.FoldMarker) { fm.IsFolded = doFold; } textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty); } } public class ShowDefinitionsOnly : AbstractEditAction { public override void Execute(TextArea textArea) { foreach (FoldMarker fm in textArea.Document.FoldingManager.FoldMarker) { fm.IsFolded = fm.FoldType == FoldType.MemberBody || fm.FoldType == FoldType.Region; } textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/FormatActions.cs ================================================ // // // // // $Revision: 2640 $ // using System; using System.Text; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Actions { public abstract class AbstractLineFormatAction : AbstractEditAction { protected TextArea textArea; abstract protected void Convert(IDocument document, int startLine, int endLine); public override void Execute(TextArea textArea) { this.textArea = textArea; textArea.BeginUpdate(); textArea.Document.UndoStack.StartUndoGroup(); if (textArea.SelectionManager.HasSomethingSelected) { foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { Convert(textArea.Document, selection.StartPosition.Y, selection.EndPosition.Y); } } else { Convert(textArea.Document, 0, textArea.Document.TotalNumberOfLines - 1); } textArea.Document.UndoStack.EndUndoGroup(); textArea.Caret.ValidateCaretPos(); textArea.EndUpdate(); textArea.Refresh(); } } public abstract class AbstractSelectionFormatAction : AbstractEditAction { protected TextArea textArea; abstract protected void Convert(IDocument document, int offset, int length); public override void Execute(TextArea textArea) { this.textArea = textArea; textArea.BeginUpdate(); if (textArea.SelectionManager.HasSomethingSelected) { foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { Convert(textArea.Document, selection.Offset, selection.Length); } } else { Convert(textArea.Document, 0, textArea.Document.TextLength); } textArea.Caret.ValidateCaretPos(); textArea.EndUpdate(); textArea.Refresh(); } } public class RemoveLeadingWS : AbstractLineFormatAction { protected override void Convert(IDocument document, int y1, int y2) { for (int i = y1; i < y2; ++i) { LineSegment line = document.GetLineSegment(i); int removeNumber = 0; for (int x = line.Offset; x < line.Offset + line.Length && Char.IsWhiteSpace(document.GetCharAt(x)); ++x) { ++removeNumber; } if (removeNumber > 0) { document.Remove(line.Offset, removeNumber); } } } } public class RemoveTrailingWS : AbstractLineFormatAction { protected override void Convert(IDocument document, int y1, int y2) { for (int i = y2 - 1; i >= y1; --i) { LineSegment line = document.GetLineSegment(i); int removeNumber = 0; for (int x = line.Offset + line.Length - 1; x >= line.Offset && Char.IsWhiteSpace(document.GetCharAt(x)); --x) { ++removeNumber; } if (removeNumber > 0) { document.Remove(line.Offset + line.Length - removeNumber, removeNumber); } } } } public class ToUpperCase : AbstractSelectionFormatAction { protected override void Convert(IDocument document, int startOffset, int length) { string what = document.GetText(startOffset, length).ToUpper(); document.Replace(startOffset, length, what); } } public class ToLowerCase : AbstractSelectionFormatAction { protected override void Convert(IDocument document, int startOffset, int length) { string what = document.GetText(startOffset, length).ToLower(); document.Replace(startOffset, length, what); } } public class InvertCaseAction : AbstractSelectionFormatAction { protected override void Convert(IDocument document, int startOffset, int length) { StringBuilder what = new StringBuilder(document.GetText(startOffset, length)); for (int i = 0; i < what.Length; ++i) { what[i] = Char.IsUpper(what[i]) ? Char.ToLower(what[i]) : Char.ToUpper(what[i]); } document.Replace(startOffset, length, what.ToString()); } } public class CapitalizeAction : AbstractSelectionFormatAction { protected override void Convert(IDocument document, int startOffset, int length) { StringBuilder what = new StringBuilder(document.GetText(startOffset, length)); for (int i = 0; i < what.Length; ++i) { if (!Char.IsLetter(what[i]) && i < what.Length - 1) { what[i + 1] = Char.ToUpper(what[i + 1]); } } document.Replace(startOffset, length, what.ToString()); } } public class ConvertTabsToSpaces : AbstractSelectionFormatAction { protected override void Convert(IDocument document, int startOffset, int length) { string what = document.GetText(startOffset, length); string spaces = new string(' ', document.TextEditorProperties.TabIndent); document.Replace(startOffset, length, what.Replace("\t", spaces)); } } public class ConvertSpacesToTabs : AbstractSelectionFormatAction { protected override void Convert(IDocument document, int startOffset, int length) { string what = document.GetText(startOffset, length); string spaces = new string(' ', document.TextEditorProperties.TabIndent); document.Replace(startOffset, length, what.Replace(spaces, "\t")); } } public class ConvertLeadingTabsToSpaces : AbstractLineFormatAction { protected override void Convert(IDocument document, int y1, int y2) { for (int i = y2; i >= y1; --i) { LineSegment line = document.GetLineSegment(i); if(line.Length > 0) { // count how many whitespace characters there are at the start int whiteSpace = 0; for(whiteSpace = 0; whiteSpace < line.Length && Char.IsWhiteSpace(document.GetCharAt(line.Offset + whiteSpace)); whiteSpace++) { // deliberately empty } if(whiteSpace > 0) { string newLine = document.GetText(line.Offset,whiteSpace); string newPrefix = newLine.Replace("\t",new string(' ', document.TextEditorProperties.TabIndent)); document.Replace(line.Offset,whiteSpace,newPrefix); } } } } } public class ConvertLeadingSpacesToTabs : AbstractLineFormatAction { protected override void Convert(IDocument document, int y1, int y2) { for (int i = y2; i >= y1; --i) { LineSegment line = document.GetLineSegment(i); if(line.Length > 0) { // note: some users may prefer a more radical ConvertLeadingSpacesToTabs that // means there can be no spaces before the first character even if the spaces // didn't add up to a whole number of tabs string newLine = TextUtilities.LeadingWhiteSpaceToTabs(document.GetText(line.Offset,line.Length), document.TextEditorProperties.TabIndent); document.Replace(line.Offset,line.Length,newLine); } } } } /// /// This is a sample editaction plugin, it indents the selected area. /// public class FormatBuffer : AbstractLineFormatAction { protected override void Convert(IDocument document, int startLine, int endLine) { document.FormattingStrategy.IndentLines(textArea, startLine, endLine); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/HomeEndActions.cs ================================================ // // // // // $Revision: 2659 $ // using System; using System.Collections.Generic; using System.Drawing; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Actions { public class Home : AbstractEditAction { public override void Execute(TextArea textArea) { LineSegment curLine; TextLocation newPos = textArea.Caret.Position; bool jumpedIntoFolding = false; do { curLine = textArea.Document.GetLineSegment(newPos.Y); if (TextUtilities.IsEmptyLine(textArea.Document, newPos.Y)) { if (newPos.X != 0) { newPos.X = 0; } else { newPos.X = curLine.Length; } } else { int firstCharOffset = TextUtilities.GetFirstNonWSChar(textArea.Document, curLine.Offset); int firstCharColumn = firstCharOffset - curLine.Offset; if (newPos.X == firstCharColumn) { newPos.X = 0; } else { newPos.X = firstCharColumn; } } List foldings = textArea.Document.FoldingManager.GetFoldingsFromPosition(newPos.Y, newPos.X); jumpedIntoFolding = false; foreach (FoldMarker foldMarker in foldings) { if (foldMarker.IsFolded) { newPos = new TextLocation(foldMarker.StartColumn, foldMarker.StartLine); jumpedIntoFolding = true; break; } } } while (jumpedIntoFolding); if (newPos != textArea.Caret.Position) { textArea.Caret.Position = newPos; textArea.SetDesiredColumn(); } } } public class End : AbstractEditAction { public override void Execute(TextArea textArea) { LineSegment curLine; TextLocation newPos = textArea.Caret.Position; bool jumpedIntoFolding = false; do { curLine = textArea.Document.GetLineSegment(newPos.Y); newPos.X = curLine.Length; List foldings = textArea.Document.FoldingManager.GetFoldingsFromPosition(newPos.Y, newPos.X); jumpedIntoFolding = false; foreach (FoldMarker foldMarker in foldings) { if (foldMarker.IsFolded) { newPos = new TextLocation(foldMarker.EndColumn, foldMarker.EndLine); jumpedIntoFolding = true; break; } } } while (jumpedIntoFolding); if (newPos != textArea.Caret.Position) { textArea.Caret.Position = newPos; textArea.SetDesiredColumn(); } } } public class MoveToStart : AbstractEditAction { public override void Execute(TextArea textArea) { if (textArea.Caret.Line != 0 || textArea.Caret.Column != 0) { textArea.Caret.Position = new TextLocation(0, 0); textArea.SetDesiredColumn(); } } } public class MoveToEnd : AbstractEditAction { public override void Execute(TextArea textArea) { TextLocation endPos = textArea.Document.OffsetToPosition(textArea.Document.TextLength); if (textArea.Caret.Position != endPos) { textArea.Caret.Position = endPos; textArea.SetDesiredColumn(); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/IEditAction.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Actions { /// /// To define a new key for the textarea, you must write a class which /// implements this interface. /// public interface IEditAction { /// /// An array of keys on which this edit action occurs. /// Keys[] Keys { get; set; } /// /// When the key which is defined per XML is pressed, this method will be launched. /// void Execute(TextArea textArea); } /// /// To define a new key for the textarea, you must write a class which /// implements this interface. /// public abstract class AbstractEditAction : IEditAction { Keys[] keys = null; /// /// An array of keys on which this edit action occurs. /// public Keys[] Keys { get { return keys; } set { keys = value; } } /// /// When the key which is defined per XML is pressed, this method will be launched. /// public abstract void Execute(TextArea textArea); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/MiscActions.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Diagnostics; using System.Drawing; using System.Text; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Actions { public class Tab : AbstractEditAction { public static string GetIndentationString(IDocument document) { return GetIndentationString(document, null); } public static string GetIndentationString(IDocument document, TextArea textArea) { StringBuilder indent = new StringBuilder(); if (document.TextEditorProperties.ConvertTabsToSpaces) { int tabIndent = document.TextEditorProperties.IndentationSize; if (textArea != null) { int column = textArea.TextView.GetVisualColumn(textArea.Caret.Line, textArea.Caret.Column); indent.Append(new String(' ', tabIndent - column % tabIndent)); } else { indent.Append(new String(' ', tabIndent)); } } else { indent.Append('\t'); } return indent.ToString(); } void InsertTabs(IDocument document, ISelection selection, int y1, int y2) { string indentationString = GetIndentationString(document); for (int i = y2; i >= y1; --i) { LineSegment line = document.GetLineSegment(i); if (i == y2 && i == selection.EndPosition.Y && selection.EndPosition.X == 0) { continue; } // this bit is optional - but useful if you are using block tabbing to sort out // a source file with a mixture of tabs and spaces // string newLine = document.GetText(line.Offset,line.Length); // document.Replace(line.Offset,line.Length,newLine); document.Insert(line.Offset, indentationString); } } void InsertTabAtCaretPosition(TextArea textArea) { switch (textArea.Caret.CaretMode) { case CaretMode.InsertMode: textArea.InsertString(GetIndentationString(textArea.Document, textArea)); break; case CaretMode.OverwriteMode: string indentStr = GetIndentationString(textArea.Document, textArea); textArea.ReplaceChar(indentStr[0]); if (indentStr.Length > 1) { textArea.InsertString(indentStr.Substring(1)); } break; } textArea.SetDesiredColumn(); } /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } textArea.Document.UndoStack.StartUndoGroup(); if (textArea.SelectionManager.HasSomethingSelected) { foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { int startLine = selection.StartPosition.Y; int endLine = selection.EndPosition.Y; if (startLine != endLine) { textArea.BeginUpdate(); InsertTabs(textArea.Document, selection, startLine, endLine); textArea.Document.UpdateQueue.Clear(); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, startLine, endLine)); textArea.EndUpdate(); } else { InsertTabAtCaretPosition(textArea); break; } } textArea.Document.CommitUpdate(); textArea.AutoClearSelection = false; } else { InsertTabAtCaretPosition(textArea); } textArea.Document.UndoStack.EndUndoGroup(); } } public class ShiftTab : AbstractEditAction { void RemoveTabs(IDocument document, ISelection selection, int y1, int y2) { document.UndoStack.StartUndoGroup(); for (int i = y2; i >= y1; --i) { LineSegment line = document.GetLineSegment(i); if (i == y2 && line.Offset == selection.EndOffset) { continue; } if (line.Length > 0) { /**** TextPad Strategy: /// first convert leading whitespace to tabs (controversial! - not all editors work like this) string newLine = TextUtilities.LeadingWhiteSpaceToTabs(document.GetText(line.Offset,line.Length),document.Properties.Get("TabIndent", 4)); if(newLine.Length > 0 && newLine[0] == '\t') { document.Replace(line.Offset,line.Length,newLine.Substring(1)); ++redocounter; } else if(newLine.Length > 0 && newLine[0] == ' ') { /// there were just some leading spaces but less than TabIndent of them int leadingSpaces = 1; for(leadingSpaces = 1; leadingSpaces < newLine.Length && newLine[leadingSpaces] == ' '; leadingSpaces++) { /// deliberately empty } document.Replace(line.Offset,line.Length,newLine.Substring(leadingSpaces)); ++redocounter; } /// else /// there were no leading tabs or spaces on this line so do nothing /// MS Visual Studio 6 strategy: ****/ // string temp = document.GetText(line.Offset,line.Length); if (line.Length > 0) { int charactersToRemove = 0; if(document.GetCharAt(line.Offset) == '\t') { // first character is a tab - just remove it charactersToRemove = 1; } else if(document.GetCharAt(line.Offset) == ' ') { int leadingSpaces = 1; int tabIndent = document.TextEditorProperties.IndentationSize; for (leadingSpaces = 1; leadingSpaces < line.Length && document.GetCharAt(line.Offset + leadingSpaces) == ' '; leadingSpaces++) { // deliberately empty } if(leadingSpaces >= tabIndent) { // just remove tabIndent charactersToRemove = tabIndent; } else if(line.Length > leadingSpaces && document.GetCharAt(line.Offset + leadingSpaces) == '\t') { // remove the leading spaces and the following tab as they add up // to just one tab stop charactersToRemove = leadingSpaces+1; } else { // just remove the leading spaces charactersToRemove = leadingSpaces; } } if (charactersToRemove > 0) { document.Remove(line.Offset,charactersToRemove); } } } } document.UndoStack.EndUndoGroup(); } /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.SelectionManager.HasSomethingSelected) { foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { int startLine = selection.StartPosition.Y; int endLine = selection.EndPosition.Y; textArea.BeginUpdate(); RemoveTabs(textArea.Document, selection, startLine, endLine); textArea.Document.UpdateQueue.Clear(); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, startLine, endLine)); textArea.EndUpdate(); } textArea.AutoClearSelection = false; } else { // Pressing Shift-Tab with nothing selected the cursor will move back to the // previous tab stop. It will stop at the beginning of the line. Also, the desired // column is updated to that column. LineSegment line = textArea.Document.GetLineSegmentForOffset(textArea.Caret.Offset); string startOfLine = textArea.Document.GetText(line.Offset,textArea.Caret.Offset - line.Offset); int tabIndent = textArea.Document.TextEditorProperties.IndentationSize; int currentColumn = textArea.Caret.Column; int remainder = currentColumn % tabIndent; if (remainder == 0) { textArea.Caret.DesiredColumn = Math.Max(0, currentColumn - tabIndent); } else { textArea.Caret.DesiredColumn = Math.Max(0, currentColumn - remainder); } textArea.SetCaretToDesiredColumn(); } } } public class ToggleComment : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } if (textArea.Document.HighlightingStrategy.Properties.ContainsKey("LineComment")) { new ToggleLineComment().Execute(textArea); } else if (textArea.Document.HighlightingStrategy.Properties.ContainsKey("BlockCommentBegin") && textArea.Document.HighlightingStrategy.Properties.ContainsKey("BlockCommentBegin")) { new ToggleBlockComment().Execute(textArea); } } } public class ToggleLineComment : AbstractEditAction { int firstLine; int lastLine; void RemoveCommentAt(IDocument document, string comment, ISelection selection, int y1, int y2) { firstLine = y1; lastLine = y2; for (int i = y2; i >= y1; --i) { LineSegment line = document.GetLineSegment(i); if (selection != null && i == y2 && line.Offset == selection.Offset + selection.Length) { --lastLine; continue; } string lineText = document.GetText(line.Offset, line.Length); if (lineText.Trim().StartsWith(comment)) { document.Remove(line.Offset + lineText.IndexOf(comment), comment.Length); } } } void SetCommentAt(IDocument document, string comment, ISelection selection, int y1, int y2) { firstLine = y1; lastLine = y2; for (int i = y2; i >= y1; --i) { LineSegment line = document.GetLineSegment(i); if (selection != null && i == y2 && line.Offset == selection.Offset + selection.Length) { --lastLine; continue; } string lineText = document.GetText(line.Offset, line.Length); document.Insert(line.Offset, comment); } } bool ShouldComment(IDocument document, string comment, ISelection selection, int startLine, int endLine) { for (int i = endLine; i >= startLine; --i) { LineSegment line = document.GetLineSegment(i); if (selection != null && i == endLine && line.Offset == selection.Offset + selection.Length) { --lastLine; continue; } string lineText = document.GetText(line.Offset, line.Length); if (!lineText.Trim().StartsWith(comment)) { return true; } } return false; } /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } string comment = null; if (textArea.Document.HighlightingStrategy.Properties.ContainsKey("LineComment")) { comment = textArea.Document.HighlightingStrategy.Properties["LineComment"].ToString(); } if (comment == null || comment.Length == 0) { return; } textArea.Document.UndoStack.StartUndoGroup(); if (textArea.SelectionManager.HasSomethingSelected) { bool shouldComment = true; foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { if (!ShouldComment(textArea.Document, comment, selection, selection.StartPosition.Y, selection.EndPosition.Y)) { shouldComment = false; break; } } foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { textArea.BeginUpdate(); if (shouldComment) { SetCommentAt(textArea.Document, comment, selection, selection.StartPosition.Y, selection.EndPosition.Y); } else { RemoveCommentAt(textArea.Document, comment, selection, selection.StartPosition.Y, selection.EndPosition.Y); } textArea.Document.UpdateQueue.Clear(); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, firstLine, lastLine)); textArea.EndUpdate(); } textArea.Document.CommitUpdate(); textArea.AutoClearSelection = false; } else { textArea.BeginUpdate(); int caretLine = textArea.Caret.Line; if (ShouldComment(textArea.Document, comment, null, caretLine, caretLine)) { SetCommentAt(textArea.Document, comment, null, caretLine, caretLine); } else { RemoveCommentAt(textArea.Document, comment, null, caretLine, caretLine); } textArea.Document.UpdateQueue.Clear(); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, caretLine)); textArea.EndUpdate(); } textArea.Document.UndoStack.EndUndoGroup(); } } public class ToggleBlockComment : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } string commentStart = null; if (textArea.Document.HighlightingStrategy.Properties.ContainsKey("BlockCommentBegin")) { commentStart = textArea.Document.HighlightingStrategy.Properties["BlockCommentBegin"].ToString(); } string commentEnd = null; if (textArea.Document.HighlightingStrategy.Properties.ContainsKey("BlockCommentEnd")) { commentEnd = textArea.Document.HighlightingStrategy.Properties["BlockCommentEnd"].ToString(); } if (commentStart == null || commentStart.Length == 0 || commentEnd == null || commentEnd.Length == 0) { return; } int selectionStartOffset; int selectionEndOffset; if (textArea.SelectionManager.HasSomethingSelected) { selectionStartOffset = textArea.SelectionManager.SelectionCollection[0].Offset; selectionEndOffset = textArea.SelectionManager.SelectionCollection[textArea.SelectionManager.SelectionCollection.Count - 1].EndOffset; } else { selectionStartOffset = textArea.Caret.Offset; selectionEndOffset = selectionStartOffset; } BlockCommentRegion commentRegion = FindSelectedCommentRegion(textArea.Document, commentStart, commentEnd, selectionStartOffset, selectionEndOffset); textArea.Document.UndoStack.StartUndoGroup(); if (commentRegion != null) { RemoveComment(textArea.Document, commentRegion); } else if (textArea.SelectionManager.HasSomethingSelected) { SetCommentAt(textArea.Document, selectionStartOffset, selectionEndOffset, commentStart, commentEnd); } textArea.Document.UndoStack.EndUndoGroup(); textArea.Document.CommitUpdate(); textArea.AutoClearSelection = false; } public static BlockCommentRegion FindSelectedCommentRegion(IDocument document, string commentStart, string commentEnd, int selectionStartOffset, int selectionEndOffset) { if (document.TextLength == 0) { return null; } // Find start of comment in selected text. int commentEndOffset = -1; string selectedText = document.GetText(selectionStartOffset, selectionEndOffset - selectionStartOffset); int commentStartOffset = selectedText.IndexOf(commentStart); if (commentStartOffset >= 0) { commentStartOffset += selectionStartOffset; } // Find end of comment in selected text. if (commentStartOffset >= 0) { commentEndOffset = selectedText.IndexOf(commentEnd, commentStartOffset + commentStart.Length - selectionStartOffset); } else { commentEndOffset = selectedText.IndexOf(commentEnd); } if (commentEndOffset >= 0) { commentEndOffset += selectionStartOffset; } // Find start of comment before or partially inside the // selected text. int commentEndBeforeStartOffset = -1; if (commentStartOffset == -1) { int offset = selectionEndOffset + commentStart.Length - 1; if (offset > document.TextLength) { offset = document.TextLength; } string text = document.GetText(0, offset); commentStartOffset = text.LastIndexOf(commentStart); if (commentStartOffset >= 0) { // Find end of comment before comment start. commentEndBeforeStartOffset = text.IndexOf(commentEnd, commentStartOffset, selectionStartOffset - commentStartOffset); if (commentEndBeforeStartOffset > commentStartOffset) { commentStartOffset = -1; } } } // Find end of comment after or partially after the // selected text. if (commentEndOffset == -1) { int offset = selectionStartOffset + 1 - commentEnd.Length; if (offset < 0) { offset = selectionStartOffset; } string text = document.GetText(offset, document.TextLength - offset); commentEndOffset = text.IndexOf(commentEnd); if (commentEndOffset >= 0) { commentEndOffset += offset; } } if (commentStartOffset != -1 && commentEndOffset != -1) { return new BlockCommentRegion(commentStart, commentEnd, commentStartOffset, commentEndOffset); } return null; } void SetCommentAt(IDocument document, int offsetStart, int offsetEnd, string commentStart, string commentEnd) { document.Insert(offsetEnd, commentEnd); document.Insert(offsetStart, commentStart); } void RemoveComment(IDocument document, BlockCommentRegion commentRegion) { document.Remove(commentRegion.EndOffset, commentRegion.CommentEnd.Length); document.Remove(commentRegion.StartOffset, commentRegion.CommentStart.Length); } } public class BlockCommentRegion { string commentStart = String.Empty; string commentEnd = String.Empty; int startOffset = -1; int endOffset = -1; /// /// The end offset is the offset where the comment end string starts from. /// public BlockCommentRegion(string commentStart, string commentEnd, int startOffset, int endOffset) { this.commentStart = commentStart; this.commentEnd = commentEnd; this.startOffset = startOffset; this.endOffset = endOffset; } public string CommentStart { get { return commentStart; } } public string CommentEnd { get { return commentEnd; } } public int StartOffset { get { return startOffset; } } public int EndOffset { get { return endOffset; } } public override int GetHashCode() { int hashCode = 0; unchecked { if (commentStart != null) hashCode += 1000000007 * commentStart.GetHashCode(); if (commentEnd != null) hashCode += 1000000009 * commentEnd.GetHashCode(); hashCode += 1000000021 * startOffset.GetHashCode(); hashCode += 1000000033 * endOffset.GetHashCode(); } return hashCode; } public override bool Equals(object obj) { BlockCommentRegion other = obj as BlockCommentRegion; if (other == null) return false; return this.commentStart == other.commentStart && this.commentEnd == other.commentEnd && this.startOffset == other.startOffset && this.endOffset == other.endOffset; } } public class IndentSelection : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } textArea.BeginUpdate(); if (textArea.SelectionManager.HasSomethingSelected) { foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { textArea.Document.FormattingStrategy.IndentLines(textArea, selection.StartPosition.Y, selection.EndPosition.Y); } } else { textArea.Document.FormattingStrategy.IndentLines(textArea, 0, textArea.Document.TotalNumberOfLines - 1); } textArea.EndUpdate(); textArea.Refresh(); } } public class Backspace : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.SelectionManager.HasSomethingSelected) { Delete.DeleteSelection(textArea); } else { if (textArea.Caret.Offset > 0 && !textArea.IsReadOnly(textArea.Caret.Offset - 1)) { textArea.BeginUpdate(); int curLineNr = textArea.Document.GetLineNumberForOffset(textArea.Caret.Offset); int curLineOffset = textArea.Document.GetLineSegment(curLineNr).Offset; if (curLineOffset == textArea.Caret.Offset) { LineSegment line = textArea.Document.GetLineSegment(curLineNr - 1); bool lastLine = curLineNr == textArea.Document.TotalNumberOfLines; int lineEndOffset = line.Offset + line.Length; int lineLength = line.Length; textArea.Document.Remove(lineEndOffset, curLineOffset - lineEndOffset); textArea.Caret.Position = new TextLocation(lineLength, curLineNr - 1); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToEnd, new TextLocation(0, curLineNr - 1))); } else { int caretOffset = textArea.Caret.Offset - 1; textArea.Caret.Position = textArea.Document.OffsetToPosition(caretOffset); textArea.Document.Remove(caretOffset, 1); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToLineEnd, new TextLocation(textArea.Caret.Offset - textArea.Document.GetLineSegment(curLineNr).Offset, curLineNr))); } textArea.EndUpdate(); } } } } public class Delete : AbstractEditAction { internal static void DeleteSelection(TextArea textArea) { Debug.Assert(textArea.SelectionManager.HasSomethingSelected); if (textArea.SelectionManager.SelectionIsReadonly) return; textArea.BeginUpdate(); textArea.Caret.Position = textArea.SelectionManager.SelectionCollection[0].StartPosition; textArea.SelectionManager.RemoveSelectedText(); textArea.ScrollToCaret(); textArea.EndUpdate(); } /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.SelectionManager.HasSomethingSelected) { DeleteSelection(textArea); } else { if (textArea.IsReadOnly(textArea.Caret.Offset)) return; if (textArea.Caret.Offset < textArea.Document.TextLength) { textArea.BeginUpdate(); int curLineNr = textArea.Document.GetLineNumberForOffset(textArea.Caret.Offset); LineSegment curLine = textArea.Document.GetLineSegment(curLineNr); if (curLine.Offset + curLine.Length == textArea.Caret.Offset) { if (curLineNr + 1 < textArea.Document.TotalNumberOfLines) { LineSegment nextLine = textArea.Document.GetLineSegment(curLineNr + 1); textArea.Document.Remove(textArea.Caret.Offset, nextLine.Offset - textArea.Caret.Offset); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToEnd, new TextLocation(0, curLineNr))); } } else { textArea.Document.Remove(textArea.Caret.Offset, 1); // textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToLineEnd, new TextLocation(textArea.Caret.Offset - textArea.Document.GetLineSegment(curLineNr).Offset, curLineNr))); } textArea.UpdateMatchingBracket(); textArea.EndUpdate(); } } } } public class MovePageDown : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { int curLineNr = textArea.Caret.Line; int requestedLineNumber = Math.Min(textArea.Document.GetNextVisibleLineAbove(curLineNr, textArea.TextView.VisibleLineCount), textArea.Document.TotalNumberOfLines - 1); if (curLineNr != requestedLineNumber) { textArea.Caret.Position = new TextLocation(0, requestedLineNumber); textArea.SetCaretToDesiredColumn(); } } } public class MovePageUp : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { int curLineNr = textArea.Caret.Line; int requestedLineNumber = Math.Max(textArea.Document.GetNextVisibleLineBelow(curLineNr, textArea.TextView.VisibleLineCount), 0); if (curLineNr != requestedLineNumber) { textArea.Caret.Position = new TextLocation(0, requestedLineNumber); textArea.SetCaretToDesiredColumn(); } } } public class Return : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } textArea.BeginUpdate(); textArea.Document.UndoStack.StartUndoGroup(); try { if (textArea.HandleKeyPress('\n')) return; textArea.InsertString(Environment.NewLine); int curLineNr = textArea.Caret.Line; textArea.Document.FormattingStrategy.FormatLine(textArea, curLineNr, textArea.Caret.Offset, '\n'); textArea.SetDesiredColumn(); textArea.Document.UpdateQueue.Clear(); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToEnd, new TextLocation(0, curLineNr - 1))); } finally { textArea.Document.UndoStack.EndUndoGroup(); textArea.EndUpdate(); } } } public class ToggleEditMode : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.Document.ReadOnly) { return; } switch (textArea.Caret.CaretMode) { case CaretMode.InsertMode: textArea.Caret.CaretMode = CaretMode.OverwriteMode; break; case CaretMode.OverwriteMode: textArea.Caret.CaretMode = CaretMode.InsertMode; break; } } } public class Undo : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { textArea.MotherTextEditorControl.Undo(); } } public class Redo : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { textArea.MotherTextEditorControl.Redo(); } } /// /// handles the ctrl-backspace key /// functionality attempts to roughly mimic MS Developer studio /// I will implement this as deleting back to the point that ctrl-leftarrow would /// take you to /// public class WordBackspace : AbstractEditAction { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { // if anything is selected we will just delete it first if (textArea.SelectionManager.HasSomethingSelected) { Delete.DeleteSelection(textArea); return; } textArea.BeginUpdate(); // now delete from the caret to the beginning of the word LineSegment line = textArea.Document.GetLineSegmentForOffset(textArea.Caret.Offset); // if we are not at the beginning of a line if (textArea.Caret.Offset > line.Offset) { int prevWordStart = TextUtilities.FindPrevWordStart(textArea.Document, textArea.Caret.Offset); if (prevWordStart < textArea.Caret.Offset) { if (!textArea.IsReadOnly(prevWordStart, textArea.Caret.Offset - prevWordStart)) { textArea.Document.Remove(prevWordStart, textArea.Caret.Offset - prevWordStart); textArea.Caret.Position = textArea.Document.OffsetToPosition(prevWordStart); } } } // if we are now at the beginning of a line if (textArea.Caret.Offset == line.Offset) { // if we are not on the first line int curLineNr = textArea.Document.GetLineNumberForOffset(textArea.Caret.Offset); if (curLineNr > 0) { // move to the end of the line above LineSegment lineAbove = textArea.Document.GetLineSegment(curLineNr - 1); int endOfLineAbove = lineAbove.Offset + lineAbove.Length; int charsToDelete = textArea.Caret.Offset - endOfLineAbove; if (!textArea.IsReadOnly(endOfLineAbove, charsToDelete)) { textArea.Document.Remove(endOfLineAbove, charsToDelete); textArea.Caret.Position = textArea.Document.OffsetToPosition(endOfLineAbove); } } } textArea.SetDesiredColumn(); textArea.EndUpdate(); // if there are now less lines, we need this or there are redraw problems textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToEnd, new TextLocation(0, textArea.Document.GetLineNumberForOffset(textArea.Caret.Offset)))); textArea.Document.CommitUpdate(); } } /// /// handles the ctrl-delete key /// functionality attempts to mimic MS Developer studio /// I will implement this as deleting forwardto the point that /// ctrl-leftarrow would take you to /// public class DeleteWord : Delete { /// /// Executes this edit action /// /// The which is used for callback purposes public override void Execute(TextArea textArea) { if (textArea.SelectionManager.HasSomethingSelected) { DeleteSelection(textArea); return; } // if anything is selected we will just delete it first textArea.BeginUpdate(); // now delete from the caret to the beginning of the word LineSegment line = textArea.Document.GetLineSegmentForOffset(textArea.Caret.Offset); if(textArea.Caret.Offset == line.Offset + line.Length) { // if we are at the end of a line base.Execute(textArea); } else { int nextWordStart = TextUtilities.FindNextWordStart(textArea.Document, textArea.Caret.Offset); if(nextWordStart > textArea.Caret.Offset) { if (!textArea.IsReadOnly(textArea.Caret.Offset, nextWordStart - textArea.Caret.Offset)) { textArea.Document.Remove(textArea.Caret.Offset, nextWordStart - textArea.Caret.Offset); // cursor never moves with this command } } } textArea.UpdateMatchingBracket(); textArea.EndUpdate(); // if there are now less lines, we need this or there are redraw problems textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToEnd, new TextLocation(0, textArea.Document.GetLineNumberForOffset(textArea.Caret.Offset)))); textArea.Document.CommitUpdate(); } } public class DeleteLine : AbstractEditAction { public override void Execute(TextArea textArea) { int lineNr = textArea.Caret.Line; LineSegment line = textArea.Document.GetLineSegment(lineNr); if (textArea.IsReadOnly(line.Offset, line.Length)) return; textArea.Document.Remove(line.Offset, line.TotalLength); textArea.Caret.Position = textArea.Document.OffsetToPosition(line.Offset); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToEnd, new TextLocation(0, lineNr))); textArea.UpdateMatchingBracket(); textArea.Document.CommitUpdate(); } } public class DeleteToLineEnd : AbstractEditAction { public override void Execute(TextArea textArea) { int lineNr = textArea.Caret.Line; LineSegment line = textArea.Document.GetLineSegment(lineNr); int numRemove = (line.Offset + line.Length) - textArea.Caret.Offset; if (numRemove > 0 && !textArea.IsReadOnly(textArea.Caret.Offset, numRemove)) { textArea.Document.Remove(textArea.Caret.Offset, numRemove); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, new TextLocation(0, lineNr))); textArea.Document.CommitUpdate(); } } } public class GotoMatchingBrace : AbstractEditAction { public override void Execute(TextArea textArea) { BracketHighlight highlight = textArea.FindMatchingBracketHighlight(); if (highlight != null) { TextLocation p1 = new TextLocation(highlight.CloseBrace.X + 1, highlight.CloseBrace.Y); TextLocation p2 = new TextLocation(highlight.OpenBrace.X + 1, highlight.OpenBrace.Y); if (p1 == textArea.Caret.Position) { if (textArea.Document.TextEditorProperties.BracketMatchingStyle == BracketMatchingStyle.After) { textArea.Caret.Position = p2; } else { textArea.Caret.Position = new TextLocation(p2.X - 1, p2.Y); } } else { if (textArea.Document.TextEditorProperties.BracketMatchingStyle == BracketMatchingStyle.After) { textArea.Caret.Position = p1; } else { textArea.Caret.Position = new TextLocation(p1.X - 1, p1.Y); } } textArea.SetDesiredColumn(); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Actions/SelectionActions.cs ================================================ // // // // // $Revision: 2659 $ // using System; using System.Drawing; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Actions { public class ShiftCaretRight : CaretRight { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftCaretLeft : CaretLeft { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftCaretUp : CaretUp { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftCaretDown : CaretDown { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftWordRight : WordRight { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftWordLeft : WordLeft { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftHome : Home { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftEnd : End { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftMoveToStart : MoveToStart { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftMoveToEnd : MoveToEnd { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftMovePageUp : MovePageUp { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class ShiftMovePageDown : MovePageDown { public override void Execute(TextArea textArea) { TextLocation oldCaretPos = textArea.Caret.Position; base.Execute(textArea); textArea.AutoClearSelection = false; textArea.SelectionManager.ExtendSelection(oldCaretPos, textArea.Caret.Position); } } public class SelectWholeDocument : AbstractEditAction { public override void Execute(TextArea textArea) { textArea.AutoClearSelection = false; TextLocation startPoint = new TextLocation(0, 0); TextLocation endPoint = textArea.Document.OffsetToPosition(textArea.Document.TextLength); if (textArea.SelectionManager.HasSomethingSelected) { if (textArea.SelectionManager.SelectionCollection[0].StartPosition == startPoint && textArea.SelectionManager.SelectionCollection[0].EndPosition == endPoint) { return; } } textArea.Caret.Position = textArea.SelectionManager.NextValidPosition(endPoint.Y); textArea.SelectionManager.ExtendSelection(startPoint, endPoint); // after a SelectWholeDocument selection, the caret is placed correctly, // but it is not positioned internally. The effect is when the cursor // is moved up or down a line, the caret will take on the column that // it was in before the SelectWholeDocument textArea.SetDesiredColumn(); } } public class ClearAllSelections : AbstractEditAction { public override void Execute(TextArea textArea) { textArea.SelectionManager.ClearSelection(); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/AbstractSegment.cs ================================================ // // // // // $Revision: 1965 $ // using System; namespace ICSharpCode.TextEditor.Document { /// /// This interface is used to describe a span inside a text sequence /// public class AbstractSegment : ISegment { [CLSCompliant(false)] protected int offset = -1; [CLSCompliant(false)] protected int length = -1; #region ICSharpCode.TextEditor.Document.ISegment interface implementation public virtual int Offset { get { return offset; } set { offset = value; } } public virtual int Length { get { return length; } set { length = value; } } #endregion public override string ToString() { return String.Format("[AbstractSegment: Offset = {0}, Length = {1}]", Offset, Length); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs ================================================ // // // // // $Revision: 3272 $ // using System; using System.Drawing; using SWF = System.Windows.Forms; namespace ICSharpCode.TextEditor.Document { /// /// Description of Bookmark. /// public class Bookmark { IDocument document; TextAnchor anchor; TextLocation location; bool isEnabled = true; public IDocument Document { get { return document; } set { if (document != value) { if (anchor != null) { location = anchor.Location; anchor = null; } document = value; CreateAnchor(); OnDocumentChanged(EventArgs.Empty); } } } void CreateAnchor() { if (document != null) { LineSegment line = document.GetLineSegment(Math.Max(0, Math.Min(location.Line, document.TotalNumberOfLines-1))); anchor = line.CreateAnchor(Math.Max(0, Math.Min(location.Column, line.Length))); // after insertion: keep bookmarks after the initial whitespace (see DefaultFormattingStrategy.SmartReplaceLine) anchor.MovementType = AnchorMovementType.AfterInsertion; anchor.Deleted += AnchorDeleted; } } void AnchorDeleted(object sender, EventArgs e) { document.BookmarkManager.RemoveMark(this); } /// /// Gets the TextAnchor used for this bookmark. /// Is null if the bookmark is not connected to a document. /// public TextAnchor Anchor { get { return anchor; } } public TextLocation Location { get { if (anchor != null) return anchor.Location; else return location; } set { location = value; CreateAnchor(); } } public event EventHandler DocumentChanged; protected virtual void OnDocumentChanged(EventArgs e) { if (DocumentChanged != null) { DocumentChanged(this, e); } } public bool IsEnabled { get { return isEnabled; } set { if (isEnabled != value) { isEnabled = value; if (document != null) { document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, LineNumber)); document.CommitUpdate(); } OnIsEnabledChanged(EventArgs.Empty); } } } public event EventHandler IsEnabledChanged; protected virtual void OnIsEnabledChanged(EventArgs e) { if (IsEnabledChanged != null) { IsEnabledChanged(this, e); } } public int LineNumber { get { if (anchor != null) return anchor.LineNumber; else return location.Line; } } public int ColumnNumber { get { if (anchor != null) return anchor.ColumnNumber; else return location.Column; } } /// /// Gets if the bookmark can be toggled off using the 'set/unset bookmark' command. /// public virtual bool CanToggle { get { return true; } } public Bookmark(IDocument document, TextLocation location) : this(document, location, true) { } public Bookmark(IDocument document, TextLocation location, bool isEnabled) { this.document = document; this.isEnabled = isEnabled; this.Location = location; } public virtual bool Click(SWF.Control parent, SWF.MouseEventArgs e) { if (e.Button == SWF.MouseButtons.Left && CanToggle) { document.BookmarkManager.RemoveMark(this); return true; } return false; } public virtual void Draw(IconBarMargin margin, Graphics g, Point p) { margin.DrawBookmark(g, p.Y, isEnabled); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/BookmarkEventHandler.cs ================================================ // // // // // $Revision: 915 $ // using System; namespace ICSharpCode.TextEditor.Document { public delegate void BookmarkEventHandler(object sender, BookmarkEventArgs e); /// /// Description of BookmarkEventHandler. /// public class BookmarkEventArgs : EventArgs { Bookmark bookmark; public Bookmark Bookmark { get { return bookmark; } } public BookmarkEventArgs(Bookmark bookmark) { this.bookmark = bookmark; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/BookmarkManager.cs ================================================ // // // // // $Revision: 3272 $ // using System; using System.Collections.Generic; using System.Collections.ObjectModel; using ICSharpCode.TextEditor.Util; namespace ICSharpCode.TextEditor.Document { public interface IBookmarkFactory { Bookmark CreateBookmark(IDocument document, TextLocation location); } /// /// This class handles the bookmarks for a buffer /// public class BookmarkManager { IDocument document; #if DEBUG IList bookmark = new CheckedList(); #else List bookmark = new List(); #endif /// /// Contains all bookmarks /// public ReadOnlyCollection Marks { get { return new ReadOnlyCollection(bookmark); } } public IDocument Document { get { return document; } } /// /// Creates a new instance of /// internal BookmarkManager(IDocument document, LineManager lineTracker) { this.document = document; } /// /// Gets/Sets the bookmark factory used to create bookmarks for "ToggleMarkAt". /// public IBookmarkFactory Factory { get; set;} /// /// Sets the mark at the line location.Line if it is not set, if the /// line is already marked the mark is cleared. /// public void ToggleMarkAt(TextLocation location) { Bookmark newMark; if (Factory != null) { newMark = Factory.CreateBookmark(document, location); } else { newMark = new Bookmark(document, location); } Type newMarkType = newMark.GetType(); for (int i = 0; i < bookmark.Count; ++i) { Bookmark mark = bookmark[i]; if (mark.LineNumber == location.Line && mark.CanToggle && mark.GetType() == newMarkType) { bookmark.RemoveAt(i); OnRemoved(new BookmarkEventArgs(mark)); return; } } bookmark.Add(newMark); OnAdded(new BookmarkEventArgs(newMark)); } public void AddMark(Bookmark mark) { bookmark.Add(mark); OnAdded(new BookmarkEventArgs(mark)); } public void RemoveMark(Bookmark mark) { bookmark.Remove(mark); OnRemoved(new BookmarkEventArgs(mark)); } public void RemoveMarks(Predicate predicate) { for (int i = 0; i < bookmark.Count; ++i) { Bookmark bm = bookmark[i]; if (predicate(bm)) { bookmark.RemoveAt(i--); OnRemoved(new BookmarkEventArgs(bm)); } } } /// /// true, if a mark at mark exists, otherwise false /// public bool IsMarked(int lineNr) { for (int i = 0; i < bookmark.Count; ++i) { if (bookmark[i].LineNumber == lineNr) { return true; } } return false; } /// /// Clears all bookmark /// public void Clear() { foreach (Bookmark mark in bookmark) { OnRemoved(new BookmarkEventArgs(mark)); } bookmark.Clear(); } /// /// The lowest mark, if no marks exists it returns -1 /// public Bookmark GetFirstMark(Predicate predicate) { if (bookmark.Count < 1) { return null; } Bookmark first = null; for (int i = 0; i < bookmark.Count; ++i) { if (predicate(bookmark[i]) && bookmark[i].IsEnabled && (first == null || bookmark[i].LineNumber < first.LineNumber)) { first = bookmark[i]; } } return first; } /// /// The highest mark, if no marks exists it returns -1 /// public Bookmark GetLastMark(Predicate predicate) { if (bookmark.Count < 1) { return null; } Bookmark last = null; for (int i = 0; i < bookmark.Count; ++i) { if (predicate(bookmark[i]) && bookmark[i].IsEnabled && (last == null || bookmark[i].LineNumber > last.LineNumber)) { last = bookmark[i]; } } return last; } bool AcceptAnyMarkPredicate(Bookmark mark) { return true; } public Bookmark GetNextMark(int curLineNr) { return GetNextMark(curLineNr, AcceptAnyMarkPredicate); } /// /// returns first mark higher than lineNr /// /// /// returns the next mark > cur, if it not exists it returns FirstMark() /// public Bookmark GetNextMark(int curLineNr, Predicate predicate) { if (bookmark.Count == 0) { return null; } Bookmark next = GetFirstMark(predicate); foreach (Bookmark mark in bookmark) { if (predicate(mark) && mark.IsEnabled && mark.LineNumber > curLineNr) { if (mark.LineNumber < next.LineNumber || next.LineNumber <= curLineNr) { next = mark; } } } return next; } public Bookmark GetPrevMark(int curLineNr) { return GetPrevMark(curLineNr, AcceptAnyMarkPredicate); } /// /// returns first mark lower than lineNr /// /// /// returns the next mark lower than cur, if it not exists it returns LastMark() /// public Bookmark GetPrevMark(int curLineNr, Predicate predicate) { if (bookmark.Count == 0) { return null; } Bookmark prev = GetLastMark(predicate); foreach (Bookmark mark in bookmark) { if (predicate(mark) && mark.IsEnabled && mark.LineNumber < curLineNr) { if (mark.LineNumber > prev.LineNumber || prev.LineNumber >= curLineNr) { prev = mark; } } } return prev; } protected virtual void OnRemoved(BookmarkEventArgs e) { if (Removed != null) { Removed(this, e); } } protected virtual void OnAdded(BookmarkEventArgs e) { if (Added != null) { Added(this, e); } } public event BookmarkEventHandler Removed; public event BookmarkEventHandler Added; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/BookmarkManagerMemento.cs ================================================ // // // // // $Revision: 915 $ // using System; using System.Collections.Generic; using System.Xml; namespace ICSharpCode.TextEditor.Document { /// /// This class is used for storing the state of a bookmark manager /// public class BookmarkManagerMemento { List bookmarks = new List(); /// /// Contains all bookmarks as int values /// public List Bookmarks { get { return bookmarks; } set { bookmarks = value; } } /// /// Validates all bookmarks if they're in range of the document. /// (removing all bookmarks < 0 and bookmarks > max. line number /// public void CheckMemento(IDocument document) { for (int i = 0; i < bookmarks.Count; ++i) { int mark = (int)bookmarks[i]; if (mark < 0 || mark >= document.TotalNumberOfLines) { bookmarks.RemoveAt(i); --i; } } } /// /// Creates a new instance of /// public BookmarkManagerMemento() { } /// /// Creates a new instance of /// public BookmarkManagerMemento(XmlElement element) { foreach (XmlElement el in element.ChildNodes) { bookmarks.Add(Int32.Parse(el.Attributes["line"].InnerText)); } } /// /// Creates a new instance of /// public BookmarkManagerMemento(List bookmarks) { this.bookmarks = bookmarks; } /// /// Converts a xml element to a object /// public object FromXmlElement(XmlElement element) { return new BookmarkManagerMemento(element); } /// /// Converts this to a xml element /// public XmlElement ToXmlElement(XmlDocument doc) { XmlElement bookmarknode = doc.CreateElement("Bookmarks"); foreach (int line in bookmarks) { XmlElement markNode = doc.CreateElement("Mark"); XmlAttribute lineAttr = doc.CreateAttribute("line"); lineAttr.InnerText = line.ToString(); markNode.Attributes.Append(lineAttr); bookmarknode.AppendChild(markNode); } return bookmarknode; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/DefaultDocument.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using ICSharpCode.TextEditor.Undo; namespace ICSharpCode.TextEditor.Document { /// /// Describes the caret marker /// public enum LineViewerStyle { /// /// No line viewer will be displayed /// None, /// /// The row in which the caret is will be marked /// FullRow } /// /// Describes the indent style /// public enum IndentStyle { /// /// No indentation occurs /// None, /// /// The indentation from the line above will be /// taken to indent the curent line /// Auto, /// /// Inteligent, context sensitive indentation will occur /// Smart } /// /// Describes the bracket highlighting style /// public enum BracketHighlightingStyle { /// /// Brackets won't be highlighted /// None, /// /// Brackets will be highlighted if the caret is on the bracket /// OnBracket, /// /// Brackets will be highlighted if the caret is after the bracket /// AfterBracket } /// /// Describes the selection mode of the text area /// public enum DocumentSelectionMode { /// /// The 'normal' selection mode. /// Normal, /// /// Selections will be added to the current selection or new /// ones will be created (multi-select mode) /// Additive } /// /// The default implementation. /// internal sealed class DefaultDocument : IDocument { bool readOnly = false; LineManager lineTrackingStrategy; BookmarkManager bookmarkManager; ITextBufferStrategy textBufferStrategy; IFormattingStrategy formattingStrategy; FoldingManager foldingManager; UndoStack undoStack = new UndoStack(); ITextEditorProperties textEditorProperties = new DefaultTextEditorProperties(); MarkerStrategy markerStrategy; public LineManager LineManager { get { return lineTrackingStrategy; } set { lineTrackingStrategy = value; } } public event EventHandler LineLengthChanged { add { lineTrackingStrategy.LineLengthChanged += value; } remove { lineTrackingStrategy.LineLengthChanged -= value; } } public event EventHandler LineCountChanged { add { lineTrackingStrategy.LineCountChanged += value; } remove { lineTrackingStrategy.LineCountChanged -= value; } } public event EventHandler LineDeleted { add { lineTrackingStrategy.LineDeleted += value; } remove { lineTrackingStrategy.LineDeleted -= value; } } public MarkerStrategy MarkerStrategy { get { return markerStrategy; } set { markerStrategy = value; } } public ITextEditorProperties TextEditorProperties { get { return textEditorProperties; } set { textEditorProperties = value; } } public UndoStack UndoStack { get { return undoStack; } } public IList LineSegmentCollection { get { return lineTrackingStrategy.LineSegmentCollection; } } public bool ReadOnly { get { return readOnly; } set { readOnly = value; } } public ITextBufferStrategy TextBufferStrategy { get { return textBufferStrategy; } set { textBufferStrategy = value; } } public IFormattingStrategy FormattingStrategy { get { return formattingStrategy; } set { formattingStrategy = value; } } public FoldingManager FoldingManager { get { return foldingManager; } set { foldingManager = value; } } public IHighlightingStrategy HighlightingStrategy { get { return lineTrackingStrategy.HighlightingStrategy; } set { lineTrackingStrategy.HighlightingStrategy = value; } } public int TextLength { get { return textBufferStrategy.Length; } } public BookmarkManager BookmarkManager { get { return bookmarkManager; } set { bookmarkManager = value; } } public string TextContent { get { return GetText(0, textBufferStrategy.Length); } set { Debug.Assert(textBufferStrategy != null); Debug.Assert(lineTrackingStrategy != null); OnDocumentAboutToBeChanged(new DocumentEventArgs(this, 0, 0, value)); textBufferStrategy.SetContent(value); lineTrackingStrategy.SetContent(value); undoStack.ClearAll(); OnDocumentChanged(new DocumentEventArgs(this, 0, 0, value)); OnTextContentChanged(EventArgs.Empty); } } public void Insert(int offset, string text) { if (readOnly) { return; } OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, -1, text)); textBufferStrategy.Insert(offset, text); lineTrackingStrategy.Insert(offset, text); undoStack.Push(new UndoableInsert(this, offset, text)); OnDocumentChanged(new DocumentEventArgs(this, offset, -1, text)); } public void Remove(int offset, int length) { if (readOnly) { return; } OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, length)); undoStack.Push(new UndoableDelete(this, offset, GetText(offset, length))); textBufferStrategy.Remove(offset, length); lineTrackingStrategy.Remove(offset, length); OnDocumentChanged(new DocumentEventArgs(this, offset, length)); } public void Replace(int offset, int length, string text) { if (readOnly) { return; } OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, length, text)); undoStack.Push(new UndoableReplace(this, offset, GetText(offset, length), text)); textBufferStrategy.Replace(offset, length, text); lineTrackingStrategy.Replace(offset, length, text); OnDocumentChanged(new DocumentEventArgs(this, offset, length, text)); } public char GetCharAt(int offset) { return textBufferStrategy.GetCharAt(offset); } public string GetText(int offset, int length) { #if DEBUG if (length < 0) throw new ArgumentOutOfRangeException("length", length, "length < 0"); #endif return textBufferStrategy.GetText(offset, length); } public string GetText(ISegment segment) { return GetText(segment.Offset, segment.Length); } public int TotalNumberOfLines { get { return lineTrackingStrategy.TotalNumberOfLines; } } public int GetLineNumberForOffset(int offset) { return lineTrackingStrategy.GetLineNumberForOffset(offset); } public LineSegment GetLineSegmentForOffset(int offset) { return lineTrackingStrategy.GetLineSegmentForOffset(offset); } public LineSegment GetLineSegment(int line) { return lineTrackingStrategy.GetLineSegment(line); } public int GetFirstLogicalLine(int lineNumber) { return lineTrackingStrategy.GetFirstLogicalLine(lineNumber); } public int GetLastLogicalLine(int lineNumber) { return lineTrackingStrategy.GetLastLogicalLine(lineNumber); } public int GetVisibleLine(int lineNumber) { return lineTrackingStrategy.GetVisibleLine(lineNumber); } // public int GetVisibleColumn(int logicalLine, int logicalColumn) // { // return lineTrackingStrategy.GetVisibleColumn(logicalLine, logicalColumn); // } // public int GetNextVisibleLineAbove(int lineNumber, int lineCount) { return lineTrackingStrategy.GetNextVisibleLineAbove(lineNumber, lineCount); } public int GetNextVisibleLineBelow(int lineNumber, int lineCount) { return lineTrackingStrategy.GetNextVisibleLineBelow(lineNumber, lineCount); } public TextLocation OffsetToPosition(int offset) { int lineNr = GetLineNumberForOffset(offset); LineSegment line = GetLineSegment(lineNr); return new TextLocation(offset - line.Offset, lineNr); } public int PositionToOffset(TextLocation p) { if (p.Y >= this.TotalNumberOfLines) { return 0; } LineSegment line = GetLineSegment(p.Y); return Math.Min(this.TextLength, line.Offset + Math.Min(line.Length, p.X)); } public void UpdateSegmentListOnDocumentChange(List list, DocumentEventArgs e) where T : ISegment { int removedCharacters = e.Length > 0 ? e.Length : 0; int insertedCharacters = e.Text != null ? e.Text.Length : 0; for (int i = 0; i < list.Count; ++i) { ISegment s = list[i]; int segmentStart = s.Offset; int segmentEnd = s.Offset + s.Length; if (e.Offset <= segmentStart) { segmentStart -= removedCharacters; if (segmentStart < e.Offset) segmentStart = e.Offset; } if (e.Offset < segmentEnd) { segmentEnd -= removedCharacters; if (segmentEnd < e.Offset) segmentEnd = e.Offset; } Debug.Assert(segmentStart <= segmentEnd); if (segmentStart == segmentEnd) { list.RemoveAt(i); --i; continue; } if (e.Offset <= segmentStart) segmentStart += insertedCharacters; if (e.Offset < segmentEnd) segmentEnd += insertedCharacters; Debug.Assert(segmentStart < segmentEnd); s.Offset = segmentStart; s.Length = segmentEnd - segmentStart; } } void OnDocumentAboutToBeChanged(DocumentEventArgs e) { if (DocumentAboutToBeChanged != null) { DocumentAboutToBeChanged(this, e); } } void OnDocumentChanged(DocumentEventArgs e) { if (DocumentChanged != null) { DocumentChanged(this, e); } } public event DocumentEventHandler DocumentAboutToBeChanged; public event DocumentEventHandler DocumentChanged; // UPDATE STUFF List updateQueue = new List(); public List UpdateQueue { get { return updateQueue; } } public void RequestUpdate(TextAreaUpdate update) { if (updateQueue.Count == 1 && updateQueue[0].TextAreaUpdateType == TextAreaUpdateType.WholeTextArea) { // if we're going to update the whole text area, we don't need to store detail updates return; } if (update.TextAreaUpdateType == TextAreaUpdateType.WholeTextArea) { // if we're going to update the whole text area, we don't need to store detail updates updateQueue.Clear(); } updateQueue.Add(update); } public void CommitUpdate() { if (UpdateCommited != null) { UpdateCommited(this, EventArgs.Empty); } } void OnTextContentChanged(EventArgs e) { if (TextContentChanged != null) { TextContentChanged(this, e); } } public event EventHandler UpdateCommited; public event EventHandler TextContentChanged; [Conditional("DEBUG")] internal static void ValidatePosition(IDocument document, TextLocation position) { document.GetLineSegment(position.Line); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/DefaultTextEditorProperties.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Drawing; using System.Text; namespace ICSharpCode.TextEditor.Document { public enum BracketMatchingStyle { Before, After } public class DefaultTextEditorProperties : ITextEditorProperties { int tabIndent = 4; int indentationSize = 4; IndentStyle indentStyle = IndentStyle.Smart; DocumentSelectionMode documentSelectionMode = DocumentSelectionMode.Normal; Encoding encoding = System.Text.Encoding.UTF8; BracketMatchingStyle bracketMatchingStyle = BracketMatchingStyle.After; FontContainer fontContainer; static Font DefaultFont; public DefaultTextEditorProperties() { if (DefaultFont == null) { DefaultFont = new Font("Courier New", 10); } this.fontContainer = new FontContainer(DefaultFont); } bool allowCaretBeyondEOL = false; bool showMatchingBracket = true; bool showLineNumbers = true; bool showSpaces = false; bool showTabs = false; bool showEOLMarker = false; bool showInvalidLines = false; bool isIconBarVisible = false; bool enableFolding = true; bool showHorizontalRuler = false; bool showVerticalRuler = true; bool convertTabsToSpaces = false; System.Drawing.Text.TextRenderingHint textRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault; bool mouseWheelScrollDown = true; bool mouseWheelTextZoom = true; bool hideMouseCursor = false; bool cutCopyWholeLine = true; int verticalRulerRow = 80; LineViewerStyle lineViewerStyle = LineViewerStyle.None; string lineTerminator = "\r\n"; bool autoInsertCurlyBracket = true; bool supportReadOnlySegments = false; public int TabIndent { get { return tabIndent; } set { tabIndent = value; } } public int IndentationSize { get { return indentationSize; } set { indentationSize = value; } } public IndentStyle IndentStyle { get { return indentStyle; } set { indentStyle = value; } } public DocumentSelectionMode DocumentSelectionMode { get { return documentSelectionMode; } set { documentSelectionMode = value; } } public bool AllowCaretBeyondEOL { get { return allowCaretBeyondEOL; } set { allowCaretBeyondEOL = value; } } public bool ShowMatchingBracket { get { return showMatchingBracket; } set { showMatchingBracket = value; } } public bool ShowLineNumbers { get { return showLineNumbers; } set { showLineNumbers = value; } } public bool ShowSpaces { get { return showSpaces; } set { showSpaces = value; } } public bool ShowTabs { get { return showTabs; } set { showTabs = value; } } public bool ShowEOLMarker { get { return showEOLMarker; } set { showEOLMarker = value; } } public bool ShowInvalidLines { get { return showInvalidLines; } set { showInvalidLines = value; } } public bool IsIconBarVisible { get { return isIconBarVisible; } set { isIconBarVisible = value; } } public bool EnableFolding { get { return enableFolding; } set { enableFolding = value; } } public bool ShowHorizontalRuler { get { return showHorizontalRuler; } set { showHorizontalRuler = value; } } public bool ShowVerticalRuler { get { return showVerticalRuler; } set { showVerticalRuler = value; } } public bool ConvertTabsToSpaces { get { return convertTabsToSpaces; } set { convertTabsToSpaces = value; } } public System.Drawing.Text.TextRenderingHint TextRenderingHint { get { return textRenderingHint; } set { textRenderingHint = value; } } public bool MouseWheelScrollDown { get { return mouseWheelScrollDown; } set { mouseWheelScrollDown = value; } } public bool MouseWheelTextZoom { get { return mouseWheelTextZoom; } set { mouseWheelTextZoom = value; } } public bool HideMouseCursor { get { return hideMouseCursor; } set { hideMouseCursor = value; } } public bool CutCopyWholeLine { get { return cutCopyWholeLine; } set { cutCopyWholeLine = value; } } public Encoding Encoding { get { return encoding; } set { encoding = value; } } public int VerticalRulerRow { get { return verticalRulerRow; } set { verticalRulerRow = value; } } public LineViewerStyle LineViewerStyle { get { return lineViewerStyle; } set { lineViewerStyle = value; } } public string LineTerminator { get { return lineTerminator; } set { lineTerminator = value; } } public bool AutoInsertCurlyBracket { get { return autoInsertCurlyBracket; } set { autoInsertCurlyBracket = value; } } public Font Font { get { return fontContainer.DefaultFont; } set { fontContainer.DefaultFont = value; } } public FontContainer FontContainer { get { return fontContainer; } } public BracketMatchingStyle BracketMatchingStyle { get { return bracketMatchingStyle; } set { bracketMatchingStyle = value; } } public bool SupportReadOnlySegments { get { return supportReadOnlySegments; } set { supportReadOnlySegments = value; } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/DocumentEventArgs.cs ================================================ // // // // // $Revision: 915 $ // using System; namespace ICSharpCode.TextEditor.Document { /// /// This delegate is used for document events. /// public delegate void DocumentEventHandler(object sender, DocumentEventArgs e); /// /// This class contains more information on a document event /// public class DocumentEventArgs : EventArgs { IDocument document; int offset; int length; string text; /// /// always a valid Document which is related to the Event. /// public IDocument Document { get { return document; } } /// /// -1 if no offset was specified for this event /// public int Offset { get { return offset; } } /// /// null if no text was specified for this event /// public string Text { get { return text; } } /// /// -1 if no length was specified for this event /// public int Length { get { return length; } } /// /// Creates a new instance off /// public DocumentEventArgs(IDocument document) : this(document, -1, -1, null) { } /// /// Creates a new instance off /// public DocumentEventArgs(IDocument document, int offset) : this(document, offset, -1, null) { } /// /// Creates a new instance off /// public DocumentEventArgs(IDocument document, int offset, int length) : this(document, offset, length, null) { } /// /// Creates a new instance off /// public DocumentEventArgs(IDocument document, int offset, int length, string text) { this.document = document; this.offset = offset; this.length = length; this.text = text; } public override string ToString() { return String.Format("[DocumentEventArgs: Document = {0}, Offset = {1}, Text = {2}, Length = {3}]", Document, Offset, Text, Length); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/DocumentFactory.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Text; namespace ICSharpCode.TextEditor.Document { /// /// This interface represents a container which holds a text sequence and /// all necessary information about it. It is used as the base for a text editor. /// public class DocumentFactory { /// /// Creates a new object. Only create /// with this method. /// public IDocument CreateDocument() { DefaultDocument doc = new DefaultDocument(); doc.TextBufferStrategy = new GapTextBufferStrategy(); doc.FormattingStrategy = new DefaultFormattingStrategy(); doc.LineManager = new LineManager(doc, null); doc.FoldingManager = new FoldingManager(doc, doc.LineManager); doc.FoldingManager.FoldingStrategy = null; //new ParserFoldingStrategy(); doc.MarkerStrategy = new MarkerStrategy(doc); doc.BookmarkManager = new BookmarkManager(doc, doc.LineManager); return doc; } /// /// Creates a new document and loads the given file /// public IDocument CreateFromTextBuffer(ITextBufferStrategy textBuffer) { DefaultDocument doc = (DefaultDocument)CreateDocument(); doc.TextContent = textBuffer.GetText(0, textBuffer.Length); doc.TextBufferStrategy = textBuffer; return doc; } /// /// Creates a new document and loads the given file /// public IDocument CreateFromFile(string fileName) { IDocument document = CreateDocument(); document.TextContent = Util.FileReader.ReadFileContent(fileName, Encoding.Default); return document; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/FoldingStrategy/FoldMarker.cs ================================================ // // // // // $Revision: 2063 $ // using System; namespace ICSharpCode.TextEditor.Document { public enum FoldType { Unspecified, MemberBody, Region, TypeBody } public class FoldMarker : AbstractSegment, IComparable { bool isFolded = false; string foldText = "..."; FoldType foldType = FoldType.Unspecified; IDocument document = null; int startLine = -1, startColumn, endLine = -1, endColumn; static void GetPointForOffset(IDocument document, int offset, out int line, out int column) { if (offset > document.TextLength) { line = document.TotalNumberOfLines + 1; column = 1; } else if (offset < 0) { line = -1; column = -1; } else { line = document.GetLineNumberForOffset(offset); column = offset - document.GetLineSegment(line).Offset; } } public FoldType FoldType { get { return foldType; } set { foldType = value; } } public int StartLine { get { if (startLine < 0) { GetPointForOffset(document, offset, out startLine, out startColumn); } return startLine; } } public int StartColumn { get { if (startLine < 0) { GetPointForOffset(document, offset, out startLine, out startColumn); } return startColumn; } } public int EndLine { get { if (endLine < 0) { GetPointForOffset(document, offset + length, out endLine, out endColumn); } return endLine; } } public int EndColumn { get { if (endLine < 0) { GetPointForOffset(document, offset + length, out endLine, out endColumn); } return endColumn; } } public override int Offset { get { return base.Offset; } set { base.Offset = value; startLine = -1; endLine = -1; } } public override int Length { get { return base.Length; } set { base.Length = value; endLine = -1; } } public bool IsFolded { get { return isFolded; } set { isFolded = value; } } public string FoldText { get { return foldText; } } public string InnerText { get { return document.GetText(offset, length); } } public FoldMarker(IDocument document, int offset, int length, string foldText, bool isFolded) { this.document = document; this.offset = offset; this.length = length; this.foldText = foldText; this.isFolded = isFolded; } public FoldMarker(IDocument document, int startLine, int startColumn, int endLine, int endColumn) : this(document, startLine, startColumn, endLine, endColumn, FoldType.Unspecified) { } public FoldMarker(IDocument document, int startLine, int startColumn, int endLine, int endColumn, FoldType foldType) : this(document, startLine, startColumn, endLine, endColumn, foldType, "...") { } public FoldMarker(IDocument document, int startLine, int startColumn, int endLine, int endColumn, FoldType foldType, string foldText) : this(document, startLine, startColumn, endLine, endColumn, foldType, foldText, false) { } public FoldMarker(IDocument document, int startLine, int startColumn, int endLine, int endColumn, FoldType foldType, string foldText, bool isFolded) { this.document = document; startLine = Math.Min(document.TotalNumberOfLines - 1, Math.Max(startLine, 0)); ISegment startLineSegment = document.GetLineSegment(startLine); endLine = Math.Min(document.TotalNumberOfLines - 1, Math.Max(endLine, 0)); ISegment endLineSegment = document.GetLineSegment(endLine); // Prevent the region from completely disappearing if (string.IsNullOrEmpty(foldText)) { foldText = "..."; } this.FoldType = foldType; this.foldText = foldText; this.offset = startLineSegment.Offset + Math.Min(startColumn, startLineSegment.Length); this.length = (endLineSegment.Offset + Math.Min(endColumn, endLineSegment.Length)) - this.offset; this.isFolded = isFolded; } public int CompareTo(object o) { if (!(o is FoldMarker)) { throw new ArgumentException(); } FoldMarker f = (FoldMarker)o; if (offset != f.offset) { return offset.CompareTo(f.offset); } return length.CompareTo(f.length); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/FoldingStrategy/FoldingManager.cs ================================================ // // // // // $Revision: 2691 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Text; namespace ICSharpCode.TextEditor.Document { public class FoldingManager { List foldMarker = new List(); List foldMarkerByEnd = new List(); IFoldingStrategy foldingStrategy = null; IDocument document; public IList FoldMarker { get { return foldMarker.AsReadOnly(); } } public IFoldingStrategy FoldingStrategy { get { return foldingStrategy; } set { foldingStrategy = value; } } internal FoldingManager(IDocument document, LineManager lineTracker) { this.document = document; document.DocumentChanged += new DocumentEventHandler(DocumentChanged); // lineTracker.LineCountChanged += new LineManagerEventHandler(LineManagerLineCountChanged); // lineTracker.LineLengthChanged += new LineLengthEventHandler(LineManagerLineLengthChanged); // foldMarker.Add(new FoldMarker(0, 5, 3, 5)); // // foldMarker.Add(new FoldMarker(5, 5, 10, 3)); // foldMarker.Add(new FoldMarker(6, 0, 8, 2)); // // FoldMarker fm1 = new FoldMarker(10, 4, 10, 7); // FoldMarker fm2 = new FoldMarker(10, 10, 10, 14); // // fm1.IsFolded = true; // fm2.IsFolded = true; // // foldMarker.Add(fm1); // foldMarker.Add(fm2); // foldMarker.Sort(); } void DocumentChanged(object sender, DocumentEventArgs e) { int oldCount = foldMarker.Count; document.UpdateSegmentListOnDocumentChange(foldMarker, e); if (oldCount != foldMarker.Count) { document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); } } public List GetFoldingsFromPosition(int line, int column) { List foldings = new List(); if (foldMarker != null) { for (int i = 0; i < foldMarker.Count; ++i) { FoldMarker fm = foldMarker[i]; if ((fm.StartLine == line && column > fm.StartColumn && !(fm.EndLine == line && column >= fm.EndColumn)) || (fm.EndLine == line && column < fm.EndColumn && !(fm.StartLine == line && column <= fm.StartColumn)) || (line > fm.StartLine && line < fm.EndLine)) { foldings.Add(fm); } } } return foldings; } class StartComparer : IComparer { public readonly static StartComparer Instance = new StartComparer(); public int Compare(FoldMarker x, FoldMarker y) { if (x.StartLine < y.StartLine) return -1; else if (x.StartLine == y.StartLine) return x.StartColumn.CompareTo(y.StartColumn); else return 1; } } class EndComparer : IComparer { public readonly static EndComparer Instance = new EndComparer(); public int Compare(FoldMarker x, FoldMarker y) { if (x.EndLine < y.EndLine) return -1; else if (x.EndLine == y.EndLine) return x.EndColumn.CompareTo(y.EndColumn); else return 1; } } List GetFoldingsByStartAfterColumn(int lineNumber, int column, bool forceFolded) { List foldings = new List(); if (foldMarker != null) { int index = foldMarker.BinarySearch( new FoldMarker(document, lineNumber, column, lineNumber, column), StartComparer.Instance); if (index < 0) index = ~index; for (; index < foldMarker.Count; index++) { FoldMarker fm = foldMarker[index]; if (fm.StartLine > lineNumber) break; if (fm.StartColumn <= column) continue; if (!forceFolded || fm.IsFolded) foldings.Add(fm); } } return foldings; } public List GetFoldingsWithStart(int lineNumber) { return GetFoldingsByStartAfterColumn(lineNumber, -1, false); } public List GetFoldedFoldingsWithStart(int lineNumber) { return GetFoldingsByStartAfterColumn(lineNumber, -1, true); } public List GetFoldedFoldingsWithStartAfterColumn(int lineNumber, int column) { return GetFoldingsByStartAfterColumn(lineNumber, column, true); } List GetFoldingsByEndAfterColumn(int lineNumber, int column, bool forceFolded) { List foldings = new List(); if (foldMarker != null) { int index = foldMarkerByEnd.BinarySearch( new FoldMarker(document, lineNumber, column, lineNumber, column), EndComparer.Instance); if (index < 0) index = ~index; for (; index < foldMarkerByEnd.Count; index++) { FoldMarker fm = foldMarkerByEnd[index]; if (fm.EndLine > lineNumber) break; if (fm.EndColumn <= column) continue; if (!forceFolded || fm.IsFolded) foldings.Add(fm); } } return foldings; } public List GetFoldingsWithEnd(int lineNumber) { return GetFoldingsByEndAfterColumn(lineNumber, -1, false); } public List GetFoldedFoldingsWithEnd(int lineNumber) { return GetFoldingsByEndAfterColumn(lineNumber, -1, true); } public bool IsFoldStart(int lineNumber) { return GetFoldingsWithStart(lineNumber).Count > 0; } public bool IsFoldEnd(int lineNumber) { return GetFoldingsWithEnd(lineNumber).Count > 0; } public List GetFoldingsContainsLineNumber(int lineNumber) { List foldings = new List(); if (foldMarker != null) { foreach (FoldMarker fm in foldMarker) { if (fm.StartLine < lineNumber && lineNumber < fm.EndLine) { foldings.Add(fm); } } } return foldings; } public bool IsBetweenFolding(int lineNumber) { return GetFoldingsContainsLineNumber(lineNumber).Count > 0; } public bool IsLineVisible(int lineNumber) { foreach (FoldMarker fm in GetFoldingsContainsLineNumber(lineNumber)) { if (fm.IsFolded) return false; } return true; } public List GetTopLevelFoldedFoldings() { List foldings = new List(); if (foldMarker != null) { Point end = new Point(0, 0); foreach (FoldMarker fm in foldMarker) { if (fm.IsFolded && (fm.StartLine > end.Y || fm.StartLine == end.Y && fm.StartColumn >= end.X)) { foldings.Add(fm); end = new Point(fm.EndColumn, fm.EndLine); } } } return foldings; } public void UpdateFoldings(string fileName, object parseInfo) { UpdateFoldings(foldingStrategy.GenerateFoldMarkers(document, fileName, parseInfo)); } public void UpdateFoldings(List newFoldings) { int oldFoldingsCount = foldMarker.Count; lock (this) { if (newFoldings != null && newFoldings.Count != 0) { newFoldings.Sort(); if (foldMarker.Count == newFoldings.Count) { for (int i = 0; i < foldMarker.Count; ++i) { newFoldings[i].IsFolded = foldMarker[i].IsFolded; } foldMarker = newFoldings; } else { for (int i = 0, j = 0; i < foldMarker.Count && j < newFoldings.Count;) { int n = newFoldings[j].CompareTo(foldMarker[i]); if (n > 0) { ++i; } else { if (n == 0) { newFoldings[j].IsFolded = foldMarker[i].IsFolded; } ++j; } } } } if (newFoldings != null) { foldMarker = newFoldings; foldMarkerByEnd = new List(newFoldings); foldMarkerByEnd.Sort(EndComparer.Instance); } else { foldMarker.Clear(); foldMarkerByEnd.Clear(); } } if (oldFoldingsCount != foldMarker.Count) { document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); document.CommitUpdate(); } } public string SerializeToString() { StringBuilder sb = new StringBuilder(); foreach (FoldMarker marker in this.foldMarker) { sb.Append(marker.Offset);sb.Append("\n"); sb.Append(marker.Length);sb.Append("\n"); sb.Append(marker.FoldText);sb.Append("\n"); sb.Append(marker.IsFolded);sb.Append("\n"); } return sb.ToString(); } public void DeserializeFromString(string str) { try { string[] lines = str.Split('\n'); for (int i = 0; i < lines.Length && lines[i].Length > 0; i += 4) { int offset = Int32.Parse(lines[i]); int length = Int32.Parse(lines[i + 1]); string text = lines[i + 2]; bool isFolded = Boolean.Parse(lines[i + 3]); bool found = false; foreach (FoldMarker marker in foldMarker) { if (marker.Offset == offset && marker.Length == length) { marker.IsFolded = isFolded; found = true; break; } } if (!found) { foldMarker.Add(new FoldMarker(document, offset, length, text, isFolded)); } } if (lines.Length > 0) { NotifyFoldingsChanged(EventArgs.Empty); } } catch (Exception) { } } public void NotifyFoldingsChanged(EventArgs e) { if (FoldingsChanged != null) { FoldingsChanged(this, e); } } public event EventHandler FoldingsChanged; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/FoldingStrategy/IFoldingStrategy.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Document { /// /// This interface is used for the folding capabilities /// of the textarea. /// public interface IFoldingStrategy { /// /// Calculates the fold level of a specific line. /// List GenerateFoldMarkers(IDocument document, string fileName, object parseInformation); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/FoldingStrategy/IndentFoldingStrategy.cs ================================================ // // // // // $Revision: 915 $ // using System; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Document { /// /// A simple folding strategy which calculates the folding level /// using the indent level of the line. /// public class IndentFoldingStrategy : IFoldingStrategy { public List GenerateFoldMarkers(IDocument document, string fileName, object parseInformation) { List l = new List(); Stack offsetStack = new Stack(); Stack textStack = new Stack(); //int level = 0; //foreach (LineSegment segment in document.LineSegmentCollection) { // //} return l; } int GetLevel(IDocument document, int offset) { int level = 0; int spaces = 0; for (int i = offset; i < document.TextLength; ++i) { char c = document.GetCharAt(i); if (c == '\t' || (c == ' ' && ++spaces == 4)) { spaces = 0; ++level; } else { break; } } return level; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/FormattingStrategy/DefaultFormattingStrategy.cs ================================================ // // // // // $Revision: 3272 $ // using System; using System.Text; namespace ICSharpCode.TextEditor.Document { /// /// This class handles the auto and smart indenting in the textbuffer while /// you type. /// public class DefaultFormattingStrategy : IFormattingStrategy { /// /// Creates a new instance off /// public DefaultFormattingStrategy() { } /// /// returns the whitespaces which are before a non white space character in the line line /// as a string. /// protected string GetIndentation(TextArea textArea, int lineNumber) { if (lineNumber < 0 || lineNumber > textArea.Document.TotalNumberOfLines) { throw new ArgumentOutOfRangeException("lineNumber"); } string lineText = TextUtilities.GetLineAsString(textArea.Document, lineNumber); StringBuilder whitespaces = new StringBuilder(); foreach (char ch in lineText) { if (Char.IsWhiteSpace(ch)) { whitespaces.Append(ch); } else { break; } } return whitespaces.ToString(); } /// /// Could be overwritten to define more complex indenting. /// protected virtual int AutoIndentLine(TextArea textArea, int lineNumber) { string indentation = lineNumber != 0 ? GetIndentation(textArea, lineNumber - 1) : ""; if(indentation.Length > 0) { string newLineText = indentation + TextUtilities.GetLineAsString(textArea.Document, lineNumber).Trim(); LineSegment oldLine = textArea.Document.GetLineSegment(lineNumber); SmartReplaceLine(textArea.Document, oldLine, newLineText); } return indentation.Length; } static readonly char[] whitespaceChars = {' ', '\t'}; /// /// Replaces the text in a line. /// If only whitespace at the beginning and end of the line was changed, this method /// only adjusts the whitespace and doesn't replace the other text. /// public static void SmartReplaceLine(IDocument document, LineSegment line, string newLineText) { if (document == null) throw new ArgumentNullException("document"); if (line == null) throw new ArgumentNullException("line"); if (newLineText == null) throw new ArgumentNullException("newLineText"); string newLineTextTrim = newLineText.Trim(whitespaceChars); string oldLineText = document.GetText(line); if (oldLineText == newLineText) return; int pos = oldLineText.IndexOf(newLineTextTrim); if (newLineTextTrim.Length > 0 && pos >= 0) { document.UndoStack.StartUndoGroup(); try { // find whitespace at beginning int startWhitespaceLength = 0; while (startWhitespaceLength < newLineText.Length) { char c = newLineText[startWhitespaceLength]; if (c != ' ' && c != '\t') break; startWhitespaceLength++; } // find whitespace at end int endWhitespaceLength = newLineText.Length - newLineTextTrim.Length - startWhitespaceLength; // replace whitespace sections int lineOffset = line.Offset; document.Replace(lineOffset + pos + newLineTextTrim.Length, line.Length - pos - newLineTextTrim.Length, newLineText.Substring(newLineText.Length - endWhitespaceLength)); document.Replace(lineOffset, pos, newLineText.Substring(0, startWhitespaceLength)); } finally { document.UndoStack.EndUndoGroup(); } } else { document.Replace(line.Offset, line.Length, newLineText); } } /// /// Could be overwritten to define more complex indenting. /// protected virtual int SmartIndentLine(TextArea textArea, int line) { return AutoIndentLine(textArea, line); // smart = autoindent in normal texts } /// /// This function formats a specific line after ch is pressed. /// /// /// the caret delta position the caret will be moved this number /// of bytes (e.g. the number of bytes inserted before the caret, or /// removed, if this number is negative) /// public virtual void FormatLine(TextArea textArea, int line, int cursorOffset, char ch) { if (ch == '\n') { textArea.Caret.Column = IndentLine(textArea, line); } } /// /// This function sets the indentation level in a specific line /// /// /// the number of inserted characters. /// public int IndentLine(TextArea textArea, int line) { textArea.Document.UndoStack.StartUndoGroup(); int result; switch (textArea.Document.TextEditorProperties.IndentStyle) { case IndentStyle.None: result = 0; break; case IndentStyle.Auto: result = AutoIndentLine(textArea, line); break; case IndentStyle.Smart: result = SmartIndentLine(textArea, line); break; default: throw new NotSupportedException("Unsupported value for IndentStyle: " + textArea.Document.TextEditorProperties.IndentStyle); } textArea.Document.UndoStack.EndUndoGroup(); return result; } /// /// This function sets the indentlevel in a range of lines. /// public virtual void IndentLines(TextArea textArea, int begin, int end) { textArea.Document.UndoStack.StartUndoGroup(); for (int i = begin; i <= end; ++i) { IndentLine(textArea, i); } textArea.Document.UndoStack.EndUndoGroup(); } public virtual int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket) { int brackets = -1; // first try "quick find" - find the matching bracket if there is no string/comment in the way for (int i = offset; i >= 0; --i) { char ch = document.GetCharAt(i); if (ch == openBracket) { ++brackets; if (brackets == 0) return i; } else if (ch == closingBracket) { --brackets; } else if (ch == '"') { break; } else if (ch == '\'') { break; } else if (ch == '/' && i > 0) { if (document.GetCharAt(i - 1) == '/') break; if (document.GetCharAt(i - 1) == '*') break; } } return -1; } public virtual int SearchBracketForward(IDocument document, int offset, char openBracket, char closingBracket) { int brackets = 1; // try "quick find" - find the matching bracket if there is no string/comment in the way for (int i = offset; i < document.TextLength; ++i) { char ch = document.GetCharAt(i); if (ch == openBracket) { ++brackets; } else if (ch == closingBracket) { --brackets; if (brackets == 0) return i; } else if (ch == '"') { break; } else if (ch == '\'') { break; } else if (ch == '/' && i > 0) { if (document.GetCharAt(i - 1) == '/') break; } else if (ch == '*' && i > 0) { if (document.GetCharAt(i - 1) == '/') break; } } return -1; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/FormattingStrategy/IFormattingStrategy.cs ================================================ // // // // // $Revision: 2640 $ // using System; namespace ICSharpCode.TextEditor.Document { /// /// This interface handles the auto and smart indenting and formating /// in the document while you type. Language bindings could overwrite this /// interface and define their own indentation/formating. /// public interface IFormattingStrategy { /// /// This function formats a specific line after ch is pressed. /// void FormatLine(TextArea textArea, int line, int caretOffset, char charTyped); /// /// This function sets the indentation level in a specific line /// /// /// The target caret position (length of new indentation). /// int IndentLine(TextArea textArea, int line); /// /// This function sets the indentlevel in a range of lines. /// void IndentLines(TextArea textArea, int begin, int end); /// /// Finds the offset of the opening bracket in the block defined by offset skipping /// brackets in strings and comments. /// /// The document to search in. /// The offset of an position in the block or the offset of the closing bracket. /// The character for the opening bracket. /// The character for the closing bracket. /// Returns the offset of the opening bracket or -1 if no matching bracket was found. int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket); /// /// Finds the offset of the closing bracket in the block defined by offset skipping /// brackets in strings and comments. /// /// The document to search in. /// The offset of an position in the block or the offset of the opening bracket. /// The character for the opening bracket. /// The character for the closing bracket. /// Returns the offset of the closing bracket or -1 if no matching bracket was found. int SearchBracketForward(IDocument document, int offset, char openBracket, char closingBracket); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/DefaultHighlightingStrategy.cs ================================================ // // // // // $Revision: 3036 $ // using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Document { public class DefaultHighlightingStrategy : IHighlightingStrategyUsingRuleSets { string name; List rules = new List(); Dictionary environmentColors = new Dictionary(); Dictionary properties = new Dictionary(); string[] extensions; HighlightColor digitColor; HighlightRuleSet defaultRuleSet = null; public HighlightColor DigitColor { get { return digitColor; } set { digitColor = value; } } public IEnumerable> EnvironmentColors { get { return environmentColors; } } protected void ImportSettingsFrom(DefaultHighlightingStrategy source) { if (source == null) throw new ArgumentNullException("source"); properties = source.properties; extensions = source.extensions; digitColor = source.digitColor; defaultRuleSet = source.defaultRuleSet; name = source.name; rules = source.rules; environmentColors = source.environmentColors; defaultTextColor = source.defaultTextColor; } public DefaultHighlightingStrategy() : this("Default") { } public DefaultHighlightingStrategy(string name) { this.name = name; digitColor = new HighlightColor(SystemColors.WindowText, false, false); defaultTextColor = new HighlightColor(SystemColors.WindowText, false, false); // set small 'default color environment' environmentColors["Default"] = new HighlightBackground("WindowText", "Window", false, false); environmentColors["Selection"] = new HighlightColor("HighlightText", "Highlight", false, false); environmentColors["VRuler"] = new HighlightColor("ControlLight", "Window", false, false); environmentColors["InvalidLines"] = new HighlightColor(Color.Red, false, false); environmentColors["CaretMarker"] = new HighlightColor(Color.Yellow, false, false); environmentColors["LineNumbers"] = new HighlightBackground("ControlDark", "Window", false, false); environmentColors["FoldLine"] = new HighlightColor(Color.FromArgb(0x80, 0x80, 0x80), Color.Black, false, false); environmentColors["FoldMarker"] = new HighlightColor(Color.FromArgb(0x80, 0x80, 0x80), Color.White, false, false); environmentColors["SelectedFoldLine"] = new HighlightColor(Color.Black, false, false); environmentColors["EOLMarkers"] = new HighlightColor("ControlLight", "Window", false, false); environmentColors["SpaceMarkers"] = new HighlightColor("ControlLight", "Window", false, false); environmentColors["TabMarkers"] = new HighlightColor("ControlLight", "Window", false, false); } public Dictionary Properties { get { return properties; } } public string Name { get { return name; } } public string[] Extensions { set { extensions = value; } get { return extensions; } } public List Rules { get { return rules; } } public HighlightRuleSet FindHighlightRuleSet(string name) { foreach(HighlightRuleSet ruleSet in rules) { if (ruleSet.Name == name) { return ruleSet; } } return null; } public void AddRuleSet(HighlightRuleSet aRuleSet) { HighlightRuleSet existing = FindHighlightRuleSet(aRuleSet.Name); if (existing != null) { existing.MergeFrom(aRuleSet); } else { rules.Add(aRuleSet); } } public void ResolveReferences() { // Resolve references from Span definitions to RuleSets ResolveRuleSetReferences(); // Resolve references from RuleSet defintitions to Highlighters defined in an external mode file ResolveExternalReferences(); } void ResolveRuleSetReferences() { foreach (HighlightRuleSet ruleSet in Rules) { if (ruleSet.Name == null) { defaultRuleSet = ruleSet; } foreach (Span aSpan in ruleSet.Spans) { if (aSpan.Rule != null) { bool found = false; foreach (HighlightRuleSet refSet in Rules) { if (refSet.Name == aSpan.Rule) { found = true; aSpan.RuleSet = refSet; break; } } if (!found) { aSpan.RuleSet = null; throw new HighlightingDefinitionInvalidException("The RuleSet " + aSpan.Rule + " could not be found in mode definition " + this.Name); } } else { aSpan.RuleSet = null; } } } if (defaultRuleSet == null) { throw new HighlightingDefinitionInvalidException("No default RuleSet is defined for mode definition " + this.Name); } } void ResolveExternalReferences() { foreach (HighlightRuleSet ruleSet in Rules) { ruleSet.Highlighter = this; if (ruleSet.Reference != null) { IHighlightingStrategy highlighter = HighlightingManager.Manager.FindHighlighter (ruleSet.Reference); if (highlighter == null) throw new HighlightingDefinitionInvalidException("The mode defintion " + ruleSet.Reference + " which is refered from the " + this.Name + " mode definition could not be found"); if (highlighter is IHighlightingStrategyUsingRuleSets) ruleSet.Highlighter = (IHighlightingStrategyUsingRuleSets)highlighter; else throw new HighlightingDefinitionInvalidException("The mode defintion " + ruleSet.Reference + " which is refered from the " + this.Name + " mode definition does not implement IHighlightingStrategyUsingRuleSets"); } } } // internal void SetDefaultColor(HighlightBackground color) // { // return (HighlightColor)environmentColors[name]; // defaultColor = color; // } HighlightColor defaultTextColor; public HighlightColor DefaultTextColor { get { return defaultTextColor; } } public void SetColorFor(string name, HighlightColor color) { if (name == "Default") defaultTextColor = new HighlightColor(color.Color, color.Bold, color.Italic); environmentColors[name] = color; } public HighlightColor GetColorFor(string name) { HighlightColor color; if (environmentColors.TryGetValue(name, out color)) return color; else return defaultTextColor; } public HighlightColor GetColor(IDocument document, LineSegment currentSegment, int currentOffset, int currentLength) { return GetColor(defaultRuleSet, document, currentSegment, currentOffset, currentLength); } protected virtual HighlightColor GetColor(HighlightRuleSet ruleSet, IDocument document, LineSegment currentSegment, int currentOffset, int currentLength) { if (ruleSet != null) { if (ruleSet.Reference != null) { return ruleSet.Highlighter.GetColor(document, currentSegment, currentOffset, currentLength); } else { return (HighlightColor)ruleSet.KeyWords[document, currentSegment, currentOffset, currentLength]; } } return null; } public HighlightRuleSet GetRuleSet(Span aSpan) { if (aSpan == null) { return this.defaultRuleSet; } else { if (aSpan.RuleSet != null) { if (aSpan.RuleSet.Reference != null) { return aSpan.RuleSet.Highlighter.GetRuleSet(null); } else { return aSpan.RuleSet; } } else { return null; } } } // Line state variable protected LineSegment currentLine; protected int currentLineNumber; // Span stack state variable protected SpanStack currentSpanStack; public virtual void MarkTokens(IDocument document) { if (Rules.Count == 0) { return; } int lineNumber = 0; while (lineNumber < document.TotalNumberOfLines) { LineSegment previousLine = (lineNumber > 0 ? document.GetLineSegment(lineNumber - 1) : null); if (lineNumber >= document.LineSegmentCollection.Count) { // may be, if the last line ends with a delimiter break; // then the last line is not in the collection :) } currentSpanStack = ((previousLine != null && previousLine.HighlightSpanStack != null) ? previousLine.HighlightSpanStack.Clone() : null); if (currentSpanStack != null) { while (!currentSpanStack.IsEmpty && currentSpanStack.Peek().StopEOL) { currentSpanStack.Pop(); } if (currentSpanStack.IsEmpty) currentSpanStack = null; } currentLine = (LineSegment)document.LineSegmentCollection[lineNumber]; if (currentLine.Length == -1) { // happens when buffer is empty ! return; } currentLineNumber = lineNumber; List words = ParseLine(document); // Alex: clear old words if (currentLine.Words != null) { currentLine.Words.Clear(); } currentLine.Words = words; currentLine.HighlightSpanStack = (currentSpanStack==null || currentSpanStack.IsEmpty) ? null : currentSpanStack; ++lineNumber; } document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); document.CommitUpdate(); currentLine = null; } bool MarkTokensInLine(IDocument document, int lineNumber, ref bool spanChanged) { currentLineNumber = lineNumber; bool processNextLine = false; LineSegment previousLine = (lineNumber > 0 ? document.GetLineSegment(lineNumber - 1) : null); currentSpanStack = ((previousLine != null && previousLine.HighlightSpanStack != null) ? previousLine.HighlightSpanStack.Clone() : null); if (currentSpanStack != null) { while (!currentSpanStack.IsEmpty && currentSpanStack.Peek().StopEOL) { currentSpanStack.Pop(); } if (currentSpanStack.IsEmpty) { currentSpanStack = null; } } currentLine = (LineSegment)document.LineSegmentCollection[lineNumber]; if (currentLine.Length == -1) { // happens when buffer is empty ! return false; } List words = ParseLine(document); if (currentSpanStack != null && currentSpanStack.IsEmpty) { currentSpanStack = null; } // Check if the span state has changed, if so we must re-render the next line // This check may seem utterly complicated but I didn't want to introduce any function calls // or allocations here for perf reasons. if(currentLine.HighlightSpanStack != currentSpanStack) { if (currentLine.HighlightSpanStack == null) { processNextLine = false; foreach (Span sp in currentSpanStack) { if (!sp.StopEOL) { spanChanged = true; processNextLine = true; break; } } } else if (currentSpanStack == null) { processNextLine = false; foreach (Span sp in currentLine.HighlightSpanStack) { if (!sp.StopEOL) { spanChanged = true; processNextLine = true; break; } } } else { SpanStack.Enumerator e1 = currentSpanStack.GetEnumerator(); SpanStack.Enumerator e2 = currentLine.HighlightSpanStack.GetEnumerator(); bool done = false; while (!done) { bool blockSpanIn1 = false; while (e1.MoveNext()) { if (!((Span)e1.Current).StopEOL) { blockSpanIn1 = true; break; } } bool blockSpanIn2 = false; while (e2.MoveNext()) { if (!((Span)e2.Current).StopEOL) { blockSpanIn2 = true; break; } } if (blockSpanIn1 || blockSpanIn2) { if (blockSpanIn1 && blockSpanIn2) { if (e1.Current != e2.Current) { done = true; processNextLine = true; spanChanged = true; } } else { spanChanged = true; done = true; processNextLine = true; } } else { done = true; processNextLine = false; } } } } else { processNextLine = false; } //// Alex: remove old words if (currentLine.Words!=null) currentLine.Words.Clear(); currentLine.Words = words; currentLine.HighlightSpanStack = (currentSpanStack != null && !currentSpanStack.IsEmpty) ? currentSpanStack : null; return processNextLine; } public virtual void MarkTokens(IDocument document, List inputLines) { if (Rules.Count == 0) { return; } Dictionary processedLines = new Dictionary(); bool spanChanged = false; int documentLineSegmentCount = document.LineSegmentCollection.Count; foreach (LineSegment lineToProcess in inputLines) { if (!processedLines.ContainsKey(lineToProcess)) { int lineNumber = lineToProcess.LineNumber; bool processNextLine = true; if (lineNumber != -1) { while (processNextLine && lineNumber < documentLineSegmentCount) { processNextLine = MarkTokensInLine(document, lineNumber, ref spanChanged); processedLines[currentLine] = true; ++lineNumber; } } } } if (spanChanged || inputLines.Count > 20) { // if the span was changed (more than inputLines lines had to be reevaluated) // or if there are many lines in inputLines, it's faster to update the whole // text area instead of many small segments document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); } else { // document.Caret.ValidateCaretPos(); // document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, document.GetLineNumberForOffset(document.Caret.Offset))); // foreach (LineSegment lineToProcess in inputLines) { document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineToProcess.LineNumber)); } } document.CommitUpdate(); currentLine = null; } // Span state variables protected bool inSpan; protected Span activeSpan; protected HighlightRuleSet activeRuleSet; // Line scanning state variables protected int currentOffset; protected int currentLength; void UpdateSpanStateVariables() { inSpan = (currentSpanStack != null && !currentSpanStack.IsEmpty); activeSpan = inSpan ? currentSpanStack.Peek() : null; activeRuleSet = GetRuleSet(activeSpan); } List ParseLine(IDocument document) { List words = new List(); HighlightColor markNext = null; currentOffset = 0; currentLength = 0; UpdateSpanStateVariables(); int currentLineLength = currentLine.Length; int currentLineOffset = currentLine.Offset; for (int i = 0; i < currentLineLength; ++i) { char ch = document.GetCharAt(currentLineOffset + i); switch (ch) { case '\n': case '\r': PushCurWord(document, ref markNext, words); ++currentOffset; break; case ' ': PushCurWord(document, ref markNext, words); if (activeSpan != null && activeSpan.Color.HasBackground) { words.Add(new TextWord.SpaceTextWord(activeSpan.Color)); } else { words.Add(TextWord.Space); } ++currentOffset; break; case '\t': PushCurWord(document, ref markNext, words); if (activeSpan != null && activeSpan.Color.HasBackground) { words.Add(new TextWord.TabTextWord(activeSpan.Color)); } else { words.Add(TextWord.Tab); } ++currentOffset; break; default: { // handle escape characters char escapeCharacter = '\0'; if (activeSpan != null && activeSpan.EscapeCharacter != '\0') { escapeCharacter = activeSpan.EscapeCharacter; } else if (activeRuleSet != null) { escapeCharacter = activeRuleSet.EscapeCharacter; } if (escapeCharacter != '\0' && escapeCharacter == ch) { // we found the escape character if (activeSpan != null && activeSpan.End != null && activeSpan.End.Length == 1 && escapeCharacter == activeSpan.End[0]) { // the escape character is a end-doubling escape character // it may count as escape only when the next character is the escape, too if (i + 1 < currentLineLength) { if (document.GetCharAt(currentLineOffset + i + 1) == escapeCharacter) { currentLength += 2; PushCurWord(document, ref markNext, words); ++i; continue; } } } else { // this is a normal \-style escape ++currentLength; if (i + 1 < currentLineLength) { ++currentLength; } PushCurWord(document, ref markNext, words); ++i; continue; } } // highlight digits if (!inSpan && (Char.IsDigit(ch) || (ch == '.' && i + 1 < currentLineLength && Char.IsDigit(document.GetCharAt(currentLineOffset + i + 1)))) && currentLength == 0) { bool ishex = false; bool isfloatingpoint = false; if (ch == '0' && i + 1 < currentLineLength && Char.ToUpper(document.GetCharAt(currentLineOffset + i + 1)) == 'X') { // hex digits const string hex = "0123456789ABCDEF"; ++currentLength; ++i; // skip 'x' ++currentLength; ishex = true; while (i + 1 < currentLineLength && hex.IndexOf(Char.ToUpper(document.GetCharAt(currentLineOffset + i + 1))) != -1) { ++i; ++currentLength; } } else { ++currentLength; while (i + 1 < currentLineLength && Char.IsDigit(document.GetCharAt(currentLineOffset + i + 1))) { ++i; ++currentLength; } } if (!ishex && i + 1 < currentLineLength && document.GetCharAt(currentLineOffset + i + 1) == '.') { isfloatingpoint = true; ++i; ++currentLength; while (i + 1 < currentLineLength && Char.IsDigit(document.GetCharAt(currentLineOffset + i + 1))) { ++i; ++currentLength; } } if (i + 1 < currentLineLength && Char.ToUpper(document.GetCharAt(currentLineOffset + i + 1)) == 'E') { isfloatingpoint = true; ++i; ++currentLength; if (i + 1 < currentLineLength && (document.GetCharAt(currentLineOffset + i + 1) == '+' || document.GetCharAt(currentLine.Offset + i + 1) == '-')) { ++i; ++currentLength; } while (i + 1 < currentLine.Length && Char.IsDigit(document.GetCharAt(currentLineOffset + i + 1))) { ++i; ++currentLength; } } if (i + 1 < currentLine.Length) { char nextch = Char.ToUpper(document.GetCharAt(currentLineOffset + i + 1)); if (nextch == 'F' || nextch == 'M' || nextch == 'D') { isfloatingpoint = true; ++i; ++currentLength; } } if (!isfloatingpoint) { bool isunsigned = false; if (i + 1 < currentLineLength && Char.ToUpper(document.GetCharAt(currentLineOffset + i + 1)) == 'U') { ++i; ++currentLength; isunsigned = true; } if (i + 1 < currentLineLength && Char.ToUpper(document.GetCharAt(currentLineOffset + i + 1)) == 'L') { ++i; ++currentLength; if (!isunsigned && i + 1 < currentLineLength && Char.ToUpper(document.GetCharAt(currentLineOffset + i + 1)) == 'U') { ++i; ++currentLength; } } } words.Add(new TextWord(document, currentLine, currentOffset, currentLength, DigitColor, false)); currentOffset += currentLength; currentLength = 0; continue; } // Check for SPAN ENDs if (inSpan) { if (activeSpan.End != null && activeSpan.End.Length > 0) { if (MatchExpr(currentLine, activeSpan.End, i, document, activeSpan.IgnoreCase)) { PushCurWord(document, ref markNext, words); string regex = GetRegString(currentLine, activeSpan.End, i, document); currentLength += regex.Length; words.Add(new TextWord(document, currentLine, currentOffset, currentLength, activeSpan.EndColor, false)); currentOffset += currentLength; currentLength = 0; i += regex.Length - 1; currentSpanStack.Pop(); UpdateSpanStateVariables(); continue; } } } // check for SPAN BEGIN if (activeRuleSet != null) { foreach (Span span in activeRuleSet.Spans) { if ((!span.IsBeginSingleWord || currentLength == 0) && (!span.IsBeginStartOfLine.HasValue || span.IsBeginStartOfLine.Value == (currentLength == 0 && words.TrueForAll(delegate(TextWord textWord) { return textWord.Type != TextWordType.Word; }))) && MatchExpr(currentLine, span.Begin, i, document, activeRuleSet.IgnoreCase)) { PushCurWord(document, ref markNext, words); string regex = GetRegString(currentLine, span.Begin, i, document); if (!OverrideSpan(regex, document, words, span, ref i)) { currentLength += regex.Length; words.Add(new TextWord(document, currentLine, currentOffset, currentLength, span.BeginColor, false)); currentOffset += currentLength; currentLength = 0; i += regex.Length - 1; if (currentSpanStack == null) { currentSpanStack = new SpanStack(); } currentSpanStack.Push(span); span.IgnoreCase = activeRuleSet.IgnoreCase; UpdateSpanStateVariables(); } goto skip; } } } // check if the char is a delimiter if (activeRuleSet != null && (int)ch < 256 && activeRuleSet.Delimiters[(int)ch]) { PushCurWord(document, ref markNext, words); if (currentOffset + currentLength +1 < currentLine.Length) { ++currentLength; PushCurWord(document, ref markNext, words); goto skip; } } ++currentLength; skip: continue; } } } PushCurWord(document, ref markNext, words); OnParsedLine(document, currentLine, words); return words; } protected virtual void OnParsedLine(IDocument document, LineSegment currentLine, List words) { } protected virtual bool OverrideSpan(string spanBegin, IDocument document, List words, Span span, ref int lineOffset) { return false; } /// /// pushes the curWord string on the word list, with the /// correct color. /// void PushCurWord(IDocument document, ref HighlightColor markNext, List words) { // Svante Lidman : Need to look through the next prev logic. if (currentLength > 0) { if (words.Count > 0 && activeRuleSet != null) { TextWord prevWord = null; int pInd = words.Count - 1; while (pInd >= 0) { if (!((TextWord)words[pInd]).IsWhiteSpace) { prevWord = (TextWord)words[pInd]; if (prevWord.HasDefaultColor) { PrevMarker marker = (PrevMarker)activeRuleSet.PrevMarkers[document, currentLine, currentOffset, currentLength]; if (marker != null) { prevWord.SyntaxColor = marker.Color; // document.Caret.ValidateCaretPos(); // document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, document.GetLineNumberForOffset(document.Caret.Offset))); } } break; } pInd--; } } if (inSpan) { HighlightColor c = null; bool hasDefaultColor = true; if (activeSpan.Rule == null) { c = activeSpan.Color; } else { c = GetColor(activeRuleSet, document, currentLine, currentOffset, currentLength); hasDefaultColor = false; } if (c == null) { c = activeSpan.Color; if (c.Color == Color.Transparent) { c = this.DefaultTextColor; } hasDefaultColor = true; } words.Add(new TextWord(document, currentLine, currentOffset, currentLength, markNext != null ? markNext : c, hasDefaultColor)); } else { HighlightColor c = markNext != null ? markNext : GetColor(activeRuleSet, document, currentLine, currentOffset, currentLength); if (c == null) { words.Add(new TextWord(document, currentLine, currentOffset, currentLength, this.DefaultTextColor, true)); } else { words.Add(new TextWord(document, currentLine, currentOffset, currentLength, c, false)); } } if (activeRuleSet != null) { NextMarker nextMarker = (NextMarker)activeRuleSet.NextMarkers[document, currentLine, currentOffset, currentLength]; if (nextMarker != null) { if (nextMarker.MarkMarker && words.Count > 0) { TextWord prevword = ((TextWord)words[words.Count - 1]); prevword.SyntaxColor = nextMarker.Color; } markNext = nextMarker.Color; } else { markNext = null; } } currentOffset += currentLength; currentLength = 0; } } #region Matching /// /// get the string, which matches the regular expression expr, /// in string s2 at index /// static string GetRegString(LineSegment lineSegment, char[] expr, int index, IDocument document) { int j = 0; StringBuilder regexpr = new StringBuilder(); for (int i = 0; i < expr.Length; ++i, ++j) { if (index + j >= lineSegment.Length) break; switch (expr[i]) { case '@': // "special" meaning ++i; switch (expr[i]) { case '!': // don't match the following expression StringBuilder whatmatch = new StringBuilder(); ++i; while (i < expr.Length && expr[i] != '@') { whatmatch.Append(expr[i++]); } break; case '@': // matches @ regexpr.Append(document.GetCharAt(lineSegment.Offset + index + j)); break; } break; default: if (expr[i] != document.GetCharAt(lineSegment.Offset + index + j)) { return regexpr.ToString(); } regexpr.Append(document.GetCharAt(lineSegment.Offset + index + j)); break; } } return regexpr.ToString(); } /// /// returns true, if the get the string s2 at index matches the expression expr /// static bool MatchExpr(LineSegment lineSegment, char[] expr, int index, IDocument document, bool ignoreCase) { for (int i = 0, j = 0; i < expr.Length; ++i, ++j) { switch (expr[i]) { case '@': // "special" meaning ++i; if (i < expr.Length) { switch (expr[i]) { case 'C': // match whitespace or punctuation if (index + j == lineSegment.Offset || index + j >= lineSegment.Offset + lineSegment.Length) { // nothing (EOL or SOL) } else { char ch = document.GetCharAt(lineSegment.Offset + index + j); if (!Char.IsWhiteSpace(ch) && !Char.IsPunctuation(ch)) { return false; } } break; case '!': // don't match the following expression { StringBuilder whatmatch = new StringBuilder(); ++i; while (i < expr.Length && expr[i] != '@') { whatmatch.Append(expr[i++]); } if (lineSegment.Offset + index + j + whatmatch.Length < document.TextLength) { int k = 0; for (; k < whatmatch.Length; ++k) { char docChar = ignoreCase ? Char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index + j + k)) : document.GetCharAt(lineSegment.Offset + index + j + k); char spanChar = ignoreCase ? Char.ToUpperInvariant(whatmatch[k]) : whatmatch[k]; if (docChar != spanChar) { break; } } if (k >= whatmatch.Length) { return false; } } // --j; break; } case '-': // don't match the expression before { StringBuilder whatmatch = new StringBuilder(); ++i; while (i < expr.Length && expr[i] != '@') { whatmatch.Append(expr[i++]); } if (index - whatmatch.Length >= 0) { int k = 0; for (; k < whatmatch.Length; ++k) { char docChar = ignoreCase ? Char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index - whatmatch.Length + k)) : document.GetCharAt(lineSegment.Offset + index - whatmatch.Length + k); char spanChar = ignoreCase ? Char.ToUpperInvariant(whatmatch[k]) : whatmatch[k]; if (docChar != spanChar) break; } if (k >= whatmatch.Length) { return false; } } // --j; break; } case '@': // matches @ if (index + j >= lineSegment.Length || '@' != document.GetCharAt(lineSegment.Offset + index + j)) { return false; } break; } } break; default: { if (index + j >= lineSegment.Length) { return false; } char docChar = ignoreCase ? Char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index + j)) : document.GetCharAt(lineSegment.Offset + index + j); char spanChar = ignoreCase ? Char.ToUpperInvariant(expr[i]) : expr[i]; if (docChar != spanChar) { return false; } break; } } } return true; } #endregion } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/FontContainer.cs ================================================ // // // // // $Revision: 3358 $ // using System; using System.Drawing; namespace ICSharpCode.TextEditor.Document { /// /// This class is used to generate bold, italic and bold/italic fonts out /// of a base font. /// public class FontContainer { Font defaultFont; Font regularfont, boldfont, italicfont, bolditalicfont; /// /// The scaled, regular version of the base font /// public Font RegularFont { get { return regularfont; } } /// /// The scaled, bold version of the base font /// public Font BoldFont { get { return boldfont; } } /// /// The scaled, italic version of the base font /// public Font ItalicFont { get { return italicfont; } } /// /// The scaled, bold/italic version of the base font /// public Font BoldItalicFont { get { return bolditalicfont; } } static float twipsPerPixelY; public static float TwipsPerPixelY { get { if (twipsPerPixelY == 0) { using (Bitmap bmp = new Bitmap(1,1)) { using (Graphics g = Graphics.FromImage(bmp)) { twipsPerPixelY = 1440 / g.DpiY; } } } return twipsPerPixelY; } } /// /// The base font /// public Font DefaultFont { get { return defaultFont; } set { // 1440 twips is one inch float pixelSize = (float)Math.Round(value.SizeInPoints * 20 / TwipsPerPixelY); defaultFont = value; regularfont = new Font(value.FontFamily, pixelSize * TwipsPerPixelY / 20f, FontStyle.Regular); boldfont = new Font(regularfont, FontStyle.Bold); italicfont = new Font(regularfont, FontStyle.Italic); bolditalicfont = new Font(regularfont, FontStyle.Bold | FontStyle.Italic); } } public static Font ParseFont(string font) { string[] descr = font.Split(new char[]{',', '='}); return new Font(descr[1], Single.Parse(descr[3])); } public FontContainer(Font defaultFont) { this.DefaultFont = defaultFont; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightBackground.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Drawing; using System.Xml; namespace ICSharpCode.TextEditor.Document { /// /// Extens the highlighting color with a background image. /// public class HighlightBackground : HighlightColor { Image backgroundImage; /// /// The image used as background /// public Image BackgroundImage { get { return backgroundImage; } } /// /// Creates a new instance of /// public HighlightBackground(XmlElement el) : base(el) { if (el.Attributes["image"] != null) { backgroundImage = new Bitmap(el.Attributes["image"].InnerText); } } /// /// Creates a new instance of /// public HighlightBackground(Color color, Color backgroundcolor, bool bold, bool italic) : base(color, backgroundcolor, bold, italic) { } public HighlightBackground(string systemColor, string systemBackgroundColor, bool bold, bool italic) : base(systemColor, systemBackgroundColor, bold, italic) { } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Reflection; using System.Xml; namespace ICSharpCode.TextEditor.Document { /// /// A color used for highlighting /// public class HighlightColor { bool systemColor = false; string systemColorName = null; bool systemBgColor = false; string systemBgColorName = null; Color color; Color backgroundcolor = System.Drawing.Color.WhiteSmoke; bool bold = false; bool italic = false; bool hasForeground = false; bool hasBackground = false; public bool HasForeground { get { return hasForeground; } } public bool HasBackground { get { return hasBackground; } } /// /// If true the font will be displayed bold style /// public bool Bold { get { return bold; } } /// /// If true the font will be displayed italic style /// public bool Italic { get { return italic; } } /// /// The background color used /// public Color BackgroundColor { get { if (!systemBgColor) { return backgroundcolor; } return ParseColorString(systemBgColorName); } } /// /// The foreground color used /// public Color Color { get { if (!systemColor) { return color; } return ParseColorString(systemColorName); } } /// /// The font used /// public Font GetFont(FontContainer fontContainer) { if (Bold) { return Italic ? fontContainer.BoldItalicFont : fontContainer.BoldFont; } return Italic ? fontContainer.ItalicFont : fontContainer.RegularFont; } Color ParseColorString(string colorName) { string[] cNames = colorName.Split('*'); PropertyInfo myPropInfo = typeof(System.Drawing.SystemColors).GetProperty(cNames[0], BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); Color c = (Color)myPropInfo.GetValue(null, null); if (cNames.Length == 2) { // hack : can't figure out how to parse doubles with '.' (culture info might set the '.' to ',') double factor = Double.Parse(cNames[1]) / 100; c = Color.FromArgb((int)((double)c.R * factor), (int)((double)c.G * factor), (int)((double)c.B * factor)); } return c; } /// /// Creates a new instance of /// public HighlightColor(XmlElement el) { Debug.Assert(el != null, "ICSharpCode.TextEditor.Document.SyntaxColor(XmlElement el) : el == null"); if (el.Attributes["bold"] != null) { bold = Boolean.Parse(el.Attributes["bold"].InnerText); } if (el.Attributes["italic"] != null) { italic = Boolean.Parse(el.Attributes["italic"].InnerText); } if (el.Attributes["color"] != null) { string c = el.Attributes["color"].InnerText; if (c[0] == '#') { color = ParseColor(c); } else if (c.StartsWith("SystemColors.")) { systemColor = true; systemColorName = c.Substring("SystemColors.".Length); } else { color = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]); } hasForeground = true; } else { color = Color.Transparent; // to set it to the default value. } if (el.Attributes["bgcolor"] != null) { string c = el.Attributes["bgcolor"].InnerText; if (c[0] == '#') { backgroundcolor = ParseColor(c); } else if (c.StartsWith("SystemColors.")) { systemBgColor = true; systemBgColorName = c.Substring("SystemColors.".Length); } else { backgroundcolor = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]); } hasBackground = true; } } /// /// Creates a new instance of /// public HighlightColor(XmlElement el, HighlightColor defaultColor) { Debug.Assert(el != null, "ICSharpCode.TextEditor.Document.SyntaxColor(XmlElement el) : el == null"); if (el.Attributes["bold"] != null) { bold = Boolean.Parse(el.Attributes["bold"].InnerText); } else { bold = defaultColor.Bold; } if (el.Attributes["italic"] != null) { italic = Boolean.Parse(el.Attributes["italic"].InnerText); } else { italic = defaultColor.Italic; } if (el.Attributes["color"] != null) { string c = el.Attributes["color"].InnerText; if (c[0] == '#') { color = ParseColor(c); } else if (c.StartsWith("SystemColors.")) { systemColor = true; systemColorName = c.Substring("SystemColors.".Length); } else { color = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]); } hasForeground = true; } else { color = defaultColor.color; } if (el.Attributes["bgcolor"] != null) { string c = el.Attributes["bgcolor"].InnerText; if (c[0] == '#') { backgroundcolor = ParseColor(c); } else if (c.StartsWith("SystemColors.")) { systemBgColor = true; systemBgColorName = c.Substring("SystemColors.".Length); } else { backgroundcolor = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]); } hasBackground = true; } else { backgroundcolor = defaultColor.BackgroundColor; } } /// /// Creates a new instance of /// public HighlightColor(Color color, bool bold, bool italic) { hasForeground = true; this.color = color; this.bold = bold; this.italic = italic; } /// /// Creates a new instance of /// public HighlightColor(Color color, Color backgroundcolor, bool bold, bool italic) { hasForeground = true; hasBackground = true; this.color = color; this.backgroundcolor = backgroundcolor; this.bold = bold; this.italic = italic; } /// /// Creates a new instance of /// public HighlightColor(string systemColor, string systemBackgroundColor, bool bold, bool italic) { hasForeground = true; hasBackground = true; this.systemColor = true; systemColorName = systemColor; systemBgColor = true; systemBgColorName = systemBackgroundColor; this.bold = bold; this.italic = italic; } static Color ParseColor(string c) { int a = 255; int offset = 0; if (c.Length > 7) { offset = 2; a = Int32.Parse(c.Substring(1,2), NumberStyles.HexNumber); } int r = Int32.Parse(c.Substring(1 + offset,2), NumberStyles.HexNumber); int g = Int32.Parse(c.Substring(3 + offset,2), NumberStyles.HexNumber); int b = Int32.Parse(c.Substring(5 + offset,2), NumberStyles.HexNumber); return Color.FromArgb(a, r, g, b); } /// /// Converts a instance to string (for debug purposes) /// public override string ToString() { return "[HighlightColor: Bold = " + Bold + ", Italic = " + Italic + ", Color = " + Color + ", BackgroundColor = " + BackgroundColor + "]"; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightInfo.cs ================================================ // // // // // $Revision: 1965 $ // using System; namespace ICSharpCode.TextEditor.Document { public class HighlightInfo { public bool BlockSpanOn = false; public bool Span = false; public Span CurSpan = null; public HighlightInfo(Span curSpan, bool span, bool blockSpanOn) { this.CurSpan = curSpan; this.Span = span; this.BlockSpanOn = blockSpanOn; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightRuleSet.cs ================================================ // // // // // $Revision: 3036 $ // using System; using System.Collections; using System.Xml; using ICSharpCode.TextEditor.Util; namespace ICSharpCode.TextEditor.Document { public class HighlightRuleSet { LookupTable keyWords; ArrayList spans = new ArrayList(); LookupTable prevMarkers; LookupTable nextMarkers; char escapeCharacter; bool ignoreCase = false; string name = null; bool[] delimiters = new bool[256]; string reference = null; public ArrayList Spans { get { return spans; } } internal IHighlightingStrategyUsingRuleSets Highlighter; public LookupTable KeyWords { get { return keyWords; } } public LookupTable PrevMarkers { get { return prevMarkers; } } public LookupTable NextMarkers { get { return nextMarkers; } } public bool[] Delimiters { get { return delimiters; } } public char EscapeCharacter { get { return escapeCharacter; } } public bool IgnoreCase { get { return ignoreCase; } } public string Name { get { return name; } set { name = value; } } public string Reference { get { return reference; } } public HighlightRuleSet() { keyWords = new LookupTable(false); prevMarkers = new LookupTable(false); nextMarkers = new LookupTable(false); } public HighlightRuleSet(XmlElement el) { XmlNodeList nodes; if (el.Attributes["name"] != null) { Name = el.Attributes["name"].InnerText; } if (el.HasAttribute("escapecharacter")) { escapeCharacter = el.GetAttribute("escapecharacter")[0]; } if (el.Attributes["reference"] != null) { reference = el.Attributes["reference"].InnerText; } if (el.Attributes["ignorecase"] != null) { ignoreCase = Boolean.Parse(el.Attributes["ignorecase"].InnerText); } for (int i = 0; i < Delimiters.Length; ++i) { delimiters[i] = false; } if (el["Delimiters"] != null) { string delimiterString = el["Delimiters"].InnerText; foreach (char ch in delimiterString) { delimiters[(int)ch] = true; } } // Spans = new LookupTable(!IgnoreCase); keyWords = new LookupTable(!IgnoreCase); prevMarkers = new LookupTable(!IgnoreCase); nextMarkers = new LookupTable(!IgnoreCase); nodes = el.GetElementsByTagName("KeyWords"); foreach (XmlElement el2 in nodes) { HighlightColor color = new HighlightColor(el2); XmlNodeList keys = el2.GetElementsByTagName("Key"); foreach (XmlElement node in keys) { keyWords[node.Attributes["word"].InnerText] = color; } } nodes = el.GetElementsByTagName("Span"); foreach (XmlElement el2 in nodes) { Spans.Add(new Span(el2)); /* Span span = new Span(el2); Spans[span.Begin] = span;*/ } nodes = el.GetElementsByTagName("MarkPrevious"); foreach (XmlElement el2 in nodes) { PrevMarker prev = new PrevMarker(el2); prevMarkers[prev.What] = prev; } nodes = el.GetElementsByTagName("MarkFollowing"); foreach (XmlElement el2 in nodes) { NextMarker next = new NextMarker(el2); nextMarkers[next.What] = next; } } /// /// Merges spans etc. from the other rule set into this rule set. /// public void MergeFrom(HighlightRuleSet ruleSet) { for (int i = 0; i < delimiters.Length; i++) { delimiters[i] |= ruleSet.delimiters[i]; } // insert merged spans in front of old spans ArrayList oldSpans = spans; spans = (ArrayList)ruleSet.spans.Clone(); spans.AddRange(oldSpans); //keyWords.MergeFrom(ruleSet.keyWords); //prevMarkers.MergeFrom(ruleSet.prevMarkers); //nextMarkers.MergeFrom(ruleSet.nextMarkers); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingColorNotFoundException.cs ================================================ // // // // // $Revision: 1624 $ // using System; using System.Runtime.Serialization; namespace ICSharpCode.TextEditor.Document { [Serializable()] public class HighlightingColorNotFoundException : Exception { public HighlightingColorNotFoundException() : base() { } public HighlightingColorNotFoundException(string message) : base(message) { } public HighlightingColorNotFoundException(string message, Exception innerException) : base(message, innerException) { } protected HighlightingColorNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingDefinitionInvalidException.cs ================================================ // // // // // $Revision: 2533 $ // using System; using System.Runtime.Serialization; namespace ICSharpCode.TextEditor.Document { /// /// Indicates that the highlighting definition that was tried to load was invalid. /// You get this exception only once per highlighting definition, after that the definition /// is replaced with the default highlighter. /// [Serializable()] public class HighlightingDefinitionInvalidException : Exception { public HighlightingDefinitionInvalidException() : base() { } public HighlightingDefinitionInvalidException(string message) : base(message) { } public HighlightingDefinitionInvalidException(string message, Exception innerException) : base(message, innerException) { } protected HighlightingDefinitionInvalidException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingDefinitionParser.cs ================================================ // // // // // $Revision: 2533 $ // using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Windows.Forms; using System.Xml; using System.Xml.Schema; namespace ICSharpCode.TextEditor.Document { public static class HighlightingDefinitionParser { public static DefaultHighlightingStrategy Parse(SyntaxMode syntaxMode, XmlReader xmlReader) { return Parse(null, syntaxMode, xmlReader); } public static DefaultHighlightingStrategy Parse(DefaultHighlightingStrategy highlighter, SyntaxMode syntaxMode, XmlReader xmlReader) { if (syntaxMode == null) throw new ArgumentNullException("syntaxMode"); if (xmlReader == null) throw new ArgumentNullException("xmlTextReader"); try { List errors = null; XmlReaderSettings settings = new XmlReaderSettings(); Stream shemaStream = typeof(HighlightingDefinitionParser).Assembly.GetManifestResourceStream("ICSharpCode.TextEditor.Resources.Mode.xsd"); settings.Schemas.Add("", new XmlTextReader(shemaStream)); settings.Schemas.ValidationEventHandler += delegate(object sender, ValidationEventArgs args) { if (errors == null) { errors = new List(); } errors.Add(args); }; settings.ValidationType = ValidationType.Schema; XmlReader validatingReader = XmlReader.Create(xmlReader, settings); XmlDocument doc = new XmlDocument(); doc.Load(validatingReader); if (highlighter == null) highlighter = new DefaultHighlightingStrategy(doc.DocumentElement.Attributes["name"].InnerText); if (doc.DocumentElement.HasAttribute("extends")) { KeyValuePair entry = HighlightingManager.Manager.FindHighlighterEntry(doc.DocumentElement.GetAttribute("extends")); if (entry.Key == null) { throw new HighlightingDefinitionInvalidException("Cannot find referenced highlighting source " + doc.DocumentElement.GetAttribute("extends")); } else { highlighter = Parse(highlighter, entry.Key, entry.Value.GetSyntaxModeFile(entry.Key)); if (highlighter == null) return null; } } if (doc.DocumentElement.HasAttribute("extensions")) { highlighter.Extensions = doc.DocumentElement.GetAttribute("extensions").Split(new char[] { ';', '|' }); } XmlElement environment = doc.DocumentElement["Environment"]; if (environment != null) { foreach (XmlNode node in environment.ChildNodes) { if (node is XmlElement) { XmlElement el = (XmlElement)node; if (el.Name == "Custom") { highlighter.SetColorFor(el.GetAttribute("name"), el.HasAttribute("bgcolor") ? new HighlightBackground(el) : new HighlightColor(el)); } else { highlighter.SetColorFor(el.Name, el.HasAttribute("bgcolor") ? new HighlightBackground(el) : new HighlightColor(el)); } } } } // parse properties if (doc.DocumentElement["Properties"]!= null) { foreach (XmlElement propertyElement in doc.DocumentElement["Properties"].ChildNodes) { highlighter.Properties[propertyElement.Attributes["name"].InnerText] = propertyElement.Attributes["value"].InnerText; } } if (doc.DocumentElement["Digits"]!= null) { highlighter.DigitColor = new HighlightColor(doc.DocumentElement["Digits"]); } XmlNodeList nodes = doc.DocumentElement.GetElementsByTagName("RuleSet"); foreach (XmlElement element in nodes) { highlighter.AddRuleSet(new HighlightRuleSet(element)); } xmlReader.Close(); if (errors != null) { StringBuilder msg = new StringBuilder(); foreach (ValidationEventArgs args in errors) { msg.AppendLine(args.Message); } throw new HighlightingDefinitionInvalidException(msg.ToString()); } else { return highlighter; } } catch (Exception e) { throw new HighlightingDefinitionInvalidException("Could not load mode definition file '" + syntaxMode.FileName + "'.\n", e); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingManager.cs ================================================ // // // // // $Revision: 3209 $ // using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Diagnostics; namespace ICSharpCode.TextEditor.Document { public class HighlightingManager { ArrayList syntaxModeFileProviders = new ArrayList(); static HighlightingManager highlightingManager; // hash table from extension name to highlighting definition, // OR from extension name to Pair SyntaxMode,ISyntaxModeFileProvider Hashtable highlightingDefs = new Hashtable(); Hashtable extensionsToName = new Hashtable(); public Hashtable HighlightingDefinitions { get { return highlightingDefs; } } public static HighlightingManager Manager { get { return highlightingManager; } } static HighlightingManager() { highlightingManager = new HighlightingManager(); highlightingManager.AddSyntaxModeFileProvider(new ResourceSyntaxModeProvider()); } public HighlightingManager() { CreateDefaultHighlightingStrategy(); } public void AddSyntaxModeFileProvider(ISyntaxModeFileProvider syntaxModeFileProvider) { foreach (SyntaxMode syntaxMode in syntaxModeFileProvider.SyntaxModes) { highlightingDefs[syntaxMode.Name] = new DictionaryEntry(syntaxMode, syntaxModeFileProvider); foreach (string extension in syntaxMode.Extensions) { extensionsToName[extension.ToUpperInvariant()] = syntaxMode.Name; } } if (!syntaxModeFileProviders.Contains(syntaxModeFileProvider)) { syntaxModeFileProviders.Add(syntaxModeFileProvider); } } public void AddHighlightingStrategy(IHighlightingStrategy highlightingStrategy) { highlightingDefs[highlightingStrategy.Name] = highlightingStrategy; foreach (string extension in highlightingStrategy.Extensions) { extensionsToName[extension.ToUpperInvariant()] = highlightingStrategy.Name; } } public void ReloadSyntaxModes() { highlightingDefs.Clear(); extensionsToName.Clear(); CreateDefaultHighlightingStrategy(); foreach (ISyntaxModeFileProvider provider in syntaxModeFileProviders) { provider.UpdateSyntaxModeList(); AddSyntaxModeFileProvider(provider); } OnReloadSyntaxHighlighting(EventArgs.Empty); } void CreateDefaultHighlightingStrategy() { DefaultHighlightingStrategy defaultHighlightingStrategy = new DefaultHighlightingStrategy(); defaultHighlightingStrategy.Extensions = new string[] {}; defaultHighlightingStrategy.Rules.Add(new HighlightRuleSet()); highlightingDefs["Default"] = defaultHighlightingStrategy; } IHighlightingStrategy LoadDefinition(DictionaryEntry entry) { SyntaxMode syntaxMode = (SyntaxMode)entry.Key; ISyntaxModeFileProvider syntaxModeFileProvider = (ISyntaxModeFileProvider)entry.Value; DefaultHighlightingStrategy highlightingStrategy = null; try { var reader = syntaxModeFileProvider.GetSyntaxModeFile(syntaxMode); if (reader == null) throw new HighlightingDefinitionInvalidException("Could not get syntax mode file for " + syntaxMode.Name); highlightingStrategy = HighlightingDefinitionParser.Parse(syntaxMode, reader); if (highlightingStrategy.Name != syntaxMode.Name) { throw new HighlightingDefinitionInvalidException("The name specified in the .xshd '" + highlightingStrategy.Name + "' must be equal the syntax mode name '" + syntaxMode.Name + "'"); } } finally { if (highlightingStrategy == null) { highlightingStrategy = DefaultHighlighting; } highlightingDefs[syntaxMode.Name] = highlightingStrategy; highlightingStrategy.ResolveReferences(); } return highlightingStrategy; } public DefaultHighlightingStrategy DefaultHighlighting { get { return (DefaultHighlightingStrategy)highlightingDefs["Default"]; } } internal KeyValuePair FindHighlighterEntry(string name) { foreach (ISyntaxModeFileProvider provider in syntaxModeFileProviders) { foreach (SyntaxMode mode in provider.SyntaxModes) { if (mode.Name == name) { return new KeyValuePair(mode, provider); } } } return new KeyValuePair(null, null); } public IHighlightingStrategy FindHighlighter(string name) { object def = highlightingDefs[name]; if (def is DictionaryEntry) { return LoadDefinition((DictionaryEntry)def); } return def == null ? DefaultHighlighting : (IHighlightingStrategy)def; } public IHighlightingStrategy FindHighlighterForFile(string fileName) { string highlighterName = (string)extensionsToName[Path.GetExtension(fileName).ToUpperInvariant()]; if (highlighterName != null) { object def = highlightingDefs[highlighterName]; if (def is DictionaryEntry) { return LoadDefinition((DictionaryEntry)def); } return def == null ? DefaultHighlighting : (IHighlightingStrategy)def; } else { return DefaultHighlighting; } } protected virtual void OnReloadSyntaxHighlighting(EventArgs e) { if (ReloadSyntaxHighlighting != null) { ReloadSyntaxHighlighting(this, e); } } public event EventHandler ReloadSyntaxHighlighting; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightingStrategyFactory.cs ================================================ // // // // // $Revision: 1965 $ // using System; namespace ICSharpCode.TextEditor.Document { public class HighlightingStrategyFactory { public static IHighlightingStrategy CreateHighlightingStrategy() { return (IHighlightingStrategy)HighlightingManager.Manager.HighlightingDefinitions["Default"]; } public static IHighlightingStrategy CreateHighlightingStrategy(string name) { IHighlightingStrategy highlightingStrategy = HighlightingManager.Manager.FindHighlighter(name); if (highlightingStrategy == null) { return CreateHighlightingStrategy(); } return highlightingStrategy; } public static IHighlightingStrategy CreateHighlightingStrategyForFile(string fileName) { IHighlightingStrategy highlightingStrategy = HighlightingManager.Manager.FindHighlighterForFile(fileName); if (highlightingStrategy == null) { return CreateHighlightingStrategy(); } return highlightingStrategy; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/IHighlightingStrategy.cs ================================================ // // // // // $Revision: 3037 $ // using System; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Document { /// /// A highlighting strategy for a buffer. /// public interface IHighlightingStrategy { /// /// The name of the highlighting strategy, must be unique /// string Name { get; } /// /// The file extenstions on which this highlighting strategy gets /// used /// string[] Extensions { get; } Dictionary Properties { get; } // returns special color. (BackGround Color, Cursor Color and so on) /// /// Gets the color of an Environment element. /// HighlightColor GetColorFor(string name); /// /// Used internally, do not call /// void MarkTokens(IDocument document, List lines); /// /// Used internally, do not call /// void MarkTokens(IDocument document); } public interface IHighlightingStrategyUsingRuleSets : IHighlightingStrategy { /// /// Used internally, do not call /// HighlightRuleSet GetRuleSet(Span span); /// /// Used internally, do not call /// HighlightColor GetColor(IDocument document, LineSegment keyWord, int index, int length); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/NextMarker.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Xml; namespace ICSharpCode.TextEditor.Document { /// /// Used for mark next token /// public class NextMarker { string what; HighlightColor color; bool markMarker = false; /// /// String value to indicate to mark next token /// public string What { get { return what; } } /// /// Color for marking next token /// public HighlightColor Color { get { return color; } } /// /// If true the indication text will be marked with the same color /// too /// public bool MarkMarker { get { return markMarker; } } /// /// Creates a new instance of /// public NextMarker(XmlElement mark) { color = new HighlightColor(mark); what = mark.InnerText; if (mark.Attributes["markmarker"] != null) { markMarker = Boolean.Parse(mark.Attributes["markmarker"].InnerText); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/PrevMarker.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Xml; namespace ICSharpCode.TextEditor.Document { /// /// Used for mark previous token /// public class PrevMarker { string what; HighlightColor color; bool markMarker = false; /// /// String value to indicate to mark previous token /// public string What { get { return what; } } /// /// Color for marking previous token /// public HighlightColor Color { get { return color; } } /// /// If true the indication text will be marked with the same color /// too /// public bool MarkMarker { get { return markMarker; } } /// /// Creates a new instance of /// public PrevMarker(XmlElement mark) { color = new HighlightColor(mark); what = mark.InnerText; if (mark.Attributes["markmarker"] != null) { markMarker = Boolean.Parse(mark.Attributes["markmarker"].InnerText); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/Span.cs ================================================ // // // // // $Revision: 2115 $ // using System; using System.Xml; namespace ICSharpCode.TextEditor.Document { public sealed class Span { bool stopEOL; HighlightColor color; HighlightColor beginColor; HighlightColor endColor; char[] begin; char[] end; string name; string rule; HighlightRuleSet ruleSet; char escapeCharacter; bool ignoreCase; bool isBeginSingleWord; bool? isBeginStartOfLine; bool isEndSingleWord; internal HighlightRuleSet RuleSet { get { return ruleSet; } set { ruleSet = value; } } public bool IgnoreCase { get { return ignoreCase; } set { ignoreCase = value; } } public bool StopEOL { get { return stopEOL; } } public bool? IsBeginStartOfLine { get { return isBeginStartOfLine; } } public bool IsBeginSingleWord { get { return isBeginSingleWord; } } public bool IsEndSingleWord { get { return isEndSingleWord; } } public HighlightColor Color { get { return color; } } public HighlightColor BeginColor { get { if(beginColor != null) { return beginColor; } else { return color; } } } public HighlightColor EndColor { get { return endColor!=null ? endColor : color; } } public char[] Begin { get { return begin; } } public char[] End { get { return end; } } public string Name { get { return name; } } public string Rule { get { return rule; } } /// /// Gets the escape character of the span. The escape character is a character that can be used in front /// of the span end to make it not end the span. The escape character followed by another escape character /// means the escape character was escaped like in @"a "" b" literals in C#. /// The default value '\0' means no escape character is allowed. /// public char EscapeCharacter { get { return escapeCharacter; } } public Span(XmlElement span) { color = new HighlightColor(span); if (span.HasAttribute("rule")) { rule = span.GetAttribute("rule"); } if (span.HasAttribute("escapecharacter")) { escapeCharacter = span.GetAttribute("escapecharacter")[0]; } name = span.GetAttribute("name"); if (span.HasAttribute("stopateol")) { stopEOL = Boolean.Parse(span.GetAttribute("stopateol")); } begin = span["Begin"].InnerText.ToCharArray(); beginColor = new HighlightColor(span["Begin"], color); if (span["Begin"].HasAttribute("singleword")) { this.isBeginSingleWord = Boolean.Parse(span["Begin"].GetAttribute("singleword")); } if (span["Begin"].HasAttribute("startofline")) { this.isBeginStartOfLine = Boolean.Parse(span["Begin"].GetAttribute("startofline")); } if (span["End"] != null) { end = span["End"].InnerText.ToCharArray(); endColor = new HighlightColor(span["End"], color); if (span["End"].HasAttribute("singleword")) { this.isEndSingleWord = Boolean.Parse(span["End"].GetAttribute("singleword")); } } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SpanStack.cs ================================================ // // // // // $Revision: 1471 $ // using System; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Document { /// /// A stack of Span instances. Works like Stack<Span>, but can be cloned quickly /// because it is implemented as linked list. /// public sealed class SpanStack : ICloneable, IEnumerable { internal sealed class StackNode { public readonly StackNode Previous; public readonly Span Data; public StackNode(StackNode previous, Span data) { this.Previous = previous; this.Data = data; } } StackNode top = null; public Span Pop() { Span s = top.Data; top = top.Previous; return s; } public Span Peek() { return top.Data; } public void Push(Span s) { top = new StackNode(top, s); } public bool IsEmpty { get { return top == null; } } public SpanStack Clone() { SpanStack n = new SpanStack(); n.top = this.top; return n; } object ICloneable.Clone() { return this.Clone(); } public Enumerator GetEnumerator() { return new Enumerator(new StackNode(top, null)); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } public struct Enumerator : IEnumerator { StackNode c; internal Enumerator(StackNode node) { c = node; } public Span Current { get { return c.Data; } } object System.Collections.IEnumerator.Current { get { return c.Data; } } public void Dispose() { c = null; } public bool MoveNext() { c = c.Previous; return c != null; } public void Reset() { throw new NotSupportedException(); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SyntaxModes/FileSyntaxModeProvider.cs ================================================ // // // // // $Revision: 2533 $ // using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; using System.Xml; namespace ICSharpCode.TextEditor.Document { public class FileSyntaxModeProvider : ISyntaxModeFileProvider { string directory; List syntaxModes = null; public ICollection SyntaxModes { get { return syntaxModes; } } public FileSyntaxModeProvider(string directory) { this.directory = directory; UpdateSyntaxModeList(); } public void UpdateSyntaxModeList() { string syntaxModeFile = Path.Combine(directory, "SyntaxModes.xml"); if (File.Exists(syntaxModeFile)) { Stream s = File.OpenRead(syntaxModeFile); syntaxModes = SyntaxMode.GetSyntaxModes(s); s.Close(); } else { syntaxModes = ScanDirectory(directory); } } public XmlTextReader GetSyntaxModeFile(SyntaxMode syntaxMode) { string syntaxModeFile = Path.Combine(directory, syntaxMode.FileName); if (!File.Exists(syntaxModeFile)) { throw new HighlightingDefinitionInvalidException("Can't load highlighting definition " + syntaxModeFile + " (file not found)!"); } return new XmlTextReader(File.OpenRead(syntaxModeFile)); } List ScanDirectory(string directory) { string[] files = Directory.GetFiles(directory); List modes = new List(); foreach (string file in files) { if (Path.GetExtension(file).Equals(".XSHD", StringComparison.OrdinalIgnoreCase)) { XmlTextReader reader = new XmlTextReader(file); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case "SyntaxDefinition": string name = reader.GetAttribute("name"); string extensions = reader.GetAttribute("extensions"); modes.Add(new SyntaxMode(Path.GetFileName(file), name, extensions)); goto bailout; default: throw new HighlightingDefinitionInvalidException("Unknown root node in syntax highlighting file :" + reader.Name); } } } bailout: reader.Close(); } } return modes; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SyntaxModes/ISyntaxModeFileProvider.cs ================================================ // // // // // $Revision: 1301 $ // using System; using System.Collections.Generic; using System.Xml; namespace ICSharpCode.TextEditor.Document { public interface ISyntaxModeFileProvider { ICollection SyntaxModes { get; } XmlTextReader GetSyntaxModeFile(SyntaxMode syntaxMode); void UpdateSyntaxModeList(); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SyntaxModes/ResourceSyntaxModeProvider.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Xml; namespace ICSharpCode.TextEditor.Document { public class ResourceSyntaxModeProvider : ISyntaxModeFileProvider { List syntaxModes = null; public ICollection SyntaxModes { get { return syntaxModes; } } public ResourceSyntaxModeProvider() { Assembly assembly = typeof(SyntaxMode).Assembly; Stream syntaxModeStream = assembly.GetManifestResourceStream("ICSharpCode.TextEditor.Resources.SyntaxModes.xml"); if (syntaxModeStream != null) { syntaxModes = SyntaxMode.GetSyntaxModes(syntaxModeStream); } else { syntaxModes = new List(); } } public XmlTextReader GetSyntaxModeFile(SyntaxMode syntaxMode) { Assembly assembly = typeof(SyntaxMode).Assembly; return new XmlTextReader(assembly.GetManifestResourceStream("ICSharpCode.TextEditor.Resources." + syntaxMode.FileName)); } public void UpdateSyntaxModeList() { // resources don't change during runtime } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SyntaxModes/SyntaxMode.cs ================================================ // // // // // $Revision: 2533 $ // using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; using System.Xml; namespace ICSharpCode.TextEditor.Document { public class SyntaxMode { string fileName; string name; string[] extensions; public string FileName { get { return fileName; } set { fileName = value; } } public string Name { get { return name; } set { name = value; } } public string[] Extensions { get { return extensions; } set { extensions = value; } } public SyntaxMode(string fileName, string name, string extensions) { this.fileName = fileName; this.name = name; this.extensions = extensions.Split(';', '|', ','); } public SyntaxMode(string fileName, string name, string[] extensions) { this.fileName = fileName; this.name = name; this.extensions = extensions; } public static List GetSyntaxModes(Stream xmlSyntaxModeStream) { XmlTextReader reader = new XmlTextReader(xmlSyntaxModeStream); List syntaxModes = new List(); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.Name) { case "SyntaxModes": string version = reader.GetAttribute("version"); if (version != "1.0") { throw new HighlightingDefinitionInvalidException("Unknown syntax mode file defininition with version " + version); } break; case "Mode": syntaxModes.Add(new SyntaxMode(reader.GetAttribute("file"), reader.GetAttribute("name"), reader.GetAttribute("extensions"))); break; default: throw new HighlightingDefinitionInvalidException("Unknown node in syntax mode file :" + reader.Name); } break; } } reader.Close(); return syntaxModes; } public override string ToString() { return String.Format("[SyntaxMode: FileName={0}, Name={1}, Extensions=({2})]", fileName, name, String.Join(",", extensions)); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Diagnostics; using System.Drawing; namespace ICSharpCode.TextEditor.Document { public enum TextWordType { Word, Space, Tab } /// /// This class represents single words with color information, two special versions of a word are /// spaces and tabs. /// public class TextWord { HighlightColor color; LineSegment line; IDocument document; int offset; int length; public sealed class SpaceTextWord : TextWord { public SpaceTextWord() { length = 1; } public SpaceTextWord(HighlightColor color) { length = 1; base.SyntaxColor = color; } public override Font GetFont(FontContainer fontContainer) { return null; } public override TextWordType Type { get { return TextWordType.Space; } } public override bool IsWhiteSpace { get { return true; } } } public sealed class TabTextWord : TextWord { public TabTextWord() { length = 1; } public TabTextWord(HighlightColor color) { length = 1; base.SyntaxColor = color; } public override Font GetFont(FontContainer fontContainer) { return null; } public override TextWordType Type { get { return TextWordType.Tab; } } public override bool IsWhiteSpace { get { return true; } } } static TextWord spaceWord = new SpaceTextWord(); static TextWord tabWord = new TabTextWord(); bool hasDefaultColor; public static TextWord Space { get { return spaceWord; } } public static TextWord Tab { get { return tabWord; } } public int Offset { get { return offset; } } public int Length { get { return length; } } /// /// Splits the into two parts: the part before is assigned to /// the reference parameter , the part after is returned. /// public static TextWord Split(ref TextWord word, int pos) { #if DEBUG if (word.Type != TextWordType.Word) throw new ArgumentException("word.Type must be Word"); if (pos <= 0) throw new ArgumentOutOfRangeException("pos", pos, "pos must be > 0"); if (pos >= word.Length) throw new ArgumentOutOfRangeException("pos", pos, "pos must be < word.Length"); #endif TextWord after = new TextWord(word.document, word.line, word.offset + pos, word.length - pos, word.color, word.hasDefaultColor); word = new TextWord(word.document, word.line, word.offset, pos, word.color, word.hasDefaultColor); return after; } public bool HasDefaultColor { get { return hasDefaultColor; } } public virtual TextWordType Type { get { return TextWordType.Word; } } public string Word { get { if (document == null) { return String.Empty; } return document.GetText(line.Offset + offset, length); } } public virtual Font GetFont(FontContainer fontContainer) { return color.GetFont(fontContainer); } public Color Color { get { if (color == null) return Color.Black; else return color.Color; } } public bool Bold { get { if (color == null) return false; else return color.Bold; } } public bool Italic { get { if (color == null) return false; else return color.Italic; } } public HighlightColor SyntaxColor { get { return color; } set { Debug.Assert(value != null); color = value; } } public virtual bool IsWhiteSpace { get { return false; } } protected TextWord() { } // TAB public TextWord(IDocument document, LineSegment line, int offset, int length, HighlightColor color, bool hasDefaultColor) { Debug.Assert(document != null); Debug.Assert(line != null); Debug.Assert(color != null); this.document = document; this.line = line; this.offset = offset; this.length = length; this.color = color; this.hasDefaultColor = hasDefaultColor; } /// /// Converts a instance to string (for debug purposes) /// public override string ToString() { return "[TextWord: Word = " + Word + ", Color = " + Color + "]"; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/IDocument.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Collections.Generic; using System.Drawing; using ICSharpCode.TextEditor.Undo; namespace ICSharpCode.TextEditor.Document { /// /// This interface represents a container which holds a text sequence and /// all necessary information about it. It is used as the base for a text editor. /// public interface IDocument { ITextEditorProperties TextEditorProperties { get; set; } UndoStack UndoStack { get; } /// /// If true the document can't be altered /// bool ReadOnly { get; set; } /// /// The attached to the instance /// IFormattingStrategy FormattingStrategy { get; set; } /// /// The attached to the instance /// ITextBufferStrategy TextBufferStrategy { get; } /// /// The attached to the instance /// FoldingManager FoldingManager { get; } /// /// The attached to the instance /// IHighlightingStrategy HighlightingStrategy { get; set; } /// /// The attached to the instance /// BookmarkManager BookmarkManager { get; } MarkerStrategy MarkerStrategy { get; } // /// // /// The attached to the instance // /// // SelectionManager SelectionManager { // get; // } #region ILineManager interface /// /// A collection of all line segments /// /// /// The collection should only be used if you're aware /// of the 'last line ends with a delimiter problem'. Otherwise /// the method should be used. /// IList LineSegmentCollection { get; } /// /// The total number of lines in the document. /// int TotalNumberOfLines { get; } /// /// Returns a valid line number for the given offset. /// /// /// A offset which points to a character in the line which /// line number is returned. /// /// /// An int which value is the line number. /// /// If offset points not to a valid position int GetLineNumberForOffset(int offset); /// /// Returns a for the given offset. /// /// /// A offset which points to a character in the line which /// is returned. /// /// /// A object. /// /// If offset points not to a valid position LineSegment GetLineSegmentForOffset(int offset); /// /// Returns a for the given line number. /// This function should be used to get a line instead of getting the /// line using the . /// /// /// The line number which is requested. /// /// /// A object. /// /// If offset points not to a valid position LineSegment GetLineSegment(int lineNumber); /// /// Get the first logical line for a given visible line. /// example : lineNumber == 100 foldings are in the linetracker /// between 0..1 (2 folded, invisible lines) this method returns 102 /// the 'logical' line number /// int GetFirstLogicalLine(int lineNumber); /// /// Get the last logical line for a given visible line. /// example : lineNumber == 100 foldings are in the linetracker /// between 0..1 (2 folded, invisible lines) this method returns 102 /// the 'logical' line number /// int GetLastLogicalLine(int lineNumber); /// /// Get the visible line for a given logical line. /// example : lineNumber == 100 foldings are in the linetracker /// between 0..1 (2 folded, invisible lines) this method returns 98 /// the 'visible' line number /// int GetVisibleLine(int lineNumber); // /// // /// Get the visible column for a given logical line and logical column. // /// // int GetVisibleColumn(int logicalLine, int logicalColumn); /// /// Get the next visible line after lineNumber /// int GetNextVisibleLineAbove(int lineNumber, int lineCount); /// /// Get the next visible line below lineNumber /// int GetNextVisibleLineBelow(int lineNumber, int lineCount); event EventHandler LineLengthChanged; event EventHandler LineCountChanged; event EventHandler LineDeleted; #endregion #region ITextBufferStrategy interface /// /// Get the whole text as string. /// When setting the text using the TextContent property, the undo stack is cleared. /// Set TextContent only for actions such as loading a file; if you want to change the current document /// use the Replace method instead. /// string TextContent { get; set; } /// /// The current length of the sequence of characters that can be edited. /// int TextLength { get; } /// /// Inserts a string of characters into the sequence. /// /// /// offset where to insert the string. /// /// /// text to be inserted. /// void Insert(int offset, string text); /// /// Removes some portion of the sequence. /// /// /// offset of the remove. /// /// /// number of characters to remove. /// void Remove(int offset, int length); /// /// Replace some portion of the sequence. /// /// /// offset. /// /// /// number of characters to replace. /// /// /// text to be replaced with. /// void Replace(int offset, int length, string text); /// /// Returns a specific char of the sequence. /// /// /// Offset of the char to get. /// char GetCharAt(int offset); /// /// Fetches a string of characters contained in the sequence. /// /// /// Offset into the sequence to fetch /// /// /// number of characters to copy. /// string GetText(int offset, int length); #endregion string GetText(ISegment segment); #region ITextModel interface /// /// returns the logical line/column position from an offset /// TextLocation OffsetToPosition(int offset); /// /// returns the offset from a logical line/column position /// int PositionToOffset(TextLocation p); #endregion /// /// A container where all TextAreaUpdate objects get stored /// List UpdateQueue { get; } /// /// Requests an update of the textarea /// void RequestUpdate(TextAreaUpdate update); /// /// Commits all updates in the queue to the textarea (the /// textarea will be painted) /// void CommitUpdate(); /// /// Moves, Resizes, Removes a list of segments on insert/remove/replace events. /// void UpdateSegmentListOnDocumentChange(List list, DocumentEventArgs e) where T : ISegment; /// /// Is fired when CommitUpdate is called /// event EventHandler UpdateCommited; /// /// event DocumentEventHandler DocumentAboutToBeChanged; /// /// event DocumentEventHandler DocumentChanged; event EventHandler TextContentChanged; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/ISegment.cs ================================================ // // // // // $Revision: 1966 $ // namespace ICSharpCode.TextEditor.Document { /// /// This interface is used to describe a span inside a text sequence /// public interface ISegment { /// /// The offset where the span begins /// int Offset { get; set; } /// /// The length of the span /// int Length { get; set; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/ITextEditorProperties.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Drawing; using System.Text; namespace ICSharpCode.TextEditor.Document { public interface ITextEditorProperties { bool AutoInsertCurlyBracket { // is wrapped in text editor control get; set; } bool HideMouseCursor { // is wrapped in text editor control get; set; } bool IsIconBarVisible { // is wrapped in text editor control get; set; } bool AllowCaretBeyondEOL { get; set; } bool ShowMatchingBracket { // is wrapped in text editor control get; set; } bool CutCopyWholeLine { get; set; } System.Drawing.Text.TextRenderingHint TextRenderingHint { // is wrapped in text editor control get; set; } bool MouseWheelScrollDown { get; set; } bool MouseWheelTextZoom { get; set; } string LineTerminator { get; set; } LineViewerStyle LineViewerStyle { // is wrapped in text editor control get; set; } bool ShowInvalidLines { // is wrapped in text editor control get; set; } int VerticalRulerRow { // is wrapped in text editor control get; set; } bool ShowSpaces { // is wrapped in text editor control get; set; } bool ShowTabs { // is wrapped in text editor control get; set; } bool ShowEOLMarker { // is wrapped in text editor control get; set; } bool ConvertTabsToSpaces { // is wrapped in text editor control get; set; } bool ShowHorizontalRuler { // is wrapped in text editor control get; set; } bool ShowVerticalRuler { // is wrapped in text editor control get; set; } Encoding Encoding { get; set; } bool EnableFolding { // is wrapped in text editor control get; set; } bool ShowLineNumbers { // is wrapped in text editor control get; set; } /// /// The width of a tab. /// int TabIndent { // is wrapped in text editor control get; set; } /// /// The amount of spaces a tab is converted to if ConvertTabsToSpaces is true. /// int IndentationSize { get; set; } IndentStyle IndentStyle { // is wrapped in text editor control get; set; } DocumentSelectionMode DocumentSelectionMode { get; set; } Font Font { // is wrapped in text editor control get; set; } FontContainer FontContainer { get; } BracketMatchingStyle BracketMatchingStyle { // is wrapped in text editor control get; set; } bool SupportReadOnlySegments { get; set; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DeferredEventList.cs ================================================ // // // // // $Revision$ // using System; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Document { /// /// A list of events that are fired after the line manager has finished working. /// struct DeferredEventList { internal List removedLines; internal List textAnchor; public void AddRemovedLine(LineSegment line) { if (removedLines == null) removedLines = new List(); removedLines.Add(line); } public void AddDeletedAnchor(TextAnchor anchor) { if (textAnchor == null) textAnchor = new List(); textAnchor.Add(anchor); } public void RaiseEvents() { // removedLines is raised by the LineManager if (textAnchor != null) { foreach (TextAnchor a in textAnchor) { a.RaiseDeleted(); } } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineManager.cs ================================================ // // // // // $Revision: 3274 $ // using System; using System.Collections.Generic; using System.Diagnostics; namespace ICSharpCode.TextEditor.Document { internal sealed class LineManager { LineSegmentTree lineCollection = new LineSegmentTree(); IDocument document; IHighlightingStrategy highlightingStrategy; public IList LineSegmentCollection { get { return lineCollection; } } public int TotalNumberOfLines { get { return lineCollection.Count; } } public IHighlightingStrategy HighlightingStrategy { get { return highlightingStrategy; } set { if (highlightingStrategy != value) { highlightingStrategy = value; if (highlightingStrategy != null) { highlightingStrategy.MarkTokens(document); } } } } public LineManager(IDocument document, IHighlightingStrategy highlightingStrategy) { this.document = document; this.highlightingStrategy = highlightingStrategy; } public int GetLineNumberForOffset(int offset) { return GetLineSegmentForOffset(offset).LineNumber; } public LineSegment GetLineSegmentForOffset(int offset) { return lineCollection.GetByOffset(offset); } public LineSegment GetLineSegment(int lineNr) { return lineCollection[lineNr]; } public void Insert(int offset, string text) { Replace(offset, 0, text); } public void Remove(int offset, int length) { Replace(offset, length, String.Empty); } public void Replace(int offset, int length, string text) { Debug.WriteLine("Replace offset="+offset+" length="+length+" text.Length="+text.Length); int lineStart = GetLineNumberForOffset(offset); int oldNumberOfLines = this.TotalNumberOfLines; DeferredEventList deferredEventList = new DeferredEventList(); RemoveInternal(ref deferredEventList, offset, length); int numberOfLinesAfterRemoving = this.TotalNumberOfLines; if (!string.IsNullOrEmpty(text)) { InsertInternal(offset, text); } // #if DEBUG // Console.WriteLine("New line collection:"); // Console.WriteLine(lineCollection.GetTreeAsString()); // Console.WriteLine("New text:"); // Console.WriteLine("'" + document.TextContent + "'"); // #endif // Only fire events after RemoveInternal+InsertInternal finished completely: // Otherwise we would expose inconsistent state to the event handlers. RunHighlighter(lineStart, 1 + Math.Max(0, this.TotalNumberOfLines - numberOfLinesAfterRemoving)); if (deferredEventList.removedLines != null) { foreach (LineSegment ls in deferredEventList.removedLines) OnLineDeleted(new LineEventArgs(document, ls)); } deferredEventList.RaiseEvents(); if (this.TotalNumberOfLines != oldNumberOfLines) { OnLineCountChanged(new LineCountChangeEventArgs(document, lineStart, this.TotalNumberOfLines - oldNumberOfLines)); } } void RemoveInternal(ref DeferredEventList deferredEventList, int offset, int length) { Debug.Assert(length >= 0); if (length == 0) return; LineSegmentTree.Enumerator it = lineCollection.GetEnumeratorForOffset(offset); LineSegment startSegment = it.Current; int startSegmentOffset = startSegment.Offset; if (offset + length < startSegmentOffset + startSegment.TotalLength) { // just removing a part of this line segment startSegment.RemovedLinePart(ref deferredEventList, offset - startSegmentOffset, length); SetSegmentLength(startSegment, startSegment.TotalLength - length); return; } // merge startSegment with another line segment because startSegment's delimiter was deleted // possibly remove lines in between if multiple delimiters were deleted int charactersRemovedInStartLine = startSegmentOffset + startSegment.TotalLength - offset; Debug.Assert(charactersRemovedInStartLine > 0); startSegment.RemovedLinePart(ref deferredEventList, offset - startSegmentOffset, charactersRemovedInStartLine); LineSegment endSegment = lineCollection.GetByOffset(offset + length); if (endSegment == startSegment) { // special case: we are removing a part of the last line up to the // end of the document SetSegmentLength(startSegment, startSegment.TotalLength - length); return; } int endSegmentOffset = endSegment.Offset; int charactersLeftInEndLine = endSegmentOffset + endSegment.TotalLength - (offset + length); endSegment.RemovedLinePart(ref deferredEventList, 0, endSegment.TotalLength - charactersLeftInEndLine); startSegment.MergedWith(endSegment, offset - startSegmentOffset); SetSegmentLength(startSegment, startSegment.TotalLength - charactersRemovedInStartLine + charactersLeftInEndLine); startSegment.DelimiterLength = endSegment.DelimiterLength; // remove all segments between startSegment (excl.) and endSegment (incl.) it.MoveNext(); LineSegment segmentToRemove; do { segmentToRemove = it.Current; it.MoveNext(); lineCollection.RemoveSegment(segmentToRemove); segmentToRemove.Deleted(ref deferredEventList); } while (segmentToRemove != endSegment); } void InsertInternal(int offset, string text) { LineSegment segment = lineCollection.GetByOffset(offset); DelimiterSegment ds = NextDelimiter(text, 0); if (ds == null) { // no newline is being inserted, all text is inserted in a single line segment.InsertedLinePart(offset - segment.Offset, text.Length); SetSegmentLength(segment, segment.TotalLength + text.Length); return; } LineSegment firstLine = segment; firstLine.InsertedLinePart(offset - firstLine.Offset, ds.Offset); int lastDelimiterEnd = 0; while (ds != null) { // split line segment at line delimiter int lineBreakOffset = offset + ds.Offset + ds.Length; int segmentOffset = segment.Offset; int lengthAfterInsertionPos = segmentOffset + segment.TotalLength - (offset + lastDelimiterEnd); lineCollection.SetSegmentLength(segment, lineBreakOffset - segmentOffset); LineSegment newSegment = lineCollection.InsertSegmentAfter(segment, lengthAfterInsertionPos); segment.DelimiterLength = ds.Length; segment = newSegment; lastDelimiterEnd = ds.Offset + ds.Length; ds = NextDelimiter(text, lastDelimiterEnd); } firstLine.SplitTo(segment); // insert rest after last delimiter if (lastDelimiterEnd != text.Length) { segment.InsertedLinePart(0, text.Length - lastDelimiterEnd); SetSegmentLength(segment, segment.TotalLength + text.Length - lastDelimiterEnd); } } void SetSegmentLength(LineSegment segment, int newTotalLength) { int delta = newTotalLength - segment.TotalLength; if (delta != 0) { lineCollection.SetSegmentLength(segment, newTotalLength); OnLineLengthChanged(new LineLengthChangeEventArgs(document, segment, delta)); } } void RunHighlighter(int firstLine, int lineCount) { if (highlightingStrategy != null) { List markLines = new List(); LineSegmentTree.Enumerator it = lineCollection.GetEnumeratorForIndex(firstLine); for (int i = 0; i < lineCount && it.IsValid; i++) { markLines.Add(it.Current); it.MoveNext(); } highlightingStrategy.MarkTokens(document, markLines); } } public void SetContent(string text) { lineCollection.Clear(); if (text != null) { Replace(0, 0, text); } } public int GetVisibleLine(int logicalLineNumber) { if (!document.TextEditorProperties.EnableFolding) { return logicalLineNumber; } int visibleLine = 0; int foldEnd = 0; List foldings = document.FoldingManager.GetTopLevelFoldedFoldings(); foreach (FoldMarker fm in foldings) { if (fm.StartLine >= logicalLineNumber) { break; } if (fm.StartLine >= foldEnd) { visibleLine += fm.StartLine - foldEnd; if (fm.EndLine > logicalLineNumber) { return visibleLine; } foldEnd = fm.EndLine; } } // Debug.Assert(logicalLineNumber >= foldEnd); visibleLine += logicalLineNumber - foldEnd; return visibleLine; } public int GetFirstLogicalLine(int visibleLineNumber) { if (!document.TextEditorProperties.EnableFolding) { return visibleLineNumber; } int v = 0; int foldEnd = 0; List foldings = document.FoldingManager.GetTopLevelFoldedFoldings(); foreach (FoldMarker fm in foldings) { if (fm.StartLine >= foldEnd) { if (v + fm.StartLine - foldEnd >= visibleLineNumber) { break; } v += fm.StartLine - foldEnd; foldEnd = fm.EndLine; } } // help GC foldings.Clear(); foldings = null; return foldEnd + visibleLineNumber - v; } public int GetLastLogicalLine(int visibleLineNumber) { if (!document.TextEditorProperties.EnableFolding) { return visibleLineNumber; } return GetFirstLogicalLine(visibleLineNumber + 1) - 1; } // TODO : speedup the next/prev visible line search // HOW? : save the foldings in a sorted list and lookup the // line numbers in this list public int GetNextVisibleLineAbove(int lineNumber, int lineCount) { int curLineNumber = lineNumber; if (document.TextEditorProperties.EnableFolding) { for (int i = 0; i < lineCount && curLineNumber < TotalNumberOfLines; ++i) { ++curLineNumber; while (curLineNumber < TotalNumberOfLines && (curLineNumber >= lineCollection.Count || !document.FoldingManager.IsLineVisible(curLineNumber))) { ++curLineNumber; } } } else { curLineNumber += lineCount; } return Math.Min(TotalNumberOfLines - 1, curLineNumber); } public int GetNextVisibleLineBelow(int lineNumber, int lineCount) { int curLineNumber = lineNumber; if (document.TextEditorProperties.EnableFolding) { for (int i = 0; i < lineCount; ++i) { --curLineNumber; while (curLineNumber >= 0 && !document.FoldingManager.IsLineVisible(curLineNumber)) { --curLineNumber; } } } else { curLineNumber -= lineCount; } return Math.Max(0, curLineNumber); } // use always the same DelimiterSegment object for the NextDelimiter DelimiterSegment delimiterSegment = new DelimiterSegment(); DelimiterSegment NextDelimiter(string text, int offset) { for (int i = offset; i < text.Length; i++) { switch (text[i]) { case '\r': if (i + 1 < text.Length) { if (text[i + 1] == '\n') { delimiterSegment.Offset = i; delimiterSegment.Length = 2; return delimiterSegment; } } goto case '\n'; case '\n': delimiterSegment.Offset = i; delimiterSegment.Length = 1; return delimiterSegment; } } return null; } void OnLineCountChanged(LineCountChangeEventArgs e) { if (LineCountChanged != null) { LineCountChanged(this, e); } } void OnLineLengthChanged(LineLengthChangeEventArgs e) { if (LineLengthChanged != null) { LineLengthChanged(this, e); } } void OnLineDeleted(LineEventArgs e) { if (LineDeleted != null) { LineDeleted(this, e); } } public event EventHandler LineLengthChanged; public event EventHandler LineCountChanged; public event EventHandler LineDeleted; sealed class DelimiterSegment { internal int Offset; internal int Length; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineManagerEventArgs.cs ================================================ // // // // // $Revision: 2691 $ // using System; namespace ICSharpCode.TextEditor.Document { public class LineCountChangeEventArgs : EventArgs { IDocument document; int start; int moved; /// /// always a valid Document which is related to the Event. /// public IDocument Document { get { return document; } } /// /// -1 if no offset was specified for this event /// public int LineStart { get { return start; } } /// /// -1 if no length was specified for this event /// public int LinesMoved { get { return moved; } } public LineCountChangeEventArgs(IDocument document, int lineStart, int linesMoved) { this.document = document; this.start = lineStart; this.moved = linesMoved; } } public class LineEventArgs : EventArgs { IDocument document; LineSegment lineSegment; public IDocument Document { get { return document; } } public LineSegment LineSegment { get { return lineSegment; } } public LineEventArgs(IDocument document, LineSegment lineSegment) { this.document = document; this.lineSegment = lineSegment; } public override string ToString() { return string.Format("[LineEventArgs Document={0} LineSegment={1}]", this.document, this.lineSegment); } } public class LineLengthChangeEventArgs : LineEventArgs { int lengthDelta; public int LengthDelta { get { return lengthDelta; } } public LineLengthChangeEventArgs(IDocument document, LineSegment lineSegment, int moved) : base(document, lineSegment) { this.lengthDelta = moved; } public override string ToString() { return string.Format("[LineLengthEventArgs Document={0} LineSegment={1} LengthDelta={2}]", this.Document, this.LineSegment, this.lengthDelta); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineSegment.cs ================================================ // // // // // $Revision: 3272 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Diagnostics; using System.Text; namespace ICSharpCode.TextEditor.Document { public sealed class LineSegment : ISegment { internal LineSegmentTree.Enumerator treeEntry; int totalLength, delimiterLength; List words; SpanStack highlightSpanStack; public TextWord GetWord(int column) { int curColumn = 0; foreach (TextWord word in words) { if (column < curColumn + word.Length) { return word; } curColumn += word.Length; } return null; } public bool IsDeleted { get { return !treeEntry.IsValid; } } public int LineNumber { get { return treeEntry.CurrentIndex; } } public int Offset { get { return treeEntry.CurrentOffset; } } public int Length { get { return totalLength - delimiterLength; } } int ISegment.Offset { get { return this.Offset; } set { throw new NotSupportedException(); } } int ISegment.Length { get { return this.Length; } set { throw new NotSupportedException(); } } public int TotalLength { get { return totalLength; } internal set { totalLength = value; } } public int DelimiterLength { get { return delimiterLength; } internal set { delimiterLength = value; } } // highlighting information public List Words { get { return words; } set { words = value; } } public HighlightColor GetColorForPosition(int x) { if (Words != null) { int xPos = 0; foreach (TextWord word in Words) { if (x < xPos + word.Length) { return word.SyntaxColor; } xPos += word.Length; } } return new HighlightColor(Color.Black, false, false); } public SpanStack HighlightSpanStack { get { return highlightSpanStack; } set { highlightSpanStack = value; } } /// /// Converts a instance to string (for debug purposes) /// public override string ToString() { if (IsDeleted) return "[LineSegment: (deleted) Length = " + Length + ", TotalLength = " + TotalLength + ", DelimiterLength = " + delimiterLength + "]"; else return "[LineSegment: LineNumber=" + LineNumber + ", Offset = "+ Offset +", Length = " + Length + ", TotalLength = " + TotalLength + ", DelimiterLength = " + delimiterLength + "]"; } #region Anchor management Util.WeakCollection anchors; public TextAnchor CreateAnchor(int column) { if (column < 0 || column > Length) throw new ArgumentOutOfRangeException("column"); TextAnchor anchor = new TextAnchor(this, column); AddAnchor(anchor); return anchor; } void AddAnchor(TextAnchor anchor) { Debug.Assert(anchor.Line == this); if (anchors == null) anchors = new Util.WeakCollection(); anchors.Add(anchor); } /// /// Is called when the LineSegment is deleted. /// internal void Deleted(ref DeferredEventList deferredEventList) { //Console.WriteLine("Deleted"); treeEntry = LineSegmentTree.Enumerator.Invalid; if (anchors != null) { foreach (TextAnchor a in anchors) { a.Delete(ref deferredEventList); } anchors = null; } } /// /// Is called when a part of the line is removed. /// internal void RemovedLinePart(ref DeferredEventList deferredEventList, int startColumn, int length) { if (length == 0) return; Debug.Assert(length > 0); //Console.WriteLine("RemovedLinePart " + startColumn + ", " + length); if (anchors != null) { List deletedAnchors = null; foreach (TextAnchor a in anchors) { if (a.ColumnNumber > startColumn) { if (a.ColumnNumber >= startColumn + length) { a.ColumnNumber -= length; } else { if (deletedAnchors == null) deletedAnchors = new List(); a.Delete(ref deferredEventList); deletedAnchors.Add(a); } } } if (deletedAnchors != null) { foreach (TextAnchor a in deletedAnchors) { anchors.Remove(a); } } } } /// /// Is called when a part of the line is inserted. /// internal void InsertedLinePart(int startColumn, int length) { if (length == 0) return; Debug.Assert(length > 0); //Console.WriteLine("InsertedLinePart " + startColumn + ", " + length); if (anchors != null) { foreach (TextAnchor a in anchors) { if (a.MovementType == AnchorMovementType.BeforeInsertion ? a.ColumnNumber > startColumn : a.ColumnNumber >= startColumn) { a.ColumnNumber += length; } } } } /// /// Is called after another line's content is appended to this line because the newline in between /// was deleted. /// The DefaultLineManager will call Deleted() on the deletedLine after the MergedWith call. /// /// firstLineLength: the length of the line before the merge. /// internal void MergedWith(LineSegment deletedLine, int firstLineLength) { //Console.WriteLine("MergedWith"); if (deletedLine.anchors != null) { foreach (TextAnchor a in deletedLine.anchors) { a.Line = this; AddAnchor(a); a.ColumnNumber += firstLineLength; } deletedLine.anchors = null; } } /// /// Is called after a newline was inserted into this line, splitting it into this and followingLine. /// internal void SplitTo(LineSegment followingLine) { //Console.WriteLine("SplitTo"); if (anchors != null) { List movedAnchors = null; foreach (TextAnchor a in anchors) { if (a.MovementType == AnchorMovementType.BeforeInsertion ? a.ColumnNumber > this.Length : a.ColumnNumber >= this.Length) { a.Line = followingLine; followingLine.AddAnchor(a); a.ColumnNumber -= this.Length; if (movedAnchors == null) movedAnchors = new List(); movedAnchors.Add(a); } } if (movedAnchors != null) { foreach (TextAnchor a in movedAnchors) { anchors.Remove(a); } } } } #endregion } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineSegmentTree.cs ================================================ // // // // // $Revision: 2683 $ // using System; using System.Collections.Generic; using System.Diagnostics; using ICSharpCode.TextEditor.Util; namespace ICSharpCode.TextEditor.Document { /// /// Data structure for efficient management of the line segments (most operations are O(lg n)). /// This implements an augmented red-black tree where each node has fields for the number of /// nodes in its subtree (like an order statistics tree) for access by index(=line number). /// Additionally, each node knows the total length of all segments in its subtree. /// This means we can find nodes by offset in O(lg n) time. Since the offset itself is not stored in /// the line segment but computed from the lengths stored in the tree, we adjusting the offsets when /// text is inserted in one line means we just have to increment the totalLength of the affected line and /// its parent nodes - an O(lg n) operation. /// However this means getting the line number or offset from a LineSegment is not a constant time /// operation, but takes O(lg n). /// /// NOTE: The tree is never empty, Clear() causes it to contain an empty segment. /// sealed class LineSegmentTree : IList { internal struct RBNode { internal LineSegment lineSegment; internal int count; internal int totalLength; public RBNode(LineSegment lineSegment) { this.lineSegment = lineSegment; this.count = 1; this.totalLength = lineSegment.TotalLength; } public override string ToString() { return "[RBNode count=" + count + " totalLength="+totalLength + " lineSegment.LineNumber=" + lineSegment.LineNumber + " lineSegment.Offset=" + lineSegment.Offset + " lineSegment.TotalLength=" + lineSegment.TotalLength + " lineSegment.DelimiterLength=" + lineSegment.DelimiterLength + "]"; } } struct MyHost : IRedBlackTreeHost { public int Compare(RBNode x, RBNode y) { throw new NotImplementedException(); } public bool Equals(RBNode a, RBNode b) { throw new NotImplementedException(); } public void UpdateAfterChildrenChange(RedBlackTreeNode node) { int count = 1; int totalLength = node.val.lineSegment.TotalLength; if (node.left != null) { count += node.left.val.count; totalLength += node.left.val.totalLength; } if (node.right != null) { count += node.right.val.count; totalLength += node.right.val.totalLength; } if (count != node.val.count || totalLength != node.val.totalLength) { node.val.count = count; node.val.totalLength = totalLength; if (node.parent != null) UpdateAfterChildrenChange(node.parent); } } public void UpdateAfterRotateLeft(RedBlackTreeNode node) { UpdateAfterChildrenChange(node); UpdateAfterChildrenChange(node.parent); } public void UpdateAfterRotateRight(RedBlackTreeNode node) { UpdateAfterChildrenChange(node); UpdateAfterChildrenChange(node.parent); } } readonly AugmentableRedBlackTree tree = new AugmentableRedBlackTree(new MyHost()); RedBlackTreeNode GetNode(int index) { if (index < 0 || index >= tree.Count) throw new ArgumentOutOfRangeException("index", index, "index should be between 0 and " + (tree.Count-1)); RedBlackTreeNode node = tree.root; while (true) { if (node.left != null && index < node.left.val.count) { node = node.left; } else { if (node.left != null) { index -= node.left.val.count; } if (index == 0) return node; index--; node = node.right; } } } static int GetIndexFromNode(RedBlackTreeNode node) { int index = (node.left != null) ? node.left.val.count : 0; while (node.parent != null) { if (node == node.parent.right) { if (node.parent.left != null) index += node.parent.left.val.count; index++; } node = node.parent; } return index; } RedBlackTreeNode GetNodeByOffset(int offset) { if (offset < 0 || offset > this.TotalLength) throw new ArgumentOutOfRangeException("offset", offset, "offset should be between 0 and " + this.TotalLength); if (offset == this.TotalLength) { if (tree.root == null) throw new InvalidOperationException("Cannot call GetNodeByOffset while tree is empty."); return tree.root.RightMost; } RedBlackTreeNode node = tree.root; while (true) { if (node.left != null && offset < node.left.val.totalLength) { node = node.left; } else { if (node.left != null) { offset -= node.left.val.totalLength; } offset -= node.val.lineSegment.TotalLength; if (offset < 0) return node; node = node.right; } } } static int GetOffsetFromNode(RedBlackTreeNode node) { int offset = (node.left != null) ? node.left.val.totalLength : 0; while (node.parent != null) { if (node == node.parent.right) { if (node.parent.left != null) offset += node.parent.left.val.totalLength; offset += node.parent.val.lineSegment.TotalLength; } node = node.parent; } return offset; } public LineSegment GetByOffset(int offset) { return GetNodeByOffset(offset).val.lineSegment; } /// /// Gets the total length of all line segments. Runs in O(1). /// public int TotalLength { get { if (tree.root == null) return 0; else return tree.root.val.totalLength; } } /// /// Updates the length of a line segment. Runs in O(lg n). /// public void SetSegmentLength(LineSegment segment, int newTotalLength) { if (segment == null) throw new ArgumentNullException("segment"); RedBlackTreeNode node = segment.treeEntry.it.node; segment.TotalLength = newTotalLength; default(MyHost).UpdateAfterChildrenChange(node); #if DEBUG CheckProperties(); #endif } public void RemoveSegment(LineSegment segment) { tree.RemoveAt(segment.treeEntry.it); #if DEBUG CheckProperties(); #endif } public LineSegment InsertSegmentAfter(LineSegment segment, int length) { LineSegment newSegment = new LineSegment(); newSegment.TotalLength = length; newSegment.DelimiterLength = segment.DelimiterLength; newSegment.treeEntry = InsertAfter(segment.treeEntry.it.node, newSegment); return newSegment; } Enumerator InsertAfter(RedBlackTreeNode node, LineSegment newSegment) { RedBlackTreeNode newNode = new RedBlackTreeNode(new RBNode(newSegment)); if (node.right == null) { tree.InsertAsRight(node, newNode); } else { tree.InsertAsLeft(node.right.LeftMost, newNode); } #if DEBUG CheckProperties(); #endif return new Enumerator(new RedBlackTreeIterator(newNode)); } /// /// Gets the number of items in the collections. Runs in O(1). /// public int Count { get { return tree.Count; } } /// /// Gets or sets an item by index. Runs in O(lg n). /// public LineSegment this[int index] { get { return GetNode(index).val.lineSegment; } set { throw new NotSupportedException(); } } bool ICollection.IsReadOnly { get { return true; } } /// /// Gets the index of an item. Runs in O(lg n). /// public int IndexOf(LineSegment item) { int index = item.LineNumber; if (index < 0 || index >= this.Count) return -1; if (item != this[index]) return -1; return index; } void IList.RemoveAt(int index) { throw new NotSupportedException(); } #if DEBUG [Conditional("DATACONSISTENCYTEST")] void CheckProperties() { if (tree.root == null) { Debug.Assert(this.Count == 0); } else { Debug.Assert(tree.root.val.count == this.Count); CheckProperties(tree.root); } } void CheckProperties(RedBlackTreeNode node) { int count = 1; int totalLength = node.val.lineSegment.TotalLength; if (node.left != null) { CheckProperties(node.left); count += node.left.val.count; totalLength += node.left.val.totalLength; } if (node.right != null) { CheckProperties(node.right); count += node.right.val.count; totalLength += node.right.val.totalLength; } Debug.Assert(node.val.count == count); Debug.Assert(node.val.totalLength == totalLength); } public string GetTreeAsString() { return tree.GetTreeAsString(); } #endif public LineSegmentTree() { Clear(); } /// /// Clears the list. Runs in O(1). /// public void Clear() { tree.Clear(); LineSegment emptySegment = new LineSegment(); emptySegment.TotalLength = 0; emptySegment.DelimiterLength = 0; tree.Add(new RBNode(emptySegment)); emptySegment.treeEntry = GetEnumeratorForIndex(0); #if DEBUG CheckProperties(); #endif } /// /// Tests whether an item is in the list. Runs in O(n). /// public bool Contains(LineSegment item) { return IndexOf(item) >= 0; } /// /// Copies all elements from the list to the array. /// public void CopyTo(LineSegment[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); foreach (LineSegment val in this) array[arrayIndex++] = val; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } public Enumerator GetEnumerator() { return new Enumerator(tree.GetEnumerator()); } public Enumerator GetEnumeratorForIndex(int index) { return new Enumerator(new RedBlackTreeIterator(GetNode(index))); } public Enumerator GetEnumeratorForOffset(int offset) { return new Enumerator(new RedBlackTreeIterator(GetNodeByOffset(offset))); } public struct Enumerator : IEnumerator { /// /// An invalid enumerator value. Calling MoveNext on the invalid enumerator /// will always return false, accessing Current will throw an exception. /// public static readonly Enumerator Invalid = default(Enumerator); internal RedBlackTreeIterator it; internal Enumerator(RedBlackTreeIterator it) { this.it = it; } /// /// Gets the current value. Runs in O(1). /// public LineSegment Current { get { return it.Current.lineSegment; } } public bool IsValid { get { return it.IsValid; } } /// /// Gets the index of the current value. Runs in O(lg n). /// public int CurrentIndex { get { if (it.node == null) throw new InvalidOperationException(); return GetIndexFromNode(it.node); } } /// /// Gets the offset of the current value. Runs in O(lg n). /// public int CurrentOffset { get { if (it.node == null) throw new InvalidOperationException(); return GetOffsetFromNode(it.node); } } object System.Collections.IEnumerator.Current { get { return it.Current.lineSegment; } } public void Dispose() { } /// /// Moves to the next index. Runs in O(lg n), but for k calls, the combined time is only O(k+lg n). /// public bool MoveNext() { return it.MoveNext(); } /// /// Moves to the previous index. Runs in O(lg n), but for k calls, the combined time is only O(k+lg n). /// public bool MoveBack() { return it.MoveBack(); } void System.Collections.IEnumerator.Reset() { throw new NotSupportedException(); } } void IList.Insert(int index, LineSegment item) { throw new NotSupportedException(); } void ICollection.Add(LineSegment item) { throw new NotSupportedException(); } bool ICollection.Remove(LineSegment item) { throw new NotSupportedException(); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/MarkerStrategy.cs ================================================ // // // // // $Revision: 2659 $ // using System; using System.Collections.Generic; using System.Drawing; namespace ICSharpCode.TextEditor.Document { /// /// Manages the list of markers and provides ways to retrieve markers for specific positions. /// public sealed class MarkerStrategy { List textMarker = new List(); IDocument document; public IDocument Document { get { return document; } } public IEnumerable TextMarker { get { return textMarker.AsReadOnly(); } } public void AddMarker(TextMarker item) { markersTable.Clear(); textMarker.Add(item); } public void InsertMarker(int index, TextMarker item) { markersTable.Clear(); textMarker.Insert(index, item); } public void RemoveMarker(TextMarker item) { markersTable.Clear(); textMarker.Remove(item); } public void RemoveAll(Predicate match) { markersTable.Clear(); textMarker.RemoveAll(match); } public MarkerStrategy(IDocument document) { this.document = document; document.DocumentChanged += new DocumentEventHandler(DocumentChanged); } Dictionary> markersTable = new Dictionary>(); public List GetMarkers(int offset) { if (!markersTable.ContainsKey(offset)) { List markers = new List(); for (int i = 0; i < textMarker.Count; ++i) { TextMarker marker = (TextMarker)textMarker[i]; if (marker.Offset <= offset && offset <= marker.EndOffset) { markers.Add(marker); } } markersTable[offset] = markers; } return markersTable[offset]; } public List GetMarkers(int offset, int length) { int endOffset = offset + length - 1; List markers = new List(); for (int i = 0; i < textMarker.Count; ++i) { TextMarker marker = (TextMarker)textMarker[i]; if (// start in marker region marker.Offset <= offset && offset <= marker.EndOffset || // end in marker region marker.Offset <= endOffset && endOffset <= marker.EndOffset || // marker start in region offset <= marker.Offset && marker.Offset <= endOffset || // marker end in region offset <= marker.EndOffset && marker.EndOffset <= endOffset ) { markers.Add(marker); } } return markers; } public List GetMarkers(TextLocation position) { if (position.Y >= document.TotalNumberOfLines || position.Y < 0) { return new List(); } LineSegment segment = document.GetLineSegment(position.Y); return GetMarkers(segment.Offset + position.X); } void DocumentChanged(object sender, DocumentEventArgs e) { // reset markers table markersTable.Clear(); document.UpdateSegmentListOnDocumentChange(textMarker, e); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/TextMarker.cs ================================================ // // // // // $Revision: 3206 $ // using System; using System.Drawing; namespace ICSharpCode.TextEditor.Document { public enum TextMarkerType { Invisible, SolidBlock, Underlined, WaveLine } /// /// Marks a part of a document. /// public class TextMarker : AbstractSegment { TextMarkerType textMarkerType; Color color; Color foreColor; string toolTip = null; bool overrideForeColor = false; public TextMarkerType TextMarkerType { get { return textMarkerType; } } public Color Color { get { return color; } } public Color ForeColor { get { return foreColor; } } public bool OverrideForeColor { get { return overrideForeColor; } } /// /// Marks the text segment as read-only. /// public bool IsReadOnly { get; set; } public string ToolTip { get { return toolTip; } set { toolTip = value; } } /// /// Gets the last offset that is inside the marker region. /// public int EndOffset { get { return Offset + Length - 1; } } public TextMarker(int offset, int length, TextMarkerType textMarkerType) : this(offset, length, textMarkerType, Color.Red) { } public TextMarker(int offset, int length, TextMarkerType textMarkerType, Color color) { if (length < 1) length = 1; this.offset = offset; this.length = length; this.textMarkerType = textMarkerType; this.color = color; } public TextMarker(int offset, int length, TextMarkerType textMarkerType, Color color, Color foreColor) { if (length < 1) length = 1; this.offset = offset; this.length = length; this.textMarkerType = textMarkerType; this.color = color; this.foreColor = foreColor; this.overrideForeColor = true; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/Selection/ColumnRange.cs ================================================ // // // // // $Revision: 1965 $ // using System; namespace ICSharpCode.TextEditor.Document { public class ColumnRange { public static readonly ColumnRange NoColumn = new ColumnRange(-2, -2); public static readonly ColumnRange WholeColumn = new ColumnRange(-1, -1); int startColumn; int endColumn; public int StartColumn { get { return startColumn; } set { startColumn = value; } } public int EndColumn { get { return endColumn; } set { endColumn = value; } } public ColumnRange(int startColumn, int endColumn) { this.startColumn = startColumn; this.endColumn = endColumn; } public override int GetHashCode() { return startColumn + (endColumn << 16); } public override bool Equals(object obj) { if (obj is ColumnRange) { return ((ColumnRange)obj).startColumn == startColumn && ((ColumnRange)obj).endColumn == endColumn; } return false; } public override string ToString() { return String.Format("[ColumnRange: StartColumn={0}, EndColumn={1}]", startColumn, endColumn); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/Selection/DefaultSelection.cs ================================================ // // // // // $Revision: 2679 $ // using System; using System.Diagnostics; using System.Drawing; namespace ICSharpCode.TextEditor.Document { /// /// Default implementation of the interface. /// public class DefaultSelection : ISelection { IDocument document; bool isRectangularSelection; TextLocation startPosition; TextLocation endPosition; public TextLocation StartPosition { get { return startPosition; } set { DefaultDocument.ValidatePosition(document, value); startPosition = value; } } public TextLocation EndPosition { get { return endPosition; } set { DefaultDocument.ValidatePosition(document, value); endPosition = value; } } public int Offset { get { return document.PositionToOffset(startPosition); } } public int EndOffset { get { return document.PositionToOffset(endPosition); } } public int Length { get { return EndOffset - Offset; } } /// /// Returns true, if the selection is empty /// public bool IsEmpty { get { return startPosition == endPosition; } } /// /// Returns true, if the selection is rectangular /// // TODO : make this unused property used. public bool IsRectangularSelection { get { return isRectangularSelection; } set { isRectangularSelection = value; } } /// /// The text which is selected by this selection. /// public string SelectedText { get { if (document != null) { if (Length < 0) { return null; } return document.GetText(Offset, Length); } return null; } } /// /// Creates a new instance of /// public DefaultSelection(IDocument document, TextLocation startPosition, TextLocation endPosition) { DefaultDocument.ValidatePosition(document, startPosition); DefaultDocument.ValidatePosition(document, endPosition); Debug.Assert(startPosition <= endPosition); this.document = document; this.startPosition = startPosition; this.endPosition = endPosition; } /// /// Converts a instance to string (for debug purposes) /// public override string ToString() { return String.Format("[DefaultSelection : StartPosition={0}, EndPosition={1}]", startPosition, endPosition); } public bool ContainsPosition(TextLocation position) { if (this.IsEmpty) return false; return startPosition.Y < position.Y && position.Y < endPosition.Y || startPosition.Y == position.Y && startPosition.X <= position.X && (startPosition.Y != endPosition.Y || position.X <= endPosition.X) || endPosition.Y == position.Y && startPosition.Y != endPosition.Y && position.X <= endPosition.X; } public bool ContainsOffset(int offset) { return Offset <= offset && offset <= EndOffset; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/Selection/ISelection.cs ================================================ // // // // // $Revision: 2659 $ // using System.Drawing; namespace ICSharpCode.TextEditor.Document { /// /// An interface representing a portion of the current selection. /// public interface ISelection { TextLocation StartPosition { get; set; } TextLocation EndPosition { get; set; } int Offset { get; } int EndOffset { get; } int Length { get; } /// /// Returns true, if the selection is rectangular /// bool IsRectangularSelection { get; } /// /// Returns true, if the selection is empty /// bool IsEmpty { get; } /// /// The text which is selected by this selection. /// string SelectedText { get; } bool ContainsOffset(int offset); bool ContainsPosition(TextLocation position); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/Selection/SelectionManager.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Text; namespace ICSharpCode.TextEditor.Document { /// /// This class manages the selections in a document. /// public class SelectionManager : IDisposable { TextLocation selectionStart; internal TextLocation SelectionStart { get { return selectionStart; } set { DefaultDocument.ValidatePosition(document, value); selectionStart = value; } } IDocument document; TextArea textArea; internal SelectFrom selectFrom = new SelectFrom(); internal List selectionCollection = new List(); /// /// A collection containing all selections. /// public List SelectionCollection { get { return selectionCollection; } } /// /// true if the is not empty, false otherwise. /// public bool HasSomethingSelected { get { return selectionCollection.Count > 0; } } public bool SelectionIsReadonly { get { if (document.ReadOnly) return true; foreach (ISelection sel in selectionCollection) { if (SelectionIsReadOnly(document, sel)) return true; } return false; } } internal static bool SelectionIsReadOnly(IDocument document, ISelection sel) { if (document.TextEditorProperties.SupportReadOnlySegments) return document.MarkerStrategy.GetMarkers(sel.Offset, sel.Length).Exists(m=>m.IsReadOnly); else return false; } /// /// The text that is currently selected. /// public string SelectedText { get { StringBuilder builder = new StringBuilder(); // PriorityQueue queue = new PriorityQueue(); foreach (ISelection s in selectionCollection) { builder.Append(s.SelectedText); // queue.Insert(-s.Offset, s); } // while (queue.Count > 0) { // ISelection s = ((ISelection)queue.Remove()); // builder.Append(s.SelectedText); // } return builder.ToString(); } } /// /// Creates a new instance of /// public SelectionManager(IDocument document) { this.document = document; document.DocumentChanged += new DocumentEventHandler(DocumentChanged); } /// /// Creates a new instance of /// public SelectionManager(IDocument document, TextArea textArea) { this.document = document; this.textArea = textArea; document.DocumentChanged += new DocumentEventHandler(DocumentChanged); } public void Dispose() { if (this.document != null) { document.DocumentChanged -= new DocumentEventHandler(DocumentChanged); this.document = null; } } void DocumentChanged(object sender, DocumentEventArgs e) { if (e.Text == null) { Remove(e.Offset, e.Length); } else { if (e.Length < 0) { Insert(e.Offset, e.Text); } else { Replace(e.Offset, e.Length, e.Text); } } } /// /// Clears the selection and sets a new selection /// using the given object. /// public void SetSelection(ISelection selection) { // autoClearSelection = false; if (selection != null) { if (SelectionCollection.Count == 1 && selection.StartPosition == SelectionCollection[0].StartPosition && selection.EndPosition == SelectionCollection[0].EndPosition ) { return; } ClearWithoutUpdate(); selectionCollection.Add(selection); document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, selection.StartPosition.Y, selection.EndPosition.Y)); document.CommitUpdate(); OnSelectionChanged(EventArgs.Empty); } else { ClearSelection(); } } public void SetSelection(TextLocation startPosition, TextLocation endPosition) { SetSelection(new DefaultSelection(document, startPosition, endPosition)); } public bool GreaterEqPos(TextLocation p1, TextLocation p2) { return p1.Y > p2.Y || p1.Y == p2.Y && p1.X >= p2.X; } public void ExtendSelection(TextLocation oldPosition, TextLocation newPosition) { // where oldposition is where the cursor was, // and newposition is where it has ended up from a click (both zero based) if (oldPosition == newPosition) { return; } TextLocation min; TextLocation max; int oldnewX = newPosition.X; bool oldIsGreater = GreaterEqPos(oldPosition, newPosition); if (oldIsGreater) { min = newPosition; max = oldPosition; } else { min = oldPosition; max = newPosition; } if (min == max) { return; } if (!HasSomethingSelected) { SetSelection(new DefaultSelection(document, min, max)); // initialise selectFrom for a cursor selection if (selectFrom.where == WhereFrom.None) SelectionStart = oldPosition; //textArea.Caret.Position; return; } ISelection selection = this.selectionCollection[0]; if (min == max) { //selection.StartPosition = newPosition; return; } else { // changed selection via gutter if (selectFrom.where == WhereFrom.Gutter) { // selection new position is always at the left edge for gutter selections newPosition.X = 0; } if (GreaterEqPos(newPosition, SelectionStart)) // selecting forward { selection.StartPosition = SelectionStart; // this handles last line selection if (selectFrom.where == WhereFrom.Gutter ) //&& newPosition.Y != oldPosition.Y) selection.EndPosition = new TextLocation(textArea.Caret.Column, textArea.Caret.Line); else { newPosition.X = oldnewX; selection.EndPosition = newPosition; } } else { // selecting back if (selectFrom.where == WhereFrom.Gutter && selectFrom.first == WhereFrom.Gutter) { // gutter selection selection.EndPosition = NextValidPosition(SelectionStart.Y); } else { // internal text selection selection.EndPosition = SelectionStart; //selection.StartPosition; } selection.StartPosition = newPosition; } } document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, min.Y, max.Y)); document.CommitUpdate(); OnSelectionChanged(EventArgs.Empty); } // retrieve the next available line // - checks that there are more lines available after the current one // - if there are then the next line is returned // - if there are NOT then the last position on the given line is returned public TextLocation NextValidPosition(int line) { if (line < document.TotalNumberOfLines - 1) return new TextLocation(0, line + 1); else return new TextLocation(document.GetLineSegment(document.TotalNumberOfLines - 1).Length + 1, line); } void ClearWithoutUpdate() { while (selectionCollection.Count > 0) { ISelection selection = selectionCollection[selectionCollection.Count - 1]; selectionCollection.RemoveAt(selectionCollection.Count - 1); document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, selection.StartPosition.Y, selection.EndPosition.Y)); OnSelectionChanged(EventArgs.Empty); } } /// /// Clears the selection. /// public void ClearSelection() { Point mousepos; mousepos = textArea.mousepos; // this is the most logical place to reset selection starting // positions because it is always called before a new selection selectFrom.first = selectFrom.where; TextLocation newSelectionStart = textArea.TextView.GetLogicalPosition(mousepos.X - textArea.TextView.DrawingPosition.X, mousepos.Y - textArea.TextView.DrawingPosition.Y); if (selectFrom.where == WhereFrom.Gutter) { newSelectionStart.X = 0; // selectionStart.Y = -1; } if (newSelectionStart.Line >= document.TotalNumberOfLines) { newSelectionStart.Line = document.TotalNumberOfLines-1; newSelectionStart.Column = document.GetLineSegment(document.TotalNumberOfLines-1).Length; } this.SelectionStart = newSelectionStart; ClearWithoutUpdate(); document.CommitUpdate(); } /// /// Removes the selected text from the buffer and clears /// the selection. /// public void RemoveSelectedText() { if (SelectionIsReadonly) { ClearSelection(); return; } List lines = new List(); int offset = -1; bool oneLine = true; // PriorityQueue queue = new PriorityQueue(); foreach (ISelection s in selectionCollection) { // ISelection s = ((ISelection)queue.Remove()); if (oneLine) { int lineBegin = s.StartPosition.Y; if (lineBegin != s.EndPosition.Y) { oneLine = false; } else { lines.Add(lineBegin); } } offset = s.Offset; document.Remove(s.Offset, s.Length); // queue.Insert(-s.Offset, s); } ClearSelection(); if (offset >= 0) { // TODO: // document.Caret.Offset = offset; } if (offset != -1) { if (oneLine) { foreach (int i in lines) { document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, i)); } } else { document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); } document.CommitUpdate(); } } bool SelectionsOverlap(ISelection s1, ISelection s2) { return (s1.Offset <= s2.Offset && s2.Offset <= s1.Offset + s1.Length) || (s1.Offset <= s2.Offset + s2.Length && s2.Offset + s2.Length <= s1.Offset + s1.Length) || (s1.Offset >= s2.Offset && s1.Offset + s1.Length <= s2.Offset + s2.Length); } /// /// Returns true if the given offset points to a section which is /// selected. /// public bool IsSelected(int offset) { return GetSelectionAt(offset) != null; } /// /// Returns a object giving the selection in which /// the offset points to. /// /// /// null if the offset doesn't point to a selection /// public ISelection GetSelectionAt(int offset) { foreach (ISelection s in selectionCollection) { if (s.ContainsOffset(offset)) { return s; } } return null; } /// /// Used internally, do not call. /// internal void Insert(int offset, string text) { // foreach (ISelection selection in SelectionCollection) { // if (selection.Offset > offset) { // selection.Offset += text.Length; // } else if (selection.Offset + selection.Length > offset) { // selection.Length += text.Length; // } // } } /// /// Used internally, do not call. /// internal void Remove(int offset, int length) { // foreach (ISelection selection in selectionCollection) { // if (selection.Offset > offset) { // selection.Offset -= length; // } else if (selection.Offset + selection.Length > offset) { // selection.Length -= length; // } // } } /// /// Used internally, do not call. /// internal void Replace(int offset, int length, string text) { // foreach (ISelection selection in selectionCollection) { // if (selection.Offset > offset) { // selection.Offset = selection.Offset - length + text.Length; // } else if (selection.Offset + selection.Length > offset) { // selection.Length = selection.Length - length + text.Length; // } // } } public ColumnRange GetSelectionAtLine(int lineNumber) { foreach (ISelection selection in selectionCollection) { int startLine = selection.StartPosition.Y; int endLine = selection.EndPosition.Y; if (startLine < lineNumber && lineNumber < endLine) { return ColumnRange.WholeColumn; } if (startLine == lineNumber) { LineSegment line = document.GetLineSegment(startLine); int startColumn = selection.StartPosition.X; int endColumn = endLine == lineNumber ? selection.EndPosition.X : line.Length + 1; return new ColumnRange(startColumn, endColumn); } if (endLine == lineNumber) { int endColumn = selection.EndPosition.X; return new ColumnRange(0, endColumn); } } return ColumnRange.NoColumn; } public void FireSelectionChanged() { OnSelectionChanged(EventArgs.Empty); } protected virtual void OnSelectionChanged(EventArgs e) { if (SelectionChanged != null) { SelectionChanged(this, e); } } public event EventHandler SelectionChanged; } // selection initiated from... internal class SelectFrom { public int where = WhereFrom.None; // last selection initiator public int first = WhereFrom.None; // first selection initiator public SelectFrom() { } } // selection initiated from type... internal class WhereFrom { public const int None = 0; public const int Gutter = 1; public const int TArea = 2; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/TextAnchor.cs ================================================ // // // // // $Revision: 3272 $ // using System; namespace ICSharpCode.TextEditor.Document { public enum AnchorMovementType { /// /// Behaves like a start marker - when text is inserted at the anchor position, the anchor will stay /// before the inserted text. /// BeforeInsertion, /// /// Behave like an end marker - when text is insered at the anchor position, the anchor will move /// after the inserted text. /// AfterInsertion } /// /// An anchor that can be put into a document and moves around when the document is changed. /// public sealed class TextAnchor { static Exception AnchorDeletedError() { return new InvalidOperationException("The text containing the anchor was deleted"); } LineSegment lineSegment; int columnNumber; public LineSegment Line { get { if (lineSegment == null) throw AnchorDeletedError(); return lineSegment; } internal set { lineSegment = value; } } public bool IsDeleted { get { return lineSegment == null; } } public int LineNumber { get { return this.Line.LineNumber; } } public int ColumnNumber { get { if (lineSegment == null) throw AnchorDeletedError(); return columnNumber; } internal set { columnNumber = value; } } public TextLocation Location { get { return new TextLocation(this.ColumnNumber, this.LineNumber); } } public int Offset { get { return this.Line.Offset + columnNumber; } } /// /// Controls how the anchor moves. /// public AnchorMovementType MovementType { get; set; } public event EventHandler Deleted; internal void Delete(ref DeferredEventList deferredEventList) { // we cannot fire an event here because this method is called while the LineManager adjusts the // lineCollection, so an event handler could see inconsistent state lineSegment = null; deferredEventList.AddDeletedAnchor(this); } internal void RaiseDeleted() { if (Deleted != null) Deleted(this, EventArgs.Empty); } internal TextAnchor(LineSegment lineSegment, int columnNumber) { this.lineSegment = lineSegment; this.columnNumber = columnNumber; } public override string ToString() { if (this.IsDeleted) return "[TextAnchor (deleted)]"; else return "[TextAnchor " + this.Location.ToString() + "]"; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/TextBufferStrategy/GapTextBufferStrategy.cs ================================================ // // // // // $Revision: 2667 $ // using System; using System.Text; namespace ICSharpCode.TextEditor.Document { public class GapTextBufferStrategy : ITextBufferStrategy { #if DEBUG int creatorThread = System.Threading.Thread.CurrentThread.ManagedThreadId; void CheckThread() { if (System.Threading.Thread.CurrentThread.ManagedThreadId != creatorThread) throw new InvalidOperationException("GapTextBufferStategy is not thread-safe!"); } #endif char[] buffer = new char[0]; int gapBeginOffset = 0; int gapEndOffset = 0; int gapLength = 0; // gapLength == gapEndOffset - gapBeginOffset const int minGapLength = 128; const int maxGapLength = 2048; public int Length { get { return buffer.Length - gapLength; } } public void SetContent(string text) { if (text == null) { text = String.Empty; } buffer = text.ToCharArray(); gapBeginOffset = gapEndOffset = gapLength = 0; } public char GetCharAt(int offset) { #if DEBUG CheckThread(); #endif if (offset < 0 || offset >= Length) { throw new ArgumentOutOfRangeException("offset", offset, "0 <= offset < " + Length.ToString()); } return offset < gapBeginOffset ? buffer[offset] : buffer[offset + gapLength]; } public string GetText(int offset, int length) { #if DEBUG CheckThread(); #endif if (offset < 0 || offset > Length) { throw new ArgumentOutOfRangeException("offset", offset, "0 <= offset <= " + Length.ToString()); } if (length < 0 || offset + length > Length) { throw new ArgumentOutOfRangeException("length", length, "0 <= length, offset(" + offset + ")+length <= " + Length.ToString()); } int end = offset + length; if (end < gapBeginOffset) { return new string(buffer, offset, length); } if (offset > gapBeginOffset) { return new string(buffer, offset + gapLength, length); } int block1Size = gapBeginOffset - offset; int block2Size = end - gapBeginOffset; StringBuilder buf = new StringBuilder(block1Size + block2Size); buf.Append(buffer, offset, block1Size); buf.Append(buffer, gapEndOffset, block2Size); return buf.ToString(); } public void Insert(int offset, string text) { Replace(offset, 0, text); } public void Remove(int offset, int length) { Replace(offset, length, String.Empty); } public void Replace(int offset, int length, string text) { if (text == null) { text = String.Empty; } #if DEBUG CheckThread(); #endif if (offset < 0 || offset > Length) { throw new ArgumentOutOfRangeException("offset", offset, "0 <= offset <= " + Length.ToString()); } if (length < 0 || offset + length > Length) { throw new ArgumentOutOfRangeException("length", length, "0 <= length, offset+length <= " + Length.ToString()); } // Math.Max is used so that if we need to resize the array // the new array has enough space for all old chars PlaceGap(offset, text.Length - length); gapEndOffset += length; // delete removed text text.CopyTo(0, buffer, gapBeginOffset, text.Length); gapBeginOffset += text.Length; gapLength = gapEndOffset - gapBeginOffset; if (gapLength > maxGapLength) { MakeNewBuffer(gapBeginOffset, minGapLength); } } void PlaceGap(int newGapOffset, int minRequiredGapLength) { if (gapLength < minRequiredGapLength) { // enlarge gap MakeNewBuffer(newGapOffset, minRequiredGapLength); } else { while (newGapOffset < gapBeginOffset) { buffer[--gapEndOffset] = buffer[--gapBeginOffset]; } while (newGapOffset > gapBeginOffset) { buffer[gapBeginOffset++] = buffer[gapEndOffset++]; } } } void MakeNewBuffer(int newGapOffset, int newGapLength) { if (newGapLength < minGapLength) newGapLength = minGapLength; char[] newBuffer = new char[Length + newGapLength]; if (newGapOffset < gapBeginOffset) { // gap is moving backwards // first part: Array.Copy(buffer, 0, newBuffer, 0, newGapOffset); // moving middle part: Array.Copy(buffer, newGapOffset, newBuffer, newGapOffset + newGapLength, gapBeginOffset - newGapOffset); // last part: Array.Copy(buffer, gapEndOffset, newBuffer, newBuffer.Length - (buffer.Length - gapEndOffset), buffer.Length - gapEndOffset); } else { // gap is moving forwards // first part: Array.Copy(buffer, 0, newBuffer, 0, gapBeginOffset); // moving middle part: Array.Copy(buffer, gapEndOffset, newBuffer, gapBeginOffset, newGapOffset - gapBeginOffset); // last part: int lastPartLength = newBuffer.Length - (newGapOffset + newGapLength); Array.Copy(buffer, buffer.Length - lastPartLength, newBuffer, newGapOffset + newGapLength, lastPartLength); } gapBeginOffset = newGapOffset; gapEndOffset = newGapOffset + newGapLength; gapLength = newGapLength; buffer = newBuffer; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/TextBufferStrategy/ITextBufferStrategy.cs ================================================ // // // // // $Revision: 1966 $ // namespace ICSharpCode.TextEditor.Document { /// /// Interface to describe a sequence of characters that can be edited. /// public interface ITextBufferStrategy { /// /// The current length of the sequence of characters that can be edited. /// int Length { get; } /// /// Inserts a string of characters into the sequence. /// /// /// offset where to insert the string. /// /// /// text to be inserted. /// void Insert(int offset, string text); /// /// Removes some portion of the sequence. /// /// /// offset of the remove. /// /// /// number of characters to remove. /// void Remove(int offset, int length); /// /// Replace some portion of the sequence. /// /// /// offset. /// /// /// number of characters to replace. /// /// /// text to be replaced with. /// void Replace(int offset, int length, string text); /// /// Fetches a string of characters contained in the sequence. /// /// /// Offset into the sequence to fetch /// /// /// number of characters to copy. /// string GetText(int offset, int length); /// /// Returns a specific char of the sequence. /// /// /// Offset of the char to get. /// char GetCharAt(int offset); /// /// This method sets the stored content. /// /// /// The string that represents the character sequence. /// void SetContent(string text); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/TextBufferStrategy/StringTextBufferStrategy.cs ================================================ // // // // // $Revision: 2682 $ // using System; using System.IO; using System.Text; namespace ICSharpCode.TextEditor.Document { /// /// Simple implementation of the ITextBuffer interface implemented using a /// string. /// Only for fall-back purposes. /// public class StringTextBufferStrategy : ITextBufferStrategy { string storedText = ""; public int Length { get { return storedText.Length; } } public void Insert(int offset, string text) { if (text != null) { storedText = storedText.Insert(offset, text); } } public void Remove(int offset, int length) { storedText = storedText.Remove(offset, length); } public void Replace(int offset, int length, string text) { Remove(offset, length); Insert(offset, text); } public string GetText(int offset, int length) { if (length == 0) { return ""; } if (offset == 0 && length >= storedText.Length) { return storedText; } return storedText.Substring(offset, Math.Min(length, storedText.Length - offset)); } public char GetCharAt(int offset) { if (offset == Length) { return '\0'; } return storedText[offset]; } public void SetContent(string text) { storedText = text; } public StringTextBufferStrategy() { } public static ITextBufferStrategy CreateTextBufferFromFile(string fileName) { if (!File.Exists(fileName)) { throw new System.IO.FileNotFoundException(fileName); } StringTextBufferStrategy s = new StringTextBufferStrategy(); s.SetContent(Util.FileReader.ReadFileContent(fileName, Encoding.Default)); return s; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/TextLocation.cs ================================================ // // // // // $Revision: 2658$ // using System; namespace ICSharpCode.TextEditor { /// /// A line/column position. /// Text editor lines/columns are counting from zero. /// public struct TextLocation : IComparable, IEquatable { /// /// Represents no text location (-1, -1). /// public static readonly TextLocation Empty = new TextLocation(-1, -1); public TextLocation(int column, int line) { x = column; y = line; } int x, y; public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } public int Line { get { return y; } set { y = value; } } public int Column { get { return x; } set { x = value; } } public bool IsEmpty { get { return x <= 0 && y <= 0; } } public override string ToString() { return string.Format("(Line {1}, Col {0})", this.x, this.y); } public override int GetHashCode() { return unchecked (87 * x.GetHashCode() ^ y.GetHashCode()); } public override bool Equals(object obj) { if (!(obj is TextLocation)) return false; return (TextLocation)obj == this; } public bool Equals(TextLocation other) { return this == other; } public static bool operator ==(TextLocation a, TextLocation b) { return a.x == b.x && a.y == b.y; } public static bool operator !=(TextLocation a, TextLocation b) { return a.x != b.x || a.y != b.y; } public static bool operator <(TextLocation a, TextLocation b) { if (a.y < b.y) return true; else if (a.y == b.y) return a.x < b.x; else return false; } public static bool operator >(TextLocation a, TextLocation b) { if (a.y > b.y) return true; else if (a.y == b.y) return a.x > b.x; else return false; } public static bool operator <=(TextLocation a, TextLocation b) { return !(a > b); } public static bool operator >=(TextLocation a, TextLocation b) { return !(a < b); } public int CompareTo(TextLocation other) { if (this == other) return 0; if (this < other) return -1; else return 1; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Document/TextUtilities.cs ================================================ // // // // // $Revision: 3020 $ // using System; using System.Diagnostics; using System.Text; namespace ICSharpCode.TextEditor.Document { public sealed class TextUtilities { /// /// This function takes a string and converts the whitespace in front of /// it to tabs. If the length of the whitespace at the start of the string /// was not a whole number of tabs then there will still be some spaces just /// before the text starts. /// the output string will be of the form: /// 1. zero or more tabs /// 2. zero or more spaces (less than tabIndent) /// 3. the rest of the line /// public static string LeadingWhiteSpaceToTabs(string line, int tabIndent) { StringBuilder sb = new StringBuilder(line.Length); int consecutiveSpaces = 0; int i = 0; for(i = 0; i < line.Length; i++) { if(line[i] == ' ') { consecutiveSpaces++; if(consecutiveSpaces == tabIndent) { sb.Append('\t'); consecutiveSpaces = 0; } } else if(line[i] == '\t') { sb.Append('\t'); // if we had say 3 spaces then a tab and tabIndent was 4 then // we would want to simply replace all of that with 1 tab consecutiveSpaces = 0; } else { break; } } if(i < line.Length) { sb.Append(line.Substring(i-consecutiveSpaces)); } return sb.ToString(); } public static bool IsLetterDigitOrUnderscore(char c) { if(!Char.IsLetterOrDigit(c)) { return c == '_'; } return true; } public enum CharacterType { LetterDigitOrUnderscore, WhiteSpace, Other } /// /// This method returns the expression before a specified offset. /// That method is used in code completion to determine the expression given /// to the parser for type resolve. /// public static string GetExpressionBeforeOffset(TextArea textArea, int initialOffset) { IDocument document = textArea.Document; int offset = initialOffset; while (offset - 1 > 0) { switch (document.GetCharAt(offset - 1)) { case '\n': case '\r': case '}': goto done; // offset = SearchBracketBackward(document, offset - 2, '{','}'); // break; case ']': offset = SearchBracketBackward(document, offset - 2, '[',']'); break; case ')': offset = SearchBracketBackward(document, offset - 2, '(',')'); break; case '.': --offset; break; case '"': if (offset < initialOffset - 1) { return null; } return "\"\""; case '\'': if (offset < initialOffset - 1) { return null; } return "'a'"; case '>': if (document.GetCharAt(offset - 2) == '-') { offset -= 2; break; } goto done; default: if (Char.IsWhiteSpace(document.GetCharAt(offset - 1))) { --offset; break; } int start = offset - 1; if (!IsLetterDigitOrUnderscore(document.GetCharAt(start))) { goto done; } while (start > 0 && IsLetterDigitOrUnderscore(document.GetCharAt(start - 1))) { --start; } string word = document.GetText(start, offset - start).Trim(); switch (word) { case "ref": case "out": case "in": case "return": case "throw": case "case": goto done; } if (word.Length > 0 && !IsLetterDigitOrUnderscore(word[0])) { goto done; } offset = start; break; } } done: //// simple exit fails when : is inside comment line or any other character //// we have to check if we got several ids in resulting line, which usually happens when //// id. is typed on next line after comment one //// Would be better if lexer would parse properly such expressions. However this will cause //// modifications in this area too - to get full comment line and remove it afterwards if (offset < 0) return string.Empty; string resText=document.GetText(offset, textArea.Caret.Offset - offset ).Trim(); int pos=resText.LastIndexOf('\n'); if (pos>=0) { offset+=pos+1; //// whitespaces and tabs, which might be inside, will be skipped by trim below } string expression = document.GetText(offset, textArea.Caret.Offset - offset ).Trim(); return expression; } public static CharacterType GetCharacterType(char c) { if(IsLetterDigitOrUnderscore(c)) return CharacterType.LetterDigitOrUnderscore; if(Char.IsWhiteSpace(c)) return CharacterType.WhiteSpace; return CharacterType.Other; } public static int GetFirstNonWSChar(IDocument document, int offset) { while (offset < document.TextLength && Char.IsWhiteSpace(document.GetCharAt(offset))) { ++offset; } return offset; } public static int FindWordEnd(IDocument document, int offset) { LineSegment line = document.GetLineSegmentForOffset(offset); int endPos = line.Offset + line.Length; while (offset < endPos && IsLetterDigitOrUnderscore(document.GetCharAt(offset))) { ++offset; } return offset; } public static int FindWordStart(IDocument document, int offset) { LineSegment line = document.GetLineSegmentForOffset(offset); int lineOffset = line.Offset; while (offset > lineOffset && IsLetterDigitOrUnderscore(document.GetCharAt(offset - 1))) { --offset; } return offset; } // go forward to the start of the next word // if the cursor is at the start or in the middle of a word we move to the end of the word // and then past any whitespace that follows it // if the cursor is at the start or in the middle of some whitespace we move to the start of the // next word public static int FindNextWordStart(IDocument document, int offset) { int originalOffset = offset; LineSegment line = document.GetLineSegmentForOffset(offset); int endPos = line.Offset + line.Length; // lets go to the end of the word, whitespace or operator CharacterType t = GetCharacterType(document.GetCharAt(offset)); while (offset < endPos && GetCharacterType(document.GetCharAt(offset)) == t) { ++offset; } // now we're at the end of the word, lets find the start of the next one by skipping whitespace while (offset < endPos && GetCharacterType(document.GetCharAt(offset)) == CharacterType.WhiteSpace) { ++offset; } return offset; } // go back to the start of the word we are on // if we are already at the start of a word or if we are in whitespace, then go back // to the start of the previous word public static int FindPrevWordStart(IDocument document, int offset) { int originalOffset = offset; if (offset > 0) { LineSegment line = document.GetLineSegmentForOffset(offset); CharacterType t = GetCharacterType(document.GetCharAt(offset - 1)); while (offset > line.Offset && GetCharacterType(document.GetCharAt(offset - 1)) == t) { --offset; } // if we were in whitespace, and now we're at the end of a word or operator, go back to the beginning of it if(t == CharacterType.WhiteSpace && offset > line.Offset) { t = GetCharacterType(document.GetCharAt(offset - 1)); while (offset > line.Offset && GetCharacterType(document.GetCharAt(offset - 1)) == t) { --offset; } } } return offset; } public static string GetLineAsString(IDocument document, int lineNumber) { LineSegment line = document.GetLineSegment(lineNumber); return document.GetText(line.Offset, line.Length); } public static int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket) { return document.FormattingStrategy.SearchBracketBackward(document, offset, openBracket, closingBracket); } public static int SearchBracketForward(IDocument document, int offset, char openBracket, char closingBracket) { return document.FormattingStrategy.SearchBracketForward(document, offset, openBracket, closingBracket); } /// /// Returns true, if the line lineNumber is empty or filled with whitespaces. /// public static bool IsEmptyLine(IDocument document, int lineNumber) { return IsEmptyLine(document, document.GetLineSegment(lineNumber)); } /// /// Returns true, if the line lineNumber is empty or filled with whitespaces. /// public static bool IsEmptyLine(IDocument document, LineSegment line) { for (int i = line.Offset; i < line.Offset + line.Length; ++i) { char ch = document.GetCharAt(i); if (!Char.IsWhiteSpace(ch)) { return false; } } return true; } static bool IsWordPart(char ch) { return IsLetterDigitOrUnderscore(ch) || ch == '.'; } public static string GetWordAt(IDocument document, int offset) { if (offset < 0 || offset >= document.TextLength - 1 || !IsWordPart(document.GetCharAt(offset))) { return String.Empty; } int startOffset = offset; int endOffset = offset; while (startOffset > 0 && IsWordPart(document.GetCharAt(startOffset - 1))) { --startOffset; } while (endOffset < document.TextLength - 1 && IsWordPart(document.GetCharAt(endOffset + 1))) { ++endOffset; } Debug.Assert(endOffset >= startOffset); return document.GetText(startOffset, endOffset - startOffset + 1); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/AbstractMargin.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Drawing; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { public delegate void MarginMouseEventHandler(AbstractMargin sender, Point mousepos, MouseButtons mouseButtons); public delegate void MarginPaintEventHandler(AbstractMargin sender, Graphics g, Rectangle rect); /// /// This class views the line numbers and folding markers. /// public abstract class AbstractMargin { Cursor cursor = Cursors.Default; [CLSCompliant(false)] protected Rectangle drawingPosition = new Rectangle(0, 0, 0, 0); [CLSCompliant(false)] protected TextArea textArea; public Rectangle DrawingPosition { get { return drawingPosition; } set { drawingPosition = value; } } public TextArea TextArea { get { return textArea; } } public IDocument Document { get { return textArea.Document; } } public ITextEditorProperties TextEditorProperties { get { return textArea.Document.TextEditorProperties; } } public virtual Cursor Cursor { get { return cursor; } set { cursor = value; } } public virtual Size Size { get { return new Size(-1, -1); } } public virtual bool IsVisible { get { return true; } } protected AbstractMargin(TextArea textArea) { this.textArea = textArea; } public virtual void HandleMouseDown(Point mousepos, MouseButtons mouseButtons) { if (MouseDown != null) { MouseDown(this, mousepos, mouseButtons); } } public virtual void HandleMouseMove(Point mousepos, MouseButtons mouseButtons) { if (MouseMove != null) { MouseMove(this, mousepos, mouseButtons); } } public virtual void HandleMouseLeave(EventArgs e) { if (MouseLeave != null) { MouseLeave(this, e); } } public virtual void Paint(Graphics g, Rectangle rect) { if (Painted != null) { Painted(this, g, rect); } } public event MarginPaintEventHandler Painted; public event MarginMouseEventHandler MouseDown; public event MarginMouseEventHandler MouseMove; public event EventHandler MouseLeave; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/BracketHighlighter.cs ================================================ // // // // // $Revision: 2659 $ // using System; using System.Drawing; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { public class BracketHighlight { public TextLocation OpenBrace { get; set; } public TextLocation CloseBrace { get; set; } public BracketHighlight(TextLocation openBrace, TextLocation closeBrace) { this.OpenBrace = openBrace; this.CloseBrace = closeBrace; } } public class BracketHighlightingSheme { char opentag; char closingtag; public char OpenTag { get { return opentag; } set { opentag = value; } } public char ClosingTag { get { return closingtag; } set { closingtag = value; } } public BracketHighlightingSheme(char opentag, char closingtag) { this.opentag = opentag; this.closingtag = closingtag; } public BracketHighlight GetHighlight(IDocument document, int offset) { int searchOffset; if (document.TextEditorProperties.BracketMatchingStyle == BracketMatchingStyle.After) { searchOffset = offset; } else { searchOffset = offset + 1; } char word = document.GetCharAt(Math.Max(0, Math.Min(document.TextLength - 1, searchOffset))); TextLocation endP = document.OffsetToPosition(searchOffset); if (word == opentag) { if (searchOffset < document.TextLength) { int bracketOffset = TextUtilities.SearchBracketForward(document, searchOffset + 1, opentag, closingtag); if (bracketOffset >= 0) { TextLocation p = document.OffsetToPosition(bracketOffset); return new BracketHighlight(p, endP); } } } else if (word == closingtag) { if (searchOffset > 0) { int bracketOffset = TextUtilities.SearchBracketBackward(document, searchOffset - 1, opentag, closingtag); if (bracketOffset >= 0) { TextLocation p = document.OffsetToPosition(bracketOffset); return new BracketHighlight(p, endP); } } } return null; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/BrushRegistry.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Collections; using System.Drawing; using System.Drawing.Drawing2D; namespace ICSharpCode.TextEditor { /// /// Contains brushes/pens for the text editor to speed up drawing. Re-Creation of brushes and pens /// seems too costly. /// public class BrushRegistry { static Hashtable brushes = new Hashtable(); static Hashtable pens = new Hashtable(); static Hashtable dotPens = new Hashtable(); public static Brush GetBrush(Color color) { if (!brushes.Contains(color)) { Brush newBrush = new SolidBrush(color); brushes.Add(color, newBrush); return newBrush; } return brushes[color] as Brush; } public static Pen GetPen(Color color) { if (!pens.Contains(color)) { Pen newPen = new Pen(color); pens.Add(color, newPen); return newPen; } return pens[color] as Pen; } public static Pen GetDotPen(Color bgColor, Color fgColor) { bool containsBgColor = dotPens.Contains(bgColor); if (!containsBgColor || !((Hashtable)dotPens[bgColor]).Contains(fgColor)) { if (!containsBgColor) { dotPens[bgColor] = new Hashtable(); } HatchBrush hb = new HatchBrush(HatchStyle.Percent50, bgColor, fgColor); Pen newPen = new Pen(hb); ((Hashtable)dotPens[bgColor])[fgColor] = newPen; return newPen; } return ((Hashtable)dotPens[bgColor])[fgColor] as Pen; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/Caret.cs ================================================ // // // // // $Revision: 3279 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Diagnostics; using System.Runtime.InteropServices; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// In this enumeration are all caret modes listed. /// public enum CaretMode { /// /// If the caret is in insert mode typed characters will be /// inserted at the caret position /// InsertMode, /// /// If the caret is in overwirte mode typed characters will /// overwrite the character at the caret position /// OverwriteMode } public class Caret : System.IDisposable { int line = 0; int column = 0; int desiredXPos = 0; CaretMode caretMode; static bool caretCreated = false; bool hidden = true; TextArea textArea; Point currentPos = new Point(-1, -1); Ime ime = null; CaretImplementation caretImplementation; /// /// The 'prefered' xPos in which the caret moves, when it is moved /// up/down. Measured in pixels, not in characters! /// public int DesiredColumn { get { return desiredXPos; } set { desiredXPos = value; } } /// /// The current caret mode. /// public CaretMode CaretMode { get { return caretMode; } set { caretMode = value; OnCaretModeChanged(EventArgs.Empty); } } public int Line { get { return line; } set { line = value; ValidateCaretPos(); UpdateCaretPosition(); OnPositionChanged(EventArgs.Empty); } } public int Column { get { return column; } set { column = value; ValidateCaretPos(); UpdateCaretPosition(); OnPositionChanged(EventArgs.Empty); } } public TextLocation Position { get { return new TextLocation(column, line); } set { line = value.Y; column = value.X; ValidateCaretPos(); UpdateCaretPosition(); OnPositionChanged(EventArgs.Empty); } } public int Offset { get { return textArea.Document.PositionToOffset(Position); } } public Caret(TextArea textArea) { this.textArea = textArea; textArea.GotFocus += new EventHandler(GotFocus); textArea.LostFocus += new EventHandler(LostFocus); if (Environment.OSVersion.Platform == PlatformID.Unix) caretImplementation = new ManagedCaret(this); else caretImplementation = new Win32Caret(this); } public void Dispose() { textArea.GotFocus -= new EventHandler(GotFocus); textArea.LostFocus -= new EventHandler(LostFocus); textArea = null; caretImplementation.Dispose(); } public TextLocation ValidatePosition(TextLocation pos) { int line = Math.Max(0, Math.Min(textArea.Document.TotalNumberOfLines - 1, pos.Y)); int column = Math.Max(0, pos.X); if (column == int.MaxValue || !textArea.TextEditorProperties.AllowCaretBeyondEOL) { LineSegment lineSegment = textArea.Document.GetLineSegment(line); column = Math.Min(column, lineSegment.Length); } return new TextLocation(column, line); } /// /// If the caret position is outside the document text bounds /// it is set to the correct position by calling ValidateCaretPos. /// public void ValidateCaretPos() { line = Math.Max(0, Math.Min(textArea.Document.TotalNumberOfLines - 1, line)); column = Math.Max(0, column); if (column == int.MaxValue || !textArea.TextEditorProperties.AllowCaretBeyondEOL) { LineSegment lineSegment = textArea.Document.GetLineSegment(line); column = Math.Min(column, lineSegment.Length); } } void CreateCaret() { while (!caretCreated) { switch (caretMode) { case CaretMode.InsertMode: caretCreated = caretImplementation.Create(2, textArea.TextView.FontHeight); break; case CaretMode.OverwriteMode: caretCreated = caretImplementation.Create((int)textArea.TextView.SpaceWidth, textArea.TextView.FontHeight); break; } } if (currentPos.X < 0) { ValidateCaretPos(); currentPos = ScreenPosition; } caretImplementation.SetPosition(currentPos.X, currentPos.Y); caretImplementation.Show(); } public void RecreateCaret() { Log("RecreateCaret"); DisposeCaret(); if (!hidden) { CreateCaret(); } } void DisposeCaret() { if (caretCreated) { caretCreated = false; caretImplementation.Hide(); caretImplementation.Destroy(); } } void GotFocus(object sender, EventArgs e) { Log("GotFocus, IsInUpdate=" + textArea.MotherTextEditorControl.IsInUpdate); hidden = false; if (!textArea.MotherTextEditorControl.IsInUpdate) { CreateCaret(); UpdateCaretPosition(); } } void LostFocus(object sender, EventArgs e) { Log("LostFocus"); hidden = true; DisposeCaret(); } public Point ScreenPosition { get { int xpos = textArea.TextView.GetDrawingXPos(this.line, this.column); return new Point(textArea.TextView.DrawingPosition.X + xpos, textArea.TextView.DrawingPosition.Y + (textArea.Document.GetVisibleLine(this.line)) * textArea.TextView.FontHeight - textArea.TextView.TextArea.VirtualTop.Y); } } int oldLine = -1; bool outstandingUpdate; internal void OnEndUpdate() { if (outstandingUpdate) UpdateCaretPosition(); } public void UpdateCaretPosition() { Log("UpdateCaretPosition"); if (caretImplementation.RequireRedrawOnPositionChange) { textArea.UpdateLine(oldLine); if (line != oldLine) textArea.UpdateLine(line); } else { if (textArea.MotherTextAreaControl.TextEditorProperties.LineViewerStyle == LineViewerStyle.FullRow && oldLine != line) { textArea.UpdateLine(oldLine); textArea.UpdateLine(line); } } oldLine = line; if (hidden || textArea.MotherTextEditorControl.IsInUpdate) { outstandingUpdate = true; return; } else { outstandingUpdate = false; } ValidateCaretPos(); int lineNr = this.line; int xpos = textArea.TextView.GetDrawingXPos(lineNr, this.column); //LineSegment lineSegment = textArea.Document.GetLineSegment(lineNr); Point pos = ScreenPosition; if (xpos >= 0) { CreateCaret(); bool success = caretImplementation.SetPosition(pos.X, pos.Y); if (!success) { caretImplementation.Destroy(); caretCreated = false; UpdateCaretPosition(); } } else { caretImplementation.Destroy(); } // set the input method editor location if (ime == null) { ime = new Ime(textArea.Handle, textArea.Document.TextEditorProperties.Font); } else { ime.HWnd = textArea.Handle; ime.Font = textArea.Document.TextEditorProperties.Font; } ime.SetIMEWindowLocation(pos.X, pos.Y); currentPos = pos; } [Conditional("DEBUG")] static void Log(string text) { //Console.WriteLine(text); } #region Caret implementation internal void PaintCaret(Graphics g) { caretImplementation.PaintCaret(g); } abstract class CaretImplementation : IDisposable { public bool RequireRedrawOnPositionChange; public abstract bool Create(int width, int height); public abstract void Hide(); public abstract void Show(); public abstract bool SetPosition(int x, int y); public abstract void PaintCaret(Graphics g); public abstract void Destroy(); public virtual void Dispose() { Destroy(); } } class ManagedCaret : CaretImplementation { System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer { Interval = 300 }; bool visible; bool blink = true; int x, y, width, height; TextArea textArea; Caret parentCaret; public ManagedCaret(Caret caret) { base.RequireRedrawOnPositionChange = true; this.textArea = caret.textArea; this.parentCaret = caret; timer.Tick += CaretTimerTick; } void CaretTimerTick(object sender, EventArgs e) { blink = !blink; if (visible) textArea.UpdateLine(parentCaret.Line); } public override bool Create(int width, int height) { this.visible = true; this.width = width - 2; this.height = height; timer.Enabled = true; return true; } public override void Hide() { visible = false; } public override void Show() { visible = true; } public override bool SetPosition(int x, int y) { this.x = x - 1; this.y = y; return true; } public override void PaintCaret(Graphics g) { if (visible && blink) g.DrawRectangle(Pens.Gray, x, y, width, height); } public override void Destroy() { visible = false; timer.Enabled = false; } public override void Dispose() { base.Dispose(); timer.Dispose(); } } class Win32Caret : CaretImplementation { [DllImport("User32.dll")] static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight); [DllImport("User32.dll")] static extern bool SetCaretPos(int x, int y); [DllImport("User32.dll")] static extern bool DestroyCaret(); [DllImport("User32.dll")] static extern bool ShowCaret(IntPtr hWnd); [DllImport("User32.dll")] static extern bool HideCaret(IntPtr hWnd); TextArea textArea; public Win32Caret(Caret caret) { this.textArea = caret.textArea; } public override bool Create(int width, int height) { return CreateCaret(textArea.Handle, 0, width, height); } public override void Hide() { HideCaret(textArea.Handle); } public override void Show() { ShowCaret(textArea.Handle); } public override bool SetPosition(int x, int y) { return SetCaretPos(x, y); } public override void PaintCaret(Graphics g) { } public override void Destroy() { DestroyCaret(); } } #endregion bool firePositionChangedAfterUpdateEnd; void FirePositionChangedAfterUpdateEnd(object sender, EventArgs e) { OnPositionChanged(EventArgs.Empty); } protected virtual void OnPositionChanged(EventArgs e) { if (this.textArea.MotherTextEditorControl.IsInUpdate) { if (firePositionChangedAfterUpdateEnd == false) { firePositionChangedAfterUpdateEnd = true; this.textArea.Document.UpdateCommited += FirePositionChangedAfterUpdateEnd; } return; } else if (firePositionChangedAfterUpdateEnd) { this.textArea.Document.UpdateCommited -= FirePositionChangedAfterUpdateEnd; firePositionChangedAfterUpdateEnd = false; } List foldings = textArea.Document.FoldingManager.GetFoldingsFromPosition(line, column); bool shouldUpdate = false; foreach (FoldMarker foldMarker in foldings) { shouldUpdate |= foldMarker.IsFolded; foldMarker.IsFolded = false; } if (shouldUpdate) { textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty); } if (PositionChanged != null) { PositionChanged(this, e); } textArea.ScrollToCaret(); } protected virtual void OnCaretModeChanged(EventArgs e) { if (CaretModeChanged != null) { CaretModeChanged(this, e); } caretImplementation.Hide(); caretImplementation.Destroy(); caretCreated = false; CreateCaret(); caretImplementation.Show(); } /// /// Is called each time the caret is moved. /// public event EventHandler PositionChanged; /// /// Is called each time the CaretMode has changed. /// public event EventHandler CaretModeChanged; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/CompletionWindow/AbstractCompletionWindow.cs ================================================ // // // // // $Revision: 2681 $ // using System; using System.Drawing; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Gui.CompletionWindow { /// /// Description of AbstractCompletionWindow. /// public abstract class AbstractCompletionWindow : System.Windows.Forms.Form { protected TextEditorControl control; protected Size drawingSize; Rectangle workingScreen; Form parentForm; protected AbstractCompletionWindow(Form parentForm, TextEditorControl control) { workingScreen = Screen.GetWorkingArea(parentForm); // SetStyle(ControlStyles.Selectable, false); this.parentForm = parentForm; this.control = control; SetLocation(); StartPosition = FormStartPosition.Manual; FormBorderStyle = FormBorderStyle.None; ShowInTaskbar = false; MinimumSize = new Size(1, 1); Size = new Size(1, 1); } protected virtual void SetLocation() { TextArea textArea = control.ActiveTextAreaControl.TextArea; TextLocation caretPos = textArea.Caret.Position; int xpos = textArea.TextView.GetDrawingXPos(caretPos.Y, caretPos.X); int rulerHeight = textArea.TextEditorProperties.ShowHorizontalRuler ? textArea.TextView.FontHeight : 0; Point pos = new Point(textArea.TextView.DrawingPosition.X + xpos, textArea.TextView.DrawingPosition.Y + (textArea.Document.GetVisibleLine(caretPos.Y)) * textArea.TextView.FontHeight - textArea.TextView.TextArea.VirtualTop.Y + textArea.TextView.FontHeight + rulerHeight); Point location = control.ActiveTextAreaControl.PointToScreen(pos); // set bounds Rectangle bounds = new Rectangle(location, drawingSize); if (!workingScreen.Contains(bounds)) { if (bounds.Right > workingScreen.Right) { bounds.X = workingScreen.Right - bounds.Width; } if (bounds.Left < workingScreen.Left) { bounds.X = workingScreen.Left; } if (bounds.Top < workingScreen.Top) { bounds.Y = workingScreen.Top; } if (bounds.Bottom > workingScreen.Bottom) { bounds.Y = bounds.Y - bounds.Height - control.ActiveTextAreaControl.TextArea.TextView.FontHeight; if (bounds.Bottom > workingScreen.Bottom) { bounds.Y = workingScreen.Bottom - bounds.Height; } } } Bounds = bounds; } protected override CreateParams CreateParams { get { CreateParams p = base.CreateParams; AddShadowToWindow(p); return p; } } static int shadowStatus; /// /// Adds a shadow to the create params if it is supported by the operating system. /// public static void AddShadowToWindow(CreateParams createParams) { if (shadowStatus == 0) { // Test OS version shadowStatus = -1; // shadow not supported if (Environment.OSVersion.Platform == PlatformID.Win32NT) { Version ver = Environment.OSVersion.Version; if (ver.Major > 5 || ver.Major == 5 && ver.Minor >= 1) { shadowStatus = 1; } } } if (shadowStatus == 1) { createParams.ClassStyle |= 0x00020000; // set CS_DROPSHADOW } } protected override bool ShowWithoutActivation { get { return true; } } protected void ShowCompletionWindow() { Owner = parentForm; Enabled = true; this.Show(); control.Focus(); if (parentForm != null) { parentForm.LocationChanged += new EventHandler(this.ParentFormLocationChanged); } control.ActiveTextAreaControl.VScrollBar.ValueChanged += new EventHandler(ParentFormLocationChanged); control.ActiveTextAreaControl.HScrollBar.ValueChanged += new EventHandler(ParentFormLocationChanged); control.ActiveTextAreaControl.TextArea.DoProcessDialogKey += new DialogKeyProcessor(ProcessTextAreaKey); control.ActiveTextAreaControl.Caret.PositionChanged += new EventHandler(CaretOffsetChanged); control.ActiveTextAreaControl.TextArea.LostFocus += new EventHandler(this.TextEditorLostFocus); control.Resize += new EventHandler(ParentFormLocationChanged); foreach (Control c in Controls) { c.MouseMove += ControlMouseMove; } } void ParentFormLocationChanged(object sender, EventArgs e) { SetLocation(); } public virtual bool ProcessKeyEvent(char ch) { return false; } protected virtual bool ProcessTextAreaKey(Keys keyData) { if (!Visible) { return false; } switch (keyData) { case Keys.Escape: Close(); return true; } return false; } protected virtual void CaretOffsetChanged(object sender, EventArgs e) { } protected void TextEditorLostFocus(object sender, EventArgs e) { if (!control.ActiveTextAreaControl.TextArea.Focused && !this.ContainsFocus) { Close(); } } protected override void OnClosed(EventArgs e) { base.OnClosed(e); // take out the inserted methods parentForm.LocationChanged -= new EventHandler(ParentFormLocationChanged); foreach (Control c in Controls) { c.MouseMove -= ControlMouseMove; } if (control.ActiveTextAreaControl.VScrollBar != null) { control.ActiveTextAreaControl.VScrollBar.ValueChanged -= new EventHandler(ParentFormLocationChanged); } if (control.ActiveTextAreaControl.HScrollBar != null) { control.ActiveTextAreaControl.HScrollBar.ValueChanged -= new EventHandler(ParentFormLocationChanged); } control.ActiveTextAreaControl.TextArea.LostFocus -= new EventHandler(this.TextEditorLostFocus); control.ActiveTextAreaControl.Caret.PositionChanged -= new EventHandler(CaretOffsetChanged); control.ActiveTextAreaControl.TextArea.DoProcessDialogKey -= new DialogKeyProcessor(ProcessTextAreaKey); control.Resize -= new EventHandler(ParentFormLocationChanged); Dispose(); } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); ControlMouseMove(this, e); } /// /// Invoked when the mouse moves over this form or any child control. /// Shows the mouse cursor on the text area if it has been hidden. /// /// /// Derived classes should attach this handler to the MouseMove event /// of all created controls which are not added to the Controls /// collection. /// protected void ControlMouseMove(object sender, MouseEventArgs e) { control.ActiveTextAreaControl.TextArea.ShowHiddenCursor(false); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/CompletionWindow/CodeCompletionListView.cs ================================================ // // // // // $Revision: 2932 $ // using System; using System.Drawing; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Gui.CompletionWindow { /// /// Description of CodeCompletionListView. /// public class CodeCompletionListView : System.Windows.Forms.UserControl { ICompletionData[] completionData; int firstItem = 0; int selectedItem = -1; ImageList imageList; public ImageList ImageList { get { return imageList; } set { imageList = value; } } public int FirstItem { get { return firstItem; } set { if (firstItem != value) { firstItem = value; OnFirstItemChanged(EventArgs.Empty); } } } public ICompletionData SelectedCompletionData { get { if (selectedItem < 0) { return null; } return completionData[selectedItem]; } } public int ItemHeight { get { return Math.Max(imageList.ImageSize.Height, (int)(Font.Height * 1.25)); } } public int MaxVisibleItem { get { return Height / ItemHeight; } } public CodeCompletionListView(ICompletionData[] completionData) { Array.Sort(completionData, DefaultCompletionData.Compare); this.completionData = completionData; // this.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKey); // SetStyle(ControlStyles.Selectable, false); // SetStyle(ControlStyles.UserPaint, true); // SetStyle(ControlStyles.DoubleBuffer, false); } public void Close() { if (completionData != null) { Array.Clear(completionData, 0, completionData.Length); } base.Dispose(); } public void SelectIndex(int index) { int oldSelectedItem = selectedItem; int oldFirstItem = firstItem; index = Math.Max(0, index); selectedItem = Math.Max(0, Math.Min(completionData.Length - 1, index)); if (selectedItem < firstItem) { FirstItem = selectedItem; } if (firstItem + MaxVisibleItem <= selectedItem) { FirstItem = selectedItem - MaxVisibleItem + 1; } if (oldSelectedItem != selectedItem) { if (firstItem != oldFirstItem) { Invalidate(); } else { int min = Math.Min(selectedItem, oldSelectedItem) - firstItem; int max = Math.Max(selectedItem, oldSelectedItem) - firstItem; Invalidate(new Rectangle(0, 1 + min * ItemHeight, Width, (max - min + 1) * ItemHeight)); } OnSelectedItemChanged(EventArgs.Empty); } } public void CenterViewOn(int index) { int oldFirstItem = this.FirstItem; int firstItem = index - MaxVisibleItem / 2; if (firstItem < 0) this.FirstItem = 0; else if (firstItem >= completionData.Length - MaxVisibleItem) this.FirstItem = completionData.Length - MaxVisibleItem; else this.FirstItem = firstItem; if (this.FirstItem != oldFirstItem) { Invalidate(); } } public void ClearSelection() { if (selectedItem < 0) return; int itemNum = selectedItem - firstItem; selectedItem = -1; Invalidate(new Rectangle(0, itemNum * ItemHeight, Width, (itemNum + 1) * ItemHeight + 1)); Update(); OnSelectedItemChanged(EventArgs.Empty); } public void PageDown() { SelectIndex(selectedItem + MaxVisibleItem); } public void PageUp() { SelectIndex(selectedItem - MaxVisibleItem); } public void SelectNextItem() { SelectIndex(selectedItem + 1); } public void SelectPrevItem() { SelectIndex(selectedItem - 1); } public void SelectItemWithStart(string startText) { if (startText == null || startText.Length == 0) return; string originalStartText = startText; startText = startText.ToLower(); int bestIndex = -1; int bestQuality = -1; // Qualities: 0 = match start // 1 = match start case sensitive // 2 = full match // 3 = full match case sensitive double bestPriority = 0; for (int i = 0; i < completionData.Length; ++i) { string itemText = completionData[i].Text; string lowerText = itemText.ToLower(); if (lowerText.StartsWith(startText)) { double priority = completionData[i].Priority; int quality; if (lowerText == startText) { if (itemText == originalStartText) quality = 3; else quality = 2; } else if (itemText.StartsWith(originalStartText)) { quality = 1; } else { quality = 0; } bool useThisItem; if (bestQuality < quality) { useThisItem = true; } else { if (bestIndex == selectedItem) { useThisItem = false; } else if (i == selectedItem) { useThisItem = bestQuality == quality; } else { useThisItem = bestQuality == quality && bestPriority < priority; } } if (useThisItem) { bestIndex = i; bestPriority = priority; bestQuality = quality; } } } if (bestIndex < 0) { ClearSelection(); } else { if (bestIndex < firstItem || firstItem + MaxVisibleItem <= bestIndex) { SelectIndex(bestIndex); CenterViewOn(bestIndex); } else { SelectIndex(bestIndex); } } } protected override void OnPaint(PaintEventArgs pe) { float yPos = 1; float itemHeight = ItemHeight; // Maintain aspect ratio int imageWidth = (int)(itemHeight * imageList.ImageSize.Width / imageList.ImageSize.Height); int curItem = firstItem; Graphics g = pe.Graphics; while (curItem < completionData.Length && yPos < Height) { RectangleF drawingBackground = new RectangleF(1, yPos, Width - 2, itemHeight); if (drawingBackground.IntersectsWith(pe.ClipRectangle)) { // draw Background if (curItem == selectedItem) { g.FillRectangle(SystemBrushes.Highlight, drawingBackground); } else { g.FillRectangle(SystemBrushes.Window, drawingBackground); } // draw Icon int xPos = 0; if (imageList != null && completionData[curItem].ImageIndex < imageList.Images.Count) { g.DrawImage(imageList.Images[completionData[curItem].ImageIndex], new RectangleF(1, yPos, imageWidth, itemHeight)); xPos = imageWidth; } // draw text if (curItem == selectedItem) { g.DrawString(completionData[curItem].Text, Font, SystemBrushes.HighlightText, xPos, yPos); } else { g.DrawString(completionData[curItem].Text, Font, SystemBrushes.WindowText, xPos, yPos); } } yPos += itemHeight; ++curItem; } g.DrawRectangle(SystemPens.Control, new Rectangle(0, 0, Width - 1, Height - 1)); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { float yPos = 1; int curItem = firstItem; float itemHeight = ItemHeight; while (curItem < completionData.Length && yPos < Height) { RectangleF drawingBackground = new RectangleF(1, yPos, Width - 2, itemHeight); if (drawingBackground.Contains(e.X, e.Y)) { SelectIndex(curItem); break; } yPos += itemHeight; ++curItem; } } protected override void OnPaintBackground(PaintEventArgs pe) { } protected virtual void OnSelectedItemChanged(EventArgs e) { if (SelectedItemChanged != null) { SelectedItemChanged(this, e); } } protected virtual void OnFirstItemChanged(EventArgs e) { if (FirstItemChanged != null) { FirstItemChanged(this, e); } } public event EventHandler SelectedItemChanged; public event EventHandler FirstItemChanged; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/CompletionWindow/CodeCompletionWindow.cs ================================================ // // // // // $Revision: 3244 $ // using System; using System.Drawing; using System.Diagnostics; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Gui.CompletionWindow { public class CodeCompletionWindow : AbstractCompletionWindow { ICompletionData[] completionData; CodeCompletionListView codeCompletionListView; VScrollBar vScrollBar = new VScrollBar(); ICompletionDataProvider dataProvider; IDocument document; bool showDeclarationWindow = true; bool fixedListViewWidth = true; const int ScrollbarWidth = 16; const int MaxListLength = 10; int startOffset; int endOffset; DeclarationViewWindow declarationViewWindow = null; Rectangle workingScreen; public static CodeCompletionWindow ShowCompletionWindow(Form parent, TextEditorControl control, string fileName, ICompletionDataProvider completionDataProvider, char firstChar) { return ShowCompletionWindow(parent, control, fileName, completionDataProvider, firstChar, true, true); } public static CodeCompletionWindow ShowCompletionWindow(Form parent, TextEditorControl control, string fileName, ICompletionDataProvider completionDataProvider, char firstChar, bool showDeclarationWindow, bool fixedListViewWidth) { ICompletionData[] completionData = completionDataProvider.GenerateCompletionData(fileName, control.ActiveTextAreaControl.TextArea, firstChar); if (completionData == null || completionData.Length == 0) { return null; } CodeCompletionWindow codeCompletionWindow = new CodeCompletionWindow(completionDataProvider, completionData, parent, control, showDeclarationWindow, fixedListViewWidth); codeCompletionWindow.CloseWhenCaretAtBeginning = firstChar == '\0'; codeCompletionWindow.ShowCompletionWindow(); return codeCompletionWindow; } CodeCompletionWindow(ICompletionDataProvider completionDataProvider, ICompletionData[] completionData, Form parentForm, TextEditorControl control, bool showDeclarationWindow, bool fixedListViewWidth) : base(parentForm, control) { this.dataProvider = completionDataProvider; this.completionData = completionData; this.document = control.Document; this.showDeclarationWindow = showDeclarationWindow; this.fixedListViewWidth = fixedListViewWidth; workingScreen = Screen.GetWorkingArea(Location); startOffset = control.ActiveTextAreaControl.Caret.Offset + 1; endOffset = startOffset; if (completionDataProvider.PreSelection != null) { startOffset -= completionDataProvider.PreSelection.Length + 1; endOffset--; } codeCompletionListView = new CodeCompletionListView(completionData); codeCompletionListView.ImageList = completionDataProvider.ImageList; codeCompletionListView.Dock = DockStyle.Fill; codeCompletionListView.SelectedItemChanged += new EventHandler(CodeCompletionListViewSelectedItemChanged); codeCompletionListView.DoubleClick += new EventHandler(CodeCompletionListViewDoubleClick); codeCompletionListView.Click += new EventHandler(CodeCompletionListViewClick); Controls.Add(codeCompletionListView); if (completionData.Length > MaxListLength) { vScrollBar.Dock = DockStyle.Right; vScrollBar.Minimum = 0; vScrollBar.Maximum = completionData.Length - 1; vScrollBar.SmallChange = 1; vScrollBar.LargeChange = MaxListLength; codeCompletionListView.FirstItemChanged += new EventHandler(CodeCompletionListViewFirstItemChanged); Controls.Add(vScrollBar); } this.drawingSize = GetListViewSize(); SetLocation(); if (declarationViewWindow == null) { declarationViewWindow = new DeclarationViewWindow(parentForm); } SetDeclarationViewLocation(); declarationViewWindow.ShowDeclarationViewWindow(); declarationViewWindow.MouseMove += ControlMouseMove; control.Focus(); CodeCompletionListViewSelectedItemChanged(this, EventArgs.Empty); if (completionDataProvider.DefaultIndex >= 0) { codeCompletionListView.SelectIndex(completionDataProvider.DefaultIndex); } if (completionDataProvider.PreSelection != null) { CaretOffsetChanged(this, EventArgs.Empty); } vScrollBar.ValueChanged += VScrollBarValueChanged; document.DocumentAboutToBeChanged += DocumentAboutToBeChanged; } bool inScrollUpdate; void CodeCompletionListViewFirstItemChanged(object sender, EventArgs e) { if (inScrollUpdate) return; inScrollUpdate = true; vScrollBar.Value = Math.Min(vScrollBar.Maximum, codeCompletionListView.FirstItem); inScrollUpdate = false; } void VScrollBarValueChanged(object sender, EventArgs e) { if (inScrollUpdate) return; inScrollUpdate = true; codeCompletionListView.FirstItem = vScrollBar.Value; codeCompletionListView.Refresh(); control.ActiveTextAreaControl.TextArea.Focus(); inScrollUpdate = false; } void SetDeclarationViewLocation() { // This method uses the side with more free space int leftSpace = Bounds.Left - workingScreen.Left; int rightSpace = workingScreen.Right - Bounds.Right; Point pos; // The declaration view window has better line break when used on // the right side, so prefer the right side to the left. if (rightSpace * 2 > leftSpace) pos = new Point(Bounds.Right, Bounds.Top); else pos = new Point(Bounds.Left - declarationViewWindow.Width, Bounds.Top); if (declarationViewWindow.Location != pos) { declarationViewWindow.Location = pos; } } protected override void SetLocation() { base.SetLocation(); if (declarationViewWindow != null) { SetDeclarationViewLocation(); } } Util.MouseWheelHandler mouseWheelHandler = new Util.MouseWheelHandler(); public void HandleMouseWheel(MouseEventArgs e) { int scrollDistance = mouseWheelHandler.GetScrollAmount(e); if (scrollDistance == 0) return; if (control.TextEditorProperties.MouseWheelScrollDown) scrollDistance = -scrollDistance; int newValue = vScrollBar.Value + vScrollBar.SmallChange * scrollDistance; vScrollBar.Value = Math.Max(vScrollBar.Minimum, Math.Min(vScrollBar.Maximum - vScrollBar.LargeChange + 1, newValue)); } void CodeCompletionListViewSelectedItemChanged(object sender, EventArgs e) { ICompletionData data = codeCompletionListView.SelectedCompletionData; if (showDeclarationWindow && data != null && data.Description != null && data.Description.Length > 0) { declarationViewWindow.Description = data.Description; SetDeclarationViewLocation(); } else { declarationViewWindow.Description = null; } } public override bool ProcessKeyEvent(char ch) { switch (dataProvider.ProcessKey(ch)) { case CompletionDataProviderKeyResult.BeforeStartKey: // increment start+end, then process as normal char ++startOffset; ++endOffset; return base.ProcessKeyEvent(ch); case CompletionDataProviderKeyResult.NormalKey: // just process normally return base.ProcessKeyEvent(ch); case CompletionDataProviderKeyResult.InsertionKey: return InsertSelectedItem(ch); default: throw new InvalidOperationException("Invalid return value of dataProvider.ProcessKey"); } } void DocumentAboutToBeChanged(object sender, DocumentEventArgs e) { // => startOffset test required so that this startOffset/endOffset are not incremented again // for BeforeStartKey characters if (e.Offset >= startOffset && e.Offset <= endOffset) { if (e.Length > 0) { // length of removed region endOffset -= e.Length; } if (!string.IsNullOrEmpty(e.Text)) { endOffset += e.Text.Length; } } } /// /// When this flag is set, code completion closes if the caret moves to the /// beginning of the allowed range. This is useful in Ctrl+Space and "complete when typing", /// but not in dot-completion. /// public bool CloseWhenCaretAtBeginning { get; set; } protected override void CaretOffsetChanged(object sender, EventArgs e) { int offset = control.ActiveTextAreaControl.Caret.Offset; if (offset == startOffset) { if (CloseWhenCaretAtBeginning) Close(); return; } if (offset < startOffset || offset > endOffset) { Close(); } else { codeCompletionListView.SelectItemWithStart(control.Document.GetText(startOffset, offset - startOffset)); } } protected override bool ProcessTextAreaKey(Keys keyData) { if (!Visible) { return false; } switch (keyData) { case Keys.Home: codeCompletionListView.SelectIndex(0); return true; case Keys.End: codeCompletionListView.SelectIndex(completionData.Length-1); return true; case Keys.PageDown: codeCompletionListView.PageDown(); return true; case Keys.PageUp: codeCompletionListView.PageUp(); return true; case Keys.Down: codeCompletionListView.SelectNextItem(); return true; case Keys.Up: codeCompletionListView.SelectPrevItem(); return true; case Keys.Tab: InsertSelectedItem('\t'); return true; case Keys.Return: InsertSelectedItem('\n'); return true; } return base.ProcessTextAreaKey(keyData); } void CodeCompletionListViewDoubleClick(object sender, EventArgs e) { InsertSelectedItem('\0'); } void CodeCompletionListViewClick(object sender, EventArgs e) { control.ActiveTextAreaControl.TextArea.Focus(); } protected override void Dispose(bool disposing) { if (disposing) { document.DocumentAboutToBeChanged -= DocumentAboutToBeChanged; if (codeCompletionListView != null) { codeCompletionListView.Dispose(); codeCompletionListView = null; } if (declarationViewWindow != null) { declarationViewWindow.Dispose(); declarationViewWindow = null; } } base.Dispose(disposing); } bool InsertSelectedItem(char ch) { document.DocumentAboutToBeChanged -= DocumentAboutToBeChanged; ICompletionData data = codeCompletionListView.SelectedCompletionData; bool result = false; if (data != null) { control.BeginUpdate(); try { if (endOffset - startOffset > 0) { control.Document.Remove(startOffset, endOffset - startOffset); } Debug.Assert(startOffset <= document.TextLength); result = dataProvider.InsertAction(data, control.ActiveTextAreaControl.TextArea, startOffset, ch); } finally { control.EndUpdate(); } } Close(); return result; } Size GetListViewSize() { int height = codeCompletionListView.ItemHeight * Math.Min(MaxListLength, completionData.Length); int width = codeCompletionListView.ItemHeight * 10; if (!fixedListViewWidth) { width = GetListViewWidth(width, height); } return new Size(width, height); } /// /// Gets the list view width large enough to handle the longest completion data /// text string. /// /// The default width of the list view. /// The height of the list view. This is /// used to determine if the scrollbar is visible. /// The list view width to accommodate the longest completion /// data text string; otherwise the default width. int GetListViewWidth(int defaultWidth, int height) { float width = defaultWidth; using (Graphics graphics = codeCompletionListView.CreateGraphics()) { for (int i = 0; i < completionData.Length; ++i) { float itemWidth = graphics.MeasureString(completionData[i].Text.ToString(), codeCompletionListView.Font).Width; if(itemWidth > width) { width = itemWidth; } } } float totalItemsHeight = codeCompletionListView.ItemHeight * completionData.Length; if (totalItemsHeight > height) { width += ScrollbarWidth; // Compensate for scroll bar. } return (int)width; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/CompletionWindow/DeclarationViewWindow.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Drawing; using System.Windows.Forms; using ICSharpCode.TextEditor.Util; namespace ICSharpCode.TextEditor.Gui.CompletionWindow { public interface IDeclarationViewWindow { string Description { get; set; } void ShowDeclarationViewWindow(); void CloseDeclarationViewWindow(); } public class DeclarationViewWindow : Form, IDeclarationViewWindow { string description = String.Empty; public string Description { get { return description; } set { description = value; if (value == null && Visible) { Visible = false; } else if (value != null) { if (!Visible) ShowDeclarationViewWindow(); Refresh(); } } } public bool HideOnClick; public DeclarationViewWindow(Form parent) { SetStyle(ControlStyles.Selectable, false); StartPosition = FormStartPosition.Manual; FormBorderStyle = FormBorderStyle.None; Owner = parent; ShowInTaskbar = false; Size = new Size(0, 0); base.CreateHandle(); } protected override CreateParams CreateParams { get { CreateParams p = base.CreateParams; AbstractCompletionWindow.AddShadowToWindow(p); return p; } } protected override bool ShowWithoutActivation { get { return true; } } protected override void OnClick(EventArgs e) { base.OnClick(e); if (HideOnClick) Hide(); } public void ShowDeclarationViewWindow() { Show(); } public void CloseDeclarationViewWindow() { Close(); Dispose(); } protected override void OnPaint(PaintEventArgs pe) { if (description != null && description.Length > 0) { TipPainterTools.DrawHelpTipFromCombinedDescription(this, pe.Graphics, Font, null, description); } } protected override void OnPaintBackground(PaintEventArgs pe) { pe.Graphics.FillRectangle(SystemBrushes.Info, pe.ClipRectangle); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/CompletionWindow/ICompletionData.cs ================================================ // // // // // $Revision: 2932 $ // using System; namespace ICSharpCode.TextEditor.Gui.CompletionWindow { public interface ICompletionData { int ImageIndex { get; } string Text { get; set; } string Description { get; } /// /// Gets a priority value for the completion data item. /// When selecting items by their start characters, the item with the highest /// priority is selected first. /// double Priority { get; } /// /// Insert the element represented by the completion data into the text /// editor. /// /// TextArea to insert the completion data in. /// Character that should be inserted after the completion data. /// \0 when no character should be inserted. /// Returns true when the insert action has processed the character /// ; false when the character was not processed. bool InsertAction(TextArea textArea, char ch); } public class DefaultCompletionData : ICompletionData { string text; string description; int imageIndex; public int ImageIndex { get { return imageIndex; } } public string Text { get { return text; } set { text = value; } } public string Description { get { return description; } } double priority; public double Priority { get { return priority; } set { priority = value; } } public virtual bool InsertAction(TextArea textArea, char ch) { textArea.InsertString(text); return false; } public DefaultCompletionData(string text, string description, int imageIndex) { this.text = text; this.description = description; this.imageIndex = imageIndex; } public static int Compare(ICompletionData a, ICompletionData b) { if (a == null) throw new ArgumentNullException("a"); if (b == null) throw new ArgumentNullException("b"); return string.Compare(a.Text, b.Text, StringComparison.InvariantCultureIgnoreCase); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/CompletionWindow/ICompletionDataProvider.cs ================================================ // // // // // $Revision: 2074 $ // using System; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Gui.CompletionWindow { public interface ICompletionDataProvider { ImageList ImageList { get; } string PreSelection { get; } /// /// Gets the index of the element in the list that is chosen by default. /// int DefaultIndex { get; } /// /// Processes a keypress. Returns the action to be run with the key. /// CompletionDataProviderKeyResult ProcessKey(char key); /// /// Executes the insertion. The provider should set the caret position and then /// call data.InsertAction. /// bool InsertAction(ICompletionData data, TextArea textArea, int insertionOffset, char key); /// /// Generates the completion data. This method is called by the text editor control. /// ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped); } public enum CompletionDataProviderKeyResult { /// /// Normal key, used to choose an entry from the completion list /// NormalKey, /// /// This key triggers insertion of the completed expression /// InsertionKey, /// /// Increment both start and end offset of completion region when inserting this /// key. Can be used to insert whitespace (or other characters) in front of the expression /// while the completion window is open. /// BeforeStartKey } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/DrawableLine.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Collections.Generic; using System.Drawing; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// A class that is able to draw a line on any control (outside the text editor) /// public class DrawableLine { static StringFormat sf = (StringFormat)System.Drawing.StringFormat.GenericTypographic.Clone(); List words = new List(); SizeF spaceSize; Font monospacedFont; Font boldMonospacedFont; private class SimpleTextWord { internal TextWordType Type; internal string Word; internal bool Bold; internal Color Color; public SimpleTextWord(TextWordType Type, string Word, bool Bold, Color Color) { this.Type = Type; this.Word = Word; this.Bold = Bold; this.Color = Color; } internal readonly static SimpleTextWord Space = new SimpleTextWord(TextWordType.Space, " ", false, Color.Black); internal readonly static SimpleTextWord Tab = new SimpleTextWord(TextWordType.Tab, "\t", false, Color.Black); } public DrawableLine(IDocument document, LineSegment line, Font monospacedFont, Font boldMonospacedFont) { this.monospacedFont = monospacedFont; this.boldMonospacedFont = boldMonospacedFont; if (line.Words != null) { foreach (TextWord word in line.Words) { if (word.Type == TextWordType.Space) { words.Add(SimpleTextWord.Space); } else if (word.Type == TextWordType.Tab) { words.Add(SimpleTextWord.Tab); } else { words.Add(new SimpleTextWord(TextWordType.Word, word.Word, word.Bold, word.Color)); } } } else { words.Add(new SimpleTextWord(TextWordType.Word, document.GetText(line), false, Color.Black)); } } public int LineLength { get { int length = 0; foreach (SimpleTextWord word in words) { length += word.Word.Length; } return length; } } public void SetBold(int startIndex, int endIndex, bool bold) { if (startIndex < 0) throw new ArgumentException("startIndex must be >= 0"); if (startIndex > endIndex) throw new ArgumentException("startIndex must be <= endIndex"); if (startIndex == endIndex) return; int pos = 0; for (int i = 0; i < words.Count; i++) { SimpleTextWord word = words[i]; if (pos >= endIndex) break; int wordEnd = pos + word.Word.Length; // 3 possibilities: if (startIndex <= pos && endIndex >= wordEnd) { // word is fully in region: word.Bold = bold; } else if (startIndex <= pos) { // beginning of word is in region int inRegionLength = endIndex - pos; SimpleTextWord newWord = new SimpleTextWord(word.Type, word.Word.Substring(inRegionLength), word.Bold, word.Color); words.Insert(i + 1, newWord); word.Bold = bold; word.Word = word.Word.Substring(0, inRegionLength); } else if (startIndex < wordEnd) { // end of word is in region (or middle of word is in region) int notInRegionLength = startIndex - pos; SimpleTextWord newWord = new SimpleTextWord(word.Type, word.Word.Substring(notInRegionLength), word.Bold, word.Color); // newWord.Bold will be set in the next iteration words.Insert(i + 1, newWord); word.Word = word.Word.Substring(0, notInRegionLength); } pos = wordEnd; } } public static float DrawDocumentWord(Graphics g, string word, PointF position, Font font, Color foreColor) { if (word == null || word.Length == 0) { return 0f; } SizeF wordSize = g.MeasureString(word, font, 32768, sf); g.DrawString(word, font, BrushRegistry.GetBrush(foreColor), position, sf); return wordSize.Width; } public SizeF GetSpaceSize(Graphics g) { if (spaceSize.IsEmpty) { spaceSize = g.MeasureString("-", boldMonospacedFont, new PointF(0, 0), sf); } return spaceSize; } public void DrawLine(Graphics g, ref float xPos, float xOffset, float yPos, Color c) { SizeF spaceSize = GetSpaceSize(g); foreach (SimpleTextWord word in words) { switch (word.Type) { case TextWordType.Space: xPos += spaceSize.Width; break; case TextWordType.Tab: float tabWidth = spaceSize.Width * 4; xPos += tabWidth; xPos = (int)((xPos + 2) / tabWidth) * tabWidth; break; case TextWordType.Word: xPos += DrawDocumentWord(g, word.Word, new PointF(xPos + xOffset, yPos), word.Bold ? boldMonospacedFont : monospacedFont, c == Color.Empty ? word.Color : c ); break; } } } public void DrawLine(Graphics g, ref float xPos, float xOffset, float yPos) { DrawLine(g, ref xPos, xOffset, yPos, Color.Empty); } public float MeasureWidth(Graphics g, float xPos) { SizeF spaceSize = GetSpaceSize(g); foreach (SimpleTextWord word in words) { switch (word.Type) { case TextWordType.Space: xPos += spaceSize.Width; break; case TextWordType.Tab: float tabWidth = spaceSize.Width * 4; xPos += tabWidth; xPos = (int)((xPos + 2) / tabWidth) * tabWidth; break; case TextWordType.Word: if (word.Word != null && word.Word.Length > 0) { xPos += g.MeasureString(word.Word, word.Bold ? boldMonospacedFont : monospacedFont, 32768, sf).Width; } break; } } return xPos; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/FindReplaceForm/FindAndReplaceForm.Designer.cs ================================================ namespace ICSharpCode.TextEditor { partial class FindAndReplaceForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.lblReplaceWith = new System.Windows.Forms.Label(); this.txtLookFor = new System.Windows.Forms.TextBox(); this.txtReplaceWith = new System.Windows.Forms.TextBox(); this.btnFindNext = new System.Windows.Forms.Button(); this.btnReplace = new System.Windows.Forms.Button(); this.btnReplaceAll = new System.Windows.Forms.Button(); this.chkMatchWholeWord = new System.Windows.Forms.CheckBox(); this.chkMatchCase = new System.Windows.Forms.CheckBox(); this.btnHighlightAll = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); this.btnFindPrevious = new System.Windows.Forms.Button(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(12, 9); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(56, 13); this.label1.TabIndex = 0; this.label1.Text = "Fi&nd what:"; // // lblReplaceWith // this.lblReplaceWith.AutoSize = true; this.lblReplaceWith.Location = new System.Drawing.Point(12, 35); this.lblReplaceWith.Name = "lblReplaceWith"; this.lblReplaceWith.Size = new System.Drawing.Size(72, 13); this.lblReplaceWith.TabIndex = 2; this.lblReplaceWith.Text = "Re&place with:"; // // txtLookFor // this.txtLookFor.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtLookFor.Location = new System.Drawing.Point(90, 6); this.txtLookFor.Name = "txtLookFor"; this.txtLookFor.Size = new System.Drawing.Size(232, 20); this.txtLookFor.TabIndex = 1; // // txtReplaceWith // this.txtReplaceWith.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtReplaceWith.Location = new System.Drawing.Point(90, 32); this.txtReplaceWith.Name = "txtReplaceWith"; this.txtReplaceWith.Size = new System.Drawing.Size(232, 20); this.txtReplaceWith.TabIndex = 3; // // btnFindNext // this.btnFindNext.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnFindNext.Location = new System.Drawing.Point(247, 81); this.btnFindNext.Name = "btnFindNext"; this.btnFindNext.Size = new System.Drawing.Size(75, 23); this.btnFindNext.TabIndex = 6; this.btnFindNext.Text = "&Find next"; this.btnFindNext.UseVisualStyleBackColor = true; this.btnFindNext.Click += new System.EventHandler(this.btnFindNext_Click); // // btnReplace // this.btnReplace.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnReplace.Location = new System.Drawing.Point(85, 110); this.btnReplace.Name = "btnReplace"; this.btnReplace.Size = new System.Drawing.Size(75, 23); this.btnReplace.TabIndex = 7; this.btnReplace.Text = "&Replace"; this.btnReplace.UseVisualStyleBackColor = true; this.btnReplace.Click += new System.EventHandler(this.btnReplace_Click); // // btnReplaceAll // this.btnReplaceAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnReplaceAll.Location = new System.Drawing.Point(166, 110); this.btnReplaceAll.Name = "btnReplaceAll"; this.btnReplaceAll.Size = new System.Drawing.Size(75, 23); this.btnReplaceAll.TabIndex = 9; this.btnReplaceAll.Text = "Replace &All"; this.btnReplaceAll.UseVisualStyleBackColor = true; this.btnReplaceAll.Click += new System.EventHandler(this.btnReplaceAll_Click); // // chkMatchWholeWord // this.chkMatchWholeWord.AutoSize = true; this.chkMatchWholeWord.Location = new System.Drawing.Point(178, 58); this.chkMatchWholeWord.Name = "chkMatchWholeWord"; this.chkMatchWholeWord.Size = new System.Drawing.Size(113, 17); this.chkMatchWholeWord.TabIndex = 5; this.chkMatchWholeWord.Text = "Match &whole word"; this.chkMatchWholeWord.UseVisualStyleBackColor = true; // // chkMatchCase // this.chkMatchCase.AutoSize = true; this.chkMatchCase.Location = new System.Drawing.Point(90, 58); this.chkMatchCase.Name = "chkMatchCase"; this.chkMatchCase.Size = new System.Drawing.Size(82, 17); this.chkMatchCase.TabIndex = 4; this.chkMatchCase.Text = "Match &case"; this.chkMatchCase.UseVisualStyleBackColor = true; // // btnHighlightAll // this.btnHighlightAll.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnHighlightAll.Location = new System.Drawing.Point(105, 110); this.btnHighlightAll.Name = "btnHighlightAll"; this.btnHighlightAll.Size = new System.Drawing.Size(136, 23); this.btnHighlightAll.TabIndex = 8; this.btnHighlightAll.Text = "Find && highlight &all"; this.btnHighlightAll.UseVisualStyleBackColor = true; this.btnHighlightAll.Visible = false; this.btnHighlightAll.Click += new System.EventHandler(this.btnHighlightAll_Click); // // btnCancel // this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.btnCancel.Location = new System.Drawing.Point(247, 110); this.btnCancel.Name = "btnCancel"; this.btnCancel.Size = new System.Drawing.Size(75, 23); this.btnCancel.TabIndex = 6; this.btnCancel.Text = "Cancel"; this.btnCancel.UseVisualStyleBackColor = true; this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); // // btnFindPrevious // this.btnFindPrevious.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnFindPrevious.Location = new System.Drawing.Point(157, 81); this.btnFindPrevious.Name = "btnFindPrevious"; this.btnFindPrevious.Size = new System.Drawing.Size(84, 23); this.btnFindPrevious.TabIndex = 6; this.btnFindPrevious.Text = "Find pre&vious"; this.btnFindPrevious.UseVisualStyleBackColor = true; this.btnFindPrevious.Click += new System.EventHandler(this.btnFindPrevious_Click); // // FindAndReplaceForm // this.AcceptButton = this.btnReplace; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.btnCancel; this.ClientSize = new System.Drawing.Size(334, 145); this.Controls.Add(this.chkMatchCase); this.Controls.Add(this.chkMatchWholeWord); this.Controls.Add(this.btnReplaceAll); this.Controls.Add(this.btnReplace); this.Controls.Add(this.btnHighlightAll); this.Controls.Add(this.btnCancel); this.Controls.Add(this.btnFindPrevious); this.Controls.Add(this.btnFindNext); this.Controls.Add(this.txtReplaceWith); this.Controls.Add(this.txtLookFor); this.Controls.Add(this.lblReplaceWith); this.Controls.Add(this.label1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "FindAndReplaceForm"; this.ShowIcon = false; this.Text = "Find and replace"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FindAndReplaceForm_FormClosing); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; private System.Windows.Forms.Label lblReplaceWith; private System.Windows.Forms.TextBox txtLookFor; private System.Windows.Forms.TextBox txtReplaceWith; private System.Windows.Forms.Button btnFindNext; private System.Windows.Forms.Button btnReplace; private System.Windows.Forms.Button btnReplaceAll; private System.Windows.Forms.CheckBox chkMatchWholeWord; private System.Windows.Forms.CheckBox chkMatchCase; private System.Windows.Forms.Button btnHighlightAll; private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.Button btnFindPrevious; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/FindReplaceForm/FindAndReplaceForm.cs ================================================  // code stolen from https://www.codeproject.com/Articles/30936/Using-ICSharpCode-TextEditor // Merged into ICSharpCode by Josh Barczak for Pyramid using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor; using System.Diagnostics; using System.IO; namespace ICSharpCode.TextEditor { public partial class FindAndReplaceForm : Form { public FindAndReplaceForm() { InitializeComponent(); _search = new TextEditorSearcher(); } TextEditorSearcher _search; TextEditorControl _editor; TextEditorControl Editor { get { return _editor; } set { _editor = value; _search.Document = _editor.Document; UpdateTitleBar(); } } private void UpdateTitleBar() { string text = ReplaceMode ? "Find & replace" : "Find"; if (_editor != null && _editor.FileName != null) text += " - " + Path.GetFileName(_editor.FileName); if (_search.HasScanRegion) text += " (selection only)"; this.Text = text; } public void ShowFor(TextEditorControl editor, bool replaceMode) { Editor = editor; _search.ClearScanRegion(); var sm = editor.ActiveTextAreaControl.SelectionManager; if (sm.HasSomethingSelected && sm.SelectionCollection.Count == 1) { var sel = sm.SelectionCollection[0]; if (sel.StartPosition.Line == sel.EndPosition.Line) txtLookFor.Text = sm.SelectedText; else _search.SetScanRegion(sel); } else { // Get the current word that the caret is on Caret caret = editor.ActiveTextAreaControl.Caret; int start = TextUtilities.FindWordStart(editor.Document, caret.Offset); int endAt = TextUtilities.FindWordEnd(editor.Document, caret.Offset); txtLookFor.Text = editor.Document.GetText(start, endAt - start); } ReplaceMode = replaceMode; this.Owner = (Form)editor.TopLevelControl; this.Show(); txtLookFor.SelectAll(); txtLookFor.Focus(); } public bool ReplaceMode { get { return txtReplaceWith.Visible; } set { btnReplace.Visible = btnReplaceAll.Visible = value; lblReplaceWith.Visible = txtReplaceWith.Visible = value; btnHighlightAll.Visible = !value; this.AcceptButton = value ? btnReplace : btnFindNext; UpdateTitleBar(); } } private void btnFindPrevious_Click(object sender, EventArgs e) { FindNext(false, true, "Text not found"); } private void btnFindNext_Click(object sender, EventArgs e) { FindNext(false, false, "Text not found"); } private bool _lastSearchWasBackward = false; private bool _lastSearchLoopedAround; public TextRange FindNext(bool viaF3, bool searchBackward, string messageIfNotFound) { if (string.IsNullOrEmpty(txtLookFor.Text)) { MessageBox.Show("No string specified to look for!"); return null; } _lastSearchWasBackward = searchBackward; _search.LookFor = txtLookFor.Text; _search.MatchCase = chkMatchCase.Checked; _search.MatchWholeWordOnly = chkMatchWholeWord.Checked; var caret = _editor.ActiveTextAreaControl.Caret; if (viaF3 && _search.HasScanRegion && !caret.Offset. IsInRange(_search.BeginOffset, _search.EndOffset)) { // user moved outside of the originally selected region _search.ClearScanRegion(); UpdateTitleBar(); } int startFrom = caret.Offset - (searchBackward ? 1 : 0); TextRange range = _search.FindNext(startFrom, searchBackward, out _lastSearchLoopedAround); if (range != null) SelectResult(range); else if (messageIfNotFound != null) MessageBox.Show(messageIfNotFound); return range; } private void SelectResult(TextRange range) { TextLocation p1 = _editor.Document.OffsetToPosition(range.Offset); TextLocation p2 = _editor.Document.OffsetToPosition(range.Offset + range.Length); _editor.ActiveTextAreaControl.SelectionManager.SetSelection(p1, p2); _editor.ActiveTextAreaControl.ScrollTo(p1.Line, p1.Column); // Also move the caret to the end of the selection, because when the user // presses F3, the caret is where we start searching next time. _editor.ActiveTextAreaControl.Caret.Position = _editor.Document.OffsetToPosition(range.Offset + range.Length); } Dictionary _highlightGroups = new Dictionary(); private void btnHighlightAll_Click(object sender, EventArgs e) { if (!_highlightGroups.ContainsKey(_editor)) _highlightGroups[_editor] = new HighlightGroup(_editor); HighlightGroup group = _highlightGroups[_editor]; group.ClearMarkers(); if (!string.IsNullOrEmpty(LookFor)) { _search.LookFor = txtLookFor.Text; _search.MatchCase = chkMatchCase.Checked; _search.MatchWholeWordOnly = chkMatchWholeWord.Checked; bool looped = false; int offset = 0, count = 0; for(;;) { TextRange range = _search.FindNext(offset, false, out looped); if (range == null || looped) break; offset = range.Offset + range.Length; count++; var m = new TextMarker(range.Offset, range.Length, TextMarkerType.SolidBlock, Color.Yellow, Color.Black); group.AddMarker(m); } _editor.Refresh(); // must repaint manually // JDB: Closing and leaving all the highlights active is annoying //if (count == 0) // MessageBox.Show("Search text not found."); //else // Close(); } } private void FindAndReplaceForm_FormClosing(object sender, FormClosingEventArgs e) { // Prevent dispose, as this form can be re-used if (e.CloseReason != CloseReason.FormOwnerClosing) { if (this.Owner != null) this.Owner.Select(); // prevent another app from being activated instead e.Cancel = true; Hide(); // Discard search region _search.ClearScanRegion(); if( _highlightGroups.ContainsKey(_editor)) _highlightGroups[_editor].ClearMarkers(); _editor.Refresh(); // must repaint manually } } private void btnCancel_Click(object sender, EventArgs e) { Close(); } private void btnReplace_Click(object sender, EventArgs e) { var sm = _editor.ActiveTextAreaControl.SelectionManager; if (string.Equals(sm.SelectedText, txtLookFor.Text, StringComparison.OrdinalIgnoreCase)) InsertText(txtReplaceWith.Text); FindNext(false, _lastSearchWasBackward, "Text not found."); } private void btnReplaceAll_Click(object sender, EventArgs e) { int count = 0; // BUG FIX: if the replacement string contains the original search string // (e.g. replace "red" with "very red") we must avoid looping around and // replacing forever! To fix, start replacing at beginning of region (by // moving the caret) and stop as soon as we loop around. _editor.ActiveTextAreaControl.Caret.Position = _editor.Document.OffsetToPosition(_search.BeginOffset); _editor.Document.UndoStack.StartUndoGroup(); try { while (FindNext(false, false, null) != null) { if (_lastSearchLoopedAround) break; // Replace count++; InsertText(txtReplaceWith.Text); } } finally { _editor.Document.UndoStack.EndUndoGroup(); } if (count == 0) MessageBox.Show("No occurrances found."); else { MessageBox.Show(string.Format("Replaced {0} occurrances.", count)); Close(); } } private void InsertText(string text) { var textArea = _editor.ActiveTextAreaControl.TextArea; textArea.Document.UndoStack.StartUndoGroup(); try { if (textArea.SelectionManager.HasSomethingSelected) { textArea.Caret.Position = textArea.SelectionManager.SelectionCollection[0].StartPosition; textArea.SelectionManager.RemoveSelectedText(); } textArea.InsertString(text); } finally { textArea.Document.UndoStack.EndUndoGroup(); } } public string LookFor { get { return txtLookFor.Text; } } } public class TextRange : AbstractSegment { IDocument _document; public TextRange(IDocument document, int offset, int length) { _document = document; this.offset = offset; this.length = length; } } /// This class finds occurrances of a search string in a text /// editor's IDocument... it's like Find box without a GUI. public class TextEditorSearcher : IDisposable { IDocument _document; public IDocument Document { get { return _document; } set { if (_document != value) { ClearScanRegion(); _document = value; } } } // I would have used the TextAnchor class to represent the beginning and // end of the region to scan while automatically adjusting to changes in // the document--but for some reason it is sealed and its constructor is // internal. Instead I use a TextMarker, which is perhaps even better as // it gives me the opportunity to highlight the region. Note that all the // markers and coloring information is associated with the text document, // not the editor control, so TextEditorSearcher doesn't need a reference // to the TextEditorControl. After adding the marker to the document, we // must remember to remove it when it is no longer needed. TextMarker _region = null; /// Sets the region to search. The region is updated /// automatically as the document changes. public void SetScanRegion(ISelection sel) { SetScanRegion(sel.Offset, sel.Length); } /// Sets the region to search. The region is updated /// automatically as the document changes. public void SetScanRegion(int offset, int length) { var bkgColor = _document.HighlightingStrategy.GetColorFor("Default").BackgroundColor; _region = new TextMarker(offset, length, TextMarkerType.SolidBlock, bkgColor.HalfMix(Color.FromArgb(160,160,160))); _document.MarkerStrategy.AddMarker(_region); } public bool HasScanRegion { get { return _region != null; } } public void ClearScanRegion() { if (_region != null) { _document.MarkerStrategy.RemoveMarker(_region); _region = null; } } public void Dispose() { ClearScanRegion(); GC.SuppressFinalize(this); } ~TextEditorSearcher() { Dispose(); } /// Begins the start offset for searching public int BeginOffset { get { if (_region != null) return _region.Offset; else return 0; } } /// Begins the end offset for searching public int EndOffset { get { if (_region != null) return _region.EndOffset; else return _document.TextLength; } } public bool MatchCase; public bool MatchWholeWordOnly; string _lookFor; string _lookFor2; // uppercase in case-insensitive mode public string LookFor { get { return _lookFor; } set { _lookFor = value; } } /// Finds next instance of LookFor, according to the search rules /// (MatchCase, MatchWholeWordOnly). /// Offset in Document at which to begin the search /// If there is a match at beginAtOffset precisely, it will be returned. /// Region of document that matches the search string public TextRange FindNext(int beginAtOffset, bool searchBackward, out bool loopedAround) { Debug.Assert(!string.IsNullOrEmpty(_lookFor)); loopedAround = false; int startAt = BeginOffset, endAt = EndOffset; int curOffs = beginAtOffset.InRange(startAt, endAt); _lookFor2 = MatchCase ? _lookFor : _lookFor.ToUpperInvariant(); TextRange result; if (searchBackward) { result = FindNextIn(startAt, curOffs, true); if (result == null) { loopedAround = true; result = FindNextIn(curOffs, endAt, true); } } else { result = FindNextIn(curOffs, endAt, false); if (result == null) { loopedAround = true; result = FindNextIn(startAt, curOffs, false); } } return result; } private TextRange FindNextIn(int offset1, int offset2, bool searchBackward) { Debug.Assert(offset2 >= offset1); offset2 -= _lookFor.Length; // Make behavior decisions before starting search loop Func matchFirstCh; Func matchWord; if (MatchCase) matchFirstCh = (lookFor, c) => (lookFor == c); else matchFirstCh = (lookFor, c) => (lookFor == Char.ToUpperInvariant(c)); if (MatchWholeWordOnly) matchWord = IsWholeWordMatch; else matchWord = IsPartWordMatch; // Search char lookForCh = _lookFor2[0]; if (searchBackward) { for (int offset = offset2; offset >= offset1; offset--) { if (matchFirstCh(lookForCh, _document.GetCharAt(offset)) && matchWord(offset)) return new TextRange(_document, offset, _lookFor.Length); } } else { for (int offset = offset1; offset <= offset2; offset++) { if (matchFirstCh(lookForCh, _document.GetCharAt(offset)) && matchWord(offset)) return new TextRange(_document, offset, _lookFor.Length); } } return null; } private bool IsWholeWordMatch(int offset) { if (IsWordBoundary(offset) && IsWordBoundary(offset + _lookFor.Length)) return IsPartWordMatch(offset); else return false; } private bool IsWordBoundary(int offset) { return offset <= 0 || offset >= _document.TextLength || !IsAlphaNumeric(offset - 1) || !IsAlphaNumeric(offset); } private bool IsAlphaNumeric(int offset) { char c = _document.GetCharAt(offset); return Char.IsLetterOrDigit(c) || c == '_'; } private bool IsPartWordMatch(int offset) { string substr = _document.GetText(offset, _lookFor.Length); if (!MatchCase) substr = substr.ToUpperInvariant(); return substr == _lookFor2; } } /// Bundles a group of markers together so that they can be cleared /// together. public class HighlightGroup : IDisposable { List _markers = new List(); TextEditorControl _editor; IDocument _document; public HighlightGroup(TextEditorControl editor) { _editor = editor; _document = editor.Document; } public void AddMarker(TextMarker marker) { _markers.Add(marker); _document.MarkerStrategy.AddMarker(marker); } public void ClearMarkers() { foreach (TextMarker m in _markers) _document.MarkerStrategy.RemoveMarker(m); _markers.Clear(); _editor.Refresh(); } public void Dispose() { ClearMarkers(); GC.SuppressFinalize(this); } ~HighlightGroup() { Dispose(); } public IList Markers { get { return _markers.AsReadOnly(); } } } public static class FIndAndReplaceHelpers { public static int InRange(this int x, int lo, int hi) { Debug.Assert(lo <= hi); return x < lo ? lo : (x > hi ? hi : x); } public static bool IsInRange(this int x, int lo, int hi) { return x >= lo && x <= hi; } public static Color HalfMix(this Color one, Color two) { return Color.FromArgb( (one.A + two.A) >> 1, (one.R + two.R) >> 1, (one.G + two.G) >> 1, (one.B + two.B) >> 1); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/FindReplaceForm/FindAndReplaceForm.resx ================================================ text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/FoldMargin.cs ================================================ // // // // // $Revision: 2063 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class views the line numbers and folding markers. /// public class FoldMargin : AbstractMargin { int selectedFoldLine = -1; public override Size Size { get { return new Size((int)(textArea.TextView.FontHeight), -1); } } public override bool IsVisible { get { return textArea.TextEditorProperties.EnableFolding; } } public FoldMargin(TextArea textArea) : base(textArea) { } public override void Paint(Graphics g, Rectangle rect) { if (rect.Width <= 0 || rect.Height <= 0) { return; } HighlightColor lineNumberPainterColor = textArea.Document.HighlightingStrategy.GetColorFor("LineNumbers"); HighlightColor foldLineColor = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine"); for (int y = 0; y < (DrawingPosition.Height + textArea.TextView.VisibleLineDrawingRemainder) / textArea.TextView.FontHeight + 1; ++y) { Rectangle markerRectangle = new Rectangle(DrawingPosition.X, DrawingPosition.Top + y * textArea.TextView.FontHeight - textArea.TextView.VisibleLineDrawingRemainder, DrawingPosition.Width, textArea.TextView.FontHeight); if (rect.IntersectsWith(markerRectangle)) { // draw dotted separator line if (textArea.Document.TextEditorProperties.ShowLineNumbers) { g.FillRectangle(BrushRegistry.GetBrush(textArea.Enabled ? lineNumberPainterColor.BackgroundColor : SystemColors.InactiveBorder), new Rectangle(markerRectangle.X + 1, markerRectangle.Y, markerRectangle.Width - 1, markerRectangle.Height)); g.DrawLine(BrushRegistry.GetDotPen(lineNumberPainterColor.Color, lineNumberPainterColor.BackgroundColor), base.drawingPosition.X, markerRectangle.Y, base.drawingPosition.X, markerRectangle.Bottom); } else { g.FillRectangle(BrushRegistry.GetBrush(textArea.Enabled ? lineNumberPainterColor.BackgroundColor : SystemColors.InactiveBorder), markerRectangle); } int currentLine = textArea.Document.GetFirstLogicalLine(textArea.TextView.FirstPhysicalLine + y); if (currentLine < textArea.Document.TotalNumberOfLines) { PaintFoldMarker(g, currentLine, markerRectangle); } } } } bool SelectedFoldingFrom(List list) { if (list != null) { for (int i = 0; i < list.Count; ++i) { if (this.selectedFoldLine == list[i].StartLine) { return true; } } } return false; } void PaintFoldMarker(Graphics g, int lineNumber, Rectangle drawingRectangle) { HighlightColor foldLineColor = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine"); HighlightColor selectedFoldLine = textArea.Document.HighlightingStrategy.GetColorFor("SelectedFoldLine"); List foldingsWithStart = textArea.Document.FoldingManager.GetFoldingsWithStart(lineNumber); List foldingsBetween = textArea.Document.FoldingManager.GetFoldingsContainsLineNumber(lineNumber); List foldingsWithEnd = textArea.Document.FoldingManager.GetFoldingsWithEnd(lineNumber); bool isFoldStart = foldingsWithStart.Count > 0; bool isBetween = foldingsBetween.Count > 0; bool isFoldEnd = foldingsWithEnd.Count > 0; bool isStartSelected = SelectedFoldingFrom(foldingsWithStart); bool isBetweenSelected = SelectedFoldingFrom(foldingsBetween); bool isEndSelected = SelectedFoldingFrom(foldingsWithEnd); int foldMarkerSize = (int)Math.Round(textArea.TextView.FontHeight * 0.57f); foldMarkerSize -= (foldMarkerSize) % 2; int foldMarkerYPos = drawingRectangle.Y + (int)((drawingRectangle.Height - foldMarkerSize) / 2); int xPos = drawingRectangle.X + (drawingRectangle.Width - foldMarkerSize) / 2 + foldMarkerSize / 2; if (isFoldStart) { bool isVisible = true; bool moreLinedOpenFold = false; foreach (FoldMarker foldMarker in foldingsWithStart) { if (foldMarker.IsFolded) { isVisible = false; } else { moreLinedOpenFold = foldMarker.EndLine > foldMarker.StartLine; } } bool isFoldEndFromUpperFold = false; foreach (FoldMarker foldMarker in foldingsWithEnd) { if (foldMarker.EndLine > foldMarker.StartLine && !foldMarker.IsFolded) { isFoldEndFromUpperFold = true; } } DrawFoldMarker(g, new RectangleF(drawingRectangle.X + (drawingRectangle.Width - foldMarkerSize) / 2, foldMarkerYPos, foldMarkerSize, foldMarkerSize), isVisible, isStartSelected ); // draw line above fold marker if (isBetween || isFoldEndFromUpperFold) { g.DrawLine(BrushRegistry.GetPen(isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color), xPos, drawingRectangle.Top, xPos, foldMarkerYPos - 1); } // draw line below fold marker if (isBetween || moreLinedOpenFold) { g.DrawLine(BrushRegistry.GetPen(isEndSelected || (isStartSelected && isVisible) || isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color), xPos, foldMarkerYPos + foldMarkerSize + 1, xPos, drawingRectangle.Bottom); } } else { if (isFoldEnd) { int midy = drawingRectangle.Top + drawingRectangle.Height / 2; // draw fold end marker g.DrawLine(BrushRegistry.GetPen(isEndSelected ? selectedFoldLine.Color : foldLineColor.Color), xPos, midy, xPos + foldMarkerSize / 2, midy); // draw line above fold end marker // must be drawn after fold marker because it might have a different color than the fold marker g.DrawLine(BrushRegistry.GetPen(isBetweenSelected || isEndSelected ? selectedFoldLine.Color : foldLineColor.Color), xPos, drawingRectangle.Top, xPos, midy); // draw line below fold end marker if (isBetween) { g.DrawLine(BrushRegistry.GetPen(isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color), xPos, midy + 1, xPos, drawingRectangle.Bottom); } } else if (isBetween) { // just draw the line :) g.DrawLine(BrushRegistry.GetPen(isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color), xPos, drawingRectangle.Top, xPos, drawingRectangle.Bottom); } } } public override void HandleMouseMove(Point mousepos, MouseButtons mouseButtons) { bool showFolding = textArea.Document.TextEditorProperties.EnableFolding; int physicalLine = + (int)((mousepos.Y + textArea.VirtualTop.Y) / textArea.TextView.FontHeight); int realline = textArea.Document.GetFirstLogicalLine(physicalLine); if (!showFolding || realline < 0 || realline + 1 >= textArea.Document.TotalNumberOfLines) { return; } List foldMarkers = textArea.Document.FoldingManager.GetFoldingsWithStart(realline); int oldSelection = selectedFoldLine; if (foldMarkers.Count > 0) { selectedFoldLine = realline; } else { selectedFoldLine = -1; } if (oldSelection != selectedFoldLine) { textArea.Refresh(this); } } public override void HandleMouseDown(Point mousepos, MouseButtons mouseButtons) { bool showFolding = textArea.Document.TextEditorProperties.EnableFolding; int physicalLine = + (int)((mousepos.Y + textArea.VirtualTop.Y) / textArea.TextView.FontHeight); int realline = textArea.Document.GetFirstLogicalLine(physicalLine); // focus the textarea if the user clicks on the line number view textArea.Focus(); if (!showFolding || realline < 0 || realline + 1 >= textArea.Document.TotalNumberOfLines) { return; } List foldMarkers = textArea.Document.FoldingManager.GetFoldingsWithStart(realline); foreach (FoldMarker fm in foldMarkers) { fm.IsFolded = !fm.IsFolded; } textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty); } public override void HandleMouseLeave(EventArgs e) { if (selectedFoldLine != -1) { selectedFoldLine = -1; textArea.Refresh(this); } } #region Drawing functions void DrawFoldMarker(Graphics g, RectangleF rectangle, bool isOpened, bool isSelected) { HighlightColor foldMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("FoldMarker"); HighlightColor foldLineColor = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine"); HighlightColor selectedFoldLine = textArea.Document.HighlightingStrategy.GetColorFor("SelectedFoldLine"); Rectangle intRect = new Rectangle((int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height); g.FillRectangle(BrushRegistry.GetBrush(foldMarkerColor.BackgroundColor), intRect); g.DrawRectangle(BrushRegistry.GetPen(isSelected ? selectedFoldLine.Color : foldMarkerColor.Color), intRect); int space = (int)Math.Round(((double)rectangle.Height) / 8d) + 1; int mid = intRect.Height / 2 + intRect.Height % 2; g.DrawLine(BrushRegistry.GetPen(foldLineColor.BackgroundColor), rectangle.X + space, rectangle.Y + mid, rectangle.X + rectangle.Width - space, rectangle.Y + mid); if (!isOpened) { g.DrawLine(BrushRegistry.GetPen(foldLineColor.BackgroundColor), rectangle.X + mid, rectangle.Y + space, rectangle.X + mid, rectangle.Y + rectangle.Height - space); } } #endregion } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/GutterMargin.cs ================================================ // // // // // $Revision: 3050 $ // using System; using System.Drawing; using System.IO; using System.Reflection; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class views the line numbers and folding markers. /// public class GutterMargin : AbstractMargin, IDisposable { StringFormat numberStringFormat = (StringFormat)StringFormat.GenericTypographic.Clone(); public static Cursor RightLeftCursor; static GutterMargin() { Stream cursorStream = Assembly.GetCallingAssembly().GetManifestResourceStream("ICSharpCode.TextEditor.Resources.RightArrow.cur"); if (cursorStream == null) throw new Exception("could not find cursor resource"); RightLeftCursor = new Cursor(cursorStream); cursorStream.Close(); } public void Dispose() { numberStringFormat.Dispose(); } public override Cursor Cursor { get { return RightLeftCursor; } } public override Size Size { get { return new Size((int)(textArea.TextView.WideSpaceWidth * Math.Max(3, (int)Math.Log10(textArea.Document.TotalNumberOfLines) + 1)), -1); } } public override bool IsVisible { get { return textArea.TextEditorProperties.ShowLineNumbers; } } public GutterMargin(TextArea textArea) : base(textArea) { numberStringFormat.LineAlignment = StringAlignment.Far; numberStringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.FitBlackBox | StringFormatFlags.NoWrap | StringFormatFlags.NoClip; } public override void Paint(Graphics g, Rectangle rect) { if (rect.Width <= 0 || rect.Height <= 0) { return; } HighlightColor lineNumberPainterColor = textArea.Document.HighlightingStrategy.GetColorFor("LineNumbers"); int fontHeight = textArea.TextView.FontHeight; Brush fillBrush = textArea.Enabled ? BrushRegistry.GetBrush(lineNumberPainterColor.BackgroundColor) : SystemBrushes.InactiveBorder; Brush drawBrush = BrushRegistry.GetBrush(lineNumberPainterColor.Color); for (int y = 0; y < (DrawingPosition.Height + textArea.TextView.VisibleLineDrawingRemainder) / fontHeight + 1; ++y) { int ypos = drawingPosition.Y + fontHeight * y - textArea.TextView.VisibleLineDrawingRemainder; Rectangle backgroundRectangle = new Rectangle(drawingPosition.X, ypos, drawingPosition.Width, fontHeight); if (rect.IntersectsWith(backgroundRectangle)) { g.FillRectangle(fillBrush, backgroundRectangle); int curLine = textArea.Document.GetFirstLogicalLine(textArea.Document.GetVisibleLine(textArea.TextView.FirstVisibleLine) + y); if (curLine < textArea.Document.TotalNumberOfLines) { g.DrawString((curLine + 1).ToString(), lineNumberPainterColor.GetFont(TextEditorProperties.FontContainer), drawBrush, backgroundRectangle, numberStringFormat); } } } } public override void HandleMouseDown(Point mousepos, MouseButtons mouseButtons) { TextLocation selectionStartPos; textArea.SelectionManager.selectFrom.where = WhereFrom.Gutter; int realline = textArea.TextView.GetLogicalLine(mousepos.Y); if (realline >= 0 && realline < textArea.Document.TotalNumberOfLines) { // shift-select if((Control.ModifierKeys & Keys.Shift) != 0) { if(!textArea.SelectionManager.HasSomethingSelected && realline != textArea.Caret.Position.Y) { if (realline >= textArea.Caret.Position.Y) { // at or below starting selection, place the cursor on the next line // nothing is selected so make a new selection from cursor selectionStartPos = textArea.Caret.Position; // whole line selection - start of line to start of next line if (realline < textArea.Document.TotalNumberOfLines - 1) { textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new TextLocation(0, realline + 1))); textArea.Caret.Position = new TextLocation(0, realline + 1); } else { textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new TextLocation(textArea.Document.GetLineSegment(realline).Length + 1, realline))); textArea.Caret.Position = new TextLocation(textArea.Document.GetLineSegment(realline).Length + 1, realline); } } else { // prior lines to starting selection, place the cursor on the same line as the new selection // nothing is selected so make a new selection from cursor selectionStartPos = textArea.Caret.Position; // whole line selection - start of line to start of next line textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new TextLocation(selectionStartPos.X, selectionStartPos.Y))); textArea.SelectionManager.ExtendSelection(new TextLocation(selectionStartPos.X, selectionStartPos.Y), new TextLocation(0, realline)); textArea.Caret.Position = new TextLocation(0, realline); } } else { // let MouseMove handle a shift-click in a gutter MouseEventArgs e = new MouseEventArgs(mouseButtons, 1, mousepos.X, mousepos.Y, 0); textArea.RaiseMouseMove(e); } } else { // this is a new selection with no shift-key // sync the textareamousehandler mouse location // (fixes problem with clicking out into a menu then back to the gutter whilst // there is a selection) textArea.mousepos = mousepos; selectionStartPos = new TextLocation(0, realline); textArea.SelectionManager.ClearSelection(); // whole line selection - start of line to start of next line if (realline < textArea.Document.TotalNumberOfLines - 1) { textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, selectionStartPos, new TextLocation(selectionStartPos.X, selectionStartPos.Y + 1))); textArea.Caret.Position = new TextLocation(selectionStartPos.X, selectionStartPos.Y + 1); } else { textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, new TextLocation(0, realline), new TextLocation(textArea.Document.GetLineSegment(realline).Length + 1, selectionStartPos.Y))); textArea.Caret.Position = new TextLocation(textArea.Document.GetLineSegment(realline).Length + 1, selectionStartPos.Y); } } } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/HRuler.cs ================================================ // // // // // $Revision: 1925 $ // using System; using System.Drawing; using System.Windows.Forms; namespace ICSharpCode.TextEditor { /// /// Horizontal ruler - text column measuring ruler at the top of the text area. /// public class HRuler : Control { TextArea textArea; public HRuler(TextArea textArea) { this.textArea = textArea; } protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { Graphics g = e.Graphics; int num = 0; for (float x = textArea.TextView.DrawingPosition.Left; x < textArea.TextView.DrawingPosition.Right; x += textArea.TextView.WideSpaceWidth) { int offset = (Height * 2) / 3; if (num % 5 == 0) { offset = (Height * 4) / 5; } if (num % 10 == 0) { offset = 1; } ++num; g.DrawLine(Pens.Black, (int)x, offset, (int)x, Height - offset); } } protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e) { e.Graphics.FillRectangle(Brushes.White, new Rectangle(0, 0, Width, Height)); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/IconBarMargin.cs ================================================ // // // // // $Revision: 3176 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class views the line numbers and folding markers. /// public class IconBarMargin : AbstractMargin { const int iconBarWidth = 18; static readonly Size iconBarSize = new Size(iconBarWidth, -1); public override Size Size { get { return iconBarSize; } } public override bool IsVisible { get { return textArea.TextEditorProperties.IsIconBarVisible; } } public IconBarMargin(TextArea textArea) : base(textArea) { } public override void Paint(Graphics g, Rectangle rect) { if (rect.Width <= 0 || rect.Height <= 0) { return; } // paint background g.FillRectangle(SystemBrushes.Control, new Rectangle(drawingPosition.X, rect.Top, drawingPosition.Width - 1, rect.Height)); g.DrawLine(SystemPens.ControlDark, base.drawingPosition.Right - 1, rect.Top, base.drawingPosition.Right - 1, rect.Bottom); // paint icons foreach (Bookmark mark in textArea.Document.BookmarkManager.Marks) { int lineNumber = textArea.Document.GetVisibleLine(mark.LineNumber); int lineHeight = textArea.TextView.FontHeight; int yPos = (int)(lineNumber * lineHeight) - textArea.VirtualTop.Y; if (IsLineInsideRegion(yPos, yPos + lineHeight, rect.Y, rect.Bottom)) { if (lineNumber == textArea.Document.GetVisibleLine(mark.LineNumber - 1)) { // marker is inside folded region, do not draw it continue; } mark.Draw(this, g, new Point(0, yPos)); } } base.Paint(g, rect); } public override void HandleMouseDown(Point mousePos, MouseButtons mouseButtons) { int clickedVisibleLine = (mousePos.Y + textArea.VirtualTop.Y) / textArea.TextView.FontHeight; int lineNumber = textArea.Document.GetFirstLogicalLine(clickedVisibleLine); if ((mouseButtons & MouseButtons.Right) == MouseButtons.Right) { if (textArea.Caret.Line != lineNumber) { textArea.Caret.Line = lineNumber; } } IList marks = textArea.Document.BookmarkManager.Marks; List marksInLine = new List(); int oldCount = marks.Count; foreach (Bookmark mark in marks) { if (mark.LineNumber == lineNumber) { marksInLine.Add(mark); } } for (int i = marksInLine.Count - 1; i >= 0; i--) { Bookmark mark = marksInLine[i]; if (mark.Click(textArea, new MouseEventArgs(mouseButtons, 1, mousePos.X, mousePos.Y, 0))) { if (oldCount != marks.Count) { textArea.UpdateLine(lineNumber); } return; } } base.HandleMouseDown(mousePos, mouseButtons); } #region Drawing functions public void DrawBreakpoint(Graphics g, int y, bool isEnabled, bool isHealthy) { int diameter = Math.Min(iconBarWidth - 2, textArea.TextView.FontHeight); Rectangle rect = new Rectangle(1, y + (textArea.TextView.FontHeight - diameter) / 2, diameter, diameter); using (GraphicsPath path = new GraphicsPath()) { path.AddEllipse(rect); using (PathGradientBrush pthGrBrush = new PathGradientBrush(path)) { pthGrBrush.CenterPoint = new PointF(rect.Left + rect.Width / 3 , rect.Top + rect.Height / 3); pthGrBrush.CenterColor = Color.MistyRose; Color[] colors = {isHealthy ? Color.Firebrick : Color.Olive}; pthGrBrush.SurroundColors = colors; if (isEnabled) { g.FillEllipse(pthGrBrush, rect); } else { g.FillEllipse(SystemBrushes.Control, rect); using (Pen pen = new Pen(pthGrBrush)) { g.DrawEllipse(pen, new Rectangle(rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2)); } } } } } public void DrawBookmark(Graphics g, int y, bool isEnabled) { int delta = textArea.TextView.FontHeight / 8; Rectangle rect = new Rectangle(1, y + delta, base.drawingPosition.Width - 4, textArea.TextView.FontHeight - delta * 2); if (isEnabled) { using (Brush brush = new LinearGradientBrush(new Point(rect.Left, rect.Top), new Point(rect.Right, rect.Bottom), Color.SkyBlue, Color.White)) { FillRoundRect(g, brush, rect); } } else { FillRoundRect(g, Brushes.White, rect); } using (Brush brush = new LinearGradientBrush(new Point(rect.Left, rect.Top), new Point(rect.Right, rect.Bottom), Color.SkyBlue, Color.Blue)) { using (Pen pen = new Pen(brush)) { DrawRoundRect(g, pen, rect); } } } public void DrawArrow(Graphics g, int y) { int delta = textArea.TextView.FontHeight / 8; Rectangle rect = new Rectangle(1, y + delta, base.drawingPosition.Width - 4, textArea.TextView.FontHeight - delta * 2); using (Brush brush = new LinearGradientBrush(new Point(rect.Left, rect.Top), new Point(rect.Right, rect.Bottom), Color.LightYellow, Color.Yellow)) { FillArrow(g, brush, rect); } using (Brush brush = new LinearGradientBrush(new Point(rect.Left, rect.Top), new Point(rect.Right, rect.Bottom), Color.Yellow, Color.Brown)) { using (Pen pen = new Pen(brush)) { DrawArrow(g, pen, rect); } } } GraphicsPath CreateArrowGraphicsPath(Rectangle r) { GraphicsPath gp = new GraphicsPath(); int halfX = r.Width / 2; int halfY = r.Height/ 2; gp.AddLine(r.X, r.Y + halfY/2, r.X + halfX, r.Y + halfY/2); gp.AddLine(r.X + halfX, r.Y + halfY/2, r.X + halfX, r.Y); gp.AddLine(r.X + halfX, r.Y, r.Right, r.Y + halfY); gp.AddLine(r.Right, r.Y + halfY, r.X + halfX, r.Bottom); gp.AddLine(r.X + halfX, r.Bottom, r.X + halfX, r.Bottom - halfY/2); gp.AddLine(r.X + halfX, r.Bottom - halfY/2, r.X, r.Bottom - halfY/2); gp.AddLine(r.X, r.Bottom - halfY/2, r.X, r.Y + halfY/2); gp.CloseFigure(); return gp; } GraphicsPath CreateRoundRectGraphicsPath(Rectangle r) { GraphicsPath gp = new GraphicsPath(); int radius = r.Width / 2; gp.AddLine(r.X + radius, r.Y, r.Right - radius, r.Y); gp.AddArc(r.Right - radius, r.Y, radius, radius, 270, 90); gp.AddLine(r.Right, r.Y + radius, r.Right, r.Bottom - radius); gp.AddArc(r.Right - radius, r.Bottom - radius, radius, radius, 0, 90); gp.AddLine(r.Right - radius, r.Bottom, r.X + radius, r.Bottom); gp.AddArc(r.X, r.Bottom - radius, radius, radius, 90, 90); gp.AddLine(r.X, r.Bottom - radius, r.X, r.Y + radius); gp.AddArc(r.X, r.Y, radius, radius, 180, 90); gp.CloseFigure(); return gp; } void DrawRoundRect(Graphics g, Pen p , Rectangle r) { using (GraphicsPath gp = CreateRoundRectGraphicsPath(r)) { g.DrawPath(p, gp); } } void FillRoundRect(Graphics g, Brush b , Rectangle r) { using (GraphicsPath gp = CreateRoundRectGraphicsPath(r)) { g.FillPath(b, gp); } } void DrawArrow(Graphics g, Pen p , Rectangle r) { using (GraphicsPath gp = CreateArrowGraphicsPath(r)) { g.DrawPath(p, gp); } } void FillArrow(Graphics g, Brush b , Rectangle r) { using (GraphicsPath gp = CreateArrowGraphicsPath(r)) { g.FillPath(b, gp); } } #endregion static bool IsLineInsideRegion(int top, int bottom, int regionTop, int regionBottom) { if (top >= regionTop && top <= regionBottom) { // Region overlaps the line's top edge. return true; } else if(regionTop > top && regionTop < bottom) { // Region's top edge inside line. return true; } return false; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/Ime.cs ================================================ // // // // // $Revision: 3113 $ // using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace ICSharpCode.TextEditor { /// /// Used internally, not for own use. /// internal class Ime { public Ime(IntPtr hWnd, Font font) { string PROCESSOR_ARCHITEW6432 = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"); if (PROCESSOR_ARCHITEW6432 == "IA64" || PROCESSOR_ARCHITEW6432 == "AMD64" || Environment.OSVersion.Platform == PlatformID.Unix) { disableIME = true; } else { this.hIMEWnd = ImmGetDefaultIMEWnd(hWnd); } this.hWnd = hWnd; this.font = font; SetIMEWindowFont(font); } private Font font = null; public Font Font { get { return font; } set { if (!value.Equals(font)) { font = value; lf = null; SetIMEWindowFont(value); } } } public IntPtr HWnd { set { if (this.hWnd != value) { this.hWnd = value; if (!disableIME) this.hIMEWnd = ImmGetDefaultIMEWnd(value); SetIMEWindowFont(font); } } } [ DllImport("imm32.dll") ] private static extern IntPtr ImmGetDefaultIMEWnd(IntPtr hWnd); [ DllImport("user32.dll") ] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, COMPOSITIONFORM lParam); [ DllImport("user32.dll") ] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, [In, MarshalAs(UnmanagedType.LPStruct)] LOGFONT lParam); [ StructLayout(LayoutKind.Sequential) ] private class COMPOSITIONFORM { public int dwStyle = 0; public POINT ptCurrentPos = null; public RECT rcArea = null; } [ StructLayout(LayoutKind.Sequential) ] private class POINT { public int x = 0; public int y = 0; } [ StructLayout(LayoutKind.Sequential) ] private class RECT { public int left = 0; public int top = 0; public int right = 0; public int bottom = 0; } private const int WM_IME_CONTROL = 0x0283; private const int IMC_SETCOMPOSITIONWINDOW = 0x000c; private IntPtr hIMEWnd; private IntPtr hWnd; private const int CFS_POINT = 0x0002; [ StructLayout(LayoutKind.Sequential) ] private class LOGFONT { public int lfHeight = 0; public int lfWidth = 0; public int lfEscapement = 0; public int lfOrientation = 0; public int lfWeight = 0; public byte lfItalic = 0; public byte lfUnderline = 0; public byte lfStrikeOut = 0; public byte lfCharSet = 0; public byte lfOutPrecision = 0; public byte lfClipPrecision = 0; public byte lfQuality = 0; public byte lfPitchAndFamily = 0; [ MarshalAs(UnmanagedType.ByValTStr, SizeConst=32) ] public string lfFaceName = null; } private const int IMC_SETCOMPOSITIONFONT = 0x000a; LOGFONT lf = null; static bool disableIME; private void SetIMEWindowFont(Font f) { if (disableIME || hIMEWnd == IntPtr.Zero) return; if (lf == null) { lf = new LOGFONT(); f.ToLogFont(lf); lf.lfFaceName = f.Name; // This is very important! "Font.ToLogFont" Method sets invalid value to LOGFONT.lfFaceName } try { SendMessage( hIMEWnd, WM_IME_CONTROL, new IntPtr(IMC_SETCOMPOSITIONFONT), lf ); } catch (AccessViolationException ex) { Handle(ex); } } public void SetIMEWindowLocation(int x, int y) { if (disableIME || hIMEWnd == IntPtr.Zero) return; POINT p = new POINT(); p.x = x; p.y = y; COMPOSITIONFORM lParam = new COMPOSITIONFORM(); lParam.dwStyle = CFS_POINT; lParam.ptCurrentPos = p; lParam.rcArea = new RECT(); try { SendMessage( hIMEWnd, WM_IME_CONTROL, new IntPtr(IMC_SETCOMPOSITIONWINDOW), lParam ); } catch (AccessViolationException ex) { Handle(ex); } } void Handle(Exception ex) { Console.WriteLine(ex); if (!disableIME) { disableIME = true; MessageBox.Show("Error calling IME: " + ex.Message + "\nIME is disabled.", "IME error"); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/InsightWindow/IInsightDataProvider.cs ================================================ // // // // // $Revision: 2318 $ // using System; namespace ICSharpCode.TextEditor.Gui.InsightWindow { public interface IInsightDataProvider { /// /// Tells the insight provider to prepare its data. /// /// The name of the edited file /// The text area in which the file is being edited void SetupDataProvider(string fileName, TextArea textArea); /// /// Notifies the insight provider that the caret offset has changed. /// /// Return true to close the insight window (e.g. when the /// caret was moved outside the region where insight is displayed for). /// Return false to keep the window open. bool CaretOffsetChanged(); /// /// Gets the text to display in the insight window. /// /// The number of the active insight entry. /// Multiple insight entries might be multiple overloads of the same method. /// The text to display, e.g. a multi-line string where /// the first line is the method definition, followed by a description. string GetInsightData(int number); /// /// Gets the number of available insight entries, e.g. the number of available /// overloads to call. /// int InsightDataCount { get; } /// /// Gets the index of the entry to initially select. /// int DefaultIndex { get; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/InsightWindow/InsightWindow.cs ================================================ // // // // // $Revision: 3064 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using ICSharpCode.TextEditor.Gui.CompletionWindow; using ICSharpCode.TextEditor.Util; namespace ICSharpCode.TextEditor.Gui.InsightWindow { public class InsightWindow : AbstractCompletionWindow { public InsightWindow(Form parentForm, TextEditorControl control) : base(parentForm, control) { SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true); } public void ShowInsightWindow() { if (!Visible) { if (insightDataProviderStack.Count > 0) { ShowCompletionWindow(); } } else { Refresh(); } } #region Event handling routines protected override bool ProcessTextAreaKey(Keys keyData) { if (!Visible) { return false; } switch (keyData) { case Keys.Down: if (DataProvider != null && DataProvider.InsightDataCount > 0) { CurrentData = (CurrentData + 1) % DataProvider.InsightDataCount; Refresh(); } return true; case Keys.Up: if (DataProvider != null && DataProvider.InsightDataCount > 0) { CurrentData = (CurrentData + DataProvider.InsightDataCount - 1) % DataProvider.InsightDataCount; Refresh(); } return true; } return base.ProcessTextAreaKey(keyData); } protected override void CaretOffsetChanged(object sender, EventArgs e) { // move the window under the caret (don't change the x position) TextLocation caretPos = control.ActiveTextAreaControl.Caret.Position; int y = (int)((1 + caretPos.Y) * control.ActiveTextAreaControl.TextArea.TextView.FontHeight) - control.ActiveTextAreaControl.TextArea.VirtualTop.Y - 1 + control.ActiveTextAreaControl.TextArea.TextView.DrawingPosition.Y; int xpos = control.ActiveTextAreaControl.TextArea.TextView.GetDrawingXPos(caretPos.Y, caretPos.X); int ypos = (control.ActiveTextAreaControl.Document.GetVisibleLine(caretPos.Y) + 1) * control.ActiveTextAreaControl.TextArea.TextView.FontHeight - control.ActiveTextAreaControl.TextArea.VirtualTop.Y; int rulerHeight = control.TextEditorProperties.ShowHorizontalRuler ? control.ActiveTextAreaControl.TextArea.TextView.FontHeight : 0; Point p = control.ActiveTextAreaControl.PointToScreen(new Point(xpos, ypos + rulerHeight)); if (p.Y != Location.Y) { Location = p; } while (DataProvider != null && DataProvider.CaretOffsetChanged()) { CloseCurrentDataProvider(); } } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); control.ActiveTextAreaControl.TextArea.Focus(); if (TipPainterTools.DrawingRectangle1.Contains(e.X, e.Y)) { CurrentData = (CurrentData + DataProvider.InsightDataCount - 1) % DataProvider.InsightDataCount; Refresh(); } if (TipPainterTools.DrawingRectangle2.Contains(e.X, e.Y)) { CurrentData = (CurrentData + 1) % DataProvider.InsightDataCount; Refresh(); } } #endregion MouseWheelHandler mouseWheelHandler = new MouseWheelHandler(); public void HandleMouseWheel(MouseEventArgs e) { if (DataProvider != null && DataProvider.InsightDataCount > 0) { int distance = mouseWheelHandler.GetScrollAmount(e); if (control.TextEditorProperties.MouseWheelScrollDown) distance = -distance; if (distance > 0) { CurrentData = (CurrentData + 1) % DataProvider.InsightDataCount; } else if (distance < 0) { CurrentData = (CurrentData + DataProvider.InsightDataCount - 1) % DataProvider.InsightDataCount; } Refresh(); } } #region Insight Window Drawing routines protected override void OnPaint(PaintEventArgs pe) { string methodCountMessage = null, description; if (DataProvider == null || DataProvider.InsightDataCount < 1) { description = "Unknown Method"; } else { if (DataProvider.InsightDataCount > 1) { methodCountMessage = control.GetRangeDescription(CurrentData + 1, DataProvider.InsightDataCount); } description = DataProvider.GetInsightData(CurrentData); } drawingSize = TipPainterTools.GetDrawingSizeHelpTipFromCombinedDescription(this, pe.Graphics, Font, methodCountMessage, description); if (drawingSize != Size) { SetLocation(); } else { TipPainterTools.DrawHelpTipFromCombinedDescription(this, pe.Graphics, Font, methodCountMessage, description); } } protected override void OnPaintBackground(PaintEventArgs pe) { pe.Graphics.FillRectangle(SystemBrushes.Info, pe.ClipRectangle); } #endregion #region InsightDataProvider handling Stack insightDataProviderStack = new Stack(); int CurrentData { get { return insightDataProviderStack.Peek().currentData; } set { insightDataProviderStack.Peek().currentData = value; } } IInsightDataProvider DataProvider { get { if (insightDataProviderStack.Count == 0) { return null; } return insightDataProviderStack.Peek().dataProvider; } } public void AddInsightDataProvider(IInsightDataProvider provider, string fileName) { provider.SetupDataProvider(fileName, control.ActiveTextAreaControl.TextArea); if (provider.InsightDataCount > 0) { insightDataProviderStack.Push(new InsightDataProviderStackElement(provider)); } } void CloseCurrentDataProvider() { insightDataProviderStack.Pop(); if (insightDataProviderStack.Count == 0) { Close(); } else { Refresh(); } } class InsightDataProviderStackElement { public int currentData; public IInsightDataProvider dataProvider; public InsightDataProviderStackElement(IInsightDataProvider dataProvider) { this.currentData = Math.Max(dataProvider.DefaultIndex, 0); this.dataProvider = dataProvider; } } #endregion } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextArea.cs ================================================ // // // // // $Revision: 3323 $ // using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Text; using System.Text; using System.Windows.Forms; using ICSharpCode.TextEditor.Actions; using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Gui.CompletionWindow; namespace ICSharpCode.TextEditor { public delegate bool KeyEventHandler(char ch); public delegate bool DialogKeyProcessor(Keys keyData); /// /// This class paints the textarea. /// [ToolboxItem(false)] public class TextArea : Control { bool hiddenMouseCursor = false; /// /// The position where the mouse cursor was when it was hidden. Sometimes the text editor gets MouseMove /// events when typing text even if the mouse is not moved. /// Point mouseCursorHidePosition; Point virtualTop = new Point(0, 0); TextAreaControl motherTextAreaControl; TextEditorControl motherTextEditorControl; List bracketshemes = new List(); TextAreaClipboardHandler textAreaClipboardHandler; bool autoClearSelection = false; List leftMargins = new List(); TextView textView; GutterMargin gutterMargin; FoldMargin foldMargin; IconBarMargin iconBarMargin; SelectionManager selectionManager; Caret caret; internal Point mousepos = new Point(0, 0); //public Point selectionStartPos = new Point(0,0); bool disposed; [Browsable(false)] public IList LeftMargins { get { return leftMargins.AsReadOnly(); } } public void InsertLeftMargin(int index, AbstractMargin margin) { leftMargins.Insert(index, margin); Refresh(); } public TextEditorControl MotherTextEditorControl { get { return motherTextEditorControl; } } public TextAreaControl MotherTextAreaControl { get { return motherTextAreaControl; } } public SelectionManager SelectionManager { get { return selectionManager; } } public Caret Caret { get { return caret; } } public TextView TextView { get { return textView; } } public GutterMargin GutterMargin { get { return gutterMargin; } } public FoldMargin FoldMargin { get { return foldMargin; } } public IconBarMargin IconBarMargin { get { return iconBarMargin; } } public Encoding Encoding { get { return motherTextEditorControl.Encoding; } } public int MaxVScrollValue { get { return (Document.GetVisibleLine(Document.TotalNumberOfLines - 1) + 1 + TextView.VisibleLineCount * 2 / 3) * TextView.FontHeight; } } public Point VirtualTop { get { return virtualTop; } set { Point newVirtualTop = new Point(value.X, Math.Min(MaxVScrollValue, Math.Max(0, value.Y))); if (virtualTop != newVirtualTop) { virtualTop = newVirtualTop; motherTextAreaControl.VScrollBar.Value = virtualTop.Y; Invalidate(); } caret.UpdateCaretPosition(); } } public bool AutoClearSelection { get { return autoClearSelection; } set { autoClearSelection = value; } } [Browsable(false)] public IDocument Document { get { return motherTextEditorControl.Document; } } public TextAreaClipboardHandler ClipboardHandler { get { return textAreaClipboardHandler; } } public ITextEditorProperties TextEditorProperties { get { return motherTextEditorControl.TextEditorProperties; } } public TextArea(TextEditorControl motherTextEditorControl, TextAreaControl motherTextAreaControl) { this.motherTextAreaControl = motherTextAreaControl; this.motherTextEditorControl = motherTextEditorControl; caret = new Caret(this); selectionManager = new SelectionManager(Document, this); this.textAreaClipboardHandler = new TextAreaClipboardHandler(this); ResizeRedraw = true; SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // SetStyle(ControlStyles.AllPaintingInWmPaint, true); // SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.Opaque, false); SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.Selectable, true); textView = new TextView(this); gutterMargin = new GutterMargin(this); foldMargin = new FoldMargin(this); iconBarMargin = new IconBarMargin(this); leftMargins.AddRange(new AbstractMargin[] { iconBarMargin, gutterMargin, foldMargin }); OptionsChanged(); new TextAreaMouseHandler(this).Attach(); new TextAreaDragDropHandler().Attach(this); bracketshemes.Add(new BracketHighlightingSheme('{', '}')); bracketshemes.Add(new BracketHighlightingSheme('(', ')')); bracketshemes.Add(new BracketHighlightingSheme('[', ']')); caret.PositionChanged += new EventHandler(SearchMatchingBracket); Document.TextContentChanged += new EventHandler(TextContentChanged); Document.FoldingManager.FoldingsChanged += new EventHandler(DocumentFoldingsChanged); } public void UpdateMatchingBracket() { SearchMatchingBracket(null, null); } void TextContentChanged(object sender, EventArgs e) { Caret.Position = new TextLocation(0, 0); SelectionManager.SelectionCollection.Clear(); } void SearchMatchingBracket(object sender, EventArgs e) { if (!TextEditorProperties.ShowMatchingBracket) { textView.Highlight = null; return; } int oldLine1 = -1, oldLine2 = -1; if (textView.Highlight != null && textView.Highlight.OpenBrace.Y >=0 && textView.Highlight.OpenBrace.Y < Document.TotalNumberOfLines) { oldLine1 = textView.Highlight.OpenBrace.Y; } if (textView.Highlight != null && textView.Highlight.CloseBrace.Y >=0 && textView.Highlight.CloseBrace.Y < Document.TotalNumberOfLines) { oldLine2 = textView.Highlight.CloseBrace.Y; } textView.Highlight = FindMatchingBracketHighlight(); if (oldLine1 >= 0) UpdateLine(oldLine1); if (oldLine2 >= 0 && oldLine2 != oldLine1) UpdateLine(oldLine2); if (textView.Highlight != null) { int newLine1 = textView.Highlight.OpenBrace.Y; int newLine2 = textView.Highlight.CloseBrace.Y; if (newLine1 != oldLine1 && newLine1 != oldLine2) UpdateLine(newLine1); if (newLine2 != oldLine1 && newLine2 != oldLine2 && newLine2 != newLine1) UpdateLine(newLine2); } } public BracketHighlight FindMatchingBracketHighlight() { if (Caret.Offset == 0) return null; foreach (BracketHighlightingSheme bracketsheme in bracketshemes) { BracketHighlight highlight = bracketsheme.GetHighlight(Document, Caret.Offset - 1); if (highlight != null) { return highlight; } } return null; } public void SetDesiredColumn() { Caret.DesiredColumn = TextView.GetDrawingXPos(Caret.Line, Caret.Column) + VirtualTop.X; } public void SetCaretToDesiredColumn() { FoldMarker dummy; Caret.Position = textView.GetLogicalColumn(Caret.Line, Caret.DesiredColumn + VirtualTop.X, out dummy); } public void OptionsChanged() { UpdateMatchingBracket(); textView.OptionsChanged(); caret.RecreateCaret(); caret.UpdateCaretPosition(); Refresh(); } AbstractMargin lastMouseInMargin; protected override void OnMouseLeave(System.EventArgs e) { base.OnMouseLeave(e); this.Cursor = Cursors.Default; if (lastMouseInMargin != null) { lastMouseInMargin.HandleMouseLeave(EventArgs.Empty); lastMouseInMargin = null; } CloseToolTip(); } protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) { // this corrects weird problems when text is selected, // then a menu item is selected, then the text is // clicked again - it correctly synchronises the // click position mousepos = new Point(e.X, e.Y); base.OnMouseDown(e); CloseToolTip(); foreach (AbstractMargin margin in leftMargins) { if (margin.DrawingPosition.Contains(e.X, e.Y)) { margin.HandleMouseDown(new Point(e.X, e.Y), e.Button); } } } /// /// Shows the mouse cursor if it has been hidden. /// /// true to always show the cursor or false to show it only if it has been moved since it was hidden. internal void ShowHiddenCursor(bool forceShow) { if (hiddenMouseCursor) { if (mouseCursorHidePosition != Cursor.Position || forceShow) { Cursor.Show(); hiddenMouseCursor = false; } } } // static because the mouse can only be in one text area and we don't want to have // tooltips of text areas from inactive tabs floating around. static DeclarationViewWindow toolTip; static string oldToolTip; void SetToolTip(string text, int lineNumber) { if (toolTip == null || toolTip.IsDisposed) toolTip = new DeclarationViewWindow(this.FindForm()); if (oldToolTip == text) return; if (text == null) { toolTip.Hide(); } else { Point p = Control.MousePosition; Point cp = PointToClient(p); if (lineNumber >= 0) { lineNumber = this.Document.GetVisibleLine(lineNumber); p.Y = (p.Y - cp.Y) + (lineNumber * this.TextView.FontHeight) - this.virtualTop.Y; } p.Offset(3, 3); toolTip.Location = p; toolTip.Description = text; toolTip.HideOnClick = true; toolTip.Show(); } oldToolTip = text; } public event ToolTipRequestEventHandler ToolTipRequest; protected virtual void OnToolTipRequest(ToolTipRequestEventArgs e) { if (ToolTipRequest != null) { ToolTipRequest(this, e); } } bool toolTipActive; /// /// Rectangle in text area that caused the current tool tip. /// Prevents tooltip from re-showing when it was closed because of a click or keyboard /// input and the mouse was not used. /// Rectangle toolTipRectangle; void CloseToolTip() { if (toolTipActive) { //Console.WriteLine("Closing tooltip"); toolTipActive = false; SetToolTip(null, -1); } ResetMouseEventArgs(); } protected override void OnMouseHover(EventArgs e) { base.OnMouseHover(e); //Console.WriteLine("Hover raised at " + PointToClient(Control.MousePosition)); if (MouseButtons == MouseButtons.None) { RequestToolTip(PointToClient(Control.MousePosition)); } else { CloseToolTip(); } } protected void RequestToolTip(Point mousePos) { if (toolTipRectangle.Contains(mousePos)) { if (!toolTipActive) ResetMouseEventArgs(); return; } //Console.WriteLine("Request tooltip for " + mousePos); toolTipRectangle = new Rectangle(mousePos.X - 4, mousePos.Y - 4, 8, 8); TextLocation logicPos = textView.GetLogicalPosition(mousePos.X - textView.DrawingPosition.Left, mousePos.Y - textView.DrawingPosition.Top); bool inDocument = textView.DrawingPosition.Contains(mousePos) && logicPos.Y >= 0 && logicPos.Y < Document.TotalNumberOfLines; ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(mousePos, logicPos, inDocument); OnToolTipRequest(args); if (args.ToolTipShown) { //Console.WriteLine("Set tooltip to " + args.toolTipText); toolTipActive = true; SetToolTip(args.toolTipText, inDocument ? logicPos.Y + 1 : -1); } else { CloseToolTip(); } } // external interface to the attached event internal void RaiseMouseMove(MouseEventArgs e) { OnMouseMove(e); } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (!toolTipRectangle.Contains(e.Location)) { toolTipRectangle = Rectangle.Empty; if (toolTipActive) RequestToolTip(e.Location); } foreach (AbstractMargin margin in leftMargins) { if (margin.DrawingPosition.Contains(e.X, e.Y)) { this.Cursor = margin.Cursor; margin.HandleMouseMove(new Point(e.X, e.Y), e.Button); if (lastMouseInMargin != margin) { if (lastMouseInMargin != null) { lastMouseInMargin.HandleMouseLeave(EventArgs.Empty); } lastMouseInMargin = margin; } return; } } if (lastMouseInMargin != null) { lastMouseInMargin.HandleMouseLeave(EventArgs.Empty); lastMouseInMargin = null; } if (textView.DrawingPosition.Contains(e.X, e.Y)) { TextLocation realmousepos = TextView.GetLogicalPosition(e.X - TextView.DrawingPosition.X, e.Y - TextView.DrawingPosition.Y); if(SelectionManager.IsSelected(Document.PositionToOffset(realmousepos)) && MouseButtons == MouseButtons.None) { // mouse is hovering over a selection, so show default mouse this.Cursor = Cursors.Default; } else { // mouse is hovering over text area, not a selection, so show the textView cursor this.Cursor = textView.Cursor; } return; } this.Cursor = Cursors.Default; } AbstractMargin updateMargin = null; public void Refresh(AbstractMargin margin) { updateMargin = margin; Invalidate(updateMargin.DrawingPosition); Update(); updateMargin = null; } protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs pevent) { } protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { int currentXPos = 0; int currentYPos = 0; bool adjustScrollBars = false; Graphics g = e.Graphics; Rectangle clipRectangle = e.ClipRectangle; bool isFullRepaint = clipRectangle.X == 0 && clipRectangle.Y == 0 && clipRectangle.Width == this.Width && clipRectangle.Height == this.Height; g.TextRenderingHint = this.TextEditorProperties.TextRenderingHint; if (updateMargin != null) { updateMargin.Paint(g, updateMargin.DrawingPosition); // clipRectangle.Intersect(updateMargin.DrawingPosition); } if (clipRectangle.Width <= 0 || clipRectangle.Height <= 0) { return; } foreach (AbstractMargin margin in leftMargins) { if (margin.IsVisible) { Rectangle marginRectangle = new Rectangle(currentXPos , currentYPos, margin.Size.Width, Height - currentYPos); if (marginRectangle != margin.DrawingPosition) { // margin changed size if (!isFullRepaint && !clipRectangle.Contains(marginRectangle)) { Invalidate(); // do a full repaint } adjustScrollBars = true; margin.DrawingPosition = marginRectangle; } currentXPos += margin.DrawingPosition.Width; if (clipRectangle.IntersectsWith(marginRectangle)) { marginRectangle.Intersect(clipRectangle); if (!marginRectangle.IsEmpty) { margin.Paint(g, marginRectangle); } } } } Rectangle textViewArea = new Rectangle(currentXPos, currentYPos, Width - currentXPos, Height - currentYPos); if (textViewArea != textView.DrawingPosition) { adjustScrollBars = true; textView.DrawingPosition = textViewArea; // update caret position (but outside of WM_PAINT!) BeginInvoke((MethodInvoker)caret.UpdateCaretPosition); } if (clipRectangle.IntersectsWith(textViewArea)) { textViewArea.Intersect(clipRectangle); if (!textViewArea.IsEmpty) { textView.Paint(g, textViewArea); } } if (adjustScrollBars) { this.motherTextAreaControl.AdjustScrollBars(); } // we cannot update the caret position here, it's not allowed to call the caret API inside WM_PAINT //Caret.UpdateCaretPosition(); base.OnPaint(e); } void DocumentFoldingsChanged(object sender, EventArgs e) { Caret.UpdateCaretPosition(); Invalidate(); this.motherTextAreaControl.AdjustScrollBars(); } #region keyboard handling methods /// /// This method is called on each Keypress /// /// /// True, if the key is handled by this method and should NOT be /// inserted in the textarea. /// protected internal virtual bool HandleKeyPress(char ch) { if (KeyEventHandler != null) { return KeyEventHandler(ch); } return false; } // Fixes SD2-747: Form containing the text editor and a button with a shortcut protected override bool IsInputChar(char charCode) { return true; } internal bool IsReadOnly(int offset) { if (Document.ReadOnly) { return true; } if (TextEditorProperties.SupportReadOnlySegments) { return Document.MarkerStrategy.GetMarkers(offset).Exists(m=>m.IsReadOnly); } else { return false; } } internal bool IsReadOnly(int offset, int length) { if (Document.ReadOnly) { return true; } if (TextEditorProperties.SupportReadOnlySegments) { return Document.MarkerStrategy.GetMarkers(offset, length).Exists(m=>m.IsReadOnly); } else { return false; } } public void SimulateKeyPress(char ch) { if (SelectionManager.HasSomethingSelected) { if (SelectionManager.SelectionIsReadonly) return; } else if (IsReadOnly(Caret.Offset)) { return; } ////////////////////////////////////////////////////////////////////////// // JDB 4/19/2015 -- Fix for Pyramid // You guys do not break lines when the shift key is down, // which is unfortunate, because I use BSD style brace placement // and I am CONSTANTLY hitting enter while the shift key is down after // closing an if block or for loop. Looking at your code, I can see why // this was never a problem for you, but it's driving me bloody crazy // // It seems that 'ProcessDialogKey' never gets hit on a shift-enter // but this path does, and so I'm gonna fake it... // if ( ch == '\r' ){ ProcessDialogKey(Keys.Enter); return; } /////////////////////////////////////////////////////////////// if (ch < ' ') { return; } if (!hiddenMouseCursor && TextEditorProperties.HideMouseCursor) { if (this.ClientRectangle.Contains(PointToClient(Cursor.Position))) { mouseCursorHidePosition = Cursor.Position; hiddenMouseCursor = true; Cursor.Hide(); } } CloseToolTip(); BeginUpdate(); Document.UndoStack.StartUndoGroup(); try { // INSERT char if (!HandleKeyPress(ch)) { switch (Caret.CaretMode) { case CaretMode.InsertMode: InsertChar(ch); break; case CaretMode.OverwriteMode: ReplaceChar(ch); break; default: Debug.Assert(false, "Unknown caret mode " + Caret.CaretMode); break; } } int currentLineNr = Caret.Line; Document.FormattingStrategy.FormatLine(this, currentLineNr, Document.PositionToOffset(Caret.Position), ch); EndUpdate(); } finally { Document.UndoStack.EndUndoGroup(); } } protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress(e); SimulateKeyPress(e.KeyChar); e.Handled = true; } /// /// This method executes a dialog key /// public bool ExecuteDialogKey(Keys keyData) { // try, if a dialog key processor was set to use this if (DoProcessDialogKey != null && DoProcessDialogKey(keyData)) { return true; } // if not (or the process was 'silent', use the standard edit actions IEditAction action = motherTextEditorControl.GetEditAction(keyData); AutoClearSelection = true; if (action != null) { BeginUpdate(); try { lock (Document) { action.Execute(this); if (SelectionManager.HasSomethingSelected && AutoClearSelection /*&& caretchanged*/) { if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal) { SelectionManager.ClearSelection(); } } } } finally { EndUpdate(); Caret.UpdateCaretPosition(); } return true; } return false; } protected override bool ProcessDialogKey(Keys keyData) { return ExecuteDialogKey(keyData) || base.ProcessDialogKey(keyData); } #endregion public void ScrollToCaret() { motherTextAreaControl.ScrollToCaret(); } public void ScrollTo(int line) { motherTextAreaControl.ScrollTo(line); } public void BeginUpdate() { motherTextEditorControl.BeginUpdate(); } public void EndUpdate() { motherTextEditorControl.EndUpdate(); } public bool EnableCutOrPaste { get { if (motherTextAreaControl == null) return false; if (SelectionManager.HasSomethingSelected) return !SelectionManager.SelectionIsReadonly; else return !IsReadOnly(Caret.Offset); } } string GenerateWhitespaceString(int length) { return new String(' ', length); } /// /// Inserts a single character at the caret position /// public void InsertChar(char ch) { bool updating = motherTextEditorControl.IsInUpdate; if (!updating) { BeginUpdate(); } // filter out forgein whitespace chars and replace them with standard space (ASCII 32) if (Char.IsWhiteSpace(ch) && ch != '\t' && ch != '\n') { ch = ' '; } Document.UndoStack.StartUndoGroup(); if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0) { Caret.Position = SelectionManager.SelectionCollection[0].StartPosition; SelectionManager.RemoveSelectedText(); } LineSegment caretLine = Document.GetLineSegment(Caret.Line); int offset = Caret.Offset; // use desired column for generated whitespaces int dc = Caret.Column; if (caretLine.Length < dc && ch != '\n') { Document.Insert(offset, GenerateWhitespaceString(dc - caretLine.Length) + ch); } else { Document.Insert(offset, ch.ToString()); } Document.UndoStack.EndUndoGroup(); ++Caret.Column; if (!updating) { EndUpdate(); UpdateLineToEnd(Caret.Line, Caret.Column); } // I prefer to set NOT the standard column, if you type something // ++Caret.DesiredColumn; } /// /// Inserts a whole string at the caret position /// public void InsertString(string str) { bool updating = motherTextEditorControl.IsInUpdate; if (!updating) { BeginUpdate(); } try { Document.UndoStack.StartUndoGroup(); if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0) { Caret.Position = SelectionManager.SelectionCollection[0].StartPosition; SelectionManager.RemoveSelectedText(); } int oldOffset = Document.PositionToOffset(Caret.Position); int oldLine = Caret.Line; LineSegment caretLine = Document.GetLineSegment(Caret.Line); if (caretLine.Length < Caret.Column) { int whiteSpaceLength = Caret.Column - caretLine.Length; Document.Insert(oldOffset, GenerateWhitespaceString(whiteSpaceLength) + str); Caret.Position = Document.OffsetToPosition(oldOffset + str.Length + whiteSpaceLength); } else { Document.Insert(oldOffset, str); Caret.Position = Document.OffsetToPosition(oldOffset + str.Length); } Document.UndoStack.EndUndoGroup(); if (oldLine != Caret.Line) { UpdateToEnd(oldLine); } else { UpdateLineToEnd(Caret.Line, Caret.Column); } } finally { if (!updating) { EndUpdate(); } } } /// /// Replaces a char at the caret position /// public void ReplaceChar(char ch) { bool updating = motherTextEditorControl.IsInUpdate; if (!updating) { BeginUpdate(); } if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0) { Caret.Position = SelectionManager.SelectionCollection[0].StartPosition; SelectionManager.RemoveSelectedText(); } int lineNr = Caret.Line; LineSegment line = Document.GetLineSegment(lineNr); int offset = Document.PositionToOffset(Caret.Position); if (offset < line.Offset + line.Length) { Document.Replace(offset, 1, ch.ToString()); } else { Document.Insert(offset, ch.ToString()); } if (!updating) { EndUpdate(); UpdateLineToEnd(lineNr, Caret.Column); } ++Caret.Column; // ++Caret.DesiredColumn; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { if (!disposed) { disposed = true; if (caret != null) { caret.PositionChanged -= new EventHandler(SearchMatchingBracket); caret.Dispose(); } if (selectionManager != null) { selectionManager.Dispose(); } Document.TextContentChanged -= new EventHandler(TextContentChanged); Document.FoldingManager.FoldingsChanged -= new EventHandler(DocumentFoldingsChanged); motherTextAreaControl = null; motherTextEditorControl = null; foreach (AbstractMargin margin in leftMargins) { if (margin is IDisposable) (margin as IDisposable).Dispose(); } textView.Dispose(); } } } #region UPDATE Commands internal void UpdateLine(int line) { UpdateLines(0, line, line); } internal void UpdateLines(int lineBegin, int lineEnd) { UpdateLines(0, lineBegin, lineEnd); } internal void UpdateToEnd(int lineBegin) { // if (lineBegin > FirstPhysicalLine + textView.VisibleLineCount) { // return; // } lineBegin = Document.GetVisibleLine(lineBegin); int y = Math.Max( 0, (int)(lineBegin * textView.FontHeight)); y = Math.Max(0, y - this.virtualTop.Y); Rectangle r = new Rectangle(0, y, Width, Height - y); Invalidate(r); } internal void UpdateLineToEnd(int lineNr, int xStart) { UpdateLines(xStart, lineNr, lineNr); } internal void UpdateLine(int line, int begin, int end) { UpdateLines(line, line); } int FirstPhysicalLine { get { return VirtualTop.Y / textView.FontHeight; } } internal void UpdateLines(int xPos, int lineBegin, int lineEnd) { // if (lineEnd < FirstPhysicalLine || lineBegin > FirstPhysicalLine + textView.VisibleLineCount) { // return; // } InvalidateLines((int)(xPos * this.TextView.WideSpaceWidth), lineBegin, lineEnd); } void InvalidateLines(int xPos, int lineBegin, int lineEnd) { lineBegin = Math.Max(Document.GetVisibleLine(lineBegin), FirstPhysicalLine); lineEnd = Math.Min(Document.GetVisibleLine(lineEnd), FirstPhysicalLine + textView.VisibleLineCount); int y = Math.Max( 0, (int)(lineBegin * textView.FontHeight)); int height = Math.Min(textView.DrawingPosition.Height, (int)((1 + lineEnd - lineBegin) * (textView.FontHeight + 1))); Rectangle r = new Rectangle(0, y - 1 - this.virtualTop.Y, Width, height + 3); Invalidate(r); } #endregion public event KeyEventHandler KeyEventHandler; public event DialogKeyProcessor DoProcessDialogKey; //internal void } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaClipboardHandler.cs ================================================ // // // // // $Revision: 3359 $ // using System; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Util; namespace ICSharpCode.TextEditor { public class TextAreaClipboardHandler { TextArea textArea; public bool EnableCut { get { return textArea.EnableCutOrPaste; //textArea.SelectionManager.HasSomethingSelected; } } public bool EnableCopy { get { return true; //textArea.SelectionManager.HasSomethingSelected; } } public bool EnablePaste { get { if (!textArea.EnableCutOrPaste) return false; try { return Clipboard.ContainsText(); } catch (ExternalException) { return false; } } } public bool EnableDelete { get { return textArea.SelectionManager.HasSomethingSelected && !textArea.SelectionManager.SelectionIsReadonly; } } public bool EnableSelectAll { get { return true; } } public TextAreaClipboardHandler(TextArea textArea) { this.textArea = textArea; textArea.SelectionManager.SelectionChanged += new EventHandler(DocumentSelectionChanged); } void DocumentSelectionChanged(object sender, EventArgs e) { // ((DefaultWorkbench)WorkbenchSingleton.Workbench).UpdateToolbars(); } const string LineSelectedType = "MSDEVLineSelect"; // This is the type VS 2003 and 2005 use for flagging a whole line copy bool CopyTextToClipboard(string stringToCopy, bool asLine) { if (stringToCopy.Length > 0) { DataObject dataObject = new DataObject(); dataObject.SetData(DataFormats.UnicodeText, true, stringToCopy); if (asLine) { MemoryStream lineSelected = new MemoryStream(1); lineSelected.WriteByte(1); dataObject.SetData(LineSelectedType, false, lineSelected); } // Default has no highlighting, therefore we don't need RTF output if (textArea.Document.HighlightingStrategy.Name != "Default") { dataObject.SetData(DataFormats.Rtf, RtfWriter.GenerateRtf(textArea)); } OnCopyText(new CopyTextEventArgs(stringToCopy)); SafeSetClipboard(dataObject); return true; } else { return false; } } // Code duplication: TextAreaClipboardHandler.cs also has SafeSetClipboard [ThreadStatic] static int SafeSetClipboardDataVersion; static void SafeSetClipboard(object dataObject) { // Work around ExternalException bug. (SD2-426) // Best reproducable inside Virtual PC. int version = unchecked(++SafeSetClipboardDataVersion); try { Clipboard.SetDataObject(dataObject, true); } catch (ExternalException) { Timer timer = new Timer(); timer.Interval = 100; timer.Tick += delegate { timer.Stop(); timer.Dispose(); if (SafeSetClipboardDataVersion == version) { try { Clipboard.SetDataObject(dataObject, true, 10, 50); } catch (ExternalException) { } } }; timer.Start(); } } bool CopyTextToClipboard(string stringToCopy) { return CopyTextToClipboard(stringToCopy, false); } public void Cut(object sender, EventArgs e) { if (textArea.SelectionManager.HasSomethingSelected) { if (CopyTextToClipboard(textArea.SelectionManager.SelectedText)) { if (textArea.SelectionManager.SelectionIsReadonly) return; // Remove text textArea.BeginUpdate(); textArea.Caret.Position = textArea.SelectionManager.SelectionCollection[0].StartPosition; textArea.SelectionManager.RemoveSelectedText(); textArea.EndUpdate(); } } else if (textArea.Document.TextEditorProperties.CutCopyWholeLine) { // No text was selected, select and cut the entire line int curLineNr = textArea.Document.GetLineNumberForOffset(textArea.Caret.Offset); LineSegment lineWhereCaretIs = textArea.Document.GetLineSegment(curLineNr); string caretLineText = textArea.Document.GetText(lineWhereCaretIs.Offset, lineWhereCaretIs.TotalLength); textArea.SelectionManager.SetSelection(textArea.Document.OffsetToPosition(lineWhereCaretIs.Offset), textArea.Document.OffsetToPosition(lineWhereCaretIs.Offset + lineWhereCaretIs.TotalLength)); if (CopyTextToClipboard(caretLineText, true)) { if (textArea.SelectionManager.SelectionIsReadonly) return; // remove line textArea.BeginUpdate(); textArea.Caret.Position = textArea.Document.OffsetToPosition(lineWhereCaretIs.Offset); textArea.SelectionManager.RemoveSelectedText(); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.PositionToEnd, new TextLocation(0, curLineNr))); textArea.EndUpdate(); } } } public void Copy(object sender, EventArgs e) { if (!CopyTextToClipboard(textArea.SelectionManager.SelectedText) && textArea.Document.TextEditorProperties.CutCopyWholeLine) { // No text was selected, select the entire line, copy it, and then deselect int curLineNr = textArea.Document.GetLineNumberForOffset(textArea.Caret.Offset); LineSegment lineWhereCaretIs = textArea.Document.GetLineSegment(curLineNr); string caretLineText = textArea.Document.GetText(lineWhereCaretIs.Offset, lineWhereCaretIs.TotalLength); CopyTextToClipboard(caretLineText, true); } } public void Paste(object sender, EventArgs e) { if (!textArea.EnableCutOrPaste) { return; } // Clipboard.GetDataObject may throw an exception... for (int i = 0;; i++) { try { IDataObject data = Clipboard.GetDataObject(); if (data == null) return; bool fullLine = data.GetDataPresent(LineSelectedType); if (data.GetDataPresent(DataFormats.UnicodeText)) { string text = (string)data.GetData(DataFormats.UnicodeText); if (text.Length > 0) { textArea.Document.UndoStack.StartUndoGroup(); try { if (textArea.SelectionManager.HasSomethingSelected) { textArea.Caret.Position = textArea.SelectionManager.SelectionCollection[0].StartPosition; textArea.SelectionManager.RemoveSelectedText(); } if (fullLine) { int col = textArea.Caret.Column; textArea.Caret.Column = 0; if (!textArea.IsReadOnly(textArea.Caret.Offset)) textArea.InsertString(text); textArea.Caret.Column = col; } else { // textArea.EnableCutOrPaste already checked readonly for this case textArea.InsertString(text); } } finally { textArea.Document.UndoStack.EndUndoGroup(); } } } return; } catch (ExternalException) { // GetDataObject does not provide RetryTimes parameter if (i > 5) throw; } } } public void Delete(object sender, EventArgs e) { new ICSharpCode.TextEditor.Actions.Delete().Execute(textArea); } public void SelectAll(object sender, EventArgs e) { new ICSharpCode.TextEditor.Actions.SelectWholeDocument().Execute(textArea); } protected virtual void OnCopyText(CopyTextEventArgs e) { if (CopyText != null) { CopyText(this, e); } } public event CopyTextEventHandler CopyText; } public delegate void CopyTextEventHandler(object sender, CopyTextEventArgs e); public class CopyTextEventArgs : EventArgs { string text; public string Text { get { return text; } } public CopyTextEventArgs(string text) { this.text = text; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaControl.cs ================================================ // // // // // $Revision: 3078 $ // using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class paints the textarea. /// [ToolboxItem(false)] public class TextAreaControl : Panel { TextEditorControl motherTextEditorControl; HRuler hRuler = null; VScrollBar vScrollBar = new VScrollBar(); HScrollBar hScrollBar = new HScrollBar(); TextArea textArea; bool doHandleMousewheel = true; bool disposed; public TextArea TextArea { get { return textArea; } } public SelectionManager SelectionManager { get { return textArea.SelectionManager; } } public Caret Caret { get { return textArea.Caret; } } [Browsable(false)] public IDocument Document { get { if (motherTextEditorControl != null) return motherTextEditorControl.Document; return null; } } public ITextEditorProperties TextEditorProperties { get { if (motherTextEditorControl != null) return motherTextEditorControl.TextEditorProperties; return null; } } public VScrollBar VScrollBar { get { return vScrollBar; } } public HScrollBar HScrollBar { get { return hScrollBar; } } public bool DoHandleMousewheel { get { return doHandleMousewheel; } set { doHandleMousewheel = value; } } public TextAreaControl(TextEditorControl motherTextEditorControl) { this.motherTextEditorControl = motherTextEditorControl; this.textArea = new TextArea(motherTextEditorControl, this); Controls.Add(textArea); vScrollBar.ValueChanged += new EventHandler(VScrollBarValueChanged); Controls.Add(this.vScrollBar); hScrollBar.ValueChanged += new EventHandler(HScrollBarValueChanged); Controls.Add(this.hScrollBar); ResizeRedraw = true; Document.TextContentChanged += DocumentTextContentChanged; Document.DocumentChanged += AdjustScrollBarsOnDocumentChange; Document.UpdateCommited += DocumentUpdateCommitted; } protected override void Dispose(bool disposing) { if (disposing) { if (!disposed) { disposed = true; Document.TextContentChanged -= DocumentTextContentChanged; Document.DocumentChanged -= AdjustScrollBarsOnDocumentChange; Document.UpdateCommited -= DocumentUpdateCommitted; motherTextEditorControl = null; if (vScrollBar != null) { vScrollBar.Dispose(); vScrollBar = null; } if (hScrollBar != null) { hScrollBar.Dispose(); hScrollBar = null; } if (hRuler != null) { hRuler.Dispose(); hRuler = null; } } } base.Dispose(disposing); } void DocumentTextContentChanged(object sender, EventArgs e) { // after the text content is changed abruptly, we need to validate the // caret position - otherwise the caret position is invalid for a short amount // of time, which can break client code that expects that the caret position is always valid Caret.ValidateCaretPos(); } protected override void OnResize(System.EventArgs e) { base.OnResize(e); ResizeTextArea(); } public void ResizeTextArea() { int y = 0; int h = 0; if (hRuler != null) { hRuler.Bounds = new Rectangle(0, 0, Width - SystemInformation.HorizontalScrollBarArrowWidth, textArea.TextView.FontHeight); y = hRuler.Bounds.Bottom; h = hRuler.Bounds.Height; } textArea.Bounds = new Rectangle(0, y, Width - SystemInformation.HorizontalScrollBarArrowWidth, Height - SystemInformation.VerticalScrollBarArrowHeight - h); SetScrollBarBounds(); } public void SetScrollBarBounds() { vScrollBar.Bounds = new Rectangle(textArea.Bounds.Right, 0, SystemInformation.HorizontalScrollBarArrowWidth, Height - SystemInformation.VerticalScrollBarArrowHeight); hScrollBar.Bounds = new Rectangle(0, textArea.Bounds.Bottom, Width - SystemInformation.HorizontalScrollBarArrowWidth, SystemInformation.VerticalScrollBarArrowHeight); } bool adjustScrollBarsOnNextUpdate; Point scrollToPosOnNextUpdate; void AdjustScrollBarsOnDocumentChange(object sender, DocumentEventArgs e) { if (motherTextEditorControl.IsInUpdate == false) { AdjustScrollBarsClearCache(); AdjustScrollBars(); } else { adjustScrollBarsOnNextUpdate = true; } } void DocumentUpdateCommitted(object sender, EventArgs e) { if (motherTextEditorControl.IsInUpdate == false) { Caret.ValidateCaretPos(); // AdjustScrollBarsOnCommittedUpdate if (!scrollToPosOnNextUpdate.IsEmpty) { ScrollTo(scrollToPosOnNextUpdate.Y, scrollToPosOnNextUpdate.X); } if (adjustScrollBarsOnNextUpdate) { AdjustScrollBarsClearCache(); AdjustScrollBars(); } } } int[] lineLengthCache; const int LineLengthCacheAdditionalSize = 100; void AdjustScrollBarsClearCache() { if (lineLengthCache != null) { if (lineLengthCache.Length < this.Document.TotalNumberOfLines + 2 * LineLengthCacheAdditionalSize) { lineLengthCache = null; } else { Array.Clear(lineLengthCache, 0, lineLengthCache.Length); } } } public void AdjustScrollBars() { adjustScrollBarsOnNextUpdate = false; vScrollBar.Minimum = 0; // number of visible lines in document (folding!) vScrollBar.Maximum = textArea.MaxVScrollValue; int max = 0; int firstLine = textArea.TextView.FirstVisibleLine; int lastLine = this.Document.GetFirstLogicalLine(textArea.TextView.FirstPhysicalLine + textArea.TextView.VisibleLineCount); if (lastLine >= this.Document.TotalNumberOfLines) lastLine = this.Document.TotalNumberOfLines - 1; if (lineLengthCache == null || lineLengthCache.Length <= lastLine) { lineLengthCache = new int[lastLine + LineLengthCacheAdditionalSize]; } for (int lineNumber = firstLine; lineNumber <= lastLine; lineNumber++) { LineSegment lineSegment = this.Document.GetLineSegment(lineNumber); if (Document.FoldingManager.IsLineVisible(lineNumber)) { if (lineLengthCache[lineNumber] > 0) { max = Math.Max(max, lineLengthCache[lineNumber]); } else { int visualLength = textArea.TextView.GetVisualColumnFast(lineSegment, lineSegment.Length); lineLengthCache[lineNumber] = Math.Max(1, visualLength); max = Math.Max(max, visualLength); } } } hScrollBar.Minimum = 0; hScrollBar.Maximum = (Math.Max(max + 20, textArea.TextView.VisibleColumnCount - 1)); vScrollBar.LargeChange = Math.Max(0, textArea.TextView.DrawingPosition.Height); vScrollBar.SmallChange = Math.Max(0, textArea.TextView.FontHeight); hScrollBar.LargeChange = Math.Max(0, textArea.TextView.VisibleColumnCount - 1); hScrollBar.SmallChange = Math.Max(0, (int)textArea.TextView.SpaceWidth); } public void OptionsChanged() { textArea.OptionsChanged(); if (textArea.TextEditorProperties.ShowHorizontalRuler) { if (hRuler == null) { hRuler = new HRuler(textArea); Controls.Add(hRuler); ResizeTextArea(); } else { hRuler.Invalidate(); } } else { if (hRuler != null) { Controls.Remove(hRuler); hRuler.Dispose(); hRuler = null; ResizeTextArea(); } } AdjustScrollBars(); } void VScrollBarValueChanged(object sender, EventArgs e) { textArea.VirtualTop = new Point(textArea.VirtualTop.X, vScrollBar.Value); textArea.Invalidate(); AdjustScrollBars(); } void HScrollBarValueChanged(object sender, EventArgs e) { textArea.VirtualTop = new Point(hScrollBar.Value * textArea.TextView.WideSpaceWidth, textArea.VirtualTop.Y); textArea.Invalidate(); } Util.MouseWheelHandler mouseWheelHandler = new Util.MouseWheelHandler(); public void HandleMouseWheel(MouseEventArgs e) { int scrollDistance = mouseWheelHandler.GetScrollAmount(e); if (scrollDistance == 0) return; if ((Control.ModifierKeys & Keys.Control) != 0 && TextEditorProperties.MouseWheelTextZoom) { if (scrollDistance > 0) { motherTextEditorControl.Font = new Font(motherTextEditorControl.Font.Name, motherTextEditorControl.Font.Size + 1); } else { motherTextEditorControl.Font = new Font(motherTextEditorControl.Font.Name, Math.Max(6, motherTextEditorControl.Font.Size - 1)); } } else { if (TextEditorProperties.MouseWheelScrollDown) scrollDistance = -scrollDistance; int newValue = vScrollBar.Value + vScrollBar.SmallChange * scrollDistance; vScrollBar.Value = Math.Max(vScrollBar.Minimum, Math.Min(vScrollBar.Maximum - vScrollBar.LargeChange + 1, newValue)); } } protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); if (DoHandleMousewheel) { HandleMouseWheel(e); } } public void ScrollToCaret() { ScrollTo(textArea.Caret.Line, textArea.Caret.Column); } public void ScrollTo(int line, int column) { if (motherTextEditorControl.IsInUpdate) { scrollToPosOnNextUpdate = new Point(column, line); return; } else { scrollToPosOnNextUpdate = Point.Empty; } ScrollTo(line); int curCharMin = (int)(this.hScrollBar.Value - this.hScrollBar.Minimum); int curCharMax = curCharMin + textArea.TextView.VisibleColumnCount; int pos = textArea.TextView.GetVisualColumn(line, column); if (textArea.TextView.VisibleColumnCount < 0) { hScrollBar.Value = 0; } else { if (pos < curCharMin) { hScrollBar.Value = (int)(Math.Max(0, pos - scrollMarginHeight)); } else { if (pos > curCharMax) { hScrollBar.Value = (int)Math.Max(0, Math.Min(hScrollBar.Maximum, (pos - textArea.TextView.VisibleColumnCount + scrollMarginHeight))); } } } } int scrollMarginHeight = 3; /// /// Ensure that is visible. /// public void ScrollTo(int line) { line = Math.Max(0, Math.Min(Document.TotalNumberOfLines - 1, line)); line = Document.GetVisibleLine(line); int curLineMin = textArea.TextView.FirstPhysicalLine; if (textArea.TextView.LineHeightRemainder > 0) { curLineMin ++; } if (line - scrollMarginHeight + 3 < curLineMin) { this.vScrollBar.Value = Math.Max(0, Math.Min(this.vScrollBar.Maximum, (line - scrollMarginHeight + 3) * textArea.TextView.FontHeight)) ; VScrollBarValueChanged(this, EventArgs.Empty); } else { int curLineMax = curLineMin + this.textArea.TextView.VisibleLineCount; if (line + scrollMarginHeight - 1 > curLineMax) { if (this.textArea.TextView.VisibleLineCount == 1) { this.vScrollBar.Value = Math.Max(0, Math.Min(this.vScrollBar.Maximum, (line - scrollMarginHeight - 1) * textArea.TextView.FontHeight)) ; } else { this.vScrollBar.Value = Math.Min(this.vScrollBar.Maximum, (line - this.textArea.TextView.VisibleLineCount + scrollMarginHeight - 1)* textArea.TextView.FontHeight) ; } VScrollBarValueChanged(this, EventArgs.Empty); } } } /// /// Scroll so that the specified line is centered. /// /// Line to center view on /// If this action would cause scrolling by less than or equal to /// lines in any direction, don't scroll. /// Use -1 to always center the view. public void CenterViewOn(int line, int treshold) { line = Math.Max(0, Math.Min(Document.TotalNumberOfLines - 1, line)); // convert line to visible line: line = Document.GetVisibleLine(line); // subtract half the visible line count line -= textArea.TextView.VisibleLineCount / 2; int curLineMin = textArea.TextView.FirstPhysicalLine; if (textArea.TextView.LineHeightRemainder > 0) { curLineMin ++; } if (Math.Abs(curLineMin - line) > treshold) { // scroll: this.vScrollBar.Value = Math.Max(0, Math.Min(this.vScrollBar.Maximum, (line - scrollMarginHeight + 3) * textArea.TextView.FontHeight)) ; VScrollBarValueChanged(this, EventArgs.Empty); } } public void JumpTo(int line) { line = Math.Min(line, Document.TotalNumberOfLines - 1); string text = Document.GetText(Document.GetLineSegment(line)); JumpTo(line, text.Length - text.TrimStart().Length); } public void JumpTo(int line, int column) { textArea.Focus(); textArea.SelectionManager.ClearSelection(); textArea.Caret.Position = new TextLocation(column, line); textArea.SetDesiredColumn(); ScrollToCaret(); } public event MouseEventHandler ShowContextMenu; protected override void WndProc(ref Message m) { if (m.Msg == 0x007B) { // handle WM_CONTEXTMENU if (ShowContextMenu != null) { long lParam = m.LParam.ToInt64(); int x = unchecked((short)(lParam & 0xffff)); int y = unchecked((short)((lParam & 0xffff0000) >> 16)); if (x == -1 && y == -1) { Point pos = Caret.ScreenPosition; ShowContextMenu(this, new MouseEventArgs(MouseButtons.None, 0, pos.X, pos.Y + textArea.TextView.FontHeight, 0)); } else { Point pos = PointToClient(new Point(x, y)); ShowContextMenu(this, new MouseEventArgs(MouseButtons.Right, 1, pos.X, pos.Y, 0)); } } } base.WndProc(ref m); } protected override void OnEnter(EventArgs e) { // SD2-1072 - Make sure the caret line is valid if anyone // has handlers for the Enter event. Caret.ValidateCaretPos(); base.OnEnter(e); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaDragDropHandler.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Drawing; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { public class TextAreaDragDropHandler { public static Action OnDragDropException = ex => MessageBox.Show(ex.ToString()); TextArea textArea; public void Attach(TextArea textArea) { this.textArea = textArea; textArea.AllowDrop = true; textArea.DragEnter += MakeDragEventHandler(OnDragEnter); textArea.DragDrop += MakeDragEventHandler(OnDragDrop); textArea.DragOver += MakeDragEventHandler(OnDragOver); } /// /// Create a drag'n'drop event handler. /// Windows Forms swallows unhandled exceptions during drag'n'drop, so we report them here. /// static DragEventHandler MakeDragEventHandler(DragEventHandler h) { return (sender, e) => { try { h(sender, e); } catch (Exception ex) { OnDragDropException(ex); } }; } static DragDropEffects GetDragDropEffect(DragEventArgs e) { if ((e.AllowedEffect & DragDropEffects.Move) > 0 && (e.AllowedEffect & DragDropEffects.Copy) > 0) { return (e.KeyState & 8) > 0 ? DragDropEffects.Copy : DragDropEffects.Move; } else if ((e.AllowedEffect & DragDropEffects.Move) > 0) { return DragDropEffects.Move; } else if ((e.AllowedEffect & DragDropEffects.Copy) > 0) { return DragDropEffects.Copy; } return DragDropEffects.None; } protected void OnDragEnter(object sender, DragEventArgs e) { // JDB: Change for pyramid. Pass the event up to the parent control // so that external handlers will fire textArea.MotherTextEditorControl.DispatchDragEnter(e); // textArea.Parent.OnDragEnter(sender, e); // if (e.Data.GetDataPresent(typeof(string))) { // e.Effect = GetDragDropEffect(e); // } } void InsertString(int offset, string str) { textArea.Document.Insert(offset, str); textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.Document, textArea.Document.OffsetToPosition(offset), textArea.Document.OffsetToPosition(offset + str.Length))); textArea.Caret.Position = textArea.Document.OffsetToPosition(offset + str.Length); textArea.Refresh(); } protected void OnDragDrop(object sender, DragEventArgs e) { // JDB: Change for pyramid. Pass the event up to the parent control // so that external handlers will fire textArea.MotherTextEditorControl.DispatchDragDrop(e); /* Point p = textArea.PointToClient(new Point(e.X, e.Y)); if (e.Data.GetDataPresent(typeof(string))) { textArea.BeginUpdate(); textArea.Document.UndoStack.StartUndoGroup(); try { int offset = textArea.Caret.Offset; if (textArea.IsReadOnly(offset)) { // prevent dragging text into readonly section return; } if (e.Data.GetDataPresent(typeof(DefaultSelection))) { ISelection sel = (ISelection)e.Data.GetData(typeof(DefaultSelection)); if (sel.ContainsPosition(textArea.Caret.Position)) { return; } if (GetDragDropEffect(e) == DragDropEffects.Move) { if (SelectionManager.SelectionIsReadOnly(textArea.Document, sel)) { // prevent dragging text out of readonly section return; } int len = sel.Length; textArea.Document.Remove(sel.Offset, len); if (sel.Offset < offset) { offset -= len; } } } textArea.SelectionManager.ClearSelection(); InsertString(offset, (string)e.Data.GetData(typeof(string))); textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); } finally { textArea.Document.UndoStack.EndUndoGroup(); textArea.EndUpdate(); } } */ } protected void OnDragOver(object sender, DragEventArgs e) { // JDB: Change for pyramid. Pass the event up to the parent control // so that external handlers will fire textArea.MotherTextEditorControl.DispatchDragOver(e); /* if (!textArea.Focused) { textArea.Focus(); } Point p = textArea.PointToClient(new Point(e.X, e.Y)); if (textArea.TextView.DrawingPosition.Contains(p.X, p.Y)) { TextLocation realmousepos= textArea.TextView.GetLogicalPosition(p.X - textArea.TextView.DrawingPosition.X, p.Y - textArea.TextView.DrawingPosition.Y); int lineNr = Math.Min(textArea.Document.TotalNumberOfLines - 1, Math.Max(0, realmousepos.Y)); textArea.Caret.Position = new TextLocation(realmousepos.X, lineNr); textArea.SetDesiredColumn(); if (e.Data.GetDataPresent(typeof(string)) && !textArea.IsReadOnly(textArea.Caret.Offset)) { e.Effect = GetDragDropEffect(e); } else { e.Effect = DragDropEffects.None; } } else { e.Effect = DragDropEffects.None; }*/ } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaMouseHandler.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Text; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class handles all mouse stuff for a textArea. /// public class TextAreaMouseHandler { TextArea textArea; bool doubleclick = false; bool clickedOnSelectedText = false; MouseButtons button; static readonly Point nilPoint = new Point(-1, -1); Point mousedownpos = nilPoint; Point lastmousedownpos = nilPoint; bool gotmousedown = false; bool dodragdrop = false; public TextAreaMouseHandler(TextArea ttextArea) { textArea = ttextArea; } public void Attach() { textArea.Click += new EventHandler(TextAreaClick); textArea.MouseMove += new MouseEventHandler(TextAreaMouseMove); textArea.MouseDown += new MouseEventHandler(OnMouseDown); textArea.DoubleClick += new EventHandler(OnDoubleClick); textArea.MouseLeave += new EventHandler(OnMouseLeave); textArea.MouseUp += new MouseEventHandler(OnMouseUp); textArea.LostFocus += new EventHandler(TextAreaLostFocus); textArea.ToolTipRequest += new ToolTipRequestEventHandler(OnToolTipRequest); } void OnToolTipRequest(object sender, ToolTipRequestEventArgs e) { if (e.ToolTipShown) return; Point mousepos = e.MousePosition; FoldMarker marker = textArea.TextView.GetFoldMarkerFromPosition(mousepos.X - textArea.TextView.DrawingPosition.X, mousepos.Y - textArea.TextView.DrawingPosition.Y); if (marker != null && marker.IsFolded) { StringBuilder sb = new StringBuilder(marker.InnerText); // max 10 lines int endLines = 0; for (int i = 0; i < sb.Length; ++i) { if (sb[i] == '\n') { ++endLines; if (endLines >= 10) { sb.Remove(i + 1, sb.Length - i - 1); sb.Append(Environment.NewLine); sb.Append("..."); break; } } } sb.Replace("\t", " "); e.ShowToolTip(sb.ToString()); return; } List markers = textArea.Document.MarkerStrategy.GetMarkers(e.LogicalPosition); foreach (TextMarker tm in markers) { if (tm.ToolTip != null) { e.ShowToolTip(tm.ToolTip.Replace("\t", " ")); return; } } } void ShowHiddenCursorIfMovedOrLeft() { textArea.ShowHiddenCursor(!textArea.Focused || !textArea.ClientRectangle.Contains(textArea.PointToClient(Cursor.Position))); } void TextAreaLostFocus(object sender, EventArgs e) { // The call to ShowHiddenCursorIfMovedOrLeft is delayed // until pending messages have been processed // so that it can properly detect whether the TextArea // has really lost focus. // For example, the CodeCompletionWindow gets focus when it is shown, // but immediately gives back focus to the TextArea. textArea.BeginInvoke(new MethodInvoker(ShowHiddenCursorIfMovedOrLeft)); } void OnMouseLeave(object sender, EventArgs e) { ShowHiddenCursorIfMovedOrLeft(); gotmousedown = false; mousedownpos = nilPoint; } void OnMouseUp(object sender, MouseEventArgs e) { textArea.SelectionManager.selectFrom.where = WhereFrom.None; gotmousedown = false; mousedownpos = nilPoint; } void TextAreaClick(object sender, EventArgs e) { Point mousepos; mousepos = textArea.mousepos; if (dodragdrop) { return; } if (clickedOnSelectedText && textArea.TextView.DrawingPosition.Contains(mousepos.X, mousepos.Y)) { textArea.SelectionManager.ClearSelection(); TextLocation clickPosition = textArea.TextView.GetLogicalPosition( mousepos.X - textArea.TextView.DrawingPosition.X, mousepos.Y - textArea.TextView.DrawingPosition.Y); textArea.Caret.Position = clickPosition; textArea.SetDesiredColumn(); } } void TextAreaMouseMove(object sender, MouseEventArgs e) { textArea.mousepos = e.Location; // honour the starting selection strategy switch (textArea.SelectionManager.selectFrom.where) { case WhereFrom.Gutter: ExtendSelectionToMouse(); return; case WhereFrom.TArea: break; } textArea.ShowHiddenCursor(false); if (dodragdrop) { dodragdrop = false; return; } doubleclick = false; textArea.mousepos = new Point(e.X, e.Y); if (clickedOnSelectedText) { if (Math.Abs(mousedownpos.X - e.X) >= SystemInformation.DragSize.Width / 2 || Math.Abs(mousedownpos.Y - e.Y) >= SystemInformation.DragSize.Height / 2) { clickedOnSelectedText = false; ISelection selection = textArea.SelectionManager.GetSelectionAt(textArea.Caret.Offset); if (selection != null) { string text = selection.SelectedText; bool isReadOnly = SelectionManager.SelectionIsReadOnly(textArea.Document, selection); if (text != null && text.Length > 0) { DataObject dataObject = new DataObject (); dataObject.SetData(DataFormats.UnicodeText, true, text); dataObject.SetData(selection); dodragdrop = true; textArea.DoDragDrop(dataObject, isReadOnly ? DragDropEffects.All & ~DragDropEffects.Move : DragDropEffects.All); } } } return; } if (e.Button == MouseButtons.Left) { if (gotmousedown && textArea.SelectionManager.selectFrom.where == WhereFrom.TArea) { ExtendSelectionToMouse(); } } } void ExtendSelectionToMouse() { Point mousepos; mousepos = textArea.mousepos; TextLocation realmousepos = textArea.TextView.GetLogicalPosition( Math.Max(0, mousepos.X - textArea.TextView.DrawingPosition.X), mousepos.Y - textArea.TextView.DrawingPosition.Y); int y = realmousepos.Y; realmousepos = textArea.Caret.ValidatePosition(realmousepos); TextLocation oldPos = textArea.Caret.Position; if (oldPos == realmousepos && textArea.SelectionManager.selectFrom.where != WhereFrom.Gutter) { return; } // the selection is from the gutter if (textArea.SelectionManager.selectFrom.where == WhereFrom.Gutter) { if(realmousepos.Y < textArea.SelectionManager.SelectionStart.Y) { // the selection has moved above the startpoint textArea.Caret.Position = new TextLocation(0, realmousepos.Y); } else { // the selection has moved below the startpoint textArea.Caret.Position = textArea.SelectionManager.NextValidPosition(realmousepos.Y); } } else { textArea.Caret.Position = realmousepos; } // moves selection across whole words for double-click initiated selection if (!minSelection.IsEmpty && textArea.SelectionManager.SelectionCollection.Count > 0 && textArea.SelectionManager.selectFrom.where == WhereFrom.TArea) { // Extend selection when selection was started with double-click ISelection selection = textArea.SelectionManager.SelectionCollection[0]; TextLocation min = textArea.SelectionManager.GreaterEqPos(minSelection, maxSelection) ? maxSelection : minSelection; TextLocation max = textArea.SelectionManager.GreaterEqPos(minSelection, maxSelection) ? minSelection : maxSelection; if (textArea.SelectionManager.GreaterEqPos(max, realmousepos) && textArea.SelectionManager.GreaterEqPos(realmousepos, min)) { textArea.SelectionManager.SetSelection(min, max); } else if (textArea.SelectionManager.GreaterEqPos(max, realmousepos)) { int moff = textArea.Document.PositionToOffset(realmousepos); min = textArea.Document.OffsetToPosition(FindWordStart(textArea.Document, moff)); textArea.SelectionManager.SetSelection(min, max); } else { int moff = textArea.Document.PositionToOffset(realmousepos); max = textArea.Document.OffsetToPosition(FindWordEnd(textArea.Document, moff)); textArea.SelectionManager.SetSelection(min, max); } } else { textArea.SelectionManager.ExtendSelection(oldPos, textArea.Caret.Position); } textArea.SetDesiredColumn(); } void DoubleClickSelectionExtend() { Point mousepos; mousepos = textArea.mousepos; textArea.SelectionManager.ClearSelection(); if (textArea.TextView.DrawingPosition.Contains(mousepos.X, mousepos.Y)) { FoldMarker marker = textArea.TextView.GetFoldMarkerFromPosition(mousepos.X - textArea.TextView.DrawingPosition.X, mousepos.Y - textArea.TextView.DrawingPosition.Y); if (marker != null && marker.IsFolded) { marker.IsFolded = false; textArea.MotherTextAreaControl.AdjustScrollBars(); } if (textArea.Caret.Offset < textArea.Document.TextLength) { switch (textArea.Document.GetCharAt(textArea.Caret.Offset)) { case '"': if (textArea.Caret.Offset < textArea.Document.TextLength) { int next = FindNext(textArea.Document, textArea.Caret.Offset + 1, '"'); minSelection = textArea.Caret.Position; if (next > textArea.Caret.Offset && next < textArea.Document.TextLength) next += 1; maxSelection = textArea.Document.OffsetToPosition(next); } break; default: minSelection = textArea.Document.OffsetToPosition(FindWordStart(textArea.Document, textArea.Caret.Offset)); maxSelection = textArea.Document.OffsetToPosition(FindWordEnd(textArea.Document, textArea.Caret.Offset)); break; } textArea.Caret.Position = maxSelection; textArea.SelectionManager.ExtendSelection(minSelection, maxSelection); } if (textArea.SelectionManager.selectionCollection.Count > 0) { ISelection selection = textArea.SelectionManager.selectionCollection[0]; selection.StartPosition = minSelection; selection.EndPosition = maxSelection; textArea.SelectionManager.SelectionStart = minSelection; } // after a double-click selection, the caret is placed correctly, // but it is not positioned internally. The effect is when the cursor // is moved up or down a line, the caret will take on the column first // clicked on for the double-click textArea.SetDesiredColumn(); // HACK WARNING !!! // must refresh here, because when a error tooltip is showed and the underlined // code is double clicked the textArea don't update corrctly, updateline doesn't // work ... but the refresh does. // Mike textArea.Refresh(); } } void OnMouseDown(object sender, MouseEventArgs e) { Point mousepos; textArea.mousepos = e.Location; mousepos = e.Location; if (dodragdrop) { return; } if (doubleclick) { doubleclick = false; return; } if (textArea.TextView.DrawingPosition.Contains(mousepos.X, mousepos.Y)) { gotmousedown = true; textArea.SelectionManager.selectFrom.where = WhereFrom.TArea; button = e.Button; // double-click if (button == MouseButtons.Left && e.Clicks == 2) { int deltaX = Math.Abs(lastmousedownpos.X - e.X); int deltaY = Math.Abs(lastmousedownpos.Y - e.Y); if (deltaX <= SystemInformation.DoubleClickSize.Width && deltaY <= SystemInformation.DoubleClickSize.Height) { DoubleClickSelectionExtend(); lastmousedownpos = new Point(e.X, e.Y); if (textArea.SelectionManager.selectFrom.where == WhereFrom.Gutter) { if (!minSelection.IsEmpty && !maxSelection.IsEmpty && textArea.SelectionManager.SelectionCollection.Count > 0) { textArea.SelectionManager.SelectionCollection[0].StartPosition = minSelection; textArea.SelectionManager.SelectionCollection[0].EndPosition = maxSelection; textArea.SelectionManager.SelectionStart = minSelection; minSelection = TextLocation.Empty; maxSelection = TextLocation.Empty; } } return; } } minSelection = TextLocation.Empty; maxSelection = TextLocation.Empty; lastmousedownpos = mousedownpos = new Point(e.X, e.Y); if (button == MouseButtons.Left) { FoldMarker marker = textArea.TextView.GetFoldMarkerFromPosition(mousepos.X - textArea.TextView.DrawingPosition.X, mousepos.Y - textArea.TextView.DrawingPosition.Y); if (marker != null && marker.IsFolded) { if (textArea.SelectionManager.HasSomethingSelected) { clickedOnSelectedText = true; } textArea.SelectionManager.SetSelection(new DefaultSelection(textArea.TextView.Document, new TextLocation(marker.StartColumn, marker.StartLine), new TextLocation(marker.EndColumn, marker.EndLine))); textArea.Focus(); return; } if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) { ExtendSelectionToMouse(); } else { TextLocation realmousepos = textArea.TextView.GetLogicalPosition(mousepos.X - textArea.TextView.DrawingPosition.X, mousepos.Y - textArea.TextView.DrawingPosition.Y); clickedOnSelectedText = false; int offset = textArea.Document.PositionToOffset(realmousepos); if (textArea.SelectionManager.HasSomethingSelected && textArea.SelectionManager.IsSelected(offset)) { clickedOnSelectedText = true; } else { textArea.SelectionManager.ClearSelection(); if (mousepos.Y > 0 && mousepos.Y < textArea.TextView.DrawingPosition.Height) { TextLocation pos = new TextLocation(); pos.Y = Math.Min(textArea.Document.TotalNumberOfLines - 1, realmousepos.Y); pos.X = realmousepos.X; textArea.Caret.Position = pos; textArea.SetDesiredColumn(); } } } } else if (button == MouseButtons.Right) { // Rightclick sets the cursor to the click position unless // the previous selection was clicked TextLocation realmousepos = textArea.TextView.GetLogicalPosition(mousepos.X - textArea.TextView.DrawingPosition.X, mousepos.Y - textArea.TextView.DrawingPosition.Y); int offset = textArea.Document.PositionToOffset(realmousepos); if (!textArea.SelectionManager.HasSomethingSelected || !textArea.SelectionManager.IsSelected(offset)) { textArea.SelectionManager.ClearSelection(); if (mousepos.Y > 0 && mousepos.Y < textArea.TextView.DrawingPosition.Height) { TextLocation pos = new TextLocation(); pos.Y = Math.Min(textArea.Document.TotalNumberOfLines - 1, realmousepos.Y); pos.X = realmousepos.X; textArea.Caret.Position = pos; textArea.SetDesiredColumn(); } } } } textArea.Focus(); } int FindNext(IDocument document, int offset, char ch) { LineSegment line = document.GetLineSegmentForOffset(offset); int endPos = line.Offset + line.Length; while (offset < endPos && document.GetCharAt(offset) != ch) { ++offset; } return offset; } bool IsSelectableChar(char ch) { return Char.IsLetterOrDigit(ch) || ch=='_'; } int FindWordStart(IDocument document, int offset) { LineSegment line = document.GetLineSegmentForOffset(offset); if (offset > 0 && Char.IsWhiteSpace(document.GetCharAt(offset - 1)) && Char.IsWhiteSpace(document.GetCharAt(offset))) { while (offset > line.Offset && Char.IsWhiteSpace(document.GetCharAt(offset - 1))) { --offset; } } else if (IsSelectableChar(document.GetCharAt(offset)) || (offset > 0 && Char.IsWhiteSpace(document.GetCharAt(offset)) && IsSelectableChar(document.GetCharAt(offset - 1)))) { while (offset > line.Offset && IsSelectableChar(document.GetCharAt(offset - 1))) { --offset; } } else { if (offset > 0 && !Char.IsWhiteSpace(document.GetCharAt(offset - 1)) && !IsSelectableChar(document.GetCharAt(offset - 1)) ) { return Math.Max(0, offset - 1); } } return offset; } int FindWordEnd(IDocument document, int offset) { LineSegment line = document.GetLineSegmentForOffset(offset); int endPos = line.Offset + line.Length; offset = Math.Min(offset, endPos - 1); if (IsSelectableChar(document.GetCharAt(offset))) { while (offset < endPos && IsSelectableChar(document.GetCharAt(offset))) { ++offset; } } else if (Char.IsWhiteSpace(document.GetCharAt(offset))) { if (offset > 0 && Char.IsWhiteSpace(document.GetCharAt(offset - 1))) { while (offset < endPos && Char.IsWhiteSpace(document.GetCharAt(offset))) { ++offset; } } } else { return Math.Max(0, offset + 1); } return offset; } TextLocation minSelection = TextLocation.Empty; TextLocation maxSelection = TextLocation.Empty; void OnDoubleClick(object sender, System.EventArgs e) { if (dodragdrop) { return; } textArea.SelectionManager.selectFrom.where = WhereFrom.TArea; doubleclick = true; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaUpdate.cs ================================================ // // // // // $Revision: 2659 $ // using System; using System.Drawing; namespace ICSharpCode.TextEditor { /// /// This enum describes all implemented request types /// public enum TextAreaUpdateType { WholeTextArea, SingleLine, SinglePosition, PositionToLineEnd, PositionToEnd, LinesBetween } /// /// This class is used to request an update of the textarea /// public class TextAreaUpdate { TextLocation position; TextAreaUpdateType type; public TextAreaUpdateType TextAreaUpdateType { get { return type; } } public TextLocation Position { get { return position; } } /// /// Creates a new instance of /// public TextAreaUpdate(TextAreaUpdateType type) { this.type = type; } /// /// Creates a new instance of /// public TextAreaUpdate(TextAreaUpdateType type, TextLocation position) { this.type = type; this.position = position; } /// /// Creates a new instance of /// public TextAreaUpdate(TextAreaUpdateType type, int startLine, int endLine) { this.type = type; this.position = new TextLocation(startLine, endLine); } /// /// Creates a new instance of /// public TextAreaUpdate(TextAreaUpdateType type, int singleLine) { this.type = type; this.position = new TextLocation(0, singleLine); } public override string ToString() { return String.Format("[TextAreaUpdate: Type={0}, Position={1}]", type, position); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControl.cs ================================================ // // // // // $Revision: 3078 $ // using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class is used for a basic text area control /// [ToolboxBitmap("ICSharpCode.TextEditor.Resources.TextEditorControl.bmp")] [ToolboxItem(true)] public class TextEditorControl : TextEditorControlBase { protected Panel textAreaPanel = new Panel(); TextAreaControl primaryTextArea; Splitter textAreaSplitter = null; TextAreaControl secondaryTextArea = null; PrintDocument printDocument = null; [Browsable(false)] public PrintDocument PrintDocument { get { if (printDocument == null) { printDocument = new PrintDocument(); printDocument.BeginPrint += new PrintEventHandler(this.BeginPrint); printDocument.PrintPage += new PrintPageEventHandler(this.PrintPage); } return printDocument; } } TextAreaControl activeTextAreaControl; public override TextAreaControl ActiveTextAreaControl { get { return activeTextAreaControl; } } protected void SetActiveTextAreaControl(TextAreaControl value) { if (activeTextAreaControl != value) { activeTextAreaControl = value; if (ActiveTextAreaControlChanged != null) { ActiveTextAreaControlChanged(this, EventArgs.Empty); } } } public event EventHandler ActiveTextAreaControlChanged; // JDB -- Change for pyramid // The drag handler will pass events up to the TextEditor usercontrol // so that outside event delegates will fire on a drag internal void DispatchDragDrop(DragEventArgs drgevent) { base.OnDragDrop(drgevent); } internal void DispatchDragEnter(DragEventArgs drgevent) { base.OnDragEnter(drgevent); } internal void DispatchDragOver(DragEventArgs drgevent) { base.OnDragLeave(drgevent); } // JDB public TextEditorControl() { SetStyle(ControlStyles.ContainerControl, true); textAreaPanel.Dock = DockStyle.Fill; Document = (new DocumentFactory()).CreateDocument(); Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(); primaryTextArea = new TextAreaControl(this); activeTextAreaControl = primaryTextArea; primaryTextArea.TextArea.GotFocus += delegate { SetActiveTextAreaControl(primaryTextArea); }; primaryTextArea.Dock = DockStyle.Fill; textAreaPanel.Controls.Add(primaryTextArea); InitializeTextAreaControl(primaryTextArea); Controls.Add(textAreaPanel); ResizeRedraw = true; Document.UpdateCommited += new EventHandler(CommitUpdateRequested); OptionsChanged(); } protected virtual void InitializeTextAreaControl(TextAreaControl newControl) { } public override void OptionsChanged() { primaryTextArea.OptionsChanged(); if (secondaryTextArea != null) { secondaryTextArea.OptionsChanged(); } } public void Split() { if (secondaryTextArea == null) { secondaryTextArea = new TextAreaControl(this); secondaryTextArea.Dock = DockStyle.Bottom; secondaryTextArea.Height = Height / 2; secondaryTextArea.TextArea.GotFocus += delegate { SetActiveTextAreaControl(secondaryTextArea); }; textAreaSplitter = new Splitter(); textAreaSplitter.BorderStyle = BorderStyle.FixedSingle ; textAreaSplitter.Height = 8; textAreaSplitter.Dock = DockStyle.Bottom; textAreaPanel.Controls.Add(textAreaSplitter); textAreaPanel.Controls.Add(secondaryTextArea); InitializeTextAreaControl(secondaryTextArea); secondaryTextArea.OptionsChanged(); } else { SetActiveTextAreaControl(primaryTextArea); textAreaPanel.Controls.Remove(secondaryTextArea); textAreaPanel.Controls.Remove(textAreaSplitter); secondaryTextArea.Dispose(); textAreaSplitter.Dispose(); secondaryTextArea = null; textAreaSplitter = null; } } [Browsable(false)] public bool EnableUndo { get { return Document.UndoStack.CanUndo; } } [Browsable(false)] public bool EnableRedo { get { return Document.UndoStack.CanRedo; } } public void Undo() { if (Document.ReadOnly) { return; } if (Document.UndoStack.CanUndo) { BeginUpdate(); Document.UndoStack.Undo(); Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); this.primaryTextArea.TextArea.UpdateMatchingBracket(); if (secondaryTextArea != null) { this.secondaryTextArea.TextArea.UpdateMatchingBracket(); } EndUpdate(); } } public void Redo() { if (Document.ReadOnly) { return; } if (Document.UndoStack.CanRedo) { BeginUpdate(); Document.UndoStack.Redo(); Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea)); this.primaryTextArea.TextArea.UpdateMatchingBracket(); if (secondaryTextArea != null) { this.secondaryTextArea.TextArea.UpdateMatchingBracket(); } EndUpdate(); } } public void SetHighlighting(string name) { Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(name); } protected override void Dispose(bool disposing) { if (disposing) { if (printDocument != null) { printDocument.BeginPrint -= new PrintEventHandler(this.BeginPrint); printDocument.PrintPage -= new PrintPageEventHandler(this.PrintPage); printDocument = null; } Document.UndoStack.ClearAll(); Document.UpdateCommited -= new EventHandler(CommitUpdateRequested); if (textAreaPanel != null) { if (secondaryTextArea != null) { secondaryTextArea.Dispose(); textAreaSplitter.Dispose(); secondaryTextArea = null; textAreaSplitter = null; } if (primaryTextArea != null) { primaryTextArea.Dispose(); } textAreaPanel.Dispose(); textAreaPanel = null; } } base.Dispose(disposing); } #region Update Methods public override void EndUpdate() { base.EndUpdate(); Document.CommitUpdate(); if (!IsInUpdate) { ActiveTextAreaControl.Caret.OnEndUpdate(); } } void CommitUpdateRequested(object sender, EventArgs e) { if (IsInUpdate) { return; } foreach (TextAreaUpdate update in Document.UpdateQueue) { switch (update.TextAreaUpdateType) { case TextAreaUpdateType.PositionToEnd: this.primaryTextArea.TextArea.UpdateToEnd(update.Position.Y); if (this.secondaryTextArea != null) { this.secondaryTextArea.TextArea.UpdateToEnd(update.Position.Y); } break; case TextAreaUpdateType.PositionToLineEnd: case TextAreaUpdateType.SingleLine: this.primaryTextArea.TextArea.UpdateLine(update.Position.Y); if (this.secondaryTextArea != null) { this.secondaryTextArea.TextArea.UpdateLine(update.Position.Y); } break; case TextAreaUpdateType.SinglePosition: this.primaryTextArea.TextArea.UpdateLine(update.Position.Y, update.Position.X, update.Position.X); if (this.secondaryTextArea != null) { this.secondaryTextArea.TextArea.UpdateLine(update.Position.Y, update.Position.X, update.Position.X); } break; case TextAreaUpdateType.LinesBetween: this.primaryTextArea.TextArea.UpdateLines(update.Position.X, update.Position.Y); if (this.secondaryTextArea != null) { this.secondaryTextArea.TextArea.UpdateLines(update.Position.X, update.Position.Y); } break; case TextAreaUpdateType.WholeTextArea: this.primaryTextArea.TextArea.Invalidate(); if (this.secondaryTextArea != null) { this.secondaryTextArea.TextArea.Invalidate(); } break; } } Document.UpdateQueue.Clear(); // this.primaryTextArea.TextArea.Update(); // if (this.secondaryTextArea != null) { // this.secondaryTextArea.TextArea.Update(); // } } #endregion #region Printing routines int curLineNr = 0; float curTabIndent = 0; StringFormat printingStringFormat; void BeginPrint(object sender, PrintEventArgs ev) { curLineNr = 0; printingStringFormat = (StringFormat)System.Drawing.StringFormat.GenericTypographic.Clone(); // 100 should be enough for everyone ...err ? float[] tabStops = new float[100]; for (int i = 0; i < tabStops.Length; ++i) { tabStops[i] = TabIndent * primaryTextArea.TextArea.TextView.WideSpaceWidth; } printingStringFormat.SetTabStops(0, tabStops); } void Advance(ref float x, ref float y, float maxWidth, float size, float fontHeight) { if (x + size < maxWidth) { x += size; } else { x = curTabIndent; y += fontHeight; } } // btw. I hate source code duplication ... but this time I don't care !!!! float MeasurePrintingHeight(Graphics g, LineSegment line, float maxWidth) { float xPos = 0; float yPos = 0; float fontHeight = Font.GetHeight(g); // bool gotNonWhitespace = false; curTabIndent = 0; FontContainer fontContainer = TextEditorProperties.FontContainer; foreach (TextWord word in line.Words) { switch (word.Type) { case TextWordType.Space: Advance(ref xPos, ref yPos, maxWidth, primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Tab: Advance(ref xPos, ref yPos, maxWidth, TabIndent * primaryTextArea.TextArea.TextView.WideSpaceWidth, fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Word: // if (!gotNonWhitespace) { // gotNonWhitespace = true; // curTabIndent += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' '); // } SizeF drawingSize = g.MeasureString(word.Word, word.GetFont(fontContainer), new SizeF(maxWidth, fontHeight * 100), printingStringFormat); Advance(ref xPos, ref yPos, maxWidth, drawingSize.Width, fontHeight); break; } } return yPos + fontHeight; } void DrawLine(Graphics g, LineSegment line, float yPos, RectangleF margin) { float xPos = 0; float fontHeight = Font.GetHeight(g); // bool gotNonWhitespace = false; curTabIndent = 0 ; FontContainer fontContainer = TextEditorProperties.FontContainer; foreach (TextWord word in line.Words) { switch (word.Type) { case TextWordType.Space: Advance(ref xPos, ref yPos, margin.Width, primaryTextArea.TextArea.TextView.SpaceWidth, fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Tab: Advance(ref xPos, ref yPos, margin.Width, TabIndent * primaryTextArea.TextArea.TextView.WideSpaceWidth, fontHeight); // if (!gotNonWhitespace) { // curTabIndent = xPos; // } break; case TextWordType.Word: // if (!gotNonWhitespace) { // gotNonWhitespace = true; // curTabIndent += TabIndent * primaryTextArea.TextArea.TextView.GetWidth(' '); // } g.DrawString(word.Word, word.GetFont(fontContainer), BrushRegistry.GetBrush(word.Color), xPos + margin.X, yPos); SizeF drawingSize = g.MeasureString(word.Word, word.GetFont(fontContainer), new SizeF(margin.Width, fontHeight * 100), printingStringFormat); Advance(ref xPos, ref yPos, margin.Width, drawingSize.Width, fontHeight); break; } } } void PrintPage(object sender, PrintPageEventArgs ev) { Graphics g = ev.Graphics; float yPos = ev.MarginBounds.Top; while (curLineNr < Document.TotalNumberOfLines) { LineSegment curLine = Document.GetLineSegment(curLineNr); if (curLine.Words != null) { float drawingHeight = MeasurePrintingHeight(g, curLine, ev.MarginBounds.Width); if (drawingHeight + yPos > ev.MarginBounds.Bottom) { break; } DrawLine(g, curLine, yPos, ev.MarginBounds); yPos += drawingHeight; } ++curLineNr; } // If more lines exist, print another page. ev.HasMorePages = curLineNr < Document.TotalNumberOfLines; } #endregion } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs ================================================ // // // // // $Revision: 2932 $ // using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Text; using System.IO; using System.Text; using System.Windows.Forms; using ICSharpCode.TextEditor.Actions; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class is used for a basic text area control /// [ToolboxItem(false)] public abstract class TextEditorControlBase : UserControl { string currentFileName = null; int updateLevel = 0; IDocument document; /// /// This hashtable contains all editor keys, where /// the key is the key combination and the value the /// action. /// protected Dictionary editactions = new Dictionary(); [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ITextEditorProperties TextEditorProperties { get { return document.TextEditorProperties; } set { document.TextEditorProperties = value; OptionsChanged(); } } Encoding encoding; /// /// Current file's character encoding /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Encoding Encoding { get { if (encoding == null) return TextEditorProperties.Encoding; return encoding; } set { encoding = value; } } /// /// The current file name /// [Browsable(false)] [ReadOnly(true)] public string FileName { get { return currentFileName; } set { if (currentFileName != value) { currentFileName = value; OnFileNameChanged(EventArgs.Empty); } } } /// /// The current document /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public IDocument Document { get { return document; } set { if (value == null) throw new ArgumentNullException("value"); if (document != null) { document.DocumentChanged -= OnDocumentChanged; } document = value; document.UndoStack.TextEditorControl = this; document.DocumentChanged += OnDocumentChanged; } } void OnDocumentChanged(object sender, EventArgs e) { OnTextChanged(e); } [EditorBrowsable(EditorBrowsableState.Always), Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Editor("System.ComponentModel.Design.MultilineStringEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))] public override string Text { get { return Document.TextContent; } set { Document.TextContent = value; } } [EditorBrowsable(EditorBrowsableState.Always), Browsable(true)] public new event EventHandler TextChanged { add { base.TextChanged += value; } remove { base.TextChanged -= value; } } static Font ParseFont(string font) { string[] descr = font.Split(new char[]{',', '='}); return new Font(descr[1], Single.Parse(descr[3])); } /// /// If set to true the contents can't be altered. /// [Browsable(false)] public bool IsReadOnly { get { return Document.ReadOnly; } set { Document.ReadOnly = value; } } /// /// true, if the textarea is updating it's status, while /// it updates it status no redraw operation occurs. /// [Browsable(false)] public bool IsInUpdate { get { return updateLevel > 0; } } /// /// supposedly this is the way to do it according to .NET docs, /// as opposed to setting the size in the constructor /// protected override Size DefaultSize { get { return new Size(100, 100); } } #region Document Properties /// /// If true spaces are shown in the textarea /// [Category("Appearance")] [DefaultValue(false)] [Description("If true spaces are shown in the textarea")] public bool ShowSpaces { get { return document.TextEditorProperties.ShowSpaces; } set { document.TextEditorProperties.ShowSpaces = value; OptionsChanged(); } } /// /// Specifies the quality of text rendering (whether to use hinting and/or anti-aliasing). /// [Category("Appearance")] [DefaultValue(TextRenderingHint.SystemDefault)] [Description("Specifies the quality of text rendering (whether to use hinting and/or anti-aliasing).")] public TextRenderingHint TextRenderingHint { get { return document.TextEditorProperties.TextRenderingHint; } set { document.TextEditorProperties.TextRenderingHint = value; OptionsChanged(); } } /// /// If true tabs are shown in the textarea /// [Category("Appearance")] [DefaultValue(false)] [Description("If true tabs are shown in the textarea")] public bool ShowTabs { get { return document.TextEditorProperties.ShowTabs; } set { document.TextEditorProperties.ShowTabs = value; OptionsChanged(); } } /// /// If true EOL markers are shown in the textarea /// [Category("Appearance")] [DefaultValue(false)] [Description("If true EOL markers are shown in the textarea")] public bool ShowEOLMarkers { get { return document.TextEditorProperties.ShowEOLMarker; } set { document.TextEditorProperties.ShowEOLMarker = value; OptionsChanged(); } } /// /// If true the horizontal ruler is shown in the textarea /// [Category("Appearance")] [DefaultValue(false)] [Description("If true the horizontal ruler is shown in the textarea")] public bool ShowHRuler { get { return document.TextEditorProperties.ShowHorizontalRuler; } set { document.TextEditorProperties.ShowHorizontalRuler = value; OptionsChanged(); } } /// /// If true the vertical ruler is shown in the textarea /// [Category("Appearance")] [DefaultValue(true)] [Description("If true the vertical ruler is shown in the textarea")] public bool ShowVRuler { get { return document.TextEditorProperties.ShowVerticalRuler; } set { document.TextEditorProperties.ShowVerticalRuler = value; OptionsChanged(); } } /// /// The row in which the vertical ruler is displayed /// [Category("Appearance")] [DefaultValue(80)] [Description("The row in which the vertical ruler is displayed")] public int VRulerRow { get { return document.TextEditorProperties.VerticalRulerRow; } set { document.TextEditorProperties.VerticalRulerRow = value; OptionsChanged(); } } /// /// If true line numbers are shown in the textarea /// [Category("Appearance")] [DefaultValue(true)] [Description("If true line numbers are shown in the textarea")] public bool ShowLineNumbers { get { return document.TextEditorProperties.ShowLineNumbers; } set { document.TextEditorProperties.ShowLineNumbers = value; OptionsChanged(); } } /// /// If true invalid lines are marked in the textarea /// [Category("Appearance")] [DefaultValue(false)] [Description("If true invalid lines are marked in the textarea")] public bool ShowInvalidLines { get { return document.TextEditorProperties.ShowInvalidLines; } set { document.TextEditorProperties.ShowInvalidLines = value; OptionsChanged(); } } /// /// If true folding is enabled in the textarea /// [Category("Appearance")] [DefaultValue(true)] [Description("If true folding is enabled in the textarea")] public bool EnableFolding { get { return document.TextEditorProperties.EnableFolding; } set { document.TextEditorProperties.EnableFolding = value; OptionsChanged(); } } [Category("Appearance")] [DefaultValue(true)] [Description("If true matching brackets are highlighted")] public bool ShowMatchingBracket { get { return document.TextEditorProperties.ShowMatchingBracket; } set { document.TextEditorProperties.ShowMatchingBracket = value; OptionsChanged(); } } [Category("Appearance")] [DefaultValue(false)] [Description("If true the icon bar is displayed")] public bool IsIconBarVisible { get { return document.TextEditorProperties.IsIconBarVisible; } set { document.TextEditorProperties.IsIconBarVisible = value; OptionsChanged(); } } /// /// The width in spaces of a tab character /// [Category("Appearance")] [DefaultValue(4)] [Description("The width in spaces of a tab character")] public int TabIndent { get { return document.TextEditorProperties.TabIndent; } set { document.TextEditorProperties.TabIndent = value; OptionsChanged(); } } /// /// The line viewer style /// [Category("Appearance")] [DefaultValue(LineViewerStyle.None)] [Description("The line viewer style")] public LineViewerStyle LineViewerStyle { get { return document.TextEditorProperties.LineViewerStyle; } set { document.TextEditorProperties.LineViewerStyle = value; OptionsChanged(); } } /// /// The indent style /// [Category("Behavior")] [DefaultValue(IndentStyle.Smart)] [Description("The indent style")] public IndentStyle IndentStyle { get { return document.TextEditorProperties.IndentStyle; } set { document.TextEditorProperties.IndentStyle = value; OptionsChanged(); } } /// /// if true spaces are converted to tabs /// [Category("Behavior")] [DefaultValue(false)] [Description("Converts tabs to spaces while typing")] public bool ConvertTabsToSpaces { get { return document.TextEditorProperties.ConvertTabsToSpaces; } set { document.TextEditorProperties.ConvertTabsToSpaces = value; OptionsChanged(); } } /// /// if true spaces are converted to tabs /// [Category("Behavior")] [DefaultValue(false)] [Description("Hide the mouse cursor while typing")] public bool HideMouseCursor { get { return document.TextEditorProperties.HideMouseCursor; } set { document.TextEditorProperties.HideMouseCursor = value; OptionsChanged(); } } /// /// if true spaces are converted to tabs /// [Category("Behavior")] [DefaultValue(false)] [Description("Allows the caret to be placed beyond the end of line")] public bool AllowCaretBeyondEOL { get { return document.TextEditorProperties.AllowCaretBeyondEOL; } set { document.TextEditorProperties.AllowCaretBeyondEOL = value; OptionsChanged(); } } /// /// if true spaces are converted to tabs /// [Category("Behavior")] [DefaultValue(BracketMatchingStyle.After)] [Description("Specifies if the bracket matching should match the bracket before or after the caret.")] public BracketMatchingStyle BracketMatchingStyle { get { return document.TextEditorProperties.BracketMatchingStyle; } set { document.TextEditorProperties.BracketMatchingStyle = value; OptionsChanged(); } } /// /// The base font of the text area. No bold or italic fonts /// can be used because bold/italic is reserved for highlighting /// purposes. /// [Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Description("The base font of the text area. No bold or italic fonts can be used because bold/italic is reserved for highlighting purposes.")] public override Font Font { get { return document.TextEditorProperties.Font; } set { document.TextEditorProperties.Font = value; OptionsChanged(); } } #endregion public abstract TextAreaControl ActiveTextAreaControl { get; } protected TextEditorControlBase() { GenerateDefaultActions(); HighlightingManager.Manager.ReloadSyntaxHighlighting += new EventHandler(OnReloadHighlighting); } protected virtual void OnReloadHighlighting(object sender, EventArgs e) { if (Document.HighlightingStrategy != null) { try { Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(Document.HighlightingStrategy.Name); } catch (HighlightingDefinitionInvalidException ex) { MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } OptionsChanged(); } } public bool IsEditAction(Keys keyData) { return editactions.ContainsKey(keyData); } internal IEditAction GetEditAction(Keys keyData) { if (!IsEditAction(keyData)) { return null; } return (IEditAction)editactions[keyData]; } void GenerateDefaultActions() { editactions[Keys.Left] = new CaretLeft(); editactions[Keys.Left | Keys.Shift] = new ShiftCaretLeft(); editactions[Keys.Left | Keys.Control] = new WordLeft(); editactions[Keys.Left | Keys.Control | Keys.Shift] = new ShiftWordLeft(); editactions[Keys.Right] = new CaretRight(); editactions[Keys.Right | Keys.Shift] = new ShiftCaretRight(); editactions[Keys.Right | Keys.Control] = new WordRight(); editactions[Keys.Right | Keys.Control | Keys.Shift] = new ShiftWordRight(); editactions[Keys.Up] = new CaretUp(); editactions[Keys.Up | Keys.Shift] = new ShiftCaretUp(); editactions[Keys.Up | Keys.Control] = new ScrollLineUp(); editactions[Keys.Down] = new CaretDown(); editactions[Keys.Down | Keys.Shift] = new ShiftCaretDown(); editactions[Keys.Down | Keys.Control] = new ScrollLineDown(); editactions[Keys.Insert] = new ToggleEditMode(); editactions[Keys.Insert | Keys.Control] = new Copy(); editactions[Keys.Insert | Keys.Shift] = new Paste(); editactions[Keys.Delete] = new Delete(); editactions[Keys.Delete | Keys.Shift] = new Cut(); editactions[Keys.Home] = new Home(); editactions[Keys.Home | Keys.Shift] = new ShiftHome(); editactions[Keys.Home | Keys.Control] = new MoveToStart(); editactions[Keys.Home | Keys.Control | Keys.Shift] = new ShiftMoveToStart(); editactions[Keys.End] = new End(); editactions[Keys.End | Keys.Shift] = new ShiftEnd(); editactions[Keys.End | Keys.Control] = new MoveToEnd(); editactions[Keys.End | Keys.Control | Keys.Shift] = new ShiftMoveToEnd(); editactions[Keys.PageUp] = new MovePageUp(); editactions[Keys.PageUp | Keys.Shift] = new ShiftMovePageUp(); editactions[Keys.PageDown] = new MovePageDown(); editactions[Keys.PageDown | Keys.Shift] = new ShiftMovePageDown(); editactions[Keys.Return] = new Return(); editactions[Keys.Tab] = new Tab(); editactions[Keys.Tab | Keys.Shift] = new ShiftTab(); editactions[Keys.Back] = new Backspace(); editactions[Keys.Back | Keys.Shift] = new Backspace(); editactions[Keys.X | Keys.Control] = new Cut(); editactions[Keys.C | Keys.Control] = new Copy(); editactions[Keys.V | Keys.Control] = new Paste(); editactions[Keys.A | Keys.Control] = new SelectWholeDocument(); editactions[Keys.Escape] = new ClearAllSelections(); editactions[Keys.Divide | Keys.Control] = new ToggleComment(); editactions[Keys.OemQuestion | Keys.Control] = new ToggleComment(); editactions[Keys.Back | Keys.Alt] = new Actions.Undo(); editactions[Keys.Z | Keys.Control] = new Actions.Undo(); editactions[Keys.Y | Keys.Control] = new Redo(); editactions[Keys.Delete | Keys.Control] = new DeleteWord(); editactions[Keys.Back | Keys.Control] = new WordBackspace(); editactions[Keys.D | Keys.Control] = new DeleteLine(); editactions[Keys.D | Keys.Shift | Keys.Control] = new DeleteToLineEnd(); editactions[Keys.B | Keys.Control] = new GotoMatchingBrace(); editactions[Keys.F | Keys.Control] = new FindReplaceAction(); } /// /// Call this method before a long update operation this /// 'locks' the text area so that no screen update occurs. /// public virtual void BeginUpdate() { ++updateLevel; } /// /// Call this method to 'unlock' the text area. After this call /// screen update can occur. But no automatical refresh occurs you /// have to commit the updates in the queue. /// public virtual void EndUpdate() { Debug.Assert(updateLevel > 0); updateLevel = Math.Max(0, updateLevel - 1); } public void LoadFile(string fileName) { LoadFile(fileName, true, true); } /// /// Loads a file given by fileName /// /// The name of the file to open /// Automatically load the highlighting for the file /// Automatically detect file encoding and set Encoding property to the detected encoding. public void LoadFile(string fileName, bool autoLoadHighlighting, bool autodetectEncoding) { using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { LoadFile(fileName, fs, autoLoadHighlighting, autodetectEncoding); } } /// /// Loads a file from the specified stream. /// /// The name of the file to open. Used to find the correct highlighting strategy /// if autoLoadHighlighting is active, and sets the filename property to this value. /// The stream to actually load the file content from. /// Automatically load the highlighting for the file /// Automatically detect file encoding and set Encoding property to the detected encoding. public void LoadFile(string fileName, Stream stream, bool autoLoadHighlighting, bool autodetectEncoding) { if (stream == null) throw new ArgumentNullException("stream"); BeginUpdate(); document.TextContent = String.Empty; document.UndoStack.ClearAll(); document.BookmarkManager.Clear(); if (autoLoadHighlighting) { try { document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(fileName); } catch (HighlightingDefinitionInvalidException ex) { MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } if (autodetectEncoding) { Encoding encoding = this.Encoding; Document.TextContent = Util.FileReader.ReadFileContent(stream, ref encoding); this.Encoding = encoding; } else { using (StreamReader reader = new StreamReader(fileName, this.Encoding)) { Document.TextContent = reader.ReadToEnd(); } } this.FileName = fileName; OptionsChanged(); Document.UpdateQueue.Clear(); EndUpdate(); Refresh(); } /// /// Gets if the document can be saved with the current encoding without losing data. /// public bool CanSaveWithCurrentEncoding() { if (encoding == null || Util.FileReader.IsUnicode(encoding)) return true; // not a unicode codepage string text = document.TextContent; return encoding.GetString(encoding.GetBytes(text)) == text; } /// /// Saves the text editor content into the file. /// public void SaveFile(string fileName) { using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { SaveFile(fs); } this.FileName = fileName; } /// /// Saves the text editor content into the specified stream. /// Does not close the stream. /// public void SaveFile(Stream stream) { StreamWriter streamWriter = new StreamWriter(stream, this.Encoding ?? Encoding.UTF8); // save line per line to apply the LineTerminator to all lines // (otherwise we might save files with mixed-up line endings) foreach (LineSegment line in Document.LineSegmentCollection) { streamWriter.Write(Document.GetText(line.Offset, line.Length)); if (line.DelimiterLength > 0) { char charAfterLine = Document.GetCharAt(line.Offset + line.Length); if (charAfterLine != '\n' && charAfterLine != '\r') throw new InvalidOperationException("The document cannot be saved because it is corrupted."); // only save line terminator if the line has one streamWriter.Write(document.TextEditorProperties.LineTerminator); } } streamWriter.Flush(); } public abstract void OptionsChanged(); // Localization ISSUES // used in insight window public virtual string GetRangeDescription(int selectedItem, int itemCount) { StringBuilder sb=new StringBuilder(selectedItem.ToString()); sb.Append(" from "); sb.Append(itemCount.ToString()); return sb.ToString(); } /// /// Overwritten refresh method that does nothing if the control is in /// an update cycle. /// public override void Refresh() { if (IsInUpdate) { return; } base.Refresh(); } protected override void Dispose(bool disposing) { if (disposing) { HighlightingManager.Manager.ReloadSyntaxHighlighting -= new EventHandler(OnReloadHighlighting); document.HighlightingStrategy = null; document.UndoStack.TextEditorControl = null; } base.Dispose(disposing); } protected virtual void OnFileNameChanged(EventArgs e) { if (FileNameChanged != null) { FileNameChanged(this, e); } } public event EventHandler FileNameChanged; } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs ================================================ // // // // // $Revision: 3205 $ // using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor { /// /// This class paints the textarea. /// public class TextView : AbstractMargin, IDisposable { int fontHeight; //Hashtable charWitdh = new Hashtable(); //StringFormat measureStringFormat = (StringFormat)StringFormat.GenericTypographic.Clone(); BracketHighlight highlight; int physicalColumn = 0; // used for calculating physical column during paint public void Dispose() { measureCache.Clear(); //measureStringFormat.Dispose(); } public BracketHighlight Highlight { get { return highlight; } set { highlight = value; } } public int FirstPhysicalLine { get { return textArea.VirtualTop.Y / fontHeight; } } public int LineHeightRemainder { get { return textArea.VirtualTop.Y % fontHeight; } } /// Gets the first visible logical line. public int FirstVisibleLine { get { return textArea.Document.GetFirstLogicalLine(textArea.VirtualTop.Y / fontHeight); } set { if (FirstVisibleLine != value) { textArea.VirtualTop = new Point(textArea.VirtualTop.X, textArea.Document.GetVisibleLine(value) * fontHeight); } } } public int VisibleLineDrawingRemainder { get { return textArea.VirtualTop.Y % fontHeight; } } public int FontHeight { get { return fontHeight; } } public int VisibleLineCount { get { return 1 + DrawingPosition.Height / fontHeight; } } public int VisibleColumnCount { get { return (int)(DrawingPosition.Width / WideSpaceWidth) - 1; } } public TextView(TextArea textArea) : base(textArea) { base.Cursor = Cursors.IBeam; OptionsChanged(); } static int GetFontHeight(Font font) { int height1 = TextRenderer.MeasureText("_", font).Height; int height2 = (int)Math.Ceiling(font.GetHeight()); return Math.Max(height1, height2) + 1; } int spaceWidth; /// /// Gets the width of a space character. /// This value can be quite small in some fonts - consider using WideSpaceWidth instead. /// public int SpaceWidth { get { return spaceWidth; } } int wideSpaceWidth; /// /// Gets the width of a 'wide space' (=one quarter of a tab, if tab is set to 4 spaces). /// On monospaced fonts, this is the same value as spaceWidth. /// public int WideSpaceWidth { get { return wideSpaceWidth; } } Font lastFont; public void OptionsChanged() { this.lastFont = TextEditorProperties.FontContainer.RegularFont; this.fontHeight = GetFontHeight(lastFont); // use minimum width - in some fonts, space has no width but kerning is used instead // -> DivideByZeroException this.spaceWidth = Math.Max(GetWidth(' ', lastFont), 1); // tab should have the width of 4*'x' this.wideSpaceWidth = Math.Max(spaceWidth, GetWidth('x', lastFont)); } #region Paint functions public override void Paint(Graphics g, Rectangle rect) { if (rect.Width <= 0 || rect.Height <= 0) { return; } // Just to ensure that fontHeight and char widths are always correct... if (lastFont != TextEditorProperties.FontContainer.RegularFont) { OptionsChanged(); textArea.Invalidate(); } int horizontalDelta = textArea.VirtualTop.X; if (horizontalDelta > 0) { g.SetClip(this.DrawingPosition); } for (int y = 0; y < (DrawingPosition.Height + VisibleLineDrawingRemainder) / fontHeight + 1; ++y) { Rectangle lineRectangle = new Rectangle(DrawingPosition.X - horizontalDelta, DrawingPosition.Top + y * fontHeight - VisibleLineDrawingRemainder, DrawingPosition.Width + horizontalDelta, fontHeight); if (rect.IntersectsWith(lineRectangle)) { int fvl = textArea.Document.GetVisibleLine(FirstVisibleLine); int currentLine = textArea.Document.GetFirstLogicalLine(textArea.Document.GetVisibleLine(FirstVisibleLine) + y); PaintDocumentLine(g, currentLine, lineRectangle); } } DrawMarkerDraw(g); if (horizontalDelta > 0) { g.ResetClip(); } textArea.Caret.PaintCaret(g); } void PaintDocumentLine(Graphics g, int lineNumber, Rectangle lineRectangle) { Debug.Assert(lineNumber >= 0); Brush bgColorBrush = GetBgColorBrush(lineNumber); Brush backgroundBrush = textArea.Enabled ? bgColorBrush : SystemBrushes.InactiveBorder; if (lineNumber >= textArea.Document.TotalNumberOfLines) { g.FillRectangle(backgroundBrush, lineRectangle); if (TextEditorProperties.ShowInvalidLines) { DrawInvalidLineMarker(g, lineRectangle.Left, lineRectangle.Top); } if (TextEditorProperties.ShowVerticalRuler) { DrawVerticalRuler(g, lineRectangle); } // bgColorBrush.Dispose(); return; } int physicalXPos = lineRectangle.X; // there can't be a folding wich starts in an above line and ends here, because the line is a new one, // there must be a return before this line. int column = 0; physicalColumn = 0; if (TextEditorProperties.EnableFolding) { while (true) { List starts = textArea.Document.FoldingManager.GetFoldedFoldingsWithStartAfterColumn(lineNumber, column - 1); if (starts == null || starts.Count <= 0) { if (lineNumber < textArea.Document.TotalNumberOfLines) { physicalXPos = PaintLinePart(g, lineNumber, column, textArea.Document.GetLineSegment(lineNumber).Length, lineRectangle, physicalXPos); } break; } // search the first starting folding FoldMarker firstFolding = (FoldMarker)starts[0]; foreach (FoldMarker fm in starts) { if (fm.StartColumn < firstFolding.StartColumn) { firstFolding = fm; } } starts.Clear(); physicalXPos = PaintLinePart(g, lineNumber, column, firstFolding.StartColumn, lineRectangle, physicalXPos); column = firstFolding.EndColumn; lineNumber = firstFolding.EndLine; if (lineNumber >= textArea.Document.TotalNumberOfLines) { Debug.Assert(false, "Folding ends after document end"); break; } ColumnRange selectionRange2 = textArea.SelectionManager.GetSelectionAtLine(lineNumber); bool drawSelected = ColumnRange.WholeColumn.Equals(selectionRange2) || firstFolding.StartColumn >= selectionRange2.StartColumn && firstFolding.EndColumn <= selectionRange2.EndColumn; physicalXPos = PaintFoldingText(g, lineNumber, physicalXPos, lineRectangle, firstFolding.FoldText, drawSelected); } } else { physicalXPos = PaintLinePart(g, lineNumber, 0, textArea.Document.GetLineSegment(lineNumber).Length, lineRectangle, physicalXPos); } if (lineNumber < textArea.Document.TotalNumberOfLines) { // Paint things after end of line ColumnRange selectionRange = textArea.SelectionManager.GetSelectionAtLine(lineNumber); LineSegment currentLine = textArea.Document.GetLineSegment(lineNumber); HighlightColor selectionColor = textArea.Document.HighlightingStrategy.GetColorFor("Selection"); bool selectionBeyondEOL = selectionRange.EndColumn > currentLine.Length || ColumnRange.WholeColumn.Equals(selectionRange); if (TextEditorProperties.ShowEOLMarker) { HighlightColor eolMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("EOLMarkers"); physicalXPos += DrawEOLMarker(g, eolMarkerColor.Color, selectionBeyondEOL ? bgColorBrush : backgroundBrush, physicalXPos, lineRectangle.Y); } else { if (selectionBeyondEOL) { g.FillRectangle(BrushRegistry.GetBrush(selectionColor.BackgroundColor), new RectangleF(physicalXPos, lineRectangle.Y, WideSpaceWidth, lineRectangle.Height)); physicalXPos += WideSpaceWidth; } } Brush fillBrush = selectionBeyondEOL && TextEditorProperties.AllowCaretBeyondEOL ? bgColorBrush : backgroundBrush; g.FillRectangle(fillBrush, new RectangleF(physicalXPos, lineRectangle.Y, lineRectangle.Width - physicalXPos + lineRectangle.X, lineRectangle.Height)); } if (TextEditorProperties.ShowVerticalRuler) { DrawVerticalRuler(g, lineRectangle); } // bgColorBrush.Dispose(); } bool DrawLineMarkerAtLine(int lineNumber) { return lineNumber == base.textArea.Caret.Line && textArea.MotherTextAreaControl.TextEditorProperties.LineViewerStyle == LineViewerStyle.FullRow; } Brush GetBgColorBrush(int lineNumber) { if (DrawLineMarkerAtLine(lineNumber)) { HighlightColor caretLine = textArea.Document.HighlightingStrategy.GetColorFor("CaretMarker"); return BrushRegistry.GetBrush(caretLine.Color); } HighlightColor background = textArea.Document.HighlightingStrategy.GetColorFor("Default"); Color bgColor = background.BackgroundColor; return BrushRegistry.GetBrush(bgColor); } const int additionalFoldTextSize = 1; int PaintFoldingText(Graphics g, int lineNumber, int physicalXPos, Rectangle lineRectangle, string text, bool drawSelected) { // TODO: get font and color from the highlighting file HighlightColor selectionColor = textArea.Document.HighlightingStrategy.GetColorFor("Selection"); Brush bgColorBrush = drawSelected ? BrushRegistry.GetBrush(selectionColor.BackgroundColor) : GetBgColorBrush(lineNumber); Brush backgroundBrush = textArea.Enabled ? bgColorBrush : SystemBrushes.InactiveBorder; Font font = textArea.TextEditorProperties.FontContainer.RegularFont; int wordWidth = MeasureStringWidth(g, text, font) + additionalFoldTextSize; Rectangle rect = new Rectangle(physicalXPos, lineRectangle.Y, wordWidth, lineRectangle.Height - 1); g.FillRectangle(backgroundBrush, rect); physicalColumn += text.Length; DrawString(g, text, font, drawSelected ? selectionColor.Color : Color.Gray, rect.X + 1, rect.Y); g.DrawRectangle(BrushRegistry.GetPen(drawSelected ? Color.DarkGray : Color.Gray), rect.X, rect.Y, rect.Width, rect.Height); return physicalXPos + wordWidth + 1; } struct MarkerToDraw { internal TextMarker marker; internal RectangleF drawingRect; public MarkerToDraw(TextMarker marker, RectangleF drawingRect) { this.marker = marker; this.drawingRect = drawingRect; } } List markersToDraw = new List(); void DrawMarker(Graphics g, TextMarker marker, RectangleF drawingRect) { // draw markers later so they can overdraw the following text markersToDraw.Add(new MarkerToDraw(marker, drawingRect)); } void DrawMarkerDraw(Graphics g) { foreach (MarkerToDraw m in markersToDraw) { TextMarker marker = m.marker; RectangleF drawingRect = m.drawingRect; float drawYPos = drawingRect.Bottom - 1; switch (marker.TextMarkerType) { case TextMarkerType.Underlined: g.DrawLine(BrushRegistry.GetPen(marker.Color), drawingRect.X, drawYPos, drawingRect.Right, drawYPos); break; case TextMarkerType.WaveLine: int reminder = ((int)drawingRect.X) % 6; for (float i = (int)drawingRect.X - reminder; i < drawingRect.Right; i += 6) { g.DrawLine(BrushRegistry.GetPen(marker.Color), i, drawYPos + 3 - 4, i + 3, drawYPos + 1 - 4); if (i + 3 < drawingRect.Right) { g.DrawLine(BrushRegistry.GetPen(marker.Color), i + 3, drawYPos + 1 - 4, i + 6, drawYPos + 3 - 4); } } break; case TextMarkerType.SolidBlock: g.FillRectangle(BrushRegistry.GetBrush(marker.Color), drawingRect); break; } } markersToDraw.Clear(); } /// /// Get the marker brush (for solid block markers) at a given position. /// /// The offset. /// The length. /// All markers that have been found. /// The Brush or null when no marker was found. Brush GetMarkerBrushAt(int offset, int length, ref Color foreColor, out IList markers) { markers = Document.MarkerStrategy.GetMarkers(offset, length); foreach (TextMarker marker in markers) { if (marker.TextMarkerType == TextMarkerType.SolidBlock) { if (marker.OverrideForeColor) { foreColor = marker.ForeColor; } return BrushRegistry.GetBrush(marker.Color); } } return null; } int PaintLinePart(Graphics g, int lineNumber, int startColumn, int endColumn, Rectangle lineRectangle, int physicalXPos) { bool drawLineMarker = DrawLineMarkerAtLine(lineNumber); Brush backgroundBrush = textArea.Enabled ? GetBgColorBrush(lineNumber) : SystemBrushes.InactiveBorder; HighlightColor selectionColor = textArea.Document.HighlightingStrategy.GetColorFor("Selection"); ColumnRange selectionRange = textArea.SelectionManager.GetSelectionAtLine(lineNumber); HighlightColor tabMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("TabMarkers"); HighlightColor spaceMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("SpaceMarkers"); LineSegment currentLine = textArea.Document.GetLineSegment(lineNumber); Brush selectionBackgroundBrush = BrushRegistry.GetBrush(selectionColor.BackgroundColor); if (currentLine.Words == null) { return physicalXPos; } int currentWordOffset = 0; // we cannot use currentWord.Offset because it is not set on space words TextWord currentWord; TextWord nextCurrentWord = null; FontContainer fontContainer = TextEditorProperties.FontContainer; for (int wordIdx = 0; wordIdx < currentLine.Words.Count; wordIdx++) { currentWord = currentLine.Words[wordIdx]; if (currentWordOffset < startColumn) { // TODO: maybe we need to split at startColumn when we support fold markers // inside words currentWordOffset += currentWord.Length; continue; } repeatDrawCurrentWord: //physicalXPos += 10; // leave room between drawn words - useful for debugging the drawing code if (currentWordOffset >= endColumn || physicalXPos >= lineRectangle.Right) { break; } int currentWordEndOffset = currentWordOffset + currentWord.Length - 1; TextWordType currentWordType = currentWord.Type; IList markers; Color wordForeColor; if (currentWordType == TextWordType.Space) wordForeColor = spaceMarkerColor.Color; else if (currentWordType == TextWordType.Tab) wordForeColor = tabMarkerColor.Color; else wordForeColor = currentWord.Color; Brush wordBackBrush = GetMarkerBrushAt(currentLine.Offset + currentWordOffset, currentWord.Length, ref wordForeColor, out markers); // It is possible that we have to split the current word because a marker/the selection begins/ends inside it if (currentWord.Length > 1) { int splitPos = int.MaxValue; if (highlight != null) { // split both before and after highlight if (highlight.OpenBrace.Y == lineNumber) { if (highlight.OpenBrace.X >= currentWordOffset && highlight.OpenBrace.X <= currentWordEndOffset) { splitPos = Math.Min(splitPos, highlight.OpenBrace.X - currentWordOffset); } } if (highlight.CloseBrace.Y == lineNumber) { if (highlight.CloseBrace.X >= currentWordOffset && highlight.CloseBrace.X <= currentWordEndOffset) { splitPos = Math.Min(splitPos, highlight.CloseBrace.X - currentWordOffset); } } if (splitPos == 0) { splitPos = 1; // split after highlight } } if (endColumn < currentWordEndOffset) { // split when endColumn is reached splitPos = Math.Min(splitPos, endColumn - currentWordOffset); } if (selectionRange.StartColumn > currentWordOffset && selectionRange.StartColumn <= currentWordEndOffset) { splitPos = Math.Min(splitPos, selectionRange.StartColumn - currentWordOffset); } else if (selectionRange.EndColumn > currentWordOffset && selectionRange.EndColumn <= currentWordEndOffset) { splitPos = Math.Min(splitPos, selectionRange.EndColumn - currentWordOffset); } foreach (TextMarker marker in markers) { int markerColumn = marker.Offset - currentLine.Offset; int markerEndColumn = marker.EndOffset - currentLine.Offset + 1; // make end offset exclusive if (markerColumn > currentWordOffset && markerColumn <= currentWordEndOffset) { splitPos = Math.Min(splitPos, markerColumn - currentWordOffset); } else if (markerEndColumn > currentWordOffset && markerEndColumn <= currentWordEndOffset) { splitPos = Math.Min(splitPos, markerEndColumn - currentWordOffset); } } if (splitPos != int.MaxValue) { if (nextCurrentWord != null) throw new ApplicationException("split part invalid: first part cannot be splitted further"); nextCurrentWord = TextWord.Split(ref currentWord, splitPos); goto repeatDrawCurrentWord; // get markers for first word part } } // get colors from selection status: if (ColumnRange.WholeColumn.Equals(selectionRange) || (selectionRange.StartColumn <= currentWordOffset && selectionRange.EndColumn > currentWordEndOffset)) { // word is completely selected wordBackBrush = selectionBackgroundBrush; if (selectionColor.HasForeground) { wordForeColor = selectionColor.Color; } } else if (drawLineMarker) { wordBackBrush = backgroundBrush; } if (wordBackBrush == null) { // use default background if no other background is set if (currentWord.SyntaxColor != null && currentWord.SyntaxColor.HasBackground) wordBackBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor); else wordBackBrush = backgroundBrush; } RectangleF wordRectangle; if (currentWord.Type == TextWordType.Space) { ++physicalColumn; wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, SpaceWidth, lineRectangle.Height); g.FillRectangle(wordBackBrush, wordRectangle); if (TextEditorProperties.ShowSpaces) { DrawSpaceMarker(g, wordForeColor, physicalXPos, lineRectangle.Y); } physicalXPos += SpaceWidth; } else if (currentWord.Type == TextWordType.Tab) { physicalColumn += TextEditorProperties.TabIndent; physicalColumn = (physicalColumn / TextEditorProperties.TabIndent) * TextEditorProperties.TabIndent; // go to next tabstop int physicalTabEnd = ((physicalXPos + MinTabWidth - lineRectangle.X) / WideSpaceWidth / TextEditorProperties.TabIndent) * WideSpaceWidth * TextEditorProperties.TabIndent + lineRectangle.X; physicalTabEnd += WideSpaceWidth * TextEditorProperties.TabIndent; wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, physicalTabEnd - physicalXPos, lineRectangle.Height); g.FillRectangle(wordBackBrush, wordRectangle); if (TextEditorProperties.ShowTabs) { DrawTabMarker(g, wordForeColor, physicalXPos, lineRectangle.Y); } physicalXPos = physicalTabEnd; } else { int wordWidth = DrawDocumentWord(g, currentWord.Word, new Point(physicalXPos, lineRectangle.Y), currentWord.GetFont(fontContainer), wordForeColor, wordBackBrush); wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, wordWidth, lineRectangle.Height); physicalXPos += wordWidth; } foreach (TextMarker marker in markers) { if (marker.TextMarkerType != TextMarkerType.SolidBlock) { DrawMarker(g, marker, wordRectangle); } } // draw bracket highlight if (highlight != null) { if (highlight.OpenBrace.Y == lineNumber && highlight.OpenBrace.X == currentWordOffset || highlight.CloseBrace.Y == lineNumber && highlight.CloseBrace.X == currentWordOffset) { DrawBracketHighlight(g, new Rectangle((int)wordRectangle.X, lineRectangle.Y, (int)wordRectangle.Width - 1, lineRectangle.Height - 1)); } } currentWordOffset += currentWord.Length; if (nextCurrentWord != null) { currentWord = nextCurrentWord; nextCurrentWord = null; goto repeatDrawCurrentWord; } } if (physicalXPos < lineRectangle.Right && endColumn >= currentLine.Length) { // draw markers at line end IList markers = Document.MarkerStrategy.GetMarkers(currentLine.Offset + currentLine.Length); foreach (TextMarker marker in markers) { if (marker.TextMarkerType != TextMarkerType.SolidBlock) { DrawMarker(g, marker, new RectangleF(physicalXPos, lineRectangle.Y, WideSpaceWidth, lineRectangle.Height)); } } } return physicalXPos; } int DrawDocumentWord(Graphics g, string word, Point position, Font font, Color foreColor, Brush backBrush) { if (word == null || word.Length == 0) { return 0; } if (word.Length > MaximumWordLength) { int width = 0; for (int i = 0; i < word.Length; i += MaximumWordLength) { Point pos = position; pos.X += width; if (i + MaximumWordLength < word.Length) width += DrawDocumentWord(g, word.Substring(i, MaximumWordLength), pos, font, foreColor, backBrush); else width += DrawDocumentWord(g, word.Substring(i, word.Length - i), pos, font, foreColor, backBrush); } return width; } int wordWidth = MeasureStringWidth(g, word, font); //num = ++num % 3; g.FillRectangle(backBrush, //num == 0 ? Brushes.LightBlue : num == 1 ? Brushes.LightGreen : Brushes.Yellow, new RectangleF(position.X, position.Y, wordWidth + 1, FontHeight)); DrawString(g, word, font, foreColor, position.X, position.Y); return wordWidth; } struct WordFontPair { string word; Font font; public WordFontPair(string word, Font font) { this.word = word; this.font = font; } public override bool Equals(object obj) { WordFontPair myWordFontPair = (WordFontPair)obj; if (!word.Equals(myWordFontPair.word)) return false; return font.Equals(myWordFontPair.font); } public override int GetHashCode() { return word.GetHashCode() ^ font.GetHashCode(); } } Dictionary measureCache = new Dictionary(); // split words after 1000 characters. Fixes GDI+ crash on very longs words, for example // a 100 KB Base64-file without any line breaks. const int MaximumWordLength = 1000; const int MaximumCacheSize = 2000; int MeasureStringWidth(Graphics g, string word, Font font) { int width; if (word == null || word.Length == 0) return 0; if (word.Length > MaximumWordLength) { width = 0; for (int i = 0; i < word.Length; i += MaximumWordLength) { if (i + MaximumWordLength < word.Length) width += MeasureStringWidth(g, word.Substring(i, MaximumWordLength), font); else width += MeasureStringWidth(g, word.Substring(i, word.Length - i), font); } return width; } if (measureCache.TryGetValue(new WordFontPair(word, font), out width)) { return width; } if (measureCache.Count > MaximumCacheSize) { measureCache.Clear(); } // This code here provides better results than MeasureString! // Example line that is measured wrong: // txt.GetPositionFromCharIndex(txt.SelectionStart) // (Verdana 10, highlighting makes GetP... bold) -> note the space between 'x' and '(' // this also fixes "jumping" characters when selecting in non-monospace fonts // [...] // Replaced GDI+ measurement with GDI measurement: faster and even more exact width = TextRenderer.MeasureText(g, word, font, new Size(short.MaxValue, short.MaxValue), textFormatFlags).Width; measureCache.Add(new WordFontPair(word, font), width); return width; } // Important: Some flags combinations work on WinXP, but not on Win2000. // Make sure to test changes here on all operating systems. const TextFormatFlags textFormatFlags = TextFormatFlags.NoPadding | TextFormatFlags.NoPrefix | TextFormatFlags.PreserveGraphicsClipping; #endregion #region Conversion Functions Dictionary> fontBoundCharWidth = new Dictionary>(); public int GetWidth(char ch, Font font) { if (!fontBoundCharWidth.ContainsKey(font)) { fontBoundCharWidth.Add(font, new Dictionary()); } if (!fontBoundCharWidth[font].ContainsKey(ch)) { using (Graphics g = textArea.CreateGraphics()) { return GetWidth(g, ch, font); } } return fontBoundCharWidth[font][ch]; } public int GetWidth(Graphics g, char ch, Font font) { if (!fontBoundCharWidth.ContainsKey(font)) { fontBoundCharWidth.Add(font, new Dictionary()); } if (!fontBoundCharWidth[font].ContainsKey(ch)) { //Console.WriteLine("Calculate character width: " + ch); fontBoundCharWidth[font].Add(ch, MeasureStringWidth(g, ch.ToString(), font)); } return fontBoundCharWidth[font][ch]; } public int GetVisualColumn(int logicalLine, int logicalColumn) { int column = 0; using (Graphics g = textArea.CreateGraphics()) { CountColumns(ref column, 0, logicalColumn, logicalLine, g); } return column; } public int GetVisualColumnFast(LineSegment line, int logicalColumn) { int lineOffset = line.Offset; int tabIndent = Document.TextEditorProperties.TabIndent; int guessedColumn = 0; for (int i = 0; i < logicalColumn; ++i) { char ch; if (i >= line.Length) { ch = ' '; } else { ch = Document.GetCharAt(lineOffset + i); } switch (ch) { case '\t': guessedColumn += tabIndent; guessedColumn = (guessedColumn / tabIndent) * tabIndent; break; default: ++guessedColumn; break; } } return guessedColumn; } /// /// returns line/column for a visual point position /// public TextLocation GetLogicalPosition(Point mousePosition) { FoldMarker dummy; return GetLogicalColumn(GetLogicalLine(mousePosition.Y), mousePosition.X, out dummy); } /// /// returns line/column for a visual point position /// public TextLocation GetLogicalPosition(int visualPosX, int visualPosY) { FoldMarker dummy; return GetLogicalColumn(GetLogicalLine(visualPosY), visualPosX, out dummy); } /// /// returns line/column for a visual point position /// public FoldMarker GetFoldMarkerFromPosition(int visualPosX, int visualPosY) { FoldMarker foldMarker; GetLogicalColumn(GetLogicalLine(visualPosY), visualPosX, out foldMarker); return foldMarker; } /// /// returns logical line number for a visual point /// public int GetLogicalLine(int visualPosY) { int clickedVisualLine = Math.Max(0, (visualPosY + this.textArea.VirtualTop.Y) / fontHeight); return Document.GetFirstLogicalLine(clickedVisualLine); } internal TextLocation GetLogicalColumn(int lineNumber, int visualPosX, out FoldMarker inFoldMarker) { visualPosX += textArea.VirtualTop.X; inFoldMarker = null; if (lineNumber >= Document.TotalNumberOfLines) { return new TextLocation((int)(visualPosX / WideSpaceWidth), lineNumber); } if (visualPosX <= 0) { return new TextLocation(0, lineNumber); } int start = 0; // column int posX = 0; // visual position int result; using (Graphics g = textArea.CreateGraphics()) { do { LineSegment line = Document.GetLineSegment(lineNumber); FoldMarker nextFolding = FindNextFoldedFoldingOnLineAfterColumn(lineNumber, start-1); int end = nextFolding != null ? nextFolding.StartColumn : int.MaxValue; result = GetLogicalColumnInternal(g, line, start, end, ref posX, visualPosX); if (result < 0) { // reached fold marker lineNumber = nextFolding.EndLine; start = nextFolding.EndColumn; int newPosX = posX + 1 + MeasureStringWidth(g, nextFolding.FoldText, TextEditorProperties.FontContainer.RegularFont); if (newPosX >= visualPosX) { inFoldMarker = nextFolding; if (IsNearerToAThanB(visualPosX, posX, newPosX)) return new TextLocation(nextFolding.StartColumn, nextFolding.StartLine); else return new TextLocation(nextFolding.EndColumn, nextFolding.EndLine); } posX = newPosX; } } while (result < 0); } return new TextLocation(result, lineNumber); } int GetLogicalColumnInternal(Graphics g, LineSegment line, int start, int end, ref int drawingPos, int targetVisualPosX) { if (start == end) return -1; Debug.Assert(start < end); Debug.Assert(drawingPos < targetVisualPosX); int tabIndent = Document.TextEditorProperties.TabIndent; /*float spaceWidth = SpaceWidth; float drawingPos = 0; LineSegment currentLine = Document.GetLineSegment(logicalLine); List words = currentLine.Words; if (words == null) return 0; int wordCount = words.Count; int wordOffset = 0; FontContainer fontContainer = TextEditorProperties.FontContainer; */ FontContainer fontContainer = TextEditorProperties.FontContainer; List words = line.Words; if (words == null) return 0; int wordOffset = 0; for (int i = 0; i < words.Count; i++) { TextWord word = words[i]; if (wordOffset >= end) { return -1; } if (wordOffset + word.Length >= start) { int newDrawingPos; switch (word.Type) { case TextWordType.Space: newDrawingPos = drawingPos + spaceWidth; if (newDrawingPos >= targetVisualPosX) return IsNearerToAThanB(targetVisualPosX, drawingPos, newDrawingPos) ? wordOffset : wordOffset+1; break; case TextWordType.Tab: // go to next tab position drawingPos = (int)((drawingPos + MinTabWidth) / tabIndent / WideSpaceWidth) * tabIndent * WideSpaceWidth; newDrawingPos = drawingPos + tabIndent * WideSpaceWidth; if (newDrawingPos >= targetVisualPosX) return IsNearerToAThanB(targetVisualPosX, drawingPos, newDrawingPos) ? wordOffset : wordOffset+1; break; case TextWordType.Word: int wordStart = Math.Max(wordOffset, start); int wordLength = Math.Min(wordOffset + word.Length, end) - wordStart; string text = Document.GetText(line.Offset + wordStart, wordLength); Font font = word.GetFont(fontContainer) ?? fontContainer.RegularFont; newDrawingPos = drawingPos + MeasureStringWidth(g, text, font); if (newDrawingPos >= targetVisualPosX) { for (int j = 0; j < text.Length; j++) { newDrawingPos = drawingPos + MeasureStringWidth(g, text[j].ToString(), font); if (newDrawingPos >= targetVisualPosX) { if (IsNearerToAThanB(targetVisualPosX, drawingPos, newDrawingPos)) return wordStart + j; else return wordStart + j + 1; } drawingPos = newDrawingPos; } return wordStart + text.Length; } break; default: throw new NotSupportedException(); } drawingPos = newDrawingPos; } wordOffset += word.Length; } return wordOffset; } static bool IsNearerToAThanB(int num, int a, int b) { return Math.Abs(a - num) < Math.Abs(b - num); } FoldMarker FindNextFoldedFoldingOnLineAfterColumn(int lineNumber, int column) { List list = Document.FoldingManager.GetFoldedFoldingsWithStartAfterColumn(lineNumber, column); if (list.Count != 0) return list[0]; else return null; } const int MinTabWidth = 4; float CountColumns(ref int column, int start, int end, int logicalLine, Graphics g) { if (start > end) throw new ArgumentException("start > end"); if (start == end) return 0; float spaceWidth = SpaceWidth; float drawingPos = 0; int tabIndent = Document.TextEditorProperties.TabIndent; LineSegment currentLine = Document.GetLineSegment(logicalLine); List words = currentLine.Words; if (words == null) return 0; int wordCount = words.Count; int wordOffset = 0; FontContainer fontContainer = TextEditorProperties.FontContainer; for (int i = 0; i < wordCount; i++) { TextWord word = words[i]; if (wordOffset >= end) break; if (wordOffset + word.Length >= start) { switch (word.Type) { case TextWordType.Space: drawingPos += spaceWidth; break; case TextWordType.Tab: // go to next tab position drawingPos = (int)((drawingPos + MinTabWidth) / tabIndent / WideSpaceWidth) * tabIndent * WideSpaceWidth; drawingPos += tabIndent * WideSpaceWidth; break; case TextWordType.Word: int wordStart = Math.Max(wordOffset, start); int wordLength = Math.Min(wordOffset + word.Length, end) - wordStart; string text = Document.GetText(currentLine.Offset + wordStart, wordLength); drawingPos += MeasureStringWidth(g, text, word.GetFont(fontContainer) ?? fontContainer.RegularFont); break; } } wordOffset += word.Length; } for (int j = currentLine.Length; j < end; j++) { drawingPos += WideSpaceWidth; } // add one pixel in column calculation to account for floating point calculation errors column += (int)((drawingPos + 1) / WideSpaceWidth); /* OLD Code (does not work for fonts like Verdana) for (int j = start; j < end; ++j) { char ch; if (j >= line.Length) { ch = ' '; } else { ch = Document.GetCharAt(line.Offset + j); } switch (ch) { case '\t': int oldColumn = column; column += tabIndent; column = (column / tabIndent) * tabIndent; drawingPos += (column - oldColumn) * spaceWidth; break; default: ++column; TextWord word = line.GetWord(j); if (word == null || word.Font == null) { drawingPos += GetWidth(ch, TextEditorProperties.Font); } else { drawingPos += GetWidth(ch, word.Font); } break; } } //*/ return drawingPos; } public int GetDrawingXPos(int logicalLine, int logicalColumn) { List foldings = Document.FoldingManager.GetTopLevelFoldedFoldings(); int i; FoldMarker f = null; // search the last folding that's interresting for (i = foldings.Count - 1; i >= 0; --i) { f = foldings[i]; if (f.StartLine < logicalLine || f.StartLine == logicalLine && f.StartColumn < logicalColumn) { break; } FoldMarker f2 = foldings[i / 2]; if (f2.StartLine > logicalLine || f2.StartLine == logicalLine && f2.StartColumn >= logicalColumn) { i /= 2; } } int lastFolding = 0; int firstFolding = 0; int column = 0; int tabIndent = Document.TextEditorProperties.TabIndent; float drawingPos; Graphics g = textArea.CreateGraphics(); // if no folding is interresting if (f == null || !(f.StartLine < logicalLine || f.StartLine == logicalLine && f.StartColumn < logicalColumn)) { drawingPos = CountColumns(ref column, 0, logicalColumn, logicalLine, g); return (int)(drawingPos - textArea.VirtualTop.X); } // if logicalLine/logicalColumn is in folding if (f.EndLine > logicalLine || f.EndLine == logicalLine && f.EndColumn > logicalColumn) { logicalColumn = f.StartColumn; logicalLine = f.StartLine; --i; } lastFolding = i; // search backwards until a new visible line is reched for (; i >= 0; --i) { f = (FoldMarker)foldings[i]; if (f.EndLine < logicalLine) { // reached the begin of a new visible line break; } } firstFolding = i + 1; if (lastFolding < firstFolding) { drawingPos = CountColumns(ref column, 0, logicalColumn, logicalLine, g); return (int)(drawingPos - textArea.VirtualTop.X); } int foldEnd = 0; drawingPos = 0; for (i = firstFolding; i <= lastFolding; ++i) { f = foldings[i]; drawingPos += CountColumns(ref column, foldEnd, f.StartColumn, f.StartLine, g); foldEnd = f.EndColumn; column += f.FoldText.Length; drawingPos += additionalFoldTextSize; drawingPos += MeasureStringWidth(g, f.FoldText, TextEditorProperties.FontContainer.RegularFont); } drawingPos += CountColumns(ref column, foldEnd, logicalColumn, logicalLine, g); g.Dispose(); return (int)(drawingPos - textArea.VirtualTop.X); } #endregion #region DrawHelper functions void DrawBracketHighlight(Graphics g, Rectangle rect) { g.FillRectangle(BrushRegistry.GetBrush(Color.FromArgb(50, 0, 0, 255)), rect); g.DrawRectangle(Pens.Blue, rect); } void DrawString(Graphics g, string text, Font font, Color color, int x, int y) { TextRenderer.DrawText(g, text, font, new Point(x, y), color, textFormatFlags); } void DrawInvalidLineMarker(Graphics g, int x, int y) { HighlightColor invalidLinesColor = textArea.Document.HighlightingStrategy.GetColorFor("InvalidLines"); DrawString(g, "~", invalidLinesColor.GetFont(TextEditorProperties.FontContainer), invalidLinesColor.Color, x, y); } void DrawSpaceMarker(Graphics g, Color color, int x, int y) { HighlightColor spaceMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("SpaceMarkers"); DrawString(g, "\u00B7", spaceMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y); } void DrawTabMarker(Graphics g, Color color, int x, int y) { HighlightColor tabMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("TabMarkers"); DrawString(g, "\u00BB", tabMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y); } int DrawEOLMarker(Graphics g, Color color, Brush backBrush, int x, int y) { HighlightColor eolMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("EOLMarkers"); int width = GetWidth('\u00B6', eolMarkerColor.GetFont(TextEditorProperties.FontContainer)); g.FillRectangle(backBrush, new RectangleF(x, y, width, fontHeight)); DrawString(g, "\u00B6", eolMarkerColor.GetFont(TextEditorProperties.FontContainer), color, x, y); return width; } void DrawVerticalRuler(Graphics g, Rectangle lineRectangle) { int xpos = WideSpaceWidth * TextEditorProperties.VerticalRulerRow - textArea.VirtualTop.X; if (xpos <= 0) { return; } HighlightColor vRulerColor = textArea.Document.HighlightingStrategy.GetColorFor("VRuler"); g.DrawLine(BrushRegistry.GetPen(vRulerColor.Color), drawingPosition.Left + xpos, lineRectangle.Top, drawingPosition.Left + xpos, lineRectangle.Bottom); } #endregion } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Gui/ToolTipRequestEventArgs.cs ================================================ // // // // // $Revision: 2659 $ // using System; using System.Drawing; namespace ICSharpCode.TextEditor { public delegate void ToolTipRequestEventHandler(object sender, ToolTipRequestEventArgs e); public class ToolTipRequestEventArgs { Point mousePosition; TextLocation logicalPosition; bool inDocument; public Point MousePosition { get { return mousePosition; } } public TextLocation LogicalPosition { get { return logicalPosition; } } public bool InDocument { get { return inDocument; } } /// /// Gets if some client handling the event has already shown a tool tip. /// public bool ToolTipShown { get { return toolTipText != null; } } internal string toolTipText; public void ShowToolTip(string text) { toolTipText = text; } public ToolTipRequestEventArgs(Point mousePosition, TextLocation logicalPosition, bool inDocument) { this.mousePosition = mousePosition; this.logicalPosition = logicalPosition; this.inDocument = inDocument; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Undo/IUndoableOperation.cs ================================================ // // // // // $Revision: 915 $ // namespace ICSharpCode.TextEditor.Undo { /// /// This Interface describes a the basic Undo/Redo operation /// all Undo Operations must implement this interface. /// public interface IUndoableOperation { /// /// Undo the last operation /// void Undo(); /// /// Redo the last operation /// void Redo(); } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Undo/UndoQueue.cs ================================================ // // // // // $Revision: 2161 $ // using System; using System.Collections.Generic; using System.Diagnostics; namespace ICSharpCode.TextEditor.Undo { /// /// This class stacks the last x operations from the undostack and makes /// one undo/redo operation from it. /// internal sealed class UndoQueue : IUndoableOperation { List undolist = new List(); /// /// public UndoQueue(Stack stack, int numops) { if (stack == null) { throw new ArgumentNullException("stack"); } Debug.Assert(numops > 0 , "ICSharpCode.TextEditor.Undo.UndoQueue : numops should be > 0"); if (numops > stack.Count) { numops = stack.Count; } for (int i = 0; i < numops; ++i) { undolist.Add(stack.Pop()); } } public void Undo() { for (int i = 0; i < undolist.Count; ++i) { undolist[i].Undo(); } } public void Redo() { for (int i = undolist.Count - 1 ; i >= 0 ; --i) { undolist[i].Redo(); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Undo/UndoStack.cs ================================================ // // // // // $Revision: 2827 $ // using System; using System.Collections.Generic; using System.Drawing; namespace ICSharpCode.TextEditor.Undo { /// /// This class implements an undo stack /// public class UndoStack { Stack undostack = new Stack(); Stack redostack = new Stack(); public TextEditorControlBase TextEditorControl = null; /// /// public event EventHandler ActionUndone; /// /// public event EventHandler ActionRedone; /// /// Gets/Sets if changes to the document are protocolled by the undo stack. /// Used internally to disable the undo stack temporarily while undoing an action. /// internal bool AcceptChanges = true; /// /// Gets if there are actions on the undo stack. /// public bool CanUndo { get { return undostack.Count > 0; } } /// /// Gets if there are actions on the redo stack. /// public bool CanRedo { get { return redostack.Count > 0; } } /// /// Gets the number of actions on the undo stack. /// public int UndoItemCount { get { return undostack.Count; } } /// /// Gets the number of actions on the redo stack. /// public int RedoItemCount { get { return redostack.Count; } } int undoGroupDepth; int actionCountInUndoGroup; public void StartUndoGroup() { if (undoGroupDepth == 0) { actionCountInUndoGroup = 0; } undoGroupDepth++; //Util.LoggingService.Debug("Open undo group (new depth=" + undoGroupDepth + ")"); } public void EndUndoGroup() { if (undoGroupDepth == 0) throw new InvalidOperationException("There are no open undo groups"); undoGroupDepth--; //Util.LoggingService.Debug("Close undo group (new depth=" + undoGroupDepth + ")"); if (undoGroupDepth == 0 && actionCountInUndoGroup > 1) { undostack.Push(new UndoQueue(undostack, actionCountInUndoGroup)); } } public void AssertNoUndoGroupOpen() { if (undoGroupDepth != 0) { undoGroupDepth = 0; throw new InvalidOperationException("No undo group should be open at this point"); } } /// /// Call this method to undo the last operation on the stack /// public void Undo() { AssertNoUndoGroupOpen(); if (undostack.Count > 0) { IUndoableOperation uedit = (IUndoableOperation)undostack.Pop(); redostack.Push(uedit); uedit.Undo(); OnActionUndone(); } } /// /// Call this method to redo the last undone operation /// public void Redo() { AssertNoUndoGroupOpen(); if (redostack.Count > 0) { IUndoableOperation uedit = (IUndoableOperation)redostack.Pop(); undostack.Push(uedit); uedit.Redo(); OnActionRedone(); } } /// /// Call this method to push an UndoableOperation on the undostack, the redostack /// will be cleared, if you use this method. /// public void Push(IUndoableOperation operation) { if (operation == null) { throw new ArgumentNullException("operation"); } if (AcceptChanges) { StartUndoGroup(); undostack.Push(operation); actionCountInUndoGroup++; if (TextEditorControl != null) { undostack.Push(new UndoableSetCaretPosition(this, TextEditorControl.ActiveTextAreaControl.Caret.Position)); actionCountInUndoGroup++; } EndUndoGroup(); ClearRedoStack(); } } /// /// Call this method, if you want to clear the redo stack /// public void ClearRedoStack() { redostack.Clear(); } /// /// Clears both the undo and redo stack. /// public void ClearAll() { AssertNoUndoGroupOpen(); undostack.Clear(); redostack.Clear(); actionCountInUndoGroup = 0; } /// /// protected void OnActionUndone() { if (ActionUndone != null) { ActionUndone(null, null); } } /// /// protected void OnActionRedone() { if (ActionRedone != null) { ActionRedone(null, null); } } class UndoableSetCaretPosition : IUndoableOperation { UndoStack stack; TextLocation pos; TextLocation redoPos; public UndoableSetCaretPosition(UndoStack stack, TextLocation pos) { this.stack = stack; this.pos = pos; } public void Undo() { redoPos = stack.TextEditorControl.ActiveTextAreaControl.Caret.Position; stack.TextEditorControl.ActiveTextAreaControl.Caret.Position = pos; } public void Redo() { stack.TextEditorControl.ActiveTextAreaControl.Caret.Position = redoPos; } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Undo/UndoableDelete.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Diagnostics; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Undo { /// /// This class is for the undo of Document insert operations /// public class UndoableDelete : IUndoableOperation { IDocument document; // int oldCaretPos; int offset; string text; /// /// Creates a new instance of /// public UndoableDelete(IDocument document, int offset, string text) { if (document == null) { throw new ArgumentNullException("document"); } if (offset < 0 || offset > document.TextLength) { throw new ArgumentOutOfRangeException("offset"); } Debug.Assert(text != null, "text can't be null"); // oldCaretPos = document.Caret.Offset; this.document = document; this.offset = offset; this.text = text; } /// /// Undo last operation /// public void Undo() { // we clear all selection direct, because the redraw // is done per refresh at the end of the action // textArea.SelectionManager.SelectionCollection.Clear(); document.UndoStack.AcceptChanges = false; document.Insert(offset, text); // document.Caret.Offset = Math.Min(document.TextLength, Math.Max(0, oldCaretPos)); document.UndoStack.AcceptChanges = true; } /// /// Redo last undone operation /// public void Redo() { // we clear all selection direct, because the redraw // is done per refresh at the end of the action // textArea.SelectionManager.SelectionCollection.Clear(); document.UndoStack.AcceptChanges = false; document.Remove(offset, text.Length); // document.Caret.Offset = Math.Min(document.TextLength, Math.Max(0, document.Caret.Offset)); document.UndoStack.AcceptChanges = true; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Undo/UndoableInsert.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Diagnostics; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Undo { /// /// This class is for the undo of Document insert operations /// public class UndoableInsert : IUndoableOperation { IDocument document; // int oldCaretPos; int offset; string text; /// /// Creates a new instance of /// public UndoableInsert(IDocument document, int offset, string text) { if (document == null) { throw new ArgumentNullException("document"); } if (offset < 0 || offset > document.TextLength) { throw new ArgumentOutOfRangeException("offset"); } Debug.Assert(text != null, "text can't be null"); // oldCaretPos = document.Caret.Offset; this.document = document; this.offset = offset; this.text = text; } /// /// Undo last operation /// public void Undo() { // we clear all selection direct, because the redraw // is done per refresh at the end of the action // document.SelectionCollection.Clear(); document.UndoStack.AcceptChanges = false; document.Remove(offset, text.Length); // document.Caret.Offset = Math.Min(document.TextLength, Math.Max(0, oldCaretPos)); document.UndoStack.AcceptChanges = true; } /// /// Redo last undone operation /// public void Redo() { // we clear all selection direct, because the redraw // is done per refresh at the end of the action // document.SelectionCollection.Clear(); document.UndoStack.AcceptChanges = false; document.Insert(offset, text); // document.Caret.Offset = Math.Min(document.TextLength, Math.Max(0, document.Caret.Offset)); document.UndoStack.AcceptChanges = true; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Undo/UndoableReplace.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Diagnostics; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Undo { /// /// This class is for the undo of Document insert operations /// public class UndoableReplace : IUndoableOperation { IDocument document; // int oldCaretPos; int offset; string text; string origText; /// /// Creates a new instance of /// public UndoableReplace(IDocument document, int offset, string origText, string text) { if (document == null) { throw new ArgumentNullException("document"); } if (offset < 0 || offset > document.TextLength) { throw new ArgumentOutOfRangeException("offset"); } Debug.Assert(text != null, "text can't be null"); // oldCaretPos = document.Caret.Offset; this.document = document; this.offset = offset; this.text = text; this.origText = origText; } /// /// Undo last operation /// public void Undo() { // we clear all selection direct, because the redraw // is done per refresh at the end of the action // document.SelectionCollection.Clear(); document.UndoStack.AcceptChanges = false; document.Replace(offset, text.Length, origText); // document.Caret.Offset = Math.Min(document.TextLength, Math.Max(0, oldCaretPos)); document.UndoStack.AcceptChanges = true; } /// /// Redo last undone operation /// public void Redo() { // we clear all selection direct, because the redraw // is done per refresh at the end of the action // document.SelectionCollection.Clear(); document.UndoStack.AcceptChanges = false; document.Replace(offset, origText.Length, text); // document.Caret.Offset = Math.Min(document.TextLength, Math.Max(0, document.Caret.Offset)); document.UndoStack.AcceptChanges = true; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/AugmentableRedBlackTree.cs ================================================ // // // // // $Revision: 2497 $ // using System; using System.Text; using System.Diagnostics; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Util { internal sealed class RedBlackTreeNode { internal RedBlackTreeNode left, right, parent; internal T val; internal bool color; internal RedBlackTreeNode(T val) { this.val = val; } internal RedBlackTreeNode LeftMost { get { RedBlackTreeNode node = this; while (node.left != null) node = node.left; return node; } } internal RedBlackTreeNode RightMost { get { RedBlackTreeNode node = this; while (node.right != null) node = node.right; return node; } } } internal interface IRedBlackTreeHost : IComparer { bool Equals(T a, T b); void UpdateAfterChildrenChange(RedBlackTreeNode node); void UpdateAfterRotateLeft(RedBlackTreeNode node); void UpdateAfterRotateRight(RedBlackTreeNode node); } /// /// Description of RedBlackTree. /// internal sealed class AugmentableRedBlackTree : ICollection where Host : IRedBlackTreeHost { readonly Host host; int count; internal RedBlackTreeNode root; public AugmentableRedBlackTree(Host host) { if (host == null) throw new ArgumentNullException("host"); this.host = host; } public int Count { get { return count; } } public void Clear() { root = null; count = 0; } #region Debugging code #if DEBUG /// /// Check tree for consistency and being balanced. /// [Conditional("DATACONSISTENCYTEST")] void CheckProperties() { int blackCount = -1; CheckNodeProperties(root, null, RED, 0, ref blackCount); int nodeCount = 0; foreach (T val in this) { nodeCount++; } Debug.Assert(count == nodeCount); } /* 1. A node is either red or black. 2. The root is black. 3. All leaves are black. (The leaves are the NIL children.) 4. Both children of every red node are black. (So every red node must have a black parent.) 5. Every simple path from a node to a descendant leaf contains the same number of black nodes. (Not counting the leaf node.) */ void CheckNodeProperties(RedBlackTreeNode node, RedBlackTreeNode parentNode, bool parentColor, int blackCount, ref int expectedBlackCount) { if (node == null) return; Debug.Assert(node.parent == parentNode); if (parentColor == RED) { Debug.Assert(node.color == BLACK); } if (node.color == BLACK) { blackCount++; } if (node.left == null && node.right == null) { // node is a leaf node: if (expectedBlackCount == -1) expectedBlackCount = blackCount; else Debug.Assert(expectedBlackCount == blackCount); } CheckNodeProperties(node.left, node, node.color, blackCount, ref expectedBlackCount); CheckNodeProperties(node.right, node, node.color, blackCount, ref expectedBlackCount); } public string GetTreeAsString() { StringBuilder b = new StringBuilder(); AppendTreeToString(root, b, 0); return b.ToString(); } static void AppendTreeToString(RedBlackTreeNode node, StringBuilder b, int indent) { if (node.color == RED) b.Append("RED "); else b.Append("BLACK "); b.AppendLine(node.val.ToString()); indent += 2; if (node.left != null) { b.Append(' ', indent); b.Append("L: "); AppendTreeToString(node.left, b, indent); } if (node.right != null) { b.Append(' ', indent); b.Append("R: "); AppendTreeToString(node.right, b, indent); } } #endif #endregion #region Add public void Add(T item) { AddInternal(new RedBlackTreeNode(item)); #if DEBUG CheckProperties(); #endif } void AddInternal(RedBlackTreeNode newNode) { Debug.Assert(newNode.color == BLACK); if (root == null) { count = 1; root = newNode; return; } // Insert into the tree RedBlackTreeNode parentNode = root; while (true) { if (host.Compare(newNode.val, parentNode.val) <= 0) { if (parentNode.left == null) { InsertAsLeft(parentNode, newNode); return; } parentNode = parentNode.left; } else { if (parentNode.right == null) { InsertAsRight(parentNode, newNode); return; } parentNode = parentNode.right; } } } internal void InsertAsLeft(RedBlackTreeNode parentNode, RedBlackTreeNode newNode) { Debug.Assert(parentNode.left == null); parentNode.left = newNode; newNode.parent = parentNode; newNode.color = RED; host.UpdateAfterChildrenChange(parentNode); FixTreeOnInsert(newNode); count++; } internal void InsertAsRight(RedBlackTreeNode parentNode, RedBlackTreeNode newNode) { Debug.Assert(parentNode.right == null); parentNode.right = newNode; newNode.parent = parentNode; newNode.color = RED; host.UpdateAfterChildrenChange(parentNode); FixTreeOnInsert(newNode); count++; } void FixTreeOnInsert(RedBlackTreeNode node) { Debug.Assert(node != null); Debug.Assert(node.color == RED); Debug.Assert(node.left == null || node.left.color == BLACK); Debug.Assert(node.right == null || node.right.color == BLACK); RedBlackTreeNode parentNode = node.parent; if (parentNode == null) { // we inserted in the root -> the node must be black // since this is a root node, making the node black increments the number of black nodes // on all paths by one, so it is still the same for all paths. node.color = BLACK; return; } if (parentNode.color == BLACK) { // if the parent node where we inserted was black, our red node is placed correctly. // since we inserted a red node, the number of black nodes on each path is unchanged // -> the tree is still balanced return; } // parentNode is red, so there is a conflict here! // because the root is black, parentNode is not the root -> there is a grandparent node RedBlackTreeNode grandparentNode = parentNode.parent; RedBlackTreeNode uncleNode = Sibling(parentNode); if (uncleNode != null && uncleNode.color == RED) { parentNode.color = BLACK; uncleNode.color = BLACK; grandparentNode.color = RED; FixTreeOnInsert(grandparentNode); return; } // now we know: parent is red but uncle is black // First rotation: if (node == parentNode.right && parentNode == grandparentNode.left) { RotateLeft(parentNode); node = node.left; } else if (node == parentNode.left && parentNode == grandparentNode.right) { RotateRight(parentNode); node = node.right; } // because node might have changed, reassign variables: parentNode = node.parent; grandparentNode = parentNode.parent; // Now recolor a bit: parentNode.color = BLACK; grandparentNode.color = RED; // Second rotation: if (node == parentNode.left && parentNode == grandparentNode.left) { RotateRight(grandparentNode); } else { // because of the first rotation, this is guaranteed: Debug.Assert(node == parentNode.right && parentNode == grandparentNode.right); RotateLeft(grandparentNode); } } void ReplaceNode(RedBlackTreeNode replacedNode, RedBlackTreeNode newNode) { if (replacedNode.parent == null) { Debug.Assert(replacedNode == root); root = newNode; } else { if (replacedNode.parent.left == replacedNode) replacedNode.parent.left = newNode; else replacedNode.parent.right = newNode; } if (newNode != null) { newNode.parent = replacedNode.parent; } replacedNode.parent = null; } void RotateLeft(RedBlackTreeNode p) { // let q be p's right child RedBlackTreeNode q = p.right; Debug.Assert(q != null); Debug.Assert(q.parent == p); // set q to be the new root ReplaceNode(p, q); // set p's right child to be q's left child p.right = q.left; if (p.right != null) p.right.parent = p; // set q's left child to be p q.left = p; p.parent = q; host.UpdateAfterRotateLeft(p); } void RotateRight(RedBlackTreeNode p) { // let q be p's left child RedBlackTreeNode q = p.left; Debug.Assert(q != null); Debug.Assert(q.parent == p); // set q to be the new root ReplaceNode(p, q); // set p's left child to be q's right child p.left = q.right; if (p.left != null) p.left.parent = p; // set q's right child to be p q.right = p; p.parent = q; host.UpdateAfterRotateRight(p); } RedBlackTreeNode Sibling(RedBlackTreeNode node) { if (node == node.parent.left) return node.parent.right; else return node.parent.left; } #endregion #region Remove public void RemoveAt(RedBlackTreeIterator iterator) { RedBlackTreeNode node = iterator.node; if (node == null) throw new ArgumentException("Invalid iterator"); while (node.parent != null) node = node.parent; if (node != root) throw new ArgumentException("Iterator does not belong to this tree"); RemoveNode(iterator.node); #if DEBUG CheckProperties(); #endif } internal void RemoveNode(RedBlackTreeNode removedNode) { if (removedNode.left != null && removedNode.right != null) { // replace removedNode with it's in-order successor RedBlackTreeNode leftMost = removedNode.right.LeftMost; RemoveNode(leftMost); // remove leftMost from its current location // and overwrite the removedNode with it ReplaceNode(removedNode, leftMost); leftMost.left = removedNode.left; if (leftMost.left != null) leftMost.left.parent = leftMost; leftMost.right = removedNode.right; if (leftMost.right != null) leftMost.right.parent = leftMost; leftMost.color = removedNode.color; host.UpdateAfterChildrenChange(leftMost); if (leftMost.parent != null) host.UpdateAfterChildrenChange(leftMost.parent); return; } count--; // now either removedNode.left or removedNode.right is null // get the remaining child RedBlackTreeNode parentNode = removedNode.parent; RedBlackTreeNode childNode = removedNode.left ?? removedNode.right; ReplaceNode(removedNode, childNode); if (parentNode != null) host.UpdateAfterChildrenChange(parentNode); if (removedNode.color == BLACK) { if (childNode != null && childNode.color == RED) { childNode.color = BLACK; } else { FixTreeOnDelete(childNode, parentNode); } } } static RedBlackTreeNode Sibling(RedBlackTreeNode node, RedBlackTreeNode parentNode) { Debug.Assert(node == null || node.parent == parentNode); if (node == parentNode.left) return parentNode.right; else return parentNode.left; } const bool RED = true; const bool BLACK = false; static bool GetColor(RedBlackTreeNode node) { return node != null ? node.color : BLACK; } void FixTreeOnDelete(RedBlackTreeNode node, RedBlackTreeNode parentNode) { Debug.Assert(node == null || node.parent == parentNode); if (parentNode == null) return; // warning: node may be null RedBlackTreeNode sibling = Sibling(node, parentNode); if (sibling.color == RED) { parentNode.color = RED; sibling.color = BLACK; if (node == parentNode.left) { RotateLeft(parentNode); } else { RotateRight(parentNode); } sibling = Sibling(node, parentNode); // update value of sibling after rotation } if (parentNode.color == BLACK && sibling.color == BLACK && GetColor(sibling.left) == BLACK && GetColor(sibling.right) == BLACK) { sibling.color = RED; FixTreeOnDelete(parentNode, parentNode.parent); return; } if (parentNode.color == RED && sibling.color == BLACK && GetColor(sibling.left) == BLACK && GetColor(sibling.right) == BLACK) { sibling.color = RED; parentNode.color = BLACK; return; } if (node == parentNode.left && sibling.color == BLACK && GetColor(sibling.left) == RED && GetColor(sibling.right) == BLACK) { sibling.color = RED; sibling.left.color = BLACK; RotateRight(sibling); } else if (node == parentNode.right && sibling.color == BLACK && GetColor(sibling.right) == RED && GetColor(sibling.left) == BLACK) { sibling.color = RED; sibling.right.color = BLACK; RotateLeft(sibling); } sibling = Sibling(node, parentNode); // update value of sibling after rotation sibling.color = parentNode.color; parentNode.color = BLACK; if (node == parentNode.left) { if (sibling.right != null) { Debug.Assert(sibling.right.color == RED); sibling.right.color = BLACK; } RotateLeft(parentNode); } else { if (sibling.left != null) { Debug.Assert(sibling.left.color == RED); sibling.left.color = BLACK; } RotateRight(parentNode); } } #endregion #region Find/LowerBound/UpperBound/GetEnumerator /// /// Returns the iterator pointing to the specified item, or an iterator in End state if the item is not found. /// public RedBlackTreeIterator Find(T item) { RedBlackTreeIterator it = LowerBound(item); while (it.IsValid && host.Compare(it.Current, item) == 0) { if (host.Equals(it.Current, item)) return it; it.MoveNext(); } return default(RedBlackTreeIterator); } /// /// Returns the iterator pointing to the first item greater or equal to . /// public RedBlackTreeIterator LowerBound(T item) { RedBlackTreeNode node = root; RedBlackTreeNode resultNode = null; while (node != null) { if (host.Compare(node.val, item) < 0) { node = node.right; } else { resultNode = node; node = node.left; } } return new RedBlackTreeIterator(resultNode); } /// /// Returns the iterator pointing to the first item greater than . /// public RedBlackTreeIterator UpperBound(T item) { RedBlackTreeIterator it = LowerBound(item); while (it.IsValid && host.Compare(it.Current, item) == 0) { it.MoveNext(); } return it; } /// /// Gets a tree iterator that starts on the first node. /// public RedBlackTreeIterator Begin() { if (root == null) return default(RedBlackTreeIterator); return new RedBlackTreeIterator(root.LeftMost); } /// /// Gets a tree iterator that starts one node before the first node. /// public RedBlackTreeIterator GetEnumerator() { if (root == null) return default(RedBlackTreeIterator); RedBlackTreeNode dummyNode = new RedBlackTreeNode(default(T)); dummyNode.right = root; return new RedBlackTreeIterator(dummyNode); } #endregion #region ICollection members public bool Contains(T item) { return Find(item).IsValid; } public bool Remove(T item) { RedBlackTreeIterator it = Find(item); if (!it.IsValid) { return false; } else { RemoveAt(it); return true; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } bool ICollection.IsReadOnly { get { return false; } } public void CopyTo(T[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException("array"); foreach (T val in this) { array[arrayIndex++] = val; } } #endregion } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/CheckedList.cs ================================================ // // // // // $Revision: 3090 $ // using System; using System.Collections.Generic; using System.Threading; namespace ICSharpCode.TextEditor.Util { /// /// A IList{T} that checks that it is only accessed on the thread that created it, and that /// it is not modified while an enumerator is running. /// sealed class CheckedList : IList { readonly int threadID; readonly IList baseList; int enumeratorCount; public CheckedList() : this(new List()) {} public CheckedList(IList baseList) { if (baseList == null) throw new ArgumentNullException("baseList"); this.baseList = baseList; this.threadID = Thread.CurrentThread.ManagedThreadId; } void CheckRead() { if (Thread.CurrentThread.ManagedThreadId != threadID) throw new InvalidOperationException("CheckList cannot be accessed from this thread!"); } void CheckWrite() { if (Thread.CurrentThread.ManagedThreadId != threadID) throw new InvalidOperationException("CheckList cannot be accessed from this thread!"); if (enumeratorCount != 0) throw new InvalidOperationException("CheckList cannot be written to while enumerators are active!"); } public T this[int index] { get { CheckRead(); return baseList[index]; } set { CheckWrite(); baseList[index] = value; } } public int Count { get { CheckRead(); return baseList.Count; } } public bool IsReadOnly { get { CheckRead(); return baseList.IsReadOnly; } } public int IndexOf(T item) { CheckRead(); return baseList.IndexOf(item); } public void Insert(int index, T item) { CheckWrite(); baseList.Insert(index, item); } public void RemoveAt(int index) { CheckWrite(); baseList.RemoveAt(index); } public void Add(T item) { CheckWrite(); baseList.Add(item); } public void Clear() { CheckWrite(); baseList.Clear(); } public bool Contains(T item) { CheckRead(); return baseList.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { CheckRead(); baseList.CopyTo(array, arrayIndex); } public bool Remove(T item) { CheckWrite(); return baseList.Remove(item); } public IEnumerator GetEnumerator() { CheckRead(); return Enumerate(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { CheckRead(); return Enumerate(); } IEnumerator Enumerate() { CheckRead(); try { enumeratorCount++; foreach (T val in baseList) { yield return val; CheckRead(); } } finally { enumeratorCount--; CheckRead(); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/FileReader.cs ================================================ // // // // // $Revision: 2682 $ // using System; using System.IO; using System.Text; namespace ICSharpCode.TextEditor.Util { /// /// Class that can open text files with auto-detection of the encoding. /// public static class FileReader { public static bool IsUnicode(Encoding encoding) { int codepage = encoding.CodePage; // return true if codepage is any UTF codepage return codepage == 65001 || codepage == 65000 || codepage == 1200 || codepage == 1201; } public static string ReadFileContent(Stream fs, ref Encoding encoding) { using (StreamReader reader = OpenStream(fs, encoding)) { reader.Peek(); encoding = reader.CurrentEncoding; return reader.ReadToEnd(); } } public static string ReadFileContent(string fileName, Encoding encoding) { using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { return ReadFileContent(fs, ref encoding); } } public static StreamReader OpenStream(Stream fs, Encoding defaultEncoding) { if (fs == null) throw new ArgumentNullException("fs"); if (fs.Length >= 2) { // the autodetection of StreamReader is not capable of detecting the difference // between ISO-8859-1 and UTF-8 without BOM. int firstByte = fs.ReadByte(); int secondByte = fs.ReadByte(); switch ((firstByte << 8) | secondByte) { case 0x0000: // either UTF-32 Big Endian or a binary file; use StreamReader case 0xfffe: // Unicode BOM (UTF-16 LE or UTF-32 LE) case 0xfeff: // UTF-16 BE BOM case 0xefbb: // start of UTF-8 BOM // StreamReader autodetection works fs.Position = 0; return new StreamReader(fs); default: return AutoDetect(fs, (byte)firstByte, (byte)secondByte, defaultEncoding); } } else { if (defaultEncoding != null) { return new StreamReader(fs, defaultEncoding); } else { return new StreamReader(fs); } } } static StreamReader AutoDetect(Stream fs, byte firstByte, byte secondByte, Encoding defaultEncoding) { int max = (int)Math.Min(fs.Length, 500000); // look at max. 500 KB const int ASCII = 0; const int Error = 1; const int UTF8 = 2; const int UTF8Sequence = 3; int state = ASCII; int sequenceLength = 0; byte b; for (int i = 0; i < max; i++) { if (i == 0) { b = firstByte; } else if (i == 1) { b = secondByte; } else { b = (byte)fs.ReadByte(); } if (b < 0x80) { // normal ASCII character if (state == UTF8Sequence) { state = Error; break; } } else if (b < 0xc0) { // 10xxxxxx : continues UTF8 byte sequence if (state == UTF8Sequence) { --sequenceLength; if (sequenceLength < 0) { state = Error; break; } else if (sequenceLength == 0) { state = UTF8; } } else { state = Error; break; } } else if (b >= 0xc2 && b < 0xf5) { // beginning of byte sequence if (state == UTF8 || state == ASCII) { state = UTF8Sequence; if (b < 0xe0) { sequenceLength = 1; // one more byte following } else if (b < 0xf0) { sequenceLength = 2; // two more bytes following } else { sequenceLength = 3; // three more bytes following } } else { state = Error; break; } } else { // 0xc0, 0xc1, 0xf5 to 0xff are invalid in UTF-8 (see RFC 3629) state = Error; break; } } fs.Position = 0; switch (state) { case ASCII: case Error: // when the file seems to be ASCII or non-UTF8, // we read it using the user-specified encoding so it is saved again // using that encoding. if (IsUnicode(defaultEncoding)) { // the file is not Unicode, so don't read it using Unicode even if the // user has choosen Unicode as the default encoding. // If we don't do this, SD will end up always adding a Byte Order Mark // to ASCII files. defaultEncoding = Encoding.Default; // use system encoding instead } return new StreamReader(fs, defaultEncoding); default: return new StreamReader(fs); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/LoggingService.cs ================================================ // // // // // $Revision: 2719 $ // using System; namespace ICSharpCode.TextEditor.Util { /// /// Central location for logging calls in the text editor. /// static class LoggingService { public static void Debug(string text) { #if DEBUG Console.WriteLine(text); #endif } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/LookupTable.cs ================================================ // // // // // $Revision: 1965 $ // using System; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Util { /// /// This class implements a keyword map. It implements a digital search trees (tries) to find /// a word. /// public class LookupTable { Node root = new Node(null, null); bool casesensitive; int length; /// /// The number of elements in the table /// public int Count { get { return length; } } /// /// Get the object, which was inserted under the keyword (line, at offset, with length length), /// returns null, if no such keyword was inserted. /// public object this[IDocument document, LineSegment line, int offset, int length] { get { if(length == 0) { return null; } Node next = root; int wordOffset = line.Offset + offset; if (casesensitive) { for (int i = 0; i < length; ++i) { int index = ((int)document.GetCharAt(wordOffset + i)) % 256; next = next.leaf[index]; if (next == null) { return null; } if (next.color != null && TextUtility.RegionMatches(document, wordOffset, length, next.word)) { return next.color; } } } else { for (int i = 0; i < length; ++i) { int index = ((int)Char.ToUpper(document.GetCharAt(wordOffset + i))) % 256; next = next.leaf[index]; if (next == null) { return null; } if (next.color != null && TextUtility.RegionMatches(document, casesensitive, wordOffset, length, next.word)) { return next.color; } } } return null; } } /// /// Inserts an object in the tree, under keyword /// public object this[string keyword] { set { Node node = root; Node next = root; if (!casesensitive) { keyword = keyword.ToUpper(); } ++length; // insert word into the tree for (int i = 0; i < keyword.Length; ++i) { int index = ((int)keyword[i]) % 256; // index of curchar bool d = keyword[i] == '\\'; next = next.leaf[index]; // get node to this index if (next == null) { // no node created -> insert word here node.leaf[index] = new Node(value, keyword); break; } if (next.word != null && next.word.Length != i) { // node there, take node content and insert them again string tmpword = next.word; // this word will be inserted 1 level deeper (better, don't need too much object tmpcolor = next.color; // string comparisons for finding.) next.color = next.word = null; this[tmpword] = tmpcolor; } if (i == keyword.Length - 1) { // end of keyword reached, insert node there, if a node was here it was next.word = keyword; // reinserted, if it has the same length (keyword EQUALS this word) it will be overwritten next.color = value; break; } node = next; } } } /// /// Creates a new instance of /// public LookupTable(bool casesensitive) { this.casesensitive = casesensitive; } class Node { public Node(object color, string word) { this.word = word; this.color = color; } public string word; public object color; public Node[] leaf { get { return _leaf ?? (_leaf = new Node[256]); } } private Node[] _leaf; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/MouseWheelHandler.cs ================================================ // // // // // $Revision: 3064 $ // using System; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Util { /// /// Accumulates mouse wheel deltas and reports the actual number of lines to scroll. /// class MouseWheelHandler { // CODE DUPLICATION: See ICSharpCode.SharpDevelop.Widgets.MouseWheelHandler const int WHEEL_DELTA = 120; int mouseWheelDelta; public int GetScrollAmount(MouseEventArgs e) { // accumulate the delta to support high-resolution mice mouseWheelDelta += e.Delta; int linesPerClick = Math.Max(SystemInformation.MouseWheelScrollLines, 1); int scrollDistance = mouseWheelDelta * linesPerClick / WHEEL_DELTA; mouseWheelDelta %= Math.Max(1, WHEEL_DELTA / linesPerClick); return scrollDistance; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/RedBlackTreeIterator.cs ================================================ // // // // // $Revision: 2497 $ // using System; using System.Diagnostics; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Util { internal struct RedBlackTreeIterator : IEnumerator { internal RedBlackTreeNode node; internal RedBlackTreeIterator(RedBlackTreeNode node) { this.node = node; } public bool IsValid { get { return node != null; } } public T Current { get { if (node != null) return node.val; else throw new InvalidOperationException(); } } object System.Collections.IEnumerator.Current { get { return this.Current; } } void IDisposable.Dispose() { } void System.Collections.IEnumerator.Reset() { throw new NotSupportedException(); } public bool MoveNext() { if (node == null) return false; if (node.right != null) { node = node.right.LeftMost; } else { RedBlackTreeNode oldNode; do { oldNode = node; node = node.parent; // we are on the way up from the right part, don't output node again } while (node != null && node.right == oldNode); } return node != null; } public bool MoveBack() { if (node == null) return false; if (node.left != null) { node = node.left.RightMost; } else { RedBlackTreeNode oldNode; do { oldNode = node; node = node.parent; // we are on the way up from the left part, don't output node again } while (node != null && node.left == oldNode); } return node != null; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/RtfWriter.cs ================================================ // // // // // $Revision: 1965 $ // using System; using System.Collections.Generic; using System.Drawing; using System.Text; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Util { public class RtfWriter { static Dictionary colors; static int colorNum; static StringBuilder colorString; public static string GenerateRtf(TextArea textArea) { colors = new Dictionary(); colorNum = 0; colorString = new StringBuilder(); StringBuilder rtf = new StringBuilder(); rtf.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1031"); BuildFontTable(textArea.Document, rtf); rtf.Append('\n'); string fileContent = BuildFileContent(textArea); BuildColorTable(textArea.Document, rtf); rtf.Append('\n'); rtf.Append(@"\viewkind4\uc1\pard"); rtf.Append(fileContent); rtf.Append("}"); return rtf.ToString(); } static void BuildColorTable(IDocument doc, StringBuilder rtf) { rtf.Append(@"{\colortbl ;"); rtf.Append(colorString.ToString()); rtf.Append("}"); } static void BuildFontTable(IDocument doc, StringBuilder rtf) { rtf.Append(@"{\fonttbl"); rtf.Append(@"{\f0\fmodern\fprq1\fcharset0 " + doc.TextEditorProperties.Font.Name + ";}"); rtf.Append("}"); } static string BuildFileContent(TextArea textArea) { StringBuilder rtf = new StringBuilder(); bool firstLine = true; Color curColor = Color.Black; bool oldItalic = false; bool oldBold = false; bool escapeSequence = false; foreach (ISelection selection in textArea.SelectionManager.SelectionCollection) { int selectionOffset = textArea.Document.PositionToOffset(selection.StartPosition); int selectionEndOffset = textArea.Document.PositionToOffset(selection.EndPosition); for (int i = selection.StartPosition.Y; i <= selection.EndPosition.Y; ++i) { LineSegment line = textArea.Document.GetLineSegment(i); int offset = line.Offset; if (line.Words == null) { continue; } foreach (TextWord word in line.Words) { switch (word.Type) { case TextWordType.Space: if (selection.ContainsOffset(offset)) { rtf.Append(' '); } ++offset; break; case TextWordType.Tab: if (selection.ContainsOffset(offset)) { rtf.Append(@"\tab"); } ++offset; escapeSequence = true; break; case TextWordType.Word: Color c = word.Color; if (offset + word.Word.Length > selectionOffset && offset < selectionEndOffset) { string colorstr = c.R + ", " + c.G + ", " + c.B; if (!colors.ContainsKey(colorstr)) { colors[colorstr] = ++colorNum; colorString.Append(@"\red" + c.R + @"\green" + c.G + @"\blue" + c.B + ";"); } if (c != curColor || firstLine) { rtf.Append(@"\cf" + colors[colorstr].ToString()); curColor = c; escapeSequence = true; } if (oldItalic != word.Italic) { if (word.Italic) { rtf.Append(@"\i"); } else { rtf.Append(@"\i0"); } oldItalic = word.Italic; escapeSequence = true; } if (oldBold != word.Bold) { if (word.Bold) { rtf.Append(@"\b"); } else { rtf.Append(@"\b0"); } oldBold = word.Bold; escapeSequence = true; } if (firstLine) { rtf.Append(@"\f0\fs" + (textArea.TextEditorProperties.Font.Size * 2)); firstLine = false; } if (escapeSequence) { rtf.Append(' '); escapeSequence = false; } string printWord; if (offset < selectionOffset) { printWord = word.Word.Substring(selectionOffset - offset); } else if (offset + word.Word.Length > selectionEndOffset) { printWord = word.Word.Substring(0, (offset + word.Word.Length) - selectionEndOffset); } else { printWord = word.Word; } rtf.Append(printWord.Replace(@"\", @"\\").Replace("{", "\\{").Replace("}", "\\}")); } offset += word.Length; break; } } if (offset < selectionEndOffset) { rtf.Append(@"\par"); } rtf.Append('\n'); } } return rtf.ToString(); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/TextUtility.cs ================================================ // // // // // $Revision: 915 $ // using System; using ICSharpCode.TextEditor.Document; namespace ICSharpCode.TextEditor.Util { public class TextUtility { public static bool RegionMatches(IDocument document, int offset, int length, string word) { if (length != word.Length || document.TextLength < offset + length) { return false; } for (int i = 0; i < length; ++i) { if (document.GetCharAt(offset + i) != word[i]) { return false; } } return true; } public static bool RegionMatches(IDocument document, bool casesensitive, int offset, int length, string word) { if (casesensitive) { return RegionMatches(document, offset, length, word); } if (length != word.Length || document.TextLength < offset + length) { return false; } for (int i = 0; i < length; ++i) { if (Char.ToUpper(document.GetCharAt(offset + i)) != Char.ToUpper(word[i])) { return false; } } return true; } public static bool RegionMatches(IDocument document, int offset, int length, char[] word) { if (length != word.Length || document.TextLength < offset + length) { return false; } for (int i = 0; i < length; ++i) { if (document.GetCharAt(offset + i) != word[i]) { return false; } } return true; } public static bool RegionMatches(IDocument document, bool casesensitive, int offset, int length, char[] word) { if (casesensitive) { return RegionMatches(document, offset, length, word); } if (length != word.Length || document.TextLength < offset + length) { return false; } for (int i = 0; i < length; ++i) { if (Char.ToUpper(document.GetCharAt(offset + i)) != Char.ToUpper(word[i])) { return false; } } return true; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/TipPainter.cs ================================================ // // // // // $Revision: 2487 $ // using System.Drawing; using System.Drawing.Text; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Util { static class TipPainter { const float HorizontalBorder = 2; const float VerticalBorder = 1; static RectangleF workingArea = RectangleF.Empty; //static StringFormat centerTipFormat = CreateTipStringFormat(); public static Size GetTipSize(Control control, Graphics graphics, Font font, string description) { return GetTipSize(control, graphics, new TipText (graphics, font, description)); } public static Size GetTipSize(Control control, Graphics graphics, TipSection tipData) { Size tipSize = Size.Empty; SizeF tipSizeF = SizeF.Empty; if (workingArea == RectangleF.Empty) { Form ownerForm = control.FindForm(); if (ownerForm.Owner != null) { ownerForm = ownerForm.Owner; } workingArea = Screen.GetWorkingArea(ownerForm); } PointF screenLocation = control.PointToScreen(Point.Empty); SizeF maxLayoutSize = new SizeF(workingArea.Right - screenLocation.X - HorizontalBorder * 2, workingArea.Bottom - screenLocation.Y - VerticalBorder * 2); if (maxLayoutSize.Width > 0 && maxLayoutSize.Height > 0) { graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; tipData.SetMaximumSize(maxLayoutSize); tipSizeF = tipData.GetRequiredSize(); tipData.SetAllocatedSize(tipSizeF); tipSizeF += new SizeF(HorizontalBorder * 2, VerticalBorder * 2); tipSize = Size.Ceiling(tipSizeF); } if (control.ClientSize != tipSize) { control.ClientSize = tipSize; } return tipSize; } public static Size DrawTip(Control control, Graphics graphics, Font font, string description) { return DrawTip(control, graphics, new TipText (graphics, font, description)); } public static Size DrawTip(Control control, Graphics graphics, TipSection tipData) { Size tipSize = Size.Empty; SizeF tipSizeF = SizeF.Empty; PointF screenLocation = control.PointToScreen(Point.Empty); if (workingArea == RectangleF.Empty) { Form ownerForm = control.FindForm(); if (ownerForm.Owner != null) { ownerForm = ownerForm.Owner; } workingArea = Screen.GetWorkingArea(ownerForm); } SizeF maxLayoutSize = new SizeF(workingArea.Right - screenLocation.X - HorizontalBorder * 2, workingArea.Bottom - screenLocation.Y - VerticalBorder * 2); if (maxLayoutSize.Width > 0 && maxLayoutSize.Height > 0) { graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; tipData.SetMaximumSize(maxLayoutSize); tipSizeF = tipData.GetRequiredSize(); tipData.SetAllocatedSize(tipSizeF); tipSizeF += new SizeF(HorizontalBorder * 2, VerticalBorder * 2); tipSize = Size.Ceiling(tipSizeF); } if (control.ClientSize != tipSize) { control.ClientSize = tipSize; } if (tipSize != Size.Empty) { Rectangle borderRectangle = new Rectangle (Point.Empty, tipSize - new Size(1, 1)); RectangleF displayRectangle = new RectangleF (HorizontalBorder, VerticalBorder, tipSizeF.Width - HorizontalBorder * 2, tipSizeF.Height - VerticalBorder * 2); // DrawRectangle draws from Left to Left + Width. A bug? :-/ graphics.DrawRectangle(SystemPens.WindowFrame, borderRectangle); tipData.Draw(new PointF(HorizontalBorder, VerticalBorder)); } return tipSize; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/TipPainterTools.cs ================================================ // // // // // $Revision: 915 $ // using System; using System.Drawing; using System.Windows.Forms; namespace ICSharpCode.TextEditor.Util { class TipPainterTools { const int SpacerSize = 4; private TipPainterTools() { } public static Size GetDrawingSizeHelpTipFromCombinedDescription(Control control, Graphics graphics, Font font, string countMessage, string description) { string basicDescription = null; string documentation = null; if (IsVisibleText(description)) { string[] splitDescription = description.Split(new char[] { '\n' }, 2); if (splitDescription.Length > 0) { basicDescription = splitDescription[0]; if (splitDescription.Length > 1) { documentation = splitDescription[1].Trim(); } } } return GetDrawingSizeDrawHelpTip(control, graphics, font, countMessage, basicDescription, documentation); } public static Size DrawHelpTipFromCombinedDescription(Control control, Graphics graphics, Font font, string countMessage, string description) { string basicDescription = null; string documentation = null; if (IsVisibleText(description)) { string[] splitDescription = description.Split (new char[] { '\n' }, 2); if (splitDescription.Length > 0) { basicDescription = splitDescription[0]; if (splitDescription.Length > 1) { documentation = splitDescription[1].Trim(); } } } return DrawHelpTip(control, graphics, font, countMessage, basicDescription, documentation); } // btw. I know it's ugly. public static Rectangle DrawingRectangle1; public static Rectangle DrawingRectangle2; public static Size GetDrawingSizeDrawHelpTip(Control control, Graphics graphics, Font font, string countMessage, string basicDescription, string documentation) { if (IsVisibleText(countMessage) || IsVisibleText(basicDescription) || IsVisibleText(documentation)) { // Create all the TipSection objects. CountTipText countMessageTip = new CountTipText(graphics, font, countMessage); TipSpacer countSpacer = new TipSpacer(graphics, new SizeF(IsVisibleText(countMessage) ? 4 : 0, 0)); TipText descriptionTip = new TipText(graphics, font, basicDescription); TipSpacer docSpacer = new TipSpacer(graphics, new SizeF(0, IsVisibleText(documentation) ? 4 : 0)); TipText docTip = new TipText(graphics, font, documentation); // Now put them together. TipSplitter descSplitter = new TipSplitter(graphics, false, descriptionTip, docSpacer ); TipSplitter mainSplitter = new TipSplitter(graphics, true, countMessageTip, countSpacer, descSplitter); TipSplitter mainSplitter2 = new TipSplitter(graphics, false, mainSplitter, docTip); // Show it. Size size = TipPainter.GetTipSize(control, graphics, mainSplitter2); DrawingRectangle1 = countMessageTip.DrawingRectangle1; DrawingRectangle2 = countMessageTip.DrawingRectangle2; return size; } return Size.Empty; } public static Size DrawHelpTip(Control control, Graphics graphics, Font font, string countMessage, string basicDescription, string documentation) { if (IsVisibleText(countMessage) || IsVisibleText(basicDescription) || IsVisibleText(documentation)) { // Create all the TipSection objects. CountTipText countMessageTip = new CountTipText(graphics, font, countMessage); TipSpacer countSpacer = new TipSpacer(graphics, new SizeF(IsVisibleText(countMessage) ? 4 : 0, 0)); TipText descriptionTip = new TipText(graphics, font, basicDescription); TipSpacer docSpacer = new TipSpacer(graphics, new SizeF(0, IsVisibleText(documentation) ? 4 : 0)); TipText docTip = new TipText(graphics, font, documentation); // Now put them together. TipSplitter descSplitter = new TipSplitter(graphics, false, descriptionTip, docSpacer ); TipSplitter mainSplitter = new TipSplitter(graphics, true, countMessageTip, countSpacer, descSplitter); TipSplitter mainSplitter2 = new TipSplitter(graphics, false, mainSplitter, docTip); // Show it. Size size = TipPainter.DrawTip(control, graphics, mainSplitter2); DrawingRectangle1 = countMessageTip.DrawingRectangle1; DrawingRectangle2 = countMessageTip.DrawingRectangle2; return size; } return Size.Empty; } static bool IsVisibleText(string text) { return text != null && text.Length > 0; } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/TipSection.cs ================================================ // // // // // $Revision: 915 $ // using System; using System.Diagnostics; using System.Drawing; namespace ICSharpCode.TextEditor.Util { abstract class TipSection { SizeF tipAllocatedSize; Graphics tipGraphics; SizeF tipMaxSize; SizeF tipRequiredSize; protected TipSection(Graphics graphics) { tipGraphics = graphics; } public abstract void Draw(PointF location); public SizeF GetRequiredSize() { return tipRequiredSize; } public void SetAllocatedSize(SizeF allocatedSize) { Debug.Assert(allocatedSize.Width >= tipRequiredSize.Width && allocatedSize.Height >= tipRequiredSize.Height); tipAllocatedSize = allocatedSize; OnAllocatedSizeChanged(); } public void SetMaximumSize(SizeF maximumSize) { tipMaxSize = maximumSize; OnMaximumSizeChanged(); } protected virtual void OnAllocatedSizeChanged() { } protected virtual void OnMaximumSizeChanged() { } protected void SetRequiredSize(SizeF requiredSize) { requiredSize.Width = Math.Max(0, requiredSize.Width); requiredSize.Height = Math.Max(0, requiredSize.Height); requiredSize.Width = Math.Min(tipMaxSize.Width, requiredSize.Width); requiredSize.Height = Math.Min(tipMaxSize.Height, requiredSize.Height); tipRequiredSize = requiredSize; } protected Graphics Graphics { get { return tipGraphics; } } protected SizeF AllocatedSize { get { return tipAllocatedSize; } } protected SizeF MaximumSize { get { return tipMaxSize; } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/TipSpacer.cs ================================================ // // // // // $Revision: 915 $ // using System; using System.Drawing; namespace ICSharpCode.TextEditor.Util { class TipSpacer: TipSection { SizeF spacerSize; public TipSpacer(Graphics graphics, SizeF size): base(graphics) { spacerSize = size; } public override void Draw(PointF location) { } protected override void OnMaximumSizeChanged() { base.OnMaximumSizeChanged(); SetRequiredSize(new SizeF (Math.Min(MaximumSize.Width, spacerSize.Width), Math.Min(MaximumSize.Height, spacerSize.Height))); } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/TipSplitter.cs ================================================ // // // // // $Revision: 915 $ // using System; using System.Diagnostics; using System.Drawing; namespace ICSharpCode.TextEditor.Util { class TipSplitter: TipSection { bool isHorizontal; float [] offsets; TipSection[] tipSections; public TipSplitter(Graphics graphics, bool horizontal, params TipSection[] sections): base(graphics) { Debug.Assert(sections != null); isHorizontal = horizontal; offsets = new float[sections.Length]; tipSections = (TipSection[])sections.Clone(); } public override void Draw(PointF location) { if (isHorizontal) { for (int i = 0; i < tipSections.Length; i ++) { tipSections[i].Draw (new PointF(location.X + offsets[i], location.Y)); } } else { for (int i = 0; i < tipSections.Length; i ++) { tipSections[i].Draw (new PointF(location.X, location.Y + offsets[i])); } } } protected override void OnMaximumSizeChanged() { base.OnMaximumSizeChanged(); float currentDim = 0; float otherDim = 0; SizeF availableArea = MaximumSize; for (int i = 0; i < tipSections.Length; i ++) { TipSection section = (TipSection)tipSections[i]; section.SetMaximumSize(availableArea); SizeF requiredArea = section.GetRequiredSize(); offsets[i] = currentDim; // It's best to start on pixel borders, so this will // round up to the nearest pixel. Otherwise there are // weird cutoff artifacts. float pixelsUsed; if (isHorizontal) { pixelsUsed = (float)Math.Ceiling(requiredArea.Width); currentDim += pixelsUsed; availableArea.Width = Math.Max (0, availableArea.Width - pixelsUsed); otherDim = Math.Max(otherDim, requiredArea.Height); } else { pixelsUsed = (float)Math.Ceiling(requiredArea.Height); currentDim += pixelsUsed; availableArea.Height = Math.Max (0, availableArea.Height - pixelsUsed); otherDim = Math.Max(otherDim, requiredArea.Width); } } foreach (TipSection section in tipSections) { if (isHorizontal) { section.SetAllocatedSize(new SizeF(section.GetRequiredSize().Width, otherDim)); } else { section.SetAllocatedSize(new SizeF(otherDim, section.GetRequiredSize().Height)); } } if (isHorizontal) { SetRequiredSize(new SizeF(currentDim, otherDim)); } else { SetRequiredSize(new SizeF(otherDim, currentDim)); } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/TipText.cs ================================================ // // // // // $Revision: 2561 $ // using System; using System.Drawing; namespace ICSharpCode.TextEditor.Util { class CountTipText: TipText { float triHeight = 10; float triWidth = 10; public CountTipText(Graphics graphics, Font font, string text) : base(graphics, font, text) { } void DrawTriangle(float x, float y, bool flipped) { Brush brush = BrushRegistry.GetBrush(Color.FromArgb(192, 192, 192)); base.Graphics.FillRectangle(brush, new RectangleF(x, y, triHeight, triHeight)); float triHeight2 = triHeight / 2; float triHeight4 = triHeight / 4; brush = Brushes.Black; if (flipped) { base.Graphics.FillPolygon(brush, new PointF[] { new PointF(x, y + triHeight2 - triHeight4), new PointF(x + triWidth / 2, y + triHeight2 + triHeight4), new PointF(x + triWidth, y + triHeight2 - triHeight4), }); } else { base.Graphics.FillPolygon(brush, new PointF[] { new PointF(x, y + triHeight2 + triHeight4), new PointF(x + triWidth / 2, y + triHeight2 - triHeight4), new PointF(x + triWidth, y + triHeight2 + triHeight4), }); } } public Rectangle DrawingRectangle1; public Rectangle DrawingRectangle2; public override void Draw(PointF location) { if (tipText != null && tipText.Length > 0) { base.Draw(new PointF(location.X + triWidth + 4, location.Y)); DrawingRectangle1 = new Rectangle((int)location.X + 2, (int)location.Y + 2, (int)(triWidth), (int)(triHeight)); DrawingRectangle2 = new Rectangle((int)(location.X + base.AllocatedSize.Width - triWidth - 2), (int)location.Y + 2, (int)(triWidth), (int)(triHeight)); DrawTriangle(location.X + 2, location.Y + 2, false); DrawTriangle(location.X + base.AllocatedSize.Width - triWidth - 2, location.Y + 2, true); } } protected override void OnMaximumSizeChanged() { if (IsTextVisible()) { SizeF tipSize = Graphics.MeasureString (tipText, tipFont, MaximumSize, GetInternalStringFormat()); tipSize.Width += triWidth * 2 + 8; SetRequiredSize(tipSize); } else { SetRequiredSize(SizeF.Empty); } } } class TipText: TipSection { protected StringAlignment horzAlign; protected StringAlignment vertAlign; protected Color tipColor; protected Font tipFont; protected StringFormat tipFormat; protected string tipText; public TipText(Graphics graphics, Font font, string text): base(graphics) { tipFont = font; tipText = text; if (text != null && text.Length > short.MaxValue) throw new ArgumentException("TipText: text too long (max. is " + short.MaxValue + " characters)", "text"); Color = SystemColors.InfoText; HorizontalAlignment = StringAlignment.Near; VerticalAlignment = StringAlignment.Near; } public override void Draw(PointF location) { if (IsTextVisible()) { RectangleF drawRectangle = new RectangleF(location, AllocatedSize); Graphics.DrawString(tipText, tipFont, BrushRegistry.GetBrush(Color), drawRectangle, GetInternalStringFormat()); } } protected StringFormat GetInternalStringFormat() { if (tipFormat == null) { tipFormat = CreateTipStringFormat(horzAlign, vertAlign); } return tipFormat; } protected override void OnMaximumSizeChanged() { base.OnMaximumSizeChanged(); if (IsTextVisible()) { SizeF tipSize = Graphics.MeasureString (tipText, tipFont, MaximumSize, GetInternalStringFormat()); SetRequiredSize(tipSize); } else { SetRequiredSize(SizeF.Empty); } } static StringFormat CreateTipStringFormat(StringAlignment horizontalAlignment, StringAlignment verticalAlignment) { StringFormat format = (StringFormat)StringFormat.GenericTypographic.Clone(); format.FormatFlags = StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces; // note: Align Near, Line Center seemed to do something before format.Alignment = horizontalAlignment; format.LineAlignment = verticalAlignment; return format; } protected bool IsTextVisible() { return tipText != null && tipText.Length > 0; } public Color Color { get { return tipColor; } set { tipColor = value; } } public StringAlignment HorizontalAlignment { get { return horzAlign; } set { horzAlign = value; tipFormat = null; } } public StringAlignment VerticalAlignment { get { return vertAlign; } set { vertAlign = value; tipFormat = null; } } } } ================================================ FILE: src/ICSharpCode.TextEditor/Project/Src/Util/WeakCollection.cs ================================================ // // // // // $Revision: 2683 $ // using System; using System.Collections.Generic; namespace ICSharpCode.TextEditor.Util { /// /// A collection that does not allows its elements to be garbage-collected (unless there are other /// references to the elements). Elements will disappear from the collection when they are /// garbage-collected. /// /// The WeakCollection is not thread-safe, not even for read-only access! /// No methods may be called on the WeakCollection while it is enumerated, not even a Contains or /// creating a second enumerator. /// The WeakCollection does not preserve any order among its contents; the ordering may be different each /// time the collection is enumerated. /// /// Since items may disappear at any time when they are garbage collected, this class /// cannot provide a useful implementation for Count and thus cannot implement the ICollection interface. /// public class WeakCollection : IEnumerable where T : class { readonly List innerList = new List(); /// /// Adds an element to the collection. Runtime: O(n). /// public void Add(T item) { if (item == null) throw new ArgumentNullException("item"); CheckNoEnumerator(); if (innerList.Count == innerList.Capacity || (innerList.Count % 32) == 31) innerList.RemoveAll(delegate(WeakReference r) { return !r.IsAlive; }); innerList.Add(new WeakReference(item)); } /// /// Removes all elements from the collection. Runtime: O(n). /// public void Clear() { innerList.Clear(); CheckNoEnumerator(); } /// /// Checks if the collection contains an item. Runtime: O(n). /// public bool Contains(T item) { if (item == null) throw new ArgumentNullException("item"); CheckNoEnumerator(); foreach (T element in this) { if (item.Equals(element)) return true; } return false; } /// /// Removes an element from the collection. Returns true if the item is found and removed, /// false when the item is not found. /// Runtime: O(n). /// public bool Remove(T item) { if (item == null) throw new ArgumentNullException("item"); CheckNoEnumerator(); for (int i = 0; i < innerList.Count;) { T element = (T)innerList[i].Target; if (element == null) { RemoveAt(i); } else if (element == item) { RemoveAt(i); return true; } else { i++; } } return false; } void RemoveAt(int i) { int lastIndex = innerList.Count - 1; innerList[i] = innerList[lastIndex]; innerList.RemoveAt(lastIndex); } bool hasEnumerator; void CheckNoEnumerator() { if (hasEnumerator) throw new InvalidOperationException("The WeakCollection is already being enumerated, it cannot be modified at the same time. Ensure you dispose the first enumerator before modifying the WeakCollection."); } /// /// Enumerates the collection. /// Each MoveNext() call on the enumerator is O(1), thus the enumeration is O(n). /// public IEnumerator GetEnumerator() { if (hasEnumerator) throw new InvalidOperationException("The WeakCollection is already being enumerated, it cannot be enumerated twice at the same time. Ensure you dispose the first enumerator before using another enumerator."); try { hasEnumerator = true; for (int i = 0; i < innerList.Count;) { T element = (T)innerList[i].Target; if (element == null) { RemoveAt(i); } else { yield return element; i++; } } } finally { hasEnumerator = false; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } } ================================================ FILE: src/IIncludeHandler.cs ================================================ using System; namespace Pyramid { public interface IIncludeResult { byte[] Contents { get; } string FullPath { get; } } public enum IncludeType { System, User, } public interface IIncludeHandler { IIncludeResult OpenInclude(IncludeType eType, string targetPath, string includerPath ); } } ================================================ FILE: src/IWrapper.cs ================================================ using System; namespace Pyramid { public interface IWrapper { /// /// Construct a D3DCompiler by dynamically loading a given D3DCompiler DLL /// Throws if the DLL could not be loaded properly /// /// /// ID3DCompiler CreateD3DCompiler(string DLLPath, IIncludeHandler handler ); IDXILCompiler CreateDXILCompiler(string DLLPath, IIncludeHandler handler); /// /// Construct an instance of the GLSL Optimizer /// /// GLSLOptimizer.IOptimizer CreateGLSLOptimizer( GLSLOptimizer.Target eTarget ); GLSlang.ICompiler CreateGLSlangCompiler( IIncludeHandler handler ); IAMDDriver CreateAMDDriver( string DLLPath ); } } ================================================ FILE: src/IncludeHandler.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Pyramid { class IncludeResult : IIncludeResult { public IncludeResult( string path ) { FullPath = path; Contents = File.ReadAllBytes(path); } public byte[] Contents { get; private set; } public string FullPath { get; private set; } } class IncludeHandler : IIncludeHandler { private List m_SearchDirs = new List(); public IncludeHandler( IEnumerable IncludePaths ) { if (IncludePaths != null) m_SearchDirs.AddRange(IncludePaths); } IIncludeResult DoPath(string searchPath, string includePath ) { string relPath = Path.GetFullPath(Path.Combine(searchPath, includePath)); if( File.Exists(relPath)) { return new IncludeResult(relPath); } return null; } public IIncludeResult OpenInclude(IncludeType eType, string path, string includerPath) { if (!String.IsNullOrEmpty(includerPath)) { string fileDir = Path.GetDirectoryName(includerPath); IIncludeResult r = DoPath(fileDir, path); if (r != null) return r; } foreach( string s in m_SearchDirs ) { if( Directory.Exists(s)) { IIncludeResult r = DoPath(s, path); if (r != null) return r; } } return null; } } } ================================================ FILE: src/LanguageTypes.cs ================================================ namespace Pyramid { public enum Languages { HLSL, GLSL, }; public interface ICompileOptions { Languages Language { get; } } public interface IShader { Languages Language { get; } string Code { get; } /// /// Full path to source file, if we have one. /// May be empty if text was typed into editor and not saved /// string SourceFilePath { get; } }; } ================================================ FILE: src/Languages/GLSLLanguage.cs ================================================  namespace Pyramid { public class GLSLLanguage : ILanguage { private GLSLOptionsPanel m_Options = new GLSLOptionsPanel(); public ICompileOptionsPanel OptionsPanel { get { return m_Options; } } public string Name { get {return "GLSL";} } } } ================================================ FILE: src/Languages/GLSLOptionsPanel.Designer.cs ================================================ namespace Pyramid { partial class GLSLOptionsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.cmbShaderType = new System.Windows.Forms.ComboBox(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.label3 = new System.Windows.Forms.Label(); this.upUnrollIter = new System.Windows.Forms.NumericUpDown(); this.cmbGLSLOptTarget = new System.Windows.Forms.ComboBox(); this.label2 = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.upUnrollIter)).BeginInit(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(5, 12); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(31, 13); this.label1.TabIndex = 0; this.label1.Text = "Type"; // // cmbShaderType // this.cmbShaderType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbShaderType.FormattingEnabled = true; this.cmbShaderType.Location = new System.Drawing.Point(42, 9); this.cmbShaderType.Name = "cmbShaderType"; this.cmbShaderType.Size = new System.Drawing.Size(135, 21); this.cmbShaderType.TabIndex = 1; // // groupBox1 // this.groupBox1.Controls.Add(this.label3); this.groupBox1.Controls.Add(this.upUnrollIter); this.groupBox1.Controls.Add(this.cmbGLSLOptTarget); this.groupBox1.Controls.Add(this.label2); this.groupBox1.Location = new System.Drawing.Point(3, 36); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(180, 81); this.groupBox1.TabIndex = 4; this.groupBox1.TabStop = false; this.groupBox1.Text = "GLSL Optimizer"; // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(6, 52); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(57, 13); this.label3.TabIndex = 7; this.label3.Text = "Max Unroll"; // // upUnrollIter // this.upUnrollIter.Location = new System.Drawing.Point(69, 48); this.upUnrollIter.Name = "upUnrollIter"; this.upUnrollIter.Size = new System.Drawing.Size(53, 20); this.upUnrollIter.TabIndex = 6; this.upUnrollIter.Value = new decimal(new int[] { 16, 0, 0, 0}); // // cmbGLSLOptTarget // this.cmbGLSLOptTarget.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbGLSLOptTarget.FormattingEnabled = true; this.cmbGLSLOptTarget.Location = new System.Drawing.Point(61, 20); this.cmbGLSLOptTarget.Name = "cmbGLSLOptTarget"; this.cmbGLSLOptTarget.Size = new System.Drawing.Size(113, 21); this.cmbGLSLOptTarget.TabIndex = 5; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(6, 23); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(38, 13); this.label2.TabIndex = 4; this.label2.Text = "Target"; // // GLSLOptionsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.groupBox1); this.Controls.Add(this.cmbShaderType); this.Controls.Add(this.label1); this.Name = "GLSLOptionsPanel"; this.Size = new System.Drawing.Size(198, 132); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.upUnrollIter)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; private System.Windows.Forms.ComboBox cmbShaderType; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.Label label3; private System.Windows.Forms.NumericUpDown upUnrollIter; private System.Windows.Forms.ComboBox cmbGLSLOptTarget; private System.Windows.Forms.Label label2; } } ================================================ FILE: src/Languages/GLSLOptionsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace Pyramid { public partial class GLSLOptionsPanel : UserControl, ICompileOptionsPanel { class GLSLOptimizerOptions : GLSLOptimizer.IOptions { public GLSLOptimizer.ShaderType ShaderType { get; set; } public uint MaxUnrollIterations { get; set; } } class GLSLOptions : IGLSLOptions { public Languages Language { get { return Languages.GLSL; } } public GLSLOptimizer.IOptions OptimizerOptions { get; set; } public GLSLShaderType ShaderType { get; set; } public GLSLOptimizer.Target OptimizerTarget { get; set; } } public GLSLOptionsPanel() { InitializeComponent(); foreach (object e in Enum.GetValues(typeof(GLSLShaderType))) cmbShaderType.Items.Add(e); foreach (object e in Enum.GetValues(typeof(GLSLOptimizer.Target))) cmbGLSLOptTarget.Items.Add(e); cmbGLSLOptTarget.SelectedIndex = 0; cmbShaderType.SelectedIndex = 0; } public Control Panel { get { return this; } } public ICompileOptions ReadOptions() { GLSLOptions opts = new GLSLOptions(); opts.ShaderType = (GLSLShaderType)cmbShaderType.SelectedItem; opts.OptimizerTarget = (GLSLOptimizer.Target)cmbGLSLOptTarget.SelectedItem; GLSLOptimizer.ShaderType eType; switch (opts.ShaderType) { default: return opts; case GLSLShaderType.VERTEX: eType = GLSLOptimizer.ShaderType.VERTEX; break; case GLSLShaderType.FRAGMENT: eType = GLSLOptimizer.ShaderType.FRAGMENT; break; } GLSLOptimizerOptions optOptions = new GLSLOptimizerOptions(); optOptions.ShaderType = eType; optOptions.MaxUnrollIterations = (uint)upUnrollIter.Value; opts.OptimizerOptions = optOptions; return opts; } } } ================================================ FILE: src/Languages/GLSLOptionsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Languages/HLSLLanguage.cs ================================================  namespace Pyramid { public class HLSLLanguage : ILanguage { private HLSLOptionsPanel m_Options = new HLSLOptionsPanel(); public ICompileOptionsPanel OptionsPanel { get { return m_Options; } } public string Name { get { return "HLSL"; } } } } ================================================ FILE: src/Languages/HLSLOptionsPanel.Designer.cs ================================================ namespace Pyramid { partial class HLSLOptionsPanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.cmbTarget = new System.Windows.Forms.ComboBox(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.cmbOpt = new System.Windows.Forms.ComboBox(); this.txtEntryPoint = new System.Windows.Forms.TextBox(); this.label4 = new System.Windows.Forms.Label(); this.chkCompat = new System.Windows.Forms.CheckBox(); this.txtRootSig = new System.Windows.Forms.TextBox(); this.label5 = new System.Windows.Forms.Label(); this.cmbRootSignature = new System.Windows.Forms.ComboBox(); this.label6 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(17, 14); this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(43, 17); this.label1.TabIndex = 0; this.label1.Text = "HLSL"; // // cmbTarget // this.cmbTarget.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbTarget.FormattingEnabled = true; this.cmbTarget.Location = new System.Drawing.Point(120, 46); this.cmbTarget.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.cmbTarget.Name = "cmbTarget"; this.cmbTarget.Size = new System.Drawing.Size(160, 24); this.cmbTarget.TabIndex = 1; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(17, 49); this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(50, 17); this.label2.TabIndex = 2; this.label2.Text = "Target"; // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(17, 80); this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(31, 17); this.label3.TabIndex = 3; this.label3.Text = "Opt"; // // cmbOpt // this.cmbOpt.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbOpt.FormattingEnabled = true; this.cmbOpt.Location = new System.Drawing.Point(120, 80); this.cmbOpt.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.cmbOpt.Name = "cmbOpt"; this.cmbOpt.Size = new System.Drawing.Size(160, 24); this.cmbOpt.TabIndex = 4; // // txtEntryPoint // this.txtEntryPoint.Location = new System.Drawing.Point(120, 112); this.txtEntryPoint.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.txtEntryPoint.Name = "txtEntryPoint"; this.txtEntryPoint.Size = new System.Drawing.Size(159, 22); this.txtEntryPoint.TabIndex = 5; this.txtEntryPoint.Text = "main"; // // label4 // this.label4.AutoSize = true; this.label4.Location = new System.Drawing.Point(9, 116); this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(73, 17); this.label4.TabIndex = 6; this.label4.Text = "EntryPoint"; // // chkCompat // this.chkCompat.AutoSize = true; this.chkCompat.Location = new System.Drawing.Point(120, 142); this.chkCompat.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.chkCompat.Name = "chkCompat"; this.chkCompat.Size = new System.Drawing.Size(78, 21); this.chkCompat.TabIndex = 7; this.chkCompat.Text = "Compat"; this.chkCompat.UseVisualStyleBackColor = true; // // txtRootSig // this.txtRootSig.Location = new System.Drawing.Point(120, 191); this.txtRootSig.Margin = new System.Windows.Forms.Padding(4); this.txtRootSig.Name = "txtRootSig"; this.txtRootSig.Size = new System.Drawing.Size(159, 22); this.txtRootSig.TabIndex = 8; this.txtRootSig.Text = "RootSignature"; // // label5 // this.label5.AutoSize = true; this.label5.Location = new System.Drawing.Point(9, 194); this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(90, 17); this.label5.TabIndex = 9; this.label5.Text = "RootSig #def"; // // cmbRootSignature // this.cmbRootSignature.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbRootSignature.FormattingEnabled = true; this.cmbRootSignature.Location = new System.Drawing.Point(119, 221); this.cmbRootSignature.Margin = new System.Windows.Forms.Padding(4); this.cmbRootSignature.Name = "cmbRootSignature"; this.cmbRootSignature.Size = new System.Drawing.Size(160, 24); this.cmbRootSignature.TabIndex = 10; // // label6 // this.label6.AutoSize = true; this.label6.Location = new System.Drawing.Point(9, 221); this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(104, 17); this.label6.TabIndex = 11; this.label6.Text = "RootSig Target"; // // HLSLOptionsPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.label6); this.Controls.Add(this.cmbRootSignature); this.Controls.Add(this.label5); this.Controls.Add(this.txtRootSig); this.Controls.Add(this.chkCompat); this.Controls.Add(this.label4); this.Controls.Add(this.txtEntryPoint); this.Controls.Add(this.cmbOpt); this.Controls.Add(this.label3); this.Controls.Add(this.label2); this.Controls.Add(this.cmbTarget); this.Controls.Add(this.label1); this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "HLSLOptionsPanel"; this.Size = new System.Drawing.Size(310, 267); this.Load += new System.EventHandler(this.HLSLOptionsPanel_Load); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; private System.Windows.Forms.ComboBox cmbTarget; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.ComboBox cmbOpt; private System.Windows.Forms.TextBox txtEntryPoint; private System.Windows.Forms.Label label4; private System.Windows.Forms.CheckBox chkCompat; private System.Windows.Forms.TextBox txtRootSig; private System.Windows.Forms.Label label5; private System.Windows.Forms.ComboBox cmbRootSignature; private System.Windows.Forms.Label label6; } } ================================================ FILE: src/Languages/HLSLOptionsPanel.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Pyramid { public partial class HLSLOptionsPanel : UserControl, ICompileOptionsPanel { private class HLSLOptions : IHLSLOptions { public Languages Language { get { return Languages.HLSL; } } public HLSLTarget Target { get; set; } public RootSignatureTarget RootSigTarget { get; set; } public HLSLOptimizationLevel OptimizationLevel { get; set; } public string EntryPoint { get; set; } public string RootSigMacro { get; set; } public bool Compatibility { get; set; } public HLSLShaderType ShaderType { get { switch (this.Target) { case HLSLTarget.vs_3_0: case HLSLTarget.vs_4_0: case HLSLTarget.vs_4_1: case HLSLTarget.vs_5_0: case HLSLTarget.vs_5_1: case HLSLTarget.vs_6_0: case HLSLTarget.vs_6_1: case HLSLTarget.vs_6_2: return HLSLShaderType.VERTEX; case HLSLTarget.ps_3_0: case HLSLTarget.ps_4_0: case HLSLTarget.ps_4_1: case HLSLTarget.ps_5_0: case HLSLTarget.ps_5_1: case HLSLTarget.ps_6_0: case HLSLTarget.ps_6_1: case HLSLTarget.ps_6_2: return HLSLShaderType.PIXEL; case HLSLTarget.gs_4_0: case HLSLTarget.gs_4_1: case HLSLTarget.gs_5_0: case HLSLTarget.gs_5_1: case HLSLTarget.gs_6_0: case HLSLTarget.gs_6_1: case HLSLTarget.gs_6_2: return HLSLShaderType.GEOMETRY; case HLSLTarget.hs_5_0: case HLSLTarget.hs_5_1: case HLSLTarget.hs_6_0: case HLSLTarget.hs_6_1: case HLSLTarget.hs_6_2: return HLSLShaderType.HULL; case HLSLTarget.ds_5_0: case HLSLTarget.ds_5_1: case HLSLTarget.ds_6_0: case HLSLTarget.ds_6_1: case HLSLTarget.ds_6_2: return HLSLShaderType.DOMAIN; case HLSLTarget.cs_4_0: case HLSLTarget.cs_4_1: case HLSLTarget.cs_5_0: case HLSLTarget.cs_5_1: case HLSLTarget.cs_6_0: case HLSLTarget.cs_6_1: case HLSLTarget.cs_6_2: return HLSLShaderType.COMPUTE; } throw new System.Exception("What is this?"); } } public uint GetD3DCompileFlagBits() { uint flags=0; switch (OptimizationLevel) { case HLSLOptimizationLevel.SKIP: flags |= (1 << 2); break; //D3DCOMPILE_SKIP_OPTIMIZATION case HLSLOptimizationLevel.LEVEL0: flags |= (1 << 14); break; //D3DCOMPILE_OPTIMIZATION_LEVEL0 case HLSLOptimizationLevel.LEVEL1: flags |= 0; break;//D3DCOMPILE_OPTIMIZATION_LEVEL1 case HLSLOptimizationLevel.LEVEL2: flags |= (1<<14)|(1<<15) ; break; //D3DCOMPILE_OPTIMIZATION_LEVEL2 case HLSLOptimizationLevel.LEVEL3: flags |= (1<<15); break; //D3DCOMPILE_OPTIMIZATION_LEVEL3 } if (Compatibility) flags |= (1 << 12);// D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY return flags; } public string GetFXCCommandLine(string shaderFile) { string switches = ""; switch (OptimizationLevel) { case HLSLOptimizationLevel.SKIP: switches += "/Od "; break; case HLSLOptimizationLevel.LEVEL0: switches += "/O0 "; break; case HLSLOptimizationLevel.LEVEL1: switches += "/O1 "; break; case HLSLOptimizationLevel.LEVEL2: switches += "/O2 "; break; case HLSLOptimizationLevel.LEVEL3: switches += "/O3 "; break; } if (Compatibility) switches += "/Gec"; return String.Format( "/T{0} /E{1} {2} \"{3}\"", Target.ToString(), EntryPoint, switches, shaderFile ); } } public HLSLOptionsPanel() { InitializeComponent(); foreach( object e in Enum.GetValues(typeof(HLSLTarget))) { string n = Enum.GetName(typeof(HLSLTarget), e); cmbTarget.Items.Add(n); } foreach( object e in Enum.GetValues(typeof(HLSLOptimizationLevel))) { string n = Enum.GetName(typeof(HLSLOptimizationLevel), e); cmbOpt.Items.Add(n); } foreach( object e in Enum.GetValues(typeof(RootSignatureTarget) ) ) { string n = Enum.GetName(typeof(RootSignatureTarget), e); cmbRootSignature.Items.Add(n); } cmbTarget.SelectedIndex = cmbTarget.Items.IndexOf("ps_5_0"); cmbOpt.SelectedIndex = cmbOpt.Items.IndexOf("LEVEL3"); cmbRootSignature.SelectedIndex = cmbRootSignature.Items.IndexOf("rootsig_1_0"); } public Control Panel { get { return this; } } public ICompileOptions ReadOptions() { HLSLOptions opts = new HLSLOptions(); opts.Compatibility = chkCompat.Checked; opts.EntryPoint = txtEntryPoint.Text; opts.RootSigMacro = txtRootSig.Text; opts.RootSigTarget = (RootSignatureTarget)Enum.Parse(typeof(RootSignatureTarget), (string) cmbRootSignature.Items[cmbRootSignature.SelectedIndex]); opts.Target = (HLSLTarget) Enum.Parse(typeof(HLSLTarget), (string) cmbTarget.Items[cmbTarget.SelectedIndex]); opts.OptimizationLevel = (HLSLOptimizationLevel)Enum.Parse(typeof(HLSLOptimizationLevel), (string) cmbOpt.Items[cmbOpt.SelectedIndex]); return opts; } private void HLSLOptionsPanel_Load(object sender, EventArgs e) { } } } ================================================ FILE: src/Languages/HLSLOptionsPanel.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Languages/ICompileOptionsPanel.cs ================================================ using System; using System.Collections.Generic; using System.Windows.Forms; namespace Pyramid { public interface ICompileOptionsPanel { Control Panel { get; } ICompileOptions ReadOptions(); }; } ================================================ FILE: src/Languages/ILanguage.cs ================================================  namespace Pyramid { public interface ILanguage { ICompileOptionsPanel OptionsPanel { get; } string Name { get; } }; } ================================================ FILE: src/MainUI/AboutBox.Designer.cs ================================================ namespace Pyramid { partial class AboutBox { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox)); this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); this.logoPictureBox = new System.Windows.Forms.PictureBox(); this.labelProductName = new System.Windows.Forms.Label(); this.labelVersion = new System.Windows.Forms.Label(); this.labelCopyright = new System.Windows.Forms.Label(); this.labelCompanyName = new System.Windows.Forms.Label(); this.textBoxDescription = new System.Windows.Forms.TextBox(); this.okButton = new System.Windows.Forms.Button(); this.tableLayoutPanel.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit(); this.SuspendLayout(); // // tableLayoutPanel // this.tableLayoutPanel.ColumnCount = 2; this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F)); this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67F)); this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0); this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0); this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1); this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2); this.tableLayoutPanel.Controls.Add(this.labelCompanyName, 1, 3); this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 1, 4); this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5); this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel.Location = new System.Drawing.Point(9, 9); this.tableLayoutPanel.Name = "tableLayoutPanel"; this.tableLayoutPanel.RowCount = 6; this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F)); this.tableLayoutPanel.Size = new System.Drawing.Size(417, 265); this.tableLayoutPanel.TabIndex = 0; // // logoPictureBox // this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill; this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image"))); this.logoPictureBox.Location = new System.Drawing.Point(3, 3); this.logoPictureBox.Name = "logoPictureBox"; this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6); this.logoPictureBox.Size = new System.Drawing.Size(131, 259); this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; this.logoPictureBox.TabIndex = 12; this.logoPictureBox.TabStop = false; // // labelProductName // this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill; this.labelProductName.Location = new System.Drawing.Point(143, 0); this.labelProductName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); this.labelProductName.MaximumSize = new System.Drawing.Size(0, 17); this.labelProductName.Name = "labelProductName"; this.labelProductName.Size = new System.Drawing.Size(271, 17); this.labelProductName.TabIndex = 19; this.labelProductName.Text = "Pyramid ShaderAnalyzer"; this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // labelVersion // this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill; this.labelVersion.Location = new System.Drawing.Point(143, 26); this.labelVersion.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17); this.labelVersion.Name = "labelVersion"; this.labelVersion.Size = new System.Drawing.Size(271, 17); this.labelVersion.TabIndex = 0; this.labelVersion.Text = "Version 1.4"; this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // labelCopyright // this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill; this.labelCopyright.Location = new System.Drawing.Point(143, 52); this.labelCopyright.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 17); this.labelCopyright.Name = "labelCopyright"; this.labelCopyright.Size = new System.Drawing.Size(271, 17); this.labelCopyright.TabIndex = 21; this.labelCopyright.Text = "Copyright 2014-2015 Joshua Barczak"; this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // labelCompanyName // this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill; this.labelCompanyName.Location = new System.Drawing.Point(143, 78); this.labelCompanyName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0); this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 17); this.labelCompanyName.Name = "labelCompanyName"; this.labelCompanyName.Size = new System.Drawing.Size(271, 17); this.labelCompanyName.TabIndex = 22; this.labelCompanyName.Text = "Me Myself and I, Ltd."; this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // textBoxDescription // this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill; this.textBoxDescription.Location = new System.Drawing.Point(143, 107); this.textBoxDescription.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3); this.textBoxDescription.Multiline = true; this.textBoxDescription.Name = "textBoxDescription"; this.textBoxDescription.ReadOnly = true; this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.textBoxDescription.Size = new System.Drawing.Size(271, 126); this.textBoxDescription.TabIndex = 23; this.textBoxDescription.TabStop = false; this.textBoxDescription.Text = resources.GetString("textBoxDescription.Text"); // // okButton // this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.okButton.Location = new System.Drawing.Point(339, 239); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(75, 23); this.okButton.TabIndex = 24; this.okButton.Text = "&OK"; // // AboutBox // this.AcceptButton = this.okButton; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(435, 283); this.Controls.Add(this.tableLayoutPanel); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "AboutBox"; this.Padding = new System.Windows.Forms.Padding(9); this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "About This Thing"; this.tableLayoutPanel.ResumeLayout(false); this.tableLayoutPanel.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; private System.Windows.Forms.PictureBox logoPictureBox; private System.Windows.Forms.Label labelProductName; private System.Windows.Forms.Label labelVersion; private System.Windows.Forms.Label labelCopyright; private System.Windows.Forms.Label labelCompanyName; private System.Windows.Forms.TextBox textBoxDescription; private System.Windows.Forms.Button okButton; } } ================================================ FILE: src/MainUI/AboutBox.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Reflection; using System.Windows.Forms; namespace Pyramid { partial class AboutBox : Form { public AboutBox() { InitializeComponent(); } } } ================================================ FILE: src/MainUI/AboutBox.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 iVBORw0KGgoAAAANSUhEUgAAAHgAAAEGCAIAAAAhWcaAAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AABvkklEQVR4Xu29B1hUd9r+z3X939+7bzax RQWmnZmhS++9i4KCXRRRsKGoiKKIKIJKlSrSpTdpioWmYm9gLzEao4kliTGmZ3ez6767yb7/+3u+M8fD DBiTTVE33+u5cKSe85n73M/9nJk5oyEsE4rKRaIKkbhKLKmVMPUM08hIW6Ty3XL5PrlOl45Ot47uEV3d 47p6J/X0TrGFG8f09I7o6Xbr6u7X1W3X1d2nq7NbR2enjk6zjk6jjk69jk6djixDxsxhRJailJSUy5cv f/vtt3/729/+/ve//+///u8//vGPf/7zn999993333//L3b936u+WNBlInG5WFIhkVRKmCpGWiOV1kpl O2TyJrm8RS5vlevs1dHt1NU9oAuy4Esoo46yrA+xn8dX29RY1+joVOvI0mXMbEZkIUpPT7958+Zf/vKX v/71r0+ePPlPw60BylA0Bc1UMgR0lVRWLZPVyuR1cnm9XKeBBdeio9OqA+US/Xbp6h7UJYi5UrLW3aOr s6sPa3mVXF4pl6ZKJTMlQmNhYWHhhx9++B+Im4B+SrlSSblaJq+Rk6qVwwQIsh06hHiTkvheljjgwjoA HQXWuAOojbSqsa6Qy8vl0o1SyWSJUEfY0NDwpz/96T8KtwYoiysUoEFZWk1AP6Vcq/O0OOIgCI4qxEEZ hRucZeMbVFiXyeWlcmY1I/YRR0REHDlyhMP9ynu3hrhMLCmXMBWsnCtZOdcoQPehzBVwqxCHL+9mXQXW Acq0uPaIgwDfybEulcu3y+WFcmYRI7IXbdmy5c6dO3zcYK2CW7GlL/nSEBeLxaWENaFcJUPJq+WkBgLN lYqlgPguHXi0gjgKN2DZtD2qsC6Ry4vlsmSZZLpEqC9samr6+uuvgZtLJq+etDXEOWLJNglTxDAljLRM KquQySoJa3DpUyqUuepX4LAUShzGwrVH3B+1PNbFcnkRK+0oRuwpXr9+/ZUrV4D7z3/+80DGrdjkl3Np iNPF4gyxJEPC5DDSPKmsSCYrkREzLSdpAfnsuYir44ZBgy8sBaDhIVwUqevLulAuL5AjcUtmkUxSX1// 5ZdffvPNNxQ337hfdmlriFPFkjQJs4VhMhhplhQl2yqTb2MRwExBHFCApur5NK6CWylwUmDNtcdqnT6s 8+WyPBmzihF7iTds2HDjxo2vvvqKc5JXQ9oa4mSxJEXCpDFgLU2XSjOkskyZLJstEM9jD3Ae8efSOB83 tW/gpkV1ja/Csvms8+SybTJpmlQSKBEaCPfs2fPFF1/06yQvqbQ1JIkSJplhUhjMFNhP2RYZZjnCmsNN ieezRMDl+QWujhuKpqy5KMJjDVHjD8lyZMwyRuQkysrK+vjjj+EkNJO87NJmQScx0mQpqRSpLE1GiuLO YHFnKXHnyMBCxVJ+QOAq3k1x0+JYVypZw6y3KVhLN0jF/mKBUNDb2/v555+rS/ulCyQaoMyBlqXIFJXK w60u8FwWN9D8NNwoyho3KGscIiqs2T/EzGaEo4QtLS2ffvrpyy5tAvqpnDnQfNwDCRx+UvBj/EQdN0RN WdPYh7sNvw2NEaxx9FDWsBFH0bZt2x4/fsyXtnrWVuzQi7o0xIvFTDxhrUqZX8/G3de+f1jdYM3H3S/r 3Kespeuk4jEkaN+6deuzzz7jAsnLZSMazs7OAgOByE0kni5mljOqiPnF95OB1P08ZsKXNj01iI/qrJUG QlinSCVTJAKJ4PTp05A2AgmytoqNvOCsNerq6vLz82NiYoKCghwdHUVWIom/hAljZBvVQNN6hrqpd2O8 Biy0OHXcHGsV3FzRcaY/1ihi2YbC9vb2Tz755KWzEY2dO3e2trbuZhfSa3Z29pIlS8aMGSMyF0nGSZhF jCxRjTVKHTdHBMmERu/nNG7OSVC4MbCuUVCAyEKEARLJDx2S2ghNIy84a42Ojo7Ozs6urq79+/fjBhYk 09bWBpkvX76cELcWSSZLmEg1V+GchOIGaw53zg8ZtwprDjetZ7NeTk77FRcXP3z4EDZC00i/lq3YxRdj aRw5cuTo0aPH2IUbhw8fPnTo0MGDByl3QIfGFyxYIJQJxR5iJlTNUp5h3NRJIG32tMkPS5uPm2Y+yhpD o7Ix0sKwLnIR5eTkfPjhh8+2bMVevgBL4yy7zp07h4+YDs6cOXPq1KkTJ06AO+4DDjrC7IYNGyZOnEgE Pl0iXaMWujnc/6a0KW58fCZr6Vop7vjU1NQPPviAb9kvbHvUeOutt65fv46P165du3r16uXLly9dunT+ /HlwB3R0eUCH0kG8u7sbxHNzc0NDQ4UmQskECROl9JNnJ26+tNVdm8+aj5vPuogd0Pmss2TSOKnYW5yY mPjgwYNHjx4h+am3xxeHtcadO3feU6533333nXfeuXnzJtCD+5UrVy5evAjoUDqInzx5EjKHt4B4RUUF eiYyAIkoK1ncYP08rg1qz2kj6qwxyHCgUWAdLxX7iDdu3Hj//n2uPapHkReBtcZHygW/w2GILb537x6g 3759m4MOpUPmFy5cgMw54tA4un9kZCTBHSCRrpI+ZT2QtGkgeR4b4XDjBjejq7DGr82USRPIOJOQkIAt p+2RiyIvFGsNqAAHHTwON7CV8DtIA9wp9Lt373JKf/vttzniVONwFfj4jh07IiIihKZCyVSJdL3ytJQK a07anI30G/74oLliv6Q491TIDo3qrH3EmzZtgkSw5VwUeaFYa8DX0LKxWfiI29hEQAd6DjqUDhOkMqfE OY2jhfb09KB5QuBVVVVhYWEiWxEzh3USPmsVG6FjJOaa57FsWvh8NY81F/hY0IQ1PMRbnJycDGXwWSP2 vSCsNXC3cwsJCQanAp0qncqcTxyughYKH+cEfvz48YKCghkzZoi9xMxS5lmsn23ZKpRpUdY4DnA09Msa vdFDnJGRAdZc7HtxWGvQjcBCKsJtxH4kJEDH9nHQ4XrYaCpzSpy6Chop31IgcOonSUlJxLgnS6Qb2EcS ONZ9LZs8fPOc7ZGCpmYN1jgaMMhwIYRjHSMVOYvy8vLef//9F421Bv4wXdgIrH6hQ+l84pzGqY9D4Ldu 3bpx4waCCsWNXIixfunSpSInETltMjBrNLc+7ZEPGvUM1jRc01+CYkGjkDhFdqLy8vJnsP5NZhkNevfS hS3A6he6OnG4CnYDAZYKHDvG+QmHG6FbqCuUTJLAQ38G1spPEtbw92JeCFGKmrBeyojMRc3NzSqssf2/ IWsNxb/KRYljUeIUugpxzlXg41TgaJuIVnBw+IkK7q6uLkRAsQvr2j8Xa5g1WNNwzYUQjnWGjFnACA2E Bw4c4Fir55BfmbUqaP7iiFPofOJwFb7AsRvUwVVwUzNB+s7OzhaOEjJBjAK0OmvEvudhrfwMAa0eQiho yjqIEUgEuKdfENbPAs2tfomrCJzvJ3zc8G60SkyYLS0tmN3F48Qka3Ogfyxr3mcIa3wnQkiBsjHyRI0/ IZkoiYqKQrvGltDMhy2kcyM2HruAffnVWD8XaG5xxPsVOPUT7AynburdaJVIJpcvX0YKjI2NRTBgIlhp q7PmPEQlh3CK7pc1QgjXGDnW6TJpolQ8WpySkqLOGvr4lVn/ONB0cbixgJsTOB83NRN4N22VNAhS487J yRGaC5m5DAE9EGv4L0DzZ/T+QCvMWqUx0l/Iilq6RiqyJyEEdzYmANz36Cj03BNljY0Ha7pHit37ZdZP Ac0tDjffTzjc1LuxY0gmCILYT+okmHHq6upIGgmUPAXNZ50nU+Tr5xC1gjXfrHmiRjHhjNBI2NHRgb+O uxypFAoAazQYbCq2GVuOXXihQdPFqqGPn1Dc1LtpMsExiz2EcSN0U2l3dnbOmzdPMkGCA/wpawqam2XY GV0BlA+6L2sCul+zZkVNWKMxCgTwLsoadzx6CXSALfzVWP8MoOlSx821Ss644SQIAJD27du3IW0E7RUr VojHiskASUFzoqYzOsyXa4wqoFHqrPlmTX8hCxqxEk04Pj4erQImhvsbW6ISrn9ps/7ZQNNFWWNR1hQ3 30lUpI38t379erGXWBqrxnqr8jwf9+xhFdAojrV6su4ravx+kYOorKwMdzD+NKwMW8IFvl+hMf7MoOlS kTbnJNgrOAkOW07aOJahssTERLGrmIlmFKwpaI41/HcgUaOUrAloLllTA6G/TSlqZjEj1BceOnQIAZ8L 1/wQgq3FNr9MoLGwuSq4qZOgBUHa1LVp/sOxjD1PT08nsW81y5oTNQohhG/W3KMBaqAVrKmB5PMMhIqa Pd8imSbBmIpcj4OJH0J+hcb4S4Gmi8OtLm3q2jSQUBvB9EhOQoE1QKuYNVhXsAYCsj/ImqY9voEoRS3d LBW7i5Ev0Y25EMI1xl/UrH9Z0HRR1nxpU9fm2wgGCkRdwhq6hofwRa1iIBS0Cm6ONcxa3UB4omaWkbTX 1tZ2/fp19GSVxsiZ9UsJGosIu6+0qY1g92iHpHMNVJaZmSl2E0vXSZ+CRvGnGGB9JmuFgaCL8hOIUtSy NPJSsCVLlmB0oo2xX7P+2UX9K4Gmi7LmpA0bgYiojcArcRSDNVSWmppKckg8jzUMhCZrGAhogi997kd/ oBWsYSBIIHSEAWjKmhW1dJMUvXfr1q0YnWBZOJhg1r/0FPOrgsZSYc23EewqTX5ojxs3bhT7ismTiTnW XNqjBsI9p6lf1pyBYIShP04NhAUNUZNxUU948OBB5Ev+FPPLGcivDRoLW09x822Es2yuPUZHR0smSp6C huEqDYR0RSrqgVkrDIQ7B8J1RRY0MZAJktWrV1+8eJFOMVyy/oUM5DcATRdlDdVwrGnyo+0Ruw2thYeH S2byWEPUynGR0ARi+gRUvocoQStYw9ZVuqJS1GSEsRZVVlZiNKfJGn3il0t7vxloLI419gesueRHUzZY nz59WqgrZBYwCtBU1DAQ2hUBl3uyb3+sFaKG29BYrSZqZjYze/bsc+fOIVkj83Bp75cwkN8SNBafNfZK nTVymNBCSJ51RllTUXNdEZTpqwWeYSAqXZGKmj4VIlmGWI1ZCQaCtPeLGshvDBrrB1lXVFSIXEWKEMKJ msZq8KUvzlBhrQT9tCvyZ0VO1KnsXC4jcznSnoqB/LwjzG8PGgv7gMWxxu6psE5OThb7ixWg1UXNveKo P9YKA0FX7FfUqTLEm/Xr1/MNBA2ZP8Jgq/59A3khQGNR1hBOv6yx80uXLoWlElLgxT1ZkoqagqasBzIQ Oiv2K+pI8tKY1tZWlQRCR5ifqyu+KKCxnsEaOeTkyZNCYyGzgiGgqXtw8QOIm9iCjTxb1PQESF/QshSZ JECycuXKnp4eJBB6vok7BwJRcwbyioDGUmHN+TXN17W1tWQ6xxSTy7oHN5RDyPTFz882EBr1+KKm7pEi k66SCk3IlZ7Onz9PzzfRcyBcV/z3Rf1igcbqlzXN11BZQkKCZJqEgMZETgfFSjbnATH/Zc9qoElXhKhL lPOLuqgnSZYtW3bmzJlnd8VXBzQWZc31RrDGBEFn9Bs3bpBkHcEoQLOnqglHmAYotyhZ/6CoaabmgZZG E1HX19efPXv2GV3xJ4v6RQSNxWeNPeRmdEisubkZaQ9oFKC5lgjEO1nW9LoJHGiONSdqdadmX4mDiR+i xpREuyJ3Yo/Oiv+mqF9Q0FjYH8hHhTWSAPY8Pj6emcEQ0LBpuAfXEvnXXunPQFRFzeU8FjRxaiNhY2Nj b28vPbGnPiv+ZFG/uKCxONaQEnYSu4odRoNCNgARHOwENLIH3KOaJQvEu5Ss+00gVNT8TE1bIuseRNT+ 5Flkp06dunDhAn9WpKKmUe+nifqFBo3FZ42Dl7KGxDAuiseIiagBmjv1QUG3sqxVDERF1PT0KUD3FTWz nBHqCPfu3ase9f5NUb/ooLEoa+yeSmMMDw9nwhkCGjaN7AGa1D12s6y5C2X9oKh5oFHi0eK4uDjEdhr1 fi5RvwSgsfisObPu7OwUOYlAioCmNg27YEE/vdjeQKLGj9CzH1xLVLoHE8aMGzfu6NGjiHo/o6hfDtBY 2CuuMVIDQfCC9JgQhlgBQMOmafag1++kF5F8hqiL2PPUai0RhfsvMzPz5xX1ywSab9Z0ikHmFVmKMCsS cJxN08sv04ujPkPU2/sOLzzQTBAza9asn1fULw1oLMpaxaxTU1MlMyVPQbM2TUCzF0d9KmoKWsmagC5X 5jw195CuI8NLVVUVFbV6/PgJmfplAo3FsYamYNbQFw5tobFQmiQloMGRgqYXW0bBQAYSdSU7vAzQEiXj Sc6DqBE/uEzNDYr8sx+KLfuh9ZKBxgJrFQOBn0pmSBSg2VkcfAnljh8SNcyd3xL57hFOnunb3d1NMzU3 KPLPfvwo93gpQfMNBAkEhzaOdGAiEOnYgn4I0F0s64FEzbVEgEZL7OseKJEDuZrksWPH6KBIz36onNJ7 fvd4+UBj8Q2EJhA4NTObISg50PBoepH2NqWoOdBK1kTUaIncqY++oCXTJHPnzj106BA9+3Hjxg16Sg8R np6n/lEt8aUEjYV94xvIpUuXED/kW9m3fgBoBA8Kmr7LAxV1vzkPLZGbElXcI4o8nNja2nr8+HHEG/pU mwcPHqAl8h98eU5Rv8SgOQOhIwzJ1IsYolwKGsEDoOm7PLSzosZ9oC5qtERMiZx78ECjxC7kigmHDx+G qOl56oFynmKzBl4vK2gsFVEfOXJE5CwiLZEPupt99xLcgKibBmiJpbxA3dc9mBlMcHDwwYMHT5w4oT68 /KiW+HKD5kRNu2JYWBgTw6iCPszqGk7dMnBL5AJ135BHTpzKhDt37lTPeT+2Jb7EoLE41rQrNjQ0SAIk xCUoaLjzIfJWSIR1F/vuMAO1ROoeajaNwjgO90BLRM7jWiJ99umPco+XGzQW9pAaCESN/RfqCuG2itMd FPRR8oZTRNrI1LQlqoOGe9DJhZ734IFG9ggNDT1w4AC/JVL3QEt8/inxpQetImqojwljyMBCrQOgj+np nWDf1quTbYl896CsqXtwk4uKTS8nk0tHRwdaIn3ott8p8dUHjYU95EQN3Yldxbot7LkODvQpwpo4NVpi v+6B7EEnl37dw0qUm5uLKfHkyZPclNhvoFZsUH/rFQHNF/WsWbNkybKnoI/r6Z1mC6JGzhvIPTC50LOm aqAl4yTLly/fv38/nRKvXr3KD9Sce2AbniHqVwE0Fl/U+fn5TAhDhu/9CtD6p/UNTxsSUe9XugcHmrKG e5SxF4vsz6aZuUxAQEBnZycXqLkTp8/vHuRSP4qbL/PiixpHt8hBRIIHRhWAPqFncNrA+IwxcOO/A7qH Ssjj2bQ0ViqUk0fH/x33eEVAY2FHsKtQFvSFKQOHPzHlwwQ05GzWYwbWUPez3IMLeX1Bo3DPpaWlUfeg z7D5se6h8Yw74eVaVNTYW+wzehezgCFyPkI6IRBb9lpa9FgQUVP34INmWStC3kA2HSAJDw+n7qGePZ5n ciGgXxlRY1+oe8BJxW5i8satCNEsaKteK9uztiZnTBTu0e95j3KeTfcFzcwnj9i2tbXx3aPfyWVA0D8Y AF+ihR3hWuL48eMRJGjkgG+AsuM5R+AmLRHj+EAhj2/TPNDSGKmAEbS0tNDJ5dy5c2+99dbt27f55z2e bdMaz7bwl2sBNCfquLg40KGd0LzH3OGcg+t5V7CGX5NxXMWmWdaqNs0DjUKazs7OhnscOXIE7qH+UADu 3WfYtMazLfylW5yooT5Mz/ANkIVBO5138rzo6XHBA9DhHuRZH2qgSchDmh6gH4pHi1etWtXe3k4fClA/ a/psmyagXzH3gG6wUziuRZYivQPEoK17rSHn0ZdG+1zygbRJ9tjL2rQKaIgaaXpr//2QCWSCgoJg09xZ 0+vXr/cb8voHzTnLK8Oac4+pU6fql+jDoO3O2kHL4y6NC7gcgBskeyDkDZSm6Uv11UGHM56ennv37uVC 3rVr11Rsmjs9rdgU3tKgzvJKtsT4+Hi9dXrUNyDniVcmTr061feSL9CTkAeb5oNmWRObpv1QLXhI15N+ 2NTUxIU8+tya57Rpcv3oZ7fLl25hJ7Ev2GFAkQfJkTfgG+ALyjPfmjn5ymS4B7HpgdL0M/qhOXl7tJ9m 0xrPeU7k5VrYF0gHwYBxYoAVdjH+8vjAa4Eh10PAGv+FTZMnjP1gP+wLGtkcYYZv0/xZ/NlpWoO7H/r9 8ku6sCOQFQ5kgUjgsMfB+6I3fGP29dkLbyyc+/ZcmDUyH3kcQP3sEu2HmA/7A435MCwsbN++fZxNP3+a 1kC75H/51WBNQUM9oaGhdoV2IDv92vT5N+Yve2fZkneWTLs6jYS8TrYf8kGzrNEPSfAAaPTDvgmPmc1M mTJlz549NE3TRxHVT3r0D5rv4q9SS6TusXnzZus4a8g5+Hpw+Dvhq99djQp9O5TY9IEB+iHmQwQPmvBU QC9h3N3dd+/e3dHRwdm0ysO1A/VDDfUTfa+MqLE7dXV15nPNIed5b89bcWvF+jvr496Lg6i9LnrpHdEj j4s/I3ioJTzpWqmZmdmuXbtg09zDteiHd+/e/cF+qEE1/+qJGnuBfQELo7FGkPOim4tibsckvp+YfDc5 +t1oBGpM52Q+7Bc0fVhLLeHJkmVCXWFlZeVAYwvXD/sB/fDhw3/n+dUv7MIuYEfQpuTm8rnX5i5/Zzm0 nH4vPft+dsJ7CUgg6If9Bw+wpglPHTSb8HJyclT64Z07d/hPNKUYVUH3+2QybKLi6y/zwl5ghx0dHUMO h0DF0PK2B9uKPihKv5++4MYCMrYgeKiAZlk/TXjqoJ1EGzduRD/s6uqiz6qhDwJwwWOgfqjBXYzslRQ1 9mXy5MkhLSHx78VDy2UflVV9XFX4QWHkO5GYy8kgrpLwKOjSgaO0tzgqKgr9kD8fcqfxqF65uUSxHezS 4NIJv2m+Gqyx/Tg6lyxZMqt4Vtq9tOIPi3c82rHz8c7qj6vj7sRhbCGDeL8JD1F6ANA0Sre2tvLnQ5VH W7jgodgOdmnQpklFTTM1vUNega5IQeNID0wNzH2QC767H+/u/Kxz1+Nd4I6hXLd74Cg90MwSKJk5cyYN HvTRlucMHhrcFfZ+3stTvCALu1BYWDhpzaTSj0qbP2k+8PmBo18e7fqsK+9B3pSrU0jCQ5TuFzSdWdRA MyHkqQc7d+7kggf/YS0uVvQDGsrnnsv+M16e4gVZAN3U1DQ+bHztx7Xtn7Uf/+r42W/O4mPlw0pM5OSM R7+gq9gn8vYLOowZPXo0QCN4cA9rPc+JafKes7/E5SlekIWNh+68Z3jDLg5/cRiUaUHdYTfC9E6xM4sK aPY9nMmjtP2CjmCcnZ1bWlr4J6afJ+FpZGdn08tTcE+x5ke9l501thyKcxnnArvo+bqHAw11I3gYnjYk J0v7A02e84gpXA20NEpqbW3d3NzMJTz6JLF+Ty31Ac0w5rh/+K8PfZW6IrYc+2XraktNgys4deztWJMz JmQ4VANNTpYOBHqt1NTUlILmP1D7g6eWNMzMloSGhuJugf7pd9OuSLvni2Yg2IwfXIpvZRf+C6GZWZvx KaOg7s3vb7bosSDPTlehjALoQuV5JRXQcVIDAwOA7jdKPwu0q2u9kVFgbGws7Yowdf71bX5RA8GhgzaC bW1sbMzPz9+0adOKFStwr2PEQMNxcnKysLAwNDSUyWQSiUTILtzAf/FJfAnf4O3tPWnSJPxIZGQkYty2 bdt27NiBeIsohV3ANmPhrxiMMuj9updfYI1x3KrXikzhKpRR6IcDgJZtlMnlcjTYfs/hqT+mpdhVFvQO R8c8Pb3RGOFxCHAGgqSiYiD4sZ/MGr8HbQCRKC8vb/Xq1YGBgcBkbjxqrIdryNSJq8Pmpq1ZuT1lY0t+ dnd1ydld9Tf2775/vOvx2aN/unz6ydvn//HOpe/fvYzCDfwXn8SX8A032prO1pV0F6S3JK/bHr0kNSx4 VWDAHB+3sbaW5ga6GL7xh5YvX/7m8DczdmTUnak78uGRni97SH3Vk3Mvx67HjiiaPb9B6nlAJ8oYhgHo gWaWZ4FG2dhslkqt6+rq6EMG1EBUEsiPMmv8FP489JWQkICEr6cjH+PuGh48Y0tMVMPW9FNNVcD0j3cu /uv2lX+3bvT+6/Kx73u7vj/e+v2hhu87Kr9vLfy+IevvFZvvpq84GRNaP39ilLPxPDdzD1M5I9bynuw9 d83cjds3xrTF2B2zk+9krz+B4nCjYB0FA4BOlolEIoBWP1kKgT5jOAToBrZ2WFquEov14Tt8A6EJ5DlH GNyZyJXQ7KJFi3Tl8gAf7zWL5pelbj7RUPXxmUOqgH7GunXxX9dO/evCoe9Pt31/uPn7rqrvdxPW31Ul fVca911B9KN1M55smfckefa9NRO753sVTrKLdBvlbSIaqvWHQT6DhgcPF6wVMAUMCRts6VSxoGm8S2aL xxoOBq9THw77fZRWgYYF3eTq2khxm5qGzZs3D+5ODYTO5c82a9zGn9m+fXt4eLiJkeGsiQHQbHtZwb1j Xao4ftF699K/rvf869KR73s6ibQP1H6/t+T75q3f1aZ9V77x0aa5T3LCWdbBTzZO/9uGSX+L9f/zau/z c83K/WVRjlrehoNHav73IM9BI0JHCBOE9NmO0gypNFUqS1KyVhYFTYdD7jmPUGe/U7gCE0C7uTXzWY8a FYyOxM3lOBa4sZJv1qCPv5GcnIy/OsHHe/PKZftKtj04cUB1/3/NeufCv946rWS9i7BuK/1+V/73OzIf pUc8KV79JHfZk4yFT1LnPNk042/xU/4cM/bxSodHS60eLTJ7tND47Az9ojHixTYj7HRe/6+h/9+w8cO0 FmhJNpD3TCOVRIpATyLWAUtEJqZT+LNBc6IkoHmsG52cyg0Np6xfv54bYbi0B9YQOH57XFyckYH+3OmT ixI3XNjToLrDv34BMeR89SQo/+vcwe/PdCj8urPq+7bt3+3M+yQ35kll/JPtMU/yVjzJXkyknTTr2/hJ j6PdH0XaP1rCsl4w6sP5RvfnGb0fatjkL13rqOmjP3jY8P8e4j5Ec7amZJ1Eii4G4hulaIb19fUAzU3h 9HkH/NMd/YJu4bEmuB0dCw0M/BMTE+E71KzBGlEGbc1AX2/e9KllqZve7tr93S2SBFT3+WcvNEyi06MK gif3ErUeaf7+UCOp7h3fd9d/f7CO6Be1v+b7rmqWb/n3+7Z/v7vo+10F/2zKebwt5knN5ifl65+URD/J X0FsJH3+t0lBn8aNeQTWK5weLbV5tMgcuias5xrdCTF8d47hO8EGe/xl6x21xugNHjbsv4d6DdWap4Uc jXxZW1uLfoiZhZvC6emOZ5xX0nB3363Gusnefque3pj09HRMmUlJSVpaWlN8x2Stj0bw+utbZ/9+A3nr 4j+VkUsVzU+oqydJHwM10GnK/q46mTSxwujvtkZ+l7Xku/Sw71Lnf5cc+l1SyHeJs0ltDmZvzPkuOeS7 lLnfpc0n35Ox+LvsZeRHtq38Ln8V+fGitd+VrPtHUezjlEUEcdHqJwVRT/Iin+QufZK16Nu0kE83BXyy Hqw9CesIu0fhlo8WmjycPwq6fi/E8FawwY1ZBteD9K/O1G/wY1bajnSSv/Ffb/x/mpqaW7ZsaWhoQMKj wyEd97jTHfS8kipoT8+Oflmbm6doatrpSqWRc2c3b8t8eKr707NHv7p44s9Xz/zt+rn//TdYkygG0dWn f1cU8136ou82Bf1z3aR/Ro39Z6T3/y7z+HaJ+5/C3b5c7Pr5YtfHi1wfh7k8Wujy8UKXhwtdPlpACjfw X9QnYS746meLXL9Y7Pp1uBt+6q9L3f++zP2fER7/XOFNfuEaf/zmJ2snfxrh82RT4JPEoCcpc56khTxJ C0V9mzLr8Sb/T+J8P4n1eRTt8Wil86Pl9oT1ItOPF4x6EGp0d46C9VtB+ldm6l+coX8hUD/fUzhHb7iV WDMgIACHOBeluSkcRz93uqMPaG/vQyzrPZS1i0ujrW21qWmJqUmRqXGCTOKSFbvq1sE9SBFg/dm5Y19f OvmXaz0ca2ogz2ZN1Lozj+grZS7L1Ac4wAWMwOuDBc735zm/P9fpTqjTu6FO74Q63QxxuhHi9HaI4/U5 jm/NcbzWX+Hz+Cq+B4Vvxk+h8OPvzXW6O8/p/nxn/Fr8ctwTn8xzuBto/M0Sx78uc/pbhOvfVnr9LXrM 39aO/3PsuE/Wejxa40kUvdr9UZQr0TVYE8s2fzTf+MO5hPWd2YZU12AN0Oem6p3z1z800SzJWW+8gdDL yysmJgZ9i5/w6MxCswMX0gD6KMu608Vll41NtZFRgYV5qb1tpatjHcrOKkVX6p4ZE/Vu9977x/d/fJqw /ubSqR9gjc8caviuctN3aQsI2eVef1niTrECAZhSoADER3l19s9Q3D1B7wbcZ9dmWp+baPROqO2deXZ3 59t9sMD+UZjDZ4scvwi3e7TIGPolKoZHwzpo4TbRNWH9Ueio+yFGYA2/VrCepndhgsH1mVbXZlhemWFV 5GUUYs7oCTTXrFmDxgj3+Oijj2DTcA/0Q+6MB1gD9HEPj257+z2mpjU2VjWOdrVuTjuUVY+ys0rTl3ul rlp+u3vfgxP7H5059Pn545Q1pmE+6+9O7CH2mjofx+w/lnngcMZRzyeLPf95sT5PnZtmcWKC4aVga9SV 2TbX5ti8HWJzM9T2Zqjl5Tn61+cYvDPH8L1QQ/gyHAP98FGYKaEcZv5ogemjecYfzyWs359NbOTtWQZX p+tfnWx0c6bV24S11dWZ1pdnWNX5miy10bWUCmNjY48ePYpBD/MhHT64oVrD0XG/lWWrg91ed5cOT9d9 Hi673JwaVFg72GQa6PgmRCy6c6gNrD/pOcxn/fe9pX/PXfG/66f8Y7kn4MI6AReH8C3WBDi4Kvv/q1XP ZLMTE0ddmGVN62IwKUA/F2x2fKbuqUDdnhl652bqXZqlfy3Y4Ca8IsTw3lwj+MbDuaNAGUV1fXe24buw kUCDG1OMb8+yfifI+u0gaxwuV2aAtfWlmTY7/c2jHPTtdMTwbrRHbtADa3iIhqN9p6fbodGeh709ur3c 93u5tXm4tLo7N/bFvcPRLs9Qb2L0gpCrbc2U9Wf12V+lhH2zatyfwl0J3HmA60jg8pSrss+/SZ2eaHJq sgkHmqszQaaHZ+gcmqZzZJrO0Wk6J6brnmahXwjSvxSkf32W/s1gA5gG+IIy6t4cwvr2DMM7gab3Z1u/ F2zzbrDNjSCb60HWV2faXJ5pc3Gm7YWZtq0TLKMcDe11Jampqch8MGskEODWGO15jK2joz2PeHsc8nI/ 4OXW7um6x925SYW1s0OZscHMReO9T6wIvLd0zAfznO7MdbgZYv/2bPtrsx2ukb1yuELKEaWyt79hnQwY dWaqqQpl1KmZJoem6xyaqqxpOodZ4sen6Z6crntmmt65QD0kDWQ7OAZ8A9BJBRren2n2YYjN/Tk278+2 BetbwTZvz7K5FmR7JciWsA6yOxdk1xJgudzBwEIuLigoQOaDtDnQlPVRsPb2OOjlBhsB6xaWNYvbsc7N psLNcrspM104aHjl6FGnA23OBNr2zLDtnWl7Nsjuwiz7C7McLgU7XCb1ArE+Nt6wZ7q5CmXUyZnGfUDz 6vBUnaNTdI5N0T05RfcMYsZ0PeQNEEc/vDHV4P5M84chNh+F2H4QYndvju17c2zfnW17M9juerDdlVl2 F4PszgfZnZ1p1xtkVzPOYoGNgT4jQujmg+Zww0YOerl3sZbd6u5Q52Zd7mZR7Gpe5GJe5GxWZCqbLxoq S3TSOTjF+uh0mxOBNqcJbvwBsLZXZ001zhX7VVL4zouzSJ2f5XAuyP5skH3PTFKnUTPsUKdm2J0MtDvB K/wXhc/Tb8B34vt72Z/Fb8A9jd+GX6vcBnJ4HfbVOzvD8vwsaxQf9ImZRv2DnqLTPZnUock6hycT4sf5 xCfqvTvD/P5smwdzbD8MsfsgxPZ+iN3dELs7c+xvzWYP7mD7S7PsLpBNsqP7kudjNs1cF6CPs3zpR441 bKTby2mfp22jh1WNq0W5s3mJs1mxk1kRLQu9KOkIqwgLSeckq8NTbY5Ptzk1A+q2OzeTsKbSvhTseFmJ lTLF54GD/nnAOh5odyTQ9tB02wPTbDqn2HSw1T7Fml9tk1VL5RvoT+HH90+16Z5GftvRQFvcJbgbyN02 w6ZzjE7PTKveIKuzQVbn2KLQj84w7J6mRnmqTjcFPUlRwM0RPzFF99R4navTzNEJbwdbwzruz7F9EGL3 INT+Xqj9+6EO74Y43Jjj8NZse+wyOODuP8OKBrtJQfctj2OjnfePtm/ztm31tNnpbtXgalnjYlHhbL7d 0azE0ayYrSJbo0Q97dEzDLQrfIy7p9ocg7Rn2J6ZYdcL3MSniMTOBjlAbhTrsUA7PlMwouD2KWvvJOs9 bO1+jqLfiR9Bcb+Bf09Q+vsCzJu8dQ5Oszg03eJooMWJGZanZlr2BBHuhwP1Dk6VH5wi7wZctvoFzRXF fcRXfn6q+ZVAy7dmWN2cBdy278+xvRdifz/U4f5ch7tzHe+EON4Kcbg+x+EKYe1AWWP3+4IGYqcDo+3b ve3avGwh572etrvdbXa5WTe5WtW5WFY7mZc59cU9igkSDhYlOunCRo5MswbuY9NQtvh4eBrB2jXVun2y TRu78xQrBUp5tU602jXRaievWiYoqlmtuC+h+D+C34DCr+LuA45+s69xnbfO7klmqL2TzNummHdNteie ZnEk0KJtqk77ZFnnZPn+KfIDU3jEp+gc7A80qQk6h311z06zOD/N4mIgGVjeCrK+Ocv29mzb90Ls7811 uDfX8d5cTKdIX45vk9BFjmOwhtSUHq2KmFabh80+D5s97ta73K13ulrtcLGsdbao5OEmxM11V0pH2Cww EdX5me2baLl7kiUiDtlt3CY7jxso61YWK0Wj4Bjws1bfO4Cirx1tUOOj3zLRbOckUrtY4qhdk0zqJjCN /szOAOnuCdK2SbL2SbKuySzxyfKDk1A6tPqADtA54qffO9UCrM9Nt7ww3fLSDKtrSHizbN8JtrsTAvcg oO/Nc8KMdpuMESTjwjbBmgVNjcJuH4fYA2VDQNPicLPSroe0n+I2J7htjdP1hBNGvvHmWjt53Tizen/z hvEWDf4Wjf4WDQGWTQGW5KO/VVMAKVVAv1Cx92WZu071WMOGCaZNqIlmqGYW+o4JhhXjJZV+kio/SfU4 yY7xTLM/Ib5voqx9oqxronz/RPlBWnzi/jrHxhkQ0IS15blplucDrS7OsL4SZPPWLLsbwXa35jjcCXV8 f67jXbBG/GXnYYwUYK0x2qFtNEEMlyBFEXNFKCvL3Wavu81uNyLtJhfLOmeLakfzSkfzcgezMnuzUpSJ PEI83DLQQJDpYVTua1bpZ17jZ143zqJ+vMWO8ZYN/paN/grcqlB+mcIfyrMXVfuNqvM3rQ8w3RFgCuKN LPRqf73tfpLSsZIyX0m5b1/i46W7/aV7A2TtAbKuCfIDfNzjdI77G/UBPd3qfKD1RQwsQbbXSMKzvzkH LdHxDjEQha7B+vocRw0v292etntQHqBsQ6sPayXodrYIbjebVlfrFmerRifLOkfgtqhyMK9wAHHzchvj bF3hlJFvaIebM2VjzSp8zar9zGv9LOoJbsIa9atJu97PrNCZAWV+UeJl4+VFvuLiMeKSsZLtYxXEK0Dc V1w5VlLjK2nwY3aOk+7xl7UFyDonKAR+wFd+YoJxz1QL1j0s4R4AfSHQ+sIMMhZenmV3dZYdIgeCxzsh ju+GOkLRwE1Za3jY7PSwbYUzsNWHtTtbStBt7qTa3WxQ+1yt97hY7XKxanGybHC0qHcwr3EwB25Fmemt lWq6+khHxNrrQtpVvpC2Rb/S/kVxV/uMKnGXq4CmVeQrLRgrLvQRF40hxREvGysuHyOuYKtqjKTel2ny Y3aPl+71JwLvHCM7OdHkzBRzgO6dZnl2utU5FvTFGTaXZtpeCrK7Emx/NZjMyUgdN+Y4srjJCTWUhpt1 ozsynM0uD5vdHGvWJRSgSdm2Aa6bDT6CcoerotpcrPc4W+1yJrgbHS12OFrUOZjXstBr7M0qjaSLhMNM p+hpJ7sYVPqaq0sbuBv8rQrGmKd4msQ4G4XbGQZb6k001RltJHPSZ6x0GGOpWE8ikoqEYqFQKBCgcAP/ xSfxJXwDvg3fjB/BD+LH8UvwqwrHmDeyoMs99cu89FQQo2r9TQp8Jfk+4vzRpAp8nhIvQfmIS33EZT7i CtQYceUYSa2vpNGP2eUn3eslPTbR9NRk8zNTFazPBRLrgKIp6Muz7K/MskfYAOu3ZjvQ87SQ8y2ARmdD nHCzbkGvA2t3ND0FaFJEvDZ7Xa1JsbfbXG3aQdnNthPF4XaxbmVxN7ECB/F6WrYm+friWdpD5EFGwgx3 I0g7y9NkrZPRQhuDiaZyF33GiBGbmJg4OTn5+fkFBgYuWLAgMjJy3bp1SUlJWVlZeXl527dvr6ioqK6u rmNXbW1tVVVVWVlZYWFhdnZ2SkpKXFxcVFTUokWLZs6cOX78eBcXF1NT01GM2NVA6iEeNsdcstZFP3u0 ER905XjD/LFiDjRXwE1qtKh4tKhktHj7aIK7XIm7erSk2Ut+IMD0yESzE5PNT0+x6KGiBmj2jBIHGgn6 ajBhjcjBnRbXQHJwtqhClnCzakajc7dpZVnvcVPw3UMpu7DlSlijONZdbFHi+1ysdysFDuJw8AbC3bLR 3CiDEUwd9EeBePhQzZEj3N3dp06dunjx4vXr1+fk5FRWVoJdTU0NIALlDnY1sKuxsbFJuZr7Wy3sUvyH t0pKSqKjo0dqj/Se7G3vZT9Se4SFXNvPWLLARp7gZrBtjE6/oEl5iwu8RWBd6C0q9u6L21Nc56nTOs64 3d/k4ASzo5PNTxLWVmcDrc/PsAFrgL40y56wZkFD11fZByKQOkgzxNCBfOZsUYGM7GrVCGm7Wu9ytd7N IibFClYBegDW+9mixKnAdztY7rS1aLYybzI3a7Kw2Glt3WpqmiOTBY8caTBt2rTNmzeXlpaWl5cDMdQK xPX19RxZkAK+nTt37mJXa2vrbnbtUa69AyzFl/fswTfHxsY6jXZKrU1FpVSnrExbOXvF7LGBYy2dLcWi 1+303phmNmy1g2aeGuh8LxGqgC3gLlLiLnUX13nptfiN2uVnsme8SWeA2aFJ5senWJ4mrG3OzySn7gjo YAKasGZBU9YoChqFMa/MyaLKyXKHs1UzGp2rdSt4sUVZP8WtZA0boaz3u9sdQLnZHnCy2W9n1WFl0WZl 1WZj02Fn1+no2OXsvN/JiZSz8wFr6+36+gu0tEwnTZoUHx8PIUPFVL/gC7jAClKgtm/fvra2tnZ2dXR0 dLKrS7n2qy3FF7q66HfOmjUrcHFgVnNWVlNWZmNmRkNGxo6M9Pr0LXVbZLGyodOGvu78+v/o/Y+e+DUf w8HhtiMyPYUsaEKZlCcpylqhbhdx3WiDJt9RmDZ3jjNuHW+6L8D0wCTzo1MsT06z7p1hew6siajREgno K0rQtDQcTAsczAodTIvsUWYlDuaVThb1zpaNcAD4wECslbgJa1fbTkfrTnvr/dZWB2xsjjg4HHd2PuHm dtLV9TjKxeWoi8thlLMz+YhydT1ib7/DyGilWOzs4+OzatUquAcQU82CL8V64MCBgwcPdrPr0KFDhw8f PsKuo+w6prbo5+n34JsdHBxicmLy9uZt27Mtd3dubmvu1l1bs3dmR9VGCdOFWrFaWlFaWiu0hgcNH+w9 +DWT1xjh/3gbDA63HpHt8RT0U9woR1Gdj9GOsaMafI2b/cDaBKz3+Jt1TrQ4NMXqxDTrHsKanC6GexBd s6fmcRtB8GTAKA170wI7kwJ700I7RRWzibgG9joA66e4naz32VnutbLYZw3Q9t0s3zNubr3u7mfZ6nVz 63FzO+3mdsrNDV8iRenjhrv7CReXAxYWKTo6U0aOZObOnUsvdgZtgizFCnwnTpw4efLkqVOnTp8+febM mZ6enl7lOstbik/19uIb8G3on9ZO1iX7S1DFXcVFnUWowo7CgraCaVXTBOkCQZxAe4229mq2orQJ8eDh gz0Gv2bwmr7gtQDDodH2mnzW+e5QtLR2jFHdGMrapNnPpGW8aau/2Z4A87YJlgenWB2bRk4XnwXrIPtL wfYIJKcnmXaP1T3mP+rMZAsNO5N8lK1JAcoO0AnrIjvTUsRh5Ae0NeBGqODjdrbeY2+5x9pij7nZbviD o+NBF5cjLi7HWIigeRqI3d3PeXhcYOs8W4Q7ysPjjLJ62Or19Dzn4FBrbLyKYdypwOmbVIEXwAHi+fPn L168eIldV65cuXr16rVr195SW/gkFr6K70Fumb5wevWJ6urj1VXHqiqPVlYcrag4UlF2qMy50lmUKRIm CIXrhYJ1AkGsQBAj0I5mcS/V0lyg+ab/m2/YvDFo2P+zl74x1/zNTHchQOe5iLa76VT7GNX4jKobO6re 17jRz6R5nOlOf7PWAPO9Eyz2TbTsmmJ1ZJoNnOTIRJPucYbdfvonJpj0TEX4c0ABdJ4tKbAmpWRNpG1v hnmvli9tJ6vdtpa7Lc13w4Lhv05OUPEhFPUE1iWAG2olrMHX0/Oip+dlL68r7EfUJRQ+6eXVp7y9L48e fcXL65yd3fZRo5ZKJE4IauhmsG9QA77r16+//fbbN2/efOedd26x6za77vAW/cy77Jo8eXJ8QXzT+abG c42NZxsbzjbU99TXnakrP1luWG0ozhGLkkSijSJRgkgYT4gL1wkF0QLtZdpaYVpa87S0QrVGBo0c6jH0 NaPX9IWvTRk1LN5aq8xDr2q0Uc2YUbVjCOh6XxPCerzZLn/z1gkWcJKmMYY7vHSbPOVtvkaHJlicnmbb G2h/bob9+Rn2BLS+eLqtyTa21HE/lba9RZONebO5WYuNTZuDA/obENMioClrmC9bxBlgF2Dt6XkeZL29 r3p7v+XtfX30aK7e8vG55uODj09rzJjrY8a8PXbsO6NHX3J0rDI2DpPJ3Dw9PSMiIpCajx8//t57791l 17179+6z68GDBx+oLRi6jbMN+O55a8/ua7tbr7W2Xm3ddWVXy6WWtUfXSuukkq0S8RaxOEUsThaLE8Wi zazAY4WC5QLBMoF2mLb2Am2t+Qrib45/8w3TN4Sv//d0I2Gykx6mTbCuG0tAQ9o1ow2qvPTK3WSVbrI6 L/3msca7/a3aJ1p3T7Y5NtX21HS7nkD7syxrjWH/85qOwM/KaEt/uIm0rU2KLUzKTIyrrKxaHBzanJxI inB2PsgWAe3iwikadcTN7aib2zHWhU/BHOAMlPXo0W/7+NwcM+bWmDHv0ho7ltYttnDjtq/vHT8/1Ht+ fnd9fC6gXFx2WFltNDAIkkis/P39YSzIhbDvDz/88OHDhx+z69GjR5988gn9iJWZmRkSGdJ5u7Pjdkf7 u+2kbrXvu7lv3419k7snM7WMJF8iyZJIMiWSDIlki0SSJhEniUVxIuEqoXC5ULBEIFgsECxiiS/U1p6v rTlGE1OVl5eXrtbwyfqCBFtmu5u82JkpdJRsd5VVeurX+Rg3jbNsGWe509+q1d9qT4DVvgDr/ZNsj0yx PTnN7kygPaStkeJqMF5HkxnpbKYXq2StwG1lnG82Kt/IMN/MrMzGptbOrtnBodXREaxhGoS1i0s3S5nK mVP0UXf3Y2wdd3c/6el52sur19v7AswBsoVgKVBf3/dBEzVu3D227rP1gK0Pxo37cOzYG2PH3vTzu+Xn d3vcuPd8fa+5u++0t081M5uvq+umrS1EgIMXY3RE/4SxfM6uL774AiNiRn1G973u7vvd+Hjw7kHU/vf2 d93pst1vK62RMkUMk8cwuQyzlSHEsyTiNLFog0i0RiSKEokiRcAtXCYULhFqL9IeOX/kEKshBgYGGDhf f/31YcOGCwa9PkFHM8lBp3q0ce0Y03pfs3pf80Y/C8J6vNUuBWvrvRNsOifaHp5iewKsp9tp5HmZ5HiO mmkoFAwdNUq2mIK2Nt5mZpRrZJhralpsZVVua1vNVo2dXYODQ4uj414npw5n5y4XF7A+5OqKIpTd3Kic FaA9PI6jPD0p6x5v73PwhDFjroKgr++7fn7vs2Q/HD/+o/HjH44f/8jf/1FAAOqTgIDHKEp//PgPAgI+ mDDhg0mTPpoy5aPAwIdBQQ+Dgz+eNq3H37/J23uLo+MSc3N/XV0LOzu7gICAiRMnWmPKurGn672u/Xf3 H7x3kOBGPejOuJ4h65IBtLREKi2UMvmMJE8izhULs4SCFIHmOs2Rq0YOXz58WPiwIWFD3pj3xushr/9x 9h9fn/3G/4j+aGnpNG7czFmzli1ZEh8aGuXpGWAk0JpjKsvzgIeY7fAz3+Fn0TjOonm8FVjvBO4A6z0T COv2iTbdk21hIxpFo03zvAnrxeaM5iCBnmi6mdHWUYZbTU0LLC2329hAy+U2NpUoJe46e/tmR8dWJ6c2 lvUBV9duN7fDbAExLQVlCtrLC3XKy+uMt3evj8/5MWMujx37lq/vO7AI0Bw//kMW8eMJEz6bMOGLiRO/ mDTpi8mT8fHjyZMfTZ36ybRpnwQGPp458/GsWZ/OmfPp3Lmfzp//aVjYZ0uXfhYZ+fnq1Z/Hxn4eF/d4 zZprkZEH7e2D5kaHtd/uarvdue9W+9532nbf2NP6duuu67vGdI15o+KN17Nefz3t9deTSb2R9MagpEGD Ng0avG7I4KjBgyOHDl325rBlw99cPnJEhObICG2t5cKRMwXDho2IiEhYtmxTRMTmyMjkqKjU1avTw8LW entPsJOKIqz1a30J6IZxYG0J1s3+Vjv9rcF6N4u7bYLNgUm2GmVjTYt9COutnsazTZk//Nd/aWqOHjUq ydq6FKUETVjb2lbZ2VXb2UHXtfb29Y6OLU5Oe1xcOlxdD7i5dbu7H3Z3P+LhcdTDA5SPeXoC8QlaLOiT 3t6nvL1Pe3v3jB59dsyYC8Dt6/uWn987sAV///v+/g9Z1gTx1KlfBgZ+OWPGpzNnfhocDLifhYR8Nm/e 5wsXfrFo0RdLl34REfHFihVfRkd/uW7dlwkJXyYmfrVly9fZ2V9nZn4oYnSL91ceeXj6yEenjjw8dfTj U0cfnTrGlvVxO6ZFLqmQS0rlkhJS4iKZuFAmypWKUqXCjYwwTiJcKxHESARrJILVYpT2KvFIH21XVz/A XbkybdWqtDVrstauzV63buuGDQWbNhUvXrze3X28r4F0k/OohnGWKMLa3xrFsW7xs2oaba1R4WsG1uke xtPN5HpCLRjchAkTBAI7Q8OV1tZltADa1halYG1vX2NvX+vgANaNzs6tLi5tbm5d7u4HwRqgPT0p5eNe XkDMp0xq9OjTbPX4+JxVqvuan9/NcePujB9/PyDg4YQJn06a9CVYz5jx+ezZn4eEfDl//pdhYV8tXvxV RMRXUVHfREd/Exv7TVzcN5s2/Skl5U8ZGX/euvXPhYV/KSv7duXKxolzAo89OnPskzPHH5858bjn5Kc9 J/HxcU/SrTTpIR2mQQkatZ1lXSgT58pEKVLRZkYYzwjXM8J1jDCW4YgPt9QKDFy8Zk1GTExWbOzW9evz 4uMLN20qSU4uT0urycioz85unD8/Wl8oDLHQK/Exaxxv2QQD8bfe4WtV621V42lV7WFZ62GhUe1nvtrR 0E1PguwZFxeXlpaWnJw8b9684cOlOjozLS23saJWsLazq7Szq7K3J6xZ0KgdTk7Nrq573Nw63N0PeHgc 8vQ84uV1zMuLgPb2BmJafUD7+Jxhi+AeM+bc2LEXx4694uf39rhx744ff9ff/8MJEz6BgUyf/uWsWV+F hn4dFvZ1ePg3K1b8KTr6T+vW/Sk+/k+JiX/esuXPOTl/KSj4trT026qqvzY2/s3PLzy5MuPkp70nP+s9 9fnZ02ydwu3PeidemCpt12HqdZgqHaacrTI5iog6h4KWijYoK05BXLBYMlyoBTmvW7ctLi4/IQEqLklM rEhLq87M3JGT07xtW2t+/t6iorbU1Mrp0xe660qjbUdVeVlWuJMqd7eocDOvckeZacy21NUTC1esWJGb m7t161Zko4yMjC1btqCh+/r6isUexsZrbW3LWEUDdAVY29tXOThUY5xzdKxzcgLoBmfnRheXXW5u+9zd Oz08Dnp5HfbyOurtfdzbm7IGX1pUzk9LSRzeDeLnx4695Ot7lRL3978bEPARBD55MtT9VUgIwR0R8c2q VYQ15JyaSkAXFX1bXv7Xurq/pqaedBnjvf/9I4TyZwrKtNo/6TI5ZSFt1WFqWdAVbBHWOpIiuThTJk6R ihOlogS24tliiWtPFHt4+G/YkA8Vb9xYvHlzWWpqVXp6XXZ2U15ea2FhGyJPWdnBlJQDS5d2Tp3aaWWV POIN7ck68kwHkzJXs3I3RVUCdFBQUFZWVlFREYaC/Pz8vLw8EMfKzs7G5+fPn6+pqaenN9vaOs/ODqDL 7e0ButLBocrRscbRsdbJibBmQaOaXF13ubu3eXh0eXp2e3kd8fY+Nnr0idGjT7I1IG5UX40T4kqN34LG AwKg8cewlMBAIvBFi75ZvvybNWuItIF769a/FBd/O2VK/Mq02BOPe0/0VTQq8sYq6SFdpkmHqdZhKtli WRMDyZeLtwC0TJwoE2+k9ZS4pp1w9uxIVsWlyckQck1mZn1OTkt29p74+PYlS7oCAw/4+cEzD8A/nZx2 4fgGKIaZaactWm1mUOZqWu5mWuZGPmqUsQtTAAIpVgm7itkF+lhJSUnITAzjYWoaY29f4eAAyqQcHavB 2tm51tm5ztkZrBvYF9CBdbObG8Xd6eXVzb6iQB23Kmh+KYn3wlWUMoeP3+DJ/DGVOaAvXkwsZdGiy6Ms 7Wp7Wo9+3HvsUe+xT3qPc8Q/O+vS6yFt02F2qIFGS8yVi9NZ0Jtl4k282igTLmVGigToe/HxpdHRFUuX Vs2ZUz1lSr2fX4uHx26kAGfnvc7OuIEAhlzQAMpwVPagL9XXjxQP0QrWl4MyLY0KdtGHOaqrq+nHmpoa 7iMWPrl69WptbR19/Rk2NpmYj1FOTtVsEdYuLnUuLvUuLg3QtZJ1i7v7Lg+PfZ6enZ6exExY4seVrFXh 9ls8mT+FrlT6O+PHk7gSEPAx7MXMLDVk1fIDD3oPPujt/qC3+8PeQx/1Hn7Ye+Rhb9LNLNFBPcEOHUGF XFgmF5aSEuFjiUyYLxNskQlSZILNMkGCVDuelNYGqWacdOR66dAxIgODSe7uBc7ORXZ2SLq0iIXCPMEU LYrappOTovAZOCq+ikPf1DRJIPAbyzBpdqMIaAqUPozU0NBAHzfiP8CBhdtY5eXlCxYsYBh7E5Mljo7l Tk5Vzs6gzBXB7epaz76Kn7w2lL7My81tp7v7Hk/Pdi+vA97eh/rifl7itPjclQ6DLnrZw+OAVM+0sLOu 697prntn9pPqUdT9Ho9jE99skr9ZKnuzQPZmnuzNfNnwPFJv5siGpcmGJkiHxkmHxkiHrpEOiWZ4JXlN X0tHJ9zcPNXcPI2tDEvLLGvrbba2Rba2pax5AjT4tjg773R23sV+RDVB2g4OmDYQ0rZLpbNttYQx5gYa QLxjx47Gxsbm5mb66EZbW1tHR0cX+ygGPfuOj1j4b2dnJxrmtGnTdHXHWlrGOjtXs1Xj4gLKtIi0WdYK J1HipgJvg8C9vA56e/8UgasXRW9ktHrmsrCuuye77p5S1D1F5d2oEnUYDatihhYyQ7cxQ3OZoVtJDcmR DEmXDN4kHhwnHrxWPHg1LRFXbwQK/vCHEcbGG0xM4k1NN5qZJVpYpFlaZlpZ5draltjZlTk41Dg5NYEv rMPVda+r6z5kAfYG8u5OfIlVN8aOcn39ZTpDtTQ4xHv37m1vbwfNQ4cOHT169AS7zpw5c/r06Z6eHnrq HZ85fvw4vpqYmCgS6RgaTrWxSaK4XVyAeyDi5IWLPOK7WeJdrIOThvnvEMd+MromeW1VLGjV8jseOLRZ MnS7eGieeOg28dBc8dCtpIZkiYakiAbHCQfHCgevEQ5erVp/dNASCscbG69Xgk42N99iZZVtY5MPC2Z9 Y4eLSwuba9sxRrCTRCebcTvc3PYig7HSxrRRgSNg1KjVGvAEqmJo9vDhw8eOHQPQs2fPXrhw4dKlS5cv X77GnmXHxytXruC/58+f7+3txR0Aya9du1YiMRk1KtjOLl2pbg66Cm7qJxxuSpxYCo/4T9G4gcHK4MjF fLhcVd7aKe00GVojGVrEglZSHpojHpIuGrKJBb1WFTFq0CLBHwQjdHXDjY3jTEwSTE03m5mlWFhAzvCN YogUudbZucXFZTcou7sDMQaIg2wdYEFD3dA1LBtWXmJjk2ttnaGxb98+GEJ3dzd0CtkCMfgC640bN27d uvXuu+/euXPnPXbhBj6Dz4M7oFPicHBkcIaxMDaeY2eX4ewM46b1o4i38lyF83EElR/wcchKz9Sq+EC9 CmJaU06GDNvJDC0TD81Xk3OqaPAGVs4xqpRRr4/VHjHC1dh4HawDcjY1TYScWYPOg+2i16EH8uaGA8iy +MhWp7s7DASujVGuwtER3wxDz7OxydGAMOEV8AT4w8WLF69evQqU4Pv+++8/ePCAnvbF+uijj3D7gw8+ uH//PiX+9ttvQ+AQPn4QXXTZsmUMYzlq1Bxb2y083D9MnO8q6JweHnt5MlexclXourqLF65bqcKXVs27 rfIus6G1kqHF/cl584ByRv2PwUipNFjpG5uUvpFjY1PAujNGB2x2KyIsTbEs37301ccuLki60Du8BSEY JoPEAtDZGrCLkydPUiGDHRDfvXsXiAH3k08++eyzz+h5XroeP3788ccfgzhwQ+McbqgbZlJfX8/iNjUy QgpM7IubloqVD9Q51aGrKJ1wx1Fs7eZe27NbBTEtIuddA8g5TTQ4Xjh4Xf9yfmOKYOhQaypnExPIGb6R amGRwbZBUCN5A3MDpjN2QINNNyt3ATLH5+uxm4hkjo64S0rs7QsB2s4uVwOODEywgps3b0KqIEgRA+tX X331zTff/OlPf/ozu3Dj66+//vLLL0Ef3wCNU3W/8847MBPcT7i38NvQXaOiosRifUPDiZaWa9VYczWQ zNWhE+6svSCVP+UukUxfnbVRhS+tsneaiDv3K+cM0ZBEpZyjVSmjXrPSFIkmsXKOMzWFogE6CZHDyirT xmarrS2aYREIgiPMgc21ZOOVO4L/wlgqnJzw1VKUknW+Bo59ODJgQaFwhkePHoEjEAPrX/7yl7/+9a9/ U64nT57gv5Q4cH/66af4ZvzIvXv3cBzgfoLtwHxg3PB6ZJi4uLhx48bp6nqZmS1xcMjtS1mlVKCrKl2d +6hR0WOmT26/fbTz7gmuuhSFsDF92E7JkNIfL+dZ2n8YMhyBDDkBf2LUqBhj41gTk/VmZvEWFpssLdNs bLKgUBgCyxpdsdLJqZK3I7hNimWNrxLcDg7bHRyKNSBGOADsAoZAhQzZgiaY/v3vf6cvr8XCDbo43Pi2 L774gpoJrAaeTp0EBwc1bjgSGmxmZuasWbNg30ZGgVZWcbxtGqj6sRcVvWM/RTL9tB3bOu8eV6+st4pE 7QZDq0VDioVDtgmHbFXU4Gzh4HTh4EThoDjBoFjBoGjBoNW0tAetUtQfHUdoaXkYGCwxMFhmaLjcyGgl cJuYrDUz22BuvtnSMgX5wdY2x94erAtZ1qUQL7CyfLld4FgrpA3W5ELdcAD4AJDRS/pAyNAvmIIvfXE+ 1nfswn8pdHzDt99+i2+G9nHfcE6CwwIHx/Xr1znjprgxxMNPBAKhjo67icl8W9tU3mY9u1R6KUEvkwWF rl7SefdYv+V22Hdoo3BIqWBIvmBIrmDIVsGQHFKDswSDUwSDNmgPWqc9aM1TuFy9Ear1h5HD8Mv19ReD taEhWK8YNSrKxGSNmdl6c/ONFhZJ1tZb0Nns7LaxoLezoCllPmgU/cxTaWuADiQJH6B2AbVCsxQxyNJL IPyf8lqV+C/HGnqn0oaPc05C+yRn3Cq4ESKzsrLmzp2LYUdPz8fUdLFaRPnhMjGJcfTxrjvb2vn+MfVa c2HjiH3M0CrhkELBkG18ytqDt2gP3qw9aL3WoLVag1ZrDVqlWq+5DB850klPb6G+fhhlbWQUwYKOMTUl oKFoGxsoeqvSPQBaXc78UrC2sUnVAGWYMt8u1Clzi7LmS7tfJ6HGrYKbjpfHjh1DmsQgmpycHBwcDOK6 ut7QuI3NZrWt7KewhyMF0oTSLSp8uTI74DB0h2BIiWBIXl85Z2gPTtYeFKc1KFZr0BpVxKg35mn+QXso w0zT01ugpwfQ4VC0kVGksfEqU1NYBzw60cqKejTkXADbZeVc/gzQ2CnsGroUdlODM2UVu2AV3IcyXfTz fNy4bzgnwa/iUiAfN8yEejdaJZIJ5njEyoMHD2IuBfHQ0FC4ikzmCB+3sFhlb5+jssVc4bieHbVIBS5X M0/PH7ZbOLSCNQ2+nDNZOW96ppxdh48Y4airC8oL9PUXsdYBOa+Eb5iarmPlnGxtnQ6DZuVMfYOT81PQ 2HjsAnYEu4OdCgwMjImJKSwsJO+VxTflfoWsvlRYU9yQNn7VM3DTVolkQoMgpiT4CQSO6b+joyM3N3f5 8uUBAQFisR6sfNSoWZaWq+3ts7l9gLjcxvkOZBrbrpcyHUZD6wRDivvKOVswOF17cJKScr9yDlWR82JW zstZOcegE1pYbGblnIlEbGfHyVkBGhuJTcUGY7Ox8WPHjl2wYMHmzZu5c861tbUaUCIOf1AeyC4GWkTY ak7yDNy0VdIhHoESuZvzEypwODg9QYgknpaWFh4ejnQoEjEymQMiuYHBTKmeQWpdjgpfrlwOjxnaLBhS ptYDIedU7UEJWoPWaQ2KUUVM6zUnuLMzT87wDch5hbFxNCvnBFbOW2xtFW3Q1jbTwmKticlCQ8MJ2Dxs pI+PD45LJNqioiL+mWcMcfTkqOIdOn8sZW71i5satwpurlUiCNLcTc+ZUIHThgkH5xNva2traWnJzs5e uXKlsbHxssRlbbfb2u50tN/pan/vQMd73R3vHep4/0jn+0cX9EYM2ysaWikYUsSaBkBzPRBy5npgtCpi 1OvBI/8wYqhMNoOTs4HBUipn2gZNTVeNGhU+alSInt5kudxLIrEQChlXV9epU6cuWbIkKSmpvLxchSyF y3/1Anlz359MmVvPgxutEsmEBkHkbs5POIFzDs4nDlcBcUz2syNnH/vkGOrIx0cOfXTo4IOD++/v77zb 2f5ee961fFm7zqCaoYOKhg7KfXNQzvDBOSMGZ49EDUofOShZc9AGzUGxmoNiNPsixn9J/Y/N0BEj7KTS iQwznmHGSCToXS5CoZ1AYKGtbaCpKdHT07OxsYFmZ86cGRERAU+AbKktAC5HlnvYhIPLvXoBiiHvCw46 lJQC209d9Jc8Gzed4Pl+QgVOHRyzJSXOaRyukpKS4jvNt+Viy4lPT5x4TOr44+NP65PjY3rGCNoEmrWa I7aPGF44/M28N4fmDh26dejgzMGDUge9kfDG67Gv/3HNH/8Y9cc/ruhbK//42qTX/t8b/08ikejq6uKg sbKycnR09PLyQqtAKIJ9rVu3Lj09HUdVfn5+cXExfd0N9EsfkKJn8zmyu3bt4l63ALjt7e1QCY5OtH0N KmQsBa1/e9HfpoKbSyY0d9Mxh/rJw4cPOQdXJw7V2LrYFrYXnvz0JIqw5oqFvvjaYvFhsWinSFgjFFYI hWVCYalQuF0oKBYICgSCbIF2irZ2orb2Rm3teFJa8VpPK05ruN1wPz+/xYsXg+nSpUvRjWFT0dHR4JuQ kIBElJGRgS5dUFBQVlZWWVkJxBAvlS3VLJ8sFn1dCIWLPo/jEkcn2r4G5aKA9PMt+mv5uLEobggcuFUE DuKcpXDEsZV6hnrJFcmnPj916jNSJz87SYqFjtp6Z6vxcWPxHrGoXiSqEonKRU9BFwkEuQLtNG0CerOC skqNnDoSngCfhTUB8YoVK1atWoU0tn79+o0bN4JyZmYmKMMoIGTc5RQx+AIuyGJRzdKH/ShZLO5FIbBB HJc4OtH2CWgFm19gqeDmBE79hAocxCFwODhnKZQ4vBsIojOjT39xmtTnpwluWiz0A58ccOlxkXRKxE1i cbVYXCkGaFGZSFQqEpYIhflC8jTRVIEgSSDYJBAkqJZ2pPZwk+Gw3cjISKgYiNesWRMbGxsfH5+YmIjY w72iFEKGEUPC0C+FC7JoHmghVLMIqZQsfcAPUYrCxUGJYQ0dCGOEhgLJL7k43HyBc37COTi1FI74hg0b lsQtOfPlGVJfkFIQZ6GjplycIj0kZXYxkjqJpEoirhCLy8XiMrFou0hUJBJtFQnThMJkoXCzULhRKNgo UJQStOYYTfqSGRgF1tq1a/EXN23ahJYAU+aEDC+Giili8IVsqRugeaCFUM1yZOlrbRClEKhggPS1ILdv 38Yx+muA5hZHXEXg6sShppDIkIP3Dire++DLHgVxJfSIGxE6J3Ske6RMA8NUM0wVI6mQSMolkjKJuEQs zhOLMkSiNJEoSSTcJCS1sU9pz9MewYyAXUDCsGPkXzgygtqWLVtycnLQ9yBkeAXaHfobfcya8oVmKVb0 D4oVmkVHAVnIlpKF71G4sEH0HnQgHKO/Kmi6ONx8gfOJYycDwwL3vb2v96teVM9X5E0mSCmhp72fZnrK VNYukzZJpXVSCpqpIAXQkkKJJEciTheLUxUvURFt6lPCdUItB61Zs2bBJcAXKgbi1NRU3Lvbtm1DtKio qIBXwIvR3IAYngvxgi91A4qVEyxGMJBFVAXZu3fvgix8j8KFDSLO4ujEMfobgOYWRxy4OeLYw0lzJiHM PX3bFBY3B732Ya3DWQd5l1y2UyarZ5/BXyWVVpJiyhimhGG2MeTFKWkSSbIEoElt7lPak7R9fX0BF+0O fKFiIKZegWiBaAw7RvgFYpgvJHzu3DnwBVy0Dc4KkEopVqpZzGKULLo6yFK4SFbo9uj5OEZ/S9Dc4ojD DQOCAnac2XH267Oop6yVdfiLw6MvjNY5rCNvlcsaZbJamaxGJqsiJa2QSkul0gIpk8Uw6YwkVSJJ7KdE i0Ra+lpwDBgxQgWMgqY3HEYIyPAK2DEiGowCKgZiGC7EC77QLOBSrGCKVEqxUs1iFuPIotMALjwQC90e PR+u+EKApgs68p/hX3eqjlJWKQp68pXJusd0dfbqyJvk8nq5vFYur5HLq+WEdZlMWiRlchgmk2G2MEwK wySplmSDROAiCAsLA18sGEVhYWFJSQm8ggoZHQ9ChhfDKKiK4Qzgy7cCjikWWjfFyieLTkPhwgaRr+CH cMUXBTRGLGi57nQd93ZWiuKxnnN9ju5JXZ12HXlLH8rkXfEqZLISmWybTJollaaTt/WQJvcpJpmAFk0S TZkyBaENiyKGV0DICMjUkREqIGT0OhgxjAIWAcOFeKkVcFhhBRzWgchi0d7Ddv1/vhCgsauTQyYTx1Ch zKvFNxcbnDbQ7dAlb4y3Q/l+3uwbAZH3pt8ul+XLZNnsm6ekqVKmJVkoEegKEJDhxRQxFTJNb5g7YBdw ZMQJCBlGjMwAFUO/1BAAF0wBlDLlY+2XLBYaD9vyyez924PGbs9YNKPlUosKWX6tvLVy1JlRul0s5Ubl m3lzlMvk5I2ABng7XlrSNVKhvXD16tVAXFpaCsRIb2i8oIwxj6OMxIaUBsoQMvwXlKFfqlmKlQLFokzp 4rByZLFo48Giu/lbgsYOoCOFrgxtu9mmQpZfMbdjyHt479clbyCmTrmcfWP6HJnira1SVRHTEvmK5s2b B8T0lAWEDLtoYd9oE2MIAhzmDlBG30PTo08IgFFAxdAvRcwBpWsgrFiK3eu7fjPQaC+YFJYlLDv04JAK WX6tu7NOlTJMg1Kukssr5ORd6bcS0+j3jelpSWZIBAIBcgV9yn1NTQ3SBVrfHvZdNkEZAx4cA5Q5LYMy LBj+AFugiClWBUvlUuzMc6zfBjQaupGpUWxOrApWlQJl8x5z3QPPpLyNpQzTGIAys4gRGgkRlrkzyJQy HAMx7hD79m2cL4My1TIoQ8iwCCCmfBWb/lPXbwAau+fk5ZRem66CVaUUjgHKu3V0mpSU6ZsNUsol7Fvw PtuaV0lFdqK1a9fS147Qk5yUMgbr7u7uEydOICwjYyDGISMjwKH1US1TI4aQ/33KWL8qaKgDvWhC8ISy g2UqWFUK3e+pY/SlTN5sEJS3y+V5P9QAE6Rib/HixYs5yrT77WLfIe/AgQM0L1++fBnDNMIyzRjofmh9 nCn/LHLG+vVAo8msX79+YczCfdf3qWBVqfCb4SRjqPgyR5kNc+TNdyll9fd2VJYkgLwrPaUM06irq0Na R16m5+GoNXMNED0DYRkxDi365zUNun4l0Bi3bJxsEgoTMN2pYFWpkOshhqcNSZL79ygzMxiBRIDZmm/N iBlogAhzsGYMJufPn7/W3xsK/rymQdcvDhpbj2EX88j2/dtVmKrUkS+PkLf5P6WnmEqeTbnf9ylVFhPK CA0UDRCLhjm+NR8/fhzj3xX2PXbv3r2L2Q+D3y9kGnT9sqBxeCJdrExe2XWnSwWrStU/qve55KN3XE+3 vS9lNmP0T3mAyMyEMyIzUXx8PL8BqlgzUjOSDx2ykZphGpitfyHToEtje1HiL1HpqdHTpoz1muCRVpdy 9OPDz65NN+ItjpkJ27UEDVra1ZraZZrapZraJZraxaS0Ckdq5Y3U2jpSa8tIzaQRmptHaG4coblhhGZc PzViwZvDjAf7+DiHzJ4UOmfS3NAp8+dODVswfdHCGUvDgyIj5kStmBezeuG6teEJG5YlblyRlrw6c8ua 7MzYbTlx+dviC/MSivI3FhdsKincrLJH/2b9IopubW01tzFflbrqB4WMQsCw6LHQPairu0dXp1ntPAZN cs+nZRLmnETLly/ntMw1QEyA1JqRmmHNSM3UmmmeoxMgnU24wUSxMz/T6qPo0uIkWmUlycpKKd+OSkVV lKLSKsrSKsu2oKrK0xVVkVFNKrOmMjM+LsLX121SyIRtu7cee3REtT7pU10POyac9ZccFglbBcJ6bWG1 trBcW1imLSzVFm4nJSjWEhRoCXK1BBla2ila2kla2pu1tBO0tOO1BLQSnpZ2pOYI++Hj/EZHrVy8Kip8 9aqlMdERsWsjN8RFbUxYk5y4Lj0tPic7qSA/vbQkp7oyv2HH9p3NFXt313a0NR7o2nmoe/eRw3uPH207 cbzz1InOM6f2nzl1oOf0wZ4zB3vPdPf2HDrbe/gc6uyR82ePXjh37ML5YxfPH7944cSliycvXzx1+dKp K5dPX7185uqVnmtXet662vvWtbPXr527/ta5t6+ff/v6hZ9N0Qj8qampPpN8UqpSznxxRkW26lX0QZHX Ra9+TFlFy5j9uKlk4O4nXScVe4kXLFjAhTluAkTM4Bpgb28vl5r7teafN2nw18+g6KyM9cFBE8xsTZYn Ltt5pVlVxfxSannRlYVGRw2EbdrCJm1BjbagUilkTstFWoJ8LcFWLe10Te0UTYWW458WX9HaqzRHuAz3 9naLWrEoagXkvCR69bK1ayLi1q2M3xCduGltWmpcZsbmvG0pxYWZFWW5dTVFTQ2lu3dV79tT19XRdHD/ zsOcnI91nDzRefpk14ul6AcPHhQVFVnaWy7fvLz5QrOKZvut5k+aJ16ZqHdajyRlzNZqpkwCBrRcxp6T o2eLBp79UNL1UvFocUhISEVFBadlGubQKlRiBp1N+Cc0uNNGv5A1c+snKjotOXrWzABDU/15q0PLDm1X Ve4AFXktwuy4iahDIGzWFtRqCSq1BGXaglJtAatiUiXagkItQZ6WIEtLO5XVcqKm9iZNvpZpUUVrRxEt e3k6r4gMW7liMdyZWPOaZetiYc2rNiXEpCSvz0jfmJuTVJifXrY9uwrWXF/SQqy5pn3fjv2dzd0HdkHO Rw/vPXYMcm6HO5862fVCKPrcuXNJSUn2rvYrklY09jaqCHagQkyGkPVP62OwVqSLhgFMGQGDnsVHDXzm EyWNIb4cGhpKtYzFaZlGZvpMAXoKlB8zfunZpN/1vIrOz01YtmS2l6ej02iHFSnL63trjz06rCxV5arU /MtziSO3s46sELKWoFRLsF1LAAmjqCkjYGzVEqQjYMCUNbU3a2pvhJZpqSpae5nmCLs3fXzcVywPo3Je HbVkTfTStTHLYc2bEDOSYrekxudkJeZtS91enFlZvq2+trCpoax1J7HmzvaGg/tbug/sPHKIyBnufPxY 28njHb+lopE6MzMz9Q31Zyyakbkj8+hHR1XU+ozacm8LiRYn+zpyXyH3MeVcXsAYICyjmOUM8nJ4eDg/ Y/DHv66uLvrQFDb+6tWrdM7+iH2JHz9m/ArWzK0BFb0pYTmGKycHS0cv+yXxi0oOFh19dJhfz1Z04Xv5 vj1jmENi4R5tYSOihZaggidkomVS2lxSVjVllXqqZa25I4ebDvP391kesRByZmPG4jWrl8TGLF+/bkVC /OrEzYgZG7IyN27bipiRUV62tbamAKl5V0vFntaajrYGNmm0HDrYCjkfO7L32JF9cOcTx9t/VUVfvHgR QQLG5+ztHL4uvGBfwcnHJ1V0+uza/Xj37OuzySMjh3R125QZmUYLdSGXk6SsOLOMqe+ZpoxiQsl5jOjo aBUtc77MaZmezoeWucj8JftyVf6jU7+Olukiik5NXrU0PMh/vKe5maGDh+3cVSEZDVs6brcpzkX0FTJX 6opu+aAp+EIQ7JjkihZtQb2WoEpLUM53ZKWQizS1CzW1t2lpZ/cV8lNTVimiZc2JI95khs4InLA8YkHk 8oWw5qiVi6JXLVkbs4xoecOqpM0xqcnrMzM25m5NLirYUsZOgDvqiluaylt3VbfthTVjCGxGcD50cNfR w3tQx4/uY+PzL6/owMBASwfLwIWBcXlxNSdqfvB8cb+179N9C28stDlro3eUPcnZytoxP1dwQuY9EKU4 fUFNeeCkjJImSCUBEoFEsGXLFv55DDr70byMjDGQltUfaf01tUyXxrbdW9tu7eVOpPVTalqmReVc+n7J 1HOTjY4YCDu0hTu1iIqr+6pYRcgFELKmdramFl/ICSr67VNaSzVHOL3p4my3aGEwq+UFKyPDVhEth69d s2x9LLQclbiJajlhKyJzQVppSXZVxbZ6MgGWwZqVqZnIGUnjcDfnzsgbv5aiVbT5/JV9P3vylcnkkT14 cfsPqLiPIz+3kFHMIkZkJ+Ie96Narq+vb2xspA+X0Nnv6NGjyMtcxlDRMndmjjub8SvLGUtDVb/q1VfI ux60hF9eZH/SVtQtEOzREjRqCWo1BVWaRMWchHkqJkKGHUPIuZraWRDySK3kkVqJmlo/JGTUSJiybOjk Sb4RS+dFLJun0HLUoujVS9auiVgfG0m0vDEmNUWp5fy07cVZVRW5dTWFjQ3bdzaV724l1tzV0bC/E0lD IWcU3PnFVXTG/YxpV6dZ9lrqHSO5mAx4LcpE0a+KqR1XKjMyfQIGosVzCJlMfb5igeCpKfPDMj2/3NHR 0d3dTc9jICzRZ35yeZlmjBdBy3T9sKIzb6VPPz/V/Jip8KA2kXCTlnatpnY1JKwpKNUUbGerBNVXxTRX 5Glq52hqZ2gSFSdByCO1No3UShiptUETpY1SUzFKc/aI4ebDvD2dwxeHRCydq9DyioVEy4qMEZkQv4r4 csq6zPQE9lRGamkJtLy1trqgkZxoLt+9q6ptT11H2w7I+UAXDc4kbMCd2WnwxVD0ia9OZN3PQhx2OudE zrR181xYXcJ9VfzUjpErCthnxVE7xrD3zIyMIuliikSoL4yNjeWEzDfl3bt304BBH8bu7e2l5+ToeQz6 /FrMfioZ47fVMl19FF30XsGSK4u9T3sYHtEXHlDqt05Tu0pTu0L5UN529tE8ImG2ipU3IORi1o7zWTvO 5Ox4pNbmkVoboWJ+9aNozXkjhtu+6exsGxoyfemSkGVLQpcTLc9fuSJs9crFa6Ix+0VsWL9iY/yqpMS1 W1LXZ2Vg9ksszN9Suj2rkvgytIzIXAYt79tT276vrpPIGUmjqfsAOa1xuHsXzRu/jaKLPyyOuhWF/OBw zoE8AfmwLvHffexEN5B+n6Hi7XJ5ofI8Mp30YMcDn7WgRYQ8TSI0EkZFRfHTBZeUMfXtU14IEabMBYyb N2/S54o/Yq+5RZ9iq56Xf1st06UhPKAl2KslQARuUIq3nCdepX77FPvgNNEybhSNVHjxVtaLVVQcryJk rp4qWjNkxHCbYY4O1rNnTVkSPgdahi8vj5i3MnIBO/iFx6xZuj52+Ya4lZs3Ricnrd2SFpeduSkvl539 tmdWlSu03NxY2rqTROa2vbWw5s72HQc6m9g5sJm682+s6H6Uqy5eWnwJ8xMFjcbUi59bxShEC8x7Qj3h Kvad9tSFjHRBH/FDUj7CvgbtLHshxOvXr8OU7927x4Xlb/pe3uU3mf2evTQGlC2/WAkrisSJkdr5I7Vz R2pnk+daEAmjIGGaKAZUMa/iNEdOGf7mqKFurvZzQ6YTIYfPYU157gqYciQJGGtWh8euXRbHBoykzWtS kxEw4rdmb87fllxcmF62neTl+tqCxnr4cunuXdBy9b499IQGGQJRB4mc4c6KvPFbK1pFtvwaSMKIE5wR c4nih6IxVxj2xO7igICAhIQElWihLuTDhw+fUF43lbsQIkz54+e4stkLtTRUxYvi65c+UahgpFY++1yh rJFaaSO0ktn6YSNWLc2wEcPdhw3TGuLn67F4UXD44tnQ8jKY8rK5kcvmrVi+YNXKsOjVi2Njlq6LXR4P U94UnZK4Np2YcgIbMDD4pVeUZVdXbSNaJhmjtJWcZa5ktQxrJnKmwZlk5xdU0er6RVXI5aVkriOnjDkX 5iT8HEZMS7qKtWNDYVhYWGFhIWfHdNhDRqbRAvOeupBpurijvG7qs035BdQyXRp99FukqRAvfa5b5kjN LSM0k0eQZ7wljtDaPEJr0withBFa8SO04kaoqHWg0lw2YsTYN4fpDHFxsZ01a+LiMAg5eMni2UuXzIlg kzJMOWrlwuhVi9ZGL1m3NiI+bsXmjUjKa7akrsvM2LA1exNrymmlJGBg8MvbUVfQ1FCysxkZA+NfJay5 bW8NtNzRVt/ZXs+e1iDZ+cVTtIp4ESHgv/SxO06/NEj80FynUkTFEyVCE2FwcHBaWhpVMT1lQe2YnrWg wx4y8sGDB2m0UBcyPX3xed/rpr7gpqyyNLRyR2ohPGSM1ExjlcuKlzxjkz5pM2GEZrziiZpExfxSEy9X IxcMH+41bJh0iJOjdeD08YsWBi0OmxW+KHgphBwesmwpmy4i56+CkFcvXrtmybpYCDlyU0JU8uaYtJTY zPS4nOyNeblJRQUppcXp5WVZNZVba2vyGuoKqZZ3tZTDl6k1t+/FEFgLLbPuTAz6BVW0QrkoKJczX4j3 uf2XX0wYIx4tFuoI586dm5mZ2a+KW1paWvu+dwMd9mhGfuuttxAtBhIy0oXKo9cvvpbp0iCy5ZSrFG+/ 9QxFa64YMWLim8MshhgZ6Xp7Os2ZNTls4UxOyHDkZXDkpaErls9duWLBqqiFayDkmKVxEPKGFZsSWEdO WZuRFrc1a+O23M2F+SklRWnlMOWKnJoqhOX8xvqi5saSnU3QchkiM9UykfO+2o59cGeEjRdf0T9JuVwx 4YxkPDHiiRMnxsTEcBKmAx6XKODFnIq72HcVOHr0KLXjCxcu0Es10OsI0IxMo4W6kF/8dDHQ0lCR7TOK L+eRi4cPHzdsmNmQIUMGubrYTp82buG8GWHzZ4QtCFoUFhS+aBaixdLw2cuWzomMmLsyct6qFQtXRy1a uyZ83dqlG9ZHJGwg0SIlMXpLKufImwvykkuKtpRtz6gsz66u3FoPU64vbNpBtbydaHknsea9u2lqrkG9 VIpWE+kzCkGCmcGIXcRCGbmObFxcHH+0oxLmjBi5mD6m19HRQb2YqvjMmTPnz5+/fPky344//PBD+iJ3 7joCNFq87ELm1nMpeuSCN4l+LYYM1RxsbWXiO8ZtTvCkBfMCF8wPXDg/kNhx2EyoeGk4UXHEspDIiNAV kfOiVixYHRUWE70oNmbJhnVsQE6IStq8OjU5Jj11XVbGhtychLxczHsQclrZ9i0VpVnVFTl1Ndsa6vIb dxRAyy1NVMul0PLuXeV7iZyr9u1BvUKKlsZKmbmMZJxEZCUSCAT0OshF7DU5IV6qXwQJzoU5Ce9TXhmO Xrns+PHjSBS9vb3Ui69fv05VfO/evQ8++IDaMc0V9CE+DHvqGfnlFTK3+ih6ZMTwETOHDfceCvMdqjXY 2FjPxdlmQoD3vNCp8+dOWzBv2oL50xcuCFyklPCSxUTFMOLlS6Fi1otXLohetTAmevG6tUviYpex6XhF 0uZVKUmY9GKz0tfnZMXn5mws2JZYVJBcWgwhp1eWZVVX5tRWs6bMarm5Ab5cvLOpBFpuhZx3le8hSaPi 5VY0YgMTSMIvUS4j+MHrIMN/aYrg9EvnOrhwd3c3lfAp9uJwMGLk4mvKd4N677334MXqKv4L+yYkfDt+ lYTMLQ19XamVpbGHu92EAK+Q4Enz2BfmKcRLCvqdAf0uDpu5ZHHQEjZLREDCy0IQiqNWQMLzWQmTRLE+ lk0U8cs3b1wJFacSFa/NSl+XnRnH2vHmovykksKU7cWp5SRaZLJCzq2vQVLOa6xHWC6ElluaiJZ3NpdA y607kTQQnF8JRUOwfM1i0dhAlQvnpREY4kUKhnjhv9DvAfbKnNAvhjoECc6FOQlzRoxcjAGPXlyLRmNO xfx0/EqqmL80FsyfBuWGLUAR8S5eSMQbvgjiZf13CfQ7m9Vv6MrIuatWzotetWDNKpolwuNil8SvXwYJ w4gTN0WlJK1OS1mTnrY2M319dlZcbnZCfu6mwnzYcdL2otTSEuSKjKpyOHJ2bRUx5R2123bAlOvzmxqg ZSJnquVdzUga2181RVO3hWZ3P991kCFeBOFz585R/V69ehVDHfT77rvvci788OFDhGJqxF+xb7iFXMwl iv8cFfOXxtLwWcuWoIKXL5sdGYFBLmRlZGjUirmrqP+S8xJha9dAv4vj1i3ZsH5p/IaITfGRiRtXJpMs sSotJXoLJLwlNjsDEt6wbWtC/raNBXmbiwqh4pRSYsdbKsvI62qrK7Ig5LrqrXU1udByQz3ryyRjFDY3 FrWQUrjzq6loCBZuSzX7PNdBvnnzJiLE7du332evH0ktmAYJ7hJ8cGEqYRUj/k9TMX9prI5CbJi/ZvWC mOiFsWvC1q1dtH6tUrxxyzbGR27eGJm4aUXy5qhU6DcZ+o3J2EKyRA5x4bhtOfF5ucjFmwrzEoupikuI iivIq2vhyBk1lVk1ldl11TlIFztqiZZ31G1jtZzfhPGPuvN/gqJhtRd/zHWQIV5ECL5+YcFckFBx4f9k CassjY0blm1KiNicsDxxY2TSJkxxMF9WvDDf1DXpqTGZ6WuzMmJzMtdtzVrPuvCG/NyEgm0bi/I3Fxcg FydtL04pK0GlkdfVlqZXlqdXwZErM2urkC6IllFUyw11qDylO/+HKRpW+6Oug8z3X75+qYSh398l3O/S SE+NzkiLztiyJnPLmqz0tdkZyA+xrHjhv8SCqX4L8jYVF0DCiSXkFYlJpcXkRbVlxI5TWTveAjumV+1Q aLlaoeX6mq2o3xVN3v0Ni7otNEsnNypb2C6nXIQHFfFy/vu7fp9naeQS2cblbd2Ays+NL9iWUMBeV4gt ouKSQhTiBH2BeErZ9hTWixVX7SBa5l2BhmSMKuTl3xWtpmi+YKlmVWSLpaJcLMXd9Pt67qVRmLcRRSXM ipcU73XhimscoJ7nmkq/K3pARbMxQSFYLIVi2aW4L35fP8fS4CSscnUDZfV/BZrfFf2jFa0A/vv6hdfP cJWw3xX9u6JfoPW7on9X9Ku1flf074p+tdbviv5d0a/S+r//+/8BPTxUq6Ub7iwAAAAASUVORK5CYII= Pyramid is a simple, cheap, free shader analysis tool. It is distributed under the GNU GPL. Third party components included with Pyramid (FXC, CodeXL, AMD DXX Driver, PowerVR compilers) are the property of their respective owners and are provided solely for convenience. ICSharpCode.TextEditor was originally written for SharpDevelop, and is distributed under the LGPL. ================================================ FILE: src/MainUI/MainForm.Designer.cs ================================================  namespace Pyramid { partial class MainForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.menuStrip1 = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.txtCode = new ICSharpCode.TextEditor.TextEditorControl(); this.splitContainer2 = new System.Windows.Forms.SplitContainer(); this.splitContainer3 = new System.Windows.Forms.SplitContainer(); this.CompilePanel = new System.Windows.Forms.Panel(); this.cmbLanguage = new System.Windows.Forms.ComboBox(); this.btnCompile = new System.Windows.Forms.Button(); this.AnalysisPanel = new System.Windows.Forms.Panel(); this.BackendPanel = new System.Windows.Forms.Panel(); this.cmbBackend = new System.Windows.Forms.ComboBox(); this.menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); this.splitContainer2.Panel1.SuspendLayout(); this.splitContainer2.Panel2.SuspendLayout(); this.splitContainer2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); this.splitContainer3.Panel1.SuspendLayout(); this.splitContainer3.Panel2.SuspendLayout(); this.splitContainer3.SuspendLayout(); this.SuspendLayout(); // // menuStrip1 // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem, this.toolsToolStripMenuItem, this.helpToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.Size = new System.Drawing.Size(784, 24); this.menuStrip1.TabIndex = 0; this.menuStrip1.Text = "menuStrip1"; // // fileToolStripMenuItem // this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.newToolStripMenuItem, this.openToolStripMenuItem, this.saveToolStripMenuItem, this.saveAsToolStripMenuItem, this.exitToolStripMenuItem}); this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.fileToolStripMenuItem.Text = "File"; // // newToolStripMenuItem // this.newToolStripMenuItem.Name = "newToolStripMenuItem"; this.newToolStripMenuItem.Size = new System.Drawing.Size(152, 22); this.newToolStripMenuItem.Text = "New"; this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click); // // openToolStripMenuItem // this.openToolStripMenuItem.Name = "openToolStripMenuItem"; this.openToolStripMenuItem.Size = new System.Drawing.Size(152, 22); this.openToolStripMenuItem.Text = "Open"; this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); // // saveToolStripMenuItem // this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; this.saveToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); this.saveToolStripMenuItem.Size = new System.Drawing.Size(152, 22); this.saveToolStripMenuItem.Text = "&Save"; this.saveToolStripMenuItem.Click += new System.EventHandler(this.saveToolStripMenuItem_Click); // // saveAsToolStripMenuItem // this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem"; this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(152, 22); this.saveAsToolStripMenuItem.Text = "Save As"; this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click); // // exitToolStripMenuItem // this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; this.exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22); this.exitToolStripMenuItem.Text = "Exit"; this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); // // toolsToolStripMenuItem // this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.optionsToolStripMenuItem}); this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20); this.toolsToolStripMenuItem.Text = "Tools"; // // optionsToolStripMenuItem // this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; this.optionsToolStripMenuItem.Size = new System.Drawing.Size(116, 22); this.optionsToolStripMenuItem.Text = "Options"; this.optionsToolStripMenuItem.Click += new System.EventHandler(this.optionsToolStripMenuItem_Click); // // helpToolStripMenuItem // this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.aboutToolStripMenuItem}); this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); this.helpToolStripMenuItem.Text = "Help"; // // aboutToolStripMenuItem // this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; this.aboutToolStripMenuItem.Size = new System.Drawing.Size(107, 22); this.aboutToolStripMenuItem.Text = "About"; this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click); // // splitContainer1 // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 24); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 // this.splitContainer1.Panel1.Controls.Add(this.txtCode); // // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.splitContainer2); this.splitContainer1.Size = new System.Drawing.Size(784, 537); this.splitContainer1.SplitterDistance = 254; this.splitContainer1.TabIndex = 1; // // txtCode // this.txtCode.AllowDrop = true; this.txtCode.Dock = System.Windows.Forms.DockStyle.Fill; this.txtCode.EnableFolding = false; this.txtCode.IsReadOnly = false; this.txtCode.Location = new System.Drawing.Point(0, 0); this.txtCode.Name = "txtCode"; this.txtCode.Size = new System.Drawing.Size(254, 537); this.txtCode.TabIndex = 2; this.txtCode.Text = "float4 main() : SV_TARGET { return 0; }\r\n"; // // splitContainer2 // this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer2.Location = new System.Drawing.Point(0, 0); this.splitContainer2.Name = "splitContainer2"; // // splitContainer2.Panel1 // this.splitContainer2.Panel1.Controls.Add(this.splitContainer3); // // splitContainer2.Panel2 // this.splitContainer2.Panel2.Controls.Add(this.BackendPanel); this.splitContainer2.Panel2.Controls.Add(this.cmbBackend); this.splitContainer2.Size = new System.Drawing.Size(526, 537); this.splitContainer2.SplitterDistance = 201; this.splitContainer2.TabIndex = 0; // // splitContainer3 // this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer3.Location = new System.Drawing.Point(0, 0); this.splitContainer3.Name = "splitContainer3"; this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; // // splitContainer3.Panel1 // this.splitContainer3.Panel1.Controls.Add(this.CompilePanel); this.splitContainer3.Panel1.Controls.Add(this.cmbLanguage); this.splitContainer3.Panel1.Controls.Add(this.btnCompile); // // splitContainer3.Panel2 // this.splitContainer3.Panel2.Controls.Add(this.AnalysisPanel); this.splitContainer3.Size = new System.Drawing.Size(201, 537); this.splitContainer3.SplitterDistance = 288; this.splitContainer3.TabIndex = 0; // // CompilePanel // this.CompilePanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.CompilePanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.CompilePanel.Location = new System.Drawing.Point(4, 68); this.CompilePanel.Name = "CompilePanel"; this.CompilePanel.Size = new System.Drawing.Size(194, 217); this.CompilePanel.TabIndex = 2; // // cmbLanguage // this.cmbLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.cmbLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbLanguage.FormattingEnabled = true; this.cmbLanguage.Location = new System.Drawing.Point(3, 45); this.cmbLanguage.Name = "cmbLanguage"; this.cmbLanguage.Size = new System.Drawing.Size(195, 21); this.cmbLanguage.TabIndex = 1; this.cmbLanguage.SelectedIndexChanged += new System.EventHandler(this.cmbLanguage_SelectedIndexChanged); // // btnCompile // this.btnCompile.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.btnCompile.Location = new System.Drawing.Point(2, 3); this.btnCompile.Name = "btnCompile"; this.btnCompile.Size = new System.Drawing.Size(196, 41); this.btnCompile.TabIndex = 0; this.btnCompile.Text = "COMPILE"; this.btnCompile.UseVisualStyleBackColor = true; this.btnCompile.Click += new System.EventHandler(this.btnCompile_Click); // // AnalysisPanel // this.AnalysisPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.AnalysisPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.AnalysisPanel.Location = new System.Drawing.Point(0, 0); this.AnalysisPanel.Name = "AnalysisPanel"; this.AnalysisPanel.Size = new System.Drawing.Size(201, 245); this.AnalysisPanel.TabIndex = 0; // // BackendPanel // this.BackendPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.BackendPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.BackendPanel.Location = new System.Drawing.Point(2, 30); this.BackendPanel.Name = "BackendPanel"; this.BackendPanel.Size = new System.Drawing.Size(316, 504); this.BackendPanel.TabIndex = 1; // // cmbBackend // this.cmbBackend.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.cmbBackend.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbBackend.FormattingEnabled = true; this.cmbBackend.Location = new System.Drawing.Point(2, 3); this.cmbBackend.Name = "cmbBackend"; this.cmbBackend.Size = new System.Drawing.Size(316, 21); this.cmbBackend.TabIndex = 0; this.cmbBackend.SelectedIndexChanged += new System.EventHandler(this.cmbBackend_SelectedIndexChanged); // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(784, 561); this.Controls.Add(this.splitContainer1); this.Controls.Add(this.menuStrip1); this.Name = "MainForm"; this.Text = "Pyramid"; this.menuStrip1.ResumeLayout(false); this.menuStrip1.PerformLayout(); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); this.splitContainer1.ResumeLayout(false); this.splitContainer2.Panel1.ResumeLayout(false); this.splitContainer2.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); this.splitContainer2.ResumeLayout(false); this.splitContainer3.Panel1.ResumeLayout(false); this.splitContainer3.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); this.splitContainer3.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.MenuStrip menuStrip1; private System.Windows.Forms.SplitContainer splitContainer1; private System.Windows.Forms.SplitContainer splitContainer2; private System.Windows.Forms.SplitContainer splitContainer3; private System.Windows.Forms.Panel BackendPanel; private System.Windows.Forms.ComboBox cmbBackend; private System.Windows.Forms.Panel AnalysisPanel; private System.Windows.Forms.ComboBox cmbLanguage; private System.Windows.Forms.Button btnCompile; private System.Windows.Forms.Panel CompilePanel; private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem saveAsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; private ICSharpCode.TextEditor.TextEditorControl txtCode; } } ================================================ FILE: src/MainUI/MainForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; namespace Pyramid { public partial class MainForm : Form { private List m_Backends; private List m_Languages; private ICompileOptionsPanel m_CompileOptionsPanel; private Options m_Options; private IWrapper m_Wrapper; private string m_FileName = ""; private string m_LastBackend = ""; public Options Options { get { return m_Options; } } private void CreateBackends( Options opts ) { List backends = new List(); IIncludeHandler handler = new IncludeHandler(opts.IncludePaths); try { ID3DCompiler fxc = m_Wrapper.CreateD3DCompiler(opts.D3DCompilerPath, handler); IDXILCompiler dxil = m_Wrapper.CreateDXILCompiler(opts.DXILCompilerPath, handler); backends.Add(new D3DCompilerBackend(fxc,dxil)); try { IAMDDriver driver = m_Wrapper.CreateAMDDriver(opts.DXXDriverPath); backends.Add(new AMDDriverBackend(driver, fxc)); } catch( System.Exception ex ) { MessageBox.Show(ex.Message); } } catch( System.Exception ex ) { MessageBox.Show(ex.Message); } backends.Add(new CodeXLBackend(opts.CodeXLPath, opts.D3DCompilerPath, opts.TempPath)); backends.Add(new GLSlangBackend(m_Wrapper,handler)); backends.Add(new GLSLOptimizerBackend(m_Wrapper)); backends.Add(new PowerVRBackend(opts.PowerVRCompilerPath, opts.TempPath)); backends.Add(new MaliSCBackend(opts.MaliSCRoot, opts.TempPath)); backends.Add(new RGABackend(opts.RGAPath, opts.TempPath,m_Wrapper,handler)); if (File.Exists(opts.IntelShaderAnalyzerPath)) { backends.Add(new IntelShaderAnalyzerBackend(opts)); } m_Backends = backends; } public MainForm( Options options, IWrapper wrapper ) { InitializeComponent(); m_Options = options; cmbBackend.DisplayMember = "Name"; cmbLanguage.DisplayMember = "Name"; List languages = new List(); languages.Add(new HLSLLanguage()); languages.Add(new GLSLLanguage()); m_Languages = languages; foreach (ILanguage l in m_Languages) cmbLanguage.Items.Add(l); cmbLanguage.SelectedIndex = 0; m_Wrapper = wrapper; CreateBackends(options); txtCode.AllowDrop = true; txtCode.DragEnter += delegate( object sender, DragEventArgs args ) { if (args.Data.GetDataPresent(DataFormats.FileDrop)) args.Effect = DragDropEffects.Move; else args.Effect = DragDropEffects.None; }; txtCode.DragDrop += delegate(object sender, DragEventArgs args) { if (args.Data.GetDataPresent(DataFormats.FileDrop)) { string[] paths = args.Data.GetData(DataFormats.FileDrop) as string[]; OpenFile(paths[0]); } }; } private void ClearResults() { cmbBackend.Items.Clear(); BackendPanel.Controls.Clear(); AnalysisPanel.Controls.Clear(); } private void btnCompile_Click(object sender, EventArgs e) { if( m_CompileOptionsPanel == null ) return; this.UseWaitCursor = true; ClearResults(); IResultSet SelectedResultSet = null; ICompileOptions opts = m_CompileOptionsPanel.ReadOptions(); IShader shader = null; switch (opts.Language) { case Languages.GLSL: shader = new GLSLShader(txtCode.Text, opts as IGLSLOptions, m_FileName ); break; case Languages.HLSL: shader = new HLSLShader(txtCode.Text, opts as IHLSLOptions, m_FileName ); break; default: throw new System.Exception("Unsupported language"); } foreach (IBackend backend in m_Backends) { if (m_Options.IsBackendDisabled(backend.Name)) continue; IBackendOptions options = null; if (backend is AMDDriverBackend) { AMDDriverBackend amdBackend = backend as AMDDriverBackend; List requestedAsics = new List(); foreach (string asic in amdBackend.Asics) { if (!m_Options.IsAMDAsicDisabled(asic)) { requestedAsics.Add(asic); } } AMDDriverBackendOptions backendOptions = new AMDDriverBackendOptions(requestedAsics); options = backendOptions; } else if (backend is CodeXLBackend) { CodeXLBackend codeXLBackend = backend as CodeXLBackend; List requestedAsics = new List(); foreach (string asic in codeXLBackend.Asics) { if (!m_Options.IsCodeXLAsicDisabled(asic)) { requestedAsics.Add(asic); } } CodeXLBackendOptions backendOptions = new CodeXLBackendOptions(requestedAsics); options = backendOptions; } else if( backend is RGABackend ) { options = new RGABackendOptions(m_Options); } IResultSet r = backend.Compile(shader, options); if (r != null) { if (r.Name.Equals(m_LastBackend)) SelectedResultSet = r; cmbBackend.Items.Add(r); } } if (cmbBackend.Items.Count > 0) { if (SelectedResultSet != null) cmbBackend.SelectedIndex = cmbBackend.Items.IndexOf(SelectedResultSet); else cmbBackend.SelectedIndex = 0; } else { m_LastBackend = ""; } this.UseWaitCursor = false; } private void cmbLanguage_SelectedIndexChanged(object sender, EventArgs e) { CompilePanel.Controls.Clear(); ClearResults(); m_CompileOptionsPanel = null; if (cmbLanguage.SelectedItem != null) { ILanguage l = (ILanguage)cmbLanguage.SelectedItem; CompilePanel.Controls.Add(l.OptionsPanel.Panel); m_CompileOptionsPanel = l.OptionsPanel; try { txtCode.SetHighlighting(l.Name); } catch( System.Exception ex ) { MessageBox.Show(ex.Message, "Uh-oh", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } private void cmbBackend_SelectedIndexChanged(object sender, EventArgs e) { BackendPanel.Controls.Clear(); AnalysisPanel.Controls.Clear(); if (cmbBackend.SelectedItem != null ) { IResultSet rs = (IResultSet) cmbBackend.SelectedItem; if (rs.ResultsPanel != null) { BackendPanel.Controls.Add(rs.ResultsPanel); rs.ResultsPanel.Dock = DockStyle.Fill; } if (rs.AnalysisPanel != null) { AnalysisPanel.Controls.Add(rs.AnalysisPanel); rs.AnalysisPanel.Dock = DockStyle.Fill; } m_LastBackend = rs.Name; } } private void optionsToolStripMenuItem_Click(object sender, EventArgs e) { OptionsScreen opts = new OptionsScreen(m_Options, m_Backends); if (opts.ShowDialog() != DialogResult.Cancel) { m_Options = opts.SelectedOptions; ClearResults(); CreateBackends(m_Options); } } private void newToolStripMenuItem_Click(object sender, EventArgs e) { this.Text = "Pyramid"; txtCode.Text = ""; txtCode.Refresh(); m_FileName = ""; ClearResults(); } private void OpenFile( string path ) { try { string code = File.ReadAllText(path); txtCode.Text = code; ClearResults(); m_FileName = path; this.Text = "Pyramid : " + m_FileName; } catch (Exception ex) { MessageBox.Show(ex.Message, "uh-oh, couldn't Open", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog fd = new OpenFileDialog(); if( fd.ShowDialog() != DialogResult.Cancel) { OpenFile(fd.FileName); } } private void saveToolStripMenuItem_Click(object sender, EventArgs e) { if (String.IsNullOrEmpty(m_FileName)) SaveAs(); else Save(m_FileName); } private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { SaveAs(); } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { this.Close(); } private void SaveAs() { SaveFileDialog save = new SaveFileDialog(); if (save.ShowDialog() != DialogResult.Cancel) { Save(save.FileName); m_FileName = save.FileName; this.Text = "Pyramid : " + m_FileName; } } private void Save( string As ) { try { File.WriteAllText(As, txtCode.Text); } catch (Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't save", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { AboutBox a = new AboutBox(); a.ShowDialog(); } // Hackery to make .NET split containers behave themselves at arbitrary dpi Courtesty of: // https://www.codeproject.com/Tips/786170/Proper-Resizing-of-SplitterContainer-Controls-at-a // Save the current scale value // ScaleControl() is called during the Form's constructor private SizeF scale = new SizeF(1.0f, 1.0f); protected override void ScaleControl(SizeF factor, BoundsSpecified specified) { scale = new SizeF(scale.Width * factor.Width, scale.Height * factor.Height); base.ScaleControl(factor, specified); } // Recursively search for SplitContainer controls private void FixSplitter(Control c) { foreach (Control child in c.Controls) { if (child is SplitContainer) { SplitContainer sp = (SplitContainer)child; FixSplitter(sp); FixSplitter(sp.Panel1); FixSplitter(sp.Panel2); } else { FixSplitter(child); } } } private void FixSplitter(SplitContainer sp) { // Scale factor depends on orientation float sc = (sp.Orientation == Orientation.Vertical) ? scale.Width : scale.Height; if (sp.FixedPanel == FixedPanel.Panel1) { sp.SplitterDistance = (int)Math.Round((float)sp.SplitterDistance * sc); } else if (sp.FixedPanel == FixedPanel.Panel2) { int cs = (sp.Orientation == Orientation.Vertical) ? sp.Panel2.ClientSize.Width : sp.Panel2.ClientSize.Height; int newcs = (int)((float)cs * sc); sp.SplitterDistance -= (newcs - cs); } } private void MainForm_Shown(object sender, EventArgs e) { FixSplitter(this); } } } ================================================ FILE: src/MainUI/MainForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 ================================================ FILE: src/MainUI/OptionsScreen.Designer.cs ================================================ namespace Pyramid { partial class OptionsScreen { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.txtCodeXL = new System.Windows.Forms.TextBox(); this.txtD3DCompiler = new System.Windows.Forms.TextBox(); this.txtTemp = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); this.btnTemp = new System.Windows.Forms.Button(); this.btnCodeXL = new System.Windows.Forms.Button(); this.btnD3DCompiler = new System.Windows.Forms.Button(); this.btnOk = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); this.txtPowerVR = new System.Windows.Forms.TextBox(); this.btnPowerVR = new System.Windows.Forms.Button(); this.btnDefaults = new System.Windows.Forms.Button(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); this.label5 = new System.Windows.Forms.Label(); this.label7 = new System.Windows.Forms.Label(); this.label12 = new System.Windows.Forms.Label(); this.btnAddInclude = new System.Windows.Forms.Button(); this.btnDeleteInclude = new System.Windows.Forms.Button(); this.label13 = new System.Windows.Forms.Label(); this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); this.label14 = new System.Windows.Forms.Label(); this.label15 = new System.Windows.Forms.Label(); this.txtDXX = new System.Windows.Forms.TextBox(); this.btnDXX = new System.Windows.Forms.Button(); this.lstBackends = new System.Windows.Forms.CheckedListBox(); this.label6 = new System.Windows.Forms.Label(); this.btnMali = new System.Windows.Forms.Button(); this.txtMali = new System.Windows.Forms.TextBox(); this.lstAMDAsics = new System.Windows.Forms.CheckedListBox(); this.label8 = new System.Windows.Forms.Label(); this.label9 = new System.Windows.Forms.Label(); this.lstCodeXLAsics = new System.Windows.Forms.CheckedListBox(); this.txtRGA = new System.Windows.Forms.TextBox(); this.btnRGA = new System.Windows.Forms.Button(); this.lstRGAAsics = new System.Windows.Forms.CheckedListBox(); this.label11 = new System.Windows.Forms.Label(); this.lstIncludes = new System.Windows.Forms.ListBox(); this.btnDXIL = new System.Windows.Forms.Button(); this.txtDXIL = new System.Windows.Forms.TextBox(); this.btnIntelShaderAnalyzer = new System.Windows.Forms.Button(); this.txtIntelShaderAnalyzer = new System.Windows.Forms.TextBox(); ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); this.SuspendLayout(); // // txtCodeXL // this.txtCodeXL.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtCodeXL.Enabled = false; this.txtCodeXL.Location = new System.Drawing.Point(115, 314); this.txtCodeXL.Margin = new System.Windows.Forms.Padding(4); this.txtCodeXL.Name = "txtCodeXL"; this.txtCodeXL.Size = new System.Drawing.Size(705, 22); this.txtCodeXL.TabIndex = 1; // // txtD3DCompiler // this.txtD3DCompiler.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtD3DCompiler.Enabled = false; this.txtD3DCompiler.Location = new System.Drawing.Point(115, 346); this.txtD3DCompiler.Margin = new System.Windows.Forms.Padding(4); this.txtD3DCompiler.Name = "txtD3DCompiler"; this.txtD3DCompiler.Size = new System.Drawing.Size(705, 22); this.txtD3DCompiler.TabIndex = 2; // // txtTemp // this.txtTemp.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtTemp.Enabled = false; this.txtTemp.Location = new System.Drawing.Point(115, 282); this.txtTemp.Margin = new System.Windows.Forms.Padding(4); this.txtTemp.Name = "txtTemp"; this.txtTemp.Size = new System.Drawing.Size(705, 22); this.txtTemp.TabIndex = 3; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(47, 317); this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(58, 17); this.label2.TabIndex = 5; this.label2.Text = "CodeXL"; this.toolTip1.SetToolTip(this.label2, "Path to AMD CodeXL Analyzer"); // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(19, 349); this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(91, 17); this.label3.TabIndex = 6; this.label3.Text = "D3DCompiler"; this.toolTip1.SetToolTip(this.label3, "Path to the D3DCompiler DLL to use"); // // label4 // this.label4.AutoSize = true; this.label4.Location = new System.Drawing.Point(40, 287); this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(66, 17); this.label4.TabIndex = 7; this.label4.Text = "Temp Dir"; this.toolTip1.SetToolTip(this.label4, "Path to a directory that will be polluted with temporary nonsense when the compil" + "e button is pressed."); // // btnTemp // this.btnTemp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnTemp.Location = new System.Drawing.Point(829, 282); this.btnTemp.Margin = new System.Windows.Forms.Padding(4); this.btnTemp.Name = "btnTemp"; this.btnTemp.Size = new System.Drawing.Size(43, 25); this.btnTemp.TabIndex = 8; this.btnTemp.Text = "..."; this.btnTemp.UseVisualStyleBackColor = true; this.btnTemp.Click += new System.EventHandler(this.btnTemp_Click); // // btnCodeXL // this.btnCodeXL.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnCodeXL.Location = new System.Drawing.Point(829, 312); this.btnCodeXL.Margin = new System.Windows.Forms.Padding(4); this.btnCodeXL.Name = "btnCodeXL"; this.btnCodeXL.Size = new System.Drawing.Size(43, 25); this.btnCodeXL.TabIndex = 10; this.btnCodeXL.Text = "..."; this.btnCodeXL.UseVisualStyleBackColor = true; this.btnCodeXL.Click += new System.EventHandler(this.btnCodeXL_Click); // // btnD3DCompiler // this.btnD3DCompiler.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnD3DCompiler.Location = new System.Drawing.Point(829, 344); this.btnD3DCompiler.Margin = new System.Windows.Forms.Padding(4); this.btnD3DCompiler.Name = "btnD3DCompiler"; this.btnD3DCompiler.Size = new System.Drawing.Size(43, 25); this.btnD3DCompiler.TabIndex = 11; this.btnD3DCompiler.Text = "..."; this.btnD3DCompiler.UseVisualStyleBackColor = true; this.btnD3DCompiler.Click += new System.EventHandler(this.btnD3DCompiler_Click); // // btnOk // this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK; this.btnOk.Location = new System.Drawing.Point(505, 609); this.btnOk.Margin = new System.Windows.Forms.Padding(4); this.btnOk.Name = "btnOk"; this.btnOk.Size = new System.Drawing.Size(92, 31); this.btnOk.TabIndex = 12; this.btnOk.Text = "Ok"; this.btnOk.UseVisualStyleBackColor = true; // // btnCancel // this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.btnCancel.Location = new System.Drawing.Point(617, 608); this.btnCancel.Margin = new System.Windows.Forms.Padding(4); this.btnCancel.Name = "btnCancel"; this.btnCancel.Size = new System.Drawing.Size(92, 31); this.btnCancel.TabIndex = 13; this.btnCancel.Text = "Cancel"; this.btnCancel.UseVisualStyleBackColor = true; // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(16, 383); this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(88, 17); this.label1.TabIndex = 14; this.label1.Text = "PowerVR Dir"; this.toolTip1.SetToolTip(this.label1, "Directory where the PowerVR compilers can be found. Default will be relative to " + "working directory."); // // txtPowerVR // this.txtPowerVR.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtPowerVR.Enabled = false; this.txtPowerVR.Location = new System.Drawing.Point(115, 376); this.txtPowerVR.Margin = new System.Windows.Forms.Padding(4); this.txtPowerVR.Name = "txtPowerVR"; this.txtPowerVR.Size = new System.Drawing.Size(705, 22); this.txtPowerVR.TabIndex = 15; // // btnPowerVR // this.btnPowerVR.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnPowerVR.Location = new System.Drawing.Point(829, 375); this.btnPowerVR.Margin = new System.Windows.Forms.Padding(4); this.btnPowerVR.Name = "btnPowerVR"; this.btnPowerVR.Size = new System.Drawing.Size(43, 23); this.btnPowerVR.TabIndex = 16; this.btnPowerVR.Text = "..."; this.btnPowerVR.UseVisualStyleBackColor = true; this.btnPowerVR.Click += new System.EventHandler(this.btnPowerVR_Click); // // btnDefaults // this.btnDefaults.Location = new System.Drawing.Point(48, 609); this.btnDefaults.Margin = new System.Windows.Forms.Padding(4); this.btnDefaults.Name = "btnDefaults"; this.btnDefaults.Size = new System.Drawing.Size(87, 30); this.btnDefaults.TabIndex = 17; this.btnDefaults.Text = "Defaults"; this.btnDefaults.UseVisualStyleBackColor = true; this.btnDefaults.Click += new System.EventHandler(this.btnDefaults_Click); // // toolTip1 // this.toolTip1.ShowAlways = true; // // label5 // this.label5.AutoSize = true; this.label5.Location = new System.Drawing.Point(32, 412); this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(70, 17); this.label5.TabIndex = 20; this.label5.Text = "AMD DXX"; this.toolTip1.SetToolTip(this.label5, "Directory where atidxx32.dll can be found. Default will be relative to working d" + "irectory."); // // label7 // this.label7.AutoSize = true; this.label7.Location = new System.Drawing.Point(51, 444); this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label7.Name = "label7"; this.label7.Size = new System.Drawing.Size(55, 17); this.label7.TabIndex = 26; this.label7.Text = "Mali Dir"; this.toolTip1.SetToolTip(this.label7, "Directory where the mali shader compiler can be found. Default will be relative " + "to working directory."); // // label12 // this.label12.AutoSize = true; this.label12.Location = new System.Drawing.Point(67, 479); this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label12.Name = "label12"; this.label12.Size = new System.Drawing.Size(38, 17); this.label12.TabIndex = 38; this.label12.Text = "RGA"; this.toolTip1.SetToolTip(this.label12, "Directory where the mali shader compiler can be found. Default will be relative " + "to working directory."); // // btnAddInclude // this.btnAddInclude.Location = new System.Drawing.Point(768, 201); this.btnAddInclude.Margin = new System.Windows.Forms.Padding(4); this.btnAddInclude.Name = "btnAddInclude"; this.btnAddInclude.Size = new System.Drawing.Size(23, 25); this.btnAddInclude.TabIndex = 44; this.btnAddInclude.Text = "+"; this.toolTip1.SetToolTip(this.btnAddInclude, "Add include path"); this.btnAddInclude.UseVisualStyleBackColor = true; this.btnAddInclude.Click += new System.EventHandler(this.btnAddInclude_Click); // // btnDeleteInclude // this.btnDeleteInclude.Location = new System.Drawing.Point(799, 201); this.btnDeleteInclude.Margin = new System.Windows.Forms.Padding(4); this.btnDeleteInclude.Name = "btnDeleteInclude"; this.btnDeleteInclude.Size = new System.Drawing.Size(23, 25); this.btnDeleteInclude.TabIndex = 45; this.btnDeleteInclude.Text = "X"; this.toolTip1.SetToolTip(this.btnDeleteInclude, "Delete include path"); this.btnDeleteInclude.UseVisualStyleBackColor = true; this.btnDeleteInclude.Click += new System.EventHandler(this.btnDeleteInclude_Click); // // label13 // this.label13.AutoSize = true; this.label13.Location = new System.Drawing.Point(44, 201); this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label13.Name = "label13"; this.label13.Size = new System.Drawing.Size(60, 17); this.label13.TabIndex = 46; this.label13.Text = "Includes"; this.toolTip1.SetToolTip(this.label13, "Path to a directory that will be polluted with temporary nonsense when the compil" + "e button is pressed."); // // numericUpDown1 // this.numericUpDown1.InterceptArrowKeys = false; this.numericUpDown1.Location = new System.Drawing.Point(768, 246); this.numericUpDown1.Margin = new System.Windows.Forms.Padding(4); this.numericUpDown1.Minimum = new decimal(new int[] { 100, 0, 0, -2147483648}); this.numericUpDown1.Name = "numericUpDown1"; this.numericUpDown1.Size = new System.Drawing.Size(23, 22); this.numericUpDown1.TabIndex = 47; this.toolTip1.SetToolTip(this.numericUpDown1, "Adjust include order"); this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged); // // label14 // this.label14.AutoSize = true; this.label14.Location = new System.Drawing.Point(19, 509); this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label14.Name = "label14"; this.label14.Size = new System.Drawing.Size(97, 17); this.label14.TabIndex = 48; this.label14.Text = "DXIL Compiler"; this.toolTip1.SetToolTip(this.label14, "Path to the D3DCompiler DLL to use"); // // label15 // this.label15.AutoSize = true; this.label15.Location = new System.Drawing.Point(21, 539); this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label15.Name = "label15"; this.label15.Size = new System.Drawing.Size(56, 17); this.label15.TabIndex = 51; this.label15.Text = "Intel SA"; this.toolTip1.SetToolTip(this.label15, "Path to the D3DCompiler DLL to use"); this.label15.Click += new System.EventHandler(this.label15_Click); // // txtDXX // this.txtDXX.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtDXX.Enabled = false; this.txtDXX.Location = new System.Drawing.Point(115, 408); this.txtDXX.Margin = new System.Windows.Forms.Padding(4); this.txtDXX.Name = "txtDXX"; this.txtDXX.Size = new System.Drawing.Size(705, 22); this.txtDXX.TabIndex = 18; // // btnDXX // this.btnDXX.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnDXX.Location = new System.Drawing.Point(829, 410); this.btnDXX.Margin = new System.Windows.Forms.Padding(4); this.btnDXX.Name = "btnDXX"; this.btnDXX.Size = new System.Drawing.Size(43, 23); this.btnDXX.TabIndex = 19; this.btnDXX.Text = "..."; this.btnDXX.UseVisualStyleBackColor = true; this.btnDXX.Click += new System.EventHandler(this.btnDXX_Click); // // lstBackends // this.lstBackends.FormattingEnabled = true; this.lstBackends.Location = new System.Drawing.Point(44, 57); this.lstBackends.Margin = new System.Windows.Forms.Padding(4); this.lstBackends.Name = "lstBackends"; this.lstBackends.ScrollAlwaysVisible = true; this.lstBackends.Size = new System.Drawing.Size(203, 123); this.lstBackends.TabIndex = 22; // // label6 // this.label6.AutoSize = true; this.label6.Location = new System.Drawing.Point(40, 22); this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(70, 17); this.label6.TabIndex = 23; this.label6.Text = "Backends"; // // btnMali // this.btnMali.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnMali.Location = new System.Drawing.Point(829, 442); this.btnMali.Margin = new System.Windows.Forms.Padding(4); this.btnMali.Name = "btnMali"; this.btnMali.Size = new System.Drawing.Size(43, 23); this.btnMali.TabIndex = 25; this.btnMali.Text = "..."; this.btnMali.UseVisualStyleBackColor = true; this.btnMali.Click += new System.EventHandler(this.btnMali_Click); // // txtMali // this.txtMali.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtMali.Enabled = false; this.txtMali.Location = new System.Drawing.Point(115, 440); this.txtMali.Margin = new System.Windows.Forms.Padding(4); this.txtMali.Name = "txtMali"; this.txtMali.Size = new System.Drawing.Size(705, 22); this.txtMali.TabIndex = 24; // // lstAMDAsics // this.lstAMDAsics.FormattingEnabled = true; this.lstAMDAsics.Location = new System.Drawing.Point(273, 57); this.lstAMDAsics.Margin = new System.Windows.Forms.Padding(4); this.lstAMDAsics.Name = "lstAMDAsics"; this.lstAMDAsics.ScrollAlwaysVisible = true; this.lstAMDAsics.Size = new System.Drawing.Size(203, 123); this.lstAMDAsics.TabIndex = 27; // // label8 // this.label8.AutoSize = true; this.label8.Location = new System.Drawing.Point(269, 22); this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label8.Name = "label8"; this.label8.Size = new System.Drawing.Size(75, 17); this.label8.TabIndex = 28; this.label8.Text = "AMD Asics"; // // label9 // this.label9.AutoSize = true; this.label9.Location = new System.Drawing.Point(497, 22); this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(95, 17); this.label9.TabIndex = 30; this.label9.Text = "CodeXL Asics"; // // lstCodeXLAsics // this.lstCodeXLAsics.FormattingEnabled = true; this.lstCodeXLAsics.Location = new System.Drawing.Point(501, 57); this.lstCodeXLAsics.Margin = new System.Windows.Forms.Padding(4); this.lstCodeXLAsics.Name = "lstCodeXLAsics"; this.lstCodeXLAsics.ScrollAlwaysVisible = true; this.lstCodeXLAsics.Size = new System.Drawing.Size(171, 123); this.lstCodeXLAsics.TabIndex = 29; // // txtRGA // this.txtRGA.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtRGA.Enabled = false; this.txtRGA.Location = new System.Drawing.Point(115, 474); this.txtRGA.Margin = new System.Windows.Forms.Padding(4); this.txtRGA.Name = "txtRGA"; this.txtRGA.Size = new System.Drawing.Size(705, 22); this.txtRGA.TabIndex = 34; // // btnRGA // this.btnRGA.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnRGA.Location = new System.Drawing.Point(828, 476); this.btnRGA.Margin = new System.Windows.Forms.Padding(4); this.btnRGA.Name = "btnRGA"; this.btnRGA.Size = new System.Drawing.Size(43, 23); this.btnRGA.TabIndex = 35; this.btnRGA.Text = "..."; this.btnRGA.UseVisualStyleBackColor = true; this.btnRGA.Click += new System.EventHandler(this.btnRGA_Click); // // lstRGAAsics // this.lstRGAAsics.FormattingEnabled = true; this.lstRGAAsics.Location = new System.Drawing.Point(700, 57); this.lstRGAAsics.Margin = new System.Windows.Forms.Padding(4); this.lstRGAAsics.Name = "lstRGAAsics"; this.lstRGAAsics.ScrollAlwaysVisible = true; this.lstRGAAsics.Size = new System.Drawing.Size(171, 123); this.lstRGAAsics.TabIndex = 36; // // label11 // this.label11.AutoSize = true; this.label11.Location = new System.Drawing.Point(696, 22); this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label11.Name = "label11"; this.label11.Size = new System.Drawing.Size(75, 17); this.label11.TabIndex = 37; this.label11.Text = "RGA Asics"; // // lstIncludes // this.lstIncludes.FormattingEnabled = true; this.lstIncludes.ItemHeight = 16; this.lstIncludes.Location = new System.Drawing.Point(115, 201); this.lstIncludes.Margin = new System.Windows.Forms.Padding(4); this.lstIncludes.Name = "lstIncludes"; this.lstIncludes.Size = new System.Drawing.Size(643, 68); this.lstIncludes.TabIndex = 39; // // btnDXIL // this.btnDXIL.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnDXIL.Location = new System.Drawing.Point(828, 505); this.btnDXIL.Margin = new System.Windows.Forms.Padding(4); this.btnDXIL.Name = "btnDXIL"; this.btnDXIL.Size = new System.Drawing.Size(43, 25); this.btnDXIL.TabIndex = 50; this.btnDXIL.Text = "..."; this.btnDXIL.UseVisualStyleBackColor = true; this.btnDXIL.Click += new System.EventHandler(this.btnDXIL_Click); // // txtDXIL // this.txtDXIL.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtDXIL.Enabled = false; this.txtDXIL.Location = new System.Drawing.Point(115, 506); this.txtDXIL.Margin = new System.Windows.Forms.Padding(4); this.txtDXIL.Name = "txtDXIL"; this.txtDXIL.Size = new System.Drawing.Size(705, 22); this.txtDXIL.TabIndex = 49; // // btnIntelShaderAnalyzer // this.btnIntelShaderAnalyzer.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnIntelShaderAnalyzer.Location = new System.Drawing.Point(830, 535); this.btnIntelShaderAnalyzer.Margin = new System.Windows.Forms.Padding(4); this.btnIntelShaderAnalyzer.Name = "btnIntelShaderAnalyzer"; this.btnIntelShaderAnalyzer.Size = new System.Drawing.Size(43, 25); this.btnIntelShaderAnalyzer.TabIndex = 53; this.btnIntelShaderAnalyzer.Text = "..."; this.btnIntelShaderAnalyzer.UseVisualStyleBackColor = true; this.btnIntelShaderAnalyzer.Click += new System.EventHandler(this.btnIntelShaderAnalyzer_Click); // // txtIntelShaderAnalyzer // this.txtIntelShaderAnalyzer.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.txtIntelShaderAnalyzer.Enabled = false; this.txtIntelShaderAnalyzer.Location = new System.Drawing.Point(117, 536); this.txtIntelShaderAnalyzer.Margin = new System.Windows.Forms.Padding(4); this.txtIntelShaderAnalyzer.Name = "txtIntelShaderAnalyzer"; this.txtIntelShaderAnalyzer.Size = new System.Drawing.Size(705, 22); this.txtIntelShaderAnalyzer.TabIndex = 52; // // OptionsScreen // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(897, 654); this.Controls.Add(this.btnIntelShaderAnalyzer); this.Controls.Add(this.txtIntelShaderAnalyzer); this.Controls.Add(this.label15); this.Controls.Add(this.btnDXIL); this.Controls.Add(this.txtDXIL); this.Controls.Add(this.label14); this.Controls.Add(this.numericUpDown1); this.Controls.Add(this.label13); this.Controls.Add(this.btnDeleteInclude); this.Controls.Add(this.btnAddInclude); this.Controls.Add(this.lstIncludes); this.Controls.Add(this.label12); this.Controls.Add(this.label11); this.Controls.Add(this.lstRGAAsics); this.Controls.Add(this.btnRGA); this.Controls.Add(this.txtRGA); this.Controls.Add(this.label9); this.Controls.Add(this.lstCodeXLAsics); this.Controls.Add(this.label8); this.Controls.Add(this.lstAMDAsics); this.Controls.Add(this.label7); this.Controls.Add(this.btnMali); this.Controls.Add(this.txtMali); this.Controls.Add(this.label6); this.Controls.Add(this.lstBackends); this.Controls.Add(this.label5); this.Controls.Add(this.btnDXX); this.Controls.Add(this.txtDXX); this.Controls.Add(this.btnDefaults); this.Controls.Add(this.btnPowerVR); this.Controls.Add(this.txtPowerVR); this.Controls.Add(this.label1); this.Controls.Add(this.btnCancel); this.Controls.Add(this.btnOk); this.Controls.Add(this.btnD3DCompiler); this.Controls.Add(this.btnCodeXL); this.Controls.Add(this.btnTemp); this.Controls.Add(this.label4); this.Controls.Add(this.label3); this.Controls.Add(this.label2); this.Controls.Add(this.txtTemp); this.Controls.Add(this.txtD3DCompiler); this.Controls.Add(this.txtCodeXL); this.Margin = new System.Windows.Forms.Padding(4); this.Name = "OptionsScreen"; this.Text = "OptionsScreen"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OptionsScreen_FormClosing); ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TextBox txtCodeXL; private System.Windows.Forms.TextBox txtD3DCompiler; private System.Windows.Forms.TextBox txtTemp; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; private System.Windows.Forms.Button btnTemp; private System.Windows.Forms.Button btnCodeXL; private System.Windows.Forms.Button btnD3DCompiler; private System.Windows.Forms.Button btnOk; private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox txtPowerVR; private System.Windows.Forms.Button btnPowerVR; private System.Windows.Forms.Button btnDefaults; private System.Windows.Forms.ToolTip toolTip1; private System.Windows.Forms.TextBox txtDXX; private System.Windows.Forms.Button btnDXX; private System.Windows.Forms.Label label5; private System.Windows.Forms.CheckedListBox lstBackends; private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label7; private System.Windows.Forms.Button btnMali; private System.Windows.Forms.TextBox txtMali; private System.Windows.Forms.CheckedListBox lstAMDAsics; private System.Windows.Forms.Label label8; private System.Windows.Forms.Label label9; private System.Windows.Forms.CheckedListBox lstCodeXLAsics; private System.Windows.Forms.TextBox txtRGA; private System.Windows.Forms.Button btnRGA; private System.Windows.Forms.CheckedListBox lstRGAAsics; private System.Windows.Forms.Label label11; private System.Windows.Forms.Label label12; private System.Windows.Forms.ListBox lstIncludes; private System.Windows.Forms.Button btnAddInclude; private System.Windows.Forms.Button btnDeleteInclude; private System.Windows.Forms.Label label13; private System.Windows.Forms.NumericUpDown numericUpDown1; private System.Windows.Forms.Label label14; private System.Windows.Forms.Button btnDXIL; private System.Windows.Forms.TextBox txtDXIL; private System.Windows.Forms.Button btnIntelShaderAnalyzer; private System.Windows.Forms.TextBox txtIntelShaderAnalyzer; private System.Windows.Forms.Label label15; } } ================================================ FILE: src/MainUI/OptionsScreen.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Pyramid { public partial class OptionsScreen : Form { private Options m_InitialOpts; private string m_IncludeBrowseStart = ""; public Options SelectedOptions { get; private set; } public OptionsScreen( Options opts, List backends ) { InitializeComponent(); m_InitialOpts = opts; PopulateGUIFromOptions(opts); foreach (IBackend backend in backends) { int index = lstBackends.Items.Add(backend.Name); lstBackends.SetItemChecked(index,!opts.IsBackendDisabled(backend.Name)); } // #mivance refactor IBackend amdBackend = backends.Find(backend => backend.Name == "AMDDXX"); if (amdBackend is AMDDriverBackend) { AMDDriverBackend driver = amdBackend as AMDDriverBackend; foreach (string asic in driver.Asics) { int index = lstAMDAsics.Items.Add(asic); lstAMDAsics.SetItemChecked(index, !opts.IsAMDAsicDisabled(asic)); } } IBackend codeXLBackend = backends.Find(backend => backend.Name == "CodeXL"); if (codeXLBackend is CodeXLBackend) { CodeXLBackend driver = codeXLBackend as CodeXLBackend; foreach (string asic in driver.Asics) { int index = lstCodeXLAsics.Items.Add(asic); lstCodeXLAsics.SetItemChecked(index, !opts.IsCodeXLAsicDisabled(asic)); } } if (System.IO.File.Exists(opts.RGAPath)) { List rgaAsics = RGABackend.GetAsicList(opts.RGAPath); foreach (string asic in rgaAsics) { int index = lstRGAAsics.Items.Add(asic); lstRGAAsics.SetItemChecked(index, !opts.IsRGAAsicDisabled(asic)); } } } private void PopulateGUIFromOptions(Options opts) { txtD3DCompiler.Text = opts.D3DCompilerPath; txtCodeXL.Text = opts.CodeXLPath; txtTemp.Text = opts.TempPath; txtPowerVR.Text = opts.PowerVRCompilerPath; txtDXX.Text = opts.DXXDriverPath; txtMali.Text = opts.MaliSCRoot; txtRGA.Text = opts.RGAPath; txtDXIL.Text = opts.DXILCompilerPath; txtIntelShaderAnalyzer.Text = opts.IntelShaderAnalyzerPath; foreach (string s in opts.IncludePaths) lstIncludes.Items.Add(s); // start include browsing at last include directory if (lstIncludes.Items.Count > 0) m_IncludeBrowseStart = (string) lstIncludes.Items[lstIncludes.Items.Count - 1]; } private string BrowseFile( string initial ) { OpenFileDialog fd = new OpenFileDialog(); fd.FileName = initial; if (fd.ShowDialog() != DialogResult.Cancel) return fd.FileName; else return initial; } private string BrowseFolder(string initial) { FolderBrowserDialog fd = new FolderBrowserDialog(); if( !string.IsNullOrEmpty(initial) && System.IO.Directory.Exists(initial)) fd.SelectedPath = initial; if (fd.ShowDialog() != DialogResult.Cancel) return fd.SelectedPath; else return initial; } private void btnD3DCompiler_Click(object sender, EventArgs e) { txtD3DCompiler.Text = BrowseFile(txtD3DCompiler.Text); } private void btnCodeXL_Click(object sender, EventArgs e) { txtCodeXL.Text = BrowseFile(txtCodeXL.Text); } private void btnTemp_Click(object sender, EventArgs e) { txtTemp.Text = BrowseFolder(txtTemp.Text); } private void OptionsScreen_FormClosing(object sender, FormClosingEventArgs e) { if (this.DialogResult == DialogResult.Cancel) { SelectedOptions = m_InitialOpts; } else { SelectedOptions = new Options(); SelectedOptions.CodeXLPath = txtCodeXL.Text; SelectedOptions.D3DCompilerPath = txtD3DCompiler.Text; SelectedOptions.TempPath = txtTemp.Text; SelectedOptions.PowerVRCompilerPath = txtPowerVR.Text; SelectedOptions.DXXDriverPath = txtDXX.Text; SelectedOptions.MaliSCRoot = txtMali.Text ; SelectedOptions.RGAPath = txtRGA.Text; SelectedOptions.DXILCompilerPath = txtDXIL.Text; SelectedOptions.IntelShaderAnalyzerPath = txtIntelShaderAnalyzer.Text; for (int backendIndex = 0; backendIndex < lstBackends.Items.Count; backendIndex++) { if (!lstBackends.GetItemChecked(backendIndex)) SelectedOptions.DisableBackend(lstBackends.Items[backendIndex].ToString()); } for (int amdAsicIndex = 0; amdAsicIndex < lstAMDAsics.Items.Count; amdAsicIndex++) { if (!lstAMDAsics.GetItemChecked(amdAsicIndex)) { SelectedOptions.DisableAMDAsic(lstAMDAsics.Items[amdAsicIndex].ToString()); } } for (int codeXLAsicIndex = 0; codeXLAsicIndex < lstCodeXLAsics.Items.Count; codeXLAsicIndex++) { if (!lstCodeXLAsics.GetItemChecked(codeXLAsicIndex)) { SelectedOptions.DisableCodeXLAsic(lstCodeXLAsics.Items[codeXLAsicIndex].ToString()); } } for (int i = 0; i < lstRGAAsics.Items.Count; i++) { if (!lstRGAAsics.GetItemChecked(i)) { SelectedOptions.DisableRGAAsic(lstRGAAsics.Items[i].ToString()); } } foreach( string s in lstIncludes.Items ) SelectedOptions.AddInclude(s); } } private void btnPowerVR_Click(object sender, EventArgs e) { txtPowerVR.Text = BrowseFolder(txtPowerVR.Text); } private void btnDefaults_Click(object sender, EventArgs e) { Options opts = Options.GetDefaults(); PopulateGUIFromOptions(opts); for (int i = 0; i < lstBackends.Items.Count; i++) lstBackends.SetItemChecked(i, true); } private void btnDXX_Click(object sender, EventArgs e) { txtDXX.Text = BrowseFile(txtDXX.Text); } private void btnMali_Click(object sender, EventArgs e) { txtMali.Text = BrowseFolder(txtMali.Text); } private void btnRGA_Click(object sender, EventArgs e) { txtRGA.Text = BrowseFile(txtRGA.Text); } private void btnAddInclude_Click(object sender, EventArgs e) { FolderBrowserDialog fd = new FolderBrowserDialog(); if( System.IO.Directory.Exists(m_IncludeBrowseStart) ) fd.SelectedPath = m_IncludeBrowseStart; if (fd.ShowDialog() != DialogResult.Cancel) { string path = fd.SelectedPath; if (!lstIncludes.Items.Contains(path)) { lstIncludes.Items.Add(path); m_IncludeBrowseStart = path; // remember last place user browsed to } } } private void btnDeleteInclude_Click(object sender, EventArgs e) { if( lstIncludes.SelectedItem != null ) { lstIncludes.Items.Remove(lstIncludes.SelectedItem); } } private void numericUpDown1_ValueChanged(object sender, EventArgs e) { if (lstIncludes.SelectedItem != null) { // figure out which direction user wamts it moved in int direction = (int)numericUpDown1.Value; int oldPlace = lstIncludes.SelectedIndex; int newPlace = lstIncludes.SelectedIndex; if (direction == 1) { // user clicked the up arrow, move it up if( lstIncludes.SelectedIndex > 0 ) newPlace = oldPlace - 1; } else if (direction == -1) { // user clicked the down arrow, move it down if (lstIncludes.SelectedIndex < lstIncludes.Items.Count - 1) newPlace = oldPlace + 1; } if( oldPlace != newPlace ) { string a = (string) lstIncludes.Items[oldPlace]; string b = (string) lstIncludes.Items[newPlace]; lstIncludes.Items[oldPlace] = b; lstIncludes.Items[newPlace] = a; lstIncludes.SelectedIndex = newPlace; } } // clear the updown for next time numericUpDown1.Value = 0; } private void btnDXIL_Click(object sender, EventArgs e) { txtDXIL.Text = BrowseFile(txtDXIL.Text); } private void btnIntelShaderAnalyzer_Click(object sender, EventArgs e) { txtIntelShaderAnalyzer.Text = BrowseFile(txtIntelShaderAnalyzer.Text); } private void label15_Click(object sender, EventArgs e) { } } } ================================================ FILE: src/MainUI/OptionsScreen.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 17, 17 ================================================ FILE: src/Options.cs ================================================ using System; using System.IO; using System.Collections.Generic; using System.Windows.Forms; namespace Pyramid { public class Options { private List m_DisabledBackends = new List(); private List m_DisabledAMDAsics = new List(); private List m_DisabledCodeXLAsics = new List(); private List m_DisabledRGAAsics = new List(); private List m_IncludePaths = new List(); public string RGAPath { get; set; } public string D3DCompilerPath { get; set; } public string DXILCompilerPath { get; set; } public string CodeXLPath { get; set; } public string TempPath { get; set; } public string PowerVRCompilerPath { get; set; } public string DXXDriverPath { get; set; } public string MaliSCRoot { get; set; } public string IntelShaderAnalyzerPath { get; set; } public IEnumerable DisabledBackends { get { return m_DisabledBackends; } } public IEnumerable DisabledAMDAsics { get { return m_DisabledAMDAsics; } } public IEnumerable DisabledCodeXLAsics { get { return m_DisabledCodeXLAsics; } } public IEnumerable DisabledRGAAsics { get { return m_DisabledRGAAsics; } } public IEnumerable IncludePaths { get { return m_IncludePaths; } } public void DisableBackend(string name) { m_DisabledBackends.Add(name); } public bool IsBackendDisabled(string name) { return m_DisabledBackends.Contains(name); } public void DisableRGAAsic(string name) { m_DisabledRGAAsics.Add(name); } public bool IsRGAAsicDisabled(string name) { return m_DisabledRGAAsics.Contains(name); } public void DisableAMDAsic(string name) { m_DisabledAMDAsics.Add(name); } public bool IsAMDAsicDisabled(string name) { return m_DisabledAMDAsics.Contains(name); } public void DisableCodeXLAsic(string name) { m_DisabledCodeXLAsics.Add(name); } public bool IsCodeXLAsicDisabled(string name) { return m_DisabledCodeXLAsics.Contains(name); } public void AddInclude(string include) { if( !m_IncludePaths.Contains(include)) m_IncludePaths.Add(include); } public void RemoveInclude( string include ) { m_IncludePaths.Remove(include); } public static Options GetDefaults() { Options opts = new Options(); opts.D3DCompilerPath = "d3dcompiler_47.dll"; opts.DXILCompilerPath = "dxcompiler.dll"; opts.CodeXLPath = "CodeXLAnalyzer.exe"; opts.PowerVRCompilerPath = "PowerVR"; opts.DXXDriverPath = "atidxx32.dll"; opts.MaliSCRoot = "MaliSC"; opts.RGAPath = "rga\\rga.exe"; opts.IntelShaderAnalyzerPath = "IntelShaderAnalyzer\\IntelShaderAnalyzer.exe"; opts.TempPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Pyramid" ); return opts; } public static Options Get() { string OptionsFile = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Pyramid\\options" ); Options defaults = GetDefaults(); if (!System.IO.File.Exists(OptionsFile)) return defaults; Options opts = new Options(); try { string[] lines = File.ReadAllLines(OptionsFile); Dictionary map = new Dictionary(); foreach( string s in lines ) { int idx = s.IndexOf('='); string key = s.Substring(0, idx); string value = s.Substring(idx+1); map.Add(key, value); } string d3dCompiler; if (!map.TryGetValue("D3DCompiler", out d3dCompiler)) d3dCompiler = defaults.D3DCompilerPath; string dxilCompiler; if (!map.TryGetValue("DXILCompiler", out dxilCompiler)) dxilCompiler = defaults.DXILCompilerPath; string codeXL; if (!map.TryGetValue("CodeXL", out codeXL)) codeXL = defaults.CodeXLPath; string temp; if (!map.TryGetValue("temp", out temp)) temp = defaults.TempPath; string pvr; if (!map.TryGetValue("PowerVR", out pvr)) pvr = defaults.PowerVRCompilerPath; string dxx; if (!map.TryGetValue("DXX", out dxx)) dxx = defaults.DXXDriverPath; string mali; if (!map.TryGetValue("Mali", out mali)) mali = defaults.MaliSCRoot; string disabledBackends; if( map.TryGetValue("DisabledBackends", out disabledBackends)) opts.m_DisabledBackends.AddRange(disabledBackends.Split(',')); string disabledAMDAsics; if (map.TryGetValue("DisabledAMDAsics", out disabledAMDAsics)) opts.m_DisabledAMDAsics.AddRange(disabledAMDAsics.Split(',')); string disabledCodeXLAsics; if (map.TryGetValue("DisabledCodeXLAsics", out disabledCodeXLAsics)) opts.m_DisabledCodeXLAsics.AddRange(disabledCodeXLAsics.Split(',')); string disabledRGAAsics; if (map.TryGetValue("DisabledRGAAsics", out disabledRGAAsics)) opts.m_DisabledRGAAsics.AddRange(disabledRGAAsics.Split(',')); string rga; if (!map.TryGetValue("RGAPath", out rga)) rga = defaults.RGAPath; string intelAnalyzer; if (!map.TryGetValue("IntelShaderAnalyzerPath", out intelAnalyzer)) intelAnalyzer = defaults.IntelShaderAnalyzerPath; string includePaths; if (map.TryGetValue("IncludePaths", out includePaths)) opts.m_IncludePaths.AddRange(includePaths.Split('?')); opts.D3DCompilerPath = d3dCompiler; opts.DXILCompilerPath = dxilCompiler; opts.CodeXLPath = codeXL; opts.TempPath = temp; opts.PowerVRCompilerPath = pvr; opts.DXXDriverPath = dxx; opts.MaliSCRoot = mali; opts.RGAPath = rga; opts.IntelShaderAnalyzerPath = intelAnalyzer; return opts; } catch (Exception e) { // not found MessageBox.Show(e.Message, "uh-oh, couldn't read options file", MessageBoxButtons.OK, MessageBoxIcon.Error); return GetDefaults(); } } public void Write() { string OptionsFile = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Pyramid\\options"); try { string DisabledBackends = String.Join(",",m_DisabledBackends.ToArray()); string DisabledAMDAsics = String.Join(",",m_DisabledAMDAsics.ToArray()); string DisabledCodeXLAsics = String.Join(",", m_DisabledCodeXLAsics.ToArray()); string DisabledRGAAsics = String.Join(",", m_DisabledRGAAsics.ToArray()); // NOTE: remember, must join include paths with a non-path character string IncludePaths = String.Join("?", m_IncludePaths); File.WriteAllText(OptionsFile, String.Format("D3DCompiler={0}\nCodeXL={1}\ntemp={2}\nPowerVR={3}\nMali={4}\nDisabledBackends={5}\nDisabledAMDAsics={6}\nDisabledCodeXLAsics={7}\nRGAPath={8}\nDisabledRGAAsics={9}\nIncludePaths={10}\nDXILCompiler={11}\nIntelShaderAnalyzerPath={12}\n", D3DCompilerPath, CodeXLPath, TempPath, PowerVRCompilerPath, MaliSCRoot, DisabledBackends, DisabledAMDAsics, DisabledCodeXLAsics, RGAPath, DisabledRGAAsics, IncludePaths, DXILCompilerPath, IntelShaderAnalyzerPath )); } catch(Exception e) { MessageBox.Show(e.Message, "uh-oh, couldn't write options file", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } } ================================================ FILE: src/Program.cs ================================================ using System; using System.Collections.Generic; using System.Windows.Forms; using System.Reflection; namespace Pyramid { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Options opts = Options.Get(); System.IO.Directory.CreateDirectory(opts.TempPath); IWrapper wrapper = new Wrapper(); MainForm main = new MainForm( opts, wrapper ); Application.Run(main); main.Options.Write(); } } } ================================================ FILE: src/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Pyramid")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Pyramid")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("20c36372-9723-4568-8ed4-853d62821d0e")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: src/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.34014 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace Pyramid.Properties { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Pyramid.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } } } ================================================ FILE: src/Properties/Resources.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Properties/Settings.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.34014 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace Pyramid.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } } } ================================================ FILE: src/Properties/Settings.settings ================================================  ================================================ FILE: src/Pyramid.csproj ================================================  Debug AnyCPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1} WinExe Properties Pyramid Pyramid v4.5 512 publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false false true x86 true full false bin\Debug\ DEBUG;TRACE prompt 4 false x86 pdbonly true bin\Release\ TRACE prompt 4 false UserControl AMDDriverResultsPanel.cs UserControl GLSlangResultsPanel.cs UserControl IntelShaderAnalyzerResultsPanel.cs UserControl MaliSCResultsPanel.cs Form AboutBox.cs UserControl CodeXLAnalysisPanel.cs UserControl CodeXLResultsPanel.cs UserControl FXCResultsPanel.cs UserControl GLSLOptionsPanel.cs UserControl HLSLOptionsPanel.cs Form MainForm.cs Form OptionsScreen.cs UserControl PVRResultsPanel.cs UserControl CFGWidget.cs UserControl InstructionWidget.cs UserControl ParameterWidget.cs Form ScrutinizerForm.cs AMDDriverResultsPanel.cs GLSlangResultsPanel.cs IntelShaderAnalyzerResultsPanel.cs MaliSCResultsPanel.cs AboutBox.cs CodeXLAnalysisPanel.cs CodeXLResultsPanel.cs FXCResultsPanel.cs GLSLOptionsPanel.cs HLSLOptionsPanel.cs MainForm.cs OptionsScreen.cs ResXFileCodeGenerator Resources.Designer.cs Designer True Resources.resx True PVRResultsPanel.cs CFGWidget.cs InstructionWidget.cs ScrutinizerForm.cs SettingsSingleFileGenerator Settings.Designer.cs True Settings.settings True False .NET Framework 3.5 SP1 Client Profile false False .NET Framework 3.5 SP1 true {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} ICSharpCode.TextEditor {3d7db344-0267-4890-8186-9fc22b78b738} PyramidTypes {aeccee3c-29c5-46de-9ae2-afb5df6d110a} Wrapper copy $(TargetPath) $(SolutionDir)\..\bin ================================================ FILE: src/Pyramid.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Windows Desktop VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pyramid", "Pyramid.csproj", "{BFF31873-BEEA-4528-ACE9-27DDFD150BF1}" ProjectSection(ProjectDependencies) = postProject {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A} = {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Wrapper", "Wrapper\Wrapper.vcxproj", "{AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}" ProjectSection(ProjectDependencies) = postProject {B475A403-9D9B-410D-8A93-BA49FC4DD811} = {B475A403-9D9B-410D-8A93-BA49FC4DD811} {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3} = {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PyramidTypes", "PyramidTypes.csproj", "{3D7DB344-0267-4890-8186-9FC22B78B738}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glsl_optimizer_lib_2013", "Wrapper\glsl-optimizer\projects\vs2013\glsl_optimizer_lib_2013.vcxproj", "{B475A403-9D9B-410D-8A93-BA49FC4DD811}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TextEditor", "ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj", "{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glslang", "Wrapper\GLSlang\glslang_Pyramid.vcxproj", "{3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BB77DB07-A9CC-44F1-B567-E77BF5F82440}" ProjectSection(SolutionItems) = preProject ..\README.md = ..\README.md EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Debug|Any CPU.Build.0 = Debug|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Debug|Win32.ActiveCfg = Debug|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Debug|Win32.Build.0 = Debug|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Debug|x64.ActiveCfg = Debug|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Release|Any CPU.ActiveCfg = Release|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Release|Any CPU.Build.0 = Release|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Release|Mixed Platforms.Build.0 = Release|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Release|Win32.ActiveCfg = Release|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Release|Win32.Build.0 = Release|Any CPU {BFF31873-BEEA-4528-ACE9-27DDFD150BF1}.Release|x64.ActiveCfg = Release|Any CPU {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Debug|Any CPU.ActiveCfg = Debug|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Debug|Win32.ActiveCfg = Debug|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Debug|Win32.Build.0 = Debug|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Debug|x64.ActiveCfg = Debug|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Release|Any CPU.ActiveCfg = Release|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Release|Mixed Platforms.Build.0 = Release|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Release|Win32.ActiveCfg = Release|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Release|Win32.Build.0 = Release|Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A}.Release|x64.ActiveCfg = Release|Win32 {3D7DB344-0267-4890-8186-9FC22B78B738}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Debug|Win32.ActiveCfg = Debug|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Debug|Win32.Build.0 = Debug|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Debug|x64.ActiveCfg = Debug|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Release|Any CPU.Build.0 = Release|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Release|Mixed Platforms.Build.0 = Release|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Release|Win32.ActiveCfg = Release|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Release|Win32.Build.0 = Release|Any CPU {3D7DB344-0267-4890-8186-9FC22B78B738}.Release|x64.ActiveCfg = Release|Any CPU {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Debug|Any CPU.ActiveCfg = Debug|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Debug|Win32.ActiveCfg = Debug|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Debug|Win32.Build.0 = Debug|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Debug|x64.ActiveCfg = Debug|x64 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Debug|x64.Build.0 = Debug|x64 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Release|Any CPU.ActiveCfg = Release|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Release|Mixed Platforms.Build.0 = Release|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Release|Win32.ActiveCfg = Release|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Release|Win32.Build.0 = Release|Win32 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Release|x64.ActiveCfg = Release|x64 {B475A403-9D9B-410D-8A93-BA49FC4DD811}.Release|x64.Build.0 = Release|x64 {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Win32.ActiveCfg = Debug|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Win32.Build.0 = Debug|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|x64.ActiveCfg = Debug|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.ActiveCfg = Release|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.Build.0 = Release|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Mixed Platforms.Build.0 = Release|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Win32.ActiveCfg = Release|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Win32.Build.0 = Release|Any CPU {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|x64.ActiveCfg = Release|Any CPU {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Debug|Any CPU.ActiveCfg = Debug|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Debug|Win32.ActiveCfg = Debug|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Debug|Win32.Build.0 = Debug|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Debug|x64.ActiveCfg = Debug|x64 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Debug|x64.Build.0 = Debug|x64 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Release|Any CPU.ActiveCfg = Release|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Release|Mixed Platforms.Build.0 = Release|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Release|Win32.ActiveCfg = Release|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Release|Win32.Build.0 = Release|Win32 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Release|x64.ActiveCfg = Release|x64 {3B146CC5-B2B8-4573-9D46-6139E2EDFEA3}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: src/PyramidTypes.csproj ================================================  Debug AnyCPU {3D7DB344-0267-4890-8186-9FC22B78B738} Library Properties PyramidTypes PyramidTypes v4.5 512 AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 copy $(TargetPath) $(SolutionDir)\..\bin ================================================ FILE: src/SPIRV.cs ================================================ using System; namespace Pyramid { namespace SPIRV { public interface IProgram { string Disassemble(); uint[] GetTokens(); byte[] GetBytes(); } } } ================================================ FILE: src/Scrutinizer/Analysis/Algorithms.cs ================================================ using System; using System.Collections.Generic; using System.Linq; namespace Pyramid.Scrutinizer { public static class Algorithms { public static bool IsCFGReducible( List Blocks ) { BasicBlock[] blocks = Blocks.ToArray(); HashSet[] Successors = new HashSet[blocks.Length]; HashSet[] Predecessors = new HashSet[blocks.Length]; Dictionary Index = new Dictionary(); // For reference: http://www.cs.colostate.edu/~mstrout/CS553Fall06/slides/lecture13-control.pdf // A CFG is reducible if it can be reduced to a single node via T1/T2 transforms // int nBlocks = 0; foreach (BasicBlock b in blocks) { Successors[nBlocks] = new HashSet(b.Successors); Predecessors[nBlocks] = new HashSet(b.Predecessors); Index.Add(b, nBlocks); nBlocks++; } while (nBlocks > 1) { // T1 transform: delete all self-loops for (int i = 0; i < nBlocks; i++) { BasicBlock bi = blocks[i]; Successors[i].Remove(blocks[i]); Predecessors[i].Remove(blocks[i]); } // find nodes having only one predecessor and merge them into their predecessor int n = nBlocks; nBlocks = 0; for (int i = 0; i < n; i++) { if (Predecessors[i].Count == 1) { // merge this node with its single predecessor BasicBlock victim = blocks[i]; BasicBlock replacement = Predecessors[i].ElementAt(0); // link successor blocks to replacement foreach (BasicBlock s in Successors[i]) { var preds = Predecessors[Index[s]]; preds.Remove(victim); preds.Add(replacement); } // link replacement to successors var replacement_successors = Successors[Index[replacement]]; replacement_successors.Remove(victim); replacement_successors.UnionWith(Successors[i]); } else { // compact the array blocks[nBlocks++] = blocks[i]; } } // bail out if we failed to find a reducible node if (n == nBlocks) return false; } return true; } public static List BuildBasicBlocks(List ops) { // collect set of branch targets HashSet BranchTargets = new HashSet(); foreach( IInstruction op in ops ) { if( op is IJumpInstruction ) { IJumpInstruction it = op as IJumpInstruction; BranchTargets.Add( it.Target ); } else if( op is IBranchInstruction ) { IBranchInstruction it = op as IBranchInstruction; BranchTargets.Add( it.IfTarget ); BranchTargets.Add( it.ElseTarget ); } } // walk instruction list and split off blocks at branches or branch targets List Blocks = new List(); int nInstructions = ops.Count; int i = 0; do { BasicBlock block = new BasicBlock(); Blocks.Add(block); do { IInstruction op = ops[i++]; block.AddInstruction(op); op.Block = block; // stop if we just added a branch/jump op if (op is IJumpInstruction || op is IBranchInstruction) break; // stop if next instruction is a branch target if (i /// Test whether node a dominates node b /// That is, a is equal to be, or an ancestor of b in the dom tree /// /// /// /// /// /// public static bool Dominates( T a, T b, Dictionary IDOM ) where T : class { if (a == b) return true; T n = IDOM[b]; while( n != null && n != a ) n = IDOM[n]; return n == a; } /// /// Find immediate dominators for each node in a graph /// /// /// /// public static Dictionary FindDominators( T[] nodes, T[][] predecessors ) where T : class { if( nodes.Length == 0 ) return new Dictionary(); // Algorithm here is based on Keith Kooper's COMP512 lecture nodes // from: http://www.cs.rice.edu/~keith/512/2011/Lectures/ // // This could be made redonkulously fast using bit vectors, but we're already using C# so why bother... // dominator of the start node is the start itself //Dom(n0) = {n0} //// for all other nodes, set all nodes as the dominators //for each n in N - {n0} // Dom(n) = N; //// iteratively eliminate nodes that are not dominators //while changes in any Dom(n) // for each n in N - {n0}: // JDB: Note, just N also works... // Dom(n) = {n} union with intersection over all p in pred(n) of Dom(p) Dictionary> doms = new Dictionary>(); // dominator of start node is the node itself // dom-set of other nodes initially set to entire graph T start = nodes[0]; foreach (T b in nodes) { if (b == start) { HashSet s = new HashSet(); s.Add(b); doms.Add(b,s); } else { doms.Add(b, new HashSet(nodes)); } } //// iteratively eliminate nodes that are not dominators //while changes in any Dom(n) // for each n in N - {n0}: // JDB: Note, just N also works... // Dom(n) = {n} union with intersection over all p in pred(n) of Dom(p) int changes; do { changes = 0; for (int i = 0; i < nodes.Length; i++ ) { HashSet s = new HashSet(); T[] preds = predecessors[i]; if (preds.Length > 0) { foreach (T d in doms[preds[0]]) s.Add(d); for (int j = 1; j < preds.Length; j++) s.IntersectWith(doms[preds[j]]); } T n = nodes[i]; s.Add(n); if (!s.SetEquals(doms[n])) changes++; doms[n] = s; } } while (changes != 0); // find immediate dominator for each block // IDOM[b] is the node from doms[b] with highest dominator count // excluding the node itself // // IDOM[start] = null // Dictionary IDOM = new Dictionary(); for( int i=0; i Blocks) { BasicBlock[] nodes = Blocks.ToArray(); BasicBlock[][] preds = new BasicBlock[nodes.Length][]; BasicBlock[][] succs = new BasicBlock[nodes.Length][]; for (int i = 0; i < nodes.Length; i++) { preds[i] = nodes[i].Predecessors.ToArray(); succs[i] = nodes[i].Successors.ToArray(); } // dominators Dictionary IDOM = FindDominators(nodes, preds); for( int i=0; i PDOM = FindDominators( nodes, succs ); for (int i = 0; i < nodes.Length; i++) nodes[i].PostDominator = PDOM[nodes[i]]; } public static List FindLoops( List blocks ) { // Great reference: T Mowry's slides on loop invariant code motion // http://www.cs.cmu.edu/afs/cs/academic/class/15745-s11/public/lectures/L7-LICM.pdf // // We assume a reversible flow graph // // 1. Find back edges List> BackEdges = new List>(); foreach (BasicBlock b in blocks) foreach( BasicBlock s in b.Successors ) if (s.Dominates(b)) BackEdges.Add(new KeyValuePair(b, s)); // 2. Identify natural loop for each backedge // by walking graph upwards to dominator // // The natural loop of a back edge is the set of blocks dominated by the head // and which can reach the tail without traversing any backedge // HashSet[] LoopSets = new HashSet[BackEdges.Count]; for (int i = 0; i < BackEdges.Count; i++) LoopSets[i] = new HashSet(); Stack S = new Stack(); for( int i=0; i 0); } // // 3. Merge loops with same header wherever one is not a proper subset of the other // List loops = new List(); for (int i = 0; i < BackEdges.Count; i++) { BasicBlock header = BackEdges[i].Value; HashSet loop = LoopSets[i]; if (loop == null) continue; // this loop was merged earlier // find other loops with same header and merge with them with in with this one for (int j = i + 1; j < BackEdges.Count; j++) { if (BackEdges[j].Value == header) { HashSet otherLoop = LoopSets[j]; if (loop.IsProperSubsetOf(otherLoop) ) continue; if (otherLoop.IsProperSupersetOf(loop)) continue; LoopSets[i].UnionWith(LoopSets[j]); LoopSets[j] = null; } } loops.Add(new Loop(header, loop)); } // Determine nestedness for remaining loops // Loops are now either disjoint, or one is fully nested in the other // loop i is nested in loop j if j's header dominates i's header // or they have the same header and j is larger int nLoops = loops.Count; List[] LoopAncestors = new List[nLoops]; for (int i = 0; i < nLoops; i++) { List ancestors = new List(); Loop li = loops[i]; for (int j = 0; j < nLoops; j++) { if (i == j) continue; Loop lj = loops[j]; if (li.Header != lj.Header ) { if (lj.Header.Dominates(li.Header)) ancestors.Add(j); } else { if (lj.BlockCount > li.BlockCount ) ancestors.Add(j); } } LoopAncestors[i] = ancestors; } int[] DescendentCounts = new int[nLoops]; for (int i = 0; i < nLoops; i++ ) foreach (int k in LoopAncestors[i]) DescendentCounts[k]++; // Find innermost parent for each loop, // which is the one with the lowest descendent count for (int i = 0; i < nLoops; i++) { List ancestors = LoopAncestors[i]; if ( ancestors.Count != 0 ) { int nImmediateParent = ancestors[0]; for (int j = 1; j < ancestors.Count; j++) if (DescendentCounts[ancestors[j]] < DescendentCounts[nImmediateParent]) nImmediateParent = ancestors[j]; loops[i].Parent = loops[nImmediateParent]; } } // sort loops inner to outer loops.Sort( delegate(Loop x, Loop y) { if (x == y) return 0; while (true) { x = x.Parent; if (x == null) return 1; else if (x == y) return -1; } } ); // Identify innermost loop for each block foreach( Loop l in loops ) { foreach (BasicBlock b in l.Blocks) { if (b.InnerMostLoop == null) b.InnerMostLoop = l; else if (l.IsNestedIn(b.InnerMostLoop)) b.InnerMostLoop = l; } } return loops; } static public void ClassifyBranches( List ops ) { // It can be shown (I think) that, given our irreducible graph/nested loop structure // for any branch node n in loop L // at least one of N's two edges must be to a node also in L // // This follows from the construction of the loops // The loop set is the set of nodes dominated by the header // having paths to the header using only nodes in the loop set // // // Note that it is still possible to have a branch that descends into one of two different // nested sub-loops // We can thus classify branch instructions into two types: // - Fork // * both targets are nested within the containing block's loop // // - Break branch // * At most one target is outside the containing block's loop // foreach( IInstruction op in ops ) { if (!(op is IBranchInstruction)) continue; IBranchInstruction branch = op as IBranchInstruction; Loop ifLoop = branch.IfTarget.Block.InnerMostLoop; Loop elseLoop = branch.ElseTarget.Block.InnerMostLoop; Loop blockLoop = op.Block.InnerMostLoop; if (blockLoop == null) { branch.Category = BranchCategory.FORK_BRANCH; } else { if (ifLoop == null && elseLoop == null) branch.Category = BranchCategory.FORK_BRANCH; else if (ifLoop == null && elseLoop != null) branch.Category = BranchCategory.BREAK_BRANCH; else if (ifLoop != null && elseLoop == null) branch.Category = BranchCategory.BREAK_BRANCH; else if (ifLoop.IsNestedIn(blockLoop) && elseLoop.IsNestedIn(blockLoop)) branch.Category = BranchCategory.FORK_BRANCH; else if (ifLoop.IsNestedIn(blockLoop) || elseLoop.IsNestedIn(blockLoop)) branch.Category = BranchCategory.BREAK_BRANCH; else throw new System.Exception("Ooops"); } // A "fork branch" can, in turn, be classified as: // - continue (conditional jump back to header) // - skip (jumps directly to branch's post-dominator) // - fork (everything else) if( branch.Category == BranchCategory.FORK_BRANCH ) { if (blockLoop != null && (branch.IfTarget == blockLoop.Header || branch.ElseTarget == blockLoop.Header)) { branch.Category = BranchCategory.CONTINUE_BRANCH; } if( branch.IfTarget.Block == branch.Block.PostDominator || branch.ElseTarget.Block == branch.Block.PostDominator ) { branch.Category = BranchCategory.SKIP_BRANCH; // a skip branch that jumps around a loop is yet another special case if( branch.IfTarget.Block != branch.Block.PostDominator && branch.IfTarget.Block.InnerMostLoop != blockLoop ) branch.Category = BranchCategory.LOOPSKIP_BRANCH; else if (branch.ElseTarget.Block != branch.Block.PostDominator && branch.ElseTarget.Block.InnerMostLoop != blockLoop) branch.Category = BranchCategory.LOOPSKIP_BRANCH; } } } } public static void AssignLabels(List ops) { int nBlock = 0; BasicBlock bl = null; for( int i=0; i DoTrace(List ops, List blocks, List loops, HashSet takenBranches ) { List Exec = new List(); Dictionary LoopCounts = new Dictionary(); foreach (Loop l in loops) LoopCounts.Add(l, 0); BasicBlock b = blocks.First(); do { // execute all instructions in current block Exec.AddRange(b.Instructions); // if block ends in a branch, determine which edge to take IInstruction blockEnd = b.LastInstruction; BasicBlock next = null; if (blockEnd is IBranchInstruction) { IBranchInstruction branch = blockEnd as IBranchInstruction; if( branch.Category == BranchCategory.BREAK_BRANCH ) { // take a break branch as soon as the iteration count reaches zero BasicBlock exit = branch.IfTarget.Block; BasicBlock noexit = branch.ElseTarget.Block; if (exit.InnerMostLoop == b.InnerMostLoop) { exit = branch.ElseTarget.Block; noexit = branch.IfTarget.Block; } if (LoopCounts[b.InnerMostLoop] >= b.InnerMostLoop.DesiredIterations) { LoopCounts[b.InnerMostLoop] = 0; next = exit; } else { next = noexit; } } else if( branch.Category == BranchCategory.LOOPSKIP_BRANCH ) { // don't enter unless the loop's iteration count is non-zero BasicBlock loop; BasicBlock noloop; if (branch.IfTarget.Block.InnerMostLoop != branch.Block.InnerMostLoop) { loop = branch.IfTarget.Block; noloop = branch.ElseTarget.Block; } else { loop = branch.ElseTarget.Block; noloop = branch.IfTarget.Block; } if (loop.InnerMostLoop.DesiredIterations > 0) next = loop; else next = noloop; } else if( branch.Category == BranchCategory.CONTINUE_BRANCH ) { // do NOT take a continue branch if the count's up BasicBlock go = branch.IfTarget.Block; BasicBlock nogo = branch.ElseTarget.Block; if (nogo == b.InnerMostLoop.Header) { go = branch.ElseTarget.Block; nogo = branch.IfTarget.Block; // swap if needed } if (LoopCounts[b.InnerMostLoop] >= b.InnerMostLoop.DesiredIterations) next = nogo; else next = go; } else { if (takenBranches.Contains(branch)) next = branch.IfTarget.Block; else next = branch.ElseTarget.Block; } } else if( blockEnd is IJumpInstruction ) { // if block ends in a jump, then jump IJumpInstruction jump = blockEnd as IJumpInstruction; next = jump.Target.Block; } else { // otherwise, proceed to next successor block if (b.SuccessorCount > 0) next = b.Successors.First(); } // increment loop count every time we pass a loop header if( b.InnerMostLoop != null && b.InnerMostLoop.Header == b ) LoopCounts[b.InnerMostLoop]++; b = next; } while (b != null); return Exec; } }; } ================================================ FILE: src/Scrutinizer/UI/CFGWidget.Designer.cs ================================================ namespace Pyramid.Scrutinizer.UI { partial class CFGWidget { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.treeView1 = new System.Windows.Forms.TreeView(); this.SuspendLayout(); // // treeView1 // this.treeView1.Dock = System.Windows.Forms.DockStyle.Fill; this.treeView1.Location = new System.Drawing.Point(0, 0); this.treeView1.Name = "treeView1"; this.treeView1.Size = new System.Drawing.Size(280, 270); this.treeView1.TabIndex = 0; this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect); this.treeView1.Leave += new System.EventHandler(this.treeView1_Leave); // // CFGWidget // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.treeView1); this.Name = "CFGWidget"; this.Size = new System.Drawing.Size(280, 270); this.ResumeLayout(false); } #endregion private System.Windows.Forms.TreeView treeView1; } } ================================================ FILE: src/Scrutinizer/UI/CFGWidget.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid.Scrutinizer.UI { /// /// Control which is responsible for visualizing the control flow graph and /// allowing users to select blocks /// /// public partial class CFGWidget : UserControl { public CFGWidget() { InitializeComponent(); } private class Node { public string NodeType = "node"; }; private class LoopNode : Node { public LoopNode(Graph sub, Loop loop) { NodeType = "loop"; SubGraph = sub; m_Loop = loop; } public Loop m_Loop = null; public Graph SubGraph = null; } private class LeafNode : Node { public LeafNode( BasicBlock bl ) { Block = bl; NodeType = "node"; } public BasicBlock Block = null; } private class BranchNode : Node { public Graph IfGraph; public Graph ElseGraph; public LeafNode Test; public List OwnedNodes; public BasicBlock IfTarget; public BasicBlock ElseTarget; public BranchNode( LeafNode test ) { Test = test; IfGraph = new Graph(); ElseGraph = new Graph(); OwnedNodes = new List(); OwnedNodes.Add(test); NodeType = "branch"; List succs = new List(test.Block.Successors); IfTarget = succs[0]; ElseTarget = succs[1]; } } private class SkipNode : Node { public Graph BranchGraph; public LeafNode Test; public SkipNode(LeafNode test, Graph gr) { Test = test; BranchGraph = gr; NodeType = "skip"; } } private class Graph { private Dictionary> m_OutgoingEdges = new Dictionary>(); private Dictionary> m_IncomingEdges = new Dictionary>(); public void AddNode(Node n) { m_OutgoingEdges.Add(n, new List()); m_IncomingEdges.Add(n, new List()); } public void AddNodes(IEnumerable nodes) { foreach (Node n in nodes) { m_OutgoingEdges.Add(n, new List()); m_IncomingEdges.Add(n, new List()); } } public void RemoveNodes(IEnumerable nodes) { foreach (Node n in nodes) { m_OutgoingEdges.Remove(n); m_IncomingEdges.Remove(n); } } public bool ContainsNode( Node n ) { return m_OutgoingEdges.ContainsKey(n); } public void AddEdge( Node from, Node to ) { m_OutgoingEdges[from].Add(to); m_IncomingEdges[to].Add(from); } public Dictionary Dominators( List nodes ) { Node[] objs = nodes.ToArray(); Node[][] preds = new Node[objs.Length][]; for (int i = 0; i < objs.Length; i++) preds[i] = m_IncomingEdges[objs[i]].ToArray(); return Algorithms.FindDominators(objs, preds); } public Dictionary PostDominators(List nodes) { Node[] objs = nodes.ToArray(); Node[][] preds = new Node[objs.Length][]; for (int i = 0; i < objs.Length; i++) preds[i] = m_OutgoingEdges[objs[i]].ToArray(); return Algorithms.FindDominators(objs, preds); } public void TransferEdgesToSubgraph( Graph g ) { foreach( Node n in g.Nodes ) { foreach (Node e in m_OutgoingEdges[n]) if( g.ContainsNode(e)) g.AddEdge(n, e); } } public void CombineNodes( IEnumerable loopNodes, Node superNode, Graph sub ) { // transfer nodes to subgraph foreach (Node b in loopNodes) sub.AddNode(b); // transfer edges to subgraph foreach( Node n in loopNodes ) foreach( Node e in m_OutgoingEdges[n] ) if (sub.ContainsNode(e)) sub.AddEdge(n, e); // add super-node to graph AddNode(superNode); // find edges from collapsing nodes to non-collapsing one // replace these with corresponding edges on the super-node foreach( Node n in loopNodes ) { foreach( Node s in m_OutgoingEdges[n]) { if (!sub.ContainsNode(s)) { m_IncomingEdges[s].Remove(n); AddEdge(superNode, s); } } } // remove the merged nodes from our graph foreach (Node n in loopNodes) { m_IncomingEdges.Remove(n); m_OutgoingEdges.Remove(n); } // find all nodes with an edge to a node that was just removed // re-point these edges at the super-node foreach( KeyValuePair> p in m_OutgoingEdges ) { List children = p.Value; for (int i = 0; i < children.Count; i++) { if (!m_OutgoingEdges.ContainsKey(children[i])) { children[i] = superNode; m_IncomingEdges[superNode].Add(p.Key); } } } } public IEnumerable ChildrenOf( Node n ) { return m_OutgoingEdges[n]; } public IEnumerable Nodes { get { return m_OutgoingEdges.Keys; } } public List ReversePostOrder() { List OrderedNodes = new List(); HashSet AddedNodes = new HashSet(); // collect source nodes List Frontier = new List(); foreach (KeyValuePair> p in m_IncomingEdges) if( p.Value.Count == 0 ) Frontier.Add(p.Key); do { // add frontier nodes to ordered list OrderedNodes.AddRange(Frontier); foreach( Node n in Frontier ) AddedNodes.Add(n); // search for new frontier nodes and add them to frontier list // a node goes on the frontier if it is not added but all // its predecessors are Frontier.Clear(); foreach( KeyValuePair> p in m_IncomingEdges ) { if (AddedNodes.Contains(p.Key)) continue; int i = 0; while( i < p.Value.Count ) { if (!AddedNodes.Contains(p.Value[i])) break; i++; } // node is ready to go into the frontier once all its predecessors have been ordered if (i == p.Value.Count ) Frontier.Add(p.Key); } } while( Frontier.Count > 0 ); return OrderedNodes; } }; private void BuildTree( TreeNode parent, Graph g) { List Nodes = g.ReversePostOrder(); for( int i=0; i Nodes = g.ReversePostOrder(); // Figure out dominance Dictionary IDOM = g.Dominators(Nodes); for( int i=0; i descendents = new List(g.ChildrenOf(Nodes[k])); Graph[] branchGraphs = new Graph[2]; branchGraphs[0] = br.IfGraph; branchGraphs[1] = br.ElseGraph; for (int k0 = k + 1; k0 < Nodes.Count; k0++) { Node n = Nodes[k0]; for (int j = 0; j < descendents.Count; j++) { if (Algorithms.Dominates(descendents[j], n, IDOM)) branchGraphs[j].AddNode(n); } } br.OwnedNodes.AddRange(branchGraphs[0].Nodes); br.OwnedNodes.AddRange(branchGraphs[1].Nodes); Graph branchGraph = new Graph(); g.CombineNodes(br.OwnedNodes, br, branchGraph); branchGraph.TransferEdgesToSubgraph(branchGraphs[0]); branchGraph.TransferEdgesToSubgraph(branchGraphs[1]); // do this recursively on the if/else branches BuildBranchNodes(br.IfGraph); BuildBranchNodes(br.ElseGraph); // start over k = 0; Nodes = g.ReversePostOrder(); } else if (Nodes[k] is LeafNode && Nodes[k].NodeType.Equals("skip")) { Dictionary PDOM = g.PostDominators(Nodes); // find nodes to put into the sub-graph // these are all the nodes which are skipped // nodes are skipped if they are post-dominated by the convergence node (which post-dominates the test) Node joinPoint = PDOM[Nodes[k]]; Graph branchGraph = new Graph(); for (int k0 = k + 1; Nodes[k0] != joinPoint; k0++) { Node n = Nodes[k0]; if (Algorithms.Dominates(joinPoint, Nodes[k0], PDOM)) branchGraph.AddNode(Nodes[k0]); } SkipNode sk = new SkipNode((Nodes[k] as LeafNode), branchGraph); // now make a graph containing both test node and all skipped nodes // combine these into one skip node List ownedNodes = new List(branchGraph.Nodes); ownedNodes.Add(Nodes[k]); Graph tmpGraph = new Graph(); g.CombineNodes(ownedNodes, sk, tmpGraph); tmpGraph.TransferEdgesToSubgraph(branchGraph); // do this recursively on the skipped nodes BuildBranchNodes(sk.BranchGraph); // start over k = 0; Nodes = g.ReversePostOrder(); } else { k++; } } } public void SetProgram(List loops, List blocks) { // build DAG of basic blocks // excluding backedges Graph g = new Graph(); Dictionary NodeMap = new Dictionary(); foreach (BasicBlock b in blocks) { Node n = new LeafNode(b); g.AddNode(n); NodeMap.Add(b,n); } foreach (BasicBlock b in blocks) foreach (BasicBlock s in b.Successors) if (!s.Dominates(b)) g.AddEdge(NodeMap[b], NodeMap[s]); // walk over loops inner to outer // for each loop, replace its contents with a single "super-node" foreach( Loop l in loops ) { HashSet loopNodes = new HashSet(); foreach (BasicBlock b in l.Blocks ) loopNodes.Add(NodeMap[b]); LoopNode superNode = new LoopNode(new Graph(), l); g.CombineNodes(loopNodes,superNode,superNode.SubGraph ); // all blocks in the loop should now be represented by the super-node foreach (BasicBlock b in l.Blocks) NodeMap[b] = superNode; } BuildBranchNodes(g); // now populate the tree view with loops and branches TreeNode root = new TreeNode("program"); BuildTree(root, g); treeView1.Nodes.Add(root); } public delegate void SelectionClearedHandler(object sender); public delegate void BlockSelectedHandler(object sender, BasicBlock bl ); public delegate void LoopSelectionHandler(object sender, Loop SelectedLoop); public delegate void BranchSelectedHandler(object sender, BasicBlock BranchBlock, IBranchInstruction branch); public delegate void BranchTargetSelectedHandler(object sender, BasicBlock TargetBlock ); public event BlockSelectedHandler BlockSelected; public event LoopSelectionHandler LoopSelected; public event BranchSelectedHandler BranchSelected; public event BranchTargetSelectedHandler BranchTargetSelected; public event SelectionClearedHandler SelectionCleared; public Loop SelectedLoop { get; private set; } public IBranchInstruction SelectedBranch { get; private set; } public BasicBlock SelectedBlock { get; private set; } private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { this.SelectedLoop = null; this.SelectedBranch = null; this.SelectedBlock = null; if (treeView1.SelectedNode == null) { if (SelectionCleared != null) { SelectionCleared(this); return; } } object tag = treeView1.SelectedNode.Tag; if (tag == null) { if (SelectionCleared != null) { SelectionCleared(this); return; } } Node n = tag as Node; if ( n is LoopNode ) { Loop l = (n as LoopNode).m_Loop; SelectedLoop = l; if (LoopSelected != null) LoopSelected(this, l); } else if( n is BranchNode ) { BranchNode br = n as BranchNode; BasicBlock bl = (br.Test as LeafNode).Block; SelectedBranch = bl.LastInstruction as IBranchInstruction; SelectedBlock = bl; if( BranchSelected != null ) BranchSelected(this, bl, SelectedBranch); } else if( n is SkipNode ) { SkipNode sk = n as SkipNode; BasicBlock bl = (sk.Test as LeafNode).Block; SelectedBranch = bl.LastInstruction as IBranchInstruction; SelectedBlock = bl; if (BranchSelected != null) BranchSelected(this, bl, SelectedBranch); } else if( n is LeafNode ) { SelectedBlock = (n as LeafNode).Block; if( BlockSelected != null ) BlockSelected(this, SelectedBlock); } else if (tag is BasicBlock) { SelectedBlock = tag as BasicBlock; if (BranchTargetSelected != null ) BranchTargetSelected(this, SelectedBlock); } } private void treeView1_Leave(object sender, EventArgs e) { treeView1.SelectedNode = null; } } } ================================================ FILE: src/Scrutinizer/UI/CFGWidget.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Scrutinizer/UI/InstructionWidget.Designer.cs ================================================ namespace Pyramid.Scrutinizer.UI { partial class InstructionWidget { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.SuspendLayout(); // // InstructionWidget // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Name = "InstructionWidget"; this.Size = new System.Drawing.Size(738, 20); this.Paint += new System.Windows.Forms.PaintEventHandler(this.InstructionWidget_Paint); this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.InstructionWidget_MouseDown); this.ResumeLayout(false); } #endregion } } ================================================ FILE: src/Scrutinizer/UI/InstructionWidget.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid.Scrutinizer.UI { public partial class InstructionWidget : UserControl { private IInstruction m_Op; private ComboBox m_FilterBox; private ComboBox m_FormatBox; private Font m_ItalicFont; public delegate void TexelFormatChangedHandler( ITextureInstruction op ); public delegate void FilterChangedHandler( ISamplingInstruction op ); public event TexelFormatChangedHandler TexelFormatChanged; public event FilterChangedHandler FilterChanged; private ComboBox CreateFilterBox( IInstruction op ) { ComboBox cb = new ComboBox(); foreach (string s in Enum.GetNames(typeof(Scrutinizer.TextureFilter))) cb.Items.Add(s); cb.Width = 96; cb.SelectedIndex = (int)(op as ISamplingInstruction).Filter; cb.DropDownStyle = ComboBoxStyle.DropDownList; cb.SelectedIndexChanged += delegate(object s, EventArgs e) { if (op is ISamplingInstruction) { ISamplingInstruction samp = op as ISamplingInstruction; samp.Filter = (TextureFilter)cb.SelectedIndex; if (this.FilterChanged != null ) this.FilterChanged(samp); } }; return cb; } private ComboBox CreateFormatBox( IInstruction op ) { ComboBox cb = new ComboBox(); foreach (string s in Enum.GetNames(typeof(Scrutinizer.TexelFormat))) cb.Items.Add(s); cb.Width = 80; cb.SelectedIndex = (int)(op as ITextureInstruction).Format; cb.DropDownStyle = ComboBoxStyle.DropDownList; cb.SelectedIndexChanged += delegate(object s, EventArgs e) { if (op is ITextureInstruction) { ITextureInstruction samp = op as ITextureInstruction; samp.Format = (TexelFormat)cb.SelectedIndex; if( this.TexelFormatChanged != null ) this.TexelFormatChanged(samp); } }; return cb; } public InstructionWidget( IInstruction op ) { InitializeComponent(); this.Font = new Font("Lucida Console", 8.25f); m_ItalicFont = new Font(this.Font, FontStyle.Italic); this.Height = 15; this.Executed = true; m_Op = op; Selected = false; if (op is Scrutinizer.ISamplingInstruction) { Panel panel = new Panel(); m_FilterBox = CreateFilterBox(op); m_FormatBox = CreateFormatBox(op); panel.Anchor = AnchorStyles.Right; panel.Width = m_FilterBox.Width + m_FormatBox.Width; m_FilterBox.Left = m_FormatBox.Width; panel.Controls.Add(m_FilterBox); panel.Controls.Add(m_FormatBox); this.Controls.Add(panel); } else if (op is Scrutinizer.ITextureInstruction) { m_FormatBox = CreateFormatBox(op); m_FormatBox.Anchor = AnchorStyles.Right; this.Controls.Add(m_FormatBox); } } public IInstruction Instruction { get { return m_Op; } } public bool Selected { get; set; } public bool Executed { get; set; } public void RefreshInstruction() { if( m_FilterBox != null ) m_FilterBox.SelectedIndex = (int) (m_Op as ISamplingInstruction).Filter; if (m_FormatBox != null) m_FormatBox.SelectedIndex = (int) (m_Op as ITextureInstruction).Format; } private void InstructionWidget_Paint(object sender, PaintEventArgs e) { if (m_Op == null) return; if( Selected ) { e.Graphics.FillRectangle(SystemBrushes.HighlightText, new Rectangle(0, 0, this.Width, this.Height)); } Brush br = SystemBrushes.ControlText; if (!Executed) br = SystemBrushes.InactiveCaption; Font f = this.Font; if (!Executed) f = m_ItalicFont; e.Graphics.DrawString(m_Op.Disassemble(), f, br, new PointF(80+96, 0)); if( !String.IsNullOrEmpty(m_Op.SimNotes) ) e.Graphics.DrawString(m_Op.SimNotes, this.Font, SystemBrushes.ControlText, new PointF(this.Width - 200, 0)); } private void InstructionWidget_MouseDown(object sender, MouseEventArgs e) { this.Parent.Focus(); } } } ================================================ FILE: src/Scrutinizer/UI/InstructionWidget.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/Scrutinizer/UI/ParameterWidget.Designer.cs ================================================ namespace Pyramid.Scrutinizer.UI { partial class ParameterWidget { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { components = new System.ComponentModel.Container(); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; } #endregion } } ================================================ FILE: src/Scrutinizer/UI/ParameterWidget.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid.Scrutinizer.UI { public partial class ParameterWidget : UserControl { const int TEXTBOX_WIDTH = 40; const int LAYOUT_PAD = 4; private List m_Parameters = new List(); public ParameterWidget() { InitializeComponent(); } interface IParameterGUI { bool Assign(); IEnumerable Controls { get; } }; class ParameterGUI_Int : IParameterGUI { private List m_Controls = new List(); private TextBox m_Box; private SimulationParameterInt m_Param; public IEnumerable Controls { get { return m_Controls; } } public ParameterGUI_Int(SimulationParameterInt p) { TextBox box = new TextBox(); box.Width = TEXTBOX_WIDTH; box.Text = Convert.ToString(p.Default); box.Top = 0; box.Left = LAYOUT_PAD; Label l = new Label(); l.AutoSize = true; l.Text = p.Name; l.TextAlign = ContentAlignment.MiddleLeft; l.Top = (box.Height/2) - (l.Height / 2); l.Left = box.Right + LAYOUT_PAD; m_Controls.Add(l); m_Controls.Add(box); m_Box = box; m_Param = p; } public bool Assign( ) { try { int n = Convert.ToInt32(m_Box.Text); if( n < m_Param.Min || n > m_Param.Max ) { MessageBox.Show( String.Format( "{0} must be between {1} and {2}", m_Param.Name, m_Param.Min, m_Param.Max ) ); m_Box.Focus(); return false; } m_Param.Value = n; } catch( System.Exception e ) { MessageBox.Show(e.Message); m_Box.Focus(); return false; } return true; } } class ParameterGUI_Double : IParameterGUI { private List m_Controls = new List(); private TextBox m_Box; private SimulationParameterDouble m_Param; public IEnumerable Controls { get { return m_Controls; } } public ParameterGUI_Double( SimulationParameterDouble p) { TextBox box = new TextBox(); box.Width = TEXTBOX_WIDTH; box.Text = Convert.ToString(p.Default); box.Top = 0; box.Left = LAYOUT_PAD; Label l = new Label(); l.AutoSize = true; l.Text = p.Name; l.TextAlign = ContentAlignment.MiddleLeft; l.Top = (box.Height / 2) - (l.Height / 2); l.Left = box.Right + LAYOUT_PAD; m_Controls.Add(l); m_Controls.Add(box); m_Box = box; m_Param = p; } public bool Assign() { try { double n = Convert.ToDouble(m_Box.Text); if (n < m_Param.Min || n > m_Param.Max) { MessageBox.Show( String.Format("{0} must be between {1] and {2}", m_Param.Name, m_Param.Min, m_Param.Max)); m_Box.Focus(); return false; } m_Param.Value = n; } catch (System.Exception e) { MessageBox.Show(e.Message); m_Box.Focus(); return false; } return true; } } /// /// Called to transfer values from UI to the parameters /// /// public bool UpdateParameters( ) { foreach( IParameterGUI gui in m_Parameters ) { if (!gui.Assign()) return false; } return true; } public void BuildUI( IEnumerable ParamSet ) { m_Parameters.Clear(); foreach( Scrutinizer.ISimulationParameter p in ParamSet ) { if( p is Scrutinizer.SimulationParameterInt ) { m_Parameters.Add(new ParameterGUI_Int(p as SimulationParameterInt)); } if( p is Scrutinizer.SimulationParameterDouble ) { m_Parameters.Add(new ParameterGUI_Double(p as SimulationParameterDouble)); } } // lay out the controls int Y = LAYOUT_PAD; foreach( IParameterGUI gui in m_Parameters ) { int h = 0; foreach (Control c in gui.Controls) { this.Controls.Add(c); c.Top = c.Top + Y; h = Math.Max(h, c.Height); } Y += h + LAYOUT_PAD; } this.Refresh(); } } } ================================================ FILE: src/Scrutinizer/UI/ScrutinizerForm.Designer.cs ================================================ namespace Pyramid.Scrutinizer.UI { partial class ScrutinizerForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.panel1 = new System.Windows.Forms.Panel(); this.lblIterations = new System.Windows.Forms.Label(); this.txtLoopCount = new System.Windows.Forms.TextBox(); this.btnSimulate = new System.Windows.Forms.Button(); this.chkTaken = new System.Windows.Forms.CheckBox(); this.parameterWidget1 = new Scrutinizer.UI.ParameterWidget(); this.cfgWidget1 = new Scrutinizer.UI.CFGWidget(); this.SuspendLayout(); // // panel1 // this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.panel1.AutoScroll = true; this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.panel1.Location = new System.Drawing.Point(13, 13); this.panel1.Name = "panel1"; this.panel1.Size = new System.Drawing.Size(561, 460); this.panel1.TabIndex = 2; this.panel1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseDown); // // lblIterations // this.lblIterations.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.lblIterations.AutoSize = true; this.lblIterations.Location = new System.Drawing.Point(676, 268); this.lblIterations.Name = "lblIterations"; this.lblIterations.Size = new System.Drawing.Size(50, 13); this.lblIterations.TabIndex = 4; this.lblIterations.Text = "Iterations"; // // txtLoopCount // this.txtLoopCount.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.txtLoopCount.Location = new System.Drawing.Point(728, 265); this.txtLoopCount.Name = "txtLoopCount"; this.txtLoopCount.Size = new System.Drawing.Size(100, 20); this.txtLoopCount.TabIndex = 3; this.txtLoopCount.WordWrap = false; this.txtLoopCount.TextChanged += new System.EventHandler(this.txtLoopCount_TextChanged); // // btnSimulate // this.btnSimulate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnSimulate.Location = new System.Drawing.Point(766, 291); this.btnSimulate.Name = "btnSimulate"; this.btnSimulate.Size = new System.Drawing.Size(62, 21); this.btnSimulate.TabIndex = 5; this.btnSimulate.Text = "Simulate"; this.btnSimulate.UseVisualStyleBackColor = true; this.btnSimulate.Click += new System.EventHandler(this.btnSimulate_Click); // // chkTaken // this.chkTaken.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.chkTaken.AutoSize = true; this.chkTaken.Location = new System.Drawing.Point(590, 266); this.chkTaken.Name = "chkTaken"; this.chkTaken.Size = new System.Drawing.Size(57, 17); this.chkTaken.TabIndex = 14; this.chkTaken.Text = "Taken"; this.chkTaken.UseVisualStyleBackColor = true; this.chkTaken.Visible = false; this.chkTaken.CheckedChanged += new System.EventHandler(this.chkTaken_CheckedChanged); // // parameterWidget1 // this.parameterWidget1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Right))); this.parameterWidget1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.parameterWidget1.Location = new System.Drawing.Point(590, 332); this.parameterWidget1.Name = "parameterWidget1"; this.parameterWidget1.Size = new System.Drawing.Size(238, 150); this.parameterWidget1.TabIndex = 15; // // cfgWidget1 // this.cfgWidget1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.cfgWidget1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.cfgWidget1.Location = new System.Drawing.Point(580, 12); this.cfgWidget1.Name = "cfgWidget1"; this.cfgWidget1.Size = new System.Drawing.Size(248, 247); this.cfgWidget1.TabIndex = 1; this.cfgWidget1.BlockSelected += new Scrutinizer.UI.CFGWidget.BlockSelectedHandler(this.cfgWidget1_BlockSelected); this.cfgWidget1.LoopSelected += new Scrutinizer.UI.CFGWidget.LoopSelectionHandler(this.cfgWidget1_LoopSelected); this.cfgWidget1.BranchSelected += new Scrutinizer.UI.CFGWidget.BranchSelectedHandler(this.cfgWidget1_BranchSelected); this.cfgWidget1.BranchTargetSelected += new Scrutinizer.UI.CFGWidget.BranchTargetSelectedHandler(this.cfgWidget1_BranchTargetSelected); this.cfgWidget1.SelectionCleared += new Scrutinizer.UI.CFGWidget.SelectionClearedHandler(this.cfgWidget1_SelectionCleared); // // ScrutinizerForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(840, 494); this.Controls.Add(this.parameterWidget1); this.Controls.Add(this.chkTaken); this.Controls.Add(this.btnSimulate); this.Controls.Add(this.lblIterations); this.Controls.Add(this.txtLoopCount); this.Controls.Add(this.panel1); this.Controls.Add(this.cfgWidget1); this.Name = "ScrutinizerForm"; this.Text = "Scrutinizer"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private CFGWidget cfgWidget1; private System.Windows.Forms.Panel panel1; private System.Windows.Forms.Label lblIterations; private System.Windows.Forms.TextBox txtLoopCount; private System.Windows.Forms.Button btnSimulate; private System.Windows.Forms.CheckBox chkTaken; private ParameterWidget parameterWidget1; } } ================================================ FILE: src/Scrutinizer/UI/ScrutinizerForm.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace Pyramid.Scrutinizer.UI { public partial class ScrutinizerForm : Form { private List m_FetchShader; private List m_Ops; private List m_Blocks; private List m_Loops; private IScrutinizer m_Backend; private HashSet m_TakenBranches = new HashSet(); private HashSet m_SelectedOps = new HashSet(); private InstructionWidget m_LastClicked = null; private Dictionary m_InstructionWidgets = new Dictionary(); private Dictionary m_InstructionIndexMap = new Dictionary(); private void ClearSelectedInstructions() { // de-select everything on a right click foreach (InstructionWidget i in m_SelectedOps) { i.Selected = false; i.Refresh(); } m_SelectedOps.Clear(); } private void SelectInstruction( IInstruction op ) { InstructionWidget widget = m_InstructionWidgets[op]; m_SelectedOps.Add(widget); widget.Selected = true; widget.Refresh(); } private void OnInstructionClick( InstructionWidget w, MouseEventArgs e ) { if (e.Button == MouseButtons.Left) { if (Form.ModifierKeys == Keys.Control) { // ctrl+click: toggle state of one widget w.Selected = !w.Selected; w.Refresh(); if (w.Selected) m_SelectedOps.Add(w); else m_SelectedOps.Remove(w); } else if( Form.ModifierKeys == Keys.Shift && m_LastClicked != null ) { // shift+click: select everything between last clicked widget // and current widget int i = m_InstructionIndexMap[m_LastClicked.Instruction]; int j = m_InstructionIndexMap[w.Instruction]; int first = Math.Min(i, j); int last = Math.Max(i, j); for (int x = first; x <= last; x++) SelectInstruction(m_Ops[x]); } else { // unmodified click. Select only the clicked widget ClearSelectedInstructions(); SelectInstruction(w.Instruction); } m_LastClicked = w; } else if (e.Button == MouseButtons.Right) { // de-select everything on a right click ClearSelectedInstructions(); } } public void AddInstructionToPanel( InstructionWidget widget, IInstruction op ) { m_InstructionIndexMap.Add(op, m_InstructionWidgets.Count); m_InstructionWidgets.Add(op, widget); widget.Click += delegate(object s, EventArgs e) { this.OnInstructionClick(widget, e as MouseEventArgs); }; // change format on all selected instructions whenever one of them is changed widget.TexelFormatChanged += delegate(ITextureInstruction inst ) { if (!widget.Selected) return; foreach( InstructionWidget s in m_SelectedOps ) { ITextureInstruction tx = s.Instruction as ITextureInstruction; if( tx != null && tx != inst ) tx.Format = inst.Format; s.RefreshInstruction(); } }; // change filter on all selected instructions whenever one of them is changed widget.FilterChanged += delegate(ISamplingInstruction inst) { if (!widget.Selected) return; foreach (InstructionWidget s in m_SelectedOps) { ISamplingInstruction tx = s.Instruction as ISamplingInstruction; if (tx != null && tx != inst) tx.Filter = inst.Filter; s.RefreshInstruction(); } }; panel1.Controls.Add(widget); } public ScrutinizerForm( List FetchShader, List Shader, IScrutinizer backend ) { InitializeComponent(); m_Backend = backend; m_FetchShader = FetchShader; m_Ops = Shader; try { Wrapper w = new Wrapper(); List Ops = m_Backend.BuildProgram(); m_Ops = Ops; m_Blocks = Algorithms.BuildBasicBlocks(Ops); if (!Algorithms.IsCFGReducible(m_Blocks)) { MessageBox.Show("Non-reducible flow-graph detected. Can't analyze this."); return; } Algorithms.FindDominators(m_Blocks); m_Loops = Algorithms.FindLoops(m_Blocks); Algorithms.ClassifyBranches(m_Ops); Algorithms.AssignLabels(m_Ops); int Y = 0; if( m_FetchShader.Count > 0 ) { Label l0 = new Label(); Label l1 = new Label(); l0.AutoSize = true; l1.AutoSize = true; l0.Text = "*** INSTRUCTIONS BELOW ARE AN APPROXIMATION TO THE FETCH SHADER***"; l1.Text = "******************************************************************"; l0.Left = 128; l1.Left = 128; panel1.Controls.Add(l0); Y = l0.Height; foreach( IInstruction op in m_FetchShader ) { InstructionWidget widget = new InstructionWidget(op); AddInstructionToPanel(widget, op); widget.Top = Y; widget.Left = 0; Y += widget.Height; } l1.Top = Y; panel1.Controls.Add(l1); Y += l1.Height; } foreach (BasicBlock b in m_Blocks) { foreach (IInstruction op in b.Instructions) { if( !String.IsNullOrEmpty(op.Label)) { Label l = new Label(); l.Font = new Font("Lucida Console", 8); l.AutoSize = true; l.Text = op.Label; l.Left = 100; l.Top = Y; panel1.Controls.Add(l); Y += l.Height; } InstructionWidget widget = new InstructionWidget(op); AddInstructionToPanel(widget, op); widget.Top = Y; widget.Left = 0; Y += widget.Height; } Y += 15; } cfgWidget1.SetProgram(m_Loops, m_Blocks); parameterWidget1.BuildUI(m_Backend.SimulationParameters); MarkExecutedInstructions(); } catch( System.Exception ex ) { MessageBox.Show(ex.Message); } } private void SelectDominatedInstructions( BasicBlock dominator ) { foreach( BasicBlock b in m_Blocks ) if (dominator.Dominates(b) ) foreach (IInstruction op in b.Instructions) SelectInstruction(op); } private void cfgWidget1_BlockSelected(object sender, BasicBlock SelectedBlock) { ClearSelectedInstructions(); foreach (IInstruction i in SelectedBlock.Instructions) SelectInstruction(i); panel1.Refresh(); txtLoopCount.Visible = false; lblIterations.Visible = false; chkTaken.Visible = false; } private void cfgWidget1_BranchTargetSelected(object sender, BasicBlock TargetBlock) { ClearSelectedInstructions(); foreach (BasicBlock b in m_Blocks) if (TargetBlock.Dominates(b)) foreach (IInstruction i in b.Instructions) SelectInstruction(i); panel1.Refresh(); txtLoopCount.Visible = false; lblIterations.Visible = false; chkTaken.Visible = false; } private void cfgWidget1_LoopSelected(object sender, Loop SelectedLoop) { ClearSelectedInstructions(); foreach (BasicBlock SelectedBlock in SelectedLoop.Blocks) foreach (IInstruction i in SelectedBlock.Instructions) SelectInstruction(i); lblIterations.Visible = true; txtLoopCount.Visible = true; chkTaken.Visible = false; txtLoopCount.Text = SelectedLoop.DesiredIterations.ToString(); } private void cfgWidget1_SelectionCleared(object sender) { ClearSelectedInstructions(); panel1.Refresh(); txtLoopCount.Visible = false; lblIterations.Visible = false; chkTaken.Visible = false; } private void cfgWidget1_BranchSelected(object sender, BasicBlock BranchBlock, IBranchInstruction branch) { ClearSelectedInstructions(); foreach (IInstruction i in BranchBlock.Instructions) SelectInstruction(i); IBranchInstruction br = BranchBlock.LastInstruction as IBranchInstruction; if( br.IfTarget.Block != br.Block.PostDominator ) SelectDominatedInstructions(br.IfTarget.Block); if (br.ElseTarget.Block != br.Block.PostDominator) SelectDominatedInstructions(br.ElseTarget.Block); txtLoopCount.Visible = false; lblIterations.Visible = false; chkTaken.Visible = true; chkTaken.Checked = m_TakenBranches.Contains(branch); } private void panel1_MouseDown(object sender, MouseEventArgs e) { panel1.Focus(); } private void MarkExecutedInstructions() { List ops = Algorithms.DoTrace(m_Ops, m_Blocks, m_Loops, m_TakenBranches); HashSet distinctOps = new HashSet(); foreach (IInstruction op in ops) distinctOps.Add(op); foreach( InstructionWidget w in m_InstructionWidgets.Values ) w.Executed = false; foreach (IInstruction op in distinctOps) m_InstructionWidgets[op].Executed = true; } private void txtLoopCount_TextChanged(object sender, EventArgs e) { int n = 0; try { n = Convert.ToInt32(txtLoopCount.Text); cfgWidget1.SelectedLoop.DesiredIterations = n; MarkExecutedInstructions(); } catch(System.Exception ) { } } private void btnSimulate_Click(object sender, EventArgs e) { if (m_FetchShader != null) { foreach (IInstruction op in m_FetchShader) op.SimNotes = ""; } foreach (IInstruction op in m_Ops) op.SimNotes = ""; try { if (parameterWidget1.UpdateParameters()) { List trace = new List(); if (m_FetchShader != null) trace.AddRange(m_FetchShader); trace.AddRange(Algorithms.DoTrace(m_Ops, m_Blocks, m_Loops, m_TakenBranches)); string sim = m_Backend.AnalyzeExecutionTrace(trace); MessageBox.Show(sim); panel1.Refresh(); } } catch( System.Exception ex ) { MessageBox.Show(ex.Message); } } private void chkTaken_CheckedChanged(object sender, EventArgs e) { if (m_TakenBranches.Contains(cfgWidget1.SelectedBranch)) m_TakenBranches.Remove(cfgWidget1.SelectedBranch); else m_TakenBranches.Add(cfgWidget1.SelectedBranch); MarkExecutedInstructions(); panel1.Refresh(); } } } ================================================ FILE: src/Scrutinizer/UI/ScrutinizerForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/ScrutinizerTypes.cs ================================================ using System.Collections.Generic; namespace Pyramid.Scrutinizer { public enum BranchCategory { FORK_BRANCH, /// Branch for which both targets are nested in same loop as current block CONTINUE_BRANCH, /// Fork branch where one target is loop's header SKIP_BRANCH, /// Fork branch where one target is the post-dominator of the loop LOOPSKIP_BRANCH, /// A skip branch which jumps around a complete loop BREAK_BRANCH, /// Not a fork branch }; public class BasicBlock { public IEnumerable Instructions { get { return m_Instructions; } } public IEnumerable Predecessors { get { return m_Predecessors; } } public IEnumerable Successors { get { return m_Successors; } } public int SuccessorCount { get { return m_Successors.Count; } } public IInstruction LastInstruction { get { return m_Instructions[m_Instructions.Count - 1]; } } public BasicBlock PostDominator { get; set; } public BasicBlock ImmediateDominator { get; set; } public Loop InnerMostLoop { get; set; } public void AddSuccessor(BasicBlock bl) { m_Successors.Add(bl); } public void AddPredecessor(BasicBlock bl) { m_Predecessors.Add(bl); } public void AddInstruction(IInstruction i) { m_Instructions.Add(i); } private List m_Instructions = new List(); private List m_Predecessors = new List(); private List m_Successors = new List(); public bool Dominates( BasicBlock b ) { if (b == this) return true; BasicBlock dom = b.ImmediateDominator; while( dom != null ) { if (dom == this) return true; dom = dom.ImmediateDominator; } return false; } }; public class Loop { private List m_Blocks; private BasicBlock m_Header; public Loop( BasicBlock header, IEnumerable blocks ) { m_Header = header; m_Blocks = new List(blocks); Parent = null; DesiredIterations = 1; } public int DesiredIterations { get; set; } public IEnumerable Blocks { get { return m_Blocks; } } public BasicBlock Header { get { return m_Header; } } public Loop Parent { get; set; } public int BlockCount { get { return m_Blocks.Count; } } public bool IsNestedIn( Loop p ) { Loop n = this; while (n != null) { if (n == p) return true; n = n.Parent; } return false; } } public interface IInstruction { BasicBlock Block { get; set; } string Label { get; set; } string SimNotes { get; set; } // String field used to display simulation results string Disassemble(); }; public interface IBranchInstruction : IInstruction { BranchCategory Category { get; set; } IInstruction IfTarget { get; } IInstruction ElseTarget { get; } }; public interface IJumpInstruction : IInstruction { IInstruction Target { get; } }; public enum TexelFormat { R8, RG8, RGBA8, R16, RG16, RGBA16, R16F, RG16F, RGBA16F, R32F, RG32F, RGBA32F, BC1, BC2, BC3, BC4, BC5, BC6, BC7 }; public enum TextureFilter { POINT, BILINEAR, TRILINEAR, ANISO_2X, ANISO_4X, ANISO_8X }; /// /// Interface for instructions which can be annoted with a texture format /// public interface ITextureInstruction : IInstruction { TexelFormat Format { get; set; } }; /// /// Interface for instructions which can be annoted with a texture format /// or a filtering mode /// public interface ISamplingInstruction : ITextureInstruction { TextureFilter Filter { get; set; } }; public interface ISimulationParameter { string Name { get; } }; public class SimulationParameterInt : ISimulationParameter { public SimulationParameterInt( int nMin, int nMax, int nDefault, string sName ) { Min = nMin; Max = nMax; Default = nDefault; Value = Default; Name = sName; } public string Name { get; private set; } public int Min { get; private set; } public int Max { get; private set; } public int Default { get; private set; } public int Value { get; set; } }; public class SimulationParameterDouble : ISimulationParameter { public SimulationParameterDouble(double fMin, double fMax, double fDefault, string sName ) { Min = fMin; Max = fMax; Default = fDefault; Value = Default; Name = sName; } public string Name { get; private set; } public double Min { get; private set; } public double Max { get; private set; } public double Default { get; private set; } public double Value { get; set; } }; public interface IScrutinizer { List BuildProgram( ); List BuildDXFetchShader(IDXShaderReflection refl); IEnumerable SimulationParameters { get; } string AnalyzeExecutionTrace(List ops); }; } ================================================ FILE: src/Wrapper/AMDAsic_Impl.cpp ================================================ #include "AMDAsic_Impl.h" #include "Utilities.h" #include "amd-codexl-analyzer/Common/Src/DeviceInfo/DeviceInfoUtils.h" #include "AMDTBackend/Include/Common/asic_reg/atiid.h" #include "AMDTBackend/Include/Common/asic_reg/si_id.h" #include "AMDTBackend/Include/Common/asic_reg/ci_id.h" #include "AMDTBackend/Include/Common/asic_reg/vi_id.h" #include "AMDTBackend/Include/Common/asic_reg/cz_id.h" #include "AMDTBackend/Include/Common/asic_reg/kv_id.h" static void GetDeviceChipFamilyRevision( GDT_HW_ASIC_TYPE type, unsigned int& chipFamily, unsigned int& chipRevision) { chipFamily = (unsigned int) - 1; chipRevision = (unsigned int) - 1; switch (type) { default: // The 600's EG, and NI are no longer supported by OpenCL. // For GSA the earliest DX/GL support is SI. break; case GDT_TAHITI_PRO: case GDT_TAHITI_XT: chipFamily = FAMILY_SI; chipRevision = SI_TAHITI_P_B1; break; case GDT_PITCAIRN_PRO: case GDT_PITCAIRN_XT: chipFamily = FAMILY_SI; chipRevision = SI_PITCAIRN_PM_A1; break; case GDT_CAPEVERDE_PRO: case GDT_CAPEVERDE_XT: chipFamily = FAMILY_SI; chipRevision = SI_CAPEVERDE_M_A1; break; case GDT_OLAND: chipFamily = FAMILY_SI; chipRevision = SI_OLAND_M_A0; break; case GDT_HAINAN: chipFamily = FAMILY_SI; chipRevision = SI_HAINAN_V_A0; break; case GDT_BONAIRE: chipFamily = FAMILY_CI; chipRevision = CI_BONAIRE_M_A0; break; case GDT_HAWAII: chipFamily = FAMILY_CI; chipRevision = CI_HAWAII_P_A0; break; case GDT_KALINDI: chipFamily = FAMILY_CI; chipRevision = CI_BONAIRE_M_A0; break; case GDT_SPECTRE: case GDT_SPECTRE_SL: case GDT_SPECTRE_LITE: chipFamily = FAMILY_CI; chipRevision = KV_SPECTRE_A0; break; case GDT_SPOOKY: chipFamily = FAMILY_CI; chipRevision = KV_SPOOKY_A0; break; case GDT_ICELAND: chipFamily = FAMILY_VI; chipRevision = VI_ICELAND_M_A0; break; case GDT_TONGA: chipFamily = FAMILY_VI; chipRevision = VI_TONGA_P_A0; break; case GDT_CARRIZO: chipFamily = FAMILY_VI; chipRevision = CARRIZO_A0; break; case GDT_FIJI: chipFamily = FAMILY_VI; chipRevision = VI_FIJI_P_A0; break; } } AMDAsic_Impl::AMDAsic_Impl( const GDT_GfxCardInfo& rCard ) : m_pmName( MakeString(rCard.m_szCALName) ) { unsigned int nChipFamily; unsigned int nChipRevision; GetDeviceChipFamilyRevision(rCard.m_asicType, nChipFamily, nChipRevision); switch( rCard.m_generation ) { case GDT_HW_GENERATION_SOUTHERNISLAND: case GDT_HW_GENERATION_SEAISLAND: m_pDecoder = GCN::IDecoder::Create(GCN::IDecoder::GCN1); break; case GDT_HW_GENERATION_VOLCANICISLAND: m_pDecoder = GCN::IDecoder::Create(GCN::IDecoder::GCN3); break; } m_nChipFamily = nChipFamily; m_nChipRevision = nChipRevision; } AMDAsic_Impl::~AMDAsic_Impl() { GCN::IDecoder::Destroy(m_pDecoder); m_pDecoder=0; } ================================================ FILE: src/Wrapper/AMDAsic_Impl.h ================================================ #pragma unmanaged #include "GCNDecoder.h" #pragma managed struct GDT_GfxCardInfo; private ref class AMDAsic_Impl : Pyramid::IAMDAsic { public: AMDAsic_Impl( const GDT_GfxCardInfo& rCardInfo ); ~AMDAsic_Impl(); property System::String^ Name { virtual System::String^ get() { return m_pmName; } } internal: System::String^ m_pmName; GCN::IDecoder* m_pDecoder; unsigned int m_nChipFamily; unsigned int m_nChipRevision; }; ================================================ FILE: src/Wrapper/AMDDriver_Impl.cpp ================================================ #pragma unmanaged #include #include #include "elf.h" #include "GCNDisassembler.h" #include "GCNDecoder.h" #include "GCNBufferedPrinter.h" #pragma managed #include "AMDDriver_Impl.h" #include "AMDAsic_Impl.h" #include "AMDShader_Impl.h" #include "Utilities.h" #undef DOMAIN // seriously Microsoft?!?!? #include "amd-codexl-analyzer/Common/Src/DeviceInfo/DeviceInfoUtils.h" static bool GfxCardInfoSortPredicate(const GDT_GfxCardInfo& a, const GDT_GfxCardInfo& b) { // Generation is the primary key. if (a.m_generation < b.m_generation) { return true; } if (a.m_generation > b.m_generation) { return false; } // CAL name is next. int ret = ::strcmp(a.m_szCALName, b.m_szCALName); if (ret < 0) { return true; } if (ret > 0) { return false; } // Marketing name next. ret = ::strcmp(a.m_szMarketingName, b.m_szMarketingName); if (ret < 0) { return true; } if (ret > 0) { return false; } // DeviceID last. return a.m_deviceID < b.m_deviceID; } AMDDriver_Impl::AMDDriver_Impl( System::String^ path ) { MarshalledString sPath(path); HMODULE hAMDDriver = LoadLibraryA( sPath ); if( !hAMDDriver ) throw gcnew System::Exception( System::String::Format( "AMD driver dll not found at {0}", path )); FARPROC pCompile = GetProcAddress( hAMDDriver, "AmdDxGsaCompileShader" ); FARPROC pFree = GetProcAddress( hAMDDriver, "AmdDxGsaFreeCompiledShader" ); if( !pCompile || !pFree ) { FreeLibrary(hAMDDriver); throw gcnew System::Exception( System::String::Format( "GSA entrypoints not found in {0}", path )); } m_pCompileFunc = (COMPILE_SHADER) pCompile; m_pFreeFunc = (FREE_SHADER) pFree; m_pmAsics = gcnew System::Collections::Generic::List(); // Populate the sorted device (card) info table. std::vector cardList; std::vector DXDeviceTable; // DX support now only SI, CI and VI if (AMDTDeviceInfoUtils::Instance()->GetAllCardsInHardwareGeneration(GDT_HW_GENERATION_SOUTHERNISLAND, cardList)) { DXDeviceTable.insert(DXDeviceTable.end(), cardList.begin(), cardList.end()); } if (AMDTDeviceInfoUtils::Instance()->GetAllCardsInHardwareGeneration(GDT_HW_GENERATION_SEAISLAND, cardList)) { DXDeviceTable.insert(DXDeviceTable.end(), cardList.begin(), cardList.end()); } if (AMDTDeviceInfoUtils::Instance()->GetAllCardsInHardwareGeneration(GDT_HW_GENERATION_VOLCANICISLAND, cardList)) { DXDeviceTable.insert(DXDeviceTable.end(), cardList.begin(), cardList.end()); } std::sort(DXDeviceTable.begin(), DXDeviceTable.end(), GfxCardInfoSortPredicate); // de-duplicate cards based on cal name // Some of these things are pre-release or otherwise unsupported by the driver (at least the current one) // there are also a few hundred entries in the device table, but only about a dozen or so "cal names" size_t i=0; while( i < DXDeviceTable.size() ) { m_pmAsics->Add( gcnew AMDAsic_Impl(DXDeviceTable[i] ) ); const char* pName = DXDeviceTable[i].m_szCALName; do { i++; } while( i < DXDeviceTable.size() && strcmp( pName, DXDeviceTable[i].m_szCALName ) == 0 ); } } Pyramid::IAMDShader^ AMDDriver_Impl::CompileDXBlob(Pyramid::IAMDAsic^ asic, array^ blob, Pyramid::IDXShaderReflection^ reflection ) { AMDAsic_Impl^ a = dynamic_cast(asic); MarshalledBlob^ bl = gcnew MarshalledBlob(blob); AmdDxGsaCompileShaderInput args; args.byteCodeLength = bl->GetLength(); args.pShaderByteCode = bl->GetBlob(); args.pCompileOptions = 0; args.numCompileOptions = 0; args.chipRevision = a->m_nChipRevision; args.chipFamily = a->m_nChipFamily; memset( args.reserved, 0, sizeof(args.reserved) ); AmdDxGsaCompileShaderOutput result; result.size = sizeof(result); result.pShaderBinary = 0; result.shaderBinarySize = 0; DWORD hResult = m_pCompileFunc( &args, &result ); if( hResult != 0 ) throw gcnew System::Exception( "Error returned from AMD driver compile" ); AMDShader_Impl::ShaderType eType; switch( reflection->GetShaderType() ) { case Pyramid::HLSLShaderType::VERTEX: eType = AMDShader_Impl::ShaderType::ST_VERTEX; break; case Pyramid::HLSLShaderType::PIXEL: eType = AMDShader_Impl::ShaderType::ST_PIXEL; break; case Pyramid::HLSLShaderType::GEOMETRY: eType = AMDShader_Impl::ShaderType::ST_GEOMETRY; break; case Pyramid::HLSLShaderType::DOMAIN: eType = AMDShader_Impl::ShaderType::ST_DOMAIN; break; case Pyramid::HLSLShaderType::HULL: eType = AMDShader_Impl::ShaderType::ST_HULL; break; case Pyramid::HLSLShaderType::COMPUTE: eType = AMDShader_Impl::ShaderType::ST_COMPUTE; break; default: throw gcnew System::Exception( "Bad shader type enum???"); } DWORD nThreadsPerGroup = reflection->GetThreadsPerGroup(); return gcnew AMDShader_Impl( this, a, (Elf32_Ehdr*)result.pShaderBinary, result.shaderBinarySize, nThreadsPerGroup, eType ); } ================================================ FILE: src/Wrapper/AMDDriver_Impl.h ================================================ #pragma unmanaged #include "AMDTBackend/Include/Common/AmdDxGsaCompile.h" typedef PfnAmdDxGsaCompileShader COMPILE_SHADER; typedef PfnAmdDxGsaFreeCompiledShader FREE_SHADER; #pragma managed private ref class AMDDriver_Impl : public Pyramid::IAMDDriver { public: AMDDriver_Impl( System::String^ path ); property System::Collections::Generic::IEnumerable^ Asics { virtual System::Collections::Generic::IEnumerable^ get() { return m_pmAsics; } } virtual Pyramid::IAMDShader^ CompileDXBlob(Pyramid::IAMDAsic^ asic, array^ exe, Pyramid::IDXShaderReflection^ reflection ); internal: COMPILE_SHADER m_pCompileFunc; FREE_SHADER m_pFreeFunc; private: System::Collections::Generic::List^ m_pmAsics; }; ================================================ FILE: src/Wrapper/AMDShader_Impl.cpp ================================================ #pragma unmanaged #include #include "elf.h" #include "GCNDisassembler.h" #include "GCNDecoder.h" #include "GCNBufferedPrinter.h" #pragma managed #include "AMDShader_Impl.h" #include "AMDDriver_Impl.h" #include "AMDAsic_Impl.h" #include "Utilities.h" #include "Scrutinizer_GCN.h" AMDShader_Impl::AMDShader_Impl( AMDDriver_Impl^ pOwner, AMDAsic_Impl^ asic, Elf32_Ehdr* pElf, DWORD nElfSize, DWORD nThreadsPerGroup, ShaderType eShaderType ) : m_pmDriver(pOwner), m_pmAsic(asic), m_pElf(pElf), m_nElfSize(nElfSize), m_pISA(0), m_nISASize(0), m_pStats(0), m_nStatsSize(0), m_nThreadsPerThreadGroup(nThreadsPerGroup), m_eShaderType(eShaderType) { // make sure they're using ELF if( pElf->e_ident[0] != 0x7f || pElf->e_ident[1] != 'E' || pElf->e_ident[2] != 'L' || pElf->e_ident[3] != 'F' ) throw gcnew System::Exception("Blob received from AMD driver is not an elf binary"); // find the '.text' section, which contains the code byte* pElfBytes = (byte*)pElf; Elf32_Shdr* pSections = (Elf32_Shdr*) (pElfBytes + pElf->e_shoff); Elf32_Shdr* pStringTable = pSections + pElf->e_shstrndx; byte* pElfStringTable = pElfBytes + pStringTable->sh_offset; for( DWORD i=0; ie_shnum; i++ ) { DWORD nString = pSections[i].sh_name; byte* pSectionName = pElfStringTable + pSections[i].sh_name; if( strcmp( (const char*) pSectionName, ".text" ) == 0 ) { m_pISA = pElfBytes + pSections[i].sh_offset; m_nISASize = pSections[i].sh_size; } if( strcmp( (const char*) pSectionName, ".stats" ) == 0 ) { m_pStats = (DWORD*) (pElfBytes + pSections[i].sh_offset); m_nStatsSize = pSections[i].sh_size; } } // didn't find it. Kick and scream if( !m_pISA ) throw gcnew System::Exception( "Blob received from AMD driver does not contain a '.text' section"); if( !m_pStats || (m_nStatsSize % 4) ) throw gcnew System::Exception( "'.stats' section from driver blob is missing or misaligned"); } AMDShader_Impl::~AMDShader_Impl() { GCN::IDecoder::Destroy( m_pDecoder ); m_pmDriver->m_pFreeFunc(m_pElf); m_pElf=0; m_nElfSize=0; m_pStats=0; m_nStatsSize=0; m_pISA=0; m_nISASize=0; } array^ AMDShader_Impl::ReadISABytes() { array^ bytes = gcnew array(m_nISASize); for( DWORD i=0; im_pDecoder, printer, m_pISA, m_nISASize ) ) printer.Push("Disassembly terminated due to encoding error\n"); printer.m_Bytes.push_back(0); System::String^ str = MakeString( printer.m_Bytes.data() ); return str->Replace( "\n", System::Environment::NewLine ); } System::String^ AMDShader_Impl::ListEncodings() { GCN::Disassembler::BufferedPrinter printer; if( !GCN::Disassembler::ListEncodings( *m_pmAsic->m_pDecoder, printer, m_pISA, m_nISASize ) ) printer.Push("Disassembly terminated due to encoding error\n"); printer.m_Bytes.push_back(0); System::String^ str = MakeString( printer.m_Bytes.data() ); return str->Replace( "\n", System::Environment::NewLine ); } System::String^ AMDShader_Impl::PrintStats( ) { DWORD nSGPRs = m_pStats[0]; DWORD nMaxSGPRs = m_pStats[1]; DWORD nVGPRs = m_pStats[2]; DWORD nMaxVGPRs = m_pStats[3]; DWORD nUsedLDS = m_pStats[4]; DWORD nMaxLDS = m_pStats[5]; DWORD nScratchBytes = m_pStats[6]; DWORD nALUOps = m_pStats[7]; DWORD nScalarOps = m_pStats[8]; DWORD nMemoryOps = m_pStats[9]; // NOTE: // SI and CI had to have GPRs allocated in multiples of 4 // According to docs this is true for VI as well. // // However, for VI chips, driver is reporting VGPR counts that are not multiples of 4 // I do not know if this is a driver bug or a doc bug, but // I'm going to assume the latter // DWORD nVGPROccupancy=10; DWORD nSGPROccupancy=10; if( nVGPRs ) nVGPROccupancy = nMaxVGPRs/nVGPRs; if( nSGPRs ) nSGPROccupancy = 512/nSGPRs; if( nVGPROccupancy > 10 ) nVGPROccupancy = 10; if( nSGPROccupancy > 10 ) nSGPROccupancy = 10; DWORD nLDSOccupancy = 0; if( nUsedLDS ) nLDSOccupancy = nMaxLDS / nUsedLDS; DWORD nWavesPerGroup = (m_nThreadsPerThreadGroup+63)/64; char buffer[4096]; sprintf( buffer, "SGPRs: %3u / %u\n" "VGPRs: %3u / %u\n" "LDS bytes/tg %6u / %u\n" "Waves/Group: %u\n" "Occupancy:\n" " S: %2u waves/SIMD\n" " V: %2u waves/SIMD\n" " L: %2u groups/CU\n" " %2u waves/CU\n" " %.2f waves/SIMD \n" "Ops:\n" " VALU: %u\n" " S: %u\n" " VMEM: %u\n", nSGPRs,nMaxSGPRs, nVGPRs,nMaxVGPRs, nUsedLDS,nMaxLDS, nWavesPerGroup, nSGPROccupancy, nVGPROccupancy, nLDSOccupancy*2, nLDSOccupancy*2*nWavesPerGroup, (nLDSOccupancy*2*nWavesPerGroup)/4.0f, nALUOps, nScalarOps, nMemoryOps ); System::String^ str = gcnew System::String(buffer); return str->Replace("\n", System::Environment::NewLine ); } size_t AMDShader_Impl::GetWaveOccupancy() { DWORD nSGPRs = m_pStats[0]; DWORD nMaxSGPRs = m_pStats[1]; DWORD nVGPRs = m_pStats[2]; DWORD nMaxVGPRs = m_pStats[3]; DWORD nUsedLDS = m_pStats[4]; DWORD nMaxLDS = m_pStats[5]; DWORD nScratchBytes = m_pStats[6]; DWORD nALUOps = m_pStats[7]; DWORD nScalarOps = m_pStats[8]; DWORD nMemoryOps = m_pStats[9]; // NOTE: // SI and CI had to have GPRs allocated in multiples of 4 // According to docs this is true for VI as well. // // However, for VI chips, driver is reporting VGPR counts that are not multiples of 4 // I do not know if this is a driver bug or a doc bug, but // I'm going to assume the latter // DWORD nVGPROccupancy=10; DWORD nSGPROccupancy=10; if( nVGPRs ) nVGPROccupancy = nMaxVGPRs/nVGPRs; if( nSGPRs ) nSGPROccupancy = 512/nSGPRs; if( nVGPROccupancy > 10 ) nVGPROccupancy = 10; if( nSGPROccupancy > 10 ) nSGPROccupancy = 10; return (nVGPROccupancy < nSGPROccupancy) ? nVGPROccupancy : nSGPROccupancy; } size_t AMDShader_Impl::GetGroupOccupancy() { DWORD nUsedLDS = m_pStats[4]; DWORD nMaxLDS = m_pStats[5]; if( !nUsedLDS ) return 40/GetWavesPerThreadGroup(); size_t nMaxGroupsLDS = (nMaxLDS/nUsedLDS)*2; size_t nMaxGroupsWaveSlots = 40/GetWavesPerThreadGroup(); return min(nMaxGroupsLDS,nMaxGroupsWaveSlots); } Pyramid::Scrutinizer::IScrutinizer^ AMDShader_Impl::CreateScrutinizer() { switch( m_eShaderType ) { case ShaderType::ST_VERTEX: return gcnew Scrutinizer_GCN_VS( m_pmAsic, this ); case ShaderType::ST_PIXEL: return gcnew Scrutinizer_GCN_PS( m_pmAsic, this ); case ShaderType::ST_COMPUTE: return gcnew Scrutinizer_GCN_CS( m_pmAsic, this ); default: return nullptr; } } Pyramid::IAMDAsic^ AMDShader_Impl::Asic::get() { return m_pmAsic; } ================================================ FILE: src/Wrapper/AMDShader_Impl.h ================================================ #pragma unmanaged #include "elf.h" typedef unsigned long DWORD; typedef unsigned char byte; #pragma managed ref class AMDAsic_Impl; ref class AMDDriver_Impl; private ref class AMDShader_Impl : public Pyramid::IAMDShader { public: enum class ShaderType { ST_VERTEX, ST_PIXEL, ST_GEOMETRY, ST_HULL, ST_DOMAIN, ST_COMPUTE }; AMDShader_Impl( AMDDriver_Impl^ pOwner, AMDAsic_Impl^ asic, Elf32_Ehdr* pElf, DWORD nElfSize, DWORD nThreadsPerThreadGroup, ShaderType eShaderType ); ~AMDShader_Impl(); virtual array^ ReadISABytes(); virtual System::String^ Disassemble(); virtual System::String^ ListEncodings(); virtual System::String^ PrintStats( ); property Pyramid::IAMDAsic^ Asic { virtual Pyramid::IAMDAsic^ get(); } size_t GetWaveOccupancy(); size_t GetGroupOccupancy(); size_t GetThreadsPerThreadGroup() { return m_nThreadsPerThreadGroup; } size_t GetWavesPerThreadGroup() { return (m_nThreadsPerThreadGroup+63)/64;} virtual Pyramid::Scrutinizer::IScrutinizer^ CreateScrutinizer(); internal: AMDDriver_Impl^ m_pmDriver; AMDAsic_Impl^ m_pmAsic; Elf32_Ehdr* m_pElf; DWORD m_nElfSize; DWORD* m_pStats; DWORD m_nStatsSize; byte* m_pISA; DWORD m_nISASize; GCN::IDecoder* m_pDecoder; DWORD m_nThreadsPerThreadGroup; ShaderType m_eShaderType; }; ================================================ FILE: src/Wrapper/D3DCompiler_Impl.cpp ================================================ #include "D3DCompiler_Impl.h" #include "Utilities.h" #include #pragma unmanaged #include #include #include "dxc/dxcapi.h" #pragma managed /////////////////////////////////////////////////////////////////////////////////////// class PyramidD3DIncludeHandler : public ID3DInclude { public: PyramidD3DIncludeHandler( Pyramid::IIncludeHandler^ pmInclude, System::String^ root ) : m_pmInclude(pmInclude) { // D3D compiler doesn't pass the source file path to you // They expect you to track it yourself. m_Stack.push_back(root); } virtual HRESULT __stdcall Open( D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) override { *ppData=0; *pBytes=0; Pyramid::IIncludeHandler^ pmInclude = static_cast(m_pmInclude); if( pmInclude == nullptr ) return E_FAIL; Pyramid::IncludeType eType; switch( IncludeType ) { case D3D_INCLUDE_SYSTEM: eType = Pyramid::IncludeType::System; break; case D3D_INCLUDE_LOCAL: eType = Pyramid::IncludeType::User; break; default: return E_FAIL; } Pyramid::IIncludeResult^ result = pmInclude->OpenInclude(eType,MakeString(pFileName),m_Stack.back() ); if( result == nullptr ) return E_FAIL; array^ pFileContents = result->Contents; void* pNative = malloc(pFileContents->Length); Marshal::Copy( pFileContents, 0, System::IntPtr(pNative), pFileContents->Length); *ppData = pNative; *pBytes = pFileContents->Length; m_Stack.push_back( result->FullPath ); return S_OK; } virtual HRESULT __stdcall Close(LPCVOID pData) override { if( !pData ) return S_OK; free((void*)pData); m_Stack.pop_back(); return S_OK; } private: gcroot m_pmInclude; std::vector< gcroot > m_Stack; }; /////////////////////////////////////////////////////////////////////////////////////// DXBCRootSignatureBlob_Impl::DXBCRootSignatureBlob_Impl( ID3DBlob* pBlob,D3DCompiler_Impl^ pCompiler ) : m_pBlob( pBlob ),m_pmCompiler( pCompiler ) { } DXBCRootSignatureBlob_Impl::~DXBCRootSignatureBlob_Impl() { if ( m_pBlob ) m_pBlob->Release(); } array^ DXBCRootSignatureBlob_Impl::ReadBytes() { if ( !m_pBlob ) return nullptr; size_t size = m_pBlob->GetBufferSize(); byte* pBytes = (byte*)m_pBlob->GetBufferPointer(); array^ pmBytes = gcnew array( m_pBlob->GetBufferSize() ); for ( size_t i=0; iRelease(); } Pyramid::IDXBlob^ DXBCShaderBlob_Impl::ExtractRootSignature() { if ( m_pBlob ) { ID3DBlob* pRSBlob; HRESULT hr = m_pmCompiler->m_pGetBlob( m_pBlob->GetBufferPointer(),m_pBlob->GetBufferSize(),D3D_BLOB_ROOT_SIGNATURE,0,&pRSBlob ); if ( SUCCEEDED( hr ) && pRSBlob != nullptr ) { return gcnew DXBCRootSignatureBlob_Impl( pRSBlob,m_pmCompiler ); } } return nullptr; } System::String^ DXBCShaderBlob_Impl::Disassemble() { if( m_pBlob ) { ID3DBlob* pAsm=0; HRESULT hr = m_pmCompiler->m_pDisassemble( m_pBlob->GetBufferPointer(), m_pBlob->GetBufferSize(), 0, 0, &pAsm ); if( SUCCEEDED(hr) && pAsm ) { System::String^ IR = Marshal::PtrToStringAnsi( System::IntPtr(pAsm->GetBufferPointer()) ); IR = IR->Replace( gcnew System::String("\n"), System::Environment::NewLine ); pAsm->Release(); return IR; } } return gcnew System::String(""); } array^ DXBCShaderBlob_Impl::ReadBytes() { if( !m_pBlob ) return nullptr; size_t size = m_pBlob->GetBufferSize(); byte* pBytes = (byte*) m_pBlob->GetBufferPointer(); array^ pmBytes = gcnew array( m_pBlob->GetBufferSize() ); for( size_t i=0; im_pStrip( m_pBlob->GetBufferPointer(), m_pBlob->GetBufferSize(), uFlags, &pStripped ); if( !SUCCEEDED(hr)) throw gcnew System::Exception("D3DStripShader failed"); return gcnew DXBCShaderBlob_Impl(pStripped,m_pmCompiler); } Pyramid::IDXBCShaderBlob^ DXBCShaderBlob_Impl::GetSignatureBlob() { if( !m_pBlob ) return nullptr; ID3DBlob* pSignature=0; HRESULT hr = m_pmCompiler->m_pGetBlob( m_pBlob->GetBufferPointer(), m_pBlob->GetBufferSize(), D3D_BLOB_INPUT_AND_OUTPUT_SIGNATURE_BLOB,0, &pSignature ); if( !SUCCEEDED(hr)) throw gcnew System::Exception("D3DGetBlobPart failed"); return gcnew DXBCShaderBlob_Impl(pSignature,m_pmCompiler); } Pyramid::IDXBCShaderBlob^ DXBCShaderBlob_Impl::GetExecutableBlob() { if( !m_pBlob ) return nullptr; // The actual, executable bytecode is signaled by a magic 4cc code // Following the fourcc is the size of the executable code in bytes // DWORD nSM4Sentinel = MAKEFOURCC('S','H','D','R'); DWORD nSM5Sentinel = MAKEFOURCC('S','H','E','X'); DWORD* pBlob = (DWORD*) m_pBlob->GetBufferPointer(); for( UINT i=0; iGetBufferSize(); i+= 4 ) { if( pBlob[i/4] == nSM5Sentinel || pBlob[i/4] == nSM4Sentinel ) { DWORD nCodeSizeInBytes = pBlob[(i/4) + 1]; ID3DBlob* pResultBlob=0; if( FAILED(m_pmCompiler->m_pCreateBlob( nCodeSizeInBytes, &pResultBlob ) ) ) throw gcnew System::Exception("D3DCreateBlob failed"); memcpy( pResultBlob->GetBufferPointer(), pBlob + (i/4)+2, nCodeSizeInBytes ); return gcnew DXBCShaderBlob_Impl( pResultBlob, m_pmCompiler ); } } return nullptr; // no code in this blob } Pyramid::IDXShaderReflection^ DXBCShaderBlob_Impl::Reflect() { ID3D11ShaderReflection* pReflect=0; HRESULT hr = m_pmCompiler->m_pReflect( m_pBlob->GetBufferPointer(), m_pBlob->GetBufferSize(), __uuidof(ID3D11ShaderReflection), (void**) &pReflect ); if( FAILED(hr) ) throw gcnew System::Exception("Shader reflection failed"); return gcnew DXShaderReflection_Impl(pReflect); } /////////////////////////////////////////////////////////////////////////////////////// D3DCompiler_Impl::D3DCompiler_Impl( System::String^ DLLPath, Pyramid::IIncludeHandler^ pmInclude ) { MarshalledString DLL(DLLPath); HMODULE hDLL = LoadLibraryA( DLL ); if( !hDLL ) throw gcnew System::Exception(System::String::Format( "LoadLibrary failed for {0}", DLLPath )); void* pCompile2Func = GetProcAddress( hDLL, "D3DCompile2" ); void* pCompileFunc = GetProcAddress( hDLL, "D3DCompile" ); if( !pCompileFunc ) throw gcnew System::Exception(System::String::Format( "GetProcAddress failed for 'D3DCompile'")); void* pDisassembleFunc = GetProcAddress( hDLL, "D3DDisassemble" ); if( !pDisassembleFunc ) throw gcnew System::Exception(System::String::Format("GetProcAddress failed for 'D3DDisassemble'")); void* pStripFunc = GetProcAddress(hDLL,"D3DStripShader"); if( !pStripFunc ) throw gcnew System::Exception(System::String::Format("GetProcAddress failed for 'D3DStripShader'")); void* pGetBlobPartFunc = GetProcAddress(hDLL,"D3DGetBlobPart"); if( !pGetBlobPartFunc ) throw gcnew System::Exception(System::String::Format("GetProcAddress failed for 'D3DGetBlobPart'")); void* pCreateBlobFunc = GetProcAddress(hDLL, "D3DCreateBlob" ); if( !pCreateBlobFunc ) throw gcnew System::Exception(System::String::Format("GetProcAddress failed for 'D3DCreateBlob'")); void* pReflectFunc = GetProcAddress(hDLL, "D3DReflect"); if( !pReflectFunc ) throw gcnew System::Exception(System::String::Format("GetProcAddress failed for 'D3DReflect'")); m_pCompile2 = (D3DCOMPILE2_FUNC) pCompile2Func; m_pCompile = (D3DCOMPILE_FUNC) pCompileFunc; m_pDisassemble = (D3DDISASSEMBLE_FUNC) pDisassembleFunc; m_pStrip = (D3DSTRIP_FUNC)pStripFunc; m_pGetBlob = (D3DGETBLOBPART_FUNC)pGetBlobPartFunc; m_pCreateBlob = (D3DCREATEBLOB_FUNC) pCreateBlobFunc; m_pReflect = (D3DREFLECT_FUNC) pReflectFunc; m_pmInclude = pmInclude; } bool D3DCompiler_Impl::Compile( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ fileName, Pyramid::IDXBCShaderBlob^% IR, System::String^% Messages ) { ID3DBlob* pCode=0; ID3DBlob* pMessages=0; HRESULT hr; MarshalledString hlsl( Shader ); MarshalledString entry( opts->EntryPoint ); MarshalledString profile( opts->Target.ToString() ); PyramidD3DIncludeHandler include( m_pmInclude,fileName ); if ( m_pCompile2 ) { hr = m_pCompile2( hlsl.GetString(), hlsl.Length()+1, "", 0, &include, entry,profile,opts->GetD3DCompileFlagBits(),0, 0,0,0, &pCode,&pMessages ); } else { hr = m_pCompile( hlsl.GetString(), hlsl.Length()+1, "", 0, &include, entry,profile,opts->GetD3DCompileFlagBits(),0,&pCode,&pMessages ); } if ( SUCCEEDED( hr ) ) IR = gcnew DXBCShaderBlob_Impl( pCode,this ); Messages = nullptr; if ( pMessages ) { Messages = Marshal::PtrToStringAnsi( System::IntPtr( pMessages->GetBufferPointer() ) ); Messages = Messages->Replace( gcnew System::String( "\n" ),System::Environment::NewLine ); pMessages->Release(); } return SUCCEEDED( hr ); } bool D3DCompiler_Impl::CompileRootSignature( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ Path, Pyramid::IDXBlob^% blob, System::String^% Messages ) { ID3DBlob* pCode=0; ID3DBlob* pMessages=0; HRESULT hr; MarshalledString hlsl( Shader ); MarshalledString entry( opts->RootSigMacro ); MarshalledString profile( opts->RootSigTarget.ToString() ); PyramidD3DIncludeHandler include( m_pmInclude,Path ); { hr = m_pCompile( hlsl.GetString(), hlsl.Length()+1, "", 0, &include, entry,profile,opts->GetD3DCompileFlagBits(),0,&pCode,&pMessages ); } if ( SUCCEEDED( hr ) ) blob = gcnew DXBCRootSignatureBlob_Impl( pCode,this ); Messages = nullptr; if ( pMessages ) { Messages = Marshal::PtrToStringAnsi( System::IntPtr( pMessages->GetBufferPointer() ) ); Messages = Messages->Replace( gcnew System::String( "\n" ),System::Environment::NewLine ); pMessages->Release(); } return SUCCEEDED( hr ); } ================================================ FILE: src/Wrapper/D3DCompiler_Impl.h ================================================ #ifndef _D3D_COMPILER_IMPL_H_ #define _D3D_COMPILER_IMPL_H_ #pragma unmanaged #include #pragma managed typedef HRESULT (WINAPI *D3DCOMPILE_FUNC)( LPCVOID pSrcData, SIZE_T SrcDataSize, LPCSTR pSourceName, const D3D_SHADER_MACRO *pDefines, ID3DInclude *pInclude, LPCSTR pEntrypoint, LPCSTR pTarget, UINT Flags1, UINT Flags2, ID3DBlob **ppCode, ID3DBlob **ppErrorMsgs); typedef HRESULT (WINAPI *D3DCOMPILE2_FUNC)( LPCVOID pSrcData, SIZE_T SrcDataSize, LPCSTR pSourceName, const D3D_SHADER_MACRO* pDefines, ID3DInclude* pInclude, LPCSTR pEntrypoint, LPCSTR pTarget, UINT Flags1, UINT Flags2, UINT SecondaryDataFlags, LPCVOID pSecondaryData, SIZE_T SecondaryDataSize, ID3DBlob** ppCode, ID3DBlob** ppErrorMsgs ); typedef HRESULT (WINAPI *D3DDISASSEMBLE_FUNC)( LPCVOID pSrcData, SIZE_T SrcDataSize, UINT Flags, LPCSTR szComments, ID3DBlob **ppDisassembly ); typedef HRESULT (WINAPI *D3DSTRIP_FUNC)( LPCVOID pShaderBytecode, SIZE_T BytecodeLength, UINT uStripFlags, ID3DBlob **ppStrippedBlob ); typedef HRESULT (WINAPI *D3DGETBLOBPART_FUNC)( LPCVOID pShaderBytecode, SIZE_T BytecodeLength, UINT uBlobPartEnum, UINT uFlags, ID3DBlob **ppBlob ); typedef HRESULT (WINAPI *D3DCREATEBLOB_FUNC)( SIZE_T nBytes, ID3DBlob** ppBlob ); typedef HRESULT (WINAPI *D3DREFLECT_FUNC)( LPCVOID pSrcData, SIZE_T SrcDataSize, REFIID pInterface, void** ppReflector ); ref class D3DCompiler_Impl; private ref class DXBCRootSignatureBlob_Impl : Pyramid::IDXBlob { public: DXBCRootSignatureBlob_Impl( ID3DBlob* pBlob,D3DCompiler_Impl^ pCompiler ); ~DXBCRootSignatureBlob_Impl(); virtual array^ ReadBytes(); private: ID3DBlob* m_pBlob; D3DCompiler_Impl^ m_pmCompiler; }; private ref class DXBCShaderBlob_Impl : Pyramid::IDXBCShaderBlob { public: DXBCShaderBlob_Impl( ID3DBlob* pBlob, D3DCompiler_Impl^ pCompiler ); ~DXBCShaderBlob_Impl( ); virtual Pyramid::IDXBlob^ ExtractRootSignature(); virtual System::String^ Disassemble(); virtual array^ ReadBytes(); virtual Pyramid::IDXBCShaderBlob^ Strip(); virtual Pyramid::IDXBCShaderBlob^ GetSignatureBlob(); virtual Pyramid::IDXBCShaderBlob^ GetExecutableBlob(); virtual Pyramid::IDXShaderReflection^ Reflect(); private: ID3DBlob* m_pBlob; D3DCompiler_Impl^ m_pmCompiler; }; private ref class D3DCompiler_Impl : Pyramid::ID3DCompiler { public: D3DCompiler_Impl( System::String^ DLLPath, Pyramid::IIncludeHandler^ pmIncludes ); virtual bool CompileRootSignature( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ Path, Pyramid::IDXBlob^% blob, System::String^% Errors ); virtual bool Compile( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ Path, Pyramid::IDXBCShaderBlob^% blob, System::String^% Errors ); internal: D3DCOMPILE_FUNC m_pCompile; D3DCOMPILE2_FUNC m_pCompile2; D3DDISASSEMBLE_FUNC m_pDisassemble; D3DSTRIP_FUNC m_pStrip; D3DGETBLOBPART_FUNC m_pGetBlob; D3DCREATEBLOB_FUNC m_pCreateBlob; D3DREFLECT_FUNC m_pReflect; Pyramid::IIncludeHandler^ m_pmInclude; }; private ref class DXShaderReflection_Impl : public Pyramid::IDXShaderReflection { public: DXShaderReflection_Impl( ID3D11ShaderReflection* pRef ) : m_pRef(pRef) { } ~DXShaderReflection_Impl() { m_pRef->Release(); } virtual UINT GetThreadsPerGroup() { UINT SizeX, SizeY, SizeZ; m_pRef->GetThreadGroupSize(&SizeX,&SizeY,&SizeZ); return SizeX*SizeY*SizeZ; } virtual Pyramid::HLSLShaderType GetShaderType() { D3D11_SHADER_DESC d; m_pRef->GetDesc(&d); UINT type = D3D11_SHVER_GET_TYPE(d.Version); switch(type) { case D3D11_SHVER_PIXEL_SHADER: return Pyramid::HLSLShaderType::PIXEL; case D3D11_SHVER_VERTEX_SHADER: return Pyramid::HLSLShaderType::VERTEX; case D3D11_SHVER_GEOMETRY_SHADER: return Pyramid::HLSLShaderType::GEOMETRY; case D3D11_SHVER_HULL_SHADER: return Pyramid::HLSLShaderType::HULL; case D3D11_SHVER_DOMAIN_SHADER: return Pyramid::HLSLShaderType::DOMAIN; case D3D11_SHVER_COMPUTE_SHADER: return Pyramid::HLSLShaderType::COMPUTE; } throw gcnew System::Exception("Bad DX shader type??"); } ID3D11ShaderReflection* m_pRef; }; #endif ================================================ FILE: src/Wrapper/DXILCompiler_Impl.cpp ================================================ #include "DXILCompiler_Impl.h" #include "Utilities.h" #pragma unmanaged #include #include #include #include "dxc/hlsl/DxilContainer.h" #pragma managed /////////////////////////////////////////////////////////////////////////////////////// // Use our own blob class bc we don't have any path for IDxcBlob from raw bytes // without somehow guessing the encoding. Marcello has punted this problem to us // and we shall punt it back to him.... :) #pragma unmanaged class MyBlob : public IDxcBlob { public: MyBlob( void* p, size_t l ) : m_cRef( 1 ),m_pPtr( p ),m_nSize( l ) {} ~MyBlob() { free( m_pPtr ); } ULONG STDMETHODCALLTYPE AddRef() { InterlockedIncrement( &m_cRef ); return m_cRef; } ULONG STDMETHODCALLTYPE Release() { // Decrement the object's internal counter. ULONG ulRefCount = InterlockedDecrement( &m_cRef ); if ( 0 == m_cRef ) { delete this; } return ulRefCount; } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID * ppvObj ) { // Always set out parameter to NULL, validating it first. if ( !ppvObj ) return E_INVALIDARG; *ppvObj = NULL; if ( riid == IID_IUnknown || riid == __uuidof(IDxcBlob) ) { // Increment the reference count and return the pointer. *ppvObj = (LPVOID)this; AddRef(); return NOERROR; } return E_NOINTERFACE; } virtual LPVOID STDMETHODCALLTYPE GetBufferPointer( void ) { return m_pPtr; } virtual SIZE_T STDMETHODCALLTYPE GetBufferSize( void ) { return m_nSize; } ULONG m_cRef; void* m_pPtr; size_t m_nSize; }; #pragma managed class PyramidDxilIncludeHandler : public IDxcIncludeHandler { public: PyramidDxilIncludeHandler( Pyramid::IIncludeHandler^ pmInclude, IDxcLibrary* pDXCLibrary ) : m_pmInclude( pmInclude ), m_pDXCLibrary( pDXCLibrary ), m_cRef(1) { } virtual HRESULT STDMETHODCALLTYPE LoadSource( _In_ LPCWSTR pFilename, // Candidate filename. _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource // Resultant source object for included file, nullptr if not found. ) override { Pyramid::IIncludeHandler^ pmInclude = static_cast(m_pmInclude); if ( pmInclude == nullptr ) return E_FAIL; Pyramid::IIncludeResult^ result = pmInclude->OpenInclude( Pyramid::IncludeType::User,MakeString( pFilename ), nullptr ); if ( result == nullptr ) { *ppIncludeSource = nullptr; return S_OK; } array^ pFileContents = result->Contents; void* pNative = malloc( pFileContents->Length ); Marshal::Copy( pFileContents,0,System::IntPtr( pNative ),pFileContents->Length ); *ppIncludeSource = new MyBlob( pNative,pFileContents->Length ); return S_OK; } ULONG STDMETHODCALLTYPE AddRef() { InterlockedIncrement( &m_cRef ); return m_cRef; } ULONG STDMETHODCALLTYPE Release() { // Decrement the object's internal counter. ULONG ulRefCount = InterlockedDecrement( &m_cRef ); if ( 0 == m_cRef ) { delete this; } return ulRefCount; } HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid,LPVOID * ppvObj ) { // Always set out parameter to NULL, validating it first. if ( !ppvObj ) return E_INVALIDARG; *ppvObj = NULL; if ( riid == IID_IUnknown || riid == __uuidof(IDxcIncludeHandler) ) { // Increment the reference count and return the pointer. *ppvObj = (LPVOID)this; AddRef(); return NOERROR; } return E_NOINTERFACE; } private: gcroot m_pmInclude; IDxcLibrary* m_pDXCLibrary = nullptr; ULONG m_cRef; }; /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// DXILShaderBlob_Impl::DXILShaderBlob_Impl( IDxcBlob* pBlob,DXILCompiler_Impl^ pCompiler ) : m_pBlob( pBlob ),m_pmCompiler( pCompiler ) { } DXILShaderBlob_Impl::~DXILShaderBlob_Impl() { if ( m_pBlob ) m_pBlob->Release(); } System::String^ DXILShaderBlob_Impl::Disassemble() { if ( m_pBlob ) { IDxcBlobEncoding* pAsm=0; HRESULT hr = m_pmCompiler->m_pDXCCompiler->Disassemble( m_pBlob, &pAsm ); if ( SUCCEEDED( hr ) && pAsm ) { IDxcBlobEncoding* pUTF16 = nullptr; hr = m_pmCompiler->m_pDXCLibrary->GetBlobAsUtf16( pAsm, &pUTF16 ); if ( SUCCEEDED( hr ) ) { System::String^ IR = Marshal::PtrToStringUni( System::IntPtr( pUTF16->GetBufferPointer() ) ); IR = IR->Replace( gcnew System::String( "\n" ),System::Environment::NewLine ); pAsm->Release(); return IR; } } } return gcnew System::String( "" ); } Pyramid::IDXBlob^ DXILShaderBlob_Impl::ExtractRootSignature() { CComPtr pReflector; HRESULT hr = m_pmCompiler->m_pfnCreateInstance( CLSID_DxcContainerReflection,__uuidof(IDxcContainerReflection),(void**)&pReflector ); if ( pReflector == nullptr || FAILED( hr ) ) return nullptr; hr = pReflector->Load( m_pBlob ); if ( FAILED( hr ) ) return nullptr; UINT32 partIdx; hr = pReflector->FindFirstPartKind( hlsl::DFCC_RootSignature,&partIdx ); if ( FAILED( hr ) ) return nullptr; IDxcBlob* pBlob; hr = pReflector->GetPartContent( partIdx,&pBlob ); if ( FAILED( hr ) ) return nullptr; return gcnew DXILRootSignatureBlob_Impl( pBlob,m_pmCompiler ); } array^ DXILShaderBlob_Impl::ReadBytes() { if ( !m_pBlob ) return nullptr; size_t size = m_pBlob->GetBufferSize(); byte* pBytes = (byte*)m_pBlob->GetBufferPointer(); array^ pmBytes = gcnew array( m_pBlob->GetBufferSize() ); for ( size_t i=0; iRelease(); } array^ DXILRootSignatureBlob_Impl::ReadBytes() { if ( !m_pBlob ) return nullptr; size_t size = m_pBlob->GetBufferSize(); byte* pBytes = (byte*)m_pBlob->GetBufferPointer(); array^ pmBytes = gcnew array( m_pBlob->GetBufferSize() ); for ( size_t i=0; iRelease(); throw gcnew System::Exception( System::String::Format( "DXCCompiler create failed in {0} ",DLLPath ) ); } m_pDXCCompiler = pCompiler; m_pDXCLibrary = pLibrary; m_pmInclude = pmInclude; m_pfnCreateInstance = pfnDxcCreateInstance; } DXILCompiler_Impl::~DXILCompiler_Impl() { if ( m_pDXCCompiler ) m_pDXCCompiler->Release(); if ( m_pDXCLibrary ) m_pDXCLibrary->Release(); } #pragma unmanaged static HRESULT CompileFromBlob( IDxcCompiler* pCompiler, IDxcBlobEncoding *pSource,LPCWSTR pSourceName, const D3D_SHADER_MACRO *pDefines,IDxcIncludeHandler *pInclude, LPWSTR pEntrypointW, LPWSTR pTargetProfileW,UINT Flags1, IDxcBlob **ppCode, IDxcBlobEncoding **ppErrorMsgs ) { CComPtr operationResult; HRESULT hr; try { std::vector defineValues; std::vector defines; std::vector arguments; // /Gec, /Ges Not implemented: //if(Flags1 & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY) arguments.push_back(L"/Gec"); //if(Flags1 & D3DCOMPILE_ENABLE_STRICTNESS) arguments.push_back(L"/Ges"); if ( Flags1 & D3DCOMPILE_IEEE_STRICTNESS ) arguments.push_back( L"/Gis" ); if ( Flags1 & D3DCOMPILE_OPTIMIZATION_LEVEL2 ) { switch ( Flags1 & D3DCOMPILE_OPTIMIZATION_LEVEL2 ) { case D3DCOMPILE_OPTIMIZATION_LEVEL0: arguments.push_back( L"/O0" ); break; case D3DCOMPILE_OPTIMIZATION_LEVEL2: arguments.push_back( L"/O2" ); break; case D3DCOMPILE_OPTIMIZATION_LEVEL3: arguments.push_back( L"/O3" ); break; } } // Currently, /Od turns off too many optimization passes, causing incorrect DXIL to be generated. // Re-enable once /Od is implemented properly: //if(Flags1 & D3DCOMPILE_SKIP_OPTIMIZATION) arguments.push_back(L"/Od"); if ( Flags1 & D3DCOMPILE_DEBUG ) arguments.push_back( L"/Zi" ); if ( Flags1 & D3DCOMPILE_PACK_MATRIX_ROW_MAJOR ) arguments.push_back( L"/Zpr" ); if ( Flags1 & D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR ) arguments.push_back( L"/Zpc" ); if ( Flags1 & D3DCOMPILE_AVOID_FLOW_CONTROL ) arguments.push_back( L"/Gfa" ); if ( Flags1 & D3DCOMPILE_PREFER_FLOW_CONTROL ) arguments.push_back( L"/Gfp" ); // We don't implement this: //if(Flags1 & D3DCOMPILE_PARTIAL_PRECISION) arguments.push_back(L"/Gpp"); if ( Flags1 & D3DCOMPILE_RESOURCES_MAY_ALIAS ) arguments.push_back( L"/res_may_alias" ); if ( Flags1 & D3DCOMPILE_SKIP_VALIDATION ) arguments.push_back( L"-Vd" ); if ( wcscmp( pTargetProfileW+3,L"6_2" ) == 0 ) { // if compiling to SM6_2, turn on 16-bit types // (because Microsoft decided that shader model 2 should be "extra-optional") // also need to disable validation because the validator apparently doesn't know about SM_6_2 yet, // at least as of when I built it arguments.push_back( L"/enable-16bit-types" ); arguments.push_back( L"-Vd" ); } if ( FAILED( pCompiler->Compile( pSource,pSourceName,pEntrypointW,pTargetProfileW, arguments.data(),(UINT)arguments.size(), defines.data(),(UINT)defines.size(),pInclude, &operationResult ) ) ) { return E_FAIL; } } catch ( const std::bad_alloc & ) { return E_OUTOFMEMORY; } catch ( const CAtlException &err ) { return err.m_hr; } operationResult->GetStatus( &hr ); if ( SUCCEEDED( hr ) ) { return operationResult->GetResult( (IDxcBlob **)ppCode ); } else { if ( ppErrorMsgs ) operationResult->GetErrorBuffer( (IDxcBlobEncoding **)ppErrorMsgs ); return hr; } } #pragma managed bool DXILCompiler_Impl::Compile( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ fileName, Pyramid::IDXILShaderBlob^% IR, System::String^% Messages ) { System::String^ targetString = opts->Target.ToString(); // DXIL path if ( !m_pDXCLibrary ) return false; IDxcBlob* pCode = nullptr; IDxcBlobEncoding* pMessages = nullptr; DWORD flags = opts->GetD3DCompileFlagBits(); MarshalledString hlsl( Shader ); MarshalledStringW entry( opts->EntryPoint ); MarshalledStringW profile( targetString ); MarshalledStringW file( fileName ); IDxcBlobEncoding* pBlobEncoding = nullptr; HRESULT hr = m_pDXCLibrary->CreateBlobWithEncodingFromPinned( (LPBYTE) hlsl.GetString(), hlsl.Length()+1, CP_UTF8, &pBlobEncoding ); if ( !SUCCEEDED( hr ) ) return false; PyramidDxilIncludeHandler kHandler( m_pmInclude,m_pDXCLibrary ); hr = CompileFromBlob( m_pDXCCompiler, pBlobEncoding, file.GetString(), nullptr, &kHandler, entry.GetString(), profile.GetString(), flags, &pCode,&pMessages ); pBlobEncoding->Release(); if ( SUCCEEDED( hr ) ) IR = gcnew DXILShaderBlob_Impl( pCode,this ); Messages = nullptr; if ( pMessages ) { IDxcBlobEncoding* pMessagesUni = nullptr; HRESULT hr2 = m_pDXCLibrary->GetBlobAsUtf16( pMessages,&pMessagesUni ); if ( SUCCEEDED( hr2 ) ) { Messages = Marshal::PtrToStringUni( System::IntPtr( pMessagesUni->GetBufferPointer() ) ); Messages = Messages->Replace( gcnew System::String( "\n" ),System::Environment::NewLine ); pMessagesUni->Release(); } pMessages->Release(); } return SUCCEEDED( hr ); } bool DXILCompiler_Impl::CompileRootSignature( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ fileName, Pyramid::IDXBlob^% IR, System::String^% Messages ) { // DXIL path if ( !m_pDXCLibrary ) return false; IDxcBlob* pCode = nullptr; IDxcBlobEncoding* pMessages = nullptr; DWORD flags = opts->GetD3DCompileFlagBits(); MarshalledString hlsl( Shader->Replace( System::Environment::NewLine,"\n" ) ); MarshalledStringW entry( opts->RootSigMacro ); MarshalledStringW profile( opts->RootSigTarget.ToString() ); MarshalledStringW file( fileName ); IDxcBlobEncoding* pBlobEncoding = nullptr; HRESULT hr = m_pDXCLibrary->CreateBlobWithEncodingFromPinned( (LPBYTE)hlsl.GetString(),hlsl.Length()+1,CP_UTF8,&pBlobEncoding ); if ( !SUCCEEDED( hr ) ) return false; PyramidDxilIncludeHandler kHandler( m_pmInclude,m_pDXCLibrary ); hr = CompileFromBlob( m_pDXCCompiler, pBlobEncoding, file.GetString(), nullptr,&kHandler, entry.GetString(),profile.GetString(),flags,&pCode,&pMessages ); pBlobEncoding->Release(); if ( SUCCEEDED( hr ) ) IR = gcnew DXILRootSignatureBlob_Impl( pCode,this ); Messages = nullptr; if ( pMessages ) { IDxcBlobEncoding* pMessagesUni = nullptr; HRESULT hr2 = m_pDXCLibrary->GetBlobAsUtf16( pMessages,&pMessagesUni ); if ( SUCCEEDED( hr2 ) ) { Messages = Marshal::PtrToStringUni( System::IntPtr( pMessagesUni->GetBufferPointer() ) ); Messages = Messages->Replace( gcnew System::String( "\n" ),System::Environment::NewLine ); pMessagesUni->Release(); } pMessages->Release(); } return SUCCEEDED( hr ); } ================================================ FILE: src/Wrapper/DXILCompiler_Impl.h ================================================ #ifndef _DXIL_COMPILER_IMPL_H_ #define _DXIL_COMPILER_IMPL_H_ #pragma unmanaged #include #include "dxc/dxcapi.h" struct IDxcLibrary; struct IDxcCompiler; struct IDxcBlob; #pragma managed typedef unsigned char byte; ref class DXILCompiler_Impl; private ref class DXILRootSignatureBlob_Impl : Pyramid::IDXBlob { public: DXILRootSignatureBlob_Impl( IDxcBlob* pBlob,DXILCompiler_Impl^ pCompiler ); ~DXILRootSignatureBlob_Impl(); virtual array^ ReadBytes(); private: IDxcBlob* m_pBlob; DXILCompiler_Impl^ m_pmCompiler; }; private ref class DXILShaderBlob_Impl : Pyramid::IDXILShaderBlob { public: DXILShaderBlob_Impl( IDxcBlob* pBlob,DXILCompiler_Impl^ pCompiler ); ~DXILShaderBlob_Impl(); virtual Pyramid::IDXBlob^ ExtractRootSignature(); virtual System::String^ Disassemble(); virtual array^ ReadBytes(); private: IDxcBlob* m_pBlob; DXILCompiler_Impl^ m_pmCompiler; }; private ref class DXILCompiler_Impl : Pyramid::IDXILCompiler { public: DXILCompiler_Impl( System::String^ DLLPath,Pyramid::IIncludeHandler^ pmIncludes ); ~DXILCompiler_Impl(); virtual bool CompileRootSignature( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ Path, Pyramid::IDXBlob^% blob, System::String^% Errors ); virtual bool Compile( System::String^ Shader, Pyramid::IHLSLOptions^ opts, System::String^ Path, Pyramid::IDXILShaderBlob^% blob, System::String^% Errors ); internal: Pyramid::IIncludeHandler^ m_pmInclude; IDxcLibrary* m_pDXCLibrary = nullptr; IDxcCompiler* m_pDXCCompiler = nullptr; DxcCreateInstanceProc m_pfnCreateInstance = nullptr; }; #endif ================================================ FILE: src/Wrapper/GCN1Decoder.cpp ================================================ // // Helper class responsible for decoding GCN instructions into a standardized form // // A decoder abstraction is necessary because AMD decided to change the // microcode formats and opcode numbers for GCN3. // // Copyright 2015 Joshua Barczak, all rights reserved. // #pragma unmanaged #include "GCNEnums.h" #include "GCNIsa.h" #include "GCN1Decoder.h" #include namespace GCN{ namespace _GCN1Decoder_INTERNAL { struct EnumLUT { uint eEnum; uint nEncoding; }; static uint LUTLookup( const EnumLUT* pLUT, size_t nLUTSize,uint en, uint TInvalid ) { size_t n = nLUTSize/sizeof(EnumLUT); for( size_t i=0; i S1.i). ENUM( S_CMP_GE_I32 ,3 ) //: SCC = (S0.i >= S1.i). ENUM( S_CMP_LT_I32 ,4 ) //: SCC = (S0.i < S1.i). ENUM( S_CMP_LE_I32 ,5 ) //: SCC = (S0.i <= S1.i). ENUM( S_CMP_EQ_U32 ,6 ) //: SCC = (S0.u == S1.u). ENUM( S_CMP_LG_U32 ,7 ) //: SCC = (S0.u != S1.u). ENUM( S_CMP_GT_U32 ,8 ) //: SCC = (S0.u > S1.u). ENUM( S_CMP_GE_U32 ,9 ) //: SCC = (S0.u >= S1.u). ENUM( S_CMP_LT_U32 ,10) //: SCC = (S0.u < S1.u). ENUM( S_CMP_LE_U32 ,11) //: SCC = (S0.u <= S1.u). ENUM( S_BITCMP0_B32 ,12) //: SCC = (S0.u[S1.u[4:0]] == 0). ENUM( S_BITCMP1_B32 ,13) //: SCC = (S0.u[S1.u[4:0]] == 1). ENUM( S_BITCMP0_B64 ,14) //: SCC = (S0.u[S1.u[5:0]] == 0). ENUM( S_BITCMP1_B64 ,15) //: SCC = (S0.u[S1.u[5:0]] == 1). ENUM( S_SETVSKIP ,16) //: VSKIP = S0.u[S1.u[4:0]]. END_TRANSLATOR(ScalarInstructions,SOPCOpcodes,S_INVALID) BEGIN_TRANSLATOR(ScalarInstructions,SOPPOpcodes) ENUM(S_NOP ,0 ) //: do nothing. Repeat NOP 1..8 times based on SIMM16[2:0]. 0 = 1 time, 7 = 8 times. ENUM(S_ENDPGM ,1 ) //: end of program; terminate wavefront. ENUM(S_BRANCH ,2 ) //: PC = PC + signext(SIMM16 * 4) + 4. ENUM(S_CBRANCH_SCC0 ,4 ) //: if(SCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_SCC1 ,5 ) //: if(SCC == 1) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_VCCZ ,6 ) //: if(VCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_VCCNZ ,7 ) //: if(VCC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_EXECZ ,8 ) //: if(EXEC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_EXECNZ ,9 ) //: if(EXEC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_BARRIER ,10 ) //: Sync waves within a thread group. ENUM(S_WAITCNT ,12 ) //: Wait for count of outstanding lds, vector-memory and ENUM(S_SETHALT ,13 ) //: set HALT bit to value of SIMM16[0]. 1=halt, 0=resume. Halt is ignored while priv=1. ENUM(S_SLEEP ,14 ) //: Cause a wave to sleep for approximately 64*SIMM16[2:0] clocks. ENUM(S_SETPRIO ,15 ) //: User settable wave priority. 0 = lowest, 3 = highest. ENUM(S_SENDMSG ,16 ) //: Send a message. ENUM(S_SENDMSGHALT ,17 ) //: Send a message and then HALT. ENUM(S_TRAP ,18 ) //: Enter the trap handler. TrapID = SIMM16[7:0]. Wait for all instructions to complete, ENUM(S_ICACHE_INV ,19 ) //: Invalidate entire L1 I cache. ENUM(S_INCPERFLEVEL ,20 ) //: Increment performance counter specified in SIMM16[3:0] by 1. ENUM(S_DECPERFLEVEL ,21 ) //: Decrement performance counter specified in SIMM16[3:0] by 1. ENUM(S_TTRACEDATA ,22 ) //: Send M0 as user data to thread-trace. ENUM(S_CBRANCH_CDBGSYS ,23 )// : If (conditional_debug_system != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. ENUM(S_CBRANCH_CDBGUSER ,24 )// : If (conditional_debug_user != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. ENUM(S_CBRANCH_CDBGSYS_OR_USER ,25 )// : If (conditional_debug_system || conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. ENUM(S_CBRANCH_CDBGSYS_AND_USER ,26 )// : If (conditional_debug_system && conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. END_TRANSLATOR(ScalarInstructions,SOPPOpcodes,S_INVALID) BEGIN_TRANSLATOR(ScalarMemoryInstructions,SMRDOpcodes) ENUM(S_LOAD_DWORD ,0 ) // : Read from read-only constant memory. ENUM(S_LOAD_DWORDX2 ,1 ) // : Read from read-only constant memory. ENUM(S_LOAD_DWORDX4 ,2 ) // : Read from read-only constant memory. ENUM(S_LOAD_DWORDX8 ,3 ) // : Read from read-only constant memory. ENUM(S_LOAD_DWORDX16 ,4 ) // : Read from read-only constant memory. ENUM(S_BUFFER_LOAD_DWORD ,8 ) // : Read from read-only constant memory. ENUM(S_BUFFER_LOAD_DWORDX2 ,9 ) // : Read from read-only constant memory. ENUM(S_BUFFER_LOAD_DWORDX4 ,10) // : Read from read-only constant memory. ENUM(S_BUFFER_LOAD_DWORDX8 ,11) // : Read from read-only constant memory. ENUM(S_BUFFER_LOAD_DWORDX16 ,12) // : Read from read-only constant memory. ENUM(S_DCACHE_INV_VOL ,29) // : Invalidate all volatile lines in L1 constant cache. ENUM(S_MEMTIME ,30) // : Return current 64-bit timestamp. ENUM(S_DCACHE_INV ,31) // : Invalidate entire L1 K cache. END_TRANSLATOR(ScalarMemoryInstructions,SMRDOpcodes,S_INVALID) BEGIN_TRANSLATOR(VectorInstructions,VOP2Opcodes) ENUM(V_CNDMASK_B32 , 0 ) ENUM(V_READLANE_B32 , 1 ) ENUM(V_WRITELANE_B32 , 2 ) ENUM(V_ADD_F32 , 3 ) ENUM(V_SUB_F32 , 4 ) ENUM(V_SUBREV_F32 , 5 ) ENUM(V_MAC_LEGACY_F32 , 6 ) ENUM(V_MUL_LEGACY_F32 , 7 ) ENUM(V_MUL_F32 , 8 ) ENUM(V_MUL_I32_I24 , 9 ) ENUM(V_MUL_HI_I32_I24 , 10) ENUM(V_MUL_U32_U24 , 11) ENUM(V_MUL_HI_U32_U24 , 12) ENUM(V_MIN_LEGACY_F32 , 13) ENUM(V_MAX_LEGACY_F32 , 14) ENUM(V_MIN_F32 , 15) ENUM(V_MAX_F32 , 16) ENUM(V_MIN_I32 , 17) ENUM(V_MAX_I32 , 18) ENUM(V_MIN_U32 , 19) ENUM(V_MAX_U32 , 20) ENUM(V_LSHR_B32 , 21) ENUM(V_LSHRREV_B32 , 22) ENUM(V_ASHR_I32 , 23) ENUM(V_ASHRREV_I32 , 24) ENUM(V_LSHL_B32 , 25) ENUM(V_LSHLREV_B32 , 26) ENUM(V_AND_B32 , 27) ENUM(V_OR_B32 , 28) ENUM(V_XOR_B32 , 29) ENUM(V_BFM_B32 , 30) ENUM(V_MAC_F32 , 31) ENUM(V_MADMK_F32 , 32) ENUM(V_MADAK_F32 , 33) ENUM(V_BCNT_U32_B32 , 34) ENUM(V_MBCNT_LO_U32_B32 , 35) ENUM(V_MBCNT_HI_U32_B32 , 36) ENUM(V_ADD_I32 , 37) ENUM(V_SUB_I32 , 38) ENUM(V_SUBREV_I32 , 39) ENUM(V_ADDC_U32 , 40) ENUM(V_SUBB_U32 , 41) ENUM(V_SUBBREV_U32 , 42) ENUM(V_LDEXP_F32 , 43) ENUM(V_CVT_PKACCUM_U8_F32 , 44) ENUM(V_CVT_PKNORM_I16_F32 , 45) ENUM(V_CVT_PKNORM_U16_F32 , 46) ENUM(V_CVT_PKRTZ_F16_F32 , 47) ENUM(V_CVT_PK_U16_U32 , 48) ENUM(V_CVT_PK_I16_I32 , 49) END_TRANSLATOR(VectorInstructions,VOP2Opcodes,V_INVALID) BEGIN_TRANSLATOR(VectorInstructions,VOP1Opcodes) ENUM(V_NOP , 0 ) ENUM(V_MOV_B32 , 1 ) ENUM(V_READFIRSTLANE_B32 , 2 ) ENUM(V_CVT_I32_F64 , 3 ) ENUM(V_CVT_F64_I32 , 4 ) ENUM(V_CVT_F32_I32 , 5 ) ENUM(V_CVT_F32_U32 , 6 ) ENUM(V_CVT_U32_F32 , 7 ) ENUM(V_CVT_I32_F32 , 8 ) ENUM(V_MOV_FED_B32 , 9 ) ENUM(V_CVT_F16_F32 , 10 ) ENUM(V_CVT_F32_F16 , 11 ) ENUM(V_CVT_RPI_I32_F32 , 12 ) ENUM(V_CVT_FLR_I32_F32 , 13 ) ENUM(V_CVT_OFF_F32_I4 , 14 ) ENUM(V_CVT_F32_F64 , 15 ) ENUM(V_CVT_F64_F32 , 16 ) ENUM(V_CVT_F32_UBYTE0 , 17 ) ENUM(V_CVT_F32_UBYTE1 , 18 ) ENUM(V_CVT_F32_UBYTE2 , 19 ) ENUM(V_CVT_F32_UBYTE3 , 20 ) ENUM(V_CVT_U32_F64 , 21 ) ENUM(V_CVT_F64_U32 , 22 ) ENUM(V_TRUNC_F64 , 23 ) ENUM(V_CEIL_F64 , 24 ) ENUM(V_RNDNE_F64 , 25 ) ENUM(V_FLOOR_F64 , 26 ) ENUM(V_FRACT_F32 , 32 ) ENUM(V_TRUNC_F32 , 33 ) ENUM(V_CEIL_F32 , 34 ) ENUM(V_RNDNE_F32 , 35 ) ENUM(V_FLOOR_F32 , 36 ) ENUM(V_EXP_F32 , 37 ) ENUM(V_LOG_CLAMP_F32 , 38 ) ENUM(V_LOG_F32 , 39 ) ENUM(V_RCP_CLAMP_F32 , 40 ) ENUM(V_RCP_LEGACY_F32 , 41 ) ENUM(V_RCP_F32 , 42 ) ENUM(V_RCP_IFLAG_F32 , 43 ) ENUM(V_RSQ_CLAMP_F32 , 44 ) ENUM(V_RSQ_LEGACY_F32 , 45 ) ENUM(V_RSQ_F32 , 46 ) ENUM(V_RCP_F64 , 47 ) ENUM(V_RCP_CLAMP_F64 , 48 ) ENUM(V_RSQ_F64 , 49 ) ENUM(V_RSQ_CLAMP_F64 , 50 ) ENUM(V_SQRT_F32 , 51 ) ENUM(V_SQRT_F64 , 52 ) ENUM(V_SIN_F32 , 53 ) ENUM(V_COS_F32 , 54 ) ENUM(V_NOT_B32 , 55 ) ENUM(V_BFREV_B32 , 56 ) ENUM(V_FFBH_U32 , 57 ) ENUM(V_FFBL_B32 , 58 ) ENUM(V_FFBH_I32 , 59 ) ENUM(V_FREXP_EXP_I32_F64 , 60 ) ENUM(V_FREXP_MANT_F64 , 61 ) ENUM(V_FRACT_F64 , 62 ) ENUM(V_FREXP_EXP_I32_F32 , 63 ) ENUM(V_FREXP_MANT_F32 , 64 ) ENUM(V_CLREXCP , 65 ) ENUM(V_MOVRELD_B32 , 66 ) ENUM(V_MOVRELS_B32 , 67 ) ENUM(V_MOVRELSD_B32 , 68 ) ENUM(V_LOG_LEGACY_F32 , 69 ) ENUM(V_EXP_LEGACY_F32 , 70 ) END_TRANSLATOR(VectorInstructions,VOP1Opcodes,V_INVALID) static VectorInstructions Translate_VOPCOpcodes( uint n ) { switch( n & 0xf0) { case 0x00: return (VectorInstructions)(V_CMP_F_F32 + (n&0xf)); case 0x10: return (VectorInstructions)(V_CMPX_F_F32 + (n&0xf)); case 0x20: return (VectorInstructions)(V_CMP_F_F64 + (n&0xf)); case 0x30: return (VectorInstructions)(V_CMPX_F_F64 + (n&0xf)); case 0x40: return (VectorInstructions)(V_CMPS_F_F32 + (n&0xf)); case 0x50: return (VectorInstructions)(V_CMPSX_F_F32 + (n&0xf)); case 0x60: return (VectorInstructions)(V_CMPS_F_F64 + (n&0xf)); case 0x70: return (VectorInstructions)(V_CMPSX_F_F64 + (n&0xf)); default: switch( n & 0xf8 ) { case 0x80: return (VectorInstructions)(V_CMP_F_I32 + (n&0xf)); case 0x90: return (VectorInstructions)(V_CMPX_F_I32 + (n&0xf)); case 0xA0: return (VectorInstructions)(V_CMP_F_I64 + (n&0xf)); case 0xB0: return (VectorInstructions)(V_CMPX_F_I64 + (n&0xf)); case 0xC0: return (VectorInstructions)(V_CMP_F_U32 + (n&0xf)); case 0xD0: return (VectorInstructions)(V_CMPX_F_U32 + (n&0xf)); case 0xE0: return (VectorInstructions)(V_CMP_F_U64 + (n&0xf)); case 0xF0: return (VectorInstructions)(V_CMPx_F_U64 + (n&0xf)); case 0x88: return V_CMP_CLASS_F32; case 0x98: return V_CMPX_CLASS_F32; case 0xA8: return V_CMP_CLASS_F64; case 0xB8: return V_CMPX_CLASS_F64; } } return V_INVALID; } BEGIN_TRANSLATOR(VectorInstructions,VOP3OpcodesExtra) ENUM(V_CNDMASK_B32 ,256) ENUM(V_READLANE_B32 ,257) ENUM(V_WRITELANE_B32 ,258) ENUM(V_ADD_F32 ,259) ENUM(V_SUB_F32 ,260) ENUM(V_SUBREV_F32 ,261) ENUM(V_MAC_LEGACY_F32 ,262) ENUM(V_MUL_LEGACY_F32 ,263) ENUM(V_MUL_F32 ,264) ENUM(V_MUL_I32_I24 ,265) ENUM(V_MUL_HI_I32_I24 ,266) ENUM(V_MUL_U32_U24 ,267) ENUM(V_MUL_HI_U32_U24 ,268) ENUM(V_MIN_LEGACY_F32 ,269) ENUM(V_MAX_LEGACY_F32 ,270) ENUM(V_MIN_F32 ,271) ENUM(V_MAX_F32 ,272) ENUM(V_MIN_I32 ,273) ENUM(V_MAX_I32 ,274) ENUM(V_MIN_U32 ,275) ENUM(V_MAX_U32 ,276) ENUM(V_LSHR_B32 ,277) ENUM(V_LSHRREV_B32 ,278) ENUM(V_ASHR_I32 ,279) ENUM(V_ASHRREV_I32 ,280) ENUM(V_LSHL_B32 ,281) ENUM(V_LSHLREV_B32 ,282) ENUM(V_AND_B32 ,283) ENUM(V_OR_B32 ,284) ENUM(V_XOR_B32 ,285) ENUM(V_BFM_B32 ,286) ENUM(V_MAC_F32 ,287) ENUM(V_MADMK_F32 ,288) ENUM(V_MADAK_F32 ,289) ENUM(V_BCNT_U32_B32 ,290) ENUM(V_MBCNT_LO_U32_B32 ,291) ENUM(V_MBCNT_HI_U32_B32 ,292) ENUM(V_ADD_I32 ,293) ENUM(V_SUB_I32 ,294) ENUM(V_SUBREV_I32 ,295) ENUM(V_ADDC_U32 ,296) ENUM(V_SUBB_U32 ,297) ENUM(V_SUBBREV_U32 ,298) ENUM(V_DIV_SCALE_F32 ,365) ENUM(V_DIV_SCALE_F64 ,366) ENUM(V_LDEXP_F32 ,299) ENUM(V_CVT_PKACCUM_U8_F32 ,300) ENUM(V_CVT_PKNORM_I16_F32 ,301) ENUM(V_CVT_PKNORM_U16_F32 ,302) ENUM(V_CVT_PKRTZ_F16_F32 ,303) ENUM(V_CVT_PK_U16_U32 ,304) ENUM(V_CVT_PK_I16_I32 ,305) ENUM(V_MAD_LEGACY_F32 ,320) ENUM(V_MAD_F32 ,321) ENUM(V_MAD_I32_I24 ,322) ENUM(V_MAD_U32_U24 ,323) ENUM(V_CUBEID_F32 ,324) ENUM(V_CUBESC_F32 ,325) ENUM(V_CUBETC_F32 ,326) ENUM(V_CUBEMA_F32 ,327) ENUM(V_BFE_U32 ,328) ENUM(V_BFE_I32 ,329) ENUM(V_BFI_B32 ,330) ENUM(V_FMA_F32 ,331) ENUM(V_FMA_F64 ,332) ENUM(V_LERP_U8 ,333) ENUM(V_ALIGNBIT_B32 ,334) ENUM(V_ALIGNBYTE_B32 ,335) ENUM(V_MULLIT_F32 ,336) ENUM(V_MIN3_F32 ,337) ENUM(V_MIN3_I32 ,338) ENUM(V_MIN3_U32 ,339) ENUM(V_MAX3_F32 ,340) ENUM(V_MAX3_I32 ,341) ENUM(V_MAX3_U32 ,342) ENUM(V_MED3_F32 ,343) ENUM(V_MED3_I32 ,344) ENUM(V_MED3_U32 ,345) ENUM(V_SAD_U8 ,346) ENUM(V_SAD_HI_U8 ,347) ENUM(V_SAD_U16 ,348) ENUM(V_SAD_U32 ,349) ENUM(V_CVT_PK_U8_F32 ,350) ENUM(V_DIV_FIXUP_F32 ,351) ENUM(V_DIV_FIXUP_F64 ,352) ENUM(V_LSHL_B64 ,353) ENUM(V_LSHR_B64 ,354) ENUM(V_ASHR_I64 ,355) ENUM(V_ADD_F64 ,356) ENUM(V_MUL_F64 ,357) ENUM(V_MIN_F64 ,358) ENUM(V_MAX_F64 ,359) ENUM(V_LDEXP_F64 ,360) ENUM(V_MUL_LO_U32 ,361) ENUM(V_MUL_HI_U32 ,362) ENUM(V_MUL_LO_I32 ,363) ENUM(V_MUL_HI_I32 ,364) ENUM(V_DIV_FMAS_F32 ,367) ENUM(V_DIV_FMAS_F64 ,368) ENUM(V_MSAD_U8 ,369) ENUM(V_QSAD_U8 ,370) ENUM(V_MQSAD_U8 ,371) ENUM(V_QSAD_PK_U16_U8 ,370) ENUM(V_MQSAD_PK_U16_U8 ,371) ENUM(V_TRIG_PREOP_F64 ,372) ENUM(V_MQSAD_U32_U8 ,373) ENUM(V_MAD_U64_U32 ,374) ENUM(V_MAD_I64_I32 ,375) ENUM(V_NOP ,384) ENUM(V_MOV_B32 ,385) ENUM(V_READFIRSTLANE_B32 ,386) ENUM(V_CVT_I32_F64 ,387) ENUM(V_CVT_F64_I32 ,388) ENUM(V_CVT_F32_I32 ,389) ENUM(V_CVT_F32_U32 ,390) ENUM(V_CVT_U32_F32 ,391) ENUM(V_CVT_I32_F32 ,392) ENUM(V_MOV_FED_B32 ,393) ENUM(V_CVT_F16_F32 ,394) ENUM(V_CVT_F32_F16 ,395) ENUM(V_CVT_RPI_I32_F32 ,396) ENUM(V_CVT_FLR_I32_F32 ,397) ENUM(V_CVT_OFF_F32_I4 ,398) ENUM(V_CVT_F32_F64 ,399) ENUM(V_CVT_F64_F32 ,400) ENUM(V_CVT_F32_UBYTE0 ,401) ENUM(V_CVT_F32_UBYTE1 ,402) ENUM(V_CVT_F32_UBYTE2 ,403) ENUM(V_CVT_F32_UBYTE3 ,404) ENUM(V_CVT_U32_F64 ,405) ENUM(V_CVT_F64_U32 ,406) ENUM(V_FRACT_F32 ,416) ENUM(V_TRUNC_F32 ,417) ENUM(V_CEIL_F32 ,418) ENUM(V_RNDNE_F32 ,419) ENUM(V_FLOOR_F32 ,420) ENUM(V_EXP_F32 ,421) ENUM(V_LOG_CLAMP_F32 ,422) ENUM(V_LOG_F32 ,423) ENUM(V_RCP_CLAMP_F32 ,424) ENUM(V_RCP_LEGACY_F32 ,425) ENUM(V_RCP_F32 ,426) ENUM(V_RCP_IFLAG_F32 ,427) ENUM(V_RSQ_CLAMP_F32 ,428) ENUM(V_RSQ_LEGACY_F32 ,429) ENUM(V_RSQ_F32 ,430) ENUM(V_RCP_F64 ,431) ENUM(V_RCP_CLAMP_F64 ,432) ENUM(V_RSQ_F64 ,433) ENUM(V_RSQ_CLAMP_F64 ,434) ENUM(V_SQRT_F32 ,435) ENUM(V_SQRT_F64 ,436) ENUM(V_SIN_F32 ,437) ENUM(V_COS_F32 ,438) ENUM(V_NOT_B32 ,439) ENUM(V_BFREV_B32 ,440) ENUM(V_FFBH_U32 ,441) ENUM(V_FFBL_B32 ,442) ENUM(V_FFBH_I32 ,443) ENUM(V_FREXP_EXP_I32_F64 ,444) ENUM(V_FREXP_MANT_F64 ,445) ENUM(V_FRACT_F64 ,446) ENUM(V_FREXP_EXP_I32_F32 ,447) ENUM(V_FREXP_MANT_F32 ,448) ENUM(V_CLREXCP ,449) ENUM(V_MOVRELD_B32 ,450) ENUM(V_MOVRELS_B32 ,451) ENUM(V_MOVRELSD_B32 ,452) END_TRANSLATOR(VectorInstructions,VOP3OpcodesExtra,V_INVALID) static VectorInstructions Translate_VOP3Opcodes( uint n ) { if( n <= 255 ) return Translate_VOPCOpcodes(n); return Translate_VOP3OpcodesExtra(n); } static VectorInstructions Translate_VINTERPOpcodes( uint n ) { switch(n) { case 0: return V_INTERP_P1_F32 ; // : D = P10 * S + P0; parameter interpolation. case 1: return V_INTERP_P2_F32 ; // : D = P20 * S + D; parameter interpolation. case 2: return V_INTERP_MOV_F32 ; // : D = {P10,P20,P0}[S]; parameter load. default: return V_INVALID; } } BEGIN_TRANSLATOR(Dests,ScalarDestOddballs) ENUM(SRC_FSCR_LO , 104) ENUM(SRC_FSCR_HI , 105) ENUM(SRC_VCC_LO , 106) ENUM(SRC_VCC_HI , 107) ENUM(SRC_TBA_LO , 108) ENUM(SRC_TBA_HI , 109) ENUM(SRC_TMA_LO , 110) ENUM(SRC_TMA_HI , 111) ENUM(SRC_M0 , 124) ENUM(SRC_EXEC_LO , 126) ENUM(SRC_EXEC_HI , 127) END_TRANSLATOR(Dests,ScalarDestOddballs, DEST_INVALID) BEGIN_TRANSLATOR(Sources,ScalarSourceOddballs) ENUM(SRC_FSCR_LO , 104) ENUM(SRC_FSCR_HI , 105) ENUM(SRC_VCC_LO , 106) ENUM(SRC_VCC_HI , 107) ENUM(SRC_TBA_LO , 108) ENUM(SRC_TBA_HI , 109) ENUM(SRC_TMA_LO , 110) ENUM(SRC_TMA_HI , 111) ENUM(SRC_M0 , 124) ENUM(SRC_EXEC_LO , 126) ENUM(SRC_EXEC_HI , 127) ENUM(SRC_C_ZERO , 128) ENUM(SRC_CF_ONEHALF , 240) ENUM(SRC_CF_MINUS_ONEHALF , 241) ENUM(SRC_CF_ONE , 242) ENUM(SRC_CF_MINUS_ONE , 243) ENUM(SRC_CF_TWO , 244) ENUM(SRC_CF_MINUS_TWO , 245) ENUM(SRC_CF_FOUR , 246) ENUM(SRC_CF_MINUS_FOUR , 247) ENUM(SRC_VCCZ , 251) ENUM(SRC_EXECZ , 252) ENUM(SRC_SCC , 253) ENUM(SRC_LDS_DIRECT , 254) ENUM(SRC_LITERAL , 255) END_TRANSLATOR(Sources,ScalarSourceOddballs,SRC_INVALID) BEGIN_TRANSLATOR(DSInstructions,DSOpcodes) ENUM(DS_ADD_U32 , 0 ) ENUM(DS_SUB_U32 , 1 ) ENUM(DS_RSUB_U32 , 2 ) ENUM(DS_INC_U32 , 3 ) ENUM(DS_DEC_U32 , 4 ) ENUM(DS_MIN_I32 , 5 ) ENUM(DS_MAX_I32 , 6 ) ENUM(DS_MIN_U32 , 7 ) ENUM(DS_MAX_U32 , 8 ) ENUM(DS_AND_B32 , 9 ) ENUM(DS_OR_B32 ,10 ) ENUM(DS_XOR_B32 ,11 ) ENUM(DS_MSKOR_B32 ,12 ) ENUM(DS_WRITE_B32 ,13 ) ENUM(DS_WRITE2_B32 ,14 ) ENUM(DS_WRITE2ST64_B32 ,15 ) ENUM(DS_CMPST_B32 ,16 ) ENUM(DS_CMPST_F32 ,17 ) ENUM(DS_MIN_F32 ,18 ) ENUM(DS_MAX_F32 ,19 ) ENUM(DS_NOP ,20 ) ENUM(DS_GWS_SEMA_RELEASE_ALL ,24 ) ENUM(DS_GWS_INIT ,25 ) ENUM(DS_GWS_SEMA_V ,26 ) ENUM(DS_GWS_SEMA_BR ,27 ) ENUM(DS_GWS_SEMA_P ,28 ) ENUM(DS_GWS_BARRIER ,29 ) ENUM(DS_WRITE_B8 ,30 ) ENUM(DS_WRITE_B16 ,31 ) ENUM(DS_ADD_RTN_U32 ,32 ) ENUM(DS_SUB_RTN_U32 ,33 ) ENUM(DS_RSUB_RTN_U32 ,34 ) ENUM(DS_INC_RTN_U32 ,35 ) ENUM(DS_DEC_RTN_U32 ,36 ) ENUM(DS_MIN_RTN_I32 ,37 ) ENUM(DS_MAX_RTN_I32 ,38 ) ENUM(DS_MIN_RTN_U32 ,39 ) ENUM(DS_MAX_RTN_U32 ,40 ) ENUM(DS_AND_RTN_B32 ,41 ) ENUM(DS_OR_RTN_B32 ,42 ) ENUM(DS_XOR_RTN_B32 ,43 ) ENUM(DS_MSKOR_RTN_B32 ,44 ) ENUM(DS_WRXCHG_RTN_B32 ,45 ) ENUM(DS_WRXCHG2_RTN_B32 ,46 ) ENUM(DS_WRXCHG2ST64_RTN_B32 ,47 ) ENUM(DS_CMPST_RTN_B32 ,48 ) ENUM(DS_CMPST_RTN_F32 ,49 ) ENUM(DS_MIN_RTN_F32 ,50 ) ENUM(DS_MAX_RTN_F32 ,51 ) ENUM(DS_WRAP_RTN_B32 ,52 ) ENUM(DS_SWIZZLE_B32 ,53 ) ENUM(DS_READ_B32 ,54 ) ENUM(DS_READ2_B32 ,55 ) ENUM(DS_READ2ST64_B32 ,56 ) ENUM(DS_READ_I8 ,57 ) ENUM(DS_READ_U8 ,58 ) ENUM(DS_READ_I16 ,59 ) ENUM(DS_READ_U16 ,60 ) ENUM(DS_CONSUME ,61 ) ENUM(DS_APPEND ,62 ) ENUM(DS_ORDERED_COUNT ,63 ) ENUM(DS_ADD_U64 ,64 ) ENUM(DS_SUB_U64 ,65 ) ENUM(DS_RSUB_U64 ,66 ) ENUM(DS_INC_U64 ,67 ) ENUM(DS_DEC_U64 ,68 ) ENUM(DS_MIN_I64 ,69 ) ENUM(DS_MAX_I64 ,70 ) ENUM(DS_MIN_U64 ,71 ) ENUM(DS_MAX_U64 ,72 ) ENUM(DS_AND_B64 ,73 ) ENUM(DS_OR_B64 ,74 ) ENUM(DS_XOR_B64 ,75 ) ENUM(DS_MSKOR_B64 ,76 ) ENUM(DS_WRITE_B64 ,77 ) ENUM(DS_WRITE2_B64 ,78 ) ENUM(DS_WRITE2ST64_B64 ,79 ) ENUM(DS_CMPST_B64 ,80 ) ENUM(DS_CMPST_F64 ,81 ) ENUM(DS_MIN_F64 ,82 ) ENUM(DS_MAX_F64 ,83 ) ENUM(DS_ADD_RTN_U64 ,96 ) ENUM(DS_SUB_RTN_U64 ,97 ) ENUM(DS_RSUB_RTN_U64 ,98 ) ENUM(DS_INC_RTN_U64 ,99 ) ENUM(DS_DEC_RTN_U64 ,100) ENUM(DS_MIN_RTN_I64 ,101) ENUM(DS_MAX_RTN_I64 ,102) ENUM(DS_MIN_RTN_U64 ,103) ENUM(DS_MAX_RTN_U64 ,104) ENUM(DS_AND_RTN_B64 ,105) ENUM(DS_OR_RTN_B64 ,106) ENUM(DS_XOR_RTN_B64 ,107) ENUM(DS_MSKOR_RTN_B64 ,108) ENUM(DS_WRXCHG_RTN_B64 ,109) ENUM(DS_WRXCHG2_RTN_B64 ,110) ENUM(DS_WRXCHG2ST64_RTN_B64 ,111) ENUM(DS_CMPST_RTN_B64 ,112) ENUM(DS_CMPST_RTN_F64 ,113) ENUM(DS_MIN_RTN_F64 ,114) ENUM(DS_MAX_RTN_F64 ,115) ENUM(DS_READ_B64 ,118) ENUM(DS_READ2_B64 ,119) ENUM(DS_READ2ST64_B64 ,120) ENUM(DS_CONDXCHG32_RTN_B64 ,126) ENUM(DS_ADD_SRC2_U32 ,128) ENUM(DS_SUB_SRC2_U32 ,129) ENUM(DS_RSUB_SRC2_U32 ,130) ENUM(DS_INC_SRC2_U32 ,131) ENUM(DS_DEC_SRC2_U32 ,132) ENUM(DS_MIN_SRC2_I32 ,133) ENUM(DS_MAX_SRC2_I32 ,134) ENUM(DS_MIN_SRC2_U32 ,135) ENUM(DS_MAX_SRC2_U32 ,136) ENUM(DS_AND_SRC2_B32 ,137) ENUM(DS_OR_SRC2_B32 ,138) ENUM(DS_XOR_SRC2_B32 ,139) ENUM(DS_WRITE_SRC2_B32 ,140) ENUM(DS_MIN_SRC2_F32 ,146) ENUM(DS_MAX_SRC2_F32 ,147) ENUM(DS_ADD_SRC2_U64 ,192) ENUM(DS_SUB_SRC2_U64 ,193) ENUM(DS_RSUB_SRC2_U64 ,194) ENUM(DS_INC_SRC2_U64 ,195) ENUM(DS_DEC_SRC2_U64 ,196) ENUM(DS_MIN_SRC2_I64 ,197) ENUM(DS_MAX_SRC2_I64 ,198) ENUM(DS_MIN_SRC2_U64 ,199) ENUM(DS_MAX_SRC2_U64 ,200) ENUM(DS_AND_SRC2_B64 ,201) ENUM(DS_OR_SRC2_B64 ,202) ENUM(DS_XOR_SRC2_B64 ,203) ENUM(DS_WRITE_SRC2_B64 ,204) ENUM(DS_MIN_SRC2_F64 ,210) ENUM(DS_MAX_SRC2_F64 ,211) ENUM(DS_WRITE_B96 ,222) ENUM(DS_WRITE_B128 ,223) ENUM(DS_CONDXCHG32_RTN_B128 ,253) ENUM(DS_READ_B96 ,254) ENUM(DS_READ_B128 ,255) END_TRANSLATOR(DSInstructions,DSOpcodes,DS_INVALID) BEGIN_TRANSLATOR(BufferInstructions,MUBUFFOpcodes) ENUM( BUFFER_LOAD_FORMAT_X ,0 ) ENUM( BUFFER_LOAD_FORMAT_XY ,1 ) ENUM( BUFFER_LOAD_FORMAT_XYZ ,2 ) ENUM( BUFFER_LOAD_FORMAT_XYZW ,3 ) ENUM( BUFFER_STORE_FORMAT_X ,4 ) ENUM( BUFFER_STORE_FORMAT_XY ,5 ) ENUM( BUFFER_STORE_FORMAT_XYZ ,6 ) ENUM( BUFFER_STORE_FORMAT_XYZW ,7 ) ENUM( BUFFER_LOAD_UBYTE ,8 ) ENUM( BUFFER_LOAD_SBYTE ,9 ) ENUM( BUFFER_LOAD_USHORT ,10 ) ENUM( BUFFER_LOAD_SSHORT ,11 ) ENUM( BUFFER_LOAD_DWORD ,12 ) ENUM( BUFFER_LOAD_DWORDX2 ,13 ) ENUM( BUFFER_LOAD_DWORDX4 ,14 ) ENUM( BUFFER_LOAD_DWORDX3 ,15 ) ENUM( BUFFER_STORE_BYTE ,24 ) ENUM( BUFFER_STORE_SHORT ,26 ) ENUM( BUFFER_STORE_DWORD ,28 ) ENUM( BUFFER_STORE_DWORDX2 ,29 ) ENUM( BUFFER_STORE_DWORDX4 ,30 ) ENUM( BUFFER_STORE_DWORDX3 ,31 ) ENUM( BUFFER_ATOMIC_SWAP ,48 ) ENUM( BUFFER_ATOMIC_CMPSWAP ,49 ) ENUM( BUFFER_ATOMIC_ADD ,50 ) ENUM( BUFFER_ATOMIC_SUB ,51 ) ENUM( BUFFER_ATOMIC_RSUB ,52 ) ENUM( BUFFER_ATOMIC_SMIN ,53 ) ENUM( BUFFER_ATOMIC_UMIN ,54 ) ENUM( BUFFER_ATOMIC_SMAX ,55 ) ENUM( BUFFER_ATOMIC_UMAX ,56 ) ENUM( BUFFER_ATOMIC_AND ,57 ) ENUM( BUFFER_ATOMIC_OR ,58 ) ENUM( BUFFER_ATOMIC_XOR ,59 ) ENUM( BUFFER_ATOMIC_INC ,60 ) ENUM( BUFFER_ATOMIC_DEC ,61 ) ENUM( BUFFER_ATOMIC_FCMPSWAP ,62 ) ENUM( BUFFER_ATOMIC_FMIN ,63 ) ENUM( BUFFER_ATOMIC_FMAX ,64 ) ENUM( BUFFER_ATOMIC_SWAP_X2 ,80 ) ENUM( BUFFER_ATOMIC_CMPSWAP_X2 ,81 ) ENUM( BUFFER_ATOMIC_ADD_X2 ,82 ) ENUM( BUFFER_ATOMIC_SUB_X2 ,83 ) ENUM( BUFFER_ATOMIC_RSUB_X2 ,84 ) ENUM( BUFFER_ATOMIC_SMIN_X2 ,85 ) ENUM( BUFFER_ATOMIC_UMIN_X2 ,86 ) ENUM( BUFFER_ATOMIC_SMAX_X2 ,87 ) ENUM( BUFFER_ATOMIC_UMAX_X2 ,88 ) ENUM( BUFFER_ATOMIC_AND_X2 ,89 ) ENUM( BUFFER_ATOMIC_OR_X2 ,90 ) ENUM( BUFFER_ATOMIC_XOR_X2 ,91 ) ENUM( BUFFER_ATOMIC_INC_X2 ,92 ) ENUM( BUFFER_ATOMIC_DEC_X2 ,93 ) ENUM( BUFFER_ATOMIC_FCMPSWAP_X2 ,94 ) ENUM( BUFFER_ATOMIC_FMIN_X2 ,95 ) ENUM( BUFFER_ATOMIC_FMAX_X2 ,96 ) ENUM( BUFFER_WBINVL1_SC ,112 ) ENUM( BUFFER_WBINVL1 ,113 ) END_TRANSLATOR(BufferInstructions,MUBUFFOpcodes,BUFFER_INVALID) BEGIN_TRANSLATOR(BufferInstructions,MTBUFFOpcodes) ENUM(TBUFFER_LOAD_FORMAT_X ,0) // : Untyped buffer load 1 Dword with format conversion. ENUM(TBUFFER_LOAD_FORMAT_XY ,1) // : Untyped buffer load 2 Dwords with format conversion. ENUM(TBUFFER_LOAD_FORMAT_XYZ ,2) // : Untyped buffer load 3 Dwords with format conversion. ENUM(TBUFFER_LOAD_FORMAT_XYZW ,3) // : Untyped buffer load 4 Dwords with format conversion. ENUM(TBUFFER_STORE_FORMAT_X ,4) // : Untyped buffer store 1 Dword with format conversion. ENUM(TBUFFER_STORE_FORMAT_XY ,5) // : Untyped buffer store 2 Dwords with format conversion. ENUM(TBUFFER_STORE_FORMAT_XYZ ,6) // : Untyped buffer store 3 Dwords with format conversion. ENUM(TBUFFER_STORE_FORMAT_XYZW ,7) // : Untyped buffer store 4 Dwords with format conversion. END_TRANSLATOR(BufferInstructions,MTBUFFOpcodes,TBUFFER_INVALID) BEGIN_TRANSLATOR(ImageInstructions,MIMGOpcodes) ENUM(IMAGE_LOAD ,0 ) ENUM(IMAGE_LOAD_MIP ,1 ) ENUM(IMAGE_LOAD_PCK ,2 ) ENUM(IMAGE_LOAD_PCK_SGN ,3 ) ENUM(IMAGE_LOAD_MIP_PCK ,4 ) ENUM(IMAGE_LOAD_MIP_PCK_SGN ,5 ) ENUM(IMAGE_STORE ,8 ) ENUM(IMAGE_STORE_MIP ,9 ) ENUM(IMAGE_STORE_PCK ,10 ) ENUM(IMAGE_STORE_MIP_PCK ,11 ) ENUM(IMAGE_GET_RESINFO ,14 ) ENUM(IMAGE_ATOMIC_SWAP ,15 ) ENUM(IMAGE_ATOMIC_CMPSWAP ,16 ) ENUM(IMAGE_ATOMIC_ADD ,17 ) ENUM(IMAGE_ATOMIC_SUB ,18 ) ENUM(IMAGE_ATOMIC_RSUB ,19 ) ENUM(IMAGE_ATOMIC_SMIN ,20 ) ENUM(IMAGE_ATOMIC_UMIN ,21 ) ENUM(IMAGE_ATOMIC_SMAX ,22 ) ENUM(IMAGE_ATOMIC_UMAX ,23 ) ENUM(IMAGE_ATOMIC_AND ,24 ) ENUM(IMAGE_ATOMIC_OR ,25 ) ENUM(IMAGE_ATOMIC_XOR ,26 ) ENUM(IMAGE_ATOMIC_INC ,27 ) ENUM(IMAGE_ATOMIC_DEC ,28 ) ENUM(IMAGE_ATOMIC_FCMPSWAP ,29 ) ENUM(IMAGE_ATOMIC_FMIN ,30 ) ENUM(IMAGE_ATOMIC_FMAX ,31 ) ENUM(IMAGE_SAMPLE ,32 ) ENUM(IMAGE_SAMPLE_CL ,33 ) ENUM(IMAGE_SAMPLE_D ,34 ) ENUM(IMAGE_SAMPLE_D_CL ,35 ) ENUM(IMAGE_SAMPLE_L ,36 ) ENUM(IMAGE_SAMPLE_B ,37 ) ENUM(IMAGE_SAMPLE_B_CL ,38 ) ENUM(IMAGE_SAMPLE_LZ ,39 ) ENUM(IMAGE_SAMPLE_C ,40 ) ENUM(IMAGE_SAMPLE_C_CL ,41 ) ENUM(IMAGE_SAMPLE_C_D ,42 ) ENUM(IMAGE_SAMPLE_C_D_CL ,43 ) ENUM(IMAGE_SAMPLE_C_L ,44 ) ENUM(IMAGE_SAMPLE_C_B ,45 ) ENUM(IMAGE_SAMPLE_C_B_CL ,46 ) ENUM(IMAGE_SAMPLE_C_LZ ,47 ) ENUM(IMAGE_SAMPLE_O ,48 ) ENUM(IMAGE_SAMPLE_CL_O ,49 ) ENUM(IMAGE_SAMPLE_D_O ,50 ) ENUM(IMAGE_SAMPLE_D_CL_O ,51 ) ENUM(IMAGE_SAMPLE_L_O ,52 ) ENUM(IMAGE_SAMPLE_B_O ,53 ) ENUM(IMAGE_SAMPLE_B_CL_O ,54 ) ENUM(IMAGE_SAMPLE_LZ_O ,55 ) ENUM(IMAGE_SAMPLE_C_O ,56 ) ENUM(IMAGE_SAMPLE_C_CL_O ,57 ) ENUM(IMAGE_SAMPLE_C_D_O ,58 ) ENUM(IMAGE_SAMPLE_C_D_CL_O ,59 ) ENUM(IMAGE_SAMPLE_C_L_O ,60 ) ENUM(IMAGE_SAMPLE_C_B_O ,61 ) ENUM(IMAGE_SAMPLE_C_B_CL_O ,62 ) ENUM(IMAGE_SAMPLE_C_LZ_O ,63 ) ENUM(IMAGE_GATHER4 ,64 ) ENUM(IMAGE_GATHER4_CL ,65 ) ENUM(IMAGE_GATHER4_L ,66 ) ENUM(IMAGE_GATHER4_B ,67 ) ENUM(IMAGE_GATHER4_B_CL ,68 ) ENUM(IMAGE_GATHER4_LZ ,69 ) ENUM(IMAGE_GATHER4_C ,70 ) ENUM(IMAGE_GATHER4_C_CL ,71 ) ENUM(IMAGE_GATHER4_C_L ,76 ) ENUM(IMAGE_GATHER4_C_B ,77 ) ENUM(IMAGE_GATHER4_C_B_CL ,78 ) ENUM(IMAGE_GATHER4_C_LZ ,79 ) ENUM(IMAGE_GATHER4_O ,80 ) ENUM(IMAGE_GATHER4_CL_O ,81 ) ENUM(IMAGE_GATHER4_L_O ,84 ) ENUM(IMAGE_GATHER4_B_O ,85 ) ENUM(IMAGE_GATHER4_B_CL_O ,86 ) ENUM(IMAGE_GATHER4_LZ_O ,87 ) ENUM(IMAGE_GATHER4_C_O ,88 ) ENUM(IMAGE_GATHER4_C_CL_O ,89 ) ENUM(IMAGE_GATHER4_C_L_O ,92 ) ENUM(IMAGE_GATHER4_C_B_O ,93 ) ENUM(IMAGE_GATHER4_C_B_CL_O ,94 ) ENUM(IMAGE_GATHER4_C_LZ_O ,95 ) ENUM(IMAGE_GET_LOD ,96 ) ENUM(IMAGE_SAMPLE_CD ,104 ) ENUM(IMAGE_SAMPLE_CD_CL ,105 ) ENUM(IMAGE_SAMPLE_C_CD ,106 ) ENUM(IMAGE_SAMPLE_C_CD_CL ,107 ) ENUM(IMAGE_SAMPLE_CD_O ,108 ) ENUM(IMAGE_SAMPLE_CD_CL_O ,109 ) ENUM(IMAGE_SAMPLE_C_CD_O ,110 ) ENUM(IMAGE_SAMPLE_C_CD_CL_O ,111 ) END_TRANSLATOR(ImageInstructions,MIMGOpcodes,IMAGE_INVALID) BEGIN_TRANSLATOR(TBufferNumberFormats,MTBUFF_NumberFormat) ENUM(NF_UNORM , 0) ENUM(NF_SNORM , 1) ENUM(NF_USCALED , 2) ENUM(NF_SSCALED , 3) ENUM(NF_UINT , 4) ENUM(NF_SINT , 5) ENUM(NF_SNORM_NZ , 6) ENUM(NF_FLOAT , 7) ENUM(NF_SRGB , 9) ENUM(NF_UBNORM , 10) ENUM(NF_UBNORM_NZ , 11) ENUM(NF_UBINT , 12) ENUM(NF_UBSCALED , 13) END_TRANSLATOR(TBufferNumberFormats,MTBUFF_NumberFormat,NF_INVALID) BEGIN_TRANSLATOR(TBufferDataFormats,MTBUFF_DataFormat) ENUM( DF_8 , 1 ) ENUM( DF_16 , 2 ) ENUM( DF_8_8 , 3 ) ENUM( DF_32 , 4 ) ENUM( DF_16_16 , 5 ) ENUM( DF_10_11_11 , 6 ) ENUM( DF_11_11_10 , 7 ) ENUM( DF_10_10_10_2 , 8 ) ENUM( DF_2_10_10_10 , 9 ) ENUM( DF_8_8_8_8 , 10 ) ENUM( DF_32_32 , 11 ) ENUM( DF_16_16_16_16, 12 ) ENUM( DF_32_32_32 , 13 ) ENUM( DF_32_32_32_32, 14 ) END_TRANSLATOR(TBufferDataFormats,MTBUFF_DataFormat,DF_INVALID) BEGIN_TRANSLATOR(ExportTargets, EXPTarget) ENUM( EXP_MRT0 ,0 ) ENUM( EXP_MRT1 ,1 ) ENUM( EXP_MRT2 ,2 ) ENUM( EXP_MRT3 ,3 ) ENUM( EXP_MRT4 ,4 ) ENUM( EXP_MRT5 ,5 ) ENUM( EXP_MRT6 ,6 ) ENUM( EXP_MRT7 ,7 ) ENUM( EXP_Z ,8 ) ENUM( EXP_NULL ,9 ) ENUM( EXP_POS0 ,12 ) ENUM( EXP_POS1 ,13 ) ENUM( EXP_POS2 ,14 ) ENUM( EXP_POS3 ,15 ) ENUM( EXP_PARAM0 ,32 ) ENUM( EXP_PARAM1 ,33 ) ENUM( EXP_PARAM2 ,34 ) ENUM( EXP_PARAM3 ,35 ) ENUM( EXP_PARAM4 ,36 ) ENUM( EXP_PARAM5 ,37 ) ENUM( EXP_PARAM6 ,38 ) ENUM( EXP_PARAM7 ,39 ) ENUM( EXP_PARAM8 ,40 ) ENUM( EXP_PARAM9 ,41 ) ENUM( EXP_PARAM10 ,42 ) ENUM( EXP_PARAM11 ,43 ) ENUM( EXP_PARAM12 ,44 ) ENUM( EXP_PARAM13 ,45 ) ENUM( EXP_PARAM14 ,46 ) ENUM( EXP_PARAM15 ,47 ) ENUM( EXP_PARAM16 ,48 ) ENUM( EXP_PARAM17 ,49 ) ENUM( EXP_PARAM18 ,50 ) ENUM( EXP_PARAM19 ,51 ) ENUM( EXP_PARAM20 ,52 ) ENUM( EXP_PARAM21 ,53 ) ENUM( EXP_PARAM22 ,54 ) ENUM( EXP_PARAM23 ,55 ) ENUM( EXP_PARAM24 ,56 ) ENUM( EXP_PARAM25 ,57 ) ENUM( EXP_PARAM26 ,58 ) ENUM( EXP_PARAM27 ,59 ) ENUM( EXP_PARAM28 ,60 ) ENUM( EXP_PARAM29 ,61 ) ENUM( EXP_PARAM30 ,62 ) ENUM( EXP_PARAM31 ,63 ) END_TRANSLATOR(ExportTargets,EXPTarget,EXP_INVALID) Dests Translate_SDest( uint n ) { if( n <= 103 ) return (Dests)(DEST_SGPR_FIRST+n); else return Translate_ScalarDestOddballs(n); } Sources Translate_SSrc( uint n ) { if( n <= 103 ) return (Sources)(SRC_SGPR_FIRST+n); // SGPRs if( n >= 112 && n <= 123 ) return (Sources)(SRC_TTMP_FIRST+(n-112)); // trap handler temps if( n >= 256 && n<= 511 ) return (Sources)(SRC_VGPR_FIRST+(n-256)); // VGPRs if( n >= 129 && n <= 192 ) return(Sources) (SRC_CI_POSITIVE_FIRST+(n-129)); if( n >= 193 && n <= 208 ) return (Sources) (SRC_CI_NEGATIVE_FIRST+(n-193)); return Translate_ScalarSourceOddballs(n); } Sources Translate_VSrc( uint n ) { return (Sources)(SRC_VGPR_FIRST+n); } Dests Translate_VDest( uint n ) { return (Dests)(DEST_VGPR_FIRST+n); } class Instruction { public: uint32 ReadTrailingLiteral() const { const uint32* pDWORD = (const uint32*)this; return pDWORD[1]; } protected: int SignExt( uint n, uint sign ) { uint bit = (1<>shift)&mask; } bool ReadBit( uint bit ) const { uint shift = bit % 32; return (( ((const uint32*)this)[bit/32]>>shift)&1) != 0; } private: }; class SOP2Instruction : public Instruction { public: bool HasLiteral() const { return ((GetSrc0() == SRC_LITERAL || GetSrc1() == SRC_LITERAL)); } uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode()const { return Translate_SOP2Opcodes(ReadBits( 29, 23 )); } Sources GetSrc0() const { return Translate_SSrc(ReadBits( 7,0 )); } Sources GetSrc1() const { return Translate_SSrc(ReadBits( 15,8)); } Dests GetDest() const { return Translate_SDest(ReadBits( 22,16)); } }; class SOP1Instruction : public Instruction { public: bool HasLiteral() const { return (GetSrc0() == SRC_LITERAL); } uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode() const { return Translate_SOP1Opcodes(ReadBits( 15,8 )); } Sources GetSrc0() const { return Translate_SSrc( ReadBits(7,0) ); } Dests GetDest() const { return Translate_SDest(ReadBits(22,16)); } }; class SOPKInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_SOPK; } bool HasLiteral() const { return (GetOpcode() == S_SETREG_IMM32_B32); } uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode() const { return Translate_SOPKOpcodes(ReadBits( 27,23 )); } Dests GetDest() const { return Translate_SDest( ReadBits(22,16) ); } int ReadSIMM16() const { return *((const int16*)this); } uint ReadSIMMBits( uint hi, uint lo) const { return ReadBits(hi,lo); } uint32 ReadIMM32() const { return ReadBits(63,32); } const uint8* GetBranchTarget() const { if( GetOpcode() != S_CBRANCH_I_FORK ) return 0; int offset = this->ReadSIMM16(); const uint32* pThis = (const uint32*)this; return (const uint8*) (pThis+1+offset); } }; class SOPCInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_SOPC; } bool HasLiteral() const { return (GetSrc0() == SRC_LITERAL || GetSrc1() == SRC_LITERAL);} uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode() const { return Translate_SOPCOpcodes(ReadBits( 22,16 )); } Sources GetSrc0() const { return Translate_SSrc(ReadBits(7,0)); } Sources GetSrc1() const { return Translate_SSrc(ReadBits(15,8 )); } Dests GetDest() const { return GetOpcode() == S_SETVSKIP ? DEST_VSKIP : DEST_SCC; } }; class SOPPInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_SOPP; } uint GetLength() const { return 4; } int ReadSIMM16() const { return *((const int16*)this); } uint ReadSIMMBits( uint hi, uint lo ) const { return ReadBits(hi,lo); } ScalarInstructions GetOpcode() const { return Translate_SOPPOpcodes(ReadBits( 22,16 )); } const uint8* GetBranchTarget() const { switch( GetOpcode() ) { case S_BRANCH : case S_CBRANCH_SCC0 : case S_CBRANCH_SCC1 : case S_CBRANCH_VCCZ : case S_CBRANCH_VCCNZ : case S_CBRANCH_EXECZ : case S_CBRANCH_EXECNZ : case S_CBRANCH_CDBGSYS : case S_CBRANCH_CDBGUSER : case S_CBRANCH_CDBGSYS_OR_USER : case S_CBRANCH_CDBGSYS_AND_USER : { int n = this->ReadSIMM16(); int offset = this->ReadSIMM16(); const uint32* pThis = (const uint32*)this; return (const uint8*) (pThis+1+offset); } default: return 0; } } }; class SMRDInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_SMEM; } uint GetLength() const { return 4 + 4*(!IsOffsetIMM() && GetOffset() == SRC_LITERAL); } ScalarMemoryInstructions GetOpcode() const { return Translate_SMRDOpcodes(ReadBits(26,22)); } Dests GetDest() const { return Translate_SDest(ReadBits( 21,15)); } Dests GetBase() const { return Translate_SDest(2*ReadBits( 14,9 )); } // base of SGPR pair containing address uint GetOffset() const { return IsOffsetIMM() ? 4*ReadBits(7,0) : ReadBits(7,0); } bool IsOffsetIMM() const { return ReadBits( 8, 8 )!=0; } // SI and CI use dword offsets, but VI uses byte. }; class VOP2Instruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOP2; } bool HasLiteral() const { return (GetSrc0() == SRC_LITERAL || GetOpcode() == V_MADAK_F32 || GetOpcode() == V_MADMK_F32); } uint GetLength() const { return 4 + 4*HasLiteral(); } VectorInstructions GetOpcode() const { return Translate_VOP2Opcodes(ReadBits(30,25)); } Sources GetSrc0() const { return Translate_SSrc(ReadBits(8,0)); } Sources GetVSrc1() const { return Translate_VSrc(ReadBits(16,9)); } Dests GetVDst() const { return Translate_VDest(ReadBits(24,17)); } uint GetResultWidthInDWORDS() const { return 1; } }; class VOP1Instruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOP1; } bool HasLiteral() const { switch( GetOpcode()) { default: return GetSrc0() == SRC_LITERAL; case V_NOP: case V_CLREXCP: return false; } } uint GetLength() const { return 4 + 4*HasLiteral(); } VectorInstructions GetOpcode() const { return Translate_VOP1Opcodes( ReadBits(16,9) ); } Dests GetDst() const { if(GetOpcode() == V_READFIRSTLANE_B32) { return Translate_SDest(ReadBits(24, 17)); } else { return Translate_VDest(ReadBits(24, 17)); } } Sources GetSrc0() const { return Translate_SSrc(ReadBits(8,0)); } uint GetResultWidthInDWORDS() const; uint GetOperandWidthInDWORDS() const; const Instruction* GetBranchTarget() const { return 0; } bool IsBranch() const { return false; } }; class VOPCInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOPC; } bool HasLiteral() const { return (GetSrc0() == SRC_LITERAL); } uint GetLength() const { return 4 + 4*HasLiteral(); } VectorInstructions GetOpcode() const { return Translate_VOPCOpcodes(ReadBits(24,17)); } Sources GetSrc0() const { return Translate_SSrc(ReadBits( 8,0 )); } Sources GetVSrc1() const { return Translate_VSrc(ReadBits( 16,9 )); } uint GetOperandWidthInDWORDs() const; const Instruction* GetBranchTarget() const { return 0; } bool IsBranch() const { return false; } }; class VINTERPInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VINTERP; } uint GetLength() const { return 4; } VectorInstructions GetOpcode() const { return Translate_VINTERPOpcodes( ReadBits(17,16) ); } uint GetAttributeChannel() const { return ReadBits(9,8); }; uint GetAttributeIndex() const { return ReadBits(15,10); }; Sources GetVSrc0() const { return Translate_VSrc( ReadBits(7,0) ); } Dests GetVDst() const { return Translate_VDest(ReadBits(25,18)); } }; class VOP3Instruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOP3; } uint GetLength() const { return 8; } VectorInstructions GetOpcode() const { return Translate_VOP3Opcodes(ReadBits(25,17));} Dests GetVDst() const { uint dst = ReadBits(7,0); if( IsCompare() ) return Translate_SDest(dst); return Translate_VDest(dst); } Sources GetSrc0() const { return Translate_SSrc(ReadBits(40,32)); } Sources GetSrc1() const { return Translate_SSrc(ReadBits(49,41)); } Sources GetSrc2() const { return Translate_SSrc(ReadBits(58,50)); } uint GetSourceNegateMask() const { return ReadBits(63,61); }; uint GetOMod() const { return ReadBits(60,59); } bool IsCompare() const { return ReadBits(25,17) < 255; } // opcodes 0-255 are vcmps. bool IsVOP3bOp() const { // NOTE: ISA Doc, section 6, claims that vcmp is vop3b. But AMD disassembler thinks its VOP3a // switch( GetOpcode() ) { case V_ADD_I32 : // : D.u = S0.u + S1.u; VCC=carry-out (VOP3:sgpr=carry-out). case V_SUB_I32 : // : D.u = S0.u - S1.u; VCC=carry-out (VOP3:sgpr=carry-out). case V_SUBREV_I32 : // : D.u = S1.u - S0.u; VCC=carry-out (VOP3:sgpr=carry-out). case V_ADDC_U32 : // : D.u = S0.u + S1.u + VCC; VCC=carry-out (VOP3:sgpr=carryout,S2.u=carry-in). case V_SUBB_U32 : // : D.u = S0.u - S1.u - VCC; VCC=carry-out (VOP3:sgpr=carry-out,S2.u=carry-in). case V_SUBBREV_U32 : // : D.u = S1.u - S0.u - VCC; VCC=carry-out (VOP3:sgpr=carryout,S2.u=carry-in). case V_DIV_SCALE_F32: // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. case V_DIV_SCALE_F64: // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. return true; default: return false; } } // VOP3a only uint GetSourceAbsMask() const { return ReadBits(10,8); } bool GetClamp() const { return ReadBit(11); } // VOP3b only Dests GetSDst() const { return Translate_SDest(ReadBits(14,8)); } }; class MUBUFFInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_MUBUFF; } BufferInstructions GetOpcode() const { return Translate_MUBUFFOpcodes(ReadBits(24,18)); } uint GetLength() const { return 8; } uint GetResultWidthInDWORDS() const ; uint GetOffset() const { return ReadBits(11,0); } Sources GetVAddr() const { return Translate_VSrc(ReadBits(39,32)); } Sources GetVData() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetSResource() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(52,48)); } Sources GetSOffset() const { return Translate_SSrc(ReadBits(63,56)); } bool IsOffN() const { return ReadBit(12); } bool IsIdxN() const { return ReadBit(13); } bool IsAddr64() const { return ReadBit(15); } bool IsDirectToLDS() const { return ReadBit(16); } bool GetSLCBit() const { return ReadBit(54); } bool GetGLCBit() const { return ReadBit(14); } bool GetTFEBit() const { return ReadBit(55); } }; class MTBUFFInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_MTBUFF; } BufferInstructions GetOpcode() const { return Translate_MTBUFFOpcodes(ReadBits(18,16)); } uint GetLength() const { return 8; } uint GetResultWidthInDWORDS() const ; TBufferNumberFormats GetNumberFormat() const { return Translate_MTBUFF_NumberFormat( ReadBits(25,23) ); } TBufferDataFormats GetDataFormat() const { return Translate_MTBUFF_DataFormat( ReadBits(22,19) ); } uint GetOffset() const { return ReadBits(11,0); } Sources GetVAddr() const { return Translate_VSrc(ReadBits(39,32)); } Sources GetVData() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetSResource() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(52,48)); } Sources GetSOffset() const { return Translate_SSrc(ReadBits(63,56)); } bool IsOffN() const { return ReadBit(12); } bool IsIdxN() const { return ReadBit(13); } bool IsAddr64() const { return ReadBit(15); } bool GetSLCBit() const { return ReadBit(54); } bool GetGLCBit() const { return ReadBit(14); } bool GetTFEBit() const { return ReadBit(55); } }; class MIMGInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_MIMG; } ImageInstructions GetOpcode() const { return Translate_MIMGOpcodes( ReadBits(24,18) ); } uint GetLength() const { return 8; } bool IsSLC() const { return ReadBit(25); } bool IsGLC() const { return ReadBit(13); } bool IsTFE() const { return ReadBit(16); } bool IsLWE() const { return ReadBit(17); } bool IsArray() const { return ReadBit(14); } bool IsUnormalized() const { return ReadBit(12); } bool IsRes256() const { return !ReadBit(15);}; uint GetDMask() const { return ReadBits(11,8); } Sources GetSSampler() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(57,53)); } Sources GetSResource() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(52,48)); } Sources GetVData() const { return Translate_VSrc( ReadBits(47,40) ); } Sources GetVAddr() const { return Translate_VSrc( ReadBits(39,32) ); } uint GetSamplerWidthInDWORDS() const; // 0, 4 uint GetResultWidthInDWORDS() const; }; class DSInstruction : public Instruction { public: uint GetOffset0() const { return ReadBits(7,0); } // Instructions can have one 16 bit offset field or two 8-bit offset fields uint GetOffset1() const { return ReadBits(15,8); } uint GetOffset16() const { return ReadBits(15,0); } DSInstructions GetOpcode() const { return Translate_DSOpcodes(ReadBits(25,18)); } Dests GetVDest() const { return Translate_VDest(ReadBits(63,56)); } Sources GetVData0() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetVData1() const { return Translate_VSrc(ReadBits(55,48)); } Sources GetVAddr() const { return Translate_VSrc(ReadBits(39,32)); } bool IsGDS() const { return ReadBit(17); } }; class EXPInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_EXP; } uint GetLength() const { return 8; } bool GetCompressBit() const { return ReadBit(10); } bool GetDoneBit() const { return ReadBit(11); } bool GetValidMaskBit() const { return ReadBit(12); } ExportTargets GetTarget() const { return Translate_EXPTarget(ReadBits(9,4)); } uint GetExportMask() const { return ReadBits(3,0); } Sources GetVSrc0() const { return Translate_VSrc(ReadBits(39,32)); } Sources GetVSrc1() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetVSrc2() const { return Translate_VSrc(ReadBits(55,48)); } Sources GetVSrc3() const { return Translate_VSrc(ReadBits(63,56)); } }; }} namespace GCN { InstructionFormat GCN1Decoder::ReadInstructionFormat( const uint8* pLocation ) { uint32 n = *((const uint32*)pLocation); // // The instruction format is inferred from magic numbers packed into the upper bits of the first DWORD // vop2 is 0....... // vop1 is 0111 111 // vopc is 0111 110 // sop2 is 10...... // sopK is 1011 ....... // sopc is 1011 1111 0 // sopp is 1011 1111 1 // sop1 is 1011 1110 1 // vinterp is 1100 10 // smrd is 1100 0 // vop3 is 1101 00 // flat is 1101 11 // ds is 1101 10 // mubuff is 1110 00 // mtbuff is 1110 10 // mimg is 1111 00 // exp is 1111 10 switch( n & (0xFF800000) ) // 1111 1111 1000 ... (9 bit) { case 0xBF000000: return IF_SOPC; // 1011 1111 0.... case 0xBF800000: return IF_SOPP; // 1011 1111 1.... case 0xBE800000: return IF_SOP1; // 1011 1110 1.... default: switch( n & (0xFE000000) ) // 1111 1110 ... (7 bit) { case 0x7E000000: return IF_VOP1; // 0111 1110 ... case 0x7C000000: return IF_VOPC; // 0111 1100 ... default: switch( n & (0xFC000000) ) // 1111 1100 ... (6 bit) { case 0xC8000000: return IF_VINTERP; // 1100 10.. .... case 0xD0000000: return IF_VOP3; // 1101 00.. ... case 0xDC000000: return IF_FLAT; // 1101 11.. .... case 0xD8000000: return IF_DS; // 1101 10.. .... case 0xE0000000: return IF_MUBUFF; // 1110 00.. case 0xE8000000: return IF_MTBUFF; // 1110 10.. case 0xF0000000: return IF_MIMG; // 1111 00.. case 0xF8000000: return IF_EXP; // 1111 10.. default: switch( n & (0xF8000000) ) // 1111 1000 (5bit) { case 0xC0000000: return IF_SMRD; // 1100 0... .... case 0xB0000000: return IF_SOPK; // 1011 0......... case 0xB8000000: return IF_SOPK; // 1011 1......... default: if( (n & 0xC0000000) == 0x80000000 ) // 1100.... return IF_SOP2; // 1000 .... if( !(n & 0x80000000) ) return IF_VOP2; // 0...... } } } } return IF_UNKNOWN; } size_t GCN1Decoder::DetermineInstructionLength( const uint8* pLocation, InstructionFormat eEncoding ) { switch( eEncoding ) { case IF_VOP2: return ((const _GCN1Decoder_INTERNAL::VOP2Instruction*)pLocation)->GetLength(); case IF_VOP1: return ((const _GCN1Decoder_INTERNAL::VOP1Instruction*)pLocation)->GetLength(); case IF_VOPC: return ((const _GCN1Decoder_INTERNAL::VOPCInstruction*)pLocation)->GetLength(); case IF_SOP2: return ((const _GCN1Decoder_INTERNAL::SOP2Instruction*)pLocation)->GetLength(); case IF_SOPK: return ((const _GCN1Decoder_INTERNAL::SOPKInstruction*)pLocation)->GetLength(); case IF_SOP1: return ((const _GCN1Decoder_INTERNAL::SOP1Instruction*)pLocation)->GetLength(); case IF_SOPC: return ((const _GCN1Decoder_INTERNAL::SOPCInstruction*)pLocation)->GetLength(); case IF_SMRD: return ((const _GCN1Decoder_INTERNAL::SMRDInstruction*)pLocation)->GetLength(); case IF_SOPP: case IF_VINTERP: return 4; case IF_DS: case IF_VOP3: case IF_MTBUFF: case IF_MUBUFF: case IF_MIMG: case IF_EXP: case IF_FLAT: return 8; case IF_UNKNOWN: default: return 0; } } void GCN1Decoder::Decode( Instruction* pInst, const uint8* pLocation, InstructionFormat eEncoding ) { memset(pInst,0,sizeof(*pInst)); switch( eEncoding ) { case IF_SOP2: case IF_SOPK: case IF_SOP1: case IF_SOPC: case IF_SOPP: pInst->m_eClass = IC_SCALAR; break; case IF_SMRD: pInst->m_eClass = IC_SCALAR_MEM; break; case IF_VOP2: case IF_VOP1: case IF_VOPC: case IF_VOP3: pInst->m_eClass = IC_VECTOR; break; case IF_VINTERP: pInst->m_eClass = IC_VECTOR_INTERP; break; case IF_DS: pInst->m_eClass = IC_DS; break; case IF_MTBUFF: case IF_MUBUFF: pInst->m_eClass = IC_BUFFER; break; case IF_MIMG: pInst->m_eClass = IC_IMAGE; break; case IF_EXP: pInst->m_eClass = IC_EXPORT; break; case IF_FLAT: case IF_UNKNOWN: default: pInst->m_eClass = IC_INVALID; } using namespace _GCN1Decoder_INTERNAL; switch( eEncoding ) { case IF_SOP2: { auto* pIt = (const SOP2Instruction*)pLocation; auto& Fields = pInst->Fields.Scalar; pInst->m_eClass = IC_SCALAR; Fields.m_Dest = pIt->GetDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSourceCount = 2; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetSrc1(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_SOPK: { auto* pIt = (const SOPKInstruction*) pLocation; auto& Fields = pInst->Fields.Scalar; Fields.m_Dest = pIt->GetDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSourceCount = 0; Fields.m_nSIMM16 = pIt->ReadSIMM16(); Fields.m_pBranchTarget = pIt->GetBranchTarget(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_SOP1: { auto* pIt = (const SOP1Instruction*) pLocation; auto& Fields = pInst->Fields.Scalar; Fields.m_Dest = pIt->GetDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSourceCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); if( pIt->HasLiteral()) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_SOPC: { auto* pIt = (const SOPCInstruction*) pLocation; auto& Fields = pInst->Fields.Scalar; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_Dest = pIt->GetDest(); Fields.m_nSourceCount = 2; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetSrc1(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_SOPP: { auto* pIt = (const SOPPInstruction*) pLocation; auto& Fields = pInst->Fields.Scalar; Fields.m_eOpcode= pIt->GetOpcode(); Fields.m_Dest = DEST_INVALID; Fields.m_nSourceCount = 0; Fields.m_nSIMM16 = pIt->ReadSIMM16(); Fields.m_pBranchTarget = pIt->GetBranchTarget(); } break; case IF_SMRD: { auto* pIt = (const SMRDInstruction*) pLocation; auto& Fields = pInst->Fields.ScalarMem; Fields.m_bIsOffsetIMM = pIt->IsOffsetIMM(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_Dest = pIt->GetDest(); Fields.m_nBaseReg = pIt->GetBase(); Fields.m_nOffset = pIt->GetOffset(); Fields.m_bIsGLC = false; } break; case IF_VOP2: { auto* pIt = (const VOP2Instruction*) pLocation; auto& Fields = pInst->Fields.Vector; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSrcCount = 2; Fields.m_nDestCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetVSrc1(); Fields.m_Dests[0] = pIt->GetVDst(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_VOP1: { auto* pIt = (const VOP1Instruction*) pLocation; auto& Fields = pInst->Fields.Vector; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSrcCount = 1; Fields.m_nDestCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Dests[0] = pIt->GetDst(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_VOPC: { auto* pIt = (const VOPCInstruction*) pLocation; auto& Fields = pInst->Fields.Vector; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSrcCount = 2; Fields.m_nDestCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetVSrc1(); Fields.m_Dests[0] = DEST_VCC; if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_VOP3: { auto* pIt = (const VOP3Instruction*) pLocation; auto& Fields = pInst->Fields.Vector; Fields.m_eOpcode = pIt->GetOpcode(); if( pIt->IsVOP3bOp() ) { Fields.m_nDestCount = 2; Fields.m_Dests[0] = pIt->GetVDst(); Fields.m_Dests[1] = pIt->GetSDst(); } else { Fields.m_nDestCount = 1; Fields.m_Dests[0] = pIt->GetVDst(); Fields.m_nClamp = pIt->GetClamp(); Fields.m_nSourceAbs = pIt->GetSourceAbsMask(); } Fields.m_nSourceNegate= pIt->GetSourceNegateMask(); Fields.m_nOMOD = pIt->GetOMod(); Fields.m_nSrcCount = GetSourceCountForInstruction( Fields.m_eOpcode ); Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetSrc1(); Fields.m_Sources[2] = pIt->GetSrc2(); } break; case IF_VINTERP: { auto* pIt = (const VINTERPInstruction*) pLocation; auto& Fields = pInst->Fields.Interp; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nAttributeChannel = pIt->GetAttributeChannel(); Fields.m_nAttributeIndex = pIt->GetAttributeIndex(); Fields.m_VDst = pIt->GetVDst(); Fields.m_VSrc = pIt->GetVSrc0(); } break; case IF_EXP: { auto* pIt = (const EXPInstruction*) pLocation; auto& Fields = pInst->Fields.Export; Fields.m_ChannelMask = pIt->GetExportMask(); Fields.m_Compress = pIt->GetCompressBit(); Fields.m_Done = pIt->GetDoneBit(); Fields.m_eTarget = pIt->GetTarget(); Fields.m_ValidMask = pIt->GetValidMaskBit(); Fields.m_Sources[0] = pIt->GetVSrc0(); Fields.m_Sources[1] = pIt->GetVSrc1(); Fields.m_Sources[2] = pIt->GetVSrc2(); Fields.m_Sources[3] = pIt->GetVSrc3(); } break; case IF_DS: { auto* pIt = (const DSInstruction*) pLocation; auto& Fields = pInst->Fields.DS; Fields.m_bGDS = pIt->IsGDS(); Fields.m_Dest = pIt->GetVDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nOffset0 = pIt->GetOffset0(); Fields.m_nOffset1 = pIt->GetOffset1(); Fields.m_nOffset16 = pIt->GetOffset16(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData0 = pIt->GetVData0(); Fields.m_VData1 = pIt->GetVData1(); } break; case IF_MTBUFF: { auto* pIt = (const MTBUFFInstruction*) pLocation; auto& Fields = pInst->Fields.Buffer; Fields.m_bAddr64 = pIt->IsAddr64(); Fields.m_bGLC = pIt->GetGLCBit(); Fields.m_bIdxN = pIt->IsIdxN(); Fields.m_bLDSDirect = 0; Fields.m_bOffN = pIt->IsOffN(); Fields.m_bSLC = pIt->GetSLCBit(); Fields.m_bTFE = pIt->GetTFEBit(); Fields.m_eDataFormat = pIt->GetDataFormat(); Fields.m_eNumberFormat = pIt->GetNumberFormat(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nOffset = pIt->GetOffset(); Fields.m_SOffset = pIt->GetSOffset(); Fields.m_SResource = pIt->GetSResource(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData = pIt->GetVData(); } break; case IF_MUBUFF: { auto* pIt = (const MUBUFFInstruction*) pLocation; auto& Fields = pInst->Fields.Buffer; Fields.m_bAddr64 = pIt->IsAddr64(); Fields.m_bGLC = pIt->GetGLCBit(); Fields.m_bIdxN = pIt->IsIdxN(); Fields.m_bLDSDirect = pIt->IsDirectToLDS(); Fields.m_bOffN = pIt->IsOffN(); Fields.m_bSLC = pIt->GetSLCBit(); Fields.m_bTFE = pIt->GetTFEBit(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nOffset = pIt->GetOffset(); Fields.m_SOffset = pIt->GetSOffset(); Fields.m_SResource = pIt->GetSResource(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData = pIt->GetVData(); } break; case IF_MIMG: { auto* pIt = (const MIMGInstruction*) pLocation; auto& Fields = pInst->Fields.Image; Fields.m_bArray = pIt->IsArray(); Fields.m_bGLC = pIt->IsGLC(); Fields.m_bLWE = pIt->IsLWE(); Fields.m_bRes256 = pIt->IsRes256(); Fields.m_bSLC = pIt->IsSLC(); Fields.m_bTFE = pIt->IsTFE(); Fields.m_bUnnormalized = pIt->IsUnormalized(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nDMask = pIt->GetDMask(); Fields.m_SResource = pIt->GetSResource(); Fields.m_SSampler = pIt->GetSSampler(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData = pIt->GetVData(); Fields.m_bIsD16 = 0; } break; case IF_FLAT: default: return; } } } ================================================ FILE: src/Wrapper/GCN1Decoder.h ================================================ // // Decoder for early GCN chips (SI and CI) // // Copyright 2015 Joshua Barczak, all rights reserved. // #ifndef _GCN1_DECODER_H_ #define _GCN1_DECODER_H_ #pragma once #include "GCNDecoder.h" namespace GCN { class GCN1Decoder : public IDecoder { public: virtual InstructionFormat ReadInstructionFormat( const uint8* pLocation ); virtual size_t DetermineInstructionLength( const uint8* pLocation, InstructionFormat eEncoding ); virtual void Decode( Instruction* pInst, const uint8* pLocation, InstructionFormat eEncoding ) ; }; } #endif ================================================ FILE: src/Wrapper/GCN3Decoder.cpp ================================================ #pragma unmanaged #include "GCNEnums.h" #include "GCNIsa.h" #include "GCN3Decoder.h" #include #include namespace GCN{ namespace _GCN3Decoder_INTERNAL { struct EnumLUT { uint eEnum; uint nEncoding; }; static uint LUTLookup( const EnumLUT* pLUT, size_t nLUTSize,uint en, uint TInvalid ) { size_t n = nLUTSize/sizeof(EnumLUT); for( size_t i=0; i S1.i). ENUM( S_CMP_GE_I32 ,3 ) //: SCC = (S0.i >= S1.i). ENUM( S_CMP_LT_I32 ,4 ) //: SCC = (S0.i < S1.i). ENUM( S_CMP_LE_I32 ,5 ) //: SCC = (S0.i <= S1.i). ENUM( S_CMP_EQ_U32 ,6 ) //: SCC = (S0.u == S1.u). ENUM( S_CMP_LG_U32 ,7 ) //: SCC = (S0.u != S1.u). ENUM( S_CMP_GT_U32 ,8 ) //: SCC = (S0.u > S1.u). ENUM( S_CMP_GE_U32 ,9 ) //: SCC = (S0.u >= S1.u). ENUM( S_CMP_LT_U32 ,10) //: SCC = (S0.u < S1.u). ENUM( S_CMP_LE_U32 ,11) //: SCC = (S0.u <= S1.u). ENUM( S_BITCMP0_B32 ,12) //: SCC = (S0.u[S1.u[4:0]] == 0). ENUM( S_BITCMP1_B32 ,13) //: SCC = (S0.u[S1.u[4:0]] == 1). ENUM( S_BITCMP0_B64 ,14) //: SCC = (S0.u[S1.u[5:0]] == 0). ENUM( S_BITCMP1_B64 ,15) //: SCC = (S0.u[S1.u[5:0]] == 1). ENUM( S_SETVSKIP ,16) //: VSKIP = S0.u[S1.u[4:0]]. ENUM( S_SET_GPR_IDX_ON , 17 ) ENUM( S_CMP_EQ_U64 , 18 ) ENUM( S_CMP_NE_U64 , 19 ) END_TRANSLATOR(ScalarInstructions,SOPCOpcodes,S_INVALID) BEGIN_TRANSLATOR(ScalarInstructions,SOPPOpcodes) ENUM(S_NOP ,0 ) //: do nothing. Repeat NOP 1..8 times based on SIMM16[2:0]. 0 = 1 time, 7 = 8 times. ENUM(S_ENDPGM ,1 ) //: end of program; terminate wavefront. ENUM(S_BRANCH ,2 ) //: PC = PC + signext(SIMM16 * 4) + 4. ENUM(S_CBRANCH_SCC0 ,4 ) //: if(SCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_SCC1 ,5 ) //: if(SCC == 1) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_VCCZ ,6 ) //: if(VCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_VCCNZ ,7 ) //: if(VCC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_EXECZ ,8 ) //: if(EXEC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_CBRANCH_EXECNZ ,9 ) //: if(EXEC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. ENUM(S_BARRIER ,10 ) //: Sync waves within a thread group. ENUM(S_SETKILL ,11 ) ENUM(S_WAITCNT ,12 ) //: Wait for count of outstanding lds, vector-memory and ENUM(S_SETHALT ,13 ) //: set HALT bit to value of SIMM16[0]. 1=halt, 0=resume. Halt is ignored while priv=1. ENUM(S_SLEEP ,14 ) //: Cause a wave to sleep for approximately 64*SIMM16[2:0] clocks. ENUM(S_SETPRIO ,15 ) //: User settable wave priority. 0 = lowest, 3 = highest. ENUM(S_SENDMSG ,16 ) //: Send a message. ENUM(S_SENDMSGHALT ,17 ) //: Send a message and then HALT. ENUM(S_TRAP ,18 ) //: Enter the trap handler. TrapID = SIMM16[7:0]. Wait for all instructions to complete, ENUM(S_ICACHE_INV ,19 ) //: Invalidate entire L1 I cache. ENUM(S_INCPERFLEVEL ,20 ) //: Increment performance counter specified in SIMM16[3:0] by 1. ENUM(S_DECPERFLEVEL ,21 ) //: Decrement performance counter specified in SIMM16[3:0] by 1. ENUM(S_TTRACEDATA ,22 ) //: Send M0 as user data to thread-trace. ENUM(S_CBRANCH_CDBGSYS ,23 )// : If (conditional_debug_system != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. ENUM(S_CBRANCH_CDBGUSER ,24 )// : If (conditional_debug_user != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. ENUM(S_CBRANCH_CDBGSYS_OR_USER ,25 )// : If (conditional_debug_system || conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. ENUM(S_CBRANCH_CDBGSYS_AND_USER ,26 )// : If (conditional_debug_system && conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. ENUM( S_ENDPGM_SAVED , 27 ) ENUM( S_SET_GPR_IDX_OFF , 28 ) ENUM( S_SET_GPR_IDX_MODE , 29 ) END_TRANSLATOR(ScalarInstructions,SOPPOpcodes,S_INVALID) BEGIN_TRANSLATOR(ScalarMemoryInstructions,SMEMOpcodes) ENUM( S_LOAD_DWORD , 0 ) ENUM( S_LOAD_DWORDX2 , 1 ) ENUM( S_LOAD_DWORDX4 , 2 ) ENUM( S_LOAD_DWORDX8 , 3 ) ENUM( S_LOAD_DWORDX16 , 4 ) ENUM( S_BUFFER_LOAD_DWORD , 8 ) ENUM( S_BUFFER_LOAD_DWORDX2 , 9 ) ENUM( S_BUFFER_LOAD_DWORDX4 , 10 ) ENUM( S_BUFFER_LOAD_DWORDX8 , 11 ) ENUM( S_BUFFER_LOAD_DWORDX16 , 12 ) ENUM( S_STORE_DWORD , 16 ) ENUM( S_STORE_DWORDX2 , 17 ) ENUM( S_STORE_DWORDX4 , 18 ) ENUM( S_BUFFER_STORE_DWORD , 24 ) ENUM( S_BUFFER_STORE_DWORDX2 , 25 ) ENUM( S_BUFFER_STORE_DWORDX4 , 26 ) ENUM( S_DCACHE_INV , 32 ) ENUM( S_DCACHE_WB , 33 ) ENUM( S_DCACHE_INV_VOL , 34 ) ENUM( S_DCACHE_WB_VOL , 35 ) ENUM( S_MEMTIME , 36 ) ENUM( S_MEMREALTIME , 37 ) ENUM( S_ATC_PROBE , 38 ) ENUM( S_ATC_PROBE_BUFFER , 39 ) END_TRANSLATOR(ScalarMemoryInstructions,SMEMOpcodes,S_INVALID) BEGIN_TRANSLATOR(VectorInstructions,VOP2Opcodes) ENUM( V_CNDMASK_B32 , 0 ) ENUM( V_ADD_F32 , 1 ) ENUM( V_SUB_F32 , 2 ) ENUM( V_SUBREV_F32 , 3 ) ENUM( V_MUL_LEGACY_F32 , 4 ) ENUM( V_MUL_F32 , 5 ) ENUM( V_MUL_I32_I24 , 6 ) ENUM( V_MUL_HI_I32_I24 , 7 ) ENUM( V_MUL_U32_U24 , 8 ) ENUM( V_MUL_HI_U32_U24 , 9 ) ENUM( V_MIN_F32 , 10 ) ENUM( V_MAX_F32 , 11 ) ENUM( V_MIN_I32 , 12 ) ENUM( V_MAX_I32 , 13 ) ENUM( V_MIN_U32 , 14 ) ENUM( V_MAX_U32 , 15 ) ENUM( V_LSHRREV_B32 , 16 ) ENUM( V_ASHRREV_I32 , 17 ) ENUM( V_LSHLREV_B32 , 18 ) ENUM( V_AND_B32 , 19 ) ENUM( V_OR_B32 , 20 ) ENUM( V_XOR_B32 , 21 ) ENUM( V_MAC_F32 , 22 ) ENUM( V_MADMK_F32 , 23 ) ENUM( V_MADAK_F32 , 24 ) ENUM( V_ADD_U32 , 25 ) ENUM( V_SUB_U32 , 26 ) ENUM( V_SUBREV_U32 , 27 ) ENUM( V_ADDC_U32 , 28 ) ENUM( V_SUBB_U32 , 29 ) ENUM( V_SUBBREV_U32 , 30 ) ENUM( V_ADD_F16 , 31 ) ENUM( V_SUB_F16 , 32 ) ENUM( V_SUBREV_F16 , 33 ) ENUM( V_MUL_F16 , 34 ) ENUM( V_MAC_F16 , 35 ) ENUM( V_MADMK_F16 , 36 ) ENUM( V_MADAK_F16 , 37 ) ENUM( V_ADD_U16 , 38 ) ENUM( V_SUB_U16 , 39 ) ENUM( V_SUBREV_U16 , 40 ) ENUM( V_MUL_LO_U16 , 41 ) ENUM( V_LSHLREV_B16 , 42 ) ENUM( V_LSHRREV_B16 , 43 ) ENUM( V_ASHRREV_I16 , 44 ) ENUM( V_MAX_F16 , 45 ) ENUM( V_MIN_F16 , 46 ) ENUM( V_MAX_U16 , 47 ) ENUM( V_MAX_I16 , 48 ) ENUM( V_MIN_U16 , 49 ) ENUM( V_MIN_I16 , 50 ) ENUM( V_LDEXP_F16 , 51 ) END_TRANSLATOR(VectorInstructions,VOP2Opcodes,V_INVALID) BEGIN_TRANSLATOR(VectorInstructions,VOP1Opcodes) ENUM( V_NOP , 0 ) ENUM( V_MOV_B32 , 1 ) ENUM( V_READFIRSTLANE_B32 , 2 ) ENUM( V_CVT_I32_F64 , 3 ) ENUM( V_CVT_F64_I32 , 4 ) ENUM( V_CVT_F32_I32 , 5 ) ENUM( V_CVT_F32_U32 , 6 ) ENUM( V_CVT_U32_F32 , 7 ) ENUM( V_CVT_I32_F32 , 8 ) ENUM( V_CVT_F16_F32 , 10 ) ENUM( V_CVT_F32_F16 , 11 ) ENUM( V_CVT_RPI_I32_F32 , 12 ) ENUM( V_CVT_FLR_I32_F32 , 13 ) ENUM( V_CVT_OFF_F32_I4 , 14 ) ENUM( V_CVT_F32_F64 , 15 ) ENUM( V_CVT_F64_F32 , 16 ) ENUM( V_CVT_F32_UBYTE0 , 17 ) ENUM( V_CVT_F32_UBYTE1 , 18 ) ENUM( V_CVT_F32_UBYTE2 , 19 ) ENUM( V_CVT_F32_UBYTE3 , 20 ) ENUM( V_CVT_U32_F64 , 21 ) ENUM( V_CVT_F64_U32 , 22 ) ENUM( V_TRUNC_F64 , 23 ) ENUM( V_CEIL_F64 , 24 ) ENUM( V_RNDNE_F64 , 25 ) ENUM( V_FLOOR_F64 , 26 ) ENUM( V_FRACT_F32 , 27 ) ENUM( V_TRUNC_F32 , 28 ) ENUM( V_CEIL_F32 , 29 ) ENUM( V_RNDNE_F32 , 30 ) ENUM( V_FLOOR_F32 , 31 ) ENUM( V_EXP_F32 , 32 ) ENUM( V_LOG_F32 , 33 ) ENUM( V_RCP_F32 , 34 ) ENUM( V_RCP_IFLAG_F32 , 35 ) ENUM( V_RSQ_F32 , 36 ) ENUM( V_RCP_F64 , 37 ) ENUM( V_RSQ_F64 , 38 ) ENUM( V_SQRT_F32 , 39 ) ENUM( V_SQRT_F64 , 40 ) ENUM( V_SIN_F32 , 41 ) ENUM( V_COS_F32 , 42 ) ENUM( V_NOT_B32 , 43 ) ENUM( V_BFREV_B32 , 44 ) ENUM( V_FFBH_U32 , 45 ) ENUM( V_FFBL_B32 , 46 ) ENUM( V_FFBH_I32 , 47 ) ENUM( V_FREXP_EXP_I32_F64 , 48 ) ENUM( V_FREXP_MANT_F64 , 49 ) ENUM( V_FRACT_F64 , 50 ) ENUM( V_FREXP_EXP_I32_F32 , 51 ) ENUM( V_FREXP_MANT_F32 , 52 ) ENUM( V_CLREXCP , 53 ) ENUM( V_MOVRELD_B32 , 54 ) ENUM( V_MOVRELS_B32 , 55 ) ENUM( V_MOVRELSD_B32 , 56 ) ENUM( V_CVT_F16_U16 , 57 ) ENUM( V_CVT_F16_I16 , 58 ) ENUM( V_CVT_U16_F16 , 59 ) ENUM( V_CVT_I16_F16 , 60 ) ENUM( V_RCP_F16 , 61 ) ENUM( V_SQRT_F16 , 62 ) ENUM( V_RSQ_F16 , 63 ) ENUM( V_LOG_F16 , 64 ) ENUM( V_EXP_F16 , 65 ) ENUM( V_FREXP_MANT_F16 , 66 ) ENUM( V_FREXP_EXP_I16_F16 , 67 ) ENUM( V_FLOOR_F16 , 68 ) ENUM( V_CEIL_F16 , 69 ) ENUM( V_TRUNC_F16 , 70 ) ENUM( V_RNDNE_F16 , 71 ) ENUM( V_FRACT_F16 , 72 ) ENUM( V_SIN_F16 , 73 ) ENUM( V_COS_F16 , 74 ) ENUM( V_EXP_LEGACY_F32 , 75 ) ENUM( V_LOG_LEGACY_F32 , 76 ) END_TRANSLATOR(VectorInstructions,VOP1Opcodes,V_INVALID) static VectorInstructions Translate_VOPCOpcodes( uint n ) { switch( n & 0xf0 ) { case 0x10: switch( n & 0xf ) { case 0: return V_CMP_CLASS_F32; case 1: return V_CMPX_CLASS_F32; case 2: return V_CMP_CLASS_F64; case 3: return V_CMPX_CLASS_F64; case 4: return V_CMP_CLASS_F16; case 5: return V_CMPX_CLASS_F16; } case 0X20: return (VectorInstructions)( V_CMP_F_F16 + (n&0xf)); case 0x30: return (VectorInstructions)( V_CMPX_F_F16 + (n&0xf)); case 0x40: return (VectorInstructions)( V_CMP_F_F32 + (n&0xf)); case 0x50: return (VectorInstructions)( V_CMPX_F_F32 + (n&0xf)); case 0x60: return (VectorInstructions)( V_CMP_F_F64 + (n&0xf)); case 0x70: return (VectorInstructions)( V_CMPX_F_F64 + (n&0xf)); default: switch( n&0xf8 ) { case 0xA0: return (VectorInstructions)( V_CMP_F_I16 + (n&0x7)); case 0xA8: return (VectorInstructions)( V_CMP_F_U16 + (n&0x7)); case 0xB0: return (VectorInstructions)( V_CMPx_F_I16 + (n&0x7)); case 0xB8: return (VectorInstructions)( V_CMPx_F_U16 + (n&0x7)); case 0xC0: return (VectorInstructions)( V_CMP_F_I32 + (n&0x7)); case 0xC8: return (VectorInstructions)( V_CMP_F_U32 + (n&0x7)); case 0xD0: return (VectorInstructions)( V_CMPX_F_I32 + (n&0x7)); case 0xD8: return (VectorInstructions)( V_CMPX_F_U32 + (n&0x7)); case 0xE0: return (VectorInstructions)( V_CMP_F_I64 + (n&0x7)); case 0xE8: return (VectorInstructions)( V_CMP_F_U64 + (n&0x7)); case 0xF0: return (VectorInstructions)( V_CMPX_F_I64 + (n&0x7)); case 0xF8: return (VectorInstructions)( V_CMPx_F_U64 + (n&0x7)); } } return V_INVALID; } BEGIN_TRANSLATOR(VectorInstructions,VOP3OpcodesExtra) ENUM( V_MAD_LEGACY_F32 , 448 ) ENUM( V_MAD_F32 , 449 ) ENUM( V_MAD_I32_I24 , 450 ) ENUM( V_MAD_U32_U24 , 451 ) ENUM( V_CUBEID_F32 , 452 ) ENUM( V_CUBESC_F32 , 453 ) ENUM( V_CUBETC_F32 , 454 ) ENUM( V_CUBEMA_F32 , 455 ) ENUM( V_BFE_U32 , 456 ) ENUM( V_BFE_I32 , 457 ) ENUM( V_BFI_B32 , 458 ) ENUM( V_FMA_F32 , 459 ) ENUM( V_FMA_F64 , 460 ) ENUM( V_LERP_U8 , 461 ) ENUM( V_ALIGNBIT_B32 , 462 ) ENUM( V_ALIGNBYTE_B32 , 463 ) ENUM( V_MIN3_F32 , 464 ) ENUM( V_MIN3_I32 , 465 ) ENUM( V_MIN3_U32 , 466 ) ENUM( V_MAX3_F32 , 467 ) ENUM( V_MAX3_I32 , 468 ) ENUM( V_MAX3_U32 , 469 ) ENUM( V_MED3_F32 , 470 ) ENUM( V_MED3_I32 , 471 ) ENUM( V_MED3_U32 , 472 ) ENUM( V_SAD_U8 , 473 ) ENUM( V_SAD_HI_U8 , 474 ) ENUM( V_SAD_U16 , 475 ) ENUM( V_SAD_U32 , 476 ) ENUM( V_CVT_PK_U8_F32 , 477 ) ENUM( V_DIV_FIXUP_F32 , 478 ) ENUM( V_DIV_FIXUP_F64 , 479 ) ENUM( V_DIV_SCALE_F32 , 480 ) ENUM( V_DIV_SCALE_F64 , 481 ) ENUM( V_DIV_FMAS_F32 , 482 ) ENUM( V_DIV_FMAS_F64 , 483 ) ENUM( V_MSAD_U8 , 484 ) ENUM( V_QSAD_PK_U16_U8 , 485 ) ENUM( V_MQSAD_PK_U16_U8 , 486 ) ENUM( V_MQSAD_U32_U8 , 487 ) ENUM( V_MAD_U64_U32 , 488 ) ENUM( V_MAD_I64_I32 , 489 ) ENUM( V_MAD_F16 , 490 ) ENUM( V_MAD_U16 , 491 ) ENUM( V_MAD_I16 , 492 ) ENUM( V_PERM_B32 , 493 ) ENUM( V_FMA_F16 , 494 ) ENUM( V_DIV_FIXUP_F16 , 495 ) ENUM( V_CVT_PKACCUM_U8_F32 , 496 ) ENUM( V_INTERP_P1_F32 , 624 ) ENUM( V_INTERP_P2_F32 , 625 ) ENUM( V_INTERP_MOV_F32 , 626 ) ENUM( V_INTERP_P1LL_F16 , 628 ) ENUM( V_INTERP_P1LV_F16 , 629 ) ENUM( V_INTERP_P2_F16 , 630 ) ENUM( V_ADD_F64 , 640 ) ENUM( V_MUL_F64 , 641 ) ENUM( V_MIN_F64 , 642 ) ENUM( V_MAX_F64 , 643 ) ENUM( V_LDEXP_F64 , 644 ) ENUM( V_MUL_LO_U32 , 645 ) ENUM( V_MUL_HI_U32 , 646 ) ENUM( V_MUL_HI_I32 , 647 ) ENUM( V_LDEXP_F32 , 648 ) ENUM( V_READLANE_B32 , 649 ) ENUM( V_WRITELANE_B32 , 650 ) ENUM( V_BCNT_U32_B32 , 651 ) ENUM( V_MBCNT_LO_U32_B32 , 652 ) ENUM( V_MBCNT_HI_U32_B32 , 653 ) ENUM( V_LSHLREV_B64 , 655 ) ENUM( V_LSHRREV_B64 , 656 ) ENUM( V_ASHRREV_I64 , 657 ) ENUM( V_TRIG_PREOP_F64 , 658 ) ENUM( V_BFM_B32 , 659 ) ENUM( V_CVT_PKNORM_I16_F32 , 660 ) ENUM( V_CVT_PKNORM_U16_F32 , 661 ) ENUM( V_CVT_PKRTZ_F16_F32 , 662 ) ENUM( V_CVT_PK_U16_U32 , 663 ) ENUM( V_CVT_PK_I16_I32 , 664 ) END_TRANSLATOR(VectorInstructions,VOP3OpcodesExtra,V_INVALID) static VectorInstructions Translate_VOP3Opcodes( uint n ) { if( n <= 255 ) return Translate_VOPCOpcodes(n); if( n >= 256 && n <= 319 ) return Translate_VOP2Opcodes(n-256); if( n >= 320 && n <= 447 ) return Translate_VOP1Opcodes(n-320); return Translate_VOP3OpcodesExtra(n); } static VectorInstructions Translate_VINTERPOpcodes( uint n ) { switch(n) { case 0: return V_INTERP_P1_F32 ; // : D = P10 * S + P0; parameter interpolation. case 1: return V_INTERP_P2_F32 ; // : D = P20 * S + D; parameter interpolation. case 2: return V_INTERP_MOV_F32 ; // : D = {P10,P20,P0}[S]; parameter load. default: return V_INVALID; } } BEGIN_TRANSLATOR(DSInstructions,DSOpcodes) ENUM( DS_ADD_U32 , 0 ) ENUM( DS_SUB_U32 , 1 ) ENUM( DS_RSUB_U32 , 2 ) ENUM( DS_INC_U32 , 3 ) ENUM( DS_DEC_U32 , 4 ) ENUM( DS_MIN_I32 , 5 ) ENUM( DS_MAX_I32 , 6 ) ENUM( DS_MIN_U32 , 7 ) ENUM( DS_MAX_U32 , 8 ) ENUM( DS_AND_B32 , 9 ) ENUM( DS_OR_B32 , 10 ) ENUM( DS_XOR_B32 , 11 ) ENUM( DS_MSKOR_B32 , 12 ) ENUM( DS_WRITE_B32 , 13 ) ENUM( DS_WRITE2_B32 , 14 ) ENUM( DS_WRITE2ST64_B32 , 15 ) ENUM( DS_CMPST_B32 , 16 ) ENUM( DS_CMPST_F32 , 17 ) ENUM( DS_MIN_F32 , 18 ) ENUM( DS_MAX_F32 , 19 ) ENUM( DS_NOP , 20 ) ENUM( DS_ADD_F32 , 21 ) ENUM( DS_WRITE_B8 , 30 ) ENUM( DS_WRITE_B16 , 31 ) ENUM( DS_ADD_RTN_U32 , 32 ) ENUM( DS_SUB_RTN_U32 , 33 ) ENUM( DS_RSUB_RTN_U32 , 34 ) ENUM( DS_INC_RTN_U32 , 35 ) ENUM( DS_DEC_RTN_U32 , 36 ) ENUM( DS_MIN_RTN_I32 , 37 ) ENUM( DS_MAX_RTN_I32 , 38 ) ENUM( DS_MIN_RTN_U32 , 39 ) ENUM( DS_MAX_RTN_U32 , 40 ) ENUM( DS_AND_RTN_B32 , 41 ) ENUM( DS_OR_RTN_B32 , 42 ) ENUM( DS_XOR_RTN_B32 , 43 ) ENUM( DS_MSKOR_RTN_B32 , 44 ) ENUM( DS_WRXCHG_RTN_B32 , 45 ) ENUM( DS_WRXCHG2_RTN_B32 , 46 ) ENUM( DS_WRXCHG2ST64_RTN_B32 , 47 ) ENUM( DS_CMPST_RTN_B32 , 48 ) ENUM( DS_CMPST_RTN_F32 , 49 ) ENUM( DS_MIN_RTN_F32 , 50 ) ENUM( DS_MAX_RTN_F32 , 51 ) ENUM( DS_WRAP_RTN_B32 , 52 ) ENUM( DS_SWIZZLE_B32 , 61 ) ENUM( DS_READ_B32 , 54 ) ENUM( DS_READ2_B32 , 55 ) ENUM( DS_READ2ST64_B32 , 56 ) ENUM( DS_READ_I8 , 57 ) ENUM( DS_READ_U8 , 58 ) ENUM( DS_READ_I16 , 59 ) ENUM( DS_READ_U16 , 60 ) ENUM( DS_PERMUTE_B32 , 62 ) ENUM( DS_BPERMUTE_B32 , 63 ) ENUM( DS_ADD_U64 , 64 ) ENUM( DS_SUB_U64 , 65 ) ENUM( DS_RSUB_U64 , 66 ) ENUM( DS_INC_U64 , 67 ) ENUM( DS_DEC_U64 , 68 ) ENUM( DS_MIN_I64 , 69 ) ENUM( DS_MAX_I64 , 70 ) ENUM( DS_MIN_U64 , 71 ) ENUM( DS_MAX_U64 , 72 ) ENUM( DS_AND_B64 , 73 ) ENUM( DS_OR_B64 , 74 ) ENUM( DS_XOR_B64 , 75 ) ENUM( DS_MSKOR_B64 , 76 ) ENUM( DS_WRITE_B64 , 77 ) ENUM( DS_WRITE2_B64 , 78 ) ENUM( DS_WRITE2ST64_B64 , 79 ) ENUM( DS_CMPST_B64 , 80 ) ENUM( DS_CMPST_F64 , 81 ) ENUM( DS_MIN_F64 , 82 ) ENUM( DS_MAX_F64 , 83 ) ENUM( DS_ADD_RTN_U64 , 96 ) ENUM( DS_SUB_RTN_U64 , 97 ) ENUM( DS_RSUB_RTN_U64 , 98 ) ENUM( DS_INC_RTN_U64 , 99 ) ENUM( DS_DEC_RTN_U64 , 100 ) ENUM( DS_MIN_RTN_I64 , 101 ) ENUM( DS_MAX_RTN_I64 , 102 ) ENUM( DS_MIN_RTN_U64 , 103 ) ENUM( DS_MAX_RTN_U64 , 104 ) ENUM( DS_AND_RTN_B64 , 105 ) ENUM( DS_OR_RTN_B64 , 106 ) ENUM( DS_XOR_RTN_B64 , 107 ) ENUM( DS_MSKOR_RTN_B64 , 108 ) ENUM( DS_WRXCHG_RTN_B64 , 109 ) ENUM( DS_WRXCHG2_RTN_B64 , 110 ) ENUM( DS_WRXCHG2ST64_RTN_B64 , 111 ) ENUM( DS_CMPST_RTN_B64 , 112 ) ENUM( DS_CMPST_RTN_F64 , 113 ) ENUM( DS_MIN_RTN_F64 , 114 ) ENUM( DS_MAX_RTN_F64 , 115 ) ENUM( DS_READ_B64 , 118 ) ENUM( DS_READ2_B64 , 119 ) ENUM( DS_READ2ST64_B64 , 120 ) ENUM( DS_CONDXCHG32_RTN_B64 , 126 ) ENUM( DS_ADD_SRC2_U32 , 128 ) ENUM( DS_SUB_SRC2_U32 , 129 ) ENUM( DS_RSUB_SRC2_U32 , 130 ) ENUM( DS_INC_SRC2_U32 , 131 ) ENUM( DS_DEC_SRC2_U32 , 132 ) ENUM( DS_MIN_SRC2_I32 , 133 ) ENUM( DS_MAX_SRC2_I32 , 134 ) ENUM( DS_MIN_SRC2_U32 , 135 ) ENUM( DS_MAX_SRC2_U32 , 136 ) ENUM( DS_AND_SRC2_B32 , 137 ) ENUM( DS_OR_SRC2_B32 , 138 ) ENUM( DS_XOR_SRC2_B32 , 139 ) ENUM( DS_WRITE_SRC2_B32 , 140 ) ENUM( DS_MIN_SRC2_F32 , 146 ) ENUM( DS_MAX_SRC2_F32 , 147 ) ENUM( DS_GWS_SEMA_RELEASE_ALL , 152 ) ENUM( DS_GWS_INIT , 153 ) ENUM( DS_GWS_SEMA_V , 154 ) ENUM( DS_GWS_SEMA_BR , 155 ) ENUM( DS_GWS_SEMA_P , 156 ) ENUM( DS_GWS_BARRIER , 157 ) ENUM( DS_CONSUME , 189 ) ENUM( DS_APPEND , 190 ) ENUM( DS_ORDERED_COUNT , 191 ) ENUM( DS_ADD_SRC2_U64 , 192 ) ENUM( DS_SUB_SRC2_U64 , 193 ) ENUM( DS_RSUB_SRC2_U64 , 194 ) ENUM( DS_INC_SRC2_U64 , 195 ) ENUM( DS_DEC_SRC2_U64 , 196 ) ENUM( DS_MIN_SRC2_I64 , 197 ) ENUM( DS_MAX_SRC2_I64 , 198 ) ENUM( DS_MIN_SRC2_U64 , 199 ) ENUM( DS_MAX_SRC2_U64 , 200 ) ENUM( DS_AND_SRC2_B64 , 201 ) ENUM( DS_OR_SRC2_B64 , 202 ) ENUM( DS_XOR_SRC2_B64 , 203 ) ENUM( DS_WRITE_SRC2_B64 , 204 ) ENUM( DS_MIN_SRC2_F64 , 210 ) ENUM( DS_MAX_SRC2_F64 , 211 ) ENUM( DS_WRITE_B96 , 222 ) ENUM( DS_WRITE_B128 , 223 ) ENUM( DS_CONDXCHG32_RTN_B128 , 253 ) ENUM( DS_READ_B96 , 254 ) ENUM( DS_READ_B128 , 255 ) END_TRANSLATOR(DSInstructions,DSOpcodes,DS_INVALID) BEGIN_TRANSLATOR(BufferInstructions,MUBUFFOpcodes) ENUM(BUFFER_LOAD_FORMAT_X , 0 ) ENUM(BUFFER_LOAD_FORMAT_XY , 1 ) ENUM(BUFFER_LOAD_FORMAT_XYZ , 2 ) ENUM(BUFFER_LOAD_FORMAT_XYZW , 3 ) ENUM(BUFFER_STORE_FORMAT_X , 4 ) ENUM(BUFFER_STORE_FORMAT_XY , 5 ) ENUM(BUFFER_STORE_FORMAT_XYZ , 6 ) ENUM(BUFFER_STORE_FORMAT_XYZW , 7 ) ENUM(BUFFER_LOAD_FORMAT_D16_X , 8 ) ENUM(BUFFER_LOAD_FORMAT_D16_XY , 9 ) ENUM(BUFFER_LOAD_FORMAT_D16_XYZ , 10 ) ENUM(BUFFER_LOAD_FORMAT_D16_XYZW , 11 ) ENUM(BUFFER_STORE_FORMAT_D16_X , 12 ) ENUM(BUFFER_STORE_FORMAT_D16_XY , 13 ) ENUM(BUFFER_STORE_FORMAT_D16_XYZ , 14 ) ENUM(BUFFER_STORE_FORMAT_D16_XYZW, 15 ) ENUM(BUFFER_LOAD_UBYTE , 16 ) ENUM(BUFFER_LOAD_SBYTE , 17 ) ENUM(BUFFER_LOAD_USHORT , 18 ) ENUM(BUFFER_LOAD_SSHORT , 19 ) ENUM(BUFFER_LOAD_DWORD , 20 ) ENUM(BUFFER_LOAD_DWORDX2 , 21 ) ENUM(BUFFER_LOAD_DWORDX3 , 22 ) ENUM(BUFFER_LOAD_DWORDX4 , 23 ) ENUM(BUFFER_STORE_BYTE , 24 ) ENUM(BUFFER_STORE_SHORT , 26 ) ENUM(BUFFER_STORE_DWORD , 28 ) ENUM(BUFFER_STORE_DWORDX2 , 29 ) ENUM(BUFFER_STORE_DWORDX3 , 30 ) ENUM(BUFFER_STORE_DWORDX4 , 31 ) ENUM(BUFFER_STORE_LDS_DWORD , 61 ) ENUM(BUFFER_WBINVL1 , 62 ) ENUM(BUFFER_WBINVL1_VOL , 63 ) ENUM(BUFFER_ATOMIC_SWAP , 64 ) ENUM(BUFFER_ATOMIC_CMPSWAP , 65 ) ENUM(BUFFER_ATOMIC_ADD , 66 ) ENUM(BUFFER_ATOMIC_SUB , 67 ) ENUM(BUFFER_ATOMIC_SMIN , 68 ) ENUM(BUFFER_ATOMIC_UMIN , 69 ) ENUM(BUFFER_ATOMIC_SMAX , 70 ) ENUM(BUFFER_ATOMIC_UMAX , 71 ) ENUM(BUFFER_ATOMIC_AND , 72 ) ENUM(BUFFER_ATOMIC_OR , 73 ) ENUM(BUFFER_ATOMIC_XOR , 74 ) ENUM(BUFFER_ATOMIC_INC , 75 ) ENUM(BUFFER_ATOMIC_DEC , 76 ) ENUM(BUFFER_ATOMIC_SWAP_X2 , 96 ) ENUM(BUFFER_ATOMIC_CMPSWAP_X2 , 97 ) ENUM(BUFFER_ATOMIC_ADD_X2 , 98 ) ENUM(BUFFER_ATOMIC_SUB_X2 , 99 ) ENUM(BUFFER_ATOMIC_SMIN_X2 , 100) ENUM(BUFFER_ATOMIC_UMIN_X2 , 101) ENUM(BUFFER_ATOMIC_SMAX_X2 , 102) ENUM(BUFFER_ATOMIC_UMAX_X2 , 103) ENUM(BUFFER_ATOMIC_AND_X2 , 104) ENUM(BUFFER_ATOMIC_OR_X2 , 105) ENUM(BUFFER_ATOMIC_XOR_X2 , 106) ENUM(BUFFER_ATOMIC_INC_X2 , 107) ENUM(BUFFER_ATOMIC_DEC_X2 , 108) END_TRANSLATOR(BufferInstructions,MUBUFFOpcodes,BUFFER_INVALID) BEGIN_TRANSLATOR(BufferInstructions,MTBUFFOpcodes) ENUM( TBUFFER_LOAD_FORMAT_X , 0 ) ENUM( TBUFFER_LOAD_FORMAT_XY , 1 ) ENUM( TBUFFER_LOAD_FORMAT_XYZ , 2 ) ENUM( TBUFFER_LOAD_FORMAT_XYZW , 3 ) ENUM( TBUFFER_STORE_FORMAT_X , 4 ) ENUM( TBUFFER_STORE_FORMAT_XY , 5 ) ENUM( TBUFFER_STORE_FORMAT_XYZ , 6 ) ENUM( TBUFFER_STORE_FORMAT_XYZW , 7 ) ENUM( TBUFFER_LOAD_FORMAT_D16_X , 8 ) ENUM( TBUFFER_LOAD_FORMAT_D16_XY , 9 ) ENUM( TBUFFER_LOAD_FORMAT_D16_XYZ , 10 ) ENUM( TBUFFER_LOAD_FORMAT_D16_XYZW , 11 ) ENUM( TBUFFER_STORE_FORMAT_D16_X , 12 ) ENUM( TBUFFER_STORE_FORMAT_D16_XY , 13 ) ENUM( TBUFFER_STORE_FORMAT_D16_XYZ , 14 ) ENUM( TBUFFER_STORE_FORMAT_D16_XYZW , 15 ) END_TRANSLATOR(BufferInstructions,MTBUFFOpcodes,TBUFFER_INVALID) BEGIN_TRANSLATOR(ImageInstructions,MIMGOpcodes) ENUM( IMAGE_LOAD , 0 ) ENUM( IMAGE_LOAD_MIP , 1 ) ENUM( IMAGE_LOAD_PCK , 2 ) ENUM( IMAGE_LOAD_PCK_SGN , 3 ) ENUM( IMAGE_LOAD_MIP_PCK , 4 ) ENUM( IMAGE_LOAD_MIP_PCK_SGN , 5 ) ENUM( IMAGE_STORE , 8 ) ENUM( IMAGE_STORE_MIP , 9 ) ENUM( IMAGE_STORE_PCK , 10 ) ENUM( IMAGE_STORE_MIP_PCK , 11 ) ENUM( IMAGE_GET_RESINFO , 14 ) ENUM( IMAGE_ATOMIC_SWAP , 15 ) ENUM( IMAGE_ATOMIC_CMPSWAP , 16 ) ENUM( IMAGE_ATOMIC_ADD , 17 ) ENUM( IMAGE_ATOMIC_SUB , 18 ) ENUM( IMAGE_ATOMIC_SMIN , 20 ) ENUM( IMAGE_ATOMIC_UMIN , 21 ) ENUM( IMAGE_ATOMIC_SMAX , 22 ) ENUM( IMAGE_ATOMIC_UMAX , 23 ) ENUM( IMAGE_ATOMIC_AND , 24 ) ENUM( IMAGE_ATOMIC_OR , 25 ) ENUM( IMAGE_ATOMIC_XOR , 26 ) ENUM( IMAGE_ATOMIC_INC , 27 ) ENUM( IMAGE_ATOMIC_DEC , 28 ) ENUM( IMAGE_SAMPLE , 32 ) ENUM( IMAGE_SAMPLE_CL , 33 ) ENUM( IMAGE_SAMPLE_D , 34 ) ENUM( IMAGE_SAMPLE_D_CL , 35 ) ENUM( IMAGE_SAMPLE_L , 36 ) ENUM( IMAGE_SAMPLE_B , 37 ) ENUM( IMAGE_SAMPLE_B_CL , 38 ) ENUM( IMAGE_SAMPLE_LZ , 39 ) ENUM( IMAGE_SAMPLE_C , 40 ) ENUM( IMAGE_SAMPLE_C_CL , 41 ) ENUM( IMAGE_SAMPLE_C_D , 42 ) ENUM( IMAGE_SAMPLE_C_D_CL , 43 ) ENUM( IMAGE_SAMPLE_C_L , 44 ) ENUM( IMAGE_SAMPLE_C_B , 45 ) ENUM( IMAGE_SAMPLE_C_B_CL , 46 ) ENUM( IMAGE_SAMPLE_C_LZ , 47 ) ENUM( IMAGE_SAMPLE_O , 48 ) ENUM( IMAGE_SAMPLE_CL_O , 49 ) ENUM( IMAGE_SAMPLE_D_O , 50 ) ENUM( IMAGE_SAMPLE_D_CL_O , 51 ) ENUM( IMAGE_SAMPLE_L_O , 52 ) ENUM( IMAGE_SAMPLE_B_O , 53 ) ENUM( IMAGE_SAMPLE_B_CL_O , 54 ) ENUM( IMAGE_SAMPLE_LZ_O , 55 ) ENUM( IMAGE_SAMPLE_C_O , 56 ) ENUM( IMAGE_SAMPLE_C_CL_O , 57 ) ENUM( IMAGE_SAMPLE_C_D_O , 58 ) ENUM( IMAGE_SAMPLE_C_D_CL_O , 59 ) ENUM( IMAGE_SAMPLE_C_L_O , 60 ) ENUM( IMAGE_SAMPLE_C_B_O , 61 ) ENUM( IMAGE_SAMPLE_C_B_CL_O , 62 ) ENUM( IMAGE_SAMPLE_C_LZ_O , 63 ) ENUM( IMAGE_GATHER4 , 64 ) ENUM( IMAGE_GATHER4_CL , 65 ) ENUM( IMAGE_GATHER4_L , 66 ) ENUM( IMAGE_GATHER4_B , 67 ) ENUM( IMAGE_GATHER4_B_CL , 68 ) ENUM( IMAGE_GATHER4_LZ , 69 ) ENUM( IMAGE_GATHER4_C , 70 ) ENUM( IMAGE_GATHER4_C_CL , 71 ) ENUM( IMAGE_GATHER4_C_L , 76 ) ENUM( IMAGE_GATHER4_C_B , 77 ) ENUM( IMAGE_GATHER4_C_B_CL , 78 ) ENUM( IMAGE_GATHER4_C_LZ , 79 ) ENUM( IMAGE_GATHER4_O , 80 ) ENUM( IMAGE_GATHER4_CL_O , 81 ) ENUM( IMAGE_GATHER4_L_O , 84 ) ENUM( IMAGE_GATHER4_B_O , 85 ) ENUM( IMAGE_GATHER4_B_CL_O , 86 ) ENUM( IMAGE_GATHER4_LZ_O , 87 ) ENUM( IMAGE_GATHER4_C_O , 88 ) ENUM( IMAGE_GATHER4_C_CL_O , 89 ) ENUM( IMAGE_GATHER4_C_L_O , 92 ) ENUM( IMAGE_GATHER4_C_B_O , 93 ) ENUM( IMAGE_GATHER4_C_B_CL_O , 94 ) ENUM( IMAGE_GATHER4_C_LZ_O , 95 ) ENUM( IMAGE_GET_LOD , 96 ) ENUM( IMAGE_SAMPLE_CD , 104 ) ENUM( IMAGE_SAMPLE_CD_CL , 105 ) ENUM( IMAGE_SAMPLE_C_CD , 106 ) ENUM( IMAGE_SAMPLE_C_CD_CL , 107 ) ENUM( IMAGE_SAMPLE_CD_O , 108 ) ENUM( IMAGE_SAMPLE_CD_CL_O , 109 ) ENUM( IMAGE_SAMPLE_C_CD_O , 110 ) ENUM( IMAGE_SAMPLE_C_CD_CL_O , 111 ) END_TRANSLATOR(ImageInstructions,MIMGOpcodes,IMAGE_INVALID) BEGIN_TRANSLATOR(TBufferNumberFormats,MTBUFF_NumberFormat) ENUM(NF_UNORM , 0) ENUM(NF_SNORM , 1) ENUM(NF_USCALED , 2) ENUM(NF_SSCALED , 3) ENUM(NF_UINT , 4) ENUM(NF_SINT , 5) ENUM(NF_FLOAT , 7) END_TRANSLATOR(TBufferNumberFormats,MTBUFF_NumberFormat,NF_INVALID) BEGIN_TRANSLATOR(TBufferDataFormats,MTBUFF_DataFormat) ENUM( DF_8 , 1 ) ENUM( DF_16 , 2 ) ENUM( DF_8_8 , 3 ) ENUM( DF_32 , 4 ) ENUM( DF_16_16 , 5 ) ENUM( DF_10_11_11 , 6 ) ENUM( DF_10_10_10_2 , 8 ) ENUM( DF_2_10_10_10 , 9 ) ENUM( DF_8_8_8_8 , 10 ) ENUM( DF_32_32 , 11 ) ENUM( DF_16_16_16_16, 12 ) ENUM( DF_32_32_32 , 13 ) ENUM( DF_32_32_32_32, 14 ) END_TRANSLATOR(TBufferDataFormats,MTBUFF_DataFormat,DF_INVALID) BEGIN_TRANSLATOR(ExportTargets, EXPTarget) ENUM( EXP_MRT0 ,0 ) ENUM( EXP_MRT1 ,1 ) ENUM( EXP_MRT2 ,2 ) ENUM( EXP_MRT3 ,3 ) ENUM( EXP_MRT4 ,4 ) ENUM( EXP_MRT5 ,5 ) ENUM( EXP_MRT6 ,6 ) ENUM( EXP_MRT7 ,7 ) ENUM( EXP_Z ,8 ) ENUM( EXP_NULL ,9 ) ENUM( EXP_POS0 ,12 ) ENUM( EXP_POS1 ,13 ) ENUM( EXP_POS2 ,14 ) ENUM( EXP_POS3 ,15 ) ENUM( EXP_PARAM0 ,32 ) ENUM( EXP_PARAM1 ,33 ) ENUM( EXP_PARAM2 ,34 ) ENUM( EXP_PARAM3 ,35 ) ENUM( EXP_PARAM4 ,36 ) ENUM( EXP_PARAM5 ,37 ) ENUM( EXP_PARAM6 ,38 ) ENUM( EXP_PARAM7 ,39 ) ENUM( EXP_PARAM8 ,40 ) ENUM( EXP_PARAM9 ,41 ) ENUM( EXP_PARAM10 ,42 ) ENUM( EXP_PARAM11 ,43 ) ENUM( EXP_PARAM12 ,44 ) ENUM( EXP_PARAM13 ,45 ) ENUM( EXP_PARAM14 ,46 ) ENUM( EXP_PARAM15 ,47 ) ENUM( EXP_PARAM16 ,48 ) ENUM( EXP_PARAM17 ,49 ) ENUM( EXP_PARAM18 ,50 ) ENUM( EXP_PARAM19 ,51 ) ENUM( EXP_PARAM20 ,52 ) ENUM( EXP_PARAM21 ,53 ) ENUM( EXP_PARAM22 ,54 ) ENUM( EXP_PARAM23 ,55 ) ENUM( EXP_PARAM24 ,56 ) ENUM( EXP_PARAM25 ,57 ) ENUM( EXP_PARAM26 ,58 ) ENUM( EXP_PARAM27 ,59 ) ENUM( EXP_PARAM28 ,60 ) ENUM( EXP_PARAM29 ,61 ) ENUM( EXP_PARAM30 ,62 ) ENUM( EXP_PARAM31 ,63 ) END_TRANSLATOR(ExportTargets,EXPTarget,EXP_INVALID) BEGIN_TRANSLATOR(Dests,ScalarDestOddballs) ENUM(SRC_FSCR_LO , 102) ENUM(SRC_FSCR_HI , 103) ENUM(SRC_XNACK_MASK_LO , 104) ENUM(SRC_XNACK_MASK_HI , 105) ENUM(SRC_VCC_LO , 106) ENUM(SRC_VCC_HI , 107) ENUM(SRC_TBA_LO , 108) ENUM(SRC_TBA_HI , 109) ENUM(SRC_TMA_LO , 110) ENUM(SRC_TMA_HI , 111) ENUM(SRC_M0 , 124) ENUM(SRC_EXEC_LO , 126) ENUM(SRC_EXEC_HI , 127) END_TRANSLATOR(Dests,ScalarDestOddballs, DEST_INVALID) BEGIN_TRANSLATOR(Sources,ScalarSourceOddballs) ENUM(SRC_FSCR_LO , 102) ENUM(SRC_FSCR_HI , 103) ENUM(SRC_XNACK_MASK_LO , 104) ENUM(SRC_XNACK_MASK_HI , 105) ENUM(SRC_VCC_LO , 106) ENUM(SRC_VCC_HI , 107) ENUM(SRC_TBA_LO , 108) ENUM(SRC_TBA_HI , 109) ENUM(SRC_TMA_LO , 110) ENUM(SRC_TMA_HI , 111) ENUM(SRC_M0 , 124) ENUM(SRC_EXEC_LO , 126) ENUM(SRC_EXEC_HI , 127) ENUM(SRC_C_ZERO , 128) ENUM(SRC_CF_ONEHALF , 240) ENUM(SRC_CF_MINUS_ONEHALF , 241) ENUM(SRC_CF_ONE , 242) ENUM(SRC_CF_MINUS_ONE , 243) ENUM(SRC_CF_TWO , 244) ENUM(SRC_CF_MINUS_TWO , 245) ENUM(SRC_CF_FOUR , 246) ENUM(SRC_CF_MINUS_FOUR , 247) ENUM(SRC_CF_INV_2PI , 248) ENUM(SRC_VCCZ , 251) ENUM(SRC_EXECZ , 252) ENUM(SRC_SCC , 253) ENUM(SRC_LDS_DIRECT , 254) ENUM(SRC_LITERAL , 255) END_TRANSLATOR(Sources,ScalarSourceOddballs,SRC_INVALID) Dests Translate_SDest( uint n ) { if( n <= 101 ) return (Dests)(DEST_SGPR_FIRST+n); else return Translate_ScalarDestOddballs(n); } Sources Translate_SSrc( uint n ) { if( n <= 101 ) return (Sources)(SRC_SGPR_FIRST+n); // SGPRs if( n >= 112 && n <= 123 ) return (Sources)(SRC_TTMP_FIRST+(n-112)); // trap handler temps if( n >= 256 && n<= 511 ) return (Sources)(SRC_VGPR_FIRST+(n-256)); // VGPRs if( n >= 129 && n <= 192 ) return(Sources) (SRC_CI_POSITIVE_FIRST+(n-129)); if( n >= 193 && n <= 208 ) return (Sources) (SRC_CI_NEGATIVE_FIRST+(n-193)); return Translate_ScalarSourceOddballs(n); } Sources Translate_VSrc( uint n ) { return (Sources)(SRC_VGPR_FIRST+n); } Dests Translate_VDest( uint n ) { return (Dests)(DEST_VGPR_FIRST+n); } class Instruction { public: uint32 ReadTrailingLiteral() const { const uint32* pDWORD = (const uint32*)this; return pDWORD[1]; } protected: int SignExt( uint n, uint sign ) { uint bit = (1<>shift)&mask; } bool ReadBit( uint bit ) const { uint shift = bit % 32; return (( ((const uint32*)this)[bit/32]>>shift)&1) != 0; } private: }; class SOP2Instruction : public Instruction { public: bool HasLiteral() const { return ((GetSrc0() == SRC_LITERAL || GetSrc1() == SRC_LITERAL)); } uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode()const { return Translate_SOP2Opcodes(ReadBits( 29, 23 )); } Sources GetSrc0() const { return Translate_SSrc(ReadBits( 7,0 )); } Sources GetSrc1() const { return Translate_SSrc(ReadBits( 15,8)); } Dests GetDest() const { return Translate_SDest(ReadBits( 22,16)); } }; class SOP1Instruction : public Instruction { public: bool HasLiteral() const { return (GetSrc0() == SRC_LITERAL); } uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode() const { return Translate_SOP1Opcodes(ReadBits( 15,8 )); } Sources GetSrc0() const { return Translate_SSrc( ReadBits(7,0) ); } Dests GetDest() const { return Translate_SDest(ReadBits(22,16)); } }; class SOPKInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_SOPK; } bool HasLiteral() const { return (GetOpcode() == S_SETREG_IMM32_B32); } uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode() const { return Translate_SOPKOpcodes(ReadBits( 27,23 )); } Dests GetDest() const { return Translate_SDest( ReadBits(22,16) ); } int ReadSIMM16() const { return *((const int16*)this); } uint ReadSIMMBits( uint hi, uint lo) const { return ReadBits(hi,lo); } uint32 ReadIMM32() const { return ReadBits(63,32); } const uint8* GetBranchTarget() const { if( GetOpcode() != S_CBRANCH_I_FORK ) return 0; int offset = this->ReadSIMM16(); const uint32* pThis = (const uint32*)this; return (const uint8*) (pThis+1+offset); } }; class SOPCInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_SOPC; } bool HasLiteral() const { return (GetSrc0() == SRC_LITERAL || GetSrc1() == SRC_LITERAL);} uint GetLength() const { return 4 + 4*HasLiteral(); }; ScalarInstructions GetOpcode() const { return Translate_SOPCOpcodes(ReadBits( 22,16 )); } Sources GetSrc0() const { return Translate_SSrc(ReadBits(7,0)); } Sources GetSrc1() const { return Translate_SSrc(ReadBits(15,8 )); } uint GetSrc1Raw() const { return ReadBits(15,8); } Dests GetDest() const { return GetOpcode() == S_SETVSKIP ? DEST_VSKIP : DEST_SCC; } }; class SOPPInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_SOPP; } uint GetLength() const { return 4; } int ReadSIMM16() const { return *((const int16*)this); } uint ReadSIMMBits( uint hi, uint lo ) const { return ReadBits(hi,lo); } ScalarInstructions GetOpcode() const { return Translate_SOPPOpcodes(ReadBits( 22,16 )); } const uint8* GetBranchTarget() const { switch( GetOpcode() ) { case S_BRANCH : case S_CBRANCH_SCC0 : case S_CBRANCH_SCC1 : case S_CBRANCH_VCCZ : case S_CBRANCH_VCCNZ : case S_CBRANCH_EXECZ : case S_CBRANCH_EXECNZ : case S_CBRANCH_CDBGSYS : case S_CBRANCH_CDBGUSER : case S_CBRANCH_CDBGSYS_OR_USER : case S_CBRANCH_CDBGSYS_AND_USER : { int n = this->ReadSIMM16(); int offset = this->ReadSIMM16(); const uint32* pThis = (const uint32*)this; return (const uint8*) (pThis+1+offset); } default: return 0; } } }; class SMEMInstruction : public Instruction { public: uint GetLength() const { return 8; } ScalarMemoryInstructions GetOpcode() const { return Translate_SMEMOpcodes(ReadBits(25,18)); } Dests GetSData() const { return Translate_SDest(ReadBits( 12,6)); } Dests GetSBase() const { return Translate_SDest(2*ReadBits( 5,0 )); } // base of SGPR pair containing address uint GetOffset() const { return ReadBits(51,32); } bool IsOffsetIMM() const { return ReadBit(17); } // SI and CI use dword offsets, but VI uses byte. }; class VOP2Instruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOP2; } bool HasLiteral() const { uint eOp = GetOpcode(); return (GetSrc0() == SRC_LITERAL || eOp == V_MADAK_F32 || eOp == V_MADMK_F32 || eOp == V_MADMK_F16 || eOp == V_MADMK_F16 ); } uint GetLength() const { return 4 + 4*HasLiteral(); } VectorInstructions GetOpcode() const { return Translate_VOP2Opcodes(ReadBits(30,25)); } Sources GetSrc0() const { return Translate_SSrc(ReadBits(8,0)); } Sources GetVSrc1() const { return Translate_VSrc(ReadBits(16,9)); } Dests GetVDst() const { return Translate_VDest(ReadBits(24,17)); } uint GetResultWidthInDWORDS() const { return 1; } }; class VOP1Instruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOP1; } bool HasLiteral() const { switch( GetOpcode()) { default: return GetSrc0() == SRC_LITERAL; case V_NOP: case V_CLREXCP: return false; } } uint GetLength() const { return 4 + 4*HasLiteral(); } VectorInstructions GetOpcode() const { return Translate_VOP1Opcodes( ReadBits(16,9) ); } Dests GetDst() const { if (GetOpcode() == V_READFIRSTLANE_B32) { return Translate_SDest(ReadBits(24, 17)); } else { return Translate_VDest(ReadBits(24, 17)); } } Sources GetSrc0() const { return Translate_SSrc(ReadBits(8,0)); } }; class VOPCInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOPC; } bool HasLiteral() const { return (GetSrc0() == SRC_LITERAL); } uint GetLength() const { return 4 + 4*HasLiteral(); } VectorInstructions GetOpcode() const { return Translate_VOPCOpcodes(ReadBits(24,17)); } Sources GetSrc0() const { return Translate_SSrc(ReadBits( 8,0 )); } Sources GetVSrc1() const { return Translate_VSrc(ReadBits( 16,9 )); } uint GetOperandWidthInDWORDs() const; bool IsBranch() const { return false; } }; class VINTERPInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VINTERP; } uint GetLength() const { return 4; } VectorInstructions GetOpcode() const { return Translate_VINTERPOpcodes( ReadBits(17,16) ); } uint GetAttributeChannel() const { return ReadBits(9,8); }; uint GetAttributeIndex() const { return ReadBits(15,10); }; Sources GetVSrc0() const { return Translate_VSrc( ReadBits(7,0) ); } Dests GetVDst() const { return Translate_VDest(ReadBits(25,18)); } }; class VOP3Instruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_VOP3; } uint GetLength() const { return 8; } VectorInstructions GetOpcode() const { return Translate_VOP3Opcodes(ReadBits(25,16));} Dests GetVDst() const { uint dst = ReadBits(7,0); if( IsCompare() ) return Translate_SDest(dst); return Translate_VDest(dst); } Sources GetSrc0() const { return Translate_SSrc(ReadBits(40,32)); } Sources GetSrc1() const { return Translate_SSrc(ReadBits(49,41)); } Sources GetSrc2() const { return Translate_SSrc(ReadBits(58,50)); } uint GetSourceNegateMask() const { return ReadBits(63,61); }; uint GetOMod() const { return ReadBits(60,59); } bool IsCompare() const { return ReadBits(25,16) < 255; } // opcodes 0-255 are vcmps. bool IsVOP3bOp() const { // NOTE: ISA Doc, section 6, claims that vcmp is vop3b. But AMD disassembler thinks its VOP3a // switch( GetOpcode() ) { case V_ADD_I32 : // : D.u = S0.u + S1.u; VCC=carry-out (VOP3:sgpr=carry-out). case V_SUB_I32 : // : D.u = S0.u - S1.u; VCC=carry-out (VOP3:sgpr=carry-out). case V_SUBREV_I32 : // : D.u = S1.u - S0.u; VCC=carry-out (VOP3:sgpr=carry-out). case V_ADD_U32 : case V_SUB_U32 : case V_SUBREV_U32 : case V_ADDC_U32 : // : D.u = S0.u + S1.u + VCC; VCC=carry-out (VOP3:sgpr=carryout,S2.u=carry-in). case V_SUBB_U32 : // : D.u = S0.u - S1.u - VCC; VCC=carry-out (VOP3:sgpr=carry-out,S2.u=carry-in). case V_SUBBREV_U32 : // : D.u = S1.u - S0.u - VCC; VCC=carry-out (VOP3:sgpr=carryout,S2.u=carry-in). case V_DIV_SCALE_F32: // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. case V_DIV_SCALE_F64: // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. return true; default: return false; } } // VOP3a only uint GetSourceAbsMask() const { return ReadBits(10,8); } bool GetClamp() const { return ReadBit(15); } // VOP3b only Dests GetSDst() const { return Translate_SDest(ReadBits(14,8)); } }; class MUBUFFInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_MUBUFF; } BufferInstructions GetOpcode() const { return Translate_MUBUFFOpcodes(ReadBits(24,18)); } uint GetLength() const { return 8; } uint GetOffset() const { return ReadBits(11,0); } Sources GetVAddr() const { return Translate_VSrc(ReadBits(39,32)); } Sources GetVData() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetSResource() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(52,48)); } Sources GetSOffset() const { return Translate_SSrc(ReadBits(63,56)); } bool IsOffN() const { return ReadBit(12); } bool IsIdxN() const { return ReadBit(13); } bool IsAddr64() const { return false; } // this bit was removed in VI bool IsDirectToLDS() const { return ReadBit(16); } bool GetSLCBit() const { return ReadBit(17); } bool GetGLCBit() const { return ReadBit(14); } bool GetTFEBit() const { return ReadBit(55); } }; class MTBUFFInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_MTBUFF; } BufferInstructions GetOpcode() const { return Translate_MTBUFFOpcodes(ReadBits(18,15)); } uint GetLength() const { return 8; } uint GetResultWidthInDWORDS() const ; TBufferNumberFormats GetNumberFormat() const { return Translate_MTBUFF_NumberFormat( ReadBits(25,23) ); } TBufferDataFormats GetDataFormat() const { return Translate_MTBUFF_DataFormat( ReadBits(22,19) ); } uint GetOffset() const { return ReadBits(11,0); } Sources GetVAddr() const { return Translate_VSrc(ReadBits(39,32)); } Sources GetVData() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetSResource() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(52,48)); } Sources GetSOffset() const { return Translate_SSrc(ReadBits(63,56)); } bool IsOffN() const { return ReadBit(12); } bool IsIdxN() const { return ReadBit(13); } bool IsAddr64() const { return false; } // removed in VI bool GetSLCBit() const { return ReadBit(54); } bool GetGLCBit() const { return ReadBit(14); } bool GetTFEBit() const { return ReadBit(55); } }; class MIMGInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_MIMG; } ImageInstructions GetOpcode() const { return Translate_MIMGOpcodes( ReadBits(24,18) ); } uint GetLength() const { return 8; } bool IsSLC() const { return ReadBit(25); } bool IsGLC() const { return ReadBit(13); } bool IsTFE() const { return ReadBit(16); } bool IsLWE() const { return ReadBit(17); } bool IsArray() const { return ReadBit(14); } bool IsUnormalized() const { return ReadBit(12); } bool IsRes256() const { return !ReadBit(15);}; bool IsD16() const { return ReadBit(63); } uint GetDMask() const { return ReadBits(11,8); } Sources GetSSampler() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(57,53)); } Sources GetSResource() const { return (Sources)(SRC_SGPR_FIRST+4*ReadBits(52,48)); } Sources GetVData() const { return Translate_VSrc( ReadBits(47,40) ); } Sources GetVAddr() const { return Translate_VSrc( ReadBits(39,32) ); } }; class DSInstruction : public Instruction { public: uint GetOffset0() const { return ReadBits(7,0); } // Instructions can have one 16 bit offset field or two 8-bit offset fields uint GetOffset1() const { return ReadBits(15,8); } uint GetOffset16() const { return ReadBits(15,0); } DSInstructions GetOpcode() const { return Translate_DSOpcodes(ReadBits(24,17)); } Dests GetVDest() const { return Translate_VDest(ReadBits(63,56)); } Sources GetVData0() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetVData1() const { return Translate_VSrc(ReadBits(55,48)); } Sources GetVAddr() const { return Translate_VSrc(ReadBits(39,32)); } bool IsGDS() const { return ReadBit(16); } }; class EXPInstruction : public Instruction { public: InstructionFormat GetFormat() const { return IF_EXP; } uint GetLength() const { return 8; } bool GetCompressBit() const { return ReadBit(10); } bool GetDoneBit() const { return ReadBit(11); } bool GetValidMaskBit() const { return ReadBit(12); } ExportTargets GetTarget() const { return Translate_EXPTarget(ReadBits(9,4)); } uint GetExportMask() const { return ReadBits(3,0); } Sources GetVSrc0() const { return Translate_VSrc(ReadBits(39,32)); } Sources GetVSrc1() const { return Translate_VSrc(ReadBits(47,40)); } Sources GetVSrc2() const { return Translate_VSrc(ReadBits(55,48)); } Sources GetVSrc3() const { return Translate_VSrc(ReadBits(63,56)); } }; }} namespace GCN { InstructionFormat GCN3Decoder::ReadInstructionFormat( const uint8* pLocation ) { uint32 n = *((const uint32*)pLocation); // // The instruction format is inferred from magic numbers packed into the upper bits of the first DWORD // vop2 is 0....... // vop1 is 0111 111 // vopc is 0111 110 // sop2 is 10...... // sopK is 1011 ....... // sopc is 1011 1111 0 // sopp is 1011 1111 1 // sop1 is 1011 1110 1 // vinterp is 1100 10 (according to doc) but 1101 10 according to sane reality // smem is 1100 00 (changed from 1100 0... in SI) // vop3 is 1101 00 // flat is 1101 11 // ds is 1101 10 // mubuff is 1110 00 // mtbuff is 1110 10 // mimg is 1111 00 // exp is 1100 01 (changed from 1111 10... in SI) switch( n & (0xFF800000) ) // 1111 1111 1000 ... (9 bit) { case 0xBF000000: return IF_SOPC; // 1011 1111 0.... case 0xBF800000: return IF_SOPP; // 1011 1111 1.... case 0xBE800000: return IF_SOP1; // 1011 1110 1.... default: switch( n & (0xFE000000) ) // 1111 1110 ... (7 bit) { case 0x7E000000: return IF_VOP1; // 0111 1110 ... case 0x7C000000: return IF_VOPC; // 0111 1100 ... default: switch( n & (0xFC000000) ) // 1111 1100 ... (6 bit) { case 0xD4000000: // 1101 10..... case 0xC8000000: return IF_VINTERP; // 1100 10.. .... case 0xD0000000: return IF_VOP3; // 1101 00.. ... case 0xDC000000: return IF_FLAT; // 1101 11.. .... case 0xD8000000: return IF_DS; // 1101 10.. .... case 0xE0000000: return IF_MUBUFF; // 1110 00.. case 0xE8000000: return IF_MTBUFF; // 1110 10.. case 0xF0000000: return IF_MIMG; // 1111 00.. case 0xC4000000: return IF_EXP; // 1100 01.. case 0xC0000000: return IF_SMEM; // 1100 00.. default: switch( n & (0xF8000000) ) // 1111 1000 (5bit) { case 0xB0000000: return IF_SOPK; // 1011 0......... case 0xB8000000: return IF_SOPK; // 1011 1......... default: if( (n & 0xC0000000) == 0x80000000 ) // 1100.... return IF_SOP2; // 1000 .... if( !(n & 0x80000000) ) return IF_VOP2; // 0...... } } } } return IF_UNKNOWN; } size_t GCN3Decoder::DetermineInstructionLength( const uint8* pLocation, InstructionFormat eEncoding ) { using namespace _GCN3Decoder_INTERNAL; switch( eEncoding ) { case IF_VOP2: return ((const VOP2Instruction*)pLocation)->GetLength(); case IF_VOP1: return ((const VOP1Instruction*)pLocation)->GetLength(); case IF_VOPC: return ((const VOPCInstruction*)pLocation)->GetLength(); case IF_SOP2: return ((const SOP2Instruction*)pLocation)->GetLength(); case IF_SOPK: return ((const SOPKInstruction*)pLocation)->GetLength(); case IF_SOP1: return ((const SOP1Instruction*)pLocation)->GetLength(); case IF_SOPC: return ((const SOPCInstruction*)pLocation)->GetLength(); case IF_SOPP: case IF_VINTERP: return 4; case IF_DS: case IF_VOP3: case IF_MTBUFF: case IF_MUBUFF: case IF_MIMG: case IF_EXP: case IF_FLAT: case IF_SMEM: return 8; case IF_UNKNOWN: default: return 0; } } void GCN3Decoder::Decode( Instruction* pInst, const uint8* pLocation, InstructionFormat eEncoding ) { memset(pInst,0,sizeof(*pInst)); using namespace _GCN3Decoder_INTERNAL; switch( eEncoding ) { case IF_SOP2: { auto* pIt = (const SOP2Instruction*)pLocation; auto& Fields = pInst->Fields.Scalar; pInst->m_eClass = IC_SCALAR; Fields.m_Dest = pIt->GetDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSourceCount = 2; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetSrc1(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_SOPK: { auto* pIt = (const SOPKInstruction*) pLocation; auto& Fields = pInst->Fields.Scalar; pInst->m_eClass = IC_SCALAR; Fields.m_Dest = pIt->GetDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSourceCount = 0; Fields.m_nSIMM16 = pIt->ReadSIMM16(); Fields.m_pBranchTarget = pIt->GetBranchTarget(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_SOP1: { auto* pIt = (const SOP1Instruction*) pLocation; auto& Fields = pInst->Fields.Scalar; pInst->m_eClass = IC_SCALAR; Fields.m_Dest = pIt->GetDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSourceCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); if( pIt->HasLiteral()) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_SOPC: { auto* pIt = (const SOPCInstruction*) pLocation; auto& Fields = pInst->Fields.Scalar; pInst->m_eClass = IC_SCALAR; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_Dest = pIt->GetDest(); Fields.m_nSourceCount = 2; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetSrc1(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); // - S_SET_GPR_IDX_ON (sopc) is a special little fella. His Src1 field gets ripped out and used as an immediate // * Move to the SIMM16 field in the scalar instruction class if( Fields.m_eOpcode == S_SET_GPR_IDX_ON ) Fields.m_nSIMM16 = pIt->GetSrc1Raw(); } break; case IF_SOPP: { auto* pIt = (const SOPPInstruction*) pLocation; auto& Fields = pInst->Fields.Scalar; pInst->m_eClass = IC_SCALAR; Fields.m_eOpcode= pIt->GetOpcode(); Fields.m_Dest = DEST_INVALID; Fields.m_nSourceCount = 0; Fields.m_nSIMM16 = pIt->ReadSIMM16(); Fields.m_pBranchTarget = pIt->GetBranchTarget(); } break; case IF_SMEM: { auto* pIt = (const SMEMInstruction*) pLocation; auto& Fields = pInst->Fields.ScalarMem; pInst->m_eClass = IC_SCALAR_MEM; Fields.m_bIsOffsetIMM = pIt->IsOffsetIMM(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_Dest = pIt->GetSData(); Fields.m_nBaseReg = pIt->GetSBase(); Fields.m_nOffset = pIt->GetOffset(); Fields.m_bIsGLC = false; } break; case IF_VOP2: { auto* pIt = (const VOP2Instruction*) pLocation; auto& Fields = pInst->Fields.Vector; pInst->m_eClass = IC_VECTOR; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSrcCount = 2; Fields.m_nDestCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetVSrc1(); Fields.m_Dests[0] = pIt->GetVDst(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); // convert float16 literals to float32 ones to make the disassembler's job easier switch( Fields.m_eOpcode ) { case V_MADAK_F16: case V_MADMK_F16: { uint32 f16 = Fields.m_Literal.UInt; uint32 sign = (f16 & 0x8000)<<16; int exp = ((f16 & 0x7C00)>>5)-15; uint mant = f16 & 0x3fff; switch( exp ) // nan { default: // normalized Fields.m_Literal.UInt = sign|((exp+127)<<23)|(mant<<13); break; case 16: // inf/nan Fields.m_Literal.UInt = sign|(0xff<<23)|(mant<<13); break; case -15: // FP16 denorm Fields.m_Literal.Float = ldexpf(sign?-1.0f:1.0f,-14) * (mant/1023.0f); break; } } break; } } break; case IF_VOP1: { auto* pIt = (const VOP1Instruction*) pLocation; auto& Fields = pInst->Fields.Vector; pInst->m_eClass = IC_VECTOR; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSrcCount = 1; Fields.m_nDestCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Dests[0] = pIt->GetDst(); if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_VOPC: { auto* pIt = (const VOPCInstruction*) pLocation; auto& Fields = pInst->Fields.Vector; pInst->m_eClass = IC_VECTOR; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nSrcCount = 2; Fields.m_nDestCount = 1; Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetVSrc1(); Fields.m_Dests[0] = DEST_VCC; if( pIt->HasLiteral() ) Fields.m_Literal.UInt = pIt->ReadTrailingLiteral(); } break; case IF_VOP3: { auto* pIt = (const VOP3Instruction*) pLocation; auto& Fields = pInst->Fields.Vector; Fields.m_eOpcode = pIt->GetOpcode(); pInst->m_eClass = IC_VECTOR; // TODO: Detect VOP3-encoded interp ops here and treat them as VC_INTERP? // so we can get better disassembly output? // Are they allowed to use abs, clamp, and all that goodness?? // How do the attribute fields get encoded? Doc is not helpful here... if( pIt->IsVOP3bOp() ) { Fields.m_nDestCount = 2; Fields.m_Dests[0] = pIt->GetVDst(); Fields.m_Dests[1] = pIt->GetSDst(); } else { Fields.m_nDestCount = 1; Fields.m_Dests[0] = pIt->GetVDst(); Fields.m_nSourceAbs = pIt->GetSourceAbsMask(); } Fields.m_nClamp = pIt->GetClamp(); Fields.m_nSourceNegate= pIt->GetSourceNegateMask(); Fields.m_nOMOD = pIt->GetOMod(); Fields.m_nSrcCount = GetSourceCountForInstruction( Fields.m_eOpcode ); Fields.m_Sources[0] = pIt->GetSrc0(); Fields.m_Sources[1] = pIt->GetSrc1(); Fields.m_Sources[2] = pIt->GetSrc2(); } break; case IF_VINTERP: { auto* pIt = (const VINTERPInstruction*) pLocation; auto& Fields = pInst->Fields.Interp; pInst->m_eClass = IC_VECTOR_INTERP; Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nAttributeChannel = pIt->GetAttributeChannel(); Fields.m_nAttributeIndex = pIt->GetAttributeIndex(); Fields.m_VDst = pIt->GetVDst(); Fields.m_VSrc = pIt->GetVSrc0(); } break; case IF_EXP: { auto* pIt = (const EXPInstruction*) pLocation; auto& Fields = pInst->Fields.Export; pInst->m_eClass = IC_EXPORT; Fields.m_ChannelMask = pIt->GetExportMask(); Fields.m_Compress = pIt->GetCompressBit(); Fields.m_Done = pIt->GetDoneBit(); Fields.m_eTarget = pIt->GetTarget(); Fields.m_ValidMask = pIt->GetValidMaskBit(); Fields.m_Sources[0] = pIt->GetVSrc0(); Fields.m_Sources[1] = pIt->GetVSrc1(); Fields.m_Sources[2] = pIt->GetVSrc2(); Fields.m_Sources[3] = pIt->GetVSrc3(); } break; case IF_DS: { auto* pIt = (const DSInstruction*) pLocation; auto& Fields = pInst->Fields.DS; pInst->m_eClass = IC_DS; Fields.m_bGDS = pIt->IsGDS(); Fields.m_Dest = pIt->GetVDest(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nOffset0 = pIt->GetOffset0(); Fields.m_nOffset1 = pIt->GetOffset1(); Fields.m_nOffset16 = pIt->GetOffset16(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData0 = pIt->GetVData0(); Fields.m_VData1 = pIt->GetVData1(); } break; case IF_MTBUFF: { auto* pIt = (const MTBUFFInstruction*) pLocation; auto& Fields = pInst->Fields.Buffer; pInst->m_eClass = IC_BUFFER; Fields.m_bAddr64 = pIt->IsAddr64(); Fields.m_bGLC = pIt->GetGLCBit(); Fields.m_bIdxN = pIt->IsIdxN(); Fields.m_bLDSDirect = 0; Fields.m_bOffN = pIt->IsOffN(); Fields.m_bSLC = pIt->GetSLCBit(); Fields.m_bTFE = pIt->GetTFEBit(); Fields.m_eDataFormat = pIt->GetDataFormat(); Fields.m_eNumberFormat = pIt->GetNumberFormat(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nOffset = pIt->GetOffset(); Fields.m_SOffset = pIt->GetSOffset(); Fields.m_SResource = pIt->GetSResource(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData = pIt->GetVData(); } break; case IF_MUBUFF: { auto* pIt = (const MUBUFFInstruction*) pLocation; auto& Fields = pInst->Fields.Buffer; pInst->m_eClass = IC_BUFFER; Fields.m_bAddr64 = pIt->IsAddr64(); Fields.m_bGLC = pIt->GetGLCBit(); Fields.m_bIdxN = pIt->IsIdxN(); Fields.m_bLDSDirect = pIt->IsDirectToLDS(); Fields.m_bOffN = pIt->IsOffN(); Fields.m_bSLC = pIt->GetSLCBit(); Fields.m_bTFE = pIt->GetTFEBit(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nOffset = pIt->GetOffset(); Fields.m_SOffset = pIt->GetSOffset(); Fields.m_SResource = pIt->GetSResource(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData = pIt->GetVData(); // - BUFFER_STORE_LDS_DWORD // set the LDS bit, so that disassembler treats it like an LDS direct read /// Not sure if this is supposed to use M0 or a vgpr and of course the doc don't say if( Fields.m_eOpcode == BUFFER_STORE_LDS_DWORD ) Fields.m_bLDSDirect = true; } break; case IF_MIMG: { auto* pIt = (const MIMGInstruction*) pLocation; auto& Fields = pInst->Fields.Image; pInst->m_eClass = IC_IMAGE; Fields.m_bArray = pIt->IsArray(); Fields.m_bGLC = pIt->IsGLC(); Fields.m_bLWE = pIt->IsLWE(); Fields.m_bRes256 = pIt->IsRes256(); Fields.m_bSLC = pIt->IsSLC(); Fields.m_bTFE = pIt->IsTFE(); Fields.m_bUnnormalized = pIt->IsUnormalized(); Fields.m_eOpcode = pIt->GetOpcode(); Fields.m_nDMask = pIt->GetDMask(); Fields.m_SResource = pIt->GetSResource(); Fields.m_SSampler = pIt->GetSSampler(); Fields.m_VAddr = pIt->GetVAddr(); Fields.m_VData = pIt->GetVData(); Fields.m_bIsD16 = pIt->IsD16(); } break; case IF_FLAT: default: return; } } } ================================================ FILE: src/Wrapper/GCN3Decoder.h ================================================ // // Decoder for GCN3 // // Copyright 2015 Joshua Barczak, all rights reserved. // #ifndef _GCN3_DECODER_H_ #define _GCN3_DECODER_H_ #pragma once #include "GCNDecoder.h" namespace GCN { class GCN3Decoder : public IDecoder { public: virtual InstructionFormat ReadInstructionFormat( const uint8* pLocation ); virtual size_t DetermineInstructionLength( const uint8* pLocation, InstructionFormat eEncoding ); virtual void Decode( Instruction* pInst, const uint8* pLocation, InstructionFormat eEncoding ) ; }; } #endif ================================================ FILE: src/Wrapper/GCNBufferedPrinter.h ================================================ // // GCN disassembler // Copyright 2015 Joshua Barczak, all rights reserved. // #ifndef _GCN_BUFFERED_PRINTER_H_ #define _GCN_BUFFERED_PRINTER_H_ #pragma once #include "GCNDisassembler.h" #include #include namespace GCN{ namespace Disassembler{ class BufferedPrinter : public GCN::Disassembler::IPrinter { public: virtual void Push( const char* p ) { m_Bytes.insert( m_Bytes.end(), p, p + strlen(p) ); } std::vector m_Bytes; }; }} #endif ================================================ FILE: src/Wrapper/GCNDecoder.cpp ================================================ // // The decoder class is responsible for decoding GCN instructions into a standardized form // // A decoder abstraction is necessary because AMD decided to change the // microcode formats and opcode numbers for GCN3. // // Copyright 2015 Joshua Barczak, all rights reserved. // #pragma unmanaged #include "GCNDecoder.h" #include "GCN1Decoder.h" #include "GCN3Decoder.h" namespace GCN { IDecoder* IDecoder::Create( GCNVersions eVersion ) { switch( eVersion ) { case GCN1: return new GCN1Decoder(); case GCN3: return new GCN3Decoder(); default: return 0; } } void IDecoder::Destroy( IDecoder* p ) { delete p; } } ================================================ FILE: src/Wrapper/GCNDecoder.h ================================================ // // The decoder class is responsible for decoding GCN instructions into a standardized form // // A decoder abstraction is necessary because AMD decided to change the // microcode formats and opcode numbers for GCN3. // // Copyright 2015 Joshua Barczak, all rights reserved. // #ifndef _GCN_DECODER_H_ #define _GCN_DECODER_H_ #pragma once namespace GCN { typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned int uint; typedef short int16; static_assert( sizeof(uint8) == 1, "Fix typedefs" ); static_assert( sizeof(int16) == 2, "Fix typedefs" ); static_assert( sizeof(uint16) == 2, "Fix typedefs" ); static_assert( sizeof(uint32) == 4, "Fix typedefs" ); enum InstructionFormat; class Instruction; class IDecoder { public: enum GCNVersions { GCN1, GCN3, }; /// Decoder factory static IDecoder* Create( GCNVersions eVersion ); static void Destroy( IDecoder* pDecoder ); /// Determine the format of the instruction at 'pLocation' by parsing the encoding bits virtual InstructionFormat ReadInstructionFormat( const uint8* pLocation ) = 0; /// Determine the length in bytes of the instruction at 'pLocation' virtual size_t DetermineInstructionLength( const uint8* pLocation, InstructionFormat eEncoding ) = 0; /// Decode the instruction at 'pLocation' virtual void Decode( Instruction* pInst, const uint8* pLocation, InstructionFormat eEncoding ) = 0; protected: // Utility methods which can be used by decoder implementations uint ReadBits( const uint8* pWhere, uint hi, uint lo ) const { uint shift = lo % 32; uint mask = (1<<(hi-lo+1))-1; return ( ((const uint32*)pWhere)[lo/32]>>shift)&mask; } bool ReadBit( const uint8* pWhere, uint bit ) const { uint shift = bit % 32; return (( ((const uint32*)pWhere)[bit/32]>>shift)&1) != 0; } }; } #endif ================================================ FILE: src/Wrapper/GCNDisassembler.cpp ================================================ // // GCN disassembler // Copyright 2015 Joshua Barczak, all rights reserved. // #pragma unmanaged #include "GCNDisassembler.h" #include "GCNIsa.h" #include "GCNDecoder.h" #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include typedef unsigned char uint8; typedef unsigned int uint; namespace GCN{ namespace Disassembler{ namespace _INTERNAL { #define OPCODE_FORMAT "%22s" static const char* BINARY_OP_FORMAT = OPCODE_FORMAT " %6s,%6s,%6s\n"; static const char* UNARY_OP_FORMAT = OPCODE_FORMAT " %6s,%6s\n"; void Printf( IPrinter& printer, const char* Format, ... ) { va_list vl; va_start(vl,Format); char scratch[2048]; char* p = scratch; int n = _vscprintf( Format, vl ); if( n+1 > sizeof(scratch) ) p = (char*) malloc( n+1 ); vsprintf(p,Format,vl); printer.Push(p); if( p != scratch ) free(p); va_end(vl); } void addprintf( char* buff, const char* Format, ... ) { va_list vl; va_start(vl,Format); size_t n = strlen(buff); if( n ) { strcat( buff, "+"); vsprintf( buff+n+1, Format, vl ); } else { vsprintf( buff, Format, vl ); } va_end(vl); } void catprintf( char* buff, const char* Format, ... ) { va_list vl; va_start(vl,Format); vsprintf( buff+strlen(buff), Format, vl ); va_end(vl); } void FormatIndexedReg( char* buff, const char* pPrefix, uint nRegNum, uint nDWORDs ) { if( nDWORDs>1) sprintf( buff, "%s%u[%u]",pPrefix, nRegNum, nDWORDs ); else sprintf( buff, "%s%u", pPrefix, nRegNum ); } void FormatReg64( char* buff, const char* pPrefix, uint nHiLo, uint nDWORDS ) { if( nDWORDS == 1 ) // partial reg write sprintf( buff, "%s[%s]", pPrefix, nHiLo ? "HI" : "LO" ); else // assumed full reg write strcpy(buff, pPrefix ); } void FormatVReg( char* buff, uint nSrc, uint nDWORDS ) { FormatIndexedReg(buff, "v", nSrc, nDWORDS ); } void FormatSReg( char* buff, uint nSrc, uint nDWORDS ) { FormatIndexedReg(buff, "s", nSrc, nDWORDS ); } static void FormatVSrc( char* pBuff, Sources nReg, uint nWidth ) { FormatVReg(pBuff,nReg-SRC_VGPR_FIRST,nWidth); } static void FormatVDest( char* pBuff, Dests nReg, uint nWidth ) { FormatVReg(pBuff,nReg-DEST_VGPR_FIRST,nWidth); } void FormatGenericSource( char* buff, Sources nSrc, uint nDWORDs ) { if( nSrc >= SRC_SGPR_FIRST && nSrc <= SRC_SGPR_LAST ) // sgpr { FormatSReg( buff, nSrc-SRC_SGPR_FIRST, nDWORDs ); return; // sgpr } if( nSrc >= SRC_TTMP_FIRST && nSrc <= SRC_TTMP_LAST ) // trap temporaries { FormatIndexedReg( buff, "TT", nSrc-SRC_TTMP_FIRST, nDWORDs ); return; // sgpr } if( nSrc >= SRC_VGPR_FIRST && nSrc <= SRC_VGPR_LAST ) // vgpr { FormatVReg( buff, nSrc-SRC_VGPR_FIRST, nDWORDs ); return; // sgpr } if( nSrc >= SRC_CI_POSITIVE_FIRST && nSrc <= SRC_CI_POSITIVE_LAST ) // positive int 1 to 64 { sprintf( buff, "%d", (nSrc - SRC_CI_POSITIVE_FIRST)+1 ); return; } if( nSrc >= SRC_CI_NEGATIVE_FIRST && nSrc <= SRC_CI_NEGATIVE_LAST ) // negative int, -1 to 16 { sprintf( buff, "%d", (SRC_CI_NEGATIVE_FIRST-1)-nSrc); return; } // various 64-bit architectural regs switch( nSrc ) { case SRC_FSCR_LO: case SRC_FSCR_HI: FormatReg64( buff, "FSCR", nSrc-SRC_FSCR_LO, nDWORDs ); return ; case SRC_VCC_LO : case SRC_VCC_HI : FormatReg64( buff, "VCC", nSrc-SRC_VCC_LO, nDWORDs ); return; case SRC_TBA_LO : case SRC_TBA_HI : FormatReg64( buff, "TBA", nSrc-SRC_TBA_LO, nDWORDs ); return; case SRC_TMA_LO : case SRC_TMA_HI : FormatReg64( buff, "TMA", nSrc-SRC_TMA_LO, nDWORDs ); return; case SRC_EXEC_LO : case SRC_EXEC_HI : FormatReg64( buff, "EXEC", nSrc-SRC_EXEC_LO, nDWORDs ); return; case SRC_XNACK_MASK_LO: case SRC_XNACK_MASK_HI: FormatReg64( buff, "XNACK", nSrc-SRC_XNACK_MASK_LO,nDWORDs ); break; } switch( nSrc ) { case SRC_M0: strcpy( buff, "M0" ); break; case SRC_C_ZERO: strcpy( buff, "0" ); break; case SRC_CF_ONEHALF: strcpy( buff, "0.5"); break; case SRC_CF_MINUS_ONEHALF: strcpy( buff, "-0.5"); break; case SRC_CF_ONE: strcpy( buff, "1.0"); break; case SRC_CF_MINUS_ONE: strcpy( buff, "-1.0"); break; case SRC_CF_TWO: strcpy( buff, "2.0"); break; case SRC_CF_MINUS_TWO: strcpy( buff, "-2.0"); break; case SRC_CF_FOUR: strcpy( buff, "4.0"); break; case SRC_CF_MINUS_FOUR: strcpy( buff, "-4.0"); break; case SRC_CF_INV_2PI: strcpy( buff, "1/2PI"); break; case SRC_VCCZ : strcpy( buff, "VCCZ"); break; case SRC_EXECZ : strcpy( buff, "EXECZ"); break; case SRC_SCC : strcpy( buff, "SCC"); break; case SRC_LDS_DIRECT : strcpy( buff, "LDS[M0]"); break; default: strcpy( buff, "???SOURCE???"); break; } } void FormatDest( char* buff, Dests nSrc, uint nDWORDs ) { if( nSrc >= DEST_SGPR_FIRST && nSrc <= DEST_SGPR_LAST ) // sgpr { FormatSReg( buff, nSrc-DEST_SGPR_FIRST, nDWORDs ); return; // sgpr } if( nSrc >= DEST_TTMP_FIRST && nSrc <= DEST_TTMP_LAST ) // trap temporaries { FormatIndexedReg( buff, "TT", nSrc-DEST_TTMP_FIRST, nDWORDs ); return; // sgpr } if( nSrc >= DEST_VGPR_FIRST && nSrc <= DEST_VGPR_LAST ) // vgpr { FormatVReg( buff, nSrc-DEST_VGPR_FIRST, nDWORDs ); return; // sgpr } // various 64-bit architectural regs switch( nSrc ) { case DEST_FSCR_LO: case DEST_FSCR_HI: FormatReg64( buff, "FSCR", nSrc-DEST_FSCR_LO, nDWORDs ); return ; case DEST_VCC_LO : case DEST_VCC_HI : FormatReg64( buff, "VCC", nSrc-DEST_VCC_LO, nDWORDs ); return; case DEST_TBA_LO : case DEST_TBA_HI : FormatReg64( buff, "TBA", nSrc-DEST_TBA_LO, nDWORDs ); return; case DEST_TMA_LO : case DEST_TMA_HI : FormatReg64( buff, "TMA", nSrc-DEST_TMA_LO, nDWORDs ); return; case DEST_EXEC_LO : case DEST_EXEC_HI : FormatReg64( buff, "EXEC", nSrc-DEST_EXEC_LO, nDWORDs ); return; case DEST_XNACK_MASK_HI: case DEST_XNACK_MASK_LO: FormatReg64( buff, "XNACK", nSrc-DEST_XNACK_MASK_LO, nDWORDs); break; } switch( nSrc ) { case DEST_M0: strcpy( buff, "M0" ); break; case DEST_SCC: strcpy( buff, "SCC"); break; case DEST_VCC: strcpy( buff, "VCC"); break; case DEST_VSKIP: strcpy( buff, "VSKIP"); break; default: strcpy( buff, "???DEST??"); break; } } template< class TInstruction > void FormatTrailingLiteral( char* buff, const TInstruction* pI ) { uint n = pI->GetLiteralAsDWORD(); sprintf( buff, "0x%x", n ); } template< class TInstruction > void FormatSource( char* buff, Sources nSrc, uint nDWORDs, const TInstruction* pI ) { if( nSrc == SRC_LITERAL ) FormatTrailingLiteral( buff, pI ) ; else FormatGenericSource( buff, nSrc, nDWORDs ); } void FormatVOPSource( char* buff, uint nDWORDS, Sources nSrc, bool abs, bool negate, const VectorInstruction* pI ) { if( nSrc == SRC_LITERAL ) { FormatTrailingLiteral(buff,pI); return; } char tmp0[64]; char tmp1[64]; FormatGenericSource( tmp0, nSrc, nDWORDS ); if( abs ) { sprintf( tmp1, "|%s|", tmp0 ); strcpy( tmp0, tmp1 ); } if( negate ) { sprintf( tmp1, "-%s", tmp0 ); strcpy(tmp0,tmp1 ); } strcpy(buff,tmp0); } static void SynthesizeLabelName( char* out, const GCN::ScalarInstruction* pInst, const std::vector* pLabels ) { const uint8* pTarget = pInst->GetBranchTarget(); size_t i=0; while( pLabels && i < pLabels->size() ) { if( pLabels->at(i) == pTarget ) break; i++; } if( pLabels && i < pLabels->size() ) { sprintf( out, "Label_%04u", i ); } else if( pInst->GetBranchTarget() ) { sprintf( out, "PC + %d", pInst->GetBranchOffset() ); } else { sprintf( out, "????"); } } void PrintLabeledBranch( IPrinter& printer, const ScalarInstruction* pInst, const char* pLabelName ) { Printf( printer, OPCODE_FORMAT" %s\n", EnumToString(pInst->GetOpcode()), pLabelName ); } void Disassemble( IPrinter& printer, const ScalarInstruction* pInst, const char* pLabelName ) { const char* pOpcode = EnumToString(pInst->GetOpcode()); char src0[64]; char src1[64]; char dst[64]; switch( pInst->GetOpcode() ) { case S_BARRIER: case S_ENDPGM: case S_ENDPGM_SAVED: case S_SET_GPR_IDX_OFF: case S_ICACHE_INV: Printf( printer, OPCODE_FORMAT"\n",pOpcode); break; case S_NOP: Printf( printer, OPCODE_FORMAT"(%u)\n","S_NOP",pInst->ReadSIMMBits(2,0)+1); break; case S_SETHALT: Printf( printer, OPCODE_FORMAT"(%u)\n", "S_SETHALT", pInst->ReadSIMMBits(0,0) ); break; case S_SLEEP: Printf( printer, OPCODE_FORMAT"(%u)\n", "S_SLEEP", 64*pInst->ReadSIMMBits(2,0) ); break; case S_SETPRIO: Printf( printer, OPCODE_FORMAT"(%u)\n", "S_SETPRIO", pInst->ReadSIMMBits(1,0) ); break; case S_TRAP: Printf( printer, OPCODE_FORMAT"(%u)\n", "S_TRAP", pInst->ReadSIMMBits(7,0) ); break; case S_INCPERFLEVEL: case S_DECPERFLEVEL: Printf( printer, OPCODE_FORMAT"(%u)\n", pOpcode, pInst->ReadSIMMBits(3,0) ); break; case S_SENDMSG: case S_SENDMSGHALT: { uint nMsg = pInst->ReadSIMMBits(3,0); switch( nMsg ) { case 1: // interrupt Printf(printer,OPCODE_FORMAT" INTERRUPT(M0)\n",pOpcode); break; case 2: // geometry shader goodness case 3: { // 2 is GS. 3 is GS_DONE // the GS op is NOP(0), CUT(1), EMIT(2), EMIT-CUT(3) uint nGSOp = pInst->ReadSIMMBits(5,4); Printf( printer, OPCODE_FORMAT" GS: %s%s%s\n", pOpcode, (nGSOp&2) ? " EMIT " : "", (nGSOp&1) ? " CUT " : "", (nMsg == 3) ? "DONE" : ""); } break; default: // something mysterious Printf(printer,OPCODE_FORMAT" 0x%04x\n",pOpcode,pInst->ReadSIMMBits(15,0) ); break; } } break; case S_WAITCNT: { uint VMCNT = pInst->GetVMwaitCount(); uint EXPCNT = pInst->GetEXPWaitCount(); uint LKGMCNT = pInst->GetLCGMWaitCount(); char COUNTS[256]=""; if( VMCNT != 15 ) catprintf(COUNTS, "vmcnt(%u) ",VMCNT); if( EXPCNT != 7 ) catprintf(COUNTS, "expcnt(%u) ",EXPCNT); if( LKGMCNT != 15 ) catprintf(COUNTS, "lkgmcnt(%u) ",LKGMCNT ); // NOTE: Max for LKGMCNT is really 31, but AMD driver seems to // think its 15, because it constantly waits on that. Printf( printer, OPCODE_FORMAT" %s\n", "S_WAITCNT", COUNTS ); } break; case S_BRANCH : //: PC = PC + signext(SIMM16 * 4) + 4. case S_CBRANCH_SCC0 : //: if(SCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_SCC1 : //: if(SCC == 1) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_VCCZ : //: if(VCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_VCCNZ : //: if(VCC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_EXECZ : //: if(EXEC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_EXECNZ : //: if(EXEC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_CDBGSYS : // : If (conditional_debug_system != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGUSER: // : If (conditional_debug_user != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGSYS_OR_USER: // : I f (conditional_debug_system || conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGSYS_AND_USER:// : If (conditional_debug_system && conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. PrintLabeledBranch(printer,pInst,pLabelName); break; case S_CBRANCH_G_FORK: { FormatGenericSource(src0,pInst->GetSource(0),2); FormatGenericSource(src1,pInst->GetSource(1),2); Printf(printer,UNARY_OP_FORMAT, pOpcode, src0,src1 ); } break; case S_MOVRELD_B32: { FormatSReg(dst,pInst->GetDest(),1); FormatSource(src0,pInst->GetSource(0),1,pInst); Printf(printer,OPCODE_FORMAT " s[M0+%s] = s[%s]\n", "S_MOVRELD_B32", dst, src0 ); } break; case S_MOVRELD_B64: { FormatSReg(dst,pInst->GetDest(),1); FormatSource(src0,pInst->GetSource(0),1,pInst); Printf(printer,OPCODE_FORMAT " s[M0+%s][2] = s[%s][2]\n", "S_MOVRELD_B64", dst, src0 ); } break; case S_MOVRELS_B32: { FormatSReg(dst,pInst->GetDest(),1); FormatSource(src0,pInst->GetSource(0),1,pInst); Printf(printer,OPCODE_FORMAT " s[%s] = s[M0+%s]\n", "S_MOVRELS_B32", dst, src0 ); } break; case S_MOVRELS_B64: { FormatSReg(dst,pInst->GetDest(),1); FormatSource(src0,pInst->GetSource(0),1,pInst); Printf(printer,OPCODE_FORMAT " s[%s][2] = s[M0+%s][2]\n", "S_MOVRELS_B64", dst, src0 ); } break; case S_MOVK_I32 : case S_CMOVK_I32 : case S_CMPK_EQ_I32 : case S_CMPK_LG_I32 : case S_CMPK_GT_I32 : case S_CMPK_GE_I32 : case S_CMPK_LT_I32 : case S_CMPK_LE_I32 : case S_CMPK_EQ_U32 : case S_CMPK_LG_U32 : case S_CMPK_GT_U32 : case S_CMPK_GE_U32 : case S_CMPK_LT_U32 : case S_CMPK_LE_U32 : case S_ADDK_I32 : case S_MULK_I32 : { char dst[64]; FormatDest(dst,pInst->GetDest(),1); Printf( printer, OPCODE_FORMAT " %6s,%6d\n", EnumToString(pInst->GetOpcode()), dst, pInst->GetSIMM16()); } break; case S_SET_GPR_IDX_MODE: { uint nIMM4 = pInst->GetSIMM16(); char flags[256]=""; if( nIMM4 & 1 ) catprintf(flags, ", VSRC0_REL"); if( nIMM4 & 2 ) catprintf(flags, ", VSRC1_REL"); if( nIMM4 & 4 ) catprintf(flags, ", VSRC2_REL"); if( nIMM4 & 8 ) catprintf(flags, ", VDST_REL"); Printf( printer, OPCODE_FORMAT " %s\n", pOpcode,flags); } break; case S_SET_GPR_IDX_ON: { char src0[64]; FormatSource(src0,pInst->GetSource(0),1,pInst); uint nIMM4 = pInst->GetSIMM16(); char flags[256]=""; if( nIMM4 & 1 ) catprintf(flags, ", VSRC0_REL"); if( nIMM4 & 2 ) catprintf(flags, ", VSRC1_REL"); if( nIMM4 & 4 ) catprintf(flags, ", VSRC2_REL"); if( nIMM4 & 8 ) catprintf(flags, ", VDST_REL"); Printf( printer, OPCODE_FORMAT " %6s%s\n", pOpcode, src0,flags); } break; case S_CBRANCH_I_FORK: PrintLabeledBranch(printer,pInst,pLabelName); break; case S_GETREG_B32: case S_SETREG_B32: case S_SETREG_IMM32_B32: { char dst[64]; FormatDest(dst,pInst->GetDest(),1); uint nSize = pInst->ReadSIMMBits(10,6); uint nStart = pInst->ReadSIMMBits(15,11); uint nEnd = nSize+nStart+1; uint nReg = pInst->ReadSIMMBits(5,0); char HWReg[128]; sprintf( HWReg, "HWREG%u(%u:%u)", nReg,nEnd,nStart ); switch( pInst->GetOpcode() ) { case S_GETREG_B32: Printf(printer, OPCODE_FORMAT " %s = %s\n", EnumToString(pInst->GetOpcode()), dst, HWReg ); break; case S_SETREG_B32: Printf(printer, OPCODE_FORMAT " %s = %s\n", EnumToString(pInst->GetOpcode()), HWReg, dst); break; case S_SETREG_IMM32_B32: Printf(printer, OPCODE_FORMAT " %s = %x\n", EnumToString(pInst->GetOpcode()), HWReg, pInst->GetLiteralAsDWORD() & ((1<GetSourceCount() ) { case 2: { FormatSource( src0, pInst->GetSource(0), pInst->GetArg0WidthInDWORDs(), pInst ); FormatSource( src1, pInst->GetSource(1), pInst->GetArg1WidthInDWORDs(), pInst ); FormatDest( dst, pInst->GetDest( ), pInst->GetResultWidthInDWORDs() ); Printf( printer, BINARY_OP_FORMAT, pOpcode, dst, src0, src1 ); } break; case 1: { uint nDstWidth = pInst->GetResultWidthInDWORDs(); uint nSrcWidth = pInst->GetArg0WidthInDWORDs(); const char* pOpcode = EnumToString(pInst->GetOpcode()); FormatSource( src0, pInst->GetSource(0), nSrcWidth, pInst ); FormatDest( dst, pInst->GetDest(), nDstWidth ); Printf( printer, UNARY_OP_FORMAT, pOpcode,dst,src0); } break; default: { Printf(printer,"????SCALAR?????\n"); } break; } } } } void Disassemble( IPrinter& printer, const ScalarMemoryInstruction* pInst ) { char glc[4]=""; if( pInst->IsGLC() ) strcpy(glc,"GLC"); switch( pInst->GetOpcode() ) { case S_LOAD_DWORD : case S_LOAD_DWORDX2 : case S_LOAD_DWORDX4 : case S_LOAD_DWORDX8 : case S_LOAD_DWORDX16 : case S_BUFFER_LOAD_DWORD : case S_BUFFER_LOAD_DWORDX2 : case S_BUFFER_LOAD_DWORDX4 : case S_BUFFER_LOAD_DWORDX8 : case S_BUFFER_LOAD_DWORDX16: case S_STORE_DWORD : case S_STORE_DWORDX2 : case S_STORE_DWORDX4 : case S_BUFFER_STORE_DWORD : case S_BUFFER_STORE_DWORDX2 : case S_BUFFER_STORE_DWORDX4 : { char base[64]; char dest[64]; char offs[64]; uint nBaseReg = pInst->GetBase(); FormatDest( dest, pInst->GetDest(), pInst->GetResultWidthInDWORDs() ); FormatSReg( base, nBaseReg, pInst->GetResourceWidthInDWORDs() ); uint nOffset = pInst->GetOffset(); if( pInst->IsOffsetIMM() ) sprintf( offs, "%u", nOffset ); else FormatSReg( offs, nOffset, 1 ); Printf( printer, OPCODE_FORMAT " %6s, %6s, %6s %s\n", EnumToString(pInst->GetOpcode()), dest, base, offs, glc); } break; case S_ATC_PROBE: case S_ATC_PROBE_BUFFER: { char base[64]; char offs[64]; uint nBaseReg = pInst->GetBase(); FormatSReg( base, nBaseReg, 2 ); uint nOffset = pInst->GetOffset(); if( pInst->IsOffsetIMM() ) sprintf( offs, "%u", nOffset ); else FormatSReg( offs, nOffset, 1 ); Printf( printer, OPCODE_FORMAT " %6s, %6s %s\n", EnumToString(pInst->GetOpcode()), base, offs, glc ); } break; case S_MEMTIME: case S_MEMREALTIME: { char dst[64]; FormatDest(dst,pInst->GetDest(), 2 ); Printf( printer, OPCODE_FORMAT " %6s %s\n", EnumToString(pInst->GetOpcode()),dst, glc); } break; case S_DCACHE_WB: case S_DCACHE_WB_VOL: case S_DCACHE_INV_VOL : case S_DCACHE_INV : Printf( printer, OPCODE_FORMAT " %s \n", EnumToString(pInst->GetOpcode()), glc ); break; default: Printf( printer, OPCODE_FORMAT "\n", "???SMEM???"); break; } } void Disassemble( IPrinter& printer, const VectorInstruction* pInst ) { const char* pOpcode = EnumToString(pInst->GetOpcode()); char src0[64]; char src1[64]; char src2[64]; char vdst[64]; char sdst[64]; char suffixes[64]; uint abs = pInst->GetSourceAbsMask(); uint negate = pInst->GetSourceNegateMask(); // TODO: DXX doesn't seem to use 'omod' and I can't tell what the values are supposed to map to if( pInst->GetOMod() ) sprintf( suffixes, "OMOD(%u)", pInst->GetOMod()); else sprintf( suffixes, "" ); bool clamp = pInst->GetClamp(); if( clamp ) catprintf( suffixes, "CLAMP"); switch( pInst->GetOpcode() ) { case V_MADAK_F16: case V_MADAK_F32: FormatDest(vdst,pInst->GetVDst(),1); FormatVOPSource( src0, 1, pInst->GetSrc0(), (abs & 1) != 0, (negate & 1) != 0, pInst ); FormatVOPSource( src1, 1, pInst->GetVSrc1(), (abs & 2) != 0, (negate & 2) != 0, pInst ); Printf(printer, OPCODE_FORMAT " %6s=%6s*%s + %f\n", pOpcode, vdst, src0, src1, pInst->GetLiteralAsFloat() ); break; case V_MADMK_F16: case V_MADMK_F32: FormatDest(vdst,pInst->GetVDst(),1); FormatVOPSource( src0, 1, pInst->GetSrc0(), (abs & 1) != 0, (negate & 1) != 0, pInst ); FormatVOPSource( src1, 1, pInst->GetVSrc1(), (abs & 2) != 0, (negate & 2) != 0, pInst ); Printf(printer, OPCODE_FORMAT " %6s=%6s *%10f + %s\n", pOpcode, vdst, src0, pInst->GetLiteralAsFloat(), src1 ); break; case V_NOP: Printf( printer, OPCODE_FORMAT"\n", "V_NOP" ); break; case V_CLREXCP: Printf( printer, OPCODE_FORMAT"\n", "V_CLREXCP"); break; case V_MOVRELD_B32: { FormatDest(vdst,pInst->GetVDst(),1); FormatVOPSource(src0,1,pInst->GetSrc0(),abs&1,negate&1,pInst); Printf(printer,OPCODE_FORMAT " v[M0+%s] = v[%s]\n", "V_MOVRELD", vdst, src0 ); } break; case V_MOVRELS_B32: { FormatDest(vdst,pInst->GetVDst(),1); FormatVOPSource(src0,1, pInst->GetSrc0(),abs&1,negate&1,pInst); Printf(printer,OPCODE_FORMAT " v[%s] = v[M0+%s]\n", "V_MOVRELS", vdst, src0 ); } break; case V_MOVRELSD_B32: { FormatDest(vdst,pInst->GetVDst(),1); FormatVOPSource(src0,1, pInst->GetSrc0(),abs&1,negate&1,pInst); Printf(printer,OPCODE_FORMAT " v[M0+%s] = v[M0+%s]\n", "V_MOVRELSD", vdst, src0 ); } break; default: { uint nSrc0Width = pInst->GetSrc0WidthInDWORDS(); uint nSrc1Width = pInst->GetSrc1WidthInDWORDS(); uint nSrc2Width = pInst->GetSrc2WidthInDWORDS(); uint nResultWidth = pInst->GetResultWidthInDWORDS(); FormatDest( vdst, pInst->GetVDst(), nResultWidth ); if( pInst->GetDestCount() == 2 ) { FormatDest( sdst, pInst->GetSDst(), 1 ); char out[64]; sprintf( out, "(%s,%s)", vdst, sdst ); Printf(printer,OPCODE_FORMAT " %10s,",pOpcode,out); } else { Printf(printer,OPCODE_FORMAT " %6s,", pOpcode, vdst ); } switch( pInst->GetSourceCount() ) { case 3: FormatVOPSource( src0, nSrc0Width, pInst->GetSrc0(), (abs & 1) != 0, (negate & 1) != 0, pInst ); FormatVOPSource( src1, nSrc1Width, pInst->GetVSrc1(), (abs & 2) != 0, (negate & 2) != 0, pInst ); FormatVOPSource( src2, nSrc2Width, pInst->GetVSrc2(), (abs & 4) != 0, (negate & 4) != 0, pInst ); Printf(printer, "%6s,%6s,%6s %s\n", src0,src1,src2,suffixes ); break; case 2: FormatVOPSource( src0, nSrc0Width, pInst->GetSrc0(), (abs & 1) != 0, (negate & 1) != 0, pInst ); FormatVOPSource( src1, nSrc1Width, pInst->GetVSrc1(), (abs & 2) != 0, (negate & 2) != 0, pInst ); Printf(printer, "%6s,%6s %s\n", src0,src1,suffixes ); break; case 1: FormatVOPSource( src0, nSrc0Width, pInst->GetSrc0(), (abs & 1) != 0, (negate & 1) != 0, pInst ); Printf(printer, "%6s %s\n", src0,suffixes ); break; } } break; } } void Disassemble( IPrinter& printer, const InterpolationInstruction* pInst ) { uint nSrc = pInst->GetVSrc() - SRC_VGPR_FIRST; char dst[8]; sprintf( dst, "v%u", pInst->GetVDst() - DEST_VGPR_FIRST ); static const char* CHANNELS[] = { "X","Y","Z","W"}; static const char* SOURCES[] = { "P10","P20","P0" }; char op[256]; sprintf( op, "%s(a%0u.%s)", EnumToString(pInst->GetOpcode()), pInst->GetAttributeIndex(), CHANNELS[pInst->GetAttributeChannel()] ); switch(pInst->GetOpcode()) { case V_INTERP_P1LL_F16: case V_INTERP_P1_F32: Printf( printer ,OPCODE_FORMAT " %6s = P10*v%u + P0\n", op, dst, nSrc ); break; case V_INTERP_P2_F16: case V_INTERP_P2_F32: Printf( printer, OPCODE_FORMAT " %6s += P20*v%u\n", op, dst, nSrc ); break; case V_INTERP_MOV_F32:Printf( printer, OPCODE_FORMAT " %6s = %s\n", op, dst, SOURCES[nSrc&3] ); break; default: Printf(printer,"????INTERP????\n"); break; // TODO //V_INTERP_P1LV_F16, // : D.f32 = P10.f16 * S0.f32 + (S2.u32 >> (attr_word * 16)).f16. 'LV' stands for 'One LDS and one VGPR argument'. S2 holds two parameters, attr_word selects the high or low word of the VGPR for this calculation, as well as the high or low half of the LDS data." Meant for use with 16-bank LDS. NOTE: In textual representations the I/J VGPR is the first source and the attribute is the second source; however in the VOP3 encoding the attribute is stored in the src0 field and the VGPR is stored in the src1 field. } } void Disassemble( IPrinter& printer, const ExportInstruction* pInst ) { uint nTarget = pInst->GetTarget(); uint nRegMask = pInst->GetExportMask(); char r[4][8]; sprintf( r[0], "v%u", pInst->GetVSrc0() - SRC_VGPR_FIRST ); sprintf( r[1], "v%u", pInst->GetVSrc1() - SRC_VGPR_FIRST ); sprintf( r[2], "v%u", pInst->GetVSrc2() - SRC_VGPR_FIRST ); sprintf( r[3], "v%u", pInst->GetVSrc3() - SRC_VGPR_FIRST ); const char* pOpcode = pInst->GetCompressBit() ? "EXP_FP16" : "EXP"; char flags[256]; sprintf(flags, "(%s%s%s)", EnumToString(pInst->GetTarget()), pInst->GetValidMaskBit() ? ",VM" : "", pInst->GetDoneBit() ? ",DONE" : "" ); Printf( printer, OPCODE_FORMAT " %6s,%4s,%4s,%4s %s\n", pOpcode, nRegMask&1 ? r[0] : "____", nRegMask&2 ? r[1] : "____", nRegMask&4 ? r[2] : "____", nRegMask&8 ? r[3] : "____", flags ); } template< class BUFFInstruction > void FormatBuffAddress( char* offset, const BUFFInstruction* pInst ) { if( pInst->IsAddr64() ) { // address is: resource_base + soffset+ioffset + vgpr[2] if( pInst->GetSOffset() != SRC_C_ZERO ) FormatGenericSource(offset,pInst->GetSOffset(), 1 ); if( pInst->GetOffset() ) addprintf( offset, "%u", pInst->GetOffset() ); // send voffset[2] as full address char reg[64]; FormatVReg( reg, pInst->GetVAddr(), 2 ); addprintf(offset, "%s", reg ); } else { // address is: resource_base + soffset+(ioffset or vgpr) + resource_stride*(vgpr_idx) // byte offset if( pInst->GetSOffset() != SRC_C_ZERO ) FormatGenericSource(offset,pInst->GetSOffset(), 1 ); if( !pInst->IsOffN() ) { // send literal offset from instruction if( pInst->GetOffset() ) addprintf( offset, "%u", pInst->GetOffset() ); } else { // send vaddr gpr as offset. If both index and offset are used, offset is the second one Sources nOffsetReg = pInst->GetVAddr(); if( pInst->IsIdxN() ) nOffsetReg = (Sources)(nOffsetReg+1); char reg[64]; FormatVSrc( reg, nOffsetReg, 1 ); addprintf( offset, "%s", reg ); } if( pInst->IsIdxN() ) { char idx[64]; FormatVSrc( idx, pInst->GetVAddr(), 1 ); // vaddr as an index addprintf( offset, "%s*STRIDE", idx ); } } } template< class BUFFInstruction > void FormatBuffFlags( char* flags, const BUFFInstruction* pInst ) { if( pInst->GetTFEBit() ) addprintf(flags,"TFE"); if( pInst->GetGLCBit() ) addprintf(flags,"GLC"); if( pInst->GetSLCBit() ) addprintf(flags,"SLC"); } void Disassemble( IPrinter& printer, const BufferInstruction* pInst ) { uint nResultWidth = pInst->GetResultWidthInDWORDS(); if( !nResultWidth ) { // oddballs like cache invalidation Printf( printer, OPCODE_FORMAT"\n", EnumToString(pInst->GetOpcode()) ); } else { // destination char dst[64]; if( pInst->IsDirectToLDS()) sprintf(dst,"LDS[M0]"); else FormatVSrc( dst, pInst->GetVData(), nResultWidth ); // resource constant char rsrc[64]=""; FormatSReg(rsrc, pInst->GetSResource(), 4 ); // address char address[256]=""; FormatBuffAddress(address,pInst); // flags char flags[256]=""; FormatBuffFlags(flags,pInst); // format char fmt[256]= ""; if( pInst->IsTBuffer() ) sprintf( fmt, "%s_%s", EnumToString(pInst->GetDataFormat()), EnumToString(pInst->GetNumberFormat()) ); Printf( printer, OPCODE_FORMAT " %6s, %8s [%s] %s %s\n", EnumToString(pInst->GetOpcode()), dst, rsrc,address,fmt,flags); } } void Disassemble( IPrinter& printer, const ImageInstruction* pInst ) { char sampler[64] = ""; char resource[64] = ""; uint nResourceWidth = pInst->GetResourceWidthInDWORDS(); uint nSamplerWidth = pInst->GetSamplerWidthInDWORDS(); if( nSamplerWidth ) FormatGenericSource( sampler, pInst->GetSSampler(), nSamplerWidth ); if( nResourceWidth ) FormatGenericSource( resource, pInst->GetSResource(), nResourceWidth ); char dmask[64]=""; uint nDMask = pInst->GetDMask(); if( nDMask & 1 ) catprintf(dmask, "R"); if( nDMask & 2 ) catprintf(dmask, "G"); if( nDMask & 4 ) catprintf(dmask, "B"); if( nDMask & 8 ) catprintf(dmask, "A"); char flags[256] = ""; if( pInst->IsGLC() ) addprintf(flags,"GLC"); if( pInst->IsSLC() ) addprintf(flags,"SLC"); if( pInst->IsLWE() ) addprintf(flags,"LWE"); if( pInst->IsTFE() ) addprintf(flags,"TFE"); if( pInst->IsArray() ) addprintf(flags,"ARRAY"); if( pInst->IsUnnormalized() ) addprintf( flags,"UNNORM"); if( pInst->IsD16() ) addprintf(flags,"D16"); // NOTE: There is no way to infer the address width, because // it depends on the resource dimension, which in turn depends on the descriptor // char vaddr[64]=""; char vdata[64]=""; FormatVSrc(vaddr,pInst->GetVAddr(),1); FormatVSrc(vdata,pInst->GetVData(),pInst->GetResultWidthInDWORDS()); char opcode[512]; sprintf( opcode, "%s(%s)", EnumToString(pInst->GetOpcode()),dmask); Printf(printer,OPCODE_FORMAT " %6s,%6s, T:%6s", opcode,vdata,vaddr,resource); if( nSamplerWidth ) Printf(printer,", S:%6s",sampler); Printf(printer," %s\n", flags); } static void FormatDSAddress( char* pBuff, Sources nReg, uint nOffset ) { char A[64]; FormatVReg(A,nReg-SRC_VGPR_FIRST,1); if( nOffset ) sprintf(pBuff,"DS[%s+%u]", A,nOffset ); else sprintf(pBuff,"DS[%s]", A ); } void Disassemble( IPrinter& printer, const DataShareInstruction* pInst ) { char opcode[256]; sprintf(opcode, "%s%s", EnumToString(pInst->GetOpcode()), pInst->IsGDS() ? "(GDS)":""); switch( pInst->GetOpcode() ) { // oddballs default: case DS_NOP: Printf( printer, OPCODE_FORMAT"\n", opcode ); break; case DS_PERMUTE_B32: case DS_BPERMUTE_B32: case DS_SWIZZLE_B32 : // R = swizzle(Data(vgpr), offset1:offset0). Dword swizzle. no data is written to LDS. see ds_opcodes.docx for details. { char R[64]; char D[64]; FormatVSrc(R,pInst->GetVData0(), 1); FormatVDest(D,pInst->GetVDest(), 1 ); Printf( printer, OPCODE_FORMAT" %6s,%6s, 0x%04x\n", opcode, R, D, pInst->GetOffset16() ); } break; case DS_GWS_SEMA_RELEASE_ALL: // GDS Only. Release all wavefronts waiting on this semaphore. ResourceID is in offset[4:0]. SEA ISLANDS ONLY case DS_GWS_INIT : // GDS only. case DS_GWS_SEMA_V : // GDS only. case DS_GWS_SEMA_BR : // GDS only. case DS_GWS_SEMA_P : // GDS only. case DS_GWS_BARRIER : // GDS only. { uint nSemaphoreID = pInst->GetOffset16()& (0x1f); Printf( printer, OPCODE_FORMAT" %u\n", EnumToString(pInst->GetOpcode()),nSemaphoreID); } break; // 1 address, 1 data case DS_ADD_U32 : // DS[A] = DS[A] + D0; uint add. case DS_SUB_U32 : // DS[A] = DS[A] - D0; uint subtract. case DS_RSUB_U32 : // DS[A] = D0 - DS[A]; uint reverse subtract. case DS_INC_U32 : // DS[A] = (DS[A] >= D0 ? 0 : DS[A] + 1); uint increment. case DS_DEC_U32 : // DS[A] = (DS[A] == 0 || DS[A] > D0 ? D0 : DS[A] - 1); uint decrement. case DS_MIN_I32 : // DS[A] = min(DS[A], D0); int min. case DS_MAX_I32 : // DS[A] = max(DS[A], D0); int max. case DS_MIN_U32 : // DS[A] = min(DS[A], D0); uint min. case DS_MAX_U32 : // DS[A] = max(DS[A], D0); uint max. case DS_AND_B32 : // DS[A] = DS[A] & D0; Dword AND. case DS_OR_B32 : // DS[A] = DS[A] | D0; Dword OR. case DS_XOR_B32 : // DS[A] = DS[A] ^ D0; Dword XOR. case DS_MSKOR_B32 : // DS[A] = (DS[A] ^ ~D0) | D1; masked Dword OR. case DS_WRITE_B32 : // DS[A] = D0; write a Dword. case DS_WRITE_B8 : // DS[A] = D0[7:0]; byte write. case DS_WRITE_B16 : // DS[A] = D0[15:0]; short write. case DS_ADD_U64 : // Uint add. case DS_SUB_U64 : // Uint subtract. case DS_RSUB_U64 : // Uint reverse subtract. case DS_INC_U64 : // Uint increment. case DS_DEC_U64 : // Uint decrement. case DS_MIN_I64 : // Int min. case DS_MAX_I64 : // Int max. case DS_MIN_U64 : // Uint min. case DS_MAX_U64 : // Uint max. case DS_AND_B64 : // Dword AND. case DS_OR_B64 : // Dword OR. case DS_XOR_B64 : // Dword XOR. case DS_MSKOR_B64 : // Masked Dword XOR. case DS_WRITE_B64 : // Write. case DS_MIN_F64 : // DS[A] = (D0 < DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. case DS_MAX_F64 : // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. case DS_MAX_F32 : // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. case DS_WRITE_B96 : //{DS[A+2], DS[A+1], DS[A]} = D0[95:0]; tri-dword write. case DS_WRITE_B128 : //{DS[A+3], DS[A+2], DS[A+1], DS[A]} = D0[127:0]; qword write. { char D[64]; FormatVSrc(D,pInst->GetVData0(),pInst->GetDataWidthInDWORDS() ); char A[64]; FormatVSrc(A,pInst->GetVAddr(), pInst->GetOffset16()); Printf(printer,OPCODE_FORMAT" %6s, %s\n", opcode, D, A ); } break; // address + result case DS_READ_B32 : // R = DS[A]; Dword read. case DS_READ_I8 : // R = signext(DS[A][7:0]}; signed byte read. case DS_READ_U8 : // R = {24h0,DS[A][7:0]}; unsigned byte read. case DS_READ_I16 : // R = signext(DS[A][15:0]}; signed short read. case DS_READ_U16 : // R = {16h0,DS[A][15:0]}; unsigned short read. case DS_READ_B64 : // Dword read. case DS_READ_B96 : //Tri-Dword read. case DS_READ_B128 : //Qword read. { char Dst[64]; FormatVDest(Dst,pInst->GetVDest(),pInst->GetDataWidthInDWORDS() ); char A[64]; FormatDSAddress(A,pInst->GetVAddr(), pInst->GetOffset16()); Printf(printer,OPCODE_FORMAT" %6s, %s\n", opcode, Dst, A ); } break; // 1 address, 1 data, 1 return (return atomics, cas) // NOTE: Some of these I'm not sure about, but am erring on the side of caution // Docs are not very explicit about some of these... case DS_MIN_F32 : // DS[A] = (DS[A] < D1) ? D0 : DS[A]; float compare swap (handles NaN/INF/denorm). NOTE: Doc says this uses D1 and D0. Typo?? case DS_CMPST_B32 : // DS[A] = (DS[A] == D0 ? D1 : DS[A]); compare store. case DS_CMPST_F32 : // DS[A] = (DS[A] == D0 ? D1 : DS[A]); compare store with float rules. case DS_ADD_RTN_U32 : // Uint add. case DS_SUB_RTN_U32 : // Uint subtract. case DS_RSUB_RTN_U32 : // Uint reverse subtract. case DS_INC_RTN_U32 : // Uint increment. case DS_DEC_RTN_U32 : // Uint decrement. case DS_MIN_RTN_I32 : // Int min. case DS_MAX_RTN_I32 : // Int max. case DS_MIN_RTN_U32 : // Uint min. case DS_MAX_RTN_U32 : // Uint max. case DS_AND_RTN_B32 : // Dword AND. case DS_OR_RTN_B32 : // Dword OR. case DS_XOR_RTN_B32 : // Dword XOR. case DS_MSKOR_RTN_B32 : // Masked Dword OR. case DS_MIN_RTN_F32 : // DS[A] = (DS[A] < D1) ? D0 : DS[A]; float compare swap (handles NaN/INF/denorm). case DS_MAX_RTN_F32 : // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm . case DS_WRAP_RTN_B32 : // DS[A] = (DS[A] >= D0) ? DS[A] - D0 : DS[A] + D1. SEA ISLANDS ONLY case DS_CMPST_B64 : // Compare store. case DS_CMPST_F64 : // Compare store with float rules. case DS_ADD_RTN_U64 : // Uint add. case DS_SUB_RTN_U64 : // Uint subtract. case DS_RSUB_RTN_U64 : // Uint reverse subtract. case DS_INC_RTN_U64 : // Uint increment. case DS_DEC_RTN_U64 : // Uint decrement. case DS_MIN_RTN_I64 : // Int min. case DS_MAX_RTN_I64 : // Int max. case DS_MIN_RTN_U64 : // Uint min. case DS_MAX_RTN_U64 : // Uint max. case DS_AND_RTN_B64 : // Dword AND. case DS_OR_RTN_B64 : // Dword OR. case DS_XOR_RTN_B64 : // Dword XOR. case DS_MSKOR_RTN_B64 : // Masked Dword XOR. case DS_CMPST_RTN_B64 : // Compare store. case DS_CMPST_RTN_F64 : // Compare store with float rules. case DS_MIN_RTN_F64 : // DS[A] = (D0 < DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. case DS_MAX_RTN_F64 : // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. case DS_WRXCHG_RTN_B32 : // Write exchange. Offset = {offset1,offset0}. A = ADDR+offset. D=DS[Addr]. DS[Addr]=D0. case DS_WRXCHG_RTN_B64 : // Write exchange. case DS_CONSUME : // Consume entries from a buffer. case DS_APPEND : // Append one or more entries to a buffer. case DS_ORDERED_COUNT : // Increment an append counter. Operation is done in order of wavefront creation. { char Dst[64]; char Arg[64]; FormatVDest(Dst,pInst->GetVDest(),pInst->GetDataWidthInDWORDS() ); FormatVSrc(Arg,pInst->GetVData0(),pInst->GetDataWidthInDWORDS() ); char A[64]; FormatDSAddress(A,pInst->GetVAddr(),pInst->GetOffset16()); Printf(printer,OPCODE_FORMAT" %6s,%6s, %s\n", opcode, Dst,Arg, A ); } break; // 1 address, 2 data, 1 return case DS_CMPST_RTN_B32 : // Compare store. case DS_CMPST_RTN_F32 : // Compare store with float rules. case DS_CONDXCHG32_RTN_B128 : // Conditional write exchange. case DS_CONDXCHG32_RTN_B64 : // Conditional write exchange. SEA ISLANDS ONLY { char Dst[64]; char Arg0[64]; char Arg1[64]; FormatVDest(Dst,pInst->GetVDest(),pInst->GetDataWidthInDWORDS() ); FormatVSrc(Arg0,pInst->GetVData0(),pInst->GetDataWidthInDWORDS() ); FormatVSrc(Arg1,pInst->GetVData1(),1); char A[64]; FormatDSAddress(A,pInst->GetVAddr(),pInst->GetOffset16()); Printf(printer,OPCODE_FORMAT" %6s,%6s,%6s %s\n", opcode, Dst,Arg0, Arg1, A ); } break; // 2 address, 2 data (2x write) case DS_WRITE2_B32 : // DS[ADDR+offset0*4] = D0;DS[ADDR+offset1*4] = D1; write 2 Dwords. case DS_WRITE2ST64_B32 : // DS[ADDR+offset0*4*64] = D0;DS[ADDR+offset1*4*64] = D1; write 2 Dwords. case DS_WRITE2_B64 : // DS[ADDR+offset0*8] = D0;DS[ADDR+offset1*8] = D1; write 2 Dwords. case DS_WRITE2ST64_B64 : // DS[ADDR+offset0*8*64] = D0; DS[ADDR+offset1*8*64] = D1; write 2 Dwords. case DS_WRXCHG2_RTN_B64 : // Write exchange 2 dwords. case DS_WRXCHG2_RTN_B32 : // Write exchange 2 separate Dwords. { uint nAddressMultiplier=0; switch( pInst->GetOpcode() ) { case DS_WRXCHG2ST64_RTN_B64 : nAddressMultiplier=64; break; case DS_WRXCHG2ST64_RTN_B32 : nAddressMultiplier=64; break; case DS_WRITE2_B32 : nAddressMultiplier=4; break; case DS_WRITE2ST64_B32 : nAddressMultiplier=4*64; break; case DS_WRITE2_B64 : nAddressMultiplier=8; break; case DS_WRITE2ST64_B64 : nAddressMultiplier=8*64; break; } uint nDataWidth = pInst->GetDataWidthInDWORDS(); char D0[64]; char D1[64]; FormatVSrc( D0, pInst->GetVData0(), nDataWidth ); FormatVSrc( D1, pInst->GetVData1(), nDataWidth ); char A0[64]; char A1[64]; uint nOffs0 = pInst->GetOffset0()*nAddressMultiplier; uint nOffs1 = pInst->GetOffset1()*nAddressMultiplier; FormatDSAddress(A0,pInst->GetVAddr(),nOffs0); FormatDSAddress(A1,pInst->GetVAddr(),nOffs1); Printf(printer,OPCODE_FORMAT" %6s,%6s, %s %s\n", opcode, D0,D1, A0,A1 ); } break; // 2 address, 1 data (read2) case DS_READ2_B32 : // R = DS[ADDR+offset0*4], R+1 = DS[ADDR+offset1*4]. Read 2 Dwords. case DS_READ2ST64_B32 : // R = DS[ADDR+offset0*4*64], R+1 = DS[ADDR+offset1*4*64]. Read 2 Dwords. case DS_READ2_B64 : // R = DS[ADDR+offset0*8], R+1 = DS[ADDR+offset1*8]. Read 2 Dwords case DS_READ2ST64_B64 : // R = DS[ADDR+offset0*8*64], R+1 = DS[ADDR+offset1*8*64]. Read 2 Dwords. { uint nAddressMultiplier=0; switch( pInst->GetOpcode() ) { case DS_READ2_B32 : nAddressMultiplier=4; break; case DS_READ2ST64_B32 : nAddressMultiplier=4*64; break; case DS_READ2_B64 : nAddressMultiplier=8; break; case DS_READ2ST64_B64 : nAddressMultiplier=8*64; break; } uint nDataWidth = pInst->GetDataWidthInDWORDS(); char Dst[64]; FormatVDest(Dst,pInst->GetVDest(),nDataWidth ); char A0[64]; char A1[64]; uint nOffs0 = pInst->GetOffset0()*nAddressMultiplier; uint nOffs1 = pInst->GetOffset1()*nAddressMultiplier; FormatDSAddress(A0,pInst->GetVAddr(),nOffs0); FormatDSAddress(A1,pInst->GetVAddr(),nOffs1); Printf(printer,OPCODE_FORMAT" %6s, %s %s\n", opcode, Dst, A0,A1 ); } break; // weird stuff case DS_ADD_SRC2_U32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] + DS[B]; uint add. case DS_SUB_SRC2_U32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] - DS[B]; uint subtract. case DS_RSUB_SRC2_U32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[B]- DS[A]; uint reverse subtract. case DS_INC_SRC2_U32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = (DS[A] >= DS[B] ? 0 : DS[A] + 1); uint increment. case DS_DEC_SRC2_U32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = (DS[A]== 0 || DS[A] > DS[B] ? DS[B] : DS[A] - 1); uintdecrement. case DS_MIN_SRC2_I32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] =min(DS[A], DS[B]); int min. case DS_MAX_SRC2_I32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] =max(DS[A], DS[B]); int max. case DS_MIN_SRC2_U32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = min(DS[A], DS[B]); uint min. case DS_MAX_SRC2_U32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] =max(DS[A], DS[B]); uint maxw case DS_AND_SRC2_B32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A]& DS[B]; Dword AND. case DS_OR_SRC2_B32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] |DS[B]; Dword OR. case DS_XOR_SRC2_B32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] ^DS[B]; Dword XOR. case DS_WRITE_SRC2_B32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = DS[B];write Dword. case DS_MIN_SRC2_F32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = (DS[B] < DS[A]) ? DS[B] : DS[A]; float, handles NaN/INF/denorm. case DS_MAX_SRC2_F32 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = (DS[B] > DS[A]) ? DS[B] : DS[A]; float, handles NaN/INF/denorm. case DS_ADD_SRC2_U64 : // Uint add. case DS_SUB_SRC2_U64 : // Uint subtract. case DS_RSUB_SRC2_U64 : // Uint reverse subtract. case DS_INC_SRC2_U64 : // Uint increment. case DS_DEC_SRC2_U64 : // Uint decrement. case DS_MIN_SRC2_I64 : // Int min. case DS_MAX_SRC2_I64 : // Int max. case DS_MIN_SRC2_U64 : // Uint min. case DS_MAX_SRC2_U64 : // Uint max. case DS_AND_SRC2_B64 : // Dword AND. case DS_OR_SRC2_B64 : // Dword OR. case DS_XOR_SRC2_B64 : // Dword XOR. case DS_WRITE_SRC2_B64 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = DS[B]; write Qword. case DS_MIN_SRC2_F64 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). [A] = (D0 < DS[A]) ? D0 : DS[A]; float, handlesNaN/INF/denorm. case DS_MAX_SRC2_F64 : // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). [A] = (D0 > DS[A]) ? D0 : DS[A]; float, handlesNaN/INF/denorm. { char Addr[64]; FormatVSrc(Addr,pInst->GetVAddr(),1); Printf(printer,OPCODE_FORMAT" %6s, off0(0x%02x),off1(0x%02x)\n", Addr, pInst->GetOffset0(),pInst->GetOffset0()); } break; } } static void Disassemble( IPrinter& printer, const Instruction* pInst, const char* pLabelName ) { switch( pInst->GetClass() ) { case IC_SCALAR: _INTERNAL::Disassemble( printer, (const ScalarInstruction*)pInst, pLabelName ); break; case IC_SCALAR_MEM: _INTERNAL::Disassemble( printer, (const ScalarMemoryInstruction*)pInst ); break; case IC_VECTOR: _INTERNAL::Disassemble( printer, (const VectorInstruction*)pInst ); break; case IC_VECTOR_INTERP: _INTERNAL::Disassemble( printer, (const InterpolationInstruction*)pInst ); break; case IC_EXPORT: _INTERNAL::Disassemble( printer, (const ExportInstruction*) pInst ); break; case IC_DS: _INTERNAL::Disassemble( printer, (const DataShareInstruction*)pInst ); break; case IC_BUFFER: _INTERNAL::Disassemble( printer, (const BufferInstruction*)pInst); break; case IC_IMAGE: _INTERNAL::Disassemble( printer, (const ImageInstruction*) pInst ); break; default: _INTERNAL::Printf( printer, "No disassembler for instruction at 0x%016x.\n", pInst ); break; } } } void Disassemble( IPrinter& printer, const Instruction* pOp, const char* pLabelName ) { char n[128]=""; if( !pLabelName && pOp->GetClass() == IC_SCALAR ) { const GCN::ScalarInstruction* pScalar = static_cast(pOp); _INTERNAL::SynthesizeLabelName(n,pScalar,0); pLabelName = n; } _INTERNAL::Disassemble(printer, pOp, pLabelName); } bool DisassembleProgram( IDecoder& decoder, IPrinter& printer, const void* pISA, size_t nISASize ) { std::vector Labels; std::vector Branches; // first pass to identify basic blocks and validate encodings const uint8* pInst = (const uint8*) pISA; const uint8* pEnd = pInst + nISASize; while( pInst < pEnd ) { InstructionFormat eFormat = decoder.ReadInstructionFormat( pInst ); const uint32* pDWORDS = reinterpret_cast(pInst); if( eFormat == IF_UNKNOWN ) { _INTERNAL::Printf( printer, "ERROR: Can't determine encoding for instruction at: 0x%016x\n", pInst ); _INTERNAL::Printf( printer, "First DWORD is: 0x%08x\n", pDWORDS[0] ); return false; } size_t nLength = decoder.DetermineInstructionLength(pInst,eFormat); if( (pInst+nLength) > pEnd ) { _INTERNAL::Printf( printer, "ERROR: Instruction at: 0x%016x overruns specified buffer\n", pInst ); return false; } if( nLength == 0 || nLength%4 != 0 ) { _INTERNAL::Printf( printer, "INTERNAL ERROR: Bad length deduced for instruction at: 0x%016x\n", pInst ); return false; } Instruction tmp; decoder.Decode( &tmp, pInst, eFormat ); if( tmp.GetClass() == IC_SCALAR ) { const ScalarInstruction* pI = static_cast(&tmp); if( pI->IsControlFlowOp() ) { Branches.push_back( pInst ); const uint8* pTarget = pI->GetBranchTarget(); if( pTarget ) Labels.push_back(pTarget); } } pInst += nLength; } std::sort( Labels.begin(), Labels.end() ); Branches.push_back( pEnd ); // so there's always at least one Labels.push_back( pEnd ); size_t nLabel = 0; size_t nBranch = 0; pInst = (const uint8*)pISA; while( pInst < pEnd ) { InstructionFormat eFormat = decoder.ReadInstructionFormat( pInst ); // print labels if( pInst == Labels[nLabel] ) { _INTERNAL::Printf(printer, "Label_%04u:\n", nLabel ); nLabel++; } // disassemble instruction Instruction tmp; decoder.Decode( &tmp, pInst, eFormat ); // resolve label names for branch targets char name[128]=""; if( tmp.GetClass() == GCN::IC_SCALAR ) _INTERNAL::SynthesizeLabelName(name, static_cast(&tmp),&Labels); _INTERNAL::Disassemble(printer,&tmp,name); // extra newline after a branch or before a label if( pInst == Branches[nBranch] ) { printer.Push("\n"); nBranch++; } else if( pInst == Labels[nLabel] ) { printer.Push("\n"); } pInst += decoder.DetermineInstructionLength(pInst,eFormat); } return true; } bool ListEncodings( IDecoder& decoder, IPrinter& printer, const void* pISA, size_t nISASize ) { const uint8* pInst = (const uint8*)pISA; const uint8* pEnd = ((const uint8*)pISA) + nISASize; while( pInst < pEnd ) { InstructionFormat eFormat = decoder.ReadInstructionFormat( pInst ); const uint32* pDWORDS = reinterpret_cast(pInst); if( eFormat == IF_UNKNOWN ) { _INTERNAL::Printf( printer, "ERROR: Can't determine encoding for instruction at: 0x%016x\n", pInst ); _INTERNAL::Printf( printer, "First DWORD is: 0x%08x\n", pDWORDS[0] ); return false; } size_t nLength = decoder.DetermineInstructionLength(pInst,eFormat); if( (pInst+nLength) > pEnd ) { _INTERNAL::Printf( printer, "ERROR: Instruction at: 0x%016x overruns specified buffer\n", pInst ); return false; } if( nLength == 0 || nLength%4 != 0 ) { _INTERNAL::Printf( printer, "INTERNAL ERROR: Bad length deduced for instruction at: 0x%016x\n", pInst ); return false; } switch( eFormat ) { case IF_SOP2: printer.Push("SOP2 "); break; case IF_SOPK: printer.Push("SOPK "); break; case IF_SOP1: printer.Push("SOP1 "); break; case IF_SOPC: printer.Push("SOPC "); break; case IF_SOPP: printer.Push("SOPP "); break; case IF_SMEM: printer.Push("SMEM "); break; case IF_SMRD: printer.Push("SMRD "); break; case IF_VOP2: printer.Push("VOP2 "); break; case IF_VOP1: printer.Push("VOP1 "); break; case IF_VOPC: printer.Push("VOPC "); break; case IF_VOP3: printer.Push("VOP3 "); break; case IF_VINTERP: printer.Push("VINTERP "); break; case IF_DS: printer.Push("DS "); break; case IF_MTBUFF: printer.Push("MTBUFF "); break; case IF_MUBUFF: printer.Push("MUBUFF "); break; case IF_MIMG: printer.Push("MIMG "); break; case IF_EXP: printer.Push("EXP "); break; case IF_FLAT: printer.Push("FLAT "); break; } for( uint i=0; i>S1.u[4:0]) & ((1<>S1.u[4:0]) & ((1<> 1) << 24 + ENUM(V_ALIGNBIT_B32 )// = D.u = ({S0,S1} >> S2.u[4:0]) & 0xFFFFFFFF. ENUM(V_ALIGNBYTE_B32 )// = D.u = ({S0,S1} >> (8*S2.u[4:0])) & 0xFFFFFFFF. ENUM(V_MULLIT_F32 )// = D.f = S0.f * S1.f, replicate result into 4 components (0.0 * x = 0.0; special INF, NaN, overflow rules). ENUM(V_MIN3_F32 )// = D.f = min(S0.f, S1.f, S2.f). ENUM(V_MIN3_I32 )// = D.i = min(S0.i, S1.i, S2.i). ENUM(V_MIN3_U32 )// = 0x153 D.u = min(S0.u, S1.u, S2.u). ENUM(V_MAX3_F32 )// = D.f = max(S0.f, S1.f, S2.f). ENUM(V_MAX3_I32 )// = D.i = max(S0.i, S1.i, S2.i). ENUM(V_MAX3_U32 )// = D.u = max(S0.u, S1.u, S2.u). ENUM(V_MED3_F32 )// = D.f = median(S0.f, S1.f, S2.f). ENUM(V_MED3_I32 )// = D.i = median(S0.i, S1.i, S2.i). ENUM(V_MED3_U32 )// = D.u = median(S0.u, S1.u, S2.u). ENUM(V_SAD_U8 )// = D.u = Byte SAD with accum_lo(S0.u, S1.u, S2.u). ENUM(V_SAD_HI_U8 )// = D.u = Byte SAD with accum_hi(S0.u, S1.u, S2.u). ENUM(V_SAD_U16 )// = D.u = Word SAD with accum(S0.u, S1.u, S2.u). ENUM(V_SAD_U32 )// = D.u = Dword SAD with accum(S0.u, S1.u, S2.u). ENUM(V_CVT_PK_U8_F32 )// = f32->u8(s0.f), pack into byte(s1.u), of dword(s2). ENUM(V_DIV_FIXUP_F32 )// = D.f = Special case divide fixup and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). ENUM(V_DIV_FIXUP_F64 )// = D.d = Special case divide fixup and flags(s0.d = Quotient, s1.d = Denominator, s2.d = Numerator). ENUM(V_LSHL_B64 )// = D = S0.u << S1.u[4:0]. ENUM(V_LSHR_B64 )// = D = S0.u >> S1.u[4:0]. ENUM(V_ASHR_I64 )// = D = S0.u >> S1.u[4:0]. ENUM(V_ADD_F64 )// = D.d = S0.d + S1.d. ENUM(V_MUL_F64 )// = D.d = S0.d * S1.d. ENUM(V_MIN_F64 )// = D.d = min(S0.d, S1.d). ENUM(V_MAX_F64 )// = D.d = max(S0.d, S1.d). ENUM(V_LDEXP_F64 )// = D.d = pow(S0.d, S1.i[31:0]). ENUM(V_MUL_LO_U32 )// = D.u = S0.u * S1.u. ENUM(V_MUL_HI_U32 )// = D.u = (S0.u * S1.u)>>32. ENUM(V_MUL_LO_I32 )// = D.i = S0.i * S1.i. ENUM(V_MUL_HI_I32 )// = D.i = (S0.i * S1.i)>>32. ENUM(V_DIV_FMAS_F32 ) ENUM(V_DIV_FMAS_F64 ) ENUM(V_MSAD_U8 ) ENUM(V_QSAD_U8 ) ENUM(V_MQSAD_U8 ) ENUM(V_QSAD_PK_U16_U8 ) ENUM(V_MQSAD_PK_U16_U8 ) ENUM(V_TRIG_PREOP_F64 ) ENUM(V_MQSAD_U32_U8 ) ENUM(V_MAD_U64_U32 ) ENUM(V_MAD_I64_I32 ) ENUM( V_ADD_F16 ) ENUM( V_SUB_F16 ) ENUM( V_SUBREV_F16 ) ENUM( V_MUL_F16 ) ENUM( V_MAC_F16 ) ENUM( V_MADMK_F16 ) ENUM( V_MADAK_F16 ) ENUM( V_ADD_U16 ) ENUM( V_SUB_U16 ) ENUM( V_SUBREV_U16 ) ENUM( V_MUL_LO_U16 ) ENUM( V_LSHLREV_B16 ) ENUM( V_LSHRREV_B16 ) ENUM( V_ASHRREV_I16 ) ENUM( V_MAX_F16 ) ENUM( V_MIN_F16 ) ENUM( V_MAX_U16 ) ENUM( V_MAX_I16 ) ENUM( V_MIN_U16 ) ENUM( V_MIN_I16 ) ENUM( V_LDEXP_F16 ) ENUM(V_CVT_F16_U16 ) ENUM(V_CVT_F16_I16 ) ENUM(V_CVT_U16_F16 ) ENUM(V_CVT_I16_F16 ) ENUM(V_RCP_F16 ) ENUM(V_SQRT_F16 ) ENUM(V_RSQ_F16 ) ENUM(V_LOG_F16 ) ENUM(V_EXP_F16 ) ENUM(V_FREXP_MANT_F16 ) ENUM(V_FREXP_EXP_I16_F16 ) ENUM(V_FLOOR_F16 ) ENUM(V_CEIL_F16 ) ENUM(V_TRUNC_F16 ) ENUM(V_RNDNE_F16 ) ENUM(V_FRACT_F16 ) ENUM(V_SIN_F16 ) ENUM(V_COS_F16 ) ENUM(V_CMP_F_F16 ) ENUM(V_CMP_LT_F16 ) ENUM(V_CMP_EQ_F16 ) ENUM(V_CMP_LE_F16 ) ENUM(V_CMP_GT_F16 ) ENUM(V_CMP_LG_F16 ) ENUM(V_CMP_GE_F16 ) ENUM(V_CMP_O_F16 ) ENUM(V_CMP_U_F16 ) ENUM(V_CMP_NGE_F16 ) ENUM(V_CMP_NLG_F16 ) ENUM(V_CMP_NGT_F16 ) ENUM(V_CMP_NLE_F16 ) ENUM(V_CMP_NEQ_F16 ) ENUM(V_CMP_NLT_F16 ) ENUM(V_CMP_TRU_F16 ) ENUM(V_CMPX_F_F16 ) ENUM(V_CMPX_LT_F16 ) ENUM(V_CMPX_EQ_F16 ) ENUM(V_CMPX_LE_F16 ) ENUM(V_CMPX_GT_F16 ) ENUM(V_CMPX_LG_F16 ) ENUM(V_CMPX_GE_F16 ) ENUM(V_CMPX_O_F16 ) ENUM(V_CMPX_U_F16 ) ENUM(V_CMPX_NGE_F16 ) ENUM(V_CMPX_NLG_F16 ) ENUM(V_CMPX_NGT_F16 ) ENUM(V_CMPX_NLE_F16 ) ENUM(V_CMPX_NEQ_F16 ) ENUM(V_CMPX_NLT_F16 ) ENUM(V_CMPX_TRU_F16 ) ENUM(V_CMP_F_U16 ) ENUM(V_CMP_LT_U16 ) ENUM(V_CMP_EQ_U16 ) ENUM(V_CMP_LE_U16 ) ENUM(V_CMP_GT_U16 ) ENUM(V_CMP_LG_U16 ) ENUM(V_CMP_GE_U16 ) ENUM(V_CMP_TRU_U16 ) ENUM(V_CMPx_F_U16 ) ENUM(V_CMPx_LT_U16 ) ENUM(V_CMPx_EQ_U16 ) ENUM(V_CMPx_LE_U16 ) ENUM(V_CMPx_GT_U16 ) ENUM(V_CMPx_LG_U16 ) ENUM(V_CMPx_GE_U16 ) ENUM(V_CMPx_TRU_U16 ) ENUM(V_CMP_F_I16 ) ENUM(V_CMP_LT_I16 ) ENUM(V_CMP_EQ_I16 ) ENUM(V_CMP_LE_I16 ) ENUM(V_CMP_GT_I16 ) ENUM(V_CMP_LG_I16 ) ENUM(V_CMP_GE_I16 ) ENUM(V_CMP_TRU_I16 ) ENUM(V_CMPx_F_I16 ) ENUM(V_CMPx_LT_I16 ) ENUM(V_CMPx_EQ_I16 ) ENUM(V_CMPx_LE_I16 ) ENUM(V_CMPx_GT_I16 ) ENUM(V_CMPx_LG_I16 ) ENUM(V_CMPx_GE_I16 ) ENUM(V_CMPx_TRU_I16 ) ENUM(V_CMP_CLASS_F16) ENUM(V_CMPX_CLASS_F16) ENUM(V_MAD_F16 ) ENUM(V_MAD_U16 ) ENUM(V_MAD_I16 ) ENUM(V_PERM_B32 ) ENUM(V_FMA_F16 ) ENUM(V_DIV_FIXUP_F16 ) ENUM( V_ADD_U32 ) ENUM( V_SUB_U32 ) ENUM( V_SUBREV_U32 ) ENUM( V_LSHLREV_B64 ) ENUM( V_LSHRREV_B64 ) ENUM( V_ASHRREV_I64 ) ENUM(V_INTERP_P1_F32 ) ENUM(V_INTERP_P2_F32 ) ENUM(V_INTERP_MOV_F32) ENUM(V_INTERP_P1LL_F16) ENUM(V_INTERP_P1LV_F16) ENUM(V_INTERP_P2_F16 ) END_ENUM_TABLE START_ENUM_TABLE(DSInstructions) ENUM( DS_ADD_U32 ) ENUM( DS_SUB_U32 ) ENUM( DS_RSUB_U32 ) ENUM( DS_INC_U32 ) ENUM( DS_DEC_U32 ) ENUM( DS_MIN_I32 ) ENUM( DS_MAX_I32 ) ENUM( DS_MIN_U32 ) ENUM( DS_MAX_U32 ) ENUM( DS_AND_B32 ) ENUM( DS_OR_B32 ) ENUM( DS_XOR_B32 ) ENUM( DS_MSKOR_B32 ) ENUM( DS_WRITE_B32 ) ENUM( DS_WRITE2_B32 ) ENUM( DS_WRITE2ST64_B32 ) ENUM( DS_CMPST_B32 ) ENUM( DS_CMPST_F32 ) ENUM( DS_MIN_F32 ) ENUM( DS_MAX_F32 ) ENUM( DS_NOP ) ENUM( DS_GWS_SEMA_RELEASE_ALL) ENUM( DS_GWS_INIT ) ENUM( DS_GWS_SEMA_V ) ENUM( DS_GWS_SEMA_BR ) ENUM( DS_GWS_SEMA_P ) ENUM( DS_GWS_BARRIER ) ENUM( DS_WRITE_B8 ) ENUM( DS_WRITE_B16 ) ENUM( DS_ADD_RTN_U32 ) ENUM( DS_SUB_RTN_U32 ) ENUM( DS_RSUB_RTN_U32 ) ENUM( DS_INC_RTN_U32 ) ENUM( DS_DEC_RTN_U32 ) ENUM( DS_MIN_RTN_I32 ) ENUM( DS_MAX_RTN_I32 ) ENUM( DS_MIN_RTN_U32 ) ENUM( DS_MAX_RTN_U32 ) ENUM( DS_AND_RTN_B32 ) ENUM( DS_OR_RTN_B32 ) ENUM( DS_XOR_RTN_B32 ) ENUM( DS_MSKOR_RTN_B32 ) ENUM( DS_WRXCHG_RTN_B32 ) ENUM( DS_WRXCHG2_RTN_B32 ) ENUM( DS_WRXCHG2ST64_RTN_B32 ) ENUM( DS_CMPST_RTN_B32 ) ENUM( DS_CMPST_RTN_F32 ) ENUM( DS_MIN_RTN_F32 ) ENUM( DS_MAX_RTN_F32 ) ENUM( DS_WRAP_RTN_B32 ) ENUM( DS_SWIZZLE_B32 ) ENUM( DS_READ_B32 ) ENUM( DS_READ2_B32 ) ENUM( DS_READ2ST64_B32 ) ENUM( DS_READ_I8 ) ENUM( DS_READ_U8 ) ENUM( DS_READ_I16 ) ENUM( DS_READ_U16 ) ENUM( DS_CONSUME ) ENUM( DS_APPEND ) ENUM( DS_ORDERED_COUNT ) ENUM( DS_ADD_U64 ) ENUM( DS_SUB_U64 ) ENUM( DS_RSUB_U64 ) ENUM( DS_INC_U64 ) ENUM( DS_DEC_U64 ) ENUM( DS_MIN_I64 ) ENUM( DS_MAX_I64 ) ENUM( DS_MIN_U64 ) ENUM( DS_MAX_U64 ) ENUM( DS_AND_B64 ) ENUM( DS_OR_B64 ) ENUM( DS_XOR_B64 ) ENUM( DS_MSKOR_B64 ) ENUM( DS_WRITE_B64 ) ENUM( DS_WRITE2_B64 ) ENUM( DS_WRITE2ST64_B64 ) ENUM( DS_CMPST_B64 ) ENUM( DS_CMPST_F64 ) ENUM( DS_MIN_F64 ) ENUM( DS_MAX_F64 ) ENUM( DS_ADD_RTN_U64 ) ENUM( DS_SUB_RTN_U64 ) ENUM( DS_RSUB_RTN_U64 ) ENUM( DS_INC_RTN_U64 ) ENUM( DS_DEC_RTN_U64 ) ENUM( DS_MIN_RTN_I64 ) ENUM( DS_MAX_RTN_I64 ) ENUM( DS_MIN_RTN_U64 ) ENUM( DS_MAX_RTN_U64 ) ENUM( DS_AND_RTN_B64 ) ENUM( DS_OR_RTN_B64 ) ENUM( DS_XOR_RTN_B64 ) ENUM( DS_MSKOR_RTN_B64 ) ENUM( DS_WRXCHG_RTN_B64 ) ENUM( DS_WRXCHG2_RTN_B64 ) ENUM( DS_WRXCHG2ST64_RTN_B64 ) ENUM( DS_CMPST_RTN_B64 ) ENUM( DS_CMPST_RTN_F64 ) ENUM( DS_MIN_RTN_F64 ) ENUM( DS_MAX_RTN_F64 ) ENUM( DS_READ_B64 ) ENUM( DS_READ2_B64 ) ENUM( DS_READ2ST64_B64 ) ENUM( DS_CONDXCHG32_RTN_B64 ) ENUM( DS_ADD_SRC2_U32 ) ENUM( DS_SUB_SRC2_U32 ) ENUM( DS_RSUB_SRC2_U32 ) ENUM( DS_INC_SRC2_U32 ) ENUM( DS_DEC_SRC2_U32 ) ENUM( DS_MIN_SRC2_I32 ) ENUM( DS_MAX_SRC2_I32 ) ENUM( DS_MIN_SRC2_U32 ) ENUM( DS_MAX_SRC2_U32 ) ENUM( DS_AND_SRC2_B32 ) ENUM( DS_OR_SRC2_B32 ) ENUM( DS_XOR_SRC2_B32 ) ENUM( DS_WRITE_SRC2_B32 ) ENUM( DS_MIN_SRC2_F32 ) ENUM( DS_MAX_SRC2_F32 ) ENUM( DS_ADD_SRC2_U64 ) ENUM( DS_SUB_SRC2_U64 ) ENUM( DS_RSUB_SRC2_U64 ) ENUM( DS_INC_SRC2_U64 ) ENUM( DS_DEC_SRC2_U64 ) ENUM( DS_MIN_SRC2_I64 ) ENUM( DS_MAX_SRC2_I64 ) ENUM( DS_MIN_SRC2_U64 ) ENUM( DS_MAX_SRC2_U64 ) ENUM( DS_AND_SRC2_B64 ) ENUM( DS_OR_SRC2_B64 ) ENUM( DS_XOR_SRC2_B64 ) ENUM( DS_WRITE_SRC2_B64 ) ENUM( DS_MIN_SRC2_F64 ) ENUM( DS_MAX_SRC2_F64 ) ENUM( DS_WRITE_B96 ) ENUM( DS_WRITE_B128 ) ENUM( DS_CONDXCHG32_RTN_B128 ) ENUM( DS_READ_B96 ) ENUM( DS_READ_B128 ) ENUM( DS_PERMUTE_B32 ) ENUM( DS_BPERMUTE_B32 ) ENUM( DS_ADD_F32 ) END_ENUM_TABLE START_ENUM_TABLE(BufferInstructions) ENUM(BUFFER_LOAD_FORMAT_X ) ENUM(BUFFER_LOAD_FORMAT_XY ) ENUM(BUFFER_LOAD_FORMAT_XYZ ) ENUM(BUFFER_LOAD_FORMAT_XYZW ) ENUM(BUFFER_STORE_FORMAT_X ) ENUM(BUFFER_STORE_FORMAT_XY ) ENUM(BUFFER_STORE_FORMAT_XYZ ) ENUM(BUFFER_STORE_FORMAT_XYZW ) ENUM(BUFFER_LOAD_UBYTE ) ENUM(BUFFER_LOAD_SBYTE ) ENUM(BUFFER_LOAD_USHORT ) ENUM(BUFFER_LOAD_SSHORT ) ENUM(BUFFER_LOAD_DWORD ) ENUM(BUFFER_LOAD_DWORDX2 ) ENUM(BUFFER_LOAD_DWORDX4 ) ENUM(BUFFER_LOAD_DWORDX3 ) ENUM(BUFFER_STORE_BYTE ) ENUM(BUFFER_STORE_SHORT ) ENUM(BUFFER_STORE_DWORD ) ENUM(BUFFER_STORE_DWORDX2 ) ENUM(BUFFER_STORE_DWORDX4 ) ENUM(BUFFER_STORE_DWORDX3 ) ENUM(BUFFER_ATOMIC_SWAP ) ENUM(BUFFER_ATOMIC_CMPSWAP ) ENUM(BUFFER_ATOMIC_ADD ) ENUM(BUFFER_ATOMIC_SUB ) ENUM(BUFFER_ATOMIC_RSUB ) ENUM(BUFFER_ATOMIC_SMIN ) ENUM(BUFFER_ATOMIC_UMIN ) ENUM(BUFFER_ATOMIC_SMAX ) ENUM(BUFFER_ATOMIC_UMAX ) ENUM(BUFFER_ATOMIC_AND ) ENUM(BUFFER_ATOMIC_OR ) ENUM(BUFFER_ATOMIC_XOR ) ENUM(BUFFER_ATOMIC_INC ) ENUM(BUFFER_ATOMIC_DEC ) ENUM(BUFFER_ATOMIC_FCMPSWAP ) ENUM(BUFFER_ATOMIC_FMIN ) ENUM(BUFFER_ATOMIC_FMAX ) ENUM(BUFFER_ATOMIC_SWAP_X2 ) ENUM(BUFFER_ATOMIC_CMPSWAP_X2 ) ENUM(BUFFER_ATOMIC_ADD_X2 ) ENUM(BUFFER_ATOMIC_SUB_X2 ) ENUM(BUFFER_ATOMIC_RSUB_X2 ) ENUM(BUFFER_ATOMIC_SMIN_X2 ) ENUM(BUFFER_ATOMIC_UMIN_X2 ) ENUM(BUFFER_ATOMIC_SMAX_X2 ) ENUM(BUFFER_ATOMIC_UMAX_X2 ) ENUM(BUFFER_ATOMIC_AND_X2 ) ENUM(BUFFER_ATOMIC_OR_X2 ) ENUM(BUFFER_ATOMIC_XOR_X2 ) ENUM(BUFFER_ATOMIC_INC_X2 ) ENUM(BUFFER_ATOMIC_DEC_X2 ) ENUM(BUFFER_ATOMIC_FCMPSWAP_X2 ) ENUM(BUFFER_ATOMIC_FMIN_X2 ) ENUM(BUFFER_ATOMIC_FMAX_X2 ) ENUM(BUFFER_WBINVL1_SC ) ENUM(BUFFER_WBINVL1 ) ENUM(TBUFFER_LOAD_FORMAT_X ) ENUM(TBUFFER_LOAD_FORMAT_XY ) ENUM(TBUFFER_LOAD_FORMAT_XYZ ) ENUM(TBUFFER_LOAD_FORMAT_XYZW ) ENUM(TBUFFER_STORE_FORMAT_X ) ENUM(TBUFFER_STORE_FORMAT_XY ) ENUM(TBUFFER_STORE_FORMAT_XYZ ) ENUM(TBUFFER_STORE_FORMAT_XYZW ) ENUM(BUFFER_WBINVL1_VOL ) ENUM(BUFFER_STORE_LDS_DWORD ) ENUM(BUFFER_LOAD_FORMAT_D16_X ) ENUM(BUFFER_LOAD_FORMAT_D16_XY ) ENUM(BUFFER_LOAD_FORMAT_D16_XYZ ) ENUM(BUFFER_LOAD_FORMAT_D16_XYZW ) ENUM(BUFFER_STORE_FORMAT_D16_X ) ENUM(BUFFER_STORE_FORMAT_D16_XY ) ENUM(BUFFER_STORE_FORMAT_D16_XYZ ) ENUM(BUFFER_STORE_FORMAT_D16_XYZW) ENUM(TBUFFER_LOAD_FORMAT_D16_X ) ENUM(TBUFFER_LOAD_FORMAT_D16_XY ) ENUM(TBUFFER_LOAD_FORMAT_D16_XYZ ) ENUM(TBUFFER_LOAD_FORMAT_D16_XYZW ) ENUM(TBUFFER_STORE_FORMAT_D16_X ) ENUM(TBUFFER_STORE_FORMAT_D16_XY ) ENUM(TBUFFER_STORE_FORMAT_D16_XYZ ) ENUM(TBUFFER_STORE_FORMAT_D16_XYZW ) END_ENUM_TABLE START_ENUM_TABLE(ImageInstructions) ENUM(IMAGE_LOAD ) ENUM(IMAGE_LOAD_MIP ) ENUM(IMAGE_LOAD_PCK ) ENUM(IMAGE_LOAD_PCK_SGN ) ENUM(IMAGE_LOAD_MIP_PCK ) ENUM(IMAGE_LOAD_MIP_PCK_SGN ) ENUM(IMAGE_STORE ) ENUM(IMAGE_STORE_MIP ) ENUM(IMAGE_STORE_PCK ) ENUM(IMAGE_STORE_MIP_PCK ) ENUM(IMAGE_GET_RESINFO ) ENUM(IMAGE_ATOMIC_SWAP ) ENUM(IMAGE_ATOMIC_CMPSWAP ) ENUM(IMAGE_ATOMIC_ADD ) ENUM(IMAGE_ATOMIC_SUB ) ENUM(IMAGE_ATOMIC_RSUB ) ENUM(IMAGE_ATOMIC_SMIN ) ENUM(IMAGE_ATOMIC_UMIN ) ENUM(IMAGE_ATOMIC_SMAX ) ENUM(IMAGE_ATOMIC_UMAX ) ENUM(IMAGE_ATOMIC_AND ) ENUM(IMAGE_ATOMIC_OR ) ENUM(IMAGE_ATOMIC_XOR ) ENUM(IMAGE_ATOMIC_INC ) ENUM(IMAGE_ATOMIC_DEC ) ENUM(IMAGE_ATOMIC_FCMPSWAP ) ENUM(IMAGE_ATOMIC_FMIN ) ENUM(IMAGE_ATOMIC_FMAX ) ENUM(IMAGE_SAMPLE ) ENUM(IMAGE_SAMPLE_CL ) ENUM(IMAGE_SAMPLE_D ) ENUM(IMAGE_SAMPLE_D_CL ) ENUM(IMAGE_SAMPLE_L ) ENUM(IMAGE_SAMPLE_B ) ENUM(IMAGE_SAMPLE_B_CL ) ENUM(IMAGE_SAMPLE_LZ ) ENUM(IMAGE_SAMPLE_C ) ENUM(IMAGE_SAMPLE_C_CL ) ENUM(IMAGE_SAMPLE_C_D ) ENUM(IMAGE_SAMPLE_C_D_CL ) ENUM(IMAGE_SAMPLE_C_L ) ENUM(IMAGE_SAMPLE_C_B ) ENUM(IMAGE_SAMPLE_C_B_CL ) ENUM(IMAGE_SAMPLE_C_LZ ) ENUM(IMAGE_SAMPLE_O ) ENUM(IMAGE_SAMPLE_CL_O ) ENUM(IMAGE_SAMPLE_D_O ) ENUM(IMAGE_SAMPLE_D_CL_O ) ENUM(IMAGE_SAMPLE_L_O ) ENUM(IMAGE_SAMPLE_B_O ) ENUM(IMAGE_SAMPLE_B_CL_O ) ENUM(IMAGE_SAMPLE_LZ_O ) ENUM(IMAGE_SAMPLE_C_O ) ENUM(IMAGE_SAMPLE_C_CL_O ) ENUM(IMAGE_SAMPLE_C_D_O ) ENUM(IMAGE_SAMPLE_C_D_CL_O ) ENUM(IMAGE_SAMPLE_C_L_O ) ENUM(IMAGE_SAMPLE_C_B_O ) ENUM(IMAGE_SAMPLE_C_B_CL_O ) ENUM(IMAGE_SAMPLE_C_LZ_O ) ENUM(IMAGE_GATHER4 ) ENUM(IMAGE_GATHER4_CL ) ENUM(IMAGE_GATHER4_L ) ENUM(IMAGE_GATHER4_B ) ENUM(IMAGE_GATHER4_B_CL ) ENUM(IMAGE_GATHER4_LZ ) ENUM(IMAGE_GATHER4_C ) ENUM(IMAGE_GATHER4_C_CL ) ENUM(IMAGE_GATHER4_C_L ) ENUM(IMAGE_GATHER4_C_B ) ENUM(IMAGE_GATHER4_C_B_CL ) ENUM(IMAGE_GATHER4_C_LZ ) ENUM(IMAGE_GATHER4_O ) ENUM(IMAGE_GATHER4_CL_O ) ENUM(IMAGE_GATHER4_L_O ) ENUM(IMAGE_GATHER4_B_O ) ENUM(IMAGE_GATHER4_B_CL_O ) ENUM(IMAGE_GATHER4_LZ_O ) ENUM(IMAGE_GATHER4_C_O ) ENUM(IMAGE_GATHER4_C_CL_O ) ENUM(IMAGE_GATHER4_C_L_O ) ENUM(IMAGE_GATHER4_C_B_O ) ENUM(IMAGE_GATHER4_C_B_CL_O ) ENUM(IMAGE_GATHER4_C_LZ_O ) ENUM(IMAGE_GET_LOD ) ENUM(IMAGE_SAMPLE_CD ) ENUM(IMAGE_SAMPLE_CD_CL ) ENUM(IMAGE_SAMPLE_C_CD ) ENUM(IMAGE_SAMPLE_C_CD_CL ) ENUM(IMAGE_SAMPLE_CD_O ) ENUM(IMAGE_SAMPLE_CD_CL_O ) ENUM(IMAGE_SAMPLE_C_CD_O ) ENUM(IMAGE_SAMPLE_C_CD_CL_O ) END_ENUM_TABLE START_ENUM_TABLE(FlatInstructions) ENUM(FLAT_LOAD_UBYTE ) ENUM(FLAT_LOAD_SBYTE ) ENUM(FLAT_LOAD_USHORT ) ENUM(FLAT_LOAD_SSHORT ) ENUM(FLAT_LOAD_DWORD ) ENUM(FLAT_LOAD_DWORDX2 ) ENUM(FLAT_LOAD_DWORDX4 ) ENUM(FLAT_LOAD_DWORDX3 ) ENUM(FLAT_STORE_BYTE ) ENUM(FLAT_STORE_SHORT ) ENUM(FLAT_STORE_DWORD ) ENUM(FLAT_STORE_DWORDX2 ) ENUM(FLAT_STORE_DWORDX4 ) ENUM(FLAT_STORE_DWORDX3 ) ENUM(FLAT_ATOMIC_SWAP ) ENUM(FLAT_ATOMIC_CMPSWAP ) ENUM(FLAT_ATOMIC_ADD ) ENUM(FLAT_ATOMIC_SUB ) ENUM(FLAT_ATOMIC_SMIN ) ENUM(FLAT_ATOMIC_UMIN ) ENUM(FLAT_ATOMIC_SMAX ) ENUM(FLAT_ATOMIC_UMAX ) ENUM(FLAT_ATOMIC_AND ) ENUM(FLAT_ATOMIC_OR ) ENUM(FLAT_ATOMIC_XOR ) ENUM(FLAT_ATOMIC_INC ) ENUM(FLAT_ATOMIC_DEC ) ENUM(FLAT_ATOMIC_FCMPSWAP ) ENUM(FLAT_ATOMIC_FMIN ) ENUM(FLAT_ATOMIC_FMAX ) ENUM(FLAT_ATOMIC_SWAP_X2 ) ENUM(FLAT_ATOMIC_CMPSWAP_X2 ) ENUM(FLAT_ATOMIC_ADD_X2 ) ENUM(FLAT_ATOMIC_SUB_X2 ) ENUM(FLAT_ATOMIC_SMIN_X2 ) ENUM(FLAT_ATOMIC_UMIN_X2 ) ENUM(FLAT_ATOMIC_SMAX_X2 ) ENUM(FLAT_ATOMIC_UMAX_X2 ) ENUM(FLAT_ATOMIC_AND_X2 ) ENUM(FLAT_ATOMIC_OR_X2 ) ENUM(FLAT_ATOMIC_XOR_X2 ) ENUM(FLAT_ATOMIC_INC_X2 ) ENUM(FLAT_ATOMIC_DEC_X2 ) ENUM(FLAT_ATOMIC_FCMPSWAP_X2 ) ENUM(FLAT_ATOMIC_FMIN_X2 ) ENUM(FLAT_ATOMIC_FMAX_X2 ) END_ENUM_TABLE #define ENUM_EXP(x) { EXP_##x, #x }, START_ENUM_TABLE(ExportTargets) ENUM_EXP(MRT0 ) ENUM_EXP(MRT1 ) ENUM_EXP(MRT2 ) ENUM_EXP(MRT3 ) ENUM_EXP(MRT4 ) ENUM_EXP(MRT5 ) ENUM_EXP(MRT6 ) ENUM_EXP(MRT7 ) ENUM_EXP(Z ) ENUM_EXP(NULL ) ENUM_EXP(POS0 ) ENUM_EXP(POS1 ) ENUM_EXP(POS2 ) ENUM_EXP(POS3 ) ENUM_EXP(PARAM0 ) ENUM_EXP(PARAM1 ) ENUM_EXP(PARAM2 ) ENUM_EXP(PARAM3 ) ENUM_EXP(PARAM4 ) ENUM_EXP(PARAM5 ) ENUM_EXP(PARAM6 ) ENUM_EXP(PARAM7 ) ENUM_EXP(PARAM8 ) ENUM_EXP(PARAM9 ) ENUM_EXP(PARAM10 ) ENUM_EXP(PARAM11 ) ENUM_EXP(PARAM12 ) ENUM_EXP(PARAM13 ) ENUM_EXP(PARAM14 ) ENUM_EXP(PARAM15 ) ENUM_EXP(PARAM16 ) ENUM_EXP(PARAM17 ) ENUM_EXP(PARAM18 ) ENUM_EXP(PARAM19 ) ENUM_EXP(PARAM20 ) ENUM_EXP(PARAM21 ) ENUM_EXP(PARAM22 ) ENUM_EXP(PARAM23 ) ENUM_EXP(PARAM24 ) ENUM_EXP(PARAM25 ) ENUM_EXP(PARAM26 ) ENUM_EXP(PARAM27 ) ENUM_EXP(PARAM28 ) ENUM_EXP(PARAM29 ) ENUM_EXP(PARAM30 ) ENUM_EXP(PARAM31 ) END_ENUM_TABLE #define ENUM_NF(x) { NF_##x, #x }, START_ENUM_TABLE(TBufferNumberFormats) ENUM_NF(UNORM ) ENUM_NF(SNORM ) ENUM_NF(USCALED ) ENUM_NF(SSCALED ) ENUM_NF(UINT ) ENUM_NF(SINT ) ENUM_NF(SNORM_NZ ) ENUM_NF(FLOAT ) ENUM_NF(SRGB ) ENUM_NF(UBNORM ) ENUM_NF(UBNORM_NZ ) ENUM_NF(UBINT ) ENUM_NF(UBSCALED ) END_ENUM_TABLE #define ENUM_DF(x) { DF_##x, #x }, START_ENUM_TABLE(TBufferDataFormats) ENUM_DF(INVALID ) ENUM_DF(8 ) ENUM_DF(16 ) ENUM_DF(8_8 ) ENUM_DF(32 ) ENUM_DF(16_16 ) ENUM_DF(10_11_11 ) ENUM_DF(11_11_10 ) ENUM_DF(10_10_10_2 ) ENUM_DF(2_10_10_10 ) ENUM_DF(8_8_8_8 ) ENUM_DF(32_32 ) ENUM_DF(16_16_16_16) ENUM_DF(32_32_32 ) ENUM_DF(32_32_32_32) END_ENUM_TABLE const char* Search( const EnumLookup* pTable, unsigned int nValue ) { do // NOTE: could be a binary search, except that the vop3 table is out of order { if( pTable->n == nValue ) break; ++pTable; } while( pTable->str ); return pTable->str; } } #define IMPLEMENT_ENUM_LOOKUP(en) \ const char* EnumToString(en op) {\ const char* p = _INTERNAL::Search( _INTERNAL::en##LUT, op ); \ return p ? p : "?????????"#en; } IMPLEMENT_ENUM_LOOKUP(ScalarInstructions); IMPLEMENT_ENUM_LOOKUP(ScalarMemoryInstructions); IMPLEMENT_ENUM_LOOKUP(VectorInstructions); IMPLEMENT_ENUM_LOOKUP(BufferInstructions) IMPLEMENT_ENUM_LOOKUP(ImageInstructions) IMPLEMENT_ENUM_LOOKUP(DSInstructions); IMPLEMENT_ENUM_LOOKUP(ExportTargets); IMPLEMENT_ENUM_LOOKUP(FlatInstructions); IMPLEMENT_ENUM_LOOKUP(TBufferDataFormats); IMPLEMENT_ENUM_LOOKUP(TBufferNumberFormats); } ================================================ FILE: src/Wrapper/GCNEnums.h ================================================ // // GCN Opcodes, register types, and other things. Based on a trawling of the ISA docs. // Copyright 2015 Joshua Barczak, all rights reserved. // #ifndef _GCN_ENUMS_H_ #define _GCN_ENUMS_H_ #pragma once namespace GCN { enum InstructionFormat { IF_SOP2, IF_SOPK, IF_SOP1, IF_SOPC, IF_SOPP, IF_SMRD, // SI and CI IF_SMEM, // GCN3+ IF_VOP2, IF_VOP1, IF_VOPC, IF_VOP3, IF_VINTERP, IF_DS, IF_MTBUFF, IF_MUBUFF, IF_MIMG, IF_EXP, IF_FLAT, // SEA ISLANDS and up IF_UNKNOWN, }; enum InstructionClass { IC_SCALAR, IC_SCALAR_MEM, IC_VECTOR, IC_VECTOR_INTERP, IC_BUFFER, IC_IMAGE, IC_EXPORT, IC_DS, IC_INVALID }; /// Scalar dests enum Dests { DEST_SGPR_FIRST = 0, DEST_SGPR_LAST = 103, // NOTE: GCN3 only allows 0-101, and stores VCC in s102 and s103 DEST_FSCR_LO = 104, // flat scratch memory descriptor, low (SEA ISLANDS+) DEST_FSCR_HI = 105, // flat scratcy memory descriptor, hi (SEA ISLANDS) DEST_VCC_LO = 106, // Vector condition code DEST_VCC_HI, DEST_TBA_LO, // Trap handler base address DEST_TBA_HI, DEST_TMA_LO, // Pointer to data in memory used by trap handler DEST_TMA_HI, DEST_TTMP_FIRST , // Trap handler temporary regs (priviledged) DEST_TTMP_LAST = 123, DEST_M0 = 124, // Magical memory register used for various things DEST_EXEC_LO =126, // Vector exec mask DEST_EXEC_HI , DEST_VGPR_FIRST = 256, DEST_VGPR_LAST = 511, DEST_SCC, DEST_VSKIP, // implied dests for compare and vskip instructions DEST_VCC, DEST_XNACK_MASK_LO, DEST_XNACK_MASK_HI, DEST_INVALID = 0xffffffff }; /// Sources enum Sources { SRC_SGPR_FIRST = 0, SRC_SGPR_LAST = 103, // NOTE: GCN3 only allows 0-101, and stores VCC in s102 and s103 SRC_FSCR_LO , // flat scratch memory descriptor, low (SEA ISLANDS+) SRC_FSCR_HI , // flat scratcy memory descriptor, hi (SEA ISLANDS) SRC_VCC_LO , // Vector condition code SRC_VCC_HI, SRC_TBA_LO, // Trap handler base address SRC_TBA_HI, SRC_TMA_LO, // Pointer to data in memory used by trap handler SRC_TMA_HI, SRC_TTMP_FIRST , // Trap handler temporary regs (priviledged) SRC_TTMP_LAST = 123, SRC_M0 , // Magical memory register used for various things // 125 reserved SRC_EXEC_LO =126, // Vector exec mask SRC_EXEC_HI , SRC_C_ZERO=128, SRC_CI_POSITIVE_FIRST= 129, // Signed integers 1 to 64 SRC_CI_POSITIVE_LAST = 192, SRC_CI_NEGATIVE_FIRST=193, // Signed integers -1 to -16 SRC_CI_NEGATIVE_LAST = 208, // 209-239 reserved SRC_CF_ONEHALF =240, // float constants SRC_CF_MINUS_ONEHALF, SRC_CF_ONE, SRC_CF_MINUS_ONE, SRC_CF_TWO, SRC_CF_MINUS_TWO, SRC_CF_FOUR, SRC_CF_MINUS_FOUR, SRC_CF_INV_2PI = 248, // 249-250 reserved SRC_VCCZ = 251, // Vector condition code SRC_EXECZ = 252, // Vector EXEC mask SRC_SCC = 253, // Scalar condition code SRC_LDS_DIRECT = 254, // direct LDS access, with address from 'M0' (vector only SRC_LITERAL= 255, // DWORD literal following instruction SRC_VGPR_FIRST = 256, SRC_VGPR_LAST = 511, SRC_XNACK_MASK_LO, // Carrizo apu only. Something to do with address translation SRC_XNACK_MASK_HI, SRC_INVALID =0xffffffff }; enum ScalarInstructions { S_INVALID = 0xffffffff, ///////////////////////////////////////// // SOP2 ///////////////////////////////////////// S_ADD_U32 , //: D.u = S0.u + S1.u. SCC = carry out. S_SUB_U32 , //: D.u = S0.u - S1.u. SCC = carry out. S_ADD_I32 , //: D.u = S0.i + S1.i. SCC = overflow. S_SUB_I32 , //: D.u = S0.i - S1.i. SCC = overflow. S_ADDC_U32 , //: D.u = S0.u + S1.u + SCC. SCC = carry-out. S_SUBB_U32 , //: D.u = S0.u - S1.u - SCC. SCC = carry-out. S_MIN_I32 , //: D.i = (S0.i < S1.i) ? S0.i : S1.i. SCC = 1 if S0 is min. S_MIN_U32 , //: D.u = (S0.u < S1.u) ? S0.u : S1.u. SCC = 1 if S0 is min. S_MAX_I32 , //: D.i = (S0.i > S1.i) ? S0.i : S1.i. SCC = 1 if S0 is max. S_MAX_U32 , //: D.u = (S0.u > S1.u) ? S0.u : S1.u. SCC = 1 if S0 is max. S_CSELECT_B32 , //: D.u = SCC ? S0.u : S1.u. S_CSELECT_B64 , //: D.u = SCC ? S0.u : S1.u. S_AND_B32 , //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. S_AND_B64 , //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. S_OR_B32 , //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. S_OR_B64 , //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. S_XOR_B32 , //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. S_XOR_B64 , //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. S_ANDN2_B32 , //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. S_ANDN2_B64 , //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. S_ORN2_B32 , //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. S_ORN2_B64 , //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. S_NAND_B32 , //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. S_NAND_B64 , //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. S_NOR_B32 , //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. S_NOR_B64 , //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. S_XNOR_B32 , //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. S_XNOR_B64 , //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. S_LSHL_B32 , //: D.u = S0.u << S1.u[4:0]. SCC = 1 if result is non-zero. S_LSHL_B64 , //: D.u = S0.u << S1.u[5:0]. SCC = 1 if result is non-zero. S_LSHR_B32 , //: D.u = S0.u >> S1.u[4:0]. SCC = 1 if result is non-zero. S_LSHR_B64 , //: D.u = S0.u >> S1.u[5:0]. SCC = 1 if result is non-zero. S_ASHR_I32 , //: D.i = signtext(S0.i) >> S1.i[4:0]. SCC = 1 if result is non-zero. S_ASHR_I64 , //: D.i = signtext(S0.i) >> S1.i[5:0]. SCC = 1 if result is non-zero. S_BFM_B32 , //: D.u = ((1 << S0.u[4:0]) - 1) << S1.u[4:0]; bitfield mask. S_BFM_B64 , //: D.u = ((1 << S0.u[5:0]) - 1) << S1.u[5:0]; bitfield mask. S_MUL_I32 , //: D.i = S0.i * S1.i. S_BFE_U32 , // : Bit field extract. S0 is data, S1[4:0] is field offset, S1[22:16] is field width. D.u = (S0.u >> S1.u[4:0]) & ((1 << S1.u[22:16]) - 1). SCC = 1 if resultis non-zero. S_BFE_I32 , S_BFE_U64 , S_BFE_I64 , S_CBRANCH_G_FORK , // Conditional branch using branch stack. Arg0 = compare mask (VCC or any SGPR), Arg1 = 64-bit byte address of target instruction. S_ABSDIFF_I32 , // D.i = abs(S0.i >> S1.i). SCC = 1 if result is non-zero. // VI+ S_RFE_RESTORE_B64 , // Return from exception handler and set: INST_ATC = S1.U32[0] ///////////////////////////////////////// // SOPK ///////////////////////////////////////// S_MOVK_I32 , //: D.i = signext(SIMM16). S_CMOVK_I32 , //: if (SCC) D.i = signext(SIMM16); else NOP. S_CMPK_EQ_I32 , //: SCC = (D.i == signext(SIMM16). S_CMPK_LG_I32 , //: SCC = (D.i != signext(SIMM16). S_CMPK_GT_I32 , //: SCC = (D.i != signext(SIMM16)). S_CMPK_GE_I32 , //: SCC = (D.i >= signext(SIMM16)). S_CMPK_LT_I32 , //: SCC = (D.i < signext(SIMM16)). S_CMPK_LE_I32 , //: SCC = (D.i <= signext(SIMM16)). S_CMPK_EQ_U32 , //: SCC = (D.u == SIMM16). S_CMPK_LG_U32 , //: SCC = (D.u != SIMM16). S_CMPK_GT_U32 , //: SCC = (D.u > SIMM16). S_CMPK_GE_U32 , //: SCC = (D.u >= SIMM16). S_CMPK_LT_U32 , //: SCC = (D.u < SIMM16). S_CMPK_LE_U32 , //: D.u = SCC = (D.u <= SIMM16). S_ADDK_I32 , //: D.i = D.i + signext(SIMM16). SCC = overflow. S_MULK_I32 , //: D.i = D.i * signext(SIMM16). SCC = overflow. S_CBRANCH_I_FORK , //: Conditional branch using branch-stack. // Arg0(sdst) = compare mask (VCC or any SGPR), SIMM16 = signed DWORD // branch offset relative to next instruction. S_GETREG_B32 , // : D.u = hardware register. Read some or all of a hardware register // into the LSBs of D. SIMM16 = {size[4:0], offset[4:0], hwRegId[5:0]}; offset // is 031, size is 132. S_SETREG_B32 , // : hardware register = D.u. Write some or all of the LSBs of D // into a hardware register (note that D is a source SGPR). // SIMM16 = {size[4:0], offset[4:0], hwRegId[5:0]}; offset is 031, size is 132. //20 reserved. // S_SETREG_IMM32_B32 , //: This instruction uses a 32-bit literal constant. Write // some or all of the LSBs of IMM32 into a hardware register. // SIMM16 = {size[4:0], offset[4:0], hwRegId[5:0]}; offset is 031, size is 132. ///////////////////////////////////////// // SOP1 ///////////////////////////////////////// S_MOV_B32 ,//: D.u = S0.u. S_MOV_B64 ,//: D/u = S0.u. S_CMOV_B32 ,//: if(SCC) D.u = S0.u; else NOP. S_CMOV_B64 ,//: if(SCC) D.u = S0.u; else NOP. S_NOT_B32 ,//: D.u = ~S0.u SCC = 1 if result non-zero. S_NOT_B64 ,//: D.u = ~S0.u SCC = 1 if result non-zero. S_WQM_B32 ,//: D.u = WholeQuadMode(S0.u). SCC = 1 if result is non-zero. S_WQM_B64 ,//: D.u = WholeQuadMode(S0.u). SCC = 1 if result is non-zero. S_BREV_B32 ,//: D.u = S0.u[0:31] (reverse bits). S_BREV_B64 ,//: D.u = S0.u[0:63] (reverse bits). S_BCNT0_I32_B32 ,//: D.i = CountZeroBits(S0.u). SCC = 1 if result is non-zero. S_BCNT0_I32_B64 ,//: D.i = CountZeroBits(S0.u). SCC = 1 if result is non-zero. S_BCNT1_I32_B32 ,//: D.i = CountOneBits(S0.u). SCC = 1 if result is non-zero. S_BCNT1_I32_B64 ,//: D.i = CountOneBits(S0.u). SCC = 1 if result is non-zero. S_FF0_I32_B32 ,//: D.i = FindFirstZero(S0.u) from LSB; if no zeros, return -1. S_FF0_I32_B64 ,//: D.i = FindFirstZero(S0.u) from LSB; if no zeros, return -1. S_FF1_I32_B32 ,//: D.i = FindFirstOne(S0.u) from LSB; if no ones, return -1. S_FF1_I32_B64 ,//: D.i = FindFirstOne(S0.u) from LSB; if no ones, return -1. S_FLBIT_I32_B32 ,//: D.i = FindFirstOne(S0.u) from MSB; if no ones, return -1. S_FLBIT_I32_B64 ,//: D.i = FindFirstOne(S0.u) from MSB; if no ones, return -1. S_FLBIT_I32 ,//: D.i = Find first bit opposite of sign bit from MSB. If S0 == -1, return -1. S_FLBIT_I32_I64 ,//: D.i = Find first bit opposite of sign bit from MSB. If S0 == -1, return -1. S_SEXT_I32_I8 ,//: D.i = signext(S0.i[7:0]). S_SEXT_I32_I16 ,//: D.i = signext(S0.i[15:0]). S_BITSET0_B32 ,//: D.u[S0.u[4:0]] = 0. S_BITSET0_B64 ,//: D.u[S0.u[5:0]] = 0. S_BITSET1_B32 ,//: D.u[S0.u[4:0]] = 1. S_BITSET1_B64 ,//: D.u[S0.u[5:0]] = 1. S_GETPC_B64 ,//: D.u = PC + 4; destination receives the byte address of the next instruction. S_SETPC_B64 ,//: PC = S0.u; S0.u is a byte address of the instruction to jump to. S_SWAPPC_B64 ,//: D.u = PC + 4; PC = S0.u. S_RFE_B64 ,//: Return from Exception; PC = TTMP1,0. S_AND_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = S0.u & EXEC. SCC = 1 if the new value of EXEC is non-zero. S_OR_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = S0.u | EXEC. SCC = 1 if the newvalue of EXEC is non-zero. S_XOR_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = S0.u ^ EXEC. SCC = 1 if the new value of EXEC is non-zero. S_ANDN2_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = S0.u & ~EXEC. SCC =1 if the new value of EXEC is non-zero. S_ORN2_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = S0.u | ~EXEC. SCC = 1 if the new value of EXEC is non-zero. S_NAND_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = ~(S0.u & EXEC). SCC =1 if the new value of EXEC is non-zero. S_NOR_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = ~(S0.u | EXEC). SCC = 1 if the new value of EXEC is non-zero. S_XNOR_SAVEEXEC_B64 ,//: D.u = EXEC, EXEC = ~(S0.u ^ EXEC). SCC = 1 if the new value of EXEC is non-zero. S_QUADMASK_B32 ,//: D.u = QuadMask(S0.u). D[0] = OR(S0[3:0]), D[1] = OR(S0[7:4]) .... SCC = 1 if result is non-zero. S_QUADMASK_B64 ,//: D.u = QuadMask(S0.u). D[0] = OR(S0[3:0]),D[1] = OR(S0[7:4]) .... SCC = 1 if result is non-zero S_MOVRELS_B32 ,//: SGPR[D.u] = SGPR[S0.u + M0.u]. S_MOVRELS_B64 ,//: SGPR[D.u] = SGPR[S0.u + M0.u]. S_MOVRELD_B32 ,//: SGPR[D.u + M0.u] = SGPR[S0.u]. S_MOVRELD_B64 ,//: SGPR[D.u + M0.u] = SGPR[S0.u]. S_CBRANCH_JOIN ,//: Conditional branch join point. Arg0 = saved CSP value. No dest. S_ABS_I32 , //: D.i = abs(S0.i). SCC=1 if result is non-zero. S_MOV_FED_B32 , //: D.u = S0.u, introduce edc double error upon write to dest sgpr. // VI+ S_SET_GPR_IDX_IDX ,//: Set offset for GPR indexing (GCN3+) M0[7:0] = S0.U[7:0] ///////////////////////////////////////// // SOPC ///////////////////////////////////////// S_CMP_EQ_I32 , //: SCC = (S0.i == S1.i). S_CMP_LG_I32 , //: SCC = (S0.i != S1.i). S_CMP_GT_I32 , //: SCC = (S0.i > S1.i). S_CMP_GE_I32 , //: SCC = (S0.i >= S1.i). S_CMP_LT_I32 , //: SCC = (S0.i < S1.i). S_CMP_LE_I32 , //: SCC = (S0.i <= S1.i). S_CMP_EQ_U32 , //: SCC = (S0.u == S1.u). S_CMP_LG_U32 , //: SCC = (S0.u != S1.u). S_CMP_GT_U32 , //: SCC = (S0.u > S1.u). S_CMP_GE_U32 , //: SCC = (S0.u >= S1.u). S_CMP_LT_U32 , //: SCC = (S0.u < S1.u). S_CMP_LE_U32 , //: SCC = (S0.u <= S1.u). S_BITCMP0_B32 , //: SCC = (S0.u[S1.u[4:0]] == 0). S_BITCMP1_B32 , //: SCC = (S0.u[S1.u[4:0]] == 1). S_BITCMP0_B64 , //: SCC = (S0.u[S1.u[5:0]] == 0). S_BITCMP1_B64 , //: SCC = (S0.u[S1.u[5:0]] == 1). S_SETVSKIP , //: VSKIP = S0.u[S1.u[4:0]]. // VI+ S_CMP_EQ_U64 , // SCC = SCC = (S0.i64 == S1.i64). S_CMP_NE_U64 , // SXCCX = (S0 != S1). S_SET_GPR_IDX_ON , //: Enable GPR indexing mode. Vector operations after this will perform relative GPR addressing based on the contents of M0. // The structure SQ_M0_GPR_IDX_WORD may be used to decode M0. // The raw contents of the S1 field are read and used to set the enable bits. // S1[0] = VSRC0_REL, S1[1] = VSRC1_REL, S1[2] = VSRC2_REL, and S1[3] = VDST_REL. // MODE.gpr_idx_en = 1; // M0[7:0] = S0.u[7:0]; // M0[15:12] = SIMM4 (direct contents of S1 field); ///////////////////////////////////////// // SOPP ///////////////////////////////////////// S_NOP , //: do nothing. Repeat NOP 1..8 times based on SIMM16[2:0]. 0 = 1 time, 7 = 8 times. S_ENDPGM , //: end of program; terminate wavefront. S_BRANCH , //: PC = PC + signext(SIMM16 * 4) + 4. S_CBRANCH_SCC0 , //: if(SCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. S_CBRANCH_SCC1 , //: if(SCC == 1) then PC = PC + signext(SIMM16 * 4) + 4; else nop. S_CBRANCH_VCCZ , //: if(VCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. S_CBRANCH_VCCNZ , //: if(VCC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. S_CBRANCH_EXECZ , //: if(EXEC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. S_CBRANCH_EXECNZ , //: if(EXEC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. S_BARRIER , //: Sync waves within a thread group. S_WAITCNT , //: Wait for count of outstanding lds, vector-memory and // export/vmem-write-data to be at or below the specified levels. simm16[3:0] = // vmcount, simm16[6:4] = export/mem-write-data count, simm16[12:8] = // LGKM_cnt (scalar-mem/GDS/LDS count). S_SETHALT , //: set HALT bit to value of SIMM16[0]. 1=halt, 0=resume. Halt is ignored while priv=1. S_SLEEP , //: Cause a wave to sleep for approximately 64*SIMM16[2:0] clocks. S_SETPRIO , //: User settable wave priority. 0 = lowest, 3 = highest. S_SENDMSG , //: Send a message. S_SENDMSGHALT , //: Send a message and then HALT. S_TRAP , //: Enter the trap handler. TrapID = SIMM16[7:0]. Wait for all instructions to complete, // save {pc_rewind,trapID,pc} into ttmp0,1; load TBA into PC, // set PRIV=1 and continue. S_ICACHE_INV , //: Invalidate entire L1 I cache. S_INCPERFLEVEL , //: Increment performance counter specified in SIMM16[3:0] by 1. S_DECPERFLEVEL , //: Decrement performance counter specified in SIMM16[3:0] by 1. S_TTRACEDATA , //: Send M0 as user data to thread-trace. // Sea islands and above only... S_CBRANCH_CDBGSYS ,// : If (conditional_debug_system != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. S_CBRANCH_CDBGUSER ,// : If (conditional_debug_user != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. S_CBRANCH_CDBGSYS_OR_USER ,// : If (conditional_debug_system || conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. S_CBRANCH_CDBGSYS_AND_USER ,// : If (conditional_debug_system && conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. // VI+ S_ENDPGM_SAVED, S_SET_GPR_IDX_OFF, S_SET_GPR_IDX_MODE, S_SETKILL, }; enum ScalarMemoryInstructions { ///////////////////////////////////////// // SMRD (GCN1) SMEM(GCN3) ///////////////////////////////////////// S_LOAD_DWORD ,// : Read from read-only constant memory. S_LOAD_DWORDX2 ,// : Read from read-only constant memory. S_LOAD_DWORDX4 ,// : Read from read-only constant memory. S_LOAD_DWORDX8 ,// : Read from read-only constant memory. S_LOAD_DWORDX16 ,// : Read from read-only constant memory. S_BUFFER_LOAD_DWORD ,// : Read from read-only constant memory. S_BUFFER_LOAD_DWORDX2 ,// : Read from read-only constant memory. S_BUFFER_LOAD_DWORDX4 ,// : Read from read-only constant memory. S_BUFFER_LOAD_DWORDX8 ,// : Read from read-only constant memory. S_BUFFER_LOAD_DWORDX16 ,// : Read from read-only constant memory. S_DCACHE_INV_VOL ,// : Invalidate all volatile lines in L1 constant cache. S_MEMTIME ,// : Return current 64-bit timestamp. S_DCACHE_INV ,// : Invalidate entire L1 K cache. // VI+ S_STORE_DWORD ,//: Write one Dword to scalar data cache. If the offset is specified as an SGPR, the SGPR contains an unsigned BYTE offset (the two LSBs are ignored). If the offset is specified as an immediate 20-bit constant, the constant is an unsigned byte offset. S_STORE_DWORDX2 ,//: Write two Dwords to scalar data cache. See S_STORE_DWORD for details on the offset input. S_STORE_DWORDX4 ,//: Write four Dwords to scalar data cache. See S_STORE_DWORD for details on the offset input. S_BUFFER_STORE_DWORD ,//: Write one Dword to scalar data cache. See S_STORE_DWORD for details on the offset input. S_BUFFER_STORE_DWORDX2 ,//: Write two Dwords to scalar data cache. See S_STORE_DWORD for details on the offset input S_BUFFER_STORE_DWORDX4 ,//: Write four Dwords to scalar data cache. See S_STORE_DWORD for details on the offset input. S_DCACHE_WB ,//: Write back dirty data in the scalar data cache. S_DCACHE_WB_VOL ,//: Write back dirty data in the scalar data cache volatile lines. S_MEMREALTIME ,//: Return current 64-bit RTC. S_ATC_PROBE ,//: Probe or prefetch an address into the SQC data cache. S_ATC_PROBE_BUFFER ,//: Probe or prefetch an address into the SQC data cache. }; enum VectorInstructions { V_INVALID = 0xffffffff, ///////////////////////////////////////// // VOP2, or VOP3a ///////////////////////////////////////// V_CNDMASK_B32 , //: D.u = VCC[i] ? S1.u : S0.u (i = threadID in wave). V_READLANE_B32 , //: copy one VGPR value to one SGPR. Dst = SGPR-dest, // Src0 = Source Data (VGPR# or M0(lds-direct)), Src1 = Lane Select (SGPR // or M0). Ignores exec mask. V_WRITELANE_B32 , //: Write value into one VGPR one one lane. Dst = VGPRdest, // Src0 = Source Data (sgpr, m0, exec or constants), Src1 = Lane Select // (SGPR or M0). Ignores exec mask. V_ADD_F32 , //: D.f = S0.f + S1.f. V_SUB_F32 , //: D.f = S0.f - S1.f. V_SUBREV_F32 , //: D.f = S1.f - S0.f. V_MAC_LEGACY_F32 , //: D.f = S0.F * S1.f + D.f. V_MUL_LEGACY_F32 , //: D.f = S0.f * S1.f (DX9 rules, 0.0*x = 0.0). V_MUL_F32 , //: D.f = S0.f * S1.f. V_MUL_I32_I24 , //: D.i = S0.i[23:0] * S1.i[23:0]. V_MUL_HI_I32_I24 , //: D.i = (S0.i[23:0] * S1.i[23:0])>>32. V_MUL_U32_U24 , //: D.u = S0.u[23:0] * S1.u[23:0]. V_MUL_HI_U32_U24 , //: D.i = (S0.u[23:0] * S1.u[23:0])>>32. V_MIN_LEGACY_F32 , //: D.f = min(S0.f, S1.f) (DX9 rules for NaN). V_MAX_LEGACY_F32 , //: D.f = max(S0.f, S1.f) (DX9 rules for NaN). V_MIN_F32 , //: D.f = min(S0.f, S1.f). V_MAX_F32 , //: D.f = max(S0.f, S1.f). V_MIN_I32 , //: D.i = min(S0.i, S1.i). V_MAX_I32 , //: D.i = max(S0.i, S1.i). V_MIN_U32 , //: D.u = min(S0.u, S1.u). V_MAX_U32 , //: D.u = max(S0.u, S1.u). V_LSHR_B32 , //: D.u = S0.u >> S1.u[4:0]. V_LSHRREV_B32 , //: D.u = S1.u >> S0.u[4:0]. V_ASHR_I32 , //: D.i = S0.i >> S1.i[4:0]. V_ASHRREV_I32 , //: D.i = S1.i >> S0.i[4:0]. V_LSHL_B32 , //: D.u = S0.u << S1.u[4:0]. V_LSHLREV_B32 , //: D.u = S1.u << S0.u[4:0]. V_AND_B32 , //: D.u = S0.u & S1.u. V_OR_B32 , //: D.u = S0.u | S1.u. V_XOR_B32 , //: D.u = S0.u ^ S1.u. V_BFM_B32 , //: D.u = ((1<u8(s0.f), pack into byte(s1.u), of dst. V_CVT_PKNORM_I16_F32 , // : D = {(snorm)S1.f, (snorm)S0.f}. V_CVT_PKNORM_U16_F32 , // : D = {(unorm)S1.f, (unorm)S0.f}. V_CVT_PKRTZ_F16_F32 , // : D = {flt32_to_flt16(S1.f),flt32_to_flt16(S0.f)}, with round-toward-zero. V_CVT_PK_U16_U32 , // : D = {(u32->u16)S1.u, (u32->u16)S0.u}. V_CVT_PK_I16_I32 , // : D = {(i32->i16)S1.i, (i32->i16)S0.i}. // Volcanic islands V_ADD_F16 ,// : D.f16 = S0.f16 + S1.f16. Supports denormals, round mode, exception flags, saturation. V_SUB_F16 ,// : D.f16 = S0.f16 - S1.f16. Supports denormals, round mode, exception flags, saturation. SQ translates to V_ADD_F16. V_SUBREV_F16 ,// : D.f16 = S1.f16 - S0.f16. Supports denormals, round mode, exception flags, saturation. SQ translates to V_ADD_F16. V_MUL_F16 ,// : D.f16 = S0.f16 * S1.f16. Supports denormals, round mode, exception flags, saturation. V_MAC_F16 ,// : D.f16 = S0.f16 * S1.f16 + D.f16. Supports round mode, exception flags, saturation. SQ translates this to V_MAD_F16. V_MADMK_F16 ,// : D.f16 = S0.f16 * K.f16 + S1.f16; K is a 16-bit inline constant stored in the following literal Dword. This opcode cannot use the VOP3 encoding and cannot use input/output modifiers. Supports round mode, exception flags, saturation. SQ translates this to V_MAD_F16. V_MADAK_F16 ,// : D.f16 = S0.f16 * S1.f16 + K.f16; K is a 16-bit inline constant stored in the following literal Dword. This opcode cannot use the VOP3 encoding and cannot use input/output modifiers. Supports round mode, exception flags, saturation. SQ translates this to V_MAD_F16. V_ADD_U16 ,// : D.u16 = S0.u16 + S1.u16. Supports saturation (unsigned 16-bit integer domain). V_SUB_U16 ,// : D.u16 = S0.u16 - S1.u16. Supports saturation (unsigned 16-bit integer domain). V_SUBREV_U16 ,// : D.u16 = S1.u16 - S0.u16. Supports saturation (unsigned 16-bit integer domain). SQ translates this to V_SUB_U16 with reversed operands. V_MUL_LO_U16 ,// : D.u16 = S0.u16 * S1.u16. Supports saturation (unsigned 16-bit integer domain). V_LSHLREV_B16 ,// : D.u[15:0] = S1.u[15:0] << S0.u[3:0]. SQ translates this to an internal SP opcode. V_LSHRREV_B16 ,// : D.u[15:0] = S1.u[15:0] >> S0.u[3:0]. The vacated bits are set to zero. SQ translates this to an internal SP opcode. V_ASHRREV_I16 ,// : D.i[15:0] = signext(S1.i[15:0]) >> S0.i[3:0]. The vacated bits are set to the sign bit of the input value. SQ translates this to an internal SP opcode. V_MAX_F16 ,// : D.f16 = max(S0.f16, S1.f16). IEEE compliant. Supports denormals, round mode, exception flags, saturation. V_MIN_F16 ,// : D.f16 = min(S0.f16, S1.f16). IEEE compliant. Supports denormals, round mode, exception flags, saturation. V_MAX_U16 ,// : D.u[15:0] = max(S0.u[15:0], S1.u[15:0]). V_MAX_I16 ,// : D.i[15:0] = max(S0.i[15:0], S1.i[15:0]). V_MIN_U16 ,// : D.u[15:0] = min(S0.u[15:0], S1.u[15:0]). V_MIN_I16 ,// : D.i[15:0] = min(S0.i[15:0], S1.i[15:0]). V_LDEXP_F16 ,// : D.f16 = S0.f16 * (2 ** S1.i16). ///////////////////////////////////////// // VOP1, or VOP3a ///////////////////////////////////////// V_NOP , //: do nothing. V_MOV_B32 , //: D.u = S0.u. V_READFIRSTLANE_B32 , //: copy one VGPR value to one SGPR. Dst = SGPRdest, // Src0 = Source Data (VGPR# or M0(lds-direct)), Lane# = // FindFirst1fromLSB(exec) (lane = 0 if exec is zero). Ignores exec mask. V_CVT_I32_F64 , //: D.i = (int)S0.d. V_CVT_F64_I32 , //: D.f = (float)S0.i. V_CVT_F32_I32 , //: D.f = (float)S0.i. V_CVT_F32_U32 , //: D.f = (float)S0.u. V_CVT_U32_F32 , //: D.u = (unsigned)S0.f. V_CVT_I32_F32 , //: D.i = (int)S0.f. V_MOV_FED_B32 , //: D.u = S0.u, introduce edc double error upon write to dest vgpr without causing an exception. V_CVT_F16_F32 , //: D.f16 = flt32_to_flt16(S0.f). V_CVT_F32_F16 , //: D.f = flt16_to_flt32(S0.f16). V_CVT_RPI_I32_F32 , //: D.i = (int)floor(S0.f + 0.5). V_CVT_FLR_I32_F32 , //: D.i = (int)floor(S0.f). V_CVT_OFF_F32_I4 , //: 4-bit signed int to 32-bit float. For interpolation in shader. V_CVT_F32_F64 , //: D.f = (float)S0.d. V_CVT_F64_F32 , //: D.d = (double)S0.f. V_CVT_F32_UBYTE0 , //: D.f = UINT2FLT(S0.u[7:0]). V_CVT_F32_UBYTE1 , //: D.f = UINT2FLT(S0.u[15:8]). V_CVT_F32_UBYTE2 , //: D.f = UINT2FLT(S0.u[23:16]). V_CVT_F32_UBYTE3 , //: D.f = UINT2FLT(S0.u[31:24]). V_CVT_U32_F64 , //: D.u = (uint)S0.d. V_CVT_F64_U32 , //: D.d = (double)S0.u. // 23-26 Sea islands only V_TRUNC_F64 , //: D.d = trunc(S0.d), return integer part of S0.d. V_CEIL_F64 , //: D.d = trunc(S0.d); if (S0.d > 0.0 && S0.d != D.d), D.d += 1.0. V_RNDNE_F64 , //: D.d = round_nearest_even(S0.d). V_FLOOR_F64 , //: D.d = trunc(S0.d); if (S0.d < 0.0 && S0.d != D.d), D.d += -1.0. // 27 31 reserved. V_FRACT_F32 , //: D.f = S0.f - floor(S0.f). V_TRUNC_F32 , //: D.f = trunc(S0.f), return integer part of S0. V_CEIL_F32 , //: D.f = ceil(S0.f). Implemented as: D.f = trunc(S0.f); if (S0 > 0.0 && S0 != D), D += 1.0. V_RNDNE_F32 , //: D.f = round_nearest_even(S0.f). V_FLOOR_F32 , //: D.f = trunc(S0); if ((S0 < 0.0) && (S0 != D)) D += -1.0. V_EXP_F32 , //: D.f = pow(2.0, S0.f). V_LOG_CLAMP_F32 , //: D.f = log2(S0.f), clamp -infinity to -max_float. V_LOG_F32 , //: D.f = log2(S0.f). V_RCP_CLAMP_F32 , //: D.f = 1.0 / S0.f, result clamped to +-max_float. V_RCP_LEGACY_F32 , //: D.f = 1.0 / S0.f, +-infinity result clamped to +-0.0. V_RCP_F32 , //: D.f = 1.0 / S0.f. V_RCP_IFLAG_F32 , //: D.f = 1.0 / S0.f, only integer div_by_zero flag can be raised. V_RSQ_CLAMP_F32 , //: D.f = 1.0 / sqrt(S0.f), result clamped to +-max_float. V_RSQ_LEGACY_F32 , //: D.f = 1.0 / sqrt(S0.f). V_RSQ_F32 , //: D.f = 1.0 / sqrt(S0.f). V_RCP_F64 , //: D.d = 1.0 / (S0.d). V_RCP_CLAMP_F64 , //: D.f = 1.0 / (S0.f), result clamped to +-max_float. V_RSQ_F64 , //: D.f = 1.0 / sqrt(S0.f). V_RSQ_CLAMP_F64 , //: D.d = 1.0 / sqrt(S0.d), result clamped to +-max_float. V_SQRT_F32 , //: D.f = sqrt(S0.f). V_SQRT_F64 , //: D.d = sqrt(S0.d). V_SIN_F32 , //: D.f = sin(S0.f). V_COS_F32 , //: D.f = cos(S0.f). V_NOT_B32 , //: D.u = ~S0.u. V_BFREV_B32 , //: D.u[31:0] = S0.u[0:31], bitfield reverse. V_FFBH_U32 , //: D.u = position of first 1 in S0 from MSB; D=0xFFFFFFFF if S0==0. V_FFBL_B32 , //: D.u = position of first 1 in S0 from LSB; D=0xFFFFFFFF if S0==0. V_FFBH_I32 , //: D.u = position of first bit different from sign bit in S0 from MSB;D=0xFFFFFFFF if S0==0 or 0xFFFFFFFF. V_FREXP_EXP_I32_F64 , //: See V_FREXP_EXP_I32_F32. V_FREXP_MANT_F64 , //: See V_FREXP_MANT_F32. V_FRACT_F64 , //: S0.d - floor(S0.d). V_FREXP_EXP_I32_F32 , //: If (S0.f == INF || S0.f == NAN), then D.i = 0; else D.i // = TwosComplement(Exponent(S0.f) - 127 + 1). Returns exponent of single // precision float input, such that S0.f = significand * (2 ** exponent). See also // FREXP_MANT_F32, which returns the significand. V_FREXP_MANT_F32 , //: if (S0.f == INF || S0.f == NAN) then D.f = S0.f; else D.f = // Mantissa(S0.f). Result range is in (-1.0,-0.5][0.5,1.0) in normal cases. // Returns binary significand of single precision float input, such that S0.f = significand // * (2 ** exponent). See also FREXP_EXP_I32_F32, which returns integer // exponent. V_CLREXCP , //: Clear wave's exception state in SIMD(SP). V_MOVRELD_B32 , //: VGPR[D.u + M0.u] = VGPR[S0.u]. V_MOVRELS_B32 , //: VGPR[D.u] = VGPR[S0.u + M0.u]. V_MOVRELSD_B32 , //: VGPR[D.u + M0.u] = VGPR[S0.u + M0.u]. // Sea Islands only.. V_LOG_LEGACY_F32 , //: D.f = log2(S0.f). Base 2 logarithm. Same as Southern Islands. (CI Doc says "..same as Sea Islands" typo?) V_EXP_LEGACY_F32 , //: D.f = pow(2.0, S0.f). Same as Southern Islands. // VI+ V_CVT_F16_U16 ,// : D.f16 = uint16_to_flt16(S.u16). Supports denormals, rounding, exception flags and saturation. V_CVT_F16_I16 ,// : D.f16 = int16_to_flt16(S.i16). Supports denormals, rounding, exception flags and saturation. V_CVT_U16_F16 ,// : D.u16 = flt16_to_uint16(S.f16). Supports rounding, exception flags and saturation. V_CVT_I16_F16 ,// : D.i16 = flt16_to_int16(S.f16). Supports rounding, exception flags and saturation. V_RCP_F16 ,// : if(S0.f16 == 1.0f), D.f16 = 1.0f; else D.f16 = ApproximateRecip(S0.f16). V_SQRT_F16 ,// : if(S0.f16 == 1.0f)\tD.f16 = 1.0f; else D.f16 = ApproximateSqrt(S0.f16). V_RSQ_F16 ,// : if(S0.f16 == 1.0f) D.f16 = 1.0f; else D.f16 = ApproximateRecipSqrt(S0.f16). V_LOG_F16 ,// : if(S0.f16 == 1.0f) D.f16 = 0.0f; else D.f16 = ApproximateLog2(S0.f16). V_EXP_F16 ,// : if(S0.f16 == 0.0f) D.f16 = 1.0f; else D.f16 = Approximate2ToX(S0.f16). V_FREXP_MANT_F16 ,// : if(S0.f16 == +-INF || S0.f16 == NAN) D.f16 = S0.f16; else D.f16 = mantissa(S0.f16). Result range is (-1.0,-0.5][0.5,1.0). C math library frexp function. Returns binary significand of half precision float input, such that the original single float = significand * (2 ** exponent). V_FREXP_EXP_I16_F16 ,// : if(S0.f16 == +-INF || S0.f16 == NAN) D.i16 = 0; else D.i16 = 2s_complement(exponent(S0.f16) - 15 + 1). C math library frexp function. Returns exponent of half precision float input, such that the original single float = significand * (2 ** exponent). V_FLOOR_F16 ,// : D.f16 = trunc(S0.f16); if(S0.f16 < 0.0f && S0.f16 != D.f16) then D.f16 -= 1.0f. V_CEIL_F16 ,// : D.f16 = trunc(S0.f16); if(S0.f16 > 0.0f && S0.f16 != D.f16) then D.f16 += 1.0f. V_TRUNC_F16 ,// : D.f16 = trunc(S0.f16).\n\nRound-to-zero semantics. V_RNDNE_F16 ,// : D.f16 = FLOOR(S0.f16 + 0.5f); if(floor(S0.f16) is even && fract(S0.f16) == 0.5f) then D.f16 -= 1.0f. Round-to-nearest-even semantics. V_FRACT_F16 ,// : D.f16 = S0.f16 + -floor(S0.f16). V_SIN_F16 ,// : D.f16 = sin(S0.f16 * 2 * PI). V_COS_F16 ,// : D.f16 = cos(S0.f16 * 2 * PI). ///////////////////////////////////////// // VOPC, or VOP3a ///////////////////////////////////////// V_CMP_F_F32 , // D.u = 0 // Signal on sNaN input only. V_CMP_LT_F32 , // D.u = (S0 < S1) V_CMP_EQ_F32 , // D.u = (S0 == S1) V_CMP_LE_F32 , // D.u = (S0 <= S1) V_CMP_GT_F32 , // D.u = (S0 > S1) V_CMP_LG_F32 , // D.u = (S0 <> S1) V_CMP_GE_F32 , // D.u = (S0 >= S1) V_CMP_O_F32 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMP_U_F32 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMP_NGE_F32 , // D.u = !(S0 >= S1) V_CMP_NLG_F32 , // D.u = !(S0 <> S1) V_CMP_NGT_F32 , // D.u = !(S0 > S1) V_CMP_NLE_F32 , // D.u = !(S0 <= S1) V_CMP_NEQ_F32 , // D.u = !(S0 == S1) V_CMP_NLT_F32 , // D.u = !(S0 < S1) V_CMP_TRU_F32 , // D.u = 1 V_CMPX_F_F32 , // Signal on sNaN input only. Also write EXEC. V_CMPX_LT_F32 , // D.u = (S0 < S1) V_CMPX_EQ_F32 , // D.u = (S0 == S1) V_CMPX_LE_F32 , // D.u = (S0 <= S1) V_CMPX_GT_F32 , // D.u = (S0 > S1) V_CMPX_LG_F32 , // D.u = (S0 <> S1) V_CMPX_GE_F32 , // D.u = (S0 >= S1) V_CMPX_O_F32 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMPX_U_F32 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMPX_NGE_F32 , // D.u = !(S0 >= S1) V_CMPX_NLG_F32 , // D.u = !(S0 <> S1) V_CMPX_NGT_F32 , // D.u = !(S0 > S1) V_CMPX_NLE_F32 , // D.u = !(S0 <= S1) V_CMPX_NEQ_F32 , // D.u = !(S0 == S1) V_CMPX_NLT_F32 , // D.u = !(S0 < S1) V_CMPX_TRU_F32 , // D.u = 1 V_CMP_F_F64 , // Signal on sNaN input only. V_CMP_LT_F64 , // D.u = (S0 < S1) V_CMP_EQ_F64 , // D.u = (S0 == S1) V_CMP_LE_F64 , // D.u = (S0 <= S1) V_CMP_GT_F64 , // D.u = (S0 > S1) V_CMP_LG_F64 , // D.u = (S0 <> S1) V_CMP_GE_F64 , // D.u = (S0 >= S1) V_CMP_O_F64 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMP_U_F64 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMP_NGE_F64 , // D.u = !(S0 >= S1) V_CMP_NLG_F64 , // D.u = !(S0 <> S1) V_CMP_NGT_F64 , // D.u = !(S0 > S1) V_CMP_NLE_F64 , // D.u = !(S0 <= S1) V_CMP_NEQ_F64 , // D.u = !(S0 == S1) V_CMP_NLT_F64 , // D.u = !(S0 < S1) V_CMP_TRU_F64 , // D.u = 1 V_CMPX_F_F64 , // Signal on sNaN input only. Also write EXEC. V_CMPX_LT_F64 , // D.u = (S0 < S1) V_CMPX_EQ_F64 , // D.u = (S0 == S1) V_CMPX_LE_F64 , // D.u = (S0 <= S1) V_CMPX_GT_F64 , // D.u = (S0 > S1) V_CMPX_LG_F64 , // D.u = (S0 <> S1) V_CMPX_GE_F64 , // D.u = (S0 >= S1) V_CMPX_O_F64 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMPX_U_F64 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMPX_NGE_F64 , // D.u = !(S0 >= S1) V_CMPX_NLG_F64 , // D.u = !(S0 <> S1) V_CMPX_NGT_F64 , // D.u = !(S0 > S1) V_CMPX_NLE_F64 , // D.u = !(S0 <= S1) V_CMPX_NEQ_F64 , // D.u = !(S0 == S1) V_CMPX_NLT_F64 , // D.u = !(S0 < S1) V_CMPX_TRU_F64 , // D.u = 1 V_CMPS_F_F32 , // Signal on any NaN. V_CMPS_LT_F32 , // D.u = (S0 < S1) V_CMPS_EQ_F32 , // D.u = (S0 == S1) V_CMPS_LE_F32 , // D.u = (S0 <= S1) V_CMPS_GT_F32 , // D.u = (S0 > S1) V_CMPS_LG_F32 , // D.u = (S0 <> S1) V_CMPS_GE_F32 , // D.u = (S0 >= S1) V_CMPS_O_F32 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMPS_U_F32 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMPS_NGE_F32 , // D.u = !(S0 >= S1) V_CMPS_NLG_F32 , // D.u = !(S0 <> S1) V_CMPS_NGT_F32 , // D.u = !(S0 > S1) V_CMPS_NLE_F32 , // D.u = !(S0 <= S1) V_CMPS_NEQ_F32 , // D.u = !(S0 == S1) V_CMPS_NLT_F32 , // D.u = !(S0 < S1) V_CMPS_TRU_F32 , // D.u = 1 V_CMPSX_F_F32 , // Signal on any NaN. Also write EXEC. V_CMPSX_LT_F32 , // D.u = (S0 < S1) V_CMPSX_EQ_F32 , // D.u = (S0 == S1) V_CMPSX_LE_F32 , // D.u = (S0 <= S1) V_CMPSX_GT_F32 , // D.u = (S0 > S1) V_CMPSX_LG_F32 , // D.u = (S0 <> S1) V_CMPSX_GE_F32 , // D.u = (S0 >= S1) V_CMPSX_O_F32 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMPSX_U_F32 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMPSX_NGE_F32 , // D.u = !(S0 >= S1) V_CMPSX_NLG_F32 , // D.u = !(S0 <> S1) V_CMPSX_NGT_F32 , // D.u = !(S0 > S1) V_CMPSX_NLE_F32 , // D.u = !(S0 <= S1) V_CMPSX_NEQ_F32 , // D.u = !(S0 == S1) V_CMPSX_NLT_F32 , // D.u = !(S0 < S1) V_CMPSX_TRU_F32 , // D.u = 1 V_CMPS_F_F64 , // Signal on any NaN. V_CMPS_LT_F64 , // D.u = (S0 < S1) V_CMPS_EQ_F64 , // D.u = (S0 == S1) V_CMPS_LE_F64 , // D.u = (S0 <= S1) V_CMPS_GT_F64 , // D.u = (S0 > S1) V_CMPS_LG_F64 , // D.u = (S0 <> S1) V_CMPS_GE_F64 , // D.u = (S0 >= S1) V_CMPS_O_F64 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMPS_U_F64 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMPS_NGE_F64 , // D.u = !(S0 >= S1) V_CMPS_NLG_F64 , // D.u = !(S0 <> S1) V_CMPS_NGT_F64 , // D.u = !(S0 > S1) V_CMPS_NLE_F64 , // D.u = !(S0 <= S1) V_CMPS_NEQ_F64 , // D.u = !(S0 == S1) V_CMPS_NLT_F64 , // D.u = !(S0 < S1) V_CMPS_TRU_F64 , // D.u = 1 V_CMPSX_F_F64 , // Signal on any NaN. Also write EXEC. V_CMPSX_LT_F64 , // D.u = (S0 < S1) V_CMPSX_EQ_F64 , // D.u = (S0 == S1) V_CMPSX_LE_F64 , // D.u = (S0 <= S1) V_CMPSX_GT_F64 , // D.u = (S0 > S1) V_CMPSX_LG_F64 , // D.u = (S0 <> S1) V_CMPSX_GE_F64 , // D.u = (S0 >= S1) V_CMPSX_O_F64 , // D.u = (!isNaN(S0) && !isNaN(S1)) V_CMPSX_U_F64 , // D.u = (!isNaN(S0) || !isNaN(S1)) V_CMPSX_NGE_F64 , // D.u = !(S0 >= S1) V_CMPSX_NLG_F64 , // D.u = !(S0 <> S1) V_CMPSX_NGT_F64 , // D.u = !(S0 > S1) V_CMPSX_NLE_F64 , // D.u = !(S0 <= S1) V_CMPSX_NEQ_F64 , // D.u = !(S0 == S1) V_CMPSX_NLT_F64 , // D.u = !(S0 < S1) V_CMPSX_TRU_F64 , // D.u = 1 V_CMP_F_I32 , //D.u = 0 , // On 32-bit integers. V_CMP_LT_I32 , //D.u = (S0 < S1) V_CMP_EQ_I32 , //D.u = (S0 == S1) V_CMP_LE_I32 , //D.u = (S0 <= S1) V_CMP_GT_I32 , //D.u = (S0 > S1) V_CMP_LG_I32 , //D.u = (S0 <> S1) V_CMP_GE_I32 , //D.u = (S0 >= S1) V_CMP_TRU_I32 , //D.u = 1 V_CMPX_F_I32 , // Also write EXEC. V_CMPX_LT_I32 ,//D.u = (S0 < S1) V_CMPX_EQ_I32 ,//D.u = (S0 == S1) V_CMPX_LE_I32 ,//D.u = (S0 <= S1) V_CMPX_GT_I32 ,//D.u = (S0 > S1) V_CMPX_LG_I32 ,//D.u = (S0 <> S1) V_CMPX_GE_I32 ,//D.u = (S0 >= S1) V_CMPX_TRU_I32 ,//D.u = 1 V_CMP_F_I64 , // On 64-bit integers. V_CMP_LT_I64 ,//D.u = (S0 < S1) V_CMP_EQ_I64 ,//D.u = (S0 == S1) V_CMP_LE_I64 ,//D.u = (S0 <= S1) V_CMP_GT_I64 ,//D.u = (S0 > S1) V_CMP_LG_I64 ,//D.u = (S0 <> S1) V_CMP_GE_I64 ,//D.u = (S0 >= S1) V_CMP_TRU_I64 ,//D.u = 1 V_CMPX_F_I64 , // Also write EXEC. V_CMPX_LT_I64 ,//D.u = (S0 < S1) V_CMPX_EQ_I64 ,//D.u = (S0 == S1) V_CMPX_LE_I64 ,//D.u = (S0 <= S1) V_CMPX_GT_I64 ,//D.u = (S0 > S1) V_CMPX_LG_I64 ,//D.u = (S0 <> S1) V_CMPX_GE_I64 ,//D.u = (S0 >= S1) V_CMPX_TRU_I64 ,//D.u = 1 V_CMP_F_U32 , // On unsigned 32-bit integers. V_CMP_LT_U32 ,//D.u = (S0 < S1) V_CMP_EQ_U32 ,//D.u = (S0 == S1) V_CMP_LE_U32 ,//D.u = (S0 <= S1) V_CMP_GT_U32 ,//D.u = (S0 > S1) V_CMP_LG_U32 ,//D.u = (S0 <> S1) V_CMP_GE_U32 ,//D.u = (S0 >= S1) V_CMP_TRU_U32 ,//D.u = 1 V_CMPX_F_U32 , // Also write EXEC. V_CMPX_LT_U32 ,//D.u = (S0 < S1) V_CMPX_EQ_U32 ,//D.u = (S0 == S1) V_CMPX_LE_U32 ,//D.u = (S0 <= S1) V_CMPX_GT_U32 ,//D.u = (S0 > S1) V_CMPX_LG_U32 ,//D.u = (S0 <> S1) V_CMPX_GE_U32 ,//D.u = (S0 >= S1) V_CMPX_TRU_U32 ,//D.u = 1 V_CMP_F_U64 , // On unsigned 64-bit integers. V_CMP_LT_U64 ,//D.u = (S0 < S1) V_CMP_EQ_U64 ,//D.u = (S0 == S1) V_CMP_LE_U64 ,//D.u = (S0 <= S1) V_CMP_GT_U64 ,//D.u = (S0 > S1) V_CMP_LG_U64 ,//D.u = (S0 <> S1) V_CMP_GE_U64 ,//D.u = (S0 >= S1) V_CMP_TRU_U64 ,//D.u = 1 V_CMPx_F_U64 , // Also write EXEC. V_CMPx_LT_U64 ,//D.u = (S0 < S1) V_CMPx_EQ_U64 ,//D.u = (S0 == S1) V_CMPx_LE_U64 ,//D.u = (S0 <= S1) V_CMPx_GT_U64 ,//D.u = (S0 > S1) V_CMPx_LG_U64 ,//D.u = (S0 <> S1) V_CMPx_GE_U64 ,//D.u = (S0 >= S1) V_CMPx_TRU_U64 ,//D.u = 1 V_CMP_CLASS_F32 , // D = IEEE numeric class function specified in S1.u, performed on S0.f. V_CMPX_CLASS_F32 , // D = IEEE numeric class function specified in S1.u, performed on S0.f. Also write EXEC. V_CMP_CLASS_F64 , // D = IEEE numeric class function specified in S1.u, performed on S0.d. V_CMPX_CLASS_F64 , // D = IEEE numeric class function specified inS1.u, performed on S0.d. Also write EXEC. // VI only V_CMP_F_F16 , V_CMP_LT_F16 , V_CMP_EQ_F16 , V_CMP_LE_F16 , V_CMP_GT_F16 , V_CMP_LG_F16 , V_CMP_GE_F16 , V_CMP_O_F16 , V_CMP_U_F16 , V_CMP_NGE_F16 , V_CMP_NLG_F16 , V_CMP_NGT_F16 , V_CMP_NLE_F16 , V_CMP_NEQ_F16 , V_CMP_NLT_F16 , V_CMP_TRU_F16 , V_CMPX_F_F16 , V_CMPX_LT_F16 , V_CMPX_EQ_F16 , V_CMPX_LE_F16 , V_CMPX_GT_F16 , V_CMPX_LG_F16 , V_CMPX_GE_F16 , V_CMPX_O_F16 , V_CMPX_U_F16 , V_CMPX_NGE_F16 , V_CMPX_NLG_F16 , V_CMPX_NGT_F16 , V_CMPX_NLE_F16 , V_CMPX_NEQ_F16 , V_CMPX_NLT_F16 , V_CMPX_TRU_F16 , V_CMP_F_U16 , V_CMP_LT_U16 , V_CMP_EQ_U16 , V_CMP_LE_U16 , V_CMP_GT_U16 , V_CMP_LG_U16 , V_CMP_GE_U16 , V_CMP_TRU_U16 , V_CMPx_F_U16 , V_CMPx_LT_U16 , V_CMPx_EQ_U16 , V_CMPx_LE_U16 , V_CMPx_GT_U16 , V_CMPx_LG_U16 , V_CMPx_GE_U16 , V_CMPx_TRU_U16 , V_CMP_F_I16 , V_CMP_LT_I16 , V_CMP_EQ_I16 , V_CMP_LE_I16 , V_CMP_GT_I16 , V_CMP_LG_I16 , V_CMP_GE_I16 , V_CMP_TRU_I16 , V_CMPx_F_I16 , V_CMPx_LT_I16 , V_CMPx_EQ_I16 , V_CMPx_LE_I16 , V_CMPx_GT_I16 , V_CMPx_LG_I16 , V_CMPx_GE_I16 , V_CMPx_TRU_I16 , V_CMP_CLASS_F16, V_CMPX_CLASS_F16, ////////////////////////////////////////////////////// // VOP3b ////////////////////////////////////////////////////// V_DIV_SCALE_F32 , // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. V_DIV_SCALE_F64 , // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. ////////////////////////////////////////////////////// // VOP3a ////////////////////////////////////////////////////// V_MAD_LEGACY_F32 , // = D.f = S0.f * S1.f + S2.f (DX9 rules, 0.0*x = 0.0). V_MAD_F32 , // = D.f = S0.f * S1.f + S2.f. V_MAD_I32_I24 , // = D.i = S0.i * S1.i + S2.iD.i = S0.i * S1.i + S2.i. V_MAD_U32_U24 , // = D.u = S0.u * S1.u + S2.u. V_CUBEID_F32 , // = Rm.w <- Rn,x, Rn,y, Rn.z. V_CUBESC_F32 , // = Rm.y <- Rn,x, Rn,y, Rn.z. V_CUBETC_F32 , // = Rm.x <- Rn,x, Rn,y, Rn.z. V_CUBEMA_F32 , // = Rm.z <- Rn,x, Rn,y, Rn.z V_BFE_U32 , // = D.u = (S0.u>>S1.u[4:0]) & ((1<>S1.u[4:0]) & ((1<> 1) << 24 + // S1.u[15:8] + S2.u[8]) >> 1) << 8 + ((S0.u[7:0] + S1.u[7:0] + S2.u[0]) >> 1). // Unsigned eight-bit pixel average on packed unsigned bytes (linear interpolation). // S2 acts as a round mode; if set, 0.5 rounds up; otherwise, 0.5 truncates. V_ALIGNBIT_B32 , // = D.u = ({S0,S1} >> S2.u[4:0]) & 0xFFFFFFFF. V_ALIGNBYTE_B32 , // = D.u = ({S0,S1} >> (8*S2.u[4:0])) & 0xFFFFFFFF. V_MULLIT_F32 , // = D.f = S0.f * S1.f, replicate result into 4 components (0.0 * x = 0.0; special INF, NaN, overflow rules). V_MIN3_F32 , // = D.f = min(S0.f, S1.f, S2.f). V_MIN3_I32 , // = D.i = min(S0.i, S1.i, S2.i). V_MIN3_U32 , // = 0x153 D.u = min(S0.u, S1.u, S2.u). V_MAX3_F32 , // = D.f = max(S0.f, S1.f, S2.f). V_MAX3_I32 , // = D.i = max(S0.i, S1.i, S2.i). V_MAX3_U32 , // = D.u = max(S0.u, S1.u, S2.u). V_MED3_F32 , // = D.f = median(S0.f, S1.f, S2.f). V_MED3_I32 , // = D.i = median(S0.i, S1.i, S2.i). V_MED3_U32 , // = D.u = median(S0.u, S1.u, S2.u). V_SAD_U8 , // = D.u = Byte SAD with accum_lo(S0.u, S1.u, S2.u). V_SAD_HI_U8 , // = D.u = Byte SAD with accum_hi(S0.u, S1.u, S2.u). V_SAD_U16 , // = D.u = Word SAD with accum(S0.u, S1.u, S2.u). V_SAD_U32 , // = D.u = Dword SAD with accum(S0.u, S1.u, S2.u). V_CVT_PK_U8_F32 , // = f32->u8(s0.f), pack into byte(s1.u), of dword(s2). V_DIV_FIXUP_F32 , // = D.f = Special case divide fixup and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). V_DIV_FIXUP_F64 , // = D.d = Special case divide fixup and flags(s0.d = Quotient, s1.d = Denominator, s2.d = Numerator). V_LSHL_B64 , // = D = S0.u << S1.u[4:0]. V_LSHR_B64 , // = D = S0.u >> S1.u[4:0]. V_ASHR_I64 , // = D = S0.u >> S1.u[4:0]. V_ADD_F64 , // = D.d = S0.d + S1.d. V_MUL_F64 , // = D.d = S0.d * S1.d. V_MIN_F64 , // = D.d = min(S0.d, S1.d). V_MAX_F64 , // = D.d = max(S0.d, S1.d). V_LDEXP_F64 , // = D.d = pow(S0.d, S1.i[31:0]). V_MUL_LO_U32 , // = D.u = S0.u * S1.u. V_MUL_HI_U32 , // = D.u = (S0.u * S1.u)>>32. V_MUL_LO_I32 , // = D.i = S0.i * S1.i. V_MUL_HI_I32 , // = D.i = (S0.i * S1.i)>>32. //365 366 See corresponding opcode numbers in VOP3 (3 in, 2 out), (VOP3b). V_DIV_FMAS_F32 , // = D.f = Special case divide FMA with scale and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). V_DIV_FMAS_F64 , // = D.d = Special case divide FMA with scale and flags(s0.d= Quotient, s1.d = Denominator, s2.d = Numerator). V_MSAD_U8 , // = D.u = Masked Byte SAD with accum_lo(S0.u, S1.u, S2.u). // Opcodes 370/371 were renamed between SI and CI. Not sure if they behave differently or not V_QSAD_U8 , // = D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). V_MQSAD_U8 , // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0],S1.u[31:0], S2.u[63:0]). V_QSAD_PK_U16_U8 , // : D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). V_MQSAD_PK_U16_U8 , // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[63:0]). // V_TRIG_PREOP_F64 , // = D.d = Look Up 2/PI (S0.d) with segment select S1.u[4:0]. // these 3 are Sea Islands only V_MQSAD_U32_U8 , // : D.u128 = Masked Quad-Byte SAD with 32-bit accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[127:0]). V_MAD_U64_U32 , // : {vcc_out,D.u64} = S0.u32 * S1.u32 + S2.u64. V_MAD_I64_I32 , // : {vcc_out,D.i64} = S0.i32 * S1.i32 + S2.i64. // new opcodes for VI V_MAD_F16 , //: D.f16 = S0.f16 * S1.f16 + S2.f16 Supports round mode, exception flags, saturation. V_MAD_U16 , //: D.u16 = S0.u16 * S1.u16 + S2.u16. Supports saturation (unsigned 16-bit integer domain). V_MAD_I16 , //: D.i16 = S0.i16 * S1.i16 + S2.i16. Supports saturation (signed 16-bit integer domain). V_PERM_B32 , //: D.u[31:24] = permute({S0.u, S1.u}, S2.u[31:24]); // D.u[23:16] = permute({S0.u, S1.u}, S2.u[23:16]); // D.u[15:8] = permute({S0.u, S1.u}, S2.u[15:8]); // D.u[7:0] = permute({S0.u, S1.u}, S2.u[7:0]); // byte permute(byte in[8], byte sel) { // if(sel>=13) then return 0xff; // elsif(sel==12) then return 0x00; // elsif(sel==11) then return in[7][7] * 0xff; // elsif(sel==10) then return in[5][7] * 0xff; // elsif(sel==9) then return in[3][7] * 0xff; // elsif(sel==8) then return in[1][7] * 0xff; // else return in[sel]; // } // Byte permute. V_FMA_F16 , // : D.f16 = S0.f16 * S1.f16 + S2.f16.\n\nFused half precision multiply add. V_DIV_FIXUP_F16 , V_ADD_U32, V_SUB_U32, V_SUBREV_U32, V_LSHLREV_B64 , V_LSHRREV_B64 , V_ASHRREV_I64 , ////////////////////////////////////////////////////// // VINTERP (can be vop3 on GCN3) ////////////////////////////////////////////////////// V_INTERP_P1_F32 , // : D = P10 * S + P0; parameter interpolation. V_INTERP_P2_F32 , // : D = P20 * S + D; parameter interpolation. V_INTERP_MOV_F32 , // : D = {P10,P20,P0}[S]; parameter load. // New interps for VI, encoded as VOP3 V_INTERP_P1LL_F16, // : D.f32 = P10.f16 * S0.f32 + P0.f16. 'LL' stands for 'two LDS arguments'. attr_word selects the high or low half 16 bits of each LDS dword accessed. This opcode is available for 32-bank LDS only. NOTE: In textual representations the I/J VGPR is the first source and the attribute is the second source; however in the VOP3 encoding the attribute is stored in the src0 field and the VGPR is stored in the src1 field. V_INTERP_P1LV_F16, // : D.f32 = P10.f16 * S0.f32 + (S2.u32 >> (attr_word * 16)).f16. 'LV' stands for 'One LDS and one VGPR argument'. S2 holds two parameters, attr_word selects the high or low word of the VGPR for this calculation, as well as the high or low half of the LDS data." Meant for use with 16-bank LDS. NOTE: In textual representations the I/J VGPR is the first source and the attribute is the second source; however in the VOP3 encoding the attribute is stored in the src0 field and the VGPR is stored in the src1 field. V_INTERP_P2_F16 , // : D.f16 = P20.f16 * S0.f32 + S2.f32. Final computation. attr_word selects LDS high or low 16bits. Used for both 16- and 32-bank LDS. Result is always written to the 16 LSBs of the destination VGPR. NOTE: In textual representations the I/J VGPR is the first source and the attribute is the second source; however in the VOP3 encoding the attribute is stored in the src0 field and the VGPR is stored in the src1 field. }; enum DSInstructions { DS_INVALID=0xffffffff, DS_ADD_U32 = 0 , // DS[A] = DS[A] + D0; uint add. DS_SUB_U32 = 1 , // DS[A] = DS[A] - D0; uint subtract. DS_RSUB_U32 = 2 , // DS[A] = D0 - DS[A]; uint reverse subtract. DS_INC_U32 = 3 , // DS[A] = (DS[A] >= D0 ? 0 : DS[A] + 1); uint increment. DS_DEC_U32 = 4 , // DS[A] = (DS[A] == 0 || DS[A] > D0 ? D0 : DS[A] - 1); uint decrement. DS_MIN_I32 = 5 , // DS[A] = min(DS[A], D0); int min. DS_MAX_I32 = 6 , // DS[A] = max(DS[A], D0); int max. DS_MIN_U32 = 7 , // DS[A] = min(DS[A], D0); uint min. DS_MAX_U32 = 8 , // DS[A] = max(DS[A], D0); uint max. DS_AND_B32 = 9 , // DS[A] = DS[A] & D0; Dword AND. DS_OR_B32 = 10 , // DS[A] = DS[A] | D0; Dword OR. DS_XOR_B32 = 11 , // DS[A] = DS[A] ^ D0; Dword XOR. DS_MSKOR_B32 = 12 , // DS[A] = (DS[A] ^ ~D0) | D1; masked Dword OR. DS_WRITE_B32 = 13 , // DS[A] = D0; write a Dword. DS_WRITE2_B32 = 14 , // DS[ADDR+offset0*4] = D0;DS[ADDR+offset1*4] = D1; write 2 Dwords. DS_WRITE2ST64_B32 = 15 , // DS[ADDR+offset0*4*64] = D0;DS[ADDR+offset1*4*64] = D1; write 2 Dwords. DS_CMPST_B32 = 16 , // DS[A] = (DS[A] == D0 ? D1 : DS[A]); compare store. DS_CMPST_F32 = 17 , // DS[A] = (DS[A] == D0 ? D1 : DS[A]); compare store with float rules. DS_MIN_F32 = 18 , // DS[A] = (DS[A] < D1) ? D0 : DS[A]; float compare swap (handles NaN/INF/denorm). DS_MAX_F32 = 19 , // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. DS_NOP = 20, // Do nothing. SEA ISLANDS ONLY DS_GWS_SEMA_RELEASE_ALL = 24, // GDS Only. Release all wavefronts waiting on this semaphore. ResourceID is in offset[4:0]. SEA ISLANDS ONLY DS_GWS_INIT = 25 , // GDS only. DS_GWS_SEMA_V = 26 , // GDS only. DS_GWS_SEMA_BR = 27 , // GDS only. DS_GWS_SEMA_P = 28 , // GDS only. DS_GWS_BARRIER = 29 , // GDS only. DS_WRITE_B8 = 30 , // DS[A] = D0[7:0]; byte write. DS_WRITE_B16 = 31 , // DS[A] = D0[15:0]; short write. DS_ADD_RTN_U32 = 32 , // Uint add. DS_SUB_RTN_U32 = 33 , // Uint subtract. DS_RSUB_RTN_U32 = 34 , // Uint reverse subtract. DS_INC_RTN_U32 = 35 , // Uint increment. DS_DEC_RTN_U32 = 36 , // Uint decrement. DS_MIN_RTN_I32 = 37 , // Int min. DS_MAX_RTN_I32 = 38 , // Int max. DS_MIN_RTN_U32 = 39 , // Uint min. DS_MAX_RTN_U32 = 40 , // Uint max. DS_AND_RTN_B32 = 41 , // Dword AND. DS_OR_RTN_B32 = 42 , // Dword OR. DS_XOR_RTN_B32 = 43 , // Dword XOR. DS_MSKOR_RTN_B32 = 44 , // Masked Dword OR. DS_WRXCHG_RTN_B32 = 45 , // Write exchange. Offset = {offset1,offset0}. A = ADDR+offset. D=DS[Addr]. DS[Addr]=D0. DS_WRXCHG2_RTN_B32 = 46 , // Write exchange 2 separate Dwords. DS_WRXCHG2ST64_RTN_B32 = 47 , // Write echange 2 Dwords, stride 64. DS_CMPST_RTN_B32 = 48 , // Compare store. DS_CMPST_RTN_F32 = 49 , // Compare store with float rules. DS_MIN_RTN_F32 = 50 , // DS[A] = (DS[A] < D1) ? D0 : DS[A]; float compare swap (handles NaN/INF/denorm). DS_MAX_RTN_F32 = 51 , // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm . DS_WRAP_RTN_B32 = 52 , // DS[A] = (DS[A] >= D0) ? DS[A] - D0 : DS[A] + D1. SEA ISLANDS ONLY DS_SWIZZLE_B32 = 53 , // R = swizzle(Data(vgpr), offset1:offset0). Dword swizzle. no data is written to LDS. see ds_opcodes.docx for details. DS_READ_B32 = 54 , // R = DS[A]; Dword read. DS_READ2_B32 = 55 , // R = DS[ADDR+offset0*4], R+1 = DS[ADDR+offset1*4]. Read 2 Dwords. DS_READ2ST64_B32 = 56 , // R = DS[ADDR+offset0*4*64], R+1 = DS[ADDR+offset1*4*64]. Read 2 Dwords. DS_READ_I8 = 57 , // R = signext(DS[A][7:0]}; signed byte read. DS_READ_U8 = 58 , // R = {24h0,DS[A][7:0]}; unsigned byte read. DS_READ_I16 = 59 , // R = signext(DS[A][15:0]}; signed short read. DS_READ_U16 = 60 , // R = {16h0,DS[A][15:0]}; unsigned short read. DS_CONSUME = 61 , // Consume entries from a buffer. DS_APPEND = 62 , // Append one or more entries to a buffer. DS_ORDERED_COUNT = 63 , // Increment an append counter. Operation is done in order of wavefront creation. DS_ADD_U64 = 64 , // Uint add. DS_SUB_U64 = 65 , // Uint subtract. DS_RSUB_U64 = 66 , // Uint reverse subtract. DS_INC_U64 = 67 , // Uint increment. DS_DEC_U64 = 68 , // Uint decrement. DS_MIN_I64 = 69 , // Int min. DS_MAX_I64 = 70 , // Int max. DS_MIN_U64 = 71 , // Uint min. DS_MAX_U64 = 72 , // Uint max. DS_AND_B64 = 73 , // Dword AND. DS_OR_B64 = 74 , // Dword OR. DS_XOR_B64 = 75 , // Dword XOR. DS_MSKOR_B64 = 76 , // Masked Dword XOR. DS_WRITE_B64 = 77 , // Write. DS_WRITE2_B64 = 78 , // DS[ADDR+offset0*8] = D0;DS[ADDR+offset1*8] = D1; write 2 Dwords. DS_WRITE2ST64_B64 = 79 , // DS[ADDR+offset0*8*64] = D0; DS[ADDR+offset1*8*64] = D1; write 2 Dwords. DS_CMPST_B64 = 80 , // Compare store. DS_CMPST_F64 = 81 , // Compare store with float rules. DS_MIN_F64 = 82 , // DS[A] = (D0 < DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. DS_MAX_F64 = 83 , // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. DS_ADD_RTN_U64 = 96 , // Uint add. DS_SUB_RTN_U64 = 97 , // Uint subtract. DS_RSUB_RTN_U64 = 98 , // Uint reverse subtract. DS_INC_RTN_U64 = 99 , // Uint increment. DS_DEC_RTN_U64 = 100, // Uint decrement. DS_MIN_RTN_I64 = 101, // Int min. DS_MAX_RTN_I64 = 102, // Int max. DS_MIN_RTN_U64 = 103, // Uint min. DS_MAX_RTN_U64 = 104, // Uint max. DS_AND_RTN_B64 = 105, // Dword AND. DS_OR_RTN_B64 = 106, // Dword OR. DS_XOR_RTN_B64 = 107, // Dword XOR. DS_MSKOR_RTN_B64 = 108, // Masked Dword XOR. DS_WRXCHG_RTN_B64 = 109, // Write exchange. DS_WRXCHG2_RTN_B64 = 110, // Write exchange relative. DS_WRXCHG2ST64_RTN_B64 = 111, // Write echange 2 Dwords. DS_CMPST_RTN_B64 = 112, // Compare store. DS_CMPST_RTN_F64 = 113, // Compare store with float rules. DS_MIN_RTN_F64 = 114, // DS[A] = (D0 < DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. DS_MAX_RTN_F64 = 115, // DS[A] = (D0 > DS[A]) ? D0 : DS[A]; float, handles NaN/INF/denorm. DS_READ_B64 = 118, // Dword read. DS_READ2_B64 = 119, // R = DS[ADDR+offset0*8], R+1 = DS[ADDR+offset1*8]. Read 2 Dwords DS_READ2ST64_B64 = 120, // R = DS[ADDR+offset0*8*64], R+1 = DS[ADDR+offset1*8*64]. Read 2 Dwords. DS_CONDXCHG32_RTN_B64 = 126, // Conditional write exchange. SEA ISLANDS ONLY DS_ADD_SRC2_U32 = 128, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] + DS[B]; uint add. DS_SUB_SRC2_U32 = 129, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] - DS[B]; uint subtract. DS_RSUB_SRC2_U32 = 130, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[B]- DS[A]; uint reverse subtract. DS_INC_SRC2_U32 = 131, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = (DS[A] >= DS[B] ? 0 : DS[A] + 1); uint increment. DS_DEC_SRC2_U32 = 132, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = (DS[A]== 0 || DS[A] > DS[B] ? DS[B] : DS[A] - 1); uintdecrement. DS_MIN_SRC2_I32 = 133, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] =min(DS[A], DS[B]); int min. DS_MAX_SRC2_I32 = 134, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] =max(DS[A], DS[B]); int max. DS_MIN_SRC2_U32 = 135, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = min(DS[A], DS[B]); uint min. DS_MAX_SRC2_U32 = 136, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] =max(DS[A], DS[B]); uint maxw DS_AND_SRC2_B32 = 137, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A]& DS[B]; Dword AND. DS_OR_SRC2_B32 = 138, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] |DS[B]; Dword OR. DS_XOR_SRC2_B32 = 139, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = DS[A] ^DS[B]; Dword XOR. DS_WRITE_SRC2_B32 = 140, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = DS[B];write Dword. DS_MIN_SRC2_F32 = 146, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = (DS[B] < DS[A]) ? DS[B] : DS[A]; float, handles NaN/INF/denorm. DS_MAX_SRC2_F32 = 147, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} : {offset1[6],offset1[6:0],offset0}). DS[A] = (DS[B] > DS[A]) ? DS[B] : DS[A]; float, handles NaN/INF/denorm. DS_ADD_SRC2_U64 = 192, // Uint add. DS_SUB_SRC2_U64 = 193, // Uint subtract. DS_RSUB_SRC2_U64 = 194, // Uint reverse subtract. DS_INC_SRC2_U64 = 195, // Uint increment. DS_DEC_SRC2_U64 = 196, // Uint decrement. DS_MIN_SRC2_I64 = 197, // Int min. DS_MAX_SRC2_I64 = 198, // Int max. DS_MIN_SRC2_U64 = 199, // Uint min. DS_MAX_SRC2_U64 = 200, // Uint max. DS_AND_SRC2_B64 = 201, // Dword AND. DS_OR_SRC2_B64 = 202, // Dword OR. DS_XOR_SRC2_B64 = 203, // Dword XOR. DS_WRITE_SRC2_B64 = 204, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). DS[A] = DS[B]; write Qword. DS_MIN_SRC2_F64 = 210, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). [A] = (D0 < DS[A]) ? D0 : DS[A]; float, handlesNaN/INF/denorm. DS_MAX_SRC2_F64 = 211, // B = A + 4*(offset1[7] ? {A[31],A[31:17]} :{offset1[6],offset1[6:0],offset0}). [A] = (D0 > DS[A]) ? D0 : DS[A]; float, handlesNaN/INF/denorm. // SEA ISLANDS ONLY DS_WRITE_B96 = 222, //{DS[A+2], DS[A+1], DS[A]} = D0[95:0]; tri-dword write. DS_WRITE_B128 = 223, //{DS[A+3], DS[A+2], DS[A+1], DS[A]} = D0[127:0]; qword write. DS_CONDXCHG32_RTN_B128 = 253, //Conditional write exchange. DS_READ_B96 = 254, //Tri-Dword read. DS_READ_B128 = 255, //Qword read. // new for VI DS_PERMUTE_B32 , // : Forward permute. Does not write any LDS memory. LDS[dst] = src0 // returnVal = LDS[thread_id] Where thread_id is 0..63. DS_BPERMUTE_B32 , // : Backward permute. Does not actually write any LDS memory. LDS[thread_id] = src0 Where thread_id is 0..63. // returnVal = LDS[dst] DS_ADD_F32, //All other values are reserved. }; enum BufferInstructions { // Memory Buffer Instructions 12-39 // 2012 Advanced Micro Devices, Inc. All rights reserved. BUFFER_LOAD_FORMAT_X = 0 , // : Untyped buffer load 1 Dword with format conversion. BUFFER_LOAD_FORMAT_XY = 1 , // : Untyped buffer load 2 Dwords with format conversion. BUFFER_LOAD_FORMAT_XYZ = 2 , // : Untyped buffer load 3 Dwords with format conversion. BUFFER_LOAD_FORMAT_XYZW = 3 , // : Untyped buffer load 4 Dwords with format conversion. BUFFER_STORE_FORMAT_X = 4 , // : Untyped buffer store 1 Dword with format conversion. BUFFER_STORE_FORMAT_XY = 5 , // : Untyped buffer store 2 Dwords with format conversion. BUFFER_STORE_FORMAT_XYZ = 6 , // : Untyped buffer store 3 Dwords with format conversion. BUFFER_STORE_FORMAT_XYZW = 7 , // : Untyped buffer store 4 Dwords with format conversion. BUFFER_LOAD_UBYTE = 8 , // : Untyped buffer load unsigned byte. BUFFER_LOAD_SBYTE = 9 , // : Untyped buffer load signed byte. BUFFER_LOAD_USHORT = 10, // : Untyped buffer load unsigned short. BUFFER_LOAD_SSHORT = 11, // : Untyped buffer load signed short. BUFFER_LOAD_DWORD = 12, // : Untyped buffer load Dword. BUFFER_LOAD_DWORDX2 = 13, // : Untyped buffer load 2 Dwords. BUFFER_LOAD_DWORDX4 = 14, // : Untyped buffer load 4 Dwords. BUFFER_LOAD_DWORDX3 = 15, // : Untyped buffer load 3 Dwords. SEA ISLANDS //16 23 reserved. // BUFFER_STORE_BYTE = 24, // : Untyped buffer store byte. //25 reserved. BUFFER_STORE_SHORT = 26 , // : Untyped buffer store short. //27 reserved. BUFFER_STORE_DWORD = 28 , // : Untyped buffer store Dword. BUFFER_STORE_DWORDX2 = 29 , // : Untyped buffer store 2 Dwords. BUFFER_STORE_DWORDX4 = 30 , // : Untyped buffer store 4 Dwords. BUFFER_STORE_DWORDX3 = 31 , // : Untyped buffer store 3 Dwords. SEA ISLANDS //31 47 reserved. BUFFER_ATOMIC_SWAP = 48, // : 32b. dst=src, returns previous value if glc==1. BUFFER_ATOMIC_CMPSWAP = 49, // : 32b, dst = (dst==cmp) ? src : dst. Returns previous value if glc==1. src comes from the first data-vgpr, cmp from the second. BUFFER_ATOMIC_ADD = 50, // : 32b, dst += src. Returns previous value if glc==1. BUFFER_ATOMIC_SUB = 51, // : 32b, dst -= src. Returns previous value if glc==1. BUFFER_ATOMIC_RSUB = 52, // : 32b, dst = src-dst. Returns previous value if glc==1. SI ONLY BUFFER_ATOMIC_SMIN = 53, // : 32b, dst = (src < dst) ? src : dst (signed). Returns previous value if glc==1. BUFFER_ATOMIC_UMIN = 54, // : 32b, dst = (src < dst) ? src : dst (unsigned). Returns previous value if glc==1. BUFFER_ATOMIC_SMAX = 55, // : 32b, dst = (src > dst) ? src : dst (signed). Returns previousvalue if glc==1. BUFFER_ATOMIC_UMAX = 56, // : 32b, dst = (src > dst) ? src : dst (unsigned). Returns previous value if glc==1. BUFFER_ATOMIC_AND = 57, // : 32b, dst &= src. Returns previous value if glc==1. BUFFER_ATOMIC_OR = 58, // : 32b, dst |= src. Returns previous value if glc==1. BUFFER_ATOMIC_XOR = 59, // : 32b, dst ^= src. Returns previous value if glc==1. BUFFER_ATOMIC_INC = 60, // : 32b, dst = (dst >= src) ? 0 : dst+1. Returns previous value if glc==1. BUFFER_ATOMIC_DEC = 61, // : 32b, dst = ((dst==0 || (dst > src)) ? src : dst-1. Returns previous value if glc==1. BUFFER_ATOMIC_FCMPSWAP = 62, // : 32b , dst = (dst == cmp) ? src : dst, returns previous value if glc==1. Float compare swap (handles NaN/INF/denorm). srccomes from the first data-vgpr; cmp from the second. BUFFER_ATOMIC_FMIN = 63, // : 32b , dst = (src < dst) ? src : dst,. Returns previousvalue if glc==1. float, handles NaN/INF/denorm. BUFFER_ATOMIC_FMAX = 64, // : 32b , dst = (src > dst) ? src : dst, returns previous valueif glc==1. float, handles NaN/INF/denorm. // 65 79 reserved. BUFFER_ATOMIC_SWAP_X2 = 80, // : 64b. dst=src, returns previous value if glc==1. BUFFER_ATOMIC_CMPSWAP_X2 = 81, // : 64b, dst = (dst==cmp) ? src : dst. Returns previous value if glc==1. src comes from the first two data-vgprs, cmp from the second two. BUFFER_ATOMIC_ADD_X2 = 82, // : 64b, dst += src. Returns previous value if glc==1. BUFFER_ATOMIC_SUB_X2 = 83, // : 64b, dst -= src. Returns previous value if glc==1. BUFFER_ATOMIC_RSUB_X2 = 84, // : 64b, dst = src-dst. Returns previous value if glc==1. SI ONLY BUFFER_ATOMIC_SMIN_X2 = 85, // : 64b, dst = (src < dst) ? src : dst (signed). Returnsprevious value if glc==1. BUFFER_ATOMIC_UMIN_X2 = 86, // : 64b, dst = (src < dst) ? src : dst (unsigned).Returns previous value if glc==1. BUFFER_ATOMIC_SMAX_X2 = 87, // : 64b, dst = (src > dst) ? src : dst (signed). Returnsprevious value if glc==1. BUFFER_ATOMIC_UMAX_X2 = 88, // : 64b, dst = (src > dst) ? src : dst (unsigned). Returns previous value if glc==1. // NOTE: BUFFER_ATOMIC_RSUB(53) and RSUB_X2(84) is SI only BUFFER_ATOMIC_AND_X2 = 89 , // : 64b, dst &= src. Returns previous value if glc==1. BUFFER_ATOMIC_OR_X2 = 90 , // : 64b, dst |= src. Returns previous value if glc==1. BUFFER_ATOMIC_XOR_X2 = 91 , // : 64b, dst ^= src. Returns previous value if glc==1. BUFFER_ATOMIC_INC_X2 = 92 , // : 64b, dst = (dst >= src) ? 0 : dst+1. Returns previous value if glc==1. BUFFER_ATOMIC_DEC_X2 = 93 , // : 64b, dst = ((dst==0 || (dst > src)) ? src : dst-1. Returns previous value if glc==1. BUFFER_ATOMIC_FCMPSWAP_X2 = 94 , // : 64b , dst = (dst == cmp) ? src : dst, returns previous value if glc==1. Double compare swap (handles NaN/INF/denorm). src comes from the first two data-vgprs, cmp from the second two. BUFFER_ATOMIC_FMIN_X2 = 95 , // : 64b , dst = (src < dst) ? src : dst, returns previous value if glc==1. Double, handles NaN/INF/denorm. BUFFER_ATOMIC_FMAX_X2 = 96 , // : 64b , dst = (src > dst) ? src : dst, returns previous value if glc==1. Double, handles NaN/INF/denorm. //97 111 reserved. BUFFER_WBINVL1_SC = 112 , // : write back and invalidate the shader L1 only for lines of MTYPE SC and GC. Always returns ACK to shader. BUFFER_WBINVL1 = 113 , // : write back and invalidate the shader L1. Always returns ACK to shader. // new for VI BUFFER_WBINVL1_VOL , //: Write back and invalidate the shader L1 only for lines that are marked volatile. Always returns ACK to shader. BUFFER_STORE_LDS_DWORD , //: Store one Dword from LDS memory to system memory without using VGPRs. BUFFER_LOAD_FORMAT_D16_X ,//: Untyped buffer load 1 dword with format conversion. BUFFER_LOAD_FORMAT_D16_XY ,//: Untyped buffer load 2 dwords with format conversion. BUFFER_LOAD_FORMAT_D16_XYZ ,//: Untyped buffer load 3 dwords with format conversion. BUFFER_LOAD_FORMAT_D16_XYZW ,//: Untyped buffer load 4 dwords with format conversion. BUFFER_STORE_FORMAT_D16_X ,//: Untyped buffer store 1 dword with format conversion. BUFFER_STORE_FORMAT_D16_XY ,//: Untyped buffer store 2 dwords with format conversion. BUFFER_STORE_FORMAT_D16_XYZ ,//: Untyped buffer store 3 dwords with format conversion. BUFFER_STORE_FORMAT_D16_XYZW ,//: Untyped buffer store 4 dwords with format conversion. TBUFFER_LOAD_FORMAT_X , // : Untyped buffer load 1 Dword with format conversion. TBUFFER_LOAD_FORMAT_XY , // : Untyped buffer load 2 Dwords with format conversion. TBUFFER_LOAD_FORMAT_XYZ , // : Untyped buffer load 3 Dwords with format conversion. TBUFFER_LOAD_FORMAT_XYZW , // : Untyped buffer load 4 Dwords with format conversion. TBUFFER_STORE_FORMAT_X , // : Untyped buffer store 1 Dword with format conversion. TBUFFER_STORE_FORMAT_XY , // : Untyped buffer store 2 Dwords with format conversion. TBUFFER_STORE_FORMAT_XYZ , // : Untyped buffer store 3 Dwords with format conversion. TBUFFER_STORE_FORMAT_XYZW , // : Untyped buffer store 4 Dwords with format conversion. TBUFFER_LOAD_FORMAT_D16_X ,// : Typed buffer load 1 dword with format conversion. TBUFFER_LOAD_FORMAT_D16_XY ,// : Typed buffer load 2 dwords with format conversion. TBUFFER_LOAD_FORMAT_D16_XYZ ,// : Typed buffer load 3 dwords with format conversion. TBUFFER_LOAD_FORMAT_D16_XYZW ,// : Typed buffer load 4 dwords with format conversion. TBUFFER_STORE_FORMAT_D16_X ,// : Typed buffer store 1 dword with format conversion. TBUFFER_STORE_FORMAT_D16_XY ,// : Typed buffer store 2 dwords with format conversion. TBUFFER_STORE_FORMAT_D16_XYZ ,// : Typed buffer store 3 dwords with format conversion. TBUFFER_STORE_FORMAT_D16_XYZW ,// : Typed buffer store 4 dwords with format conversion. TBUFFER_INVALID = 0xffffffff, BUFFER_INVALID = 0xffffffff }; enum TBufferNumberFormats { NF_UNORM , NF_SNORM , NF_USCALED , NF_SSCALED , NF_UINT , NF_SINT , NF_SNORM_NZ , NF_FLOAT , //8 reserved NF_SRGB =9, NF_UBNORM , NF_UBNORM_NZ , NF_UBINT , NF_UBSCALED , NF_INVALID = 0xfffffff }; enum TBufferDataFormats { DF_INVALID=0, DF_8, DF_16, DF_8_8, DF_32, DF_16_16, DF_10_11_11, DF_11_11_10, DF_10_10_10_2, DF_2_10_10_10, DF_8_8_8_8, DF_32_32, DF_16_16_16_16, DF_32_32_32, DF_32_32_32_32, }; enum ImageInstructions { IMAGE_LOAD , // Image memory load with format conversion specified in T#. No sampler. IMAGE_LOAD_MIP , // Image memory load with user-supplied mip level. No sampler. IMAGE_LOAD_PCK , // Image memory load with no format conversion. No sampler. IMAGE_LOAD_PCK_SGN , // Image memory load with with no format conversion and sign extension. No sampler. IMAGE_LOAD_MIP_PCK , // Image memory load with user-supplied mip level, no format conversion. No sampler. IMAGE_LOAD_MIP_PCK_SGN , // Image memory load with user-supplied mip level, no format conversion and with sign extension. No sampler. //6 7 reserved. IMAGE_STORE , //: Image memory store with format conversion specified in T#. No sampler. IMAGE_STORE_MIP , //: Image memory store with format conversion specified in T# to user specified mip level. No sampler. IMAGE_STORE_PCK , //: Image memory store of packed data without format conversion. No sampler. IMAGE_STORE_MIP_PCK , //: Image memory store of packed data without format conversion to user-supplied mip level. No sampler. //12 13 reserved. IMAGE_GET_RESINFO , //: return resource info. No sampler. IMAGE_ATOMIC_SWAP , //: dst=src, returns previous value if glc==1. IMAGE_ATOMIC_CMPSWAP , //: dst = (dst==cmp) ? src : dst. Returns previous value if glc==1. IMAGE_ATOMIC_ADD , //: dst += src. Returns previous value if glc==1. IMAGE_ATOMIC_SUB , //: dst -= src. Returns previous value if glc==1. IMAGE_ATOMIC_RSUB , //: dst = src-dst. Returns previous value if glc==1. SI ONLY IMAGE_ATOMIC_SMIN , //: dst = (src < dst) ? src : dst (signed). Returns previous value if glc==1. IMAGE_ATOMIC_UMIN , //: dst = (src < dst) ? src : dst (unsigned). Returns previous value if glc==1. IMAGE_ATOMIC_SMAX , //: dst = (src > dst) ? src : dst (signed). Returns previous value if glc==1. IMAGE_ATOMIC_UMAX , //: dst = (src > dst) ? src : dst (unsigned). Returns previous value if glc==1. IMAGE_ATOMIC_AND , //: dst &= src. Returns previous value if glc==1. IMAGE_ATOMIC_OR , //: dst |= src. Returns previous value if glc==1. IMAGE_ATOMIC_XOR , //: dst ^= src. Returns previous value if glc==1. IMAGE_ATOMIC_INC , //: dst = (dst >= src) ? 0 : dst+1. Returns previous value if glc==1. IMAGE_ATOMIC_DEC , //: dst = ((dst==0 || (dst > src)) ? src : dst-1. Returns previous value if glc==1. IMAGE_ATOMIC_FCMPSWAP , //: dst = (dst == cmp) ? src : dst, returns previous value of dst if glc==1 - double and float atomic compare swap. Obeys floating point compare rules for special values. IMAGE_ATOMIC_FMIN , //: dst = (src < dst) ? src : dst, returns previous value of dst if glc==1 - double and float atomic min (handles NaN/INF/denorm). IMAGE_ATOMIC_FMAX , //: dst = (src > dst) ? src : dst, returns previous value of dst if glc==1 - double and float atomic min (handles NaN/INF/denorm). IMAGE_SAMPLE , //: sample texture map. IMAGE_SAMPLE_CL , //: sample texture map, with LOD clamp specified in shader. IMAGE_SAMPLE_D , //: sample texture map, with user derivatives. IMAGE_SAMPLE_D_CL , //: sample texture map, with LOD clamp specified in shader, with user derivatives. IMAGE_SAMPLE_L , //: sample texture map, with user LOD. IMAGE_SAMPLE_B , //: sample texture map, with lod bias. IMAGE_SAMPLE_B_CL , //: sample texture map, with LOD clamp specified in shader, with lod bias. IMAGE_SAMPLE_LZ , //: sample texture map, from level 0. IMAGE_SAMPLE_C , //: sample texture map, with PCF. IMAGE_SAMPLE_C_CL , //: SAMPLE_C, with LOD clamp specified in shader. IMAGE_SAMPLE_C_D , //: SAMPLE_C, with user derivatives. IMAGE_SAMPLE_C_D_CL , //: SAMPLE_C, with LOD clamp specified in shader,with user derivatives. IMAGE_SAMPLE_C_L , //: SAMPLE_C, with user LOD. IMAGE_SAMPLE_C_B , //: SAMPLE_C, with lod bias. IMAGE_SAMPLE_C_B_CL , //: SAMPLE_C, with LOD clamp specified in shader, with lod bias. IMAGE_SAMPLE_C_LZ , // : SAMPLE_C, from level 0. IMAGE_SAMPLE_O , // : sample texture map, with user offsets. IMAGE_SAMPLE_CL_O , // : SAMPLE_O with LOD clamp specified in shader. IMAGE_SAMPLE_D_O , // : SAMPLE_O, with user derivatives. IMAGE_SAMPLE_D_CL_O , // : SAMPLE_O, with LOD clamp specified in shader,with user derivatives. IMAGE_SAMPLE_L_O , // : SAMPLE_O, with user LOD. IMAGE_SAMPLE_B_O , // : SAMPLE_O, with lod bias. IMAGE_SAMPLE_B_CL_O , // : SAMPLE_O, with LOD clamp specified in shader,with lod bias. IMAGE_SAMPLE_LZ_O , // : SAMPLE_O, from level 0. IMAGE_SAMPLE_C_O , // : SAMPLE_C with user specified offsets. IMAGE_SAMPLE_C_CL_O , // : SAMPLE_C_O, with LOD clamp specified in shader. IMAGE_SAMPLE_C_D_O , // : SAMPLE_C_O, with user derivatives. IMAGE_SAMPLE_C_D_CL_O , // : SAMPLE_C_O, with LOD clamp specified in shader, with user derivatives. IMAGE_SAMPLE_C_L_O , // : SAMPLE_C_O, with user LOD. IMAGE_SAMPLE_C_B_O , // : SAMPLE_C_O, with lod bias. IMAGE_SAMPLE_C_B_CL_O , // : SAMPLE_C_O, with LOD clamp specified in shader, with lod bias. IMAGE_SAMPLE_C_LZ_O , // : SAMPLE_C_O, from level 0. IMAGE_GATHER4 , // : gather 4 single component elements (2x2). IMAGE_GATHER4_CL , // : gather 4 single component elements (2x2) with user LOD clamp. IMAGE_GATHER4_L , // : gather 4 single component elements (2x2) with user LOD. IMAGE_GATHER4_B , // : gather 4 single component elements (2x2) with user bias. IMAGE_GATHER4_B_CL , // : gather 4 single component elements (2x2) with user bias and clamp. IMAGE_GATHER4_LZ , // : gather 4 single component elements (2x2) at level 0. IMAGE_GATHER4_C , // : gather 4 single component elements (2x2) with PCF. IMAGE_GATHER4_C_CL , // : gather 4 single component elements (2x2) with user LOD clamp and PCF. //72 75 reserved. // IMAGE_GATHER4_C_L , // : gather 4 single component elements (2x2) with user LOD and PCF. IMAGE_GATHER4_C_B , // : gather 4 single component elements (2x2) with user bias and PCF. IMAGE_GATHER4_C_B_CL , // : gather 4 single component elements (2x2) with user bias, clamp and PCF. IMAGE_GATHER4_C_LZ , // : gather 4 single component elements (2x2) at level 0, with PCF. IMAGE_GATHER4_O , // : GATHER4, with user offsets. IMAGE_GATHER4_CL_O , // : GATHER4_CL, with user offsets. //82 83 reserved. // IMAGE_GATHER4_L_O , // : GATHER4_L, with user offsets. IMAGE_GATHER4_B_O , // : GATHER4_B, with user offsets. IMAGE_GATHER4_B_CL_O , // : GATHER4_B_CL, with user offsets. IMAGE_GATHER4_LZ_O , // : GATHER4_LZ, with user offsets. IMAGE_GATHER4_C_O , // : GATHER4_C, with user offsets. IMAGE_GATHER4_C_CL_O , // : GATHER4_C_CL, with user offsets. //90 91 reserved. // IMAGE_GATHER4_C_L_O , // : GATHER4_C_L, with user offsets. IMAGE_GATHER4_C_B_O , // : GATHER4_B, with user offsets. IMAGE_GATHER4_C_B_CL_O, // : GATHER4_B_CL, with user offsets. IMAGE_GATHER4_C_LZ_O , // : GATHER4_C_LZ, with user offsets. IMAGE_GET_LOD , // : Return calculated LOD. //97 103 reserved. // IMAGE_SAMPLE_CD , // : sample texture map, with user derivatives (LOD per quad) IMAGE_SAMPLE_CD_CL , // : sample texture map, with LOD clamp specified in shader, with user derivatives (LOD per quad). IMAGE_SAMPLE_C_CD , // : SAMPLE_C, with user derivatives (LOD per quad). IMAGE_SAMPLE_C_CD_CL , // : SAMPLE_C, with LOD clamp specified in shader, with user derivatives (LOD per quad). IMAGE_SAMPLE_CD_O , // : SAMPLE_O, with user derivatives (LOD per quad). IMAGE_SAMPLE_CD_CL_O , // : SAMPLE_O, with LOD clamp specified in shader, with user derivatives (LOD per quad). IMAGE_SAMPLE_C_CD_O , // : SAMPLE_C_O, with user derivatives (LOD per quad). IMAGE_SAMPLE_C_CD_CL_O , // : SAMPLE_C_O, with LOD clamp specified in shader, with user derivatives (LOD per quad). IMAGE_INVALID = 0xffffffff // All other values are reserved. }; enum FlatInstructions // Flat opcode family is SEA ISLANDS ONLY (and above) { //0 - 7 reserved. FLAT_LOAD_UBYTE = 8, //: Flat load unsigned byte. Zero extend to VGPR destination. FLAT_LOAD_SBYTE = 9, //: Flat load signed byte. Sign extend to VGPR destination. FLAT_LOAD_USHORT = 10, //: Flat load unsigned short. Zero extend to VGPR destination. FLAT_LOAD_SSHORT = 11, //: Flat load signed short. Sign extend to VGPR destination. FLAT_LOAD_DWORD = 12, //: Flat load Dword. FLAT_LOAD_DWORDX2 = 13, //: Flat load 2 Dwords. FLAT_LOAD_DWORDX4 = 14, //: Flat load 4 Dwords. FLAT_LOAD_DWORDX3 = 15, //: Flat load 3 Dwords. //16 - 23 reserved. // FLAT_STORE_BYTE = 24, //: Flat store byte. //25reserved. // FLAT_STORE_SHORT = 26, //: Flat store short. //27reserved. // FLAT_STORE_DWORD = 28, //: Flat store Dword. FLAT_STORE_DWORDX2 = 29, //: Flat store 2 Dwords. FLAT_STORE_DWORDX4 = 30, //: Flat store 4 Dwords. FLAT_STORE_DWORDX3 = 31, //: Flat store 3 Dwords. //32 47 reserved. // FLAT_ATOMIC_SWAP = 48, //: 32b. dst=src, returns previous value if rtn==1. FLAT_ATOMIC_CMPSWAP = 49, //: 32b, dst = (dst==cmp) ? src : dst. Returns previous value if rtn==1. src comes from the first data-VGPR, cmp from the second. FLAT_ATOMIC_ADD = 50, //: 32b, dst += src. Returns previous value if rtn==1. FLAT_ATOMIC_SUB = 51, //: 32b, dst -= src. Returns previous value if rtn==1. //52reserved. // FLAT_ATOMIC_SMIN = 53, //: 32b, dst = (src < dst) ? src : dst (signed comparison). Returns previous value if rtn==1. FLAT_ATOMIC_UMIN = 54, //: 32b, dst = (src < dst) ? src : dst (unsigned comparison). Returns previous value if rtn==1. FLAT_ATOMIC_SMAX = 55, //: 32b, dst = (src > dst) ? src : dst (signed comparison). Returns previous value if rtn==1. // FLAT_ATOMIC_UMAX = 56, //: 32b, dst = (src > dst) ? src : dst (unsigned comparison). Returns previous value if rtn==1. FLAT_ATOMIC_AND = 57, //: 32b, dst &= src. Returns previous value if rtn==1. FLAT_ATOMIC_OR = 58, //: 32b, dst |= src. Returns previous value if rtn==1. FLAT_ATOMIC_XOR = 59, //: 32b, dst ^= src. Returns previous value if rtn==1. FLAT_ATOMIC_INC = 60, //: 32b, dst = (dst >= src) ? 0 : dst+1 (unsigned comparison). Returns previous value if rtn==1. FLAT_ATOMIC_DEC = 61, //: 32b, dst = ((dst==0 || (dst > src)) ? src : dst-1 (unsigned comparison). Returns previous value if rtn==1. FLAT_ATOMIC_FCMPSWAP = 62, //: 32b , dst = (dst == cmp) ? src : dst, returns previous value if rtn==1. Floating point compare-swap handles NaN/INF/denorm. src comes from the first data-VGPR; cmp from the second. FLAT_ATOMIC_FMIN = 63, //: 32b , dst = (src < dst) ? src : dst. Returns previous value if rtn==1. float, handles NaN/INF/denorm. FLAT_ATOMIC_FMAX = 64, //: 32b , dst = (src > dst) ? src : dst, returns previous value if rtn==1. Floating point compare handles NaN/INF/denorm. //65 79 reserved. // FLAT_ATOMIC_SWAP_X2 = 80, //: 64b. dst=src, returns previous value if rtn==1. FLAT_ATOMIC_CMPSWAP_X2 = 81, //: 64b, dst = (dst==cmp) ? src : dst. Returns previous value if rtn==1. src comes from the first two data-VGPRs, cmp from the second two. FLAT_ATOMIC_ADD_X2 = 82, //: 64b, dst += src. Returns previous value if rtn==1. FLAT_ATOMIC_SUB_X2 = 83, //: 64b, dst -= src. Returns previous value if rtn==1. //84reserved. // FLAT_ATOMIC_SMIN_X2 = 85, //: 64b, dst = (src < dst) ? src : dst (signed comparison). Returns previous value if rtn==1. FLAT_ATOMIC_UMIN_X2 = 86, //: 64b, dst = (src < dst) ? src : dst (unsigned comparison). Returns previous value if rtn==1. FLAT_ATOMIC_SMAX_X2 = 87, //: 64b, dst = (src > dst) ? src : dst (signed comparison). Returns previous value if rtn==1. FLAT_ATOMIC_UMAX_X2 = 88, //: 64b, dst = (src > dst) ? src : dst (unsigned comparison). Returns previous value if rtn==1. FLAT_ATOMIC_AND_X2 = 89, //: 64b, dst &= src. Returns previous value if rtn==1. FLAT_ATOMIC_OR_X2 = 90, //: 64b, dst |= src. Returns previous value if rtn==1. FLAT_ATOMIC_XOR_X2 = 91, //: 64b, dst ^= src. Returns previous value if rtn==1. FLAT_ATOMIC_INC_X2 = 92, //: 64b, dst = (dst >= src) ? 0 : dst+1. Returns previous value if rtn==1. FLAT_ATOMIC_DEC_X2 = 93, //: 64b, dst = ((dst==0 || (dst > src)) ? src : dst - 1. Returns previous value if rtn==1. FLAT_ATOMIC_FCMPSWAP_X2 = 94, //: 64b , dst = (dst == cmp) ? src : dst, returns previous value if rtn==1. Double compare swap (handles NaN/INF/denorm). src comes from the first two data-VGPRs, cmp from the second two. FLAT_ATOMIC_FMIN_X2 = 95, //: 64b , dst = (src < dst) ? src : dst, returns previous value if rtn==1. Double, handles NaN/INF/denorm. FLAT_ATOMIC_FMAX_X2 = 96, //: 64b , dst = (src > dst) ? src : dst, returns previous value if rtn==1. Double, handles NaN/INF/denorm. //All other values are reserved. }; enum ExportTargets { EXP_MRT0 = 0, EXP_MRT1 = 1, EXP_MRT2 = 2, EXP_MRT3 = 3, EXP_MRT4 = 4, EXP_MRT5 = 5, EXP_MRT6 = 6, EXP_MRT7 = 7, EXP_Z = 8, EXP_NULL = 9, EXP_POS0 = 12, EXP_POS1 = 13, EXP_POS2 = 14, EXP_POS3 = 15, EXP_PARAM0 = 32, EXP_PARAM1, EXP_PARAM2, EXP_PARAM3, EXP_PARAM4, EXP_PARAM5, EXP_PARAM6, EXP_PARAM7, EXP_PARAM8, EXP_PARAM9, EXP_PARAM10, EXP_PARAM11, EXP_PARAM12, EXP_PARAM13, EXP_PARAM14, EXP_PARAM15, EXP_PARAM16, EXP_PARAM17, EXP_PARAM18, EXP_PARAM19, EXP_PARAM20, EXP_PARAM21, EXP_PARAM22, EXP_PARAM23, EXP_PARAM24, EXP_PARAM25, EXP_PARAM26, EXP_PARAM27, EXP_PARAM28, EXP_PARAM29, EXP_PARAM30, EXP_PARAM31, EXP_INVALID = 0xffffffff }; const char* EnumToString(ScalarInstructions); const char* EnumToString(ScalarMemoryInstructions); const char* EnumToString(VectorInstructions); const char* EnumToString(DSInstructions); const char* EnumToString(BufferInstructions); const char* EnumToString(ImageInstructions); const char* EnumToString(FlatInstructions); const char* EnumToString(ExportTargets); const char* EnumToString(TBufferNumberFormats); const char* EnumToString(TBufferDataFormats); } #endif ================================================ FILE: src/Wrapper/GCNIsa.cpp ================================================ #pragma unmanaged #include "GCNIsa.h" namespace GCN { uint GetSourceCountForInstruction( VectorInstructions eOp ) { switch( eOp ) { default: return 0; case V_MAD_F16 : case V_MAD_U16 : case V_MAD_I16 : case V_PERM_B32 : case V_FMA_F16 : case V_DIV_FIXUP_F16 : return 3; case V_CVT_F16_U16 : case V_CVT_F16_I16 : case V_CVT_U16_F16 : case V_CVT_I16_F16 : case V_RCP_F16 : case V_SQRT_F16 : case V_RSQ_F16 : case V_LOG_F16 : case V_EXP_F16 : case V_FREXP_MANT_F16 : case V_FREXP_EXP_I16_F16 : case V_FLOOR_F16 : case V_CEIL_F16 : case V_TRUNC_F16 : case V_RNDNE_F16 : case V_FRACT_F16 : case V_SIN_F16 : case V_COS_F16 : return 1; case V_ADD_U32: case V_SUB_U32: case V_SUBREV_U32: case V_LSHLREV_B64: case V_LSHRREV_B64: case V_ASHRREV_I64: case V_ADD_F16 : case V_SUB_F16 : case V_SUBREV_F16 : case V_MUL_F16 : case V_MAC_F16 : case V_MADMK_F16 : case V_MADAK_F16 : case V_ADD_U16 : case V_SUB_U16 : case V_SUBREV_U16 : case V_MUL_LO_U16 : case V_LSHLREV_B16 : case V_LSHRREV_B16 : case V_ASHRREV_I16 : case V_MAX_F16 : case V_MIN_F16 : case V_MAX_U16 : case V_MAX_I16 : case V_MIN_U16 : case V_MIN_I16 : case V_LDEXP_F16 : case V_CNDMASK_B32 : case V_READLANE_B32 : case V_WRITELANE_B32 : case V_ADD_F32 : case V_SUB_F32 : case V_SUBREV_F32 : case V_MAC_LEGACY_F32 : case V_MUL_LEGACY_F32 : case V_MUL_F32 : case V_MUL_I32_I24 : case V_MUL_HI_I32_I24 : case V_MUL_U32_U24 : case V_MUL_HI_U32_U24 : case V_MIN_LEGACY_F32 : case V_MAX_LEGACY_F32 : case V_MIN_F32 : case V_MAX_F32 : case V_MIN_I32 : case V_MAX_I32 : case V_MIN_U32 : case V_MAX_U32 : case V_LSHR_B32 : case V_LSHRREV_B32 : case V_ASHR_I32 : case V_ASHRREV_I32 : case V_LSHL_B32 : case V_LSHLREV_B32 : case V_AND_B32 : case V_OR_B32 : case V_XOR_B32 : case V_BFM_B32 : case V_MAC_F32 : case V_MADMK_F32 : case V_MADAK_F32 : case V_BCNT_U32_B32 : case V_MBCNT_LO_U32_B32 : case V_MBCNT_HI_U32_B32 : case V_ADD_I32 : case V_SUB_I32 : case V_SUBREV_I32 : case V_ADDC_U32 : case V_SUBB_U32 : case V_SUBBREV_U32 : case V_LDEXP_F32 : case V_CVT_PKACCUM_U8_F32 : case V_CVT_PKNORM_I16_F32 : case V_CVT_PKNORM_U16_F32 : case V_CVT_PKRTZ_F16_F32 : case V_CVT_PK_U16_U32 : case V_CVT_PK_I16_I32 : case V_CMP_F_F32 : case V_CMP_LT_F32 : case V_CMP_EQ_F32 : case V_CMP_LE_F32 : case V_CMP_GT_F32 : case V_CMP_LG_F32 : case V_CMP_GE_F32 : case V_CMP_O_F32 : case V_CMP_U_F32 : case V_CMP_NGE_F32 : case V_CMP_NLG_F32 : case V_CMP_NGT_F32 : case V_CMP_NLE_F32 : case V_CMP_NEQ_F32 : case V_CMP_NLT_F32 : case V_CMP_TRU_F32 : case V_CMPX_F_F32 : case V_CMPX_LT_F32 : case V_CMPX_EQ_F32 : case V_CMPX_LE_F32 : case V_CMPX_GT_F32 : case V_CMPX_LG_F32 : case V_CMPX_GE_F32 : case V_CMPX_O_F32 : case V_CMPX_U_F32 : case V_CMPX_NGE_F32 : case V_CMPX_NLG_F32 : case V_CMPX_NGT_F32 : case V_CMPX_NLE_F32 : case V_CMPX_NEQ_F32 : case V_CMPX_NLT_F32 : case V_CMPX_TRU_F32 : case V_CMP_F_F64 : case V_CMP_LT_F64 : case V_CMP_EQ_F64 : case V_CMP_LE_F64 : case V_CMP_GT_F64 : case V_CMP_LG_F64 : case V_CMP_GE_F64 : case V_CMP_O_F64 : case V_CMP_U_F64 : case V_CMP_NGE_F64 : case V_CMP_NLG_F64 : case V_CMP_NGT_F64 : case V_CMP_NLE_F64 : case V_CMP_NEQ_F64 : case V_CMP_NLT_F64 : case V_CMP_TRU_F64 : case V_CMPX_F_F64 : case V_CMPX_LT_F64 : case V_CMPX_EQ_F64 : case V_CMPX_LE_F64 : case V_CMPX_GT_F64 : case V_CMPX_LG_F64 : case V_CMPX_GE_F64 : case V_CMPX_O_F64 : case V_CMPX_U_F64 : case V_CMPX_NGE_F64 : case V_CMPX_NLG_F64 : case V_CMPX_NGT_F64 : case V_CMPX_NLE_F64 : case V_CMPX_NEQ_F64 : case V_CMPX_NLT_F64 : case V_CMPX_TRU_F64 : case V_CMPS_F_F32 : case V_CMPS_LT_F32 : case V_CMPS_EQ_F32 : case V_CMPS_LE_F32 : case V_CMPS_GT_F32 : case V_CMPS_LG_F32 : case V_CMPS_GE_F32 : case V_CMPS_O_F32 : case V_CMPS_U_F32 : case V_CMPS_NGE_F32 : case V_CMPS_NLG_F32 : case V_CMPS_NGT_F32 : case V_CMPS_NLE_F32 : case V_CMPS_NEQ_F32 : case V_CMPS_NLT_F32 : case V_CMPS_TRU_F32 : case V_CMPSX_F_F32 : case V_CMPSX_LT_F32 : case V_CMPSX_EQ_F32 : case V_CMPSX_LE_F32 : case V_CMPSX_GT_F32 : case V_CMPSX_LG_F32 : case V_CMPSX_GE_F32 : case V_CMPSX_O_F32 : case V_CMPSX_U_F32 : case V_CMPSX_NGE_F32 : case V_CMPSX_NLG_F32 : case V_CMPSX_NGT_F32 : case V_CMPSX_NLE_F32 : case V_CMPSX_NEQ_F32 : case V_CMPSX_NLT_F32 : case V_CMPSX_TRU_F32 : case V_CMPS_F_F64 : case V_CMPS_LT_F64 : case V_CMPS_EQ_F64 : case V_CMPS_LE_F64 : case V_CMPS_GT_F64 : case V_CMPS_LG_F64 : case V_CMPS_GE_F64 : case V_CMPS_O_F64 : case V_CMPS_U_F64 : case V_CMPS_NGE_F64 : case V_CMPS_NLG_F64 : case V_CMPS_NGT_F64 : case V_CMPS_NLE_F64 : case V_CMPS_NEQ_F64 : case V_CMPS_NLT_F64 : case V_CMPS_TRU_F64 : case V_CMPSX_F_F64 : case V_CMPSX_LT_F64 : case V_CMPSX_EQ_F64 : case V_CMPSX_LE_F64 : case V_CMPSX_GT_F64 : case V_CMPSX_LG_F64 : case V_CMPSX_GE_F64 : case V_CMPSX_O_F64 : case V_CMPSX_U_F64 : case V_CMPSX_NGE_F64 : case V_CMPSX_NLG_F64 : case V_CMPSX_NGT_F64 : case V_CMPSX_NLE_F64 : case V_CMPSX_NEQ_F64 : case V_CMPSX_NLT_F64 : case V_CMPSX_TRU_F64 : case V_CMP_F_I32 : case V_CMP_LT_I32 : case V_CMP_EQ_I32 : case V_CMP_LE_I32 : case V_CMP_GT_I32 : case V_CMP_LG_I32 : case V_CMP_GE_I32 : case V_CMP_TRU_I32 : case V_CMPX_F_I32 : case V_CMPX_LT_I32 : case V_CMPX_EQ_I32 : case V_CMPX_LE_I32 : case V_CMPX_GT_I32 : case V_CMPX_LG_I32 : case V_CMPX_GE_I32 : case V_CMPX_TRU_I32 : case V_CMP_F_I64 : case V_CMP_LT_I64 : case V_CMP_EQ_I64 : case V_CMP_LE_I64 : case V_CMP_GT_I64 : case V_CMP_LG_I64 : case V_CMP_GE_I64 : case V_CMP_TRU_I64 : case V_CMPX_F_I64 : case V_CMPX_LT_I64 : case V_CMPX_EQ_I64 : case V_CMPX_LE_I64 : case V_CMPX_GT_I64 : case V_CMPX_LG_I64 : case V_CMPX_GE_I64 : case V_CMPX_TRU_I64 : case V_CMP_F_U32 : case V_CMP_LT_U32 : case V_CMP_EQ_U32 : case V_CMP_LE_U32 : case V_CMP_GT_U32 : case V_CMP_LG_U32 : case V_CMP_GE_U32 : case V_CMP_TRU_U32 : case V_CMPX_F_U32 : case V_CMPX_LT_U32 : case V_CMPX_EQ_U32 : case V_CMPX_LE_U32 : case V_CMPX_GT_U32 : case V_CMPX_LG_U32 : case V_CMPX_GE_U32 : case V_CMPX_TRU_U32 : case V_CMP_F_U64 : case V_CMP_LT_U64 : case V_CMP_EQ_U64 : case V_CMP_LE_U64 : case V_CMP_GT_U64 : case V_CMP_LG_U64 : case V_CMP_GE_U64 : case V_CMP_TRU_U64 : case V_CMPx_F_U64 : case V_CMPx_LT_U64 : case V_CMPx_EQ_U64 : case V_CMPx_LE_U64 : case V_CMPx_GT_U64 : case V_CMPx_LG_U64 : case V_CMPx_GE_U64 : case V_CMPx_TRU_U64 : case V_CMP_CLASS_F32 : case V_CMPX_CLASS_F32 : case V_CMP_CLASS_F64 : case V_CMPX_CLASS_F64 : case V_CMP_F_F16 : case V_CMP_LT_F16 : case V_CMP_EQ_F16 : case V_CMP_LE_F16 : case V_CMP_GT_F16 : case V_CMP_LG_F16 : case V_CMP_GE_F16 : case V_CMP_O_F16 : case V_CMP_U_F16 : case V_CMP_NGE_F16 : case V_CMP_NLG_F16 : case V_CMP_NGT_F16 : case V_CMP_NLE_F16 : case V_CMP_NEQ_F16 : case V_CMP_NLT_F16 : case V_CMP_TRU_F16 : case V_CMPX_F_F16 : case V_CMPX_LT_F16 : case V_CMPX_EQ_F16 : case V_CMPX_LE_F16 : case V_CMPX_GT_F16 : case V_CMPX_LG_F16 : case V_CMPX_GE_F16 : case V_CMPX_O_F16 : case V_CMPX_U_F16 : case V_CMPX_NGE_F16 : case V_CMPX_NLG_F16 : case V_CMPX_NGT_F16 : case V_CMPX_NLE_F16 : case V_CMPX_NEQ_F16 : case V_CMPX_NLT_F16 : case V_CMPX_TRU_F16 : case V_CMP_F_U16 : case V_CMP_LT_U16 : case V_CMP_EQ_U16 : case V_CMP_LE_U16 : case V_CMP_GT_U16 : case V_CMP_LG_U16 : case V_CMP_GE_U16 : case V_CMP_TRU_U16 : case V_CMPx_F_U16 : case V_CMPx_LT_U16 : case V_CMPx_EQ_U16 : case V_CMPx_LE_U16 : case V_CMPx_GT_U16 : case V_CMPx_LG_U16 : case V_CMPx_GE_U16 : case V_CMPx_TRU_U16 : case V_CMP_F_I16 : case V_CMP_LT_I16 : case V_CMP_EQ_I16 : case V_CMP_LE_I16 : case V_CMP_GT_I16 : case V_CMP_LG_I16 : case V_CMP_GE_I16 : case V_CMP_TRU_I16 : case V_CMPx_F_I16 : case V_CMPx_LT_I16 : case V_CMPx_EQ_I16 : case V_CMPx_LE_I16 : case V_CMPx_GT_I16 : case V_CMPx_LG_I16 : case V_CMPx_GE_I16 : case V_CMPx_TRU_I16 : case V_CMP_CLASS_F16: case V_CMPX_CLASS_F16: return 2; case V_MOV_B32 : case V_READFIRSTLANE_B32 : case V_CVT_I32_F64 : case V_CVT_F64_I32 : case V_CVT_F32_I32 : case V_CVT_F32_U32 : case V_CVT_U32_F32 : case V_CVT_I32_F32 : case V_MOV_FED_B32 : case V_CVT_F16_F32 : case V_CVT_F32_F16 : case V_CVT_RPI_I32_F32 : case V_CVT_FLR_I32_F32 : case V_CVT_OFF_F32_I4 : case V_CVT_F32_F64 : case V_CVT_F64_F32 : case V_CVT_F32_UBYTE0 : case V_CVT_F32_UBYTE1 : case V_CVT_F32_UBYTE2 : case V_CVT_F32_UBYTE3 : case V_CVT_U32_F64 : case V_CVT_F64_U32 : case V_TRUNC_F64 : case V_CEIL_F64 : case V_RNDNE_F64 : case V_FLOOR_F64 : case V_FRACT_F32 : case V_TRUNC_F32 : case V_CEIL_F32 : case V_RNDNE_F32 : case V_FLOOR_F32 : case V_EXP_F32 : case V_LOG_CLAMP_F32 : case V_LOG_F32 : case V_RCP_CLAMP_F32 : case V_RCP_LEGACY_F32 : case V_RCP_F32 : case V_RCP_IFLAG_F32 : case V_RSQ_CLAMP_F32 : case V_RSQ_LEGACY_F32 : case V_RSQ_F32 : case V_RCP_F64 : case V_RCP_CLAMP_F64 : case V_RSQ_F64 : case V_RSQ_CLAMP_F64 : case V_SQRT_F32 : case V_SQRT_F64 : case V_SIN_F32 : case V_COS_F32 : case V_NOT_B32 : case V_BFREV_B32 : case V_FFBH_U32 : case V_FFBL_B32 : case V_FFBH_I32 : case V_FREXP_EXP_I32_F64 : case V_FREXP_MANT_F64 : case V_FRACT_F64 : case V_FREXP_EXP_I32_F32 : case V_FREXP_MANT_F32 : case V_MOVRELD_B32 : case V_MOVRELS_B32 : case V_MOVRELSD_B32 : case V_LOG_LEGACY_F32 : case V_EXP_LEGACY_F32 : return 1; case V_MULLIT_F32 : // = D.f = S0.f * S1.f, replicate result into 4 components (0.0 * x = 0.0; special INF, NaN, overflow rules). case V_LSHL_B64 : // = D = S0.u << S1.u[4:0]. case V_LSHR_B64 : // = D = S0.u >> S1.u[4:0]. case V_ASHR_I64 : // = D = S0.u >> S1.u[4:0]. case V_ADD_F64 : // = D.d = S0.d + S1.d. case V_MUL_F64 : // = D.d = S0.d * S1.d. case V_MIN_F64 : // = D.d = min(S0.d, S1.d). case V_MAX_F64 : // = D.d = max(S0.d, S1.d). case V_LDEXP_F64 : // = D.d = pow(S0.d, S1.i[31:0]). case V_MUL_LO_U32 : // = D.u = S0.u * S1.u. case V_MUL_HI_U32 : // = D.u = (S0.u * S1.u)>>32. case V_MUL_LO_I32 : // = D.i = S0.i * S1.i. case V_MUL_HI_I32 : // = D.i = (S0.i * S1.i)>>32. case V_TRIG_PREOP_F64 : // = D.d = Look Up 2/PI (S0.d) with segment select S1.u[4:0]. return 2; case V_DIV_SCALE_F32 : // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. case V_DIV_SCALE_F64 : // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. case V_MAD_LEGACY_F32 : // = D.f = S0.f * S1.f + S2.f (DX9 rules, 0.0*x = 0.0). case V_MAD_F32 : // = D.f = S0.f * S1.f + S2.f. case V_MAD_I32_I24 : // = D.i = S0.i * S1.i + S2.iD.i = S0.i * S1.i + S2.i. case V_MAD_U32_U24 : // = D.u = S0.u * S1.u + S2.u. case V_CUBEID_F32 : // = Rm.w <- Rn,x, Rn,y, Rn.z. case V_CUBESC_F32 : // = Rm.y <- Rn,x, Rn,y, Rn.z. case V_CUBETC_F32 : // = Rm.x <- Rn,x, Rn,y, Rn.z. case V_CUBEMA_F32 : // = Rm.z <- Rn,x, Rn,y, Rn.z case V_BFE_U32 : // = D.u = (S0.u>>S1.u[4:0]) & ((1<>S1.u[4:0]) & ((1<> 1) << 24 + case V_ALIGNBIT_B32 : // = D.u = ({S0,S1} >> S2.u[4:0]) & 0xFFFFFFFF. case V_ALIGNBYTE_B32 : // = D.u = ({S0,S1} >> (8*S2.u[4:0])) & 0xFFFFFFFF. case V_MIN3_F32 : // = D.f = min(S0.f, S1.f, S2.f). case V_MIN3_I32 : // = D.i = min(S0.i, S1.i, S2.i). case V_MIN3_U32 : // = 0x153 D.u = min(S0.u, S1.u, S2.u). case V_MAX3_F32 : // = D.f = max(S0.f, S1.f, S2.f). case V_MAX3_I32 : // = D.i = max(S0.i, S1.i, S2.i). case V_MAX3_U32 : // = D.u = max(S0.u, S1.u, S2.u). case V_MED3_F32 : // = D.f = median(S0.f, S1.f, S2.f). case V_MED3_I32 : // = D.i = median(S0.i, S1.i, S2.i). case V_MED3_U32 : // = D.u = median(S0.u, S1.u, S2.u). case V_SAD_U8 : // = D.u = Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_SAD_HI_U8 : // = D.u = Byte SAD with accum_hi(S0.u, S1.u, S2.u). case V_SAD_U16 : // = D.u = Word SAD with accum(S0.u, S1.u, S2.u). case V_SAD_U32 : // = D.u = Dword SAD with accum(S0.u, S1.u, S2.u). case V_CVT_PK_U8_F32 : // = f32->u8(s0.f), pack into byte(s1.u), of dword(s2). case V_DIV_FIXUP_F32 : // = D.f = Special case divide fixup and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_DIV_FIXUP_F64 : // = D.d = Special case divide fixup and flags(s0.d = Quotient, s1.d = Denominator, s2.d = Numerator). case V_DIV_FMAS_F32 : // = D.f = Special case divide FMA with scale and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_DIV_FMAS_F64 : // = D.d = Special case divide FMA with scale and flags(s0.d= Quotient, s1.d = Denominator, s2.d = Numerator). case V_MSAD_U8 : // = D.u = Masked Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_QSAD_U8 : // = D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0],S1.u[31:0], S2.u[63:0]). case V_QSAD_PK_U16_U8 : // : D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_PK_U16_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U32_U8 : // : D.u128 = Masked Quad-Byte SAD with 32-bit accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[127:0]). case V_MAD_U64_U32 : // : {vcc_out,D.u64} = S0.u32 * S1.u32 + S2.u64. case V_MAD_I64_I32 : // : {vcc_out,D.i64} = S0.i32 * S1.i32 + S2.i64. return 3; case V_INTERP_P1_F32 : case V_INTERP_P2_F32 : case V_INTERP_MOV_F32 : case V_INTERP_P1LL_F16: case V_INTERP_P1LV_F16: case V_INTERP_P2_F16 : return 1; } } uint GetResultWidthInDWORDs( VectorInstructions e ) { switch( e ) { default: return 0; case V_ADD_U32: case V_SUB_U32: case V_SUBREV_U32: return 1; case V_LSHLREV_B64: case V_LSHRREV_B64: case V_ASHRREV_I64: return 2; case V_MAD_F16 : case V_MAD_U16 : case V_MAD_I16 : case V_PERM_B32 : case V_FMA_F16 : case V_DIV_FIXUP_F16 : case V_ADD_F16 : case V_SUB_F16 : case V_SUBREV_F16 : case V_MUL_F16 : case V_MAC_F16 : case V_MADMK_F16 : case V_MADAK_F16 : case V_ADD_U16 : case V_SUB_U16 : case V_SUBREV_U16 : case V_MUL_LO_U16 : case V_LSHLREV_B16 : case V_LSHRREV_B16 : case V_ASHRREV_I16 : case V_MAX_F16 : case V_MIN_F16 : case V_MAX_U16 : case V_MAX_I16 : case V_MIN_U16 : case V_MIN_I16 : case V_LDEXP_F16 : case V_CVT_F16_U16 : case V_CVT_F16_I16 : case V_CVT_U16_F16 : case V_CVT_I16_F16 : case V_RCP_F16 : case V_SQRT_F16 : case V_RSQ_F16 : case V_LOG_F16 : case V_EXP_F16 : case V_FREXP_MANT_F16 : case V_FREXP_EXP_I16_F16 : case V_FLOOR_F16 : case V_CEIL_F16 : case V_TRUNC_F16 : case V_RNDNE_F16 : case V_FRACT_F16 : case V_SIN_F16 : case V_COS_F16 : case V_CNDMASK_B32 : case V_READLANE_B32 : case V_WRITELANE_B32 : case V_ADD_F32 : case V_SUB_F32 : case V_SUBREV_F32 : case V_MAC_LEGACY_F32 : case V_MUL_LEGACY_F32 : case V_MUL_F32 : case V_MUL_I32_I24 : case V_MUL_HI_I32_I24 : case V_MUL_U32_U24 : case V_MUL_HI_U32_U24 : case V_MIN_LEGACY_F32 : case V_MAX_LEGACY_F32 : case V_MIN_F32 : case V_MAX_F32 : case V_MIN_I32 : case V_MAX_I32 : case V_MIN_U32 : case V_MAX_U32 : case V_LSHR_B32 : case V_LSHRREV_B32 : case V_ASHR_I32 : case V_ASHRREV_I32 : case V_LSHL_B32 : case V_LSHLREV_B32 : case V_AND_B32 : case V_OR_B32 : case V_XOR_B32 : case V_BFM_B32 : case V_MAC_F32 : case V_MADMK_F32 : case V_MADAK_F32 : case V_BCNT_U32_B32 : case V_MBCNT_LO_U32_B32 : case V_MBCNT_HI_U32_B32 : case V_ADD_I32 : case V_SUB_I32 : case V_SUBREV_I32 : case V_ADDC_U32 : case V_SUBB_U32 : case V_SUBBREV_U32 : case V_LDEXP_F32 : case V_CVT_PKACCUM_U8_F32 : case V_CVT_PKNORM_I16_F32 : case V_CVT_PKNORM_U16_F32 : case V_CVT_PKRTZ_F16_F32 : case V_CVT_PK_U16_U32 : case V_CVT_PK_I16_I32 : return 1; case V_CMP_CLASS_F16: case V_CMPX_CLASS_F16: case V_CMP_F_F32 : case V_CMP_LT_F32 : case V_CMP_EQ_F32 : case V_CMP_LE_F32 : case V_CMP_GT_F32 : case V_CMP_LG_F32 : case V_CMP_GE_F32 : case V_CMP_O_F32 : case V_CMP_U_F32 : case V_CMP_NGE_F32 : case V_CMP_NLG_F32 : case V_CMP_NGT_F32 : case V_CMP_NLE_F32 : case V_CMP_NEQ_F32 : case V_CMP_NLT_F32 : case V_CMP_TRU_F32 : case V_CMPX_F_F32 : case V_CMPX_LT_F32 : case V_CMPX_EQ_F32 : case V_CMPX_LE_F32 : case V_CMPX_GT_F32 : case V_CMPX_LG_F32 : case V_CMPX_GE_F32 : case V_CMPX_O_F32 : case V_CMPX_U_F32 : case V_CMPX_NGE_F32 : case V_CMPX_NLG_F32 : case V_CMPX_NGT_F32 : case V_CMPX_NLE_F32 : case V_CMPX_NEQ_F32 : case V_CMPX_NLT_F32 : case V_CMPX_TRU_F32 : case V_CMP_F_F64 : case V_CMP_LT_F64 : case V_CMP_EQ_F64 : case V_CMP_LE_F64 : case V_CMP_GT_F64 : case V_CMP_LG_F64 : case V_CMP_GE_F64 : case V_CMP_O_F64 : case V_CMP_U_F64 : case V_CMP_NGE_F64 : case V_CMP_NLG_F64 : case V_CMP_NGT_F64 : case V_CMP_NLE_F64 : case V_CMP_NEQ_F64 : case V_CMP_NLT_F64 : case V_CMP_TRU_F64 : case V_CMPX_F_F64 : case V_CMPX_LT_F64 : case V_CMPX_EQ_F64 : case V_CMPX_LE_F64 : case V_CMPX_GT_F64 : case V_CMPX_LG_F64 : case V_CMPX_GE_F64 : case V_CMPX_O_F64 : case V_CMPX_U_F64 : case V_CMPX_NGE_F64 : case V_CMPX_NLG_F64 : case V_CMPX_NGT_F64 : case V_CMPX_NLE_F64 : case V_CMPX_NEQ_F64 : case V_CMPX_NLT_F64 : case V_CMPX_TRU_F64 : case V_CMPS_F_F32 : case V_CMPS_LT_F32 : case V_CMPS_EQ_F32 : case V_CMPS_LE_F32 : case V_CMPS_GT_F32 : case V_CMPS_LG_F32 : case V_CMPS_GE_F32 : case V_CMPS_O_F32 : case V_CMPS_U_F32 : case V_CMPS_NGE_F32 : case V_CMPS_NLG_F32 : case V_CMPS_NGT_F32 : case V_CMPS_NLE_F32 : case V_CMPS_NEQ_F32 : case V_CMPS_NLT_F32 : case V_CMPS_TRU_F32 : case V_CMPSX_F_F32 : case V_CMPSX_LT_F32 : case V_CMPSX_EQ_F32 : case V_CMPSX_LE_F32 : case V_CMPSX_GT_F32 : case V_CMPSX_LG_F32 : case V_CMPSX_GE_F32 : case V_CMPSX_O_F32 : case V_CMPSX_U_F32 : case V_CMPSX_NGE_F32 : case V_CMPSX_NLG_F32 : case V_CMPSX_NGT_F32 : case V_CMPSX_NLE_F32 : case V_CMPSX_NEQ_F32 : case V_CMPSX_NLT_F32 : case V_CMPSX_TRU_F32 : case V_CMPS_F_F64 : case V_CMPS_LT_F64 : case V_CMPS_EQ_F64 : case V_CMPS_LE_F64 : case V_CMPS_GT_F64 : case V_CMPS_LG_F64 : case V_CMPS_GE_F64 : case V_CMPS_O_F64 : case V_CMPS_U_F64 : case V_CMPS_NGE_F64 : case V_CMPS_NLG_F64 : case V_CMPS_NGT_F64 : case V_CMPS_NLE_F64 : case V_CMPS_NEQ_F64 : case V_CMPS_NLT_F64 : case V_CMPS_TRU_F64 : case V_CMPSX_F_F64 : case V_CMPSX_LT_F64 : case V_CMPSX_EQ_F64 : case V_CMPSX_LE_F64 : case V_CMPSX_GT_F64 : case V_CMPSX_LG_F64 : case V_CMPSX_GE_F64 : case V_CMPSX_O_F64 : case V_CMPSX_U_F64 : case V_CMPSX_NGE_F64 : case V_CMPSX_NLG_F64 : case V_CMPSX_NGT_F64 : case V_CMPSX_NLE_F64 : case V_CMPSX_NEQ_F64 : case V_CMPSX_NLT_F64 : case V_CMPSX_TRU_F64 : case V_CMP_F_I32 : case V_CMP_LT_I32 : case V_CMP_EQ_I32 : case V_CMP_LE_I32 : case V_CMP_GT_I32 : case V_CMP_LG_I32 : case V_CMP_GE_I32 : case V_CMP_TRU_I32 : case V_CMPX_F_I32 : case V_CMPX_LT_I32 : case V_CMPX_EQ_I32 : case V_CMPX_LE_I32 : case V_CMPX_GT_I32 : case V_CMPX_LG_I32 : case V_CMPX_GE_I32 : case V_CMPX_TRU_I32 : case V_CMP_F_I64 : case V_CMP_LT_I64 : case V_CMP_EQ_I64 : case V_CMP_LE_I64 : case V_CMP_GT_I64 : case V_CMP_LG_I64 : case V_CMP_GE_I64 : case V_CMP_TRU_I64 : case V_CMPX_F_I64 : case V_CMPX_LT_I64 : case V_CMPX_EQ_I64 : case V_CMPX_LE_I64 : case V_CMPX_GT_I64 : case V_CMPX_LG_I64 : case V_CMPX_GE_I64 : case V_CMPX_TRU_I64 : case V_CMP_F_U32 : case V_CMP_LT_U32 : case V_CMP_EQ_U32 : case V_CMP_LE_U32 : case V_CMP_GT_U32 : case V_CMP_LG_U32 : case V_CMP_GE_U32 : case V_CMP_TRU_U32 : case V_CMPX_F_U32 : case V_CMPX_LT_U32 : case V_CMPX_EQ_U32 : case V_CMPX_LE_U32 : case V_CMPX_GT_U32 : case V_CMPX_LG_U32 : case V_CMPX_GE_U32 : case V_CMPX_TRU_U32 : case V_CMP_F_U64 : case V_CMP_LT_U64 : case V_CMP_EQ_U64 : case V_CMP_LE_U64 : case V_CMP_GT_U64 : case V_CMP_LG_U64 : case V_CMP_GE_U64 : case V_CMP_TRU_U64 : case V_CMPx_F_U64 : case V_CMPx_LT_U64 : case V_CMPx_EQ_U64 : case V_CMPx_LE_U64 : case V_CMPx_GT_U64 : case V_CMPx_LG_U64 : case V_CMPx_GE_U64 : case V_CMPx_TRU_U64 : case V_CMP_CLASS_F32 : case V_CMPX_CLASS_F32 : case V_CMP_CLASS_F64 : case V_CMPX_CLASS_F64 : case V_CMP_F_F16 : case V_CMP_LT_F16 : case V_CMP_EQ_F16 : case V_CMP_LE_F16 : case V_CMP_GT_F16 : case V_CMP_LG_F16 : case V_CMP_GE_F16 : case V_CMP_O_F16 : case V_CMP_U_F16 : case V_CMP_NGE_F16 : case V_CMP_NLG_F16 : case V_CMP_NGT_F16 : case V_CMP_NLE_F16 : case V_CMP_NEQ_F16 : case V_CMP_NLT_F16 : case V_CMP_TRU_F16 : case V_CMPX_F_F16 : case V_CMPX_LT_F16 : case V_CMPX_EQ_F16 : case V_CMPX_LE_F16 : case V_CMPX_GT_F16 : case V_CMPX_LG_F16 : case V_CMPX_GE_F16 : case V_CMPX_O_F16 : case V_CMPX_U_F16 : case V_CMPX_NGE_F16 : case V_CMPX_NLG_F16 : case V_CMPX_NGT_F16 : case V_CMPX_NLE_F16 : case V_CMPX_NEQ_F16 : case V_CMPX_NLT_F16 : case V_CMPX_TRU_F16 : case V_CMP_F_U16 : case V_CMP_LT_U16 : case V_CMP_EQ_U16 : case V_CMP_LE_U16 : case V_CMP_GT_U16 : case V_CMP_LG_U16 : case V_CMP_GE_U16 : case V_CMP_TRU_U16 : case V_CMPx_F_U16 : case V_CMPx_LT_U16 : case V_CMPx_EQ_U16 : case V_CMPx_LE_U16 : case V_CMPx_GT_U16 : case V_CMPx_LG_U16 : case V_CMPx_GE_U16 : case V_CMPx_TRU_U16 : case V_CMP_F_I16 : case V_CMP_LT_I16 : case V_CMP_EQ_I16 : case V_CMP_LE_I16 : case V_CMP_GT_I16 : case V_CMP_LG_I16 : case V_CMP_GE_I16 : case V_CMP_TRU_I16 : case V_CMPx_F_I16 : case V_CMPx_LT_I16 : case V_CMPx_EQ_I16 : case V_CMPx_LE_I16 : case V_CMPx_GT_I16 : case V_CMPx_LG_I16 : case V_CMPx_GE_I16 : case V_CMPx_TRU_I16 : return 2; case V_MOV_B32 : case V_READFIRSTLANE_B32 : case V_CVT_I32_F64 : case V_CVT_F32_I32 : case V_CVT_F32_U32 : case V_CVT_U32_F32 : case V_CVT_I32_F32 : case V_MOV_FED_B32 : case V_CVT_F16_F32 : case V_CVT_F32_F16 : case V_CVT_RPI_I32_F32 : case V_CVT_FLR_I32_F32 : case V_CVT_OFF_F32_I4 : case V_CVT_F32_F64 : case V_CVT_F32_UBYTE0 : case V_CVT_F32_UBYTE1 : case V_CVT_F32_UBYTE2 : case V_CVT_F32_UBYTE3 : case V_CVT_U32_F64 : case V_FRACT_F32 : case V_TRUNC_F32 : case V_CEIL_F32 : case V_RNDNE_F32 : case V_FLOOR_F32 : case V_EXP_F32 : case V_LOG_CLAMP_F32 : case V_LOG_F32 : case V_RCP_CLAMP_F32 : case V_RCP_LEGACY_F32 : case V_RCP_F32 : case V_RCP_IFLAG_F32 : case V_RSQ_CLAMP_F32 : case V_RSQ_LEGACY_F32 : case V_RSQ_F32 : case V_SQRT_F32 : case V_SIN_F32 : case V_COS_F32 : case V_NOT_B32 : case V_BFREV_B32 : case V_FFBH_U32 : case V_FFBL_B32 : case V_FFBH_I32 : case V_FREXP_EXP_I32_F64 : case V_FREXP_EXP_I32_F32 : case V_FREXP_MANT_F32 : case V_MOVRELD_B32 : case V_MOVRELS_B32 : case V_MOVRELSD_B32 : case V_LOG_LEGACY_F32 : case V_EXP_LEGACY_F32 : case V_MULLIT_F32 : // = D.f = S0.f * S1.f, replicate result into 4 components (0.0 * x = 0.0; special INF, NaN, overflow rules). case V_MUL_LO_U32 : // = D.u = S0.u * S1.u. case V_MUL_HI_U32 : // = D.u = (S0.u * S1.u)>>32. case V_MUL_LO_I32 : // = D.i = S0.i * S1.i. case V_MUL_HI_I32 : // = D.i = (S0.i * S1.i)>>32. case V_DIV_SCALE_F64 : // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. case V_MAD_LEGACY_F32 : // = D.f = S0.f * S1.f + S2.f (DX9 rules, 0.0*x = 0.0). case V_MAD_F32 : // = D.f = S0.f * S1.f + S2.f. case V_MAD_I32_I24 : // = D.i = S0.i * S1.i + S2.iD.i = S0.i * S1.i + S2.i. case V_MAD_U32_U24 : // = D.u = S0.u * S1.u + S2.u. case V_CUBEID_F32 : // = Rm.w <- Rn,x, Rn,y, Rn.z. case V_CUBESC_F32 : // = Rm.y <- Rn,x, Rn,y, Rn.z. case V_CUBETC_F32 : // = Rm.x <- Rn,x, Rn,y, Rn.z. case V_CUBEMA_F32 : // = Rm.z <- Rn,x, Rn,y, Rn.z case V_BFE_U32 : // = D.u = (S0.u>>S1.u[4:0]) & ((1<>S1.u[4:0]) & ((1<> S1.u[4:0]. case V_ASHR_I64 : // = D = S0.u >> S1.u[4:0]. case V_ADD_F64 : // = D.d = S0.d + S1.d. case V_MUL_F64 : // = D.d = S0.d * S1.d. case V_MIN_F64 : // = D.d = min(S0.d, S1.d). case V_MAX_F64 : // = D.d = max(S0.d, S1.d). case V_LDEXP_F64 : // = D.d = pow(S0.d, S1.i[31:0]). case V_TRIG_PREOP_F64 : // = D.d = Look Up 2/PI (S0.d) with segment select S1.u[4:0]. case V_FMA_F64 : // = D.d = S0.d * S1.d + S2.d. case V_DIV_FIXUP_F64 : // = D.d = Special case divide fixup and flags(s0.d = Quotient, s1.d = Denominator, s2.d = Numerator). case V_DIV_FMAS_F64 : // = D.d = Special case divide FMA with scale and flags(s0.d= Quotient, s1.d = Denominator, s2.d = Numerator). return 2; case V_DIV_SCALE_F32 : // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. case V_LERP_U8 : // = D.u = ((S0.u[31:24] + S1.u[31:24] + S2.u[24]) >> 1) << 24 + case V_ALIGNBIT_B32 : // = D.u = ({S0,S1} >> S2.u[4:0]) & 0xFFFFFFFF. case V_ALIGNBYTE_B32 : // = D.u = ({S0,S1} >> (8*S2.u[4:0])) & 0xFFFFFFFF. case V_MIN3_F32 : // = D.f = min(S0.f, S1.f, S2.f). case V_MIN3_I32 : // = D.i = min(S0.i, S1.i, S2.i). case V_MIN3_U32 : // = 0x153 D.u = min(S0.u, S1.u, S2.u). case V_MAX3_F32 : // = D.f = max(S0.f, S1.f, S2.f). case V_MAX3_I32 : // = D.i = max(S0.i, S1.i, S2.i). case V_MAX3_U32 : // = D.u = max(S0.u, S1.u, S2.u). case V_MED3_F32 : // = D.f = median(S0.f, S1.f, S2.f). case V_MED3_I32 : // = D.i = median(S0.i, S1.i, S2.i). case V_MED3_U32 : // = D.u = median(S0.u, S1.u, S2.u). case V_SAD_U8 : // = D.u = Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_SAD_HI_U8 : // = D.u = Byte SAD with accum_hi(S0.u, S1.u, S2.u). case V_SAD_U16 : // = D.u = Word SAD with accum(S0.u, S1.u, S2.u). case V_SAD_U32 : // = D.u = Dword SAD with accum(S0.u, S1.u, S2.u). case V_CVT_PK_U8_F32 : // = f32->u8(s0.f), pack into byte(s1.u), of dword(s2). case V_DIV_FIXUP_F32 : // = D.f = Special case divide fixup and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_DIV_FMAS_F32 : // = D.f = Special case divide FMA with scale and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_MSAD_U8 : // = D.u = Masked Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_QSAD_U8 : // = D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0],S1.u[31:0], S2.u[63:0]). case V_QSAD_PK_U16_U8 : // : D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_PK_U16_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U32_U8 : // : D.u128 = Masked Quad-Byte SAD with 32-bit accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[127:0]). case V_MAD_U64_U32 : // : {vcc_out,D.u64} = S0.u32 * S1.u32 + S2.u64. case V_MAD_I64_I32 : // : {vcc_out,D.i64} = S0.i32 * S1.i32 + S2.i64. case V_INTERP_P1_F32 : case V_INTERP_P2_F32 : case V_INTERP_MOV_F32 : case V_INTERP_P1LL_F16: case V_INTERP_P1LV_F16: case V_INTERP_P2_F16 : return 1; } } uint GetSrc0WidthInDWORDs( VectorInstructions e ) { switch( e ) { default: return 0; case V_ADD_U32: case V_SUB_U32: case V_SUBREV_U32: case V_LSHLREV_B64 : case V_LSHRREV_B64 : case V_ASHRREV_I64 : return 1; case V_MAD_F16 : case V_MAD_U16 : case V_MAD_I16 : case V_PERM_B32 : case V_FMA_F16 : case V_DIV_FIXUP_F16 : case V_ADD_F16 : case V_SUB_F16 : case V_SUBREV_F16 : case V_MUL_F16 : case V_MAC_F16 : case V_MADMK_F16 : case V_MADAK_F16 : case V_ADD_U16 : case V_SUB_U16 : case V_SUBREV_U16 : case V_MUL_LO_U16 : case V_LSHLREV_B16 : case V_LSHRREV_B16 : case V_ASHRREV_I16 : case V_MAX_F16 : case V_MIN_F16 : case V_MAX_U16 : case V_MAX_I16 : case V_MIN_U16 : case V_MIN_I16 : case V_LDEXP_F16 : case V_CVT_F16_U16 : case V_CVT_F16_I16 : case V_CVT_U16_F16 : case V_CVT_I16_F16 : case V_RCP_F16 : case V_SQRT_F16 : case V_RSQ_F16 : case V_LOG_F16 : case V_EXP_F16 : case V_FREXP_MANT_F16 : case V_FREXP_EXP_I16_F16 : case V_FLOOR_F16 : case V_CEIL_F16 : case V_TRUNC_F16 : case V_RNDNE_F16 : case V_FRACT_F16 : case V_SIN_F16 : case V_COS_F16 : case V_CNDMASK_B32 : case V_READLANE_B32 : case V_WRITELANE_B32 : case V_ADD_F32 : case V_SUB_F32 : case V_SUBREV_F32 : case V_MAC_LEGACY_F32 : case V_MUL_LEGACY_F32 : case V_MUL_F32 : case V_MUL_I32_I24 : case V_MUL_HI_I32_I24 : case V_MUL_U32_U24 : case V_MUL_HI_U32_U24 : case V_MIN_LEGACY_F32 : case V_MAX_LEGACY_F32 : case V_MIN_F32 : case V_MAX_F32 : case V_MIN_I32 : case V_MAX_I32 : case V_MIN_U32 : case V_MAX_U32 : case V_LSHR_B32 : case V_LSHRREV_B32 : case V_ASHR_I32 : case V_ASHRREV_I32 : case V_LSHL_B32 : case V_LSHLREV_B32 : case V_AND_B32 : case V_OR_B32 : case V_XOR_B32 : case V_BFM_B32 : case V_MAC_F32 : case V_MADMK_F32 : case V_MADAK_F32 : case V_BCNT_U32_B32 : case V_MBCNT_LO_U32_B32 : case V_MBCNT_HI_U32_B32 : case V_ADD_I32 : case V_SUB_I32 : case V_SUBREV_I32 : case V_ADDC_U32 : case V_SUBB_U32 : case V_SUBBREV_U32 : case V_LDEXP_F32 : case V_CVT_PKACCUM_U8_F32 : case V_CVT_PKNORM_I16_F32 : case V_CVT_PKNORM_U16_F32 : case V_CVT_PKRTZ_F16_F32 : case V_CVT_PK_U16_U32 : case V_CVT_PK_I16_I32 : return 1; // VOPC case V_CMP_CLASS_F16: case V_CMPX_CLASS_F16: case V_CMP_F_F16 : case V_CMP_LT_F16 : case V_CMP_EQ_F16 : case V_CMP_LE_F16 : case V_CMP_GT_F16 : case V_CMP_LG_F16 : case V_CMP_GE_F16 : case V_CMP_O_F16 : case V_CMP_U_F16 : case V_CMP_NGE_F16 : case V_CMP_NLG_F16 : case V_CMP_NGT_F16 : case V_CMP_NLE_F16 : case V_CMP_NEQ_F16 : case V_CMP_NLT_F16 : case V_CMP_TRU_F16 : case V_CMPX_F_F16 : case V_CMPX_LT_F16 : case V_CMPX_EQ_F16 : case V_CMPX_LE_F16 : case V_CMPX_GT_F16 : case V_CMPX_LG_F16 : case V_CMPX_GE_F16 : case V_CMPX_O_F16 : case V_CMPX_U_F16 : case V_CMPX_NGE_F16 : case V_CMPX_NLG_F16 : case V_CMPX_NGT_F16 : case V_CMPX_NLE_F16 : case V_CMPX_NEQ_F16 : case V_CMPX_NLT_F16 : case V_CMPX_TRU_F16 : case V_CMP_F_U16 : case V_CMP_LT_U16 : case V_CMP_EQ_U16 : case V_CMP_LE_U16 : case V_CMP_GT_U16 : case V_CMP_LG_U16 : case V_CMP_GE_U16 : case V_CMP_TRU_U16 : case V_CMPx_F_U16 : case V_CMPx_LT_U16 : case V_CMPx_EQ_U16 : case V_CMPx_LE_U16 : case V_CMPx_GT_U16 : case V_CMPx_LG_U16 : case V_CMPx_GE_U16 : case V_CMPx_TRU_U16 : case V_CMP_F_I16 : case V_CMP_LT_I16 : case V_CMP_EQ_I16 : case V_CMP_LE_I16 : case V_CMP_GT_I16 : case V_CMP_LG_I16 : case V_CMP_GE_I16 : case V_CMP_TRU_I16 : case V_CMPx_F_I16 : case V_CMPx_LT_I16 : case V_CMPx_EQ_I16 : case V_CMPx_LE_I16 : case V_CMPx_GT_I16 : case V_CMPx_LG_I16 : case V_CMPx_GE_I16 : case V_CMPx_TRU_I16 : case V_CMP_F_F32 : case V_CMP_LT_F32 : case V_CMP_EQ_F32 : case V_CMP_LE_F32 : case V_CMP_GT_F32 : case V_CMP_LG_F32 : case V_CMP_GE_F32 : case V_CMP_O_F32 : case V_CMP_U_F32 : case V_CMP_NGE_F32 : case V_CMP_NLG_F32 : case V_CMP_NGT_F32 : case V_CMP_NLE_F32 : case V_CMP_NEQ_F32 : case V_CMP_NLT_F32 : case V_CMP_TRU_F32 : case V_CMPX_F_F32 : case V_CMPX_LT_F32 : case V_CMPX_EQ_F32 : case V_CMPX_LE_F32 : case V_CMPX_GT_F32 : case V_CMPX_LG_F32 : case V_CMPX_GE_F32 : case V_CMPX_O_F32 : case V_CMPX_U_F32 : case V_CMPX_NGE_F32 : case V_CMPX_NLG_F32 : case V_CMPX_NGT_F32 : case V_CMPX_NLE_F32 : case V_CMPX_NEQ_F32 : case V_CMPX_NLT_F32 : case V_CMPX_TRU_F32 : return 1; case V_CMP_F_F64 : case V_CMP_LT_F64 : case V_CMP_EQ_F64 : case V_CMP_LE_F64 : case V_CMP_GT_F64 : case V_CMP_LG_F64 : case V_CMP_GE_F64 : case V_CMP_O_F64 : case V_CMP_U_F64 : case V_CMP_NGE_F64 : case V_CMP_NLG_F64 : case V_CMP_NGT_F64 : case V_CMP_NLE_F64 : case V_CMP_NEQ_F64 : case V_CMP_NLT_F64 : case V_CMP_TRU_F64 : case V_CMPX_F_F64 : case V_CMPX_LT_F64 : case V_CMPX_EQ_F64 : case V_CMPX_LE_F64 : case V_CMPX_GT_F64 : case V_CMPX_LG_F64 : case V_CMPX_GE_F64 : case V_CMPX_O_F64 : case V_CMPX_U_F64 : case V_CMPX_NGE_F64 : case V_CMPX_NLG_F64 : case V_CMPX_NGT_F64 : case V_CMPX_NLE_F64 : case V_CMPX_NEQ_F64 : case V_CMPX_NLT_F64 : case V_CMPX_TRU_F64 : return 2; case V_CMPS_F_F32 : case V_CMPS_LT_F32 : case V_CMPS_EQ_F32 : case V_CMPS_LE_F32 : case V_CMPS_GT_F32 : case V_CMPS_LG_F32 : case V_CMPS_GE_F32 : case V_CMPS_O_F32 : case V_CMPS_U_F32 : case V_CMPS_NGE_F32 : case V_CMPS_NLG_F32 : case V_CMPS_NGT_F32 : case V_CMPS_NLE_F32 : case V_CMPS_NEQ_F32 : case V_CMPS_NLT_F32 : case V_CMPS_TRU_F32 : case V_CMPSX_F_F32 : case V_CMPSX_LT_F32 : case V_CMPSX_EQ_F32 : case V_CMPSX_LE_F32 : case V_CMPSX_GT_F32 : case V_CMPSX_LG_F32 : case V_CMPSX_GE_F32 : case V_CMPSX_O_F32 : case V_CMPSX_U_F32 : case V_CMPSX_NGE_F32 : case V_CMPSX_NLG_F32 : case V_CMPSX_NGT_F32 : case V_CMPSX_NLE_F32 : case V_CMPSX_NEQ_F32 : case V_CMPSX_NLT_F32 : case V_CMPSX_TRU_F32 : return 1; case V_CMPS_F_F64 : case V_CMPS_LT_F64 : case V_CMPS_EQ_F64 : case V_CMPS_LE_F64 : case V_CMPS_GT_F64 : case V_CMPS_LG_F64 : case V_CMPS_GE_F64 : case V_CMPS_O_F64 : case V_CMPS_U_F64 : case V_CMPS_NGE_F64 : case V_CMPS_NLG_F64 : case V_CMPS_NGT_F64 : case V_CMPS_NLE_F64 : case V_CMPS_NEQ_F64 : case V_CMPS_NLT_F64 : case V_CMPS_TRU_F64 : case V_CMPSX_F_F64 : case V_CMPSX_LT_F64 : case V_CMPSX_EQ_F64 : case V_CMPSX_LE_F64 : case V_CMPSX_GT_F64 : case V_CMPSX_LG_F64 : case V_CMPSX_GE_F64 : case V_CMPSX_O_F64 : case V_CMPSX_U_F64 : case V_CMPSX_NGE_F64 : case V_CMPSX_NLG_F64 : case V_CMPSX_NGT_F64 : case V_CMPSX_NLE_F64 : case V_CMPSX_NEQ_F64 : case V_CMPSX_NLT_F64 : case V_CMPSX_TRU_F64 : return 2; case V_CMP_F_I32 : case V_CMP_LT_I32 : case V_CMP_EQ_I32 : case V_CMP_LE_I32 : case V_CMP_GT_I32 : case V_CMP_LG_I32 : case V_CMP_GE_I32 : case V_CMP_TRU_I32 : case V_CMPX_F_I32 : case V_CMPX_LT_I32 : case V_CMPX_EQ_I32 : case V_CMPX_LE_I32 : case V_CMPX_GT_I32 : case V_CMPX_LG_I32 : case V_CMPX_GE_I32 : case V_CMPX_TRU_I32 : return 1; case V_CMP_F_I64 : case V_CMP_LT_I64 : case V_CMP_EQ_I64 : case V_CMP_LE_I64 : case V_CMP_GT_I64 : case V_CMP_LG_I64 : case V_CMP_GE_I64 : case V_CMP_TRU_I64 : case V_CMPX_F_I64 : case V_CMPX_LT_I64 : case V_CMPX_EQ_I64 : case V_CMPX_LE_I64 : case V_CMPX_GT_I64 : case V_CMPX_LG_I64 : case V_CMPX_GE_I64 : case V_CMPX_TRU_I64 : return 2; case V_CMP_F_U32 : case V_CMP_LT_U32 : case V_CMP_EQ_U32 : case V_CMP_LE_U32 : case V_CMP_GT_U32 : case V_CMP_LG_U32 : case V_CMP_GE_U32 : case V_CMP_TRU_U32 : case V_CMPX_F_U32 : case V_CMPX_LT_U32 : case V_CMPX_EQ_U32 : case V_CMPX_LE_U32 : case V_CMPX_GT_U32 : case V_CMPX_LG_U32 : case V_CMPX_GE_U32 : case V_CMPX_TRU_U32 : return 1; case V_CMP_F_U64 : case V_CMP_LT_U64 : case V_CMP_EQ_U64 : case V_CMP_LE_U64 : case V_CMP_GT_U64 : case V_CMP_LG_U64 : case V_CMP_GE_U64 : case V_CMP_TRU_U64 : case V_CMPx_F_U64 : case V_CMPx_LT_U64 : case V_CMPx_EQ_U64 : case V_CMPx_LE_U64 : case V_CMPx_GT_U64 : case V_CMPx_LG_U64 : case V_CMPx_GE_U64 : case V_CMPx_TRU_U64 : case V_CMP_CLASS_F64 : case V_CMPX_CLASS_F64 : return 2; case V_CMP_CLASS_F32 : case V_CMPX_CLASS_F32 : return 1; // VOP1 case V_CVT_F64_I32 : case V_CVT_F64_F32 : case V_CVT_F64_U32 : case V_MOV_B32 : case V_READFIRSTLANE_B32 : case V_CVT_F32_I32 : case V_CVT_F32_U32 : case V_CVT_U32_F32 : case V_CVT_I32_F32 : case V_MOV_FED_B32 : case V_CVT_F16_F32 : case V_CVT_F32_F16 : case V_CVT_RPI_I32_F32 : case V_CVT_FLR_I32_F32 : case V_CVT_OFF_F32_I4 : case V_CVT_F32_UBYTE0 : case V_CVT_F32_UBYTE1 : case V_CVT_F32_UBYTE2 : case V_CVT_F32_UBYTE3 : case V_FRACT_F32 : case V_TRUNC_F32 : case V_CEIL_F32 : case V_RNDNE_F32 : case V_FLOOR_F32 : case V_EXP_F32 : case V_LOG_CLAMP_F32 : case V_LOG_F32 : case V_RCP_CLAMP_F32 : case V_RCP_LEGACY_F32 : case V_RCP_F32 : case V_RCP_IFLAG_F32 : case V_RSQ_CLAMP_F32 : case V_RSQ_LEGACY_F32 : case V_RSQ_F32 : case V_SQRT_F32 : case V_SIN_F32 : case V_COS_F32 : case V_NOT_B32 : case V_BFREV_B32 : case V_FFBH_U32 : case V_FFBL_B32 : case V_FFBH_I32 : case V_FREXP_EXP_I32_F32 : case V_FREXP_MANT_F32 : case V_MOVRELD_B32 : case V_MOVRELS_B32 : case V_MOVRELSD_B32 : case V_LOG_LEGACY_F32 : case V_EXP_LEGACY_F32 : return 1; case V_TRUNC_F64 : case V_CEIL_F64 : case V_RNDNE_F64 : case V_FLOOR_F64 : case V_RCP_F64 : case V_RCP_CLAMP_F64 : case V_RSQ_F64 : case V_RSQ_CLAMP_F64 : case V_SQRT_F64 : case V_FREXP_MANT_F64 : case V_FRACT_F64 : case V_CVT_I32_F64 : case V_CVT_F32_F64 : case V_CVT_U32_F64 : case V_FREXP_EXP_I32_F64 : return 2; case V_DIV_SCALE_F32 : // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. case V_MAD_LEGACY_F32 : // = D.f = S0.f * S1.f + S2.f (DX9 rules, 0.0*x = 0.0). case V_MAD_F32 : // = D.f = S0.f * S1.f + S2.f. case V_MAD_I32_I24 : // = D.i = S0.i * S1.i + S2.iD.i = S0.i * S1.i + S2.i. case V_MAD_U32_U24 : // = D.u = S0.u * S1.u + S2.u. case V_CUBEID_F32 : // = Rm.w <- Rn,x, Rn,y, Rn.z. case V_CUBESC_F32 : // = Rm.y <- Rn,x, Rn,y, Rn.z. case V_CUBETC_F32 : // = Rm.x <- Rn,x, Rn,y, Rn.z. case V_CUBEMA_F32 : // = Rm.z <- Rn,x, Rn,y, Rn.z case V_BFE_U32 : // = D.u = (S0.u>>S1.u[4:0]) & ((1<>S1.u[4:0]) & ((1<> 1) << 24 + case V_ALIGNBIT_B32 : // = D.u = ({S0,S1} >> S2.u[4:0]) & 0xFFFFFFFF. case V_ALIGNBYTE_B32 : // = D.u = ({S0,S1} >> (8*S2.u[4:0])) & 0xFFFFFFFF. case V_MULLIT_F32 : // = D.f = S0.f * S1.f, replicate result into 4 components (0.0 * x = 0.0; special INF, NaN, overflow rules). case V_MIN3_F32 : // = D.f = min(S0.f, S1.f, S2.f). case V_MIN3_I32 : // = D.i = min(S0.i, S1.i, S2.i). case V_MIN3_U32 : // = 0x153 D.u = min(S0.u, S1.u, S2.u). case V_MAX3_F32 : // = D.f = max(S0.f, S1.f, S2.f). case V_MAX3_I32 : // = D.i = max(S0.i, S1.i, S2.i). case V_MAX3_U32 : // = D.u = max(S0.u, S1.u, S2.u). case V_MED3_F32 : // = D.f = median(S0.f, S1.f, S2.f). case V_MED3_I32 : // = D.i = median(S0.i, S1.i, S2.i). case V_MED3_U32 : // = D.u = median(S0.u, S1.u, S2.u). case V_SAD_U8 : // = D.u = Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_SAD_HI_U8 : // = D.u = Byte SAD with accum_hi(S0.u, S1.u, S2.u). case V_SAD_U16 : // = D.u = Word SAD with accum(S0.u, S1.u, S2.u). case V_SAD_U32 : // = D.u = Dword SAD with accum(S0.u, S1.u, S2.u). case V_CVT_PK_U8_F32 : // = f32->u8(s0.f), pack into byte(s1.u), of dword(s2). case V_DIV_FIXUP_F32 : // = D.f = Special case divide fixup and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). return 1; case V_DIV_SCALE_F64 : // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. case V_DIV_FIXUP_F64 : // = D.d = Special case divide fixup and flags(s0.d = Quotient, s1.d = Denominator, s2.d = Numerator). case V_FMA_F64 : // = D.d = S0.d * S1.d + S2.d. case V_LSHL_B64 : // = D = S0.u << S1.u[4:0]. case V_LSHR_B64 : // = D = S0.u >> S1.u[4:0]. case V_ASHR_I64 : // = D = S0.u >> S1.u[4:0]. case V_ADD_F64 : // = D.d = S0.d + S1.d. case V_MUL_F64 : // = D.d = S0.d * S1.d. case V_MIN_F64 : // = D.d = min(S0.d, S1.d). case V_MAX_F64 : // = D.d = max(S0.d, S1.d). case V_LDEXP_F64 : // = D.d = pow(S0.d, S1.i[31:0]). case V_DIV_FMAS_F64 : // = D.d = Special case divide FMA with scale and flags(s0.d= Quotient, s1.d = Denominator, s2.d = Numerator). case V_TRIG_PREOP_F64 : // = D.d = Look Up 2/PI (S0.d) with segment select S1.u[4:0]. return 2; case V_MUL_LO_U32 : // = D.u = S0.u * S1.u. case V_MUL_HI_U32 : // = D.u = (S0.u * S1.u)>>32. case V_MUL_LO_I32 : // = D.i = S0.i * S1.i. case V_MUL_HI_I32 : // = D.i = (S0.i * S1.i)>>32. case V_DIV_FMAS_F32 : // = D.f = Special case divide FMA with scale and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_MSAD_U8 : // = D.u = Masked Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_QSAD_U8 : // = D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0],S1.u[31:0], S2.u[63:0]). case V_QSAD_PK_U16_U8 : // : D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_PK_U16_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U32_U8 : // : D.u128 = Masked Quad-Byte SAD with 32-bit accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[127:0]). case V_MAD_U64_U32 : // : {vcc_out,D.u64} = S0.u32 * S1.u32 + S2.u64. case V_MAD_I64_I32 : // : {vcc_out,D.i64} = S0.i32 * S1.i32 + S2.i64. return 1; case V_INTERP_P1_F32 : case V_INTERP_P2_F32 : case V_INTERP_MOV_F32 : case V_INTERP_P1LL_F16: case V_INTERP_P1LV_F16: case V_INTERP_P2_F16 : return 1; } } uint GetSrc1WidthInDWORDs(VectorInstructions e) { switch(e) { default: return 0; // VOP2 case V_ADD_U32: case V_SUB_U32: case V_SUBREV_U32: return 1; case V_LSHLREV_B64 : case V_LSHRREV_B64 : case V_ASHRREV_I64 : return 2; case V_MAD_F16 : case V_MAD_U16 : case V_MAD_I16 : case V_PERM_B32 : case V_FMA_F16 : case V_DIV_FIXUP_F16 : case V_ADD_F16 : case V_SUB_F16 : case V_SUBREV_F16 : case V_MUL_F16 : case V_MAC_F16 : case V_MADMK_F16 : case V_MADAK_F16 : case V_ADD_U16 : case V_SUB_U16 : case V_SUBREV_U16 : case V_MUL_LO_U16 : case V_LSHLREV_B16 : case V_LSHRREV_B16 : case V_ASHRREV_I16 : case V_MAX_F16 : case V_MIN_F16 : case V_MAX_U16 : case V_MAX_I16 : case V_MIN_U16 : case V_MIN_I16 : case V_LDEXP_F16 : case V_CNDMASK_B32 : case V_READLANE_B32 : case V_WRITELANE_B32 : case V_ADD_F32 : case V_SUB_F32 : case V_SUBREV_F32 : case V_MAC_LEGACY_F32 : case V_MUL_LEGACY_F32 : case V_MUL_F32 : case V_MUL_I32_I24 : case V_MUL_HI_I32_I24 : case V_MUL_U32_U24 : case V_MUL_HI_U32_U24 : case V_MIN_LEGACY_F32 : case V_MAX_LEGACY_F32 : case V_MIN_F32 : case V_MAX_F32 : case V_MIN_I32 : case V_MAX_I32 : case V_MIN_U32 : case V_MAX_U32 : case V_LSHR_B32 : case V_LSHRREV_B32 : case V_ASHR_I32 : case V_ASHRREV_I32 : case V_LSHL_B32 : case V_LSHLREV_B32 : case V_AND_B32 : case V_OR_B32 : case V_XOR_B32 : case V_BFM_B32 : case V_MAC_F32 : case V_MADMK_F32 : case V_MADAK_F32 : case V_BCNT_U32_B32 : case V_MBCNT_LO_U32_B32 : case V_MBCNT_HI_U32_B32 : case V_ADD_I32 : case V_SUB_I32 : case V_SUBREV_I32 : case V_ADDC_U32 : case V_SUBB_U32 : case V_SUBBREV_U32 : case V_LDEXP_F32 : case V_CVT_PKACCUM_U8_F32 : case V_CVT_PKNORM_I16_F32 : case V_CVT_PKNORM_U16_F32 : case V_CVT_PKRTZ_F16_F32 : case V_CVT_PK_U16_U32 : case V_CVT_PK_I16_I32 : return 1; // VOPC case V_CMP_CLASS_F16: case V_CMPX_CLASS_F16: case V_CMP_F_F16 : case V_CMP_LT_F16 : case V_CMP_EQ_F16 : case V_CMP_LE_F16 : case V_CMP_GT_F16 : case V_CMP_LG_F16 : case V_CMP_GE_F16 : case V_CMP_O_F16 : case V_CMP_U_F16 : case V_CMP_NGE_F16 : case V_CMP_NLG_F16 : case V_CMP_NGT_F16 : case V_CMP_NLE_F16 : case V_CMP_NEQ_F16 : case V_CMP_NLT_F16 : case V_CMP_TRU_F16 : case V_CMPX_F_F16 : case V_CMPX_LT_F16 : case V_CMPX_EQ_F16 : case V_CMPX_LE_F16 : case V_CMPX_GT_F16 : case V_CMPX_LG_F16 : case V_CMPX_GE_F16 : case V_CMPX_O_F16 : case V_CMPX_U_F16 : case V_CMPX_NGE_F16 : case V_CMPX_NLG_F16 : case V_CMPX_NGT_F16 : case V_CMPX_NLE_F16 : case V_CMPX_NEQ_F16 : case V_CMPX_NLT_F16 : case V_CMPX_TRU_F16 : case V_CMP_F_U16 : case V_CMP_LT_U16 : case V_CMP_EQ_U16 : case V_CMP_LE_U16 : case V_CMP_GT_U16 : case V_CMP_LG_U16 : case V_CMP_GE_U16 : case V_CMP_TRU_U16 : case V_CMPx_F_U16 : case V_CMPx_LT_U16 : case V_CMPx_EQ_U16 : case V_CMPx_LE_U16 : case V_CMPx_GT_U16 : case V_CMPx_LG_U16 : case V_CMPx_GE_U16 : case V_CMPx_TRU_U16 : case V_CMP_F_I16 : case V_CMP_LT_I16 : case V_CMP_EQ_I16 : case V_CMP_LE_I16 : case V_CMP_GT_I16 : case V_CMP_LG_I16 : case V_CMP_GE_I16 : case V_CMP_TRU_I16 : case V_CMPx_F_I16 : case V_CMPx_LT_I16 : case V_CMPx_EQ_I16 : case V_CMPx_LE_I16 : case V_CMPx_GT_I16 : case V_CMPx_LG_I16 : case V_CMPx_GE_I16 : case V_CMPx_TRU_I16 : case V_CMP_F_F32 : case V_CMP_LT_F32 : case V_CMP_EQ_F32 : case V_CMP_LE_F32 : case V_CMP_GT_F32 : case V_CMP_LG_F32 : case V_CMP_GE_F32 : case V_CMP_O_F32 : case V_CMP_U_F32 : case V_CMP_NGE_F32 : case V_CMP_NLG_F32 : case V_CMP_NGT_F32 : case V_CMP_NLE_F32 : case V_CMP_NEQ_F32 : case V_CMP_NLT_F32 : case V_CMP_TRU_F32 : case V_CMPX_F_F32 : case V_CMPX_LT_F32 : case V_CMPX_EQ_F32 : case V_CMPX_LE_F32 : case V_CMPX_GT_F32 : case V_CMPX_LG_F32 : case V_CMPX_GE_F32 : case V_CMPX_O_F32 : case V_CMPX_U_F32 : case V_CMPX_NGE_F32 : case V_CMPX_NLG_F32 : case V_CMPX_NGT_F32 : case V_CMPX_NLE_F32 : case V_CMPX_NEQ_F32 : case V_CMPX_NLT_F32 : case V_CMPX_TRU_F32 : return 1; case V_CMP_F_F64 : case V_CMP_LT_F64 : case V_CMP_EQ_F64 : case V_CMP_LE_F64 : case V_CMP_GT_F64 : case V_CMP_LG_F64 : case V_CMP_GE_F64 : case V_CMP_O_F64 : case V_CMP_U_F64 : case V_CMP_NGE_F64 : case V_CMP_NLG_F64 : case V_CMP_NGT_F64 : case V_CMP_NLE_F64 : case V_CMP_NEQ_F64 : case V_CMP_NLT_F64 : case V_CMP_TRU_F64 : case V_CMPX_F_F64 : case V_CMPX_LT_F64 : case V_CMPX_EQ_F64 : case V_CMPX_LE_F64 : case V_CMPX_GT_F64 : case V_CMPX_LG_F64 : case V_CMPX_GE_F64 : case V_CMPX_O_F64 : case V_CMPX_U_F64 : case V_CMPX_NGE_F64 : case V_CMPX_NLG_F64 : case V_CMPX_NGT_F64 : case V_CMPX_NLE_F64 : case V_CMPX_NEQ_F64 : case V_CMPX_NLT_F64 : case V_CMPX_TRU_F64 : return 2; case V_CMPS_F_F32 : case V_CMPS_LT_F32 : case V_CMPS_EQ_F32 : case V_CMPS_LE_F32 : case V_CMPS_GT_F32 : case V_CMPS_LG_F32 : case V_CMPS_GE_F32 : case V_CMPS_O_F32 : case V_CMPS_U_F32 : case V_CMPS_NGE_F32 : case V_CMPS_NLG_F32 : case V_CMPS_NGT_F32 : case V_CMPS_NLE_F32 : case V_CMPS_NEQ_F32 : case V_CMPS_NLT_F32 : case V_CMPS_TRU_F32 : case V_CMPSX_F_F32 : case V_CMPSX_LT_F32 : case V_CMPSX_EQ_F32 : case V_CMPSX_LE_F32 : case V_CMPSX_GT_F32 : case V_CMPSX_LG_F32 : case V_CMPSX_GE_F32 : case V_CMPSX_O_F32 : case V_CMPSX_U_F32 : case V_CMPSX_NGE_F32 : case V_CMPSX_NLG_F32 : case V_CMPSX_NGT_F32 : case V_CMPSX_NLE_F32 : case V_CMPSX_NEQ_F32 : case V_CMPSX_NLT_F32 : case V_CMPSX_TRU_F32 : return 1; case V_CMPS_F_F64 : case V_CMPS_LT_F64 : case V_CMPS_EQ_F64 : case V_CMPS_LE_F64 : case V_CMPS_GT_F64 : case V_CMPS_LG_F64 : case V_CMPS_GE_F64 : case V_CMPS_O_F64 : case V_CMPS_U_F64 : case V_CMPS_NGE_F64 : case V_CMPS_NLG_F64 : case V_CMPS_NGT_F64 : case V_CMPS_NLE_F64 : case V_CMPS_NEQ_F64 : case V_CMPS_NLT_F64 : case V_CMPS_TRU_F64 : case V_CMPSX_F_F64 : case V_CMPSX_LT_F64 : case V_CMPSX_EQ_F64 : case V_CMPSX_LE_F64 : case V_CMPSX_GT_F64 : case V_CMPSX_LG_F64 : case V_CMPSX_GE_F64 : case V_CMPSX_O_F64 : case V_CMPSX_U_F64 : case V_CMPSX_NGE_F64 : case V_CMPSX_NLG_F64 : case V_CMPSX_NGT_F64 : case V_CMPSX_NLE_F64 : case V_CMPSX_NEQ_F64 : case V_CMPSX_NLT_F64 : case V_CMPSX_TRU_F64 : return 2; case V_CMP_F_I32 : case V_CMP_LT_I32 : case V_CMP_EQ_I32 : case V_CMP_LE_I32 : case V_CMP_GT_I32 : case V_CMP_LG_I32 : case V_CMP_GE_I32 : case V_CMP_TRU_I32 : case V_CMPX_F_I32 : case V_CMPX_LT_I32 : case V_CMPX_EQ_I32 : case V_CMPX_LE_I32 : case V_CMPX_GT_I32 : case V_CMPX_LG_I32 : case V_CMPX_GE_I32 : case V_CMPX_TRU_I32 : return 1; case V_CMP_F_I64 : case V_CMP_LT_I64 : case V_CMP_EQ_I64 : case V_CMP_LE_I64 : case V_CMP_GT_I64 : case V_CMP_LG_I64 : case V_CMP_GE_I64 : case V_CMP_TRU_I64 : case V_CMPX_F_I64 : case V_CMPX_LT_I64 : case V_CMPX_EQ_I64 : case V_CMPX_LE_I64 : case V_CMPX_GT_I64 : case V_CMPX_LG_I64 : case V_CMPX_GE_I64 : case V_CMPX_TRU_I64 : return 2; case V_CMP_F_U32 : case V_CMP_LT_U32 : case V_CMP_EQ_U32 : case V_CMP_LE_U32 : case V_CMP_GT_U32 : case V_CMP_LG_U32 : case V_CMP_GE_U32 : case V_CMP_TRU_U32 : case V_CMPX_F_U32 : case V_CMPX_LT_U32 : case V_CMPX_EQ_U32 : case V_CMPX_LE_U32 : case V_CMPX_GT_U32 : case V_CMPX_LG_U32 : case V_CMPX_GE_U32 : case V_CMPX_TRU_U32 : return 1; case V_CMP_F_U64 : case V_CMP_LT_U64 : case V_CMP_EQ_U64 : case V_CMP_LE_U64 : case V_CMP_GT_U64 : case V_CMP_LG_U64 : case V_CMP_GE_U64 : case V_CMP_TRU_U64 : case V_CMPx_F_U64 : case V_CMPx_LT_U64 : case V_CMPx_EQ_U64 : case V_CMPx_LE_U64 : case V_CMPx_GT_U64 : case V_CMPx_LG_U64 : case V_CMPx_GE_U64 : case V_CMPx_TRU_U64 : case V_CMP_CLASS_F64 : case V_CMPX_CLASS_F64 : return 2; case V_CMP_CLASS_F32 : case V_CMPX_CLASS_F32 : return 1; case V_DIV_SCALE_F32 : // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. case V_MAD_LEGACY_F32 : // = D.f = S0.f * S1.f + S2.f (DX9 rules, 0.0*x = 0.0). case V_MAD_F32 : // = D.f = S0.f * S1.f + S2.f. case V_MAD_I32_I24 : // = D.i = S0.i * S1.i + S2.iD.i = S0.i * S1.i + S2.i. case V_MAD_U32_U24 : // = D.u = S0.u * S1.u + S2.u. case V_CUBEID_F32 : // = Rm.w <- Rn,x, Rn,y, Rn.z. case V_CUBESC_F32 : // = Rm.y <- Rn,x, Rn,y, Rn.z. case V_CUBETC_F32 : // = Rm.x <- Rn,x, Rn,y, Rn.z. case V_CUBEMA_F32 : // = Rm.z <- Rn,x, Rn,y, Rn.z case V_BFE_U32 : // = D.u = (S0.u>>S1.u[4:0]) & ((1<>S1.u[4:0]) & ((1<> 1) << 24 + case V_ALIGNBIT_B32 : // = D.u = ({S0,S1} >> S2.u[4:0]) & 0xFFFFFFFF. case V_ALIGNBYTE_B32 : // = D.u = ({S0,S1} >> (8*S2.u[4:0])) & 0xFFFFFFFF. case V_MULLIT_F32 : // = D.f = S0.f * S1.f, replicate result into 4 components (0.0 * x = 0.0; special INF, NaN, overflow rules). case V_MIN3_F32 : // = D.f = min(S0.f, S1.f, S2.f). case V_MIN3_I32 : // = D.i = min(S0.i, S1.i, S2.i). case V_MIN3_U32 : // = 0x153 D.u = min(S0.u, S1.u, S2.u). case V_MAX3_F32 : // = D.f = max(S0.f, S1.f, S2.f). case V_MAX3_I32 : // = D.i = max(S0.i, S1.i, S2.i). case V_MAX3_U32 : // = D.u = max(S0.u, S1.u, S2.u). case V_MED3_F32 : // = D.f = median(S0.f, S1.f, S2.f). case V_MED3_I32 : // = D.i = median(S0.i, S1.i, S2.i). case V_MED3_U32 : // = D.u = median(S0.u, S1.u, S2.u). case V_SAD_U8 : // = D.u = Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_SAD_HI_U8 : // = D.u = Byte SAD with accum_hi(S0.u, S1.u, S2.u). case V_SAD_U16 : // = D.u = Word SAD with accum(S0.u, S1.u, S2.u). case V_SAD_U32 : // = D.u = Dword SAD with accum(S0.u, S1.u, S2.u). case V_CVT_PK_U8_F32 : // = f32->u8(s0.f), pack into byte(s1.u), of dword(s2). case V_DIV_FIXUP_F32 : // = D.f = Special case divide fixup and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_LSHL_B64 : // = D = S0.u << S1.u[4:0]. case V_LSHR_B64 : // = D = S0.u >> S1.u[4:0]. case V_ASHR_I64 : // = D = S0.u >> S1.u[4:0]. case V_LDEXP_F64 : // = D.d = pow(S0.d, S1.i[31:0]). return 1; case V_FMA_F64 : // = D.d = S0.d * S1.d + S2.d. case V_DIV_SCALE_F64 : // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. case V_DIV_FIXUP_F64 : // = D.d = Special case divide fixup and flags(s0.d = Quotient, s1.d = Denominator, s2.d = Numerator). case V_ADD_F64 : // = D.d = S0.d + S1.d. case V_MUL_F64 : // = D.d = S0.d * S1.d. case V_MIN_F64 : // = D.d = min(S0.d, S1.d). case V_MAX_F64 : // = D.d = max(S0.d, S1.d). case V_DIV_FMAS_F64 : // = D.d = Special case divide FMA with scale and flags(s0.d= Quotient, s1.d = Denominator, s2.d = Numerator). case V_TRIG_PREOP_F64 : // = D.d = Look Up 2/PI (S0.d) with segment select S1.u[4:0]. return 2; case V_MUL_LO_U32 : // = D.u = S0.u * S1.u. case V_MUL_HI_U32 : // = D.u = (S0.u * S1.u)>>32. case V_MUL_LO_I32 : // = D.i = S0.i * S1.i. case V_MUL_HI_I32 : // = D.i = (S0.i * S1.i)>>32. case V_DIV_FMAS_F32 : // = D.f = Special case divide FMA with scale and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_MSAD_U8 : // = D.u = Masked Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_QSAD_U8 : // = D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0],S1.u[31:0], S2.u[63:0]). case V_QSAD_PK_U16_U8 : // : D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_PK_U16_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U32_U8 : // : D.u128 = Masked Quad-Byte SAD with 32-bit accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[127:0]). case V_MAD_U64_U32 : // : {vcc_out,D.u64} = S0.u32 * S1.u32 + S2.u64. case V_MAD_I64_I32 : // : {vcc_out,D.i64} = S0.i32 * S1.i32 + S2.i64. return 1; } } uint GetSrc2WidthInDWORDs( VectorInstructions e ) { switch(e) { default: return 0; case V_DIV_SCALE_F32 : // = D.f = Special case divide preop and flags(s0.f = Quotient,s1.f = Denominator, s2.f = Numerator) s0 must equal s1 or s2. case V_MAD_LEGACY_F32 : // = D.f = S0.f * S1.f + S2.f (DX9 rules, 0.0*x = 0.0). case V_MAD_F32 : // = D.f = S0.f * S1.f + S2.f. case V_MAD_I32_I24 : // = D.i = S0.i * S1.i + S2.iD.i = S0.i * S1.i + S2.i. case V_MAD_U32_U24 : // = D.u = S0.u * S1.u + S2.u. case V_CUBEID_F32 : // = Rm.w <- Rn,x, Rn,y, Rn.z. case V_CUBESC_F32 : // = Rm.y <- Rn,x, Rn,y, Rn.z. case V_CUBETC_F32 : // = Rm.x <- Rn,x, Rn,y, Rn.z. case V_CUBEMA_F32 : // = Rm.z <- Rn,x, Rn,y, Rn.z case V_BFE_U32 : // = D.u = (S0.u>>S1.u[4:0]) & ((1<>S1.u[4:0]) & ((1<> 1) << 24 + case V_ALIGNBIT_B32 : // = D.u = ({S0,S1} >> S2.u[4:0]) & 0xFFFFFFFF. case V_ALIGNBYTE_B32 : // = D.u = ({S0,S1} >> (8*S2.u[4:0])) & 0xFFFFFFFF. case V_MIN3_F32 : // = D.f = min(S0.f, S1.f, S2.f). case V_MIN3_I32 : // = D.i = min(S0.i, S1.i, S2.i). case V_MIN3_U32 : // = 0x153 D.u = min(S0.u, S1.u, S2.u). case V_MAX3_F32 : // = D.f = max(S0.f, S1.f, S2.f). case V_MAX3_I32 : // = D.i = max(S0.i, S1.i, S2.i). case V_MAX3_U32 : // = D.u = max(S0.u, S1.u, S2.u). case V_MED3_F32 : // = D.f = median(S0.f, S1.f, S2.f). case V_MED3_I32 : // = D.i = median(S0.i, S1.i, S2.i). case V_MED3_U32 : // = D.u = median(S0.u, S1.u, S2.u). case V_SAD_U8 : // = D.u = Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_SAD_HI_U8 : // = D.u = Byte SAD with accum_hi(S0.u, S1.u, S2.u). case V_SAD_U16 : // = D.u = Word SAD with accum(S0.u, S1.u, S2.u). case V_SAD_U32 : // = D.u = Dword SAD with accum(S0.u, S1.u, S2.u). case V_CVT_PK_U8_F32 : // = f32->u8(s0.f), pack into byte(s1.u), of dword(s2). case V_DIV_FIXUP_F32 : // = D.f = Special case divide fixup and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). return 1; case V_FMA_F64 : // = D.d = S0.d * S1.d + S2.d. case V_DIV_SCALE_F64 : // = D.d = Special case divide preop and flags(s0.d = Quotient,s1.d = Denominator, s2.d = Numerator) s0 must equal s1 or s2. case V_DIV_FIXUP_F64 : // = D.d = Special case divide fixup and flags(s0.d = Quotient, s1.d = Denominator, s2.d = Numerator). case V_DIV_FMAS_F64 : // = D.d = Special case divide FMA with scale and flags(s0.d= Quotient, s1.d = Denominator, s2.d = Numerator). case V_TRIG_PREOP_F64 : // = D.d = Look Up 2/PI (S0.d) with segment select S1.u[4:0]. case V_MAD_U64_U32 : // : {vcc_out,D.u64} = S0.u32 * S1.u32 + S2.u64. case V_MAD_I64_I32 : // : {vcc_out,D.i64} = S0.i32 * S1.i32 + S2.i64. return 2; case V_MUL_LO_U32 : // = D.u = S0.u * S1.u. case V_MUL_HI_U32 : // = D.u = (S0.u * S1.u)>>32. case V_MUL_LO_I32 : // = D.i = S0.i * S1.i. case V_MUL_HI_I32 : // = D.i = (S0.i * S1.i)>>32. case V_DIV_FMAS_F32 : // = D.f = Special case divide FMA with scale and flags(s0.f = Quotient, s1.f = Denominator, s2.f = Numerator). case V_MSAD_U8 : // = D.u = Masked Byte SAD with accum_lo(S0.u, S1.u, S2.u). case V_QSAD_U8 : // = D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0],S1.u[31:0], S2.u[63:0]). case V_QSAD_PK_U16_U8 : // : D.u = Quad-Byte SAD with accum_lo/hiu(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_PK_U16_U8 : // = D.u = Masked Quad-Byte SAD with accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[63:0]). case V_MQSAD_U32_U8 : // : D.u128 = Masked Quad-Byte SAD with 32-bit accum_lo/hi(S0.u[63:0], S1.u[31:0], S2.u[127:0]). return 1; } } uint GetDataWidthInDWORDs( DSInstructions eOp ) { switch( eOp ) { default: return 0; case DS_PERMUTE_B32: case DS_BPERMUTE_B32: case DS_ADD_U32 : case DS_ADD_F32 : case DS_SUB_U32 : case DS_RSUB_U32 : case DS_INC_U32 : case DS_DEC_U32 : case DS_MIN_I32 : case DS_MAX_I32 : case DS_MIN_U32 : case DS_MAX_U32 : case DS_AND_B32 : case DS_OR_B32 : case DS_XOR_B32 : case DS_MSKOR_B32 : case DS_WRITE_B32 : case DS_WRITE2_B32 : case DS_WRITE2ST64_B32 : case DS_CMPST_B32 : case DS_CMPST_F32 : case DS_MIN_F32 : case DS_MAX_F32 : case DS_WRITE_B8 : case DS_WRITE_B16 : case DS_ADD_RTN_U32 : case DS_SUB_RTN_U32 : case DS_RSUB_RTN_U32 : case DS_INC_RTN_U32 : case DS_DEC_RTN_U32 : case DS_MIN_RTN_I32 : case DS_MAX_RTN_I32 : case DS_MIN_RTN_U32 : case DS_MAX_RTN_U32 : case DS_AND_RTN_B32 : case DS_OR_RTN_B32 : case DS_XOR_RTN_B32 : case DS_MSKOR_RTN_B32 : case DS_WRXCHG_RTN_B32 : case DS_WRXCHG2_RTN_B32 : case DS_WRXCHG2ST64_RTN_B32 : case DS_CMPST_RTN_B32 : case DS_CMPST_RTN_F32 : case DS_MIN_RTN_F32 : case DS_MAX_RTN_F32 : case DS_WRAP_RTN_B32 : case DS_SWIZZLE_B32 : case DS_READ_B32 : case DS_READ2_B32 : case DS_READ2ST64_B32 : case DS_READ_I8 : case DS_READ_U8 : case DS_READ_I16 : case DS_READ_U16 : case DS_CONSUME : case DS_APPEND : case DS_ORDERED_COUNT : return 1; case DS_ADD_U64 : case DS_SUB_U64 : case DS_RSUB_U64 : case DS_INC_U64 : case DS_DEC_U64 : case DS_MIN_I64 : case DS_MAX_I64 : case DS_MIN_U64 : case DS_MAX_U64 : case DS_AND_B64 : case DS_OR_B64 : case DS_XOR_B64 : case DS_MSKOR_B64 : case DS_WRITE_B64 : case DS_WRITE2_B64 : case DS_WRITE2ST64_B64 : case DS_CMPST_B64 : case DS_CMPST_F64 : case DS_MIN_F64 : case DS_MAX_F64 : case DS_ADD_RTN_U64 : case DS_SUB_RTN_U64 : case DS_RSUB_RTN_U64 : case DS_INC_RTN_U64 : case DS_DEC_RTN_U64 : case DS_MIN_RTN_I64 : case DS_MAX_RTN_I64 : case DS_MIN_RTN_U64 : case DS_MAX_RTN_U64 : case DS_AND_RTN_B64 : case DS_OR_RTN_B64 : case DS_XOR_RTN_B64 : case DS_MSKOR_RTN_B64 : case DS_WRXCHG_RTN_B64 : case DS_WRXCHG2_RTN_B64 : case DS_WRXCHG2ST64_RTN_B64 : case DS_CMPST_RTN_B64 : case DS_CMPST_RTN_F64 : case DS_MIN_RTN_F64 : case DS_MAX_RTN_F64 : case DS_READ_B64 : case DS_READ2_B64 : case DS_READ2ST64_B64 : case DS_CONDXCHG32_RTN_B64 : return 2; case DS_ADD_SRC2_U32 : case DS_SUB_SRC2_U32 : case DS_RSUB_SRC2_U32 : case DS_INC_SRC2_U32 : case DS_DEC_SRC2_U32 : case DS_MIN_SRC2_I32 : case DS_MAX_SRC2_I32 : case DS_MIN_SRC2_U32 : case DS_MAX_SRC2_U32 : case DS_AND_SRC2_B32 : case DS_OR_SRC2_B32 : case DS_XOR_SRC2_B32 : case DS_WRITE_SRC2_B32 : case DS_MIN_SRC2_F32 : case DS_MAX_SRC2_F32 : return 1; case DS_ADD_SRC2_U64 : case DS_SUB_SRC2_U64 : case DS_RSUB_SRC2_U64 : case DS_INC_SRC2_U64 : case DS_DEC_SRC2_U64 : case DS_MIN_SRC2_I64 : case DS_MAX_SRC2_I64 : case DS_MIN_SRC2_U64 : case DS_MAX_SRC2_U64 : case DS_AND_SRC2_B64 : case DS_OR_SRC2_B64 : case DS_XOR_SRC2_B64 : case DS_WRITE_SRC2_B64 : case DS_MIN_SRC2_F64 : case DS_MAX_SRC2_F64 : return 2; case DS_WRITE_B96 : case DS_READ_B96 : return 3; case DS_WRITE_B128 : case DS_CONDXCHG32_RTN_B128 : case DS_READ_B128 : return 4; } } uint ScalarInstruction::GetResultWidthInDWORDs() const { switch( GetOpcode() ) { default: return 0; case S_ADD_U32 : //: D.u = S0.u + S1.u. SCC = carry out. case S_SUB_U32 : //: D.u = S0.u - S1.u. SCC = carry out. case S_ADD_I32 : //: D.u = S0.i + S1.i. SCC = overflow. case S_SUB_I32 : //: D.u = S0.i - S1.i. SCC = overflow. case S_ADDC_U32 : //: D.u = S0.u + S1.u + SCC. SCC = carry-out. case S_SUBB_U32 : //: D.u = S0.u - S1.u - SCC. SCC = carry-out. case S_MIN_I32 : //: D.i = (S0.i < S1.i) ? S0.i : S1.i. SCC = 1 if S0 is min. case S_MIN_U32 : //: D.u = (S0.u < S1.u) ? S0.u : S1.u. SCC = 1 if S0 is min. case S_MAX_I32 : //: D.i = (S0.i > S1.i) ? S0.i : S1.i. SCC = 1 if S0 is max. case S_MAX_U32 : //: D.u = (S0.u > S1.u) ? S0.u : S1.u. SCC = 1 if S0 is max. case S_CSELECT_B32 : //: D.u = SCC ? S0.u : S1.u. case S_AND_B32 : //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. case S_OR_B32 : //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. case S_XOR_B32 : //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. case S_ANDN2_B32 : //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. case S_ORN2_B32 : //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. case S_NAND_B32 : //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. case S_NOR_B32 : //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. case S_XNOR_B32 : //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. case S_LSHL_B32 : //: D.u = S0.u << S1.u[4:0]. SCC = 1 if result is non-zero. case S_LSHR_B32 : //: D.u = S0.u >> S1.u[4:0]. SCC = 1 if result is non-zero. case S_ASHR_I32 : //: D.i = signtext(S0.i) >> S1.i[4:0]. SCC = 1 if result is non-zero. case S_BFM_B32 : //: D.u = ((1 << S0.u[4:0]) - 1) << S1.u[4:0]; bitfield mask. case S_MUL_I32 : //: D.i = S0.i * S1.i. case S_BFE_U32 : // : Bit field extract. S0 is data, S1[4:0] is field offset, S1[22:16] is field width. D.u = (S0.u >> S1.u[4:0]) & ((1 << S1.u[22:16]) - 1). SCC = 1 if resultis non-zero. case S_BFE_I32 : case S_ABSDIFF_I32 : // D.i = abs(S0.i >> S1.i). SCC = 1 if result is non-zero. case S_MOVK_I32 : //: D.i = signext(SIMM16). case S_CMOVK_I32 : //: if (SCC) D.i = signext(SIMM16); else NOP. case S_CMPK_EQ_I32 : //: SCC = (D.i == signext(SIMM16). case S_CMPK_LG_I32 : //: SCC = (D.i != signext(SIMM16). case S_CMPK_GT_I32 : //: SCC = (D.i != signext(SIMM16)). case S_CMPK_GE_I32 : //: SCC = (D.i >= signext(SIMM16)). case S_CMPK_LT_I32 : //: SCC = (D.i < signext(SIMM16)). case S_CMPK_LE_I32 : //: SCC = (D.i <= signext(SIMM16)). case S_CMPK_EQ_U32 : //: SCC = (D.u == SIMM16). case S_CMPK_LG_U32 : //: SCC = (D.u != SIMM16). case S_CMPK_GT_U32 : //: SCC = (D.u > SIMM16). case S_CMPK_GE_U32 : //: SCC = (D.u >= SIMM16). case S_CMPK_LT_U32 : //: SCC = (D.u < SIMM16). case S_CMPK_LE_U32 : //: D.u = SCC = (D.u <= SIMM16). case S_ADDK_I32 : //: D.i = D.i + signext(SIMM16). SCC = overflow. case S_MULK_I32 : //: D.i = D.i * signext(SIMM16). SCC = overflow. case S_GETREG_B32 : // : D.u = hardware register. Read some or all of a hardware register case S_MOV_B32 ://: D.u = S0.u. case S_CMOV_B32 ://: if(SCC) D.u = S0.u; else NOP. case S_NOT_B32 ://: D.u = ~S0.u SCC = 1 if result non-zero. case S_WQM_B32 ://: D.u = WholeQuadMode(S0.u). SCC = 1 if result is non-zero. case S_BREV_B32 ://: D.u = S0.u[0:31] (reverse bits). case S_BCNT0_I32_B32 ://: D.i = CountZeroBits(S0.u). SCC = 1 if result is non-zero. case S_BCNT0_I32_B64 ://: D.i = CountZeroBits(S0.u). SCC = 1 if result is non-zero. case S_BCNT1_I32_B32 ://: D.i = CountOneBits(S0.u). SCC = 1 if result is non-zero. case S_BCNT1_I32_B64 ://: D.i = CountOneBits(S0.u). SCC = 1 if result is non-zero. case S_FF0_I32_B32 ://: D.i = FindFirstZero(S0.u) from LSB; if no zeros, return -1. case S_FF0_I32_B64 ://: D.i = FindFirstZero(S0.u) from LSB; if no zeros, return -1. case S_FF1_I32_B32 ://: D.i = FindFirstOne(S0.u) from LSB; if no ones, return -1. case S_FF1_I32_B64 ://: D.i = FindFirstOne(S0.u) from LSB; if no ones, return -1. case S_FLBIT_I32_B32 ://: D.i = FindFirstOne(S0.u) from MSB; if no ones, return -1. case S_FLBIT_I32_B64 ://: D.i = FindFirstOne(S0.u) from MSB; if no ones, return -1. case S_FLBIT_I32 ://: D.i = Find first bit opposite of sign bit from MSB. If S0 == -1, return -1. case S_FLBIT_I32_I64 ://: D.i = Find first bit opposite of sign bit from MSB. If S0 == -1, return -1. case S_SEXT_I32_I8 ://: D.i = signext(S0.i[7:0]). case S_SEXT_I32_I16 ://: D.i = signext(S0.i[15:0]). case S_BITSET0_B32 ://: D.u[S0.u[4:0]] = 0. case S_BITSET1_B32 ://: D.u[S0.u[4:0]] = 1. case S_QUADMASK_B32 ://: D.u = QuadMask(S0.u). D[0] = OR(S0[3:0]), D[1] = OR(S0[7:4]) .... SCC = 1 if result is non-zero. case S_MOVRELS_B32 ://: SGPR[D.u] = SGPR[S0.u + M0.u]. case S_MOVRELD_B32 ://: SGPR[D.u + M0.u] = SGPR[S0.u]. case S_ABS_I32 : //: D.i = abs(S0.i). SCC=1 if result is non-zero. case S_MOV_FED_B32 : //: D.u = S0.u, introduce edc double error upon write to dest sgpr. case S_CMP_EQ_I32 : //: SCC = (S0.i == S1.i). case S_CMP_LG_I32 : //: SCC = (S0.i != S1.i). case S_CMP_GT_I32 : //: SCC = (S0.i > S1.i). case S_CMP_GE_I32 : //: SCC = (S0.i >= S1.i). case S_CMP_LT_I32 : //: SCC = (S0.i < S1.i). case S_CMP_LE_I32 : //: SCC = (S0.i <= S1.i). case S_CMP_EQ_U32 : //: SCC = (S0.u == S1.u). case S_CMP_LG_U32 : //: SCC = (S0.u != S1.u). case S_CMP_GT_U32 : //: SCC = (S0.u > S1.u). case S_CMP_GE_U32 : //: SCC = (S0.u >= S1.u). case S_CMP_LT_U32 : //: SCC = (S0.u < S1.u). case S_CMP_LE_U32 : //: SCC = (S0.u <= S1.u). case S_BITCMP0_B32 : //: SCC = (S0.u[S1.u[4:0]] == 0). case S_BITCMP1_B32 : //: SCC = (S0.u[S1.u[4:0]] == 1). case S_BITCMP0_B64 : //: SCC = (S0.u[S1.u[5:0]] == 0). case S_BITCMP1_B64 : //: SCC = (S0.u[S1.u[5:0]] == 1). case S_SETVSKIP : //: VSKIP = S0.u[S1.u[4:0]]. case S_CMP_EQ_U64: case S_CMP_NE_U64: return 1; case S_AND_B64 : //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. case S_OR_B64 : //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. case S_XOR_B64 : //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. case S_ANDN2_B64 : //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. case S_ORN2_B64 : //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. case S_NAND_B64 : //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. case S_NOR_B64 : //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. case S_XNOR_B64 : //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. case S_LSHL_B64 : //: D.u = S0.u << S1.u[5:0]. SCC = 1 if result is non-zero. case S_LSHR_B64 : //: D.u = S0.u >> S1.u[5:0]. SCC = 1 if result is non-zero. case S_ASHR_I64 : //: D.i = signtext(S0.i) >> S1.i[5:0]. SCC = 1 if result is non-zero. case S_BFM_B64 : //: D.u = ((1 << S0.u[5:0]) - 1) << S1.u[5:0]; bitfield mask. case S_BFE_U64 : case S_BFE_I64 : case S_MOV_B64 ://: D/u = S0.u. case S_CMOV_B64 ://: if(SCC) D.u = S0.u; else NOP. case S_NOT_B64 ://: D.u = ~S0.u SCC = 1 if result non-zero. case S_WQM_B64 ://: D.u = WholeQuadMode(S0.u). SCC = 1 if result is non-zero. case S_BREV_B64 ://: D.u = S0.u[0:63] (reverse bits). case S_BITSET0_B64 ://: D.u[S0.u[5:0]] = 0. case S_BITSET1_B64 ://: D.u[S0.u[5:0]] = 1. case S_GETPC_B64 ://: D.u = PC + 4; destination receives the byte address of the next instruction. case S_SWAPPC_B64 ://: D.u = PC + 4; PC = S0.u. case S_AND_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u & EXEC. SCC = 1 if the new value of EXEC is non-zero. case S_OR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u | EXEC. SCC = 1 if the newvalue of EXEC is non-zero. case S_XOR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u ^ EXEC. SCC = 1 if the new value of EXEC is non-zero. case S_ANDN2_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u & ~EXEC. SCC =1 if the new value of EXEC is non-zero. case S_ORN2_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u | ~EXEC. SCC = 1 if the new value of EXEC is non-zero. case S_NAND_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = ~(S0.u & EXEC). SCC =1 if the new value of EXEC is non-zero. case S_NOR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = ~(S0.u | EXEC). SCC = 1 if the new value of EXEC is non-zero. case S_XNOR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = ~(S0.u ^ EXEC). SCC = 1 if the new value of EXEC is non-zero. case S_QUADMASK_B64 ://: D.u = QuadMask(S0.u). D[0] = OR(S0[3:0]),D[1] = OR(S0[7:4]) .... SCC = 1 if result is non-zero case S_CSELECT_B64 : //: D.u = SCC ? S0.u : S1.u. return 2; case S_CBRANCH_G_FORK : // Conditional branch using branch stack. Arg0 = compare mask (VCC or any SGPR), Arg1 = 64-bit byte address of target instruction. case S_CBRANCH_I_FORK : //: Conditional branch using branch-stack. case S_SETREG_B32 : // : hardware register = D.u. Write some or all of the LSBs of D case S_SETREG_IMM32_B32 : //: This instruction uses a 32-bit literal constant. Write case S_RFE_B64 ://: Return from Exception; PC = TTMP1,0. case S_SETPC_B64 ://: PC = S0.u; S0.u is a byte address of the instruction to jump to. case S_MOVRELS_B64 ://: SGPR[D.u] = SGPR[S0.u + M0.u]. case S_MOVRELD_B64 ://: SGPR[D.u + M0.u] = SGPR[S0.u]. case S_CBRANCH_JOIN ://: Conditional branch join point. Arg0 = saved CSP value. No dest. case S_NOP : //: do nothing. Repeat NOP 1..8 times based on SIMM16[2:0]. 0 = 1 time, 7 = 8 times. case S_ENDPGM : //: end of program; terminate wavefront. case S_BRANCH : //: PC = PC + signext(SIMM16 * 4) + 4. case S_CBRANCH_SCC0 : //: if(SCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_SCC1 : //: if(SCC == 1) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_VCCZ : //: if(VCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_VCCNZ : //: if(VCC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_EXECZ : //: if(EXEC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_EXECNZ : //: if(EXEC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_BARRIER : //: Sync waves within a thread group. case S_WAITCNT : //: Wait for count of outstanding lds, vector-memory and case S_SETHALT : //: set HALT bit to value of SIMM16[0]. 1=halt, 0=resume. Halt is ignored while priv=1. case S_SLEEP : //: Cause a wave to sleep for approximately 64*SIMM16[2:0] clocks. case S_SETPRIO : //: User settable wave priority. 0 = lowest, 3 = highest. case S_SENDMSG : //: Send a message. case S_SENDMSGHALT : //: Send a message and then HALT. case S_TRAP : //: Enter the trap handler. TrapID = SIMM16[7:0]. Wait for all instructions to complete, case S_ICACHE_INV : //: Invalidate entire L1 I cache. case S_INCPERFLEVEL : //: Increment performance counter specified in SIMM16[3:0] by 1. case S_DECPERFLEVEL : //: Decrement performance counter specified in SIMM16[3:0] by 1. case S_TTRACEDATA : //: Send M0 as user data to thread-trace. case S_CBRANCH_CDBGSYS : // : If (conditional_debug_system != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGUSER : // : If (conditional_debug_user != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGSYS_OR_USER : // : If (conditional_debug_system || conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGSYS_AND_USER : // : If (conditional_debug_system && conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_RFE_RESTORE_B64: return 0; } } uint ScalarInstruction::GetArg0WidthInDWORDs() const { switch( GetOpcode() ) { default: return 0; case S_ADD_U32 : //: D.u = S0.u + S1.u. SCC = carry out. case S_SUB_U32 : //: D.u = S0.u - S1.u. SCC = carry out. case S_ADD_I32 : //: D.u = S0.i + S1.i. SCC = overflow. case S_SUB_I32 : //: D.u = S0.i - S1.i. SCC = overflow. case S_ADDC_U32 : //: D.u = S0.u + S1.u + SCC. SCC = carry-out. case S_SUBB_U32 : //: D.u = S0.u - S1.u - SCC. SCC = carry-out. case S_MIN_I32 : //: D.i = (S0.i < S1.i) ? S0.i : S1.i. SCC = 1 if S0 is min. case S_MIN_U32 : //: D.u = (S0.u < S1.u) ? S0.u : S1.u. SCC = 1 if S0 is min. case S_MAX_I32 : //: D.i = (S0.i > S1.i) ? S0.i : S1.i. SCC = 1 if S0 is max. case S_MAX_U32 : //: D.u = (S0.u > S1.u) ? S0.u : S1.u. SCC = 1 if S0 is max. case S_CSELECT_B32 : //: D.u = SCC ? S0.u : S1.u. case S_AND_B32 : //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. case S_OR_B32 : //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. case S_XOR_B32 : //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. case S_ANDN2_B32 : //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. case S_ORN2_B32 : //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. case S_NAND_B32 : //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. case S_NOR_B32 : //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. case S_XNOR_B32 : //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. case S_LSHL_B32 : //: D.u = S0.u << S1.u[4:0]. SCC = 1 if result is non-zero. case S_LSHR_B32 : //: D.u = S0.u >> S1.u[4:0]. SCC = 1 if result is non-zero. case S_ASHR_I32 : //: D.i = signtext(S0.i) >> S1.i[4:0]. SCC = 1 if result is non-zero. case S_BFM_B32 : //: D.u = ((1 << S0.u[4:0]) - 1) << S1.u[4:0]; bitfield mask. case S_MUL_I32 : //: D.i = S0.i * S1.i. case S_BFE_U32 : // : Bit field extract. S0 is data, S1[4:0] is field offset, S1[22:16] is field width. D.u = (S0.u >> S1.u[4:0]) & ((1 << S1.u[22:16]) - 1). SCC = 1 if resultis non-zero. case S_BFE_I32 : case S_ABSDIFF_I32 : // D.i = abs(S0.i >> S1.i). SCC = 1 if result is non-zero. case S_MOVK_I32 : //: D.i = signext(SIMM16). case S_CMOVK_I32 : //: if (SCC) D.i = signext(SIMM16); else NOP. case S_CMPK_EQ_I32 : //: SCC = (D.i == signext(SIMM16). case S_CMPK_LG_I32 : //: SCC = (D.i != signext(SIMM16). case S_CMPK_GT_I32 : //: SCC = (D.i != signext(SIMM16)). case S_CMPK_GE_I32 : //: SCC = (D.i >= signext(SIMM16)). case S_CMPK_LT_I32 : //: SCC = (D.i < signext(SIMM16)). case S_CMPK_LE_I32 : //: SCC = (D.i <= signext(SIMM16)). case S_CMPK_EQ_U32 : //: SCC = (D.u == SIMM16). case S_CMPK_LG_U32 : //: SCC = (D.u != SIMM16). case S_CMPK_GT_U32 : //: SCC = (D.u > SIMM16). case S_CMPK_GE_U32 : //: SCC = (D.u >= SIMM16). case S_CMPK_LT_U32 : //: SCC = (D.u < SIMM16). case S_CMPK_LE_U32 : //: D.u = SCC = (D.u <= SIMM16). case S_ADDK_I32 : //: D.i = D.i + signext(SIMM16). SCC = overflow. case S_MULK_I32 : //: D.i = D.i * signext(SIMM16). SCC = overflow. case S_GETREG_B32 : // : D.u = hardware register. Read some or all of a hardware register case S_MOV_B32 ://: D.u = S0.u. case S_CMOV_B32 ://: if(SCC) D.u = S0.u; else NOP. case S_NOT_B32 ://: D.u = ~S0.u SCC = 1 if result non-zero. case S_WQM_B32 ://: D.u = WholeQuadMode(S0.u). SCC = 1 if result is non-zero. case S_BREV_B32 ://: D.u = S0.u[0:31] (reverse bits). case S_BCNT0_I32_B32 ://: D.i = CountZeroBits(S0.u). SCC = 1 if result is non-zero. case S_BCNT1_I32_B32 ://: D.i = CountOneBits(S0.u). SCC = 1 if result is non-zero. case S_FF0_I32_B32 ://: D.i = FindFirstZero(S0.u) from LSB; if no zeros, return -1. case S_FF1_I32_B32 ://: D.i = FindFirstOne(S0.u) from LSB; if no ones, return -1. case S_FLBIT_I32_B32 ://: D.i = FindFirstOne(S0.u) from MSB; if no ones, return -1. case S_FLBIT_I32 ://: D.i = Find first bit opposite of sign bit from MSB. If S0 == -1, return -1. case S_SEXT_I32_I8 ://: D.i = signext(S0.i[7:0]). case S_SEXT_I32_I16 ://: D.i = signext(S0.i[15:0]). case S_BITSET0_B32 ://: D.u[S0.u[4:0]] = 0. case S_BITSET1_B32 ://: D.u[S0.u[4:0]] = 1. case S_QUADMASK_B32 ://: D.u = QuadMask(S0.u). D[0] = OR(S0[3:0]), D[1] = OR(S0[7:4]) .... SCC = 1 if result is non-zero. case S_MOVRELS_B32 ://: SGPR[D.u] = SGPR[S0.u + M0.u]. case S_MOVRELD_B32 ://: SGPR[D.u + M0.u] = SGPR[S0.u]. case S_ABS_I32 : //: D.i = abs(S0.i). SCC=1 if result is non-zero. case S_MOV_FED_B32 : //: D.u = S0.u, introduce edc double error upon write to dest sgpr. case S_CMP_EQ_I32 : //: SCC = (S0.i == S1.i). case S_CMP_LG_I32 : //: SCC = (S0.i != S1.i). case S_CMP_GT_I32 : //: SCC = (S0.i > S1.i). case S_CMP_GE_I32 : //: SCC = (S0.i >= S1.i). case S_CMP_LT_I32 : //: SCC = (S0.i < S1.i). case S_CMP_LE_I32 : //: SCC = (S0.i <= S1.i). case S_CMP_EQ_U32 : //: SCC = (S0.u == S1.u). case S_CMP_LG_U32 : //: SCC = (S0.u != S1.u). case S_CMP_GT_U32 : //: SCC = (S0.u > S1.u). case S_CMP_GE_U32 : //: SCC = (S0.u >= S1.u). case S_CMP_LT_U32 : //: SCC = (S0.u < S1.u). case S_CMP_LE_U32 : //: SCC = (S0.u <= S1.u). case S_BITCMP0_B32 : //: SCC = (S0.u[S1.u[4:0]] == 0). case S_BITCMP1_B32 : //: SCC = (S0.u[S1.u[4:0]] == 1). case S_SETVSKIP : //: VSKIP = S0.u[S1.u[4:0]]. case S_SETREG_B32 : // : hardware register = D.u. Write some or all of the LSBs of D case S_SETREG_IMM32_B32 : //: This instruction uses a 32-bit literal constant. Write case S_SET_GPR_IDX_IDX : case S_SET_GPR_IDX_ON: return 1; case S_MOVRELS_B64 ://: SGPR[D.u] = SGPR[S0.u + M0.u]. case S_MOVRELD_B64 ://: SGPR[D.u + M0.u] = SGPR[S0.u]. case S_BITCMP0_B64 : //: SCC = (S0.u[S1.u[5:0]] == 0). case S_BITCMP1_B64 : //: SCC = (S0.u[S1.u[5:0]] == 1). case S_BCNT0_I32_B64 ://: D.i = CountZeroBits(S0.u). SCC = 1 if result is non-zero. case S_BCNT1_I32_B64 ://: D.i = CountOneBits(S0.u). SCC = 1 if result is non-zero. case S_FF0_I32_B64 ://: D.i = FindFirstZero(S0.u) from LSB; if no zeros, return -1. case S_FF1_I32_B64 ://: D.i = FindFirstOne(S0.u) from LSB; if no ones, return -1. case S_FLBIT_I32_B64 ://: D.i = FindFirstOne(S0.u) from MSB; if no ones, return -1. case S_FLBIT_I32_I64 ://: D.i = Find first bit opposite of sign bit from MSB. If S0 == -1, return -1. case S_AND_B64 : //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. case S_OR_B64 : //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. case S_XOR_B64 : //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. case S_ANDN2_B64 : //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. case S_ORN2_B64 : //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. case S_NAND_B64 : //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. case S_NOR_B64 : //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. case S_XNOR_B64 : //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. case S_LSHL_B64 : //: D.u = S0.u << S1.u[5:0]. SCC = 1 if result is non-zero. case S_LSHR_B64 : //: D.u = S0.u >> S1.u[5:0]. SCC = 1 if result is non-zero. case S_ASHR_I64 : //: D.i = signtext(S0.i) >> S1.i[5:0]. SCC = 1 if result is non-zero. case S_BFM_B64 : //: D.u = ((1 << S0.u[5:0]) - 1) << S1.u[5:0]; bitfield mask. case S_BFE_U64 : case S_BFE_I64 : case S_MOV_B64 ://: D/u = S0.u. case S_CMOV_B64 ://: if(SCC) D.u = S0.u; else NOP. case S_NOT_B64 ://: D.u = ~S0.u SCC = 1 if result non-zero. case S_WQM_B64 ://: D.u = WholeQuadMode(S0.u). SCC = 1 if result is non-zero. case S_BREV_B64 ://: D.u = S0.u[0:63] (reverse bits). case S_BITSET0_B64 ://: D.u[S0.u[5:0]] = 0. case S_BITSET1_B64 ://: D.u[S0.u[5:0]] = 1. case S_GETPC_B64 ://: D.u = PC + 4; destination receives the byte address of the next instruction. case S_SWAPPC_B64 ://: D.u = PC + 4; PC = S0.u. case S_AND_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u & EXEC. SCC = 1 if the new value of EXEC is non-zero. case S_OR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u | EXEC. SCC = 1 if the newvalue of EXEC is non-zero. case S_XOR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u ^ EXEC. SCC = 1 if the new value of EXEC is non-zero. case S_ANDN2_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u & ~EXEC. SCC =1 if the new value of EXEC is non-zero. case S_ORN2_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = S0.u | ~EXEC. SCC = 1 if the new value of EXEC is non-zero. case S_NAND_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = ~(S0.u & EXEC). SCC =1 if the new value of EXEC is non-zero. case S_NOR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = ~(S0.u | EXEC). SCC = 1 if the new value of EXEC is non-zero. case S_XNOR_SAVEEXEC_B64 ://: D.u = EXEC, EXEC = ~(S0.u ^ EXEC). SCC = 1 if the new value of EXEC is non-zero. case S_QUADMASK_B64 ://: D.u = QuadMask(S0.u). D[0] = OR(S0[3:0]),D[1] = OR(S0[7:4]) .... SCC = 1 if result is non-zero case S_CSELECT_B64 : //: D.u = SCC ? S0.u : S1.u. case S_CBRANCH_G_FORK : // Conditional branch using branch stack. Arg0 = compare mask (VCC or any SGPR), Arg1 = 64-bit byte address of target instruction. case S_CBRANCH_I_FORK : //: Conditional branch using branch-stack. case S_CBRANCH_JOIN ://: Conditional branch join point. Arg0 = saved CSP value. No dest. case S_RFE_B64 ://: Return from Exception; PC = TTMP1,0. case S_SETPC_B64 ://: PC = S0.u; S0.u is a byte address of the instruction to jump to. case S_RFE_RESTORE_B64 : case S_CMP_EQ_U64: case S_CMP_NE_U64: return 2; case S_NOP : //: do nothing. Repeat NOP 1..8 times based on SIMM16[2:0]. 0 = 1 time, 7 = 8 times. case S_ENDPGM : //: end of program; terminate wavefront. case S_BRANCH : //: PC = PC + signext(SIMM16 * 4) + 4. case S_CBRANCH_SCC0 : //: if(SCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_SCC1 : //: if(SCC == 1) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_VCCZ : //: if(VCC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_VCCNZ : //: if(VCC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_EXECZ : //: if(EXEC == 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_CBRANCH_EXECNZ : //: if(EXEC != 0) then PC = PC + signext(SIMM16 * 4) + 4; else nop. case S_BARRIER : //: Sync waves within a thread group. case S_WAITCNT : //: Wait for count of outstanding lds, vector-memory and case S_SETHALT : //: set HALT bit to value of SIMM16[0]. 1=halt, 0=resume. Halt is ignored while priv=1. case S_SLEEP : //: Cause a wave to sleep for approximately 64*SIMM16[2:0] clocks. case S_SETPRIO : //: User settable wave priority. 0 = lowest, 3 = highest. case S_SENDMSG : //: Send a message. case S_SENDMSGHALT : //: Send a message and then HALT. case S_TRAP : //: Enter the trap handler. TrapID = SIMM16[7:0]. Wait for all instructions to complete, case S_ICACHE_INV : //: Invalidate entire L1 I cache. case S_INCPERFLEVEL : //: Increment performance counter specified in SIMM16[3:0] by 1. case S_DECPERFLEVEL : //: Decrement performance counter specified in SIMM16[3:0] by 1. case S_TTRACEDATA : //: Send M0 as user data to thread-trace. case S_CBRANCH_CDBGSYS : // : If (conditional_debug_system != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGUSER : // : If (conditional_debug_user != 0) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGSYS_OR_USER : // : If (conditional_debug_system || conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. case S_CBRANCH_CDBGSYS_AND_USER : // : If (conditional_debug_system && conditional_debug_user) then PC = PC + signext(SIMM16 * 4) + 4; else NOP. return 0; } } uint ScalarInstruction::GetArg1WidthInDWORDs() const { switch( GetOpcode() ) { default: return 0; case S_ADD_U32 : //: D.u = S0.u + S1.u. SCC = carry out. case S_SUB_U32 : //: D.u = S0.u - S1.u. SCC = carry out. case S_ADD_I32 : //: D.u = S0.i + S1.i. SCC = overflow. case S_SUB_I32 : //: D.u = S0.i - S1.i. SCC = overflow. case S_ADDC_U32 : //: D.u = S0.u + S1.u + SCC. SCC = carry-out. case S_SUBB_U32 : //: D.u = S0.u - S1.u - SCC. SCC = carry-out. case S_MIN_I32 : //: D.i = (S0.i < S1.i) ? S0.i : S1.i. SCC = 1 if S0 is min. case S_MIN_U32 : //: D.u = (S0.u < S1.u) ? S0.u : S1.u. SCC = 1 if S0 is min. case S_MAX_I32 : //: D.i = (S0.i > S1.i) ? S0.i : S1.i. SCC = 1 if S0 is max. case S_MAX_U32 : //: D.u = (S0.u > S1.u) ? S0.u : S1.u. SCC = 1 if S0 is max. case S_AND_B32 : //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. case S_CSELECT_B32 : //: D.u = SCC ? S0.u : S1.u. case S_OR_B32 : //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. case S_XOR_B32 : //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. case S_ANDN2_B32 : //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. case S_ORN2_B32 : //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. case S_NAND_B32 : //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. case S_NOR_B32 : //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. case S_XNOR_B32 : //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. case S_LSHL_B32 : //: D.u = S0.u << S1.u[4:0]. SCC = 1 if result is non-zero. case S_LSHR_B32 : //: D.u = S0.u >> S1.u[4:0]. SCC = 1 if result is non-zero. case S_ASHR_I32 : //: D.i = signtext(S0.i) >> S1.i[4:0]. SCC = 1 if result is non-zero. case S_BFM_B32 : //: D.u = ((1 << S0.u[4:0]) - 1) << S1.u[4:0]; bitfield mask. case S_LSHL_B64 : //: D.u = S0.u << S1.u[5:0]. SCC = 1 if result is non-zero. case S_LSHR_B64 : //: D.u = S0.u >> S1.u[5:0]. SCC = 1 if result is non-zero. case S_ASHR_I64 : //: D.i = signtext(S0.i) >> S1.i[5:0]. SCC = 1 if result is non-zero. case S_BFM_B64 : //: D.u = ((1 << S0.u[5:0]) - 1) << S1.u[5:0]; bitfield mask. case S_BFE_U32 : // : Bit field extract. S0 is data, S1[4:0] is field offset, S1[22:16] is field width. D.u = (S0.u >> S1.u[4:0]) & ((1 << S1.u[22:16]) - 1). SCC = 1 if resultis non-zero. case S_BFE_I32 : case S_BFE_U64 : case S_BFE_I64 : case S_ABSDIFF_I32 : // D.i = abs(S0.i >> S1.i). SCC = 1 if result is non-zero. case S_MUL_I32 : //: D.i = S0.i * S1.i. case S_CMP_EQ_I32 : //: SCC = (S0.i == S1.i). case S_CMP_LG_I32 : //: SCC = (S0.i != S1.i). case S_CMP_GT_I32 : //: SCC = (S0.i > S1.i). case S_CMP_GE_I32 : //: SCC = (S0.i >= S1.i). case S_CMP_LT_I32 : //: SCC = (S0.i < S1.i). case S_CMP_LE_I32 : //: SCC = (S0.i <= S1.i). case S_CMP_EQ_U32 : //: SCC = (S0.u == S1.u). case S_CMP_LG_U32 : //: SCC = (S0.u != S1.u). case S_CMP_GT_U32 : //: SCC = (S0.u > S1.u). case S_CMP_GE_U32 : //: SCC = (S0.u >= S1.u). case S_CMP_LT_U32 : //: SCC = (S0.u < S1.u). case S_CMP_LE_U32 : //: SCC = (S0.u <= S1.u). case S_BITCMP0_B32 : //: SCC = (S0.u[S1.u[4:0]] == 0). case S_BITCMP1_B32 : //: SCC = (S0.u[S1.u[4:0]] == 1). case S_BITCMP0_B64 : //: SCC = (S0.u[S1.u[5:0]] == 0). case S_BITCMP1_B64 : //: SCC = (S0.u[S1.u[5:0]] == 1). case S_SETVSKIP : //: VSKIP = S0.u[S1.u[4:0]]. case S_RFE_RESTORE_B64: case S_SET_GPR_IDX_ON: return 1; case S_CSELECT_B64 : //: D.u = SCC ? S0.u : S1.u. case S_AND_B64 : //: D.u = S0.u & S1.u. SCC = 1 if result is non-zero. case S_OR_B64 : //: D.u = S0.u | S1.u. SCC = 1 if result is non-zero. case S_XOR_B64 : //: D.u = S0.u ^ S1.u. SCC = 1 if result is non-zero. case S_ANDN2_B64 : //: D.u = S0.u & ~S1.u. SCC = 1 if result is non-zero. case S_ORN2_B64 : //: D.u = S0.u | ~S1.u. SCC = 1 if result is non-zero. case S_NAND_B64 : //: D.u = ~(S0.u & S1.u). SCC = 1 if result is non-zero. case S_NOR_B64 : //: D.u = ~(S0.u | S1.u). SCC = 1 if result is non-zero. case S_XNOR_B64 : //: D.u = ~(S0.u ^ S1.u). SCC = 1 if result is non-zero. case S_CBRANCH_G_FORK : // Conditional branch using branch stack. Arg0 = compare mask (VCC or any SGPR), Arg1 = 64-bit byte address of target instruction. case S_CMP_EQ_U64: case S_CMP_NE_U64: return 2; } } uint GetResultWidthInDWORDs(BufferInstructions e) { switch( e ) { case BUFFER_LOAD_FORMAT_X : case BUFFER_STORE_FORMAT_X : case BUFFER_LOAD_UBYTE : case BUFFER_LOAD_SBYTE : case BUFFER_LOAD_USHORT : case BUFFER_LOAD_SSHORT : case BUFFER_LOAD_DWORD : case BUFFER_STORE_BYTE : case BUFFER_STORE_SHORT : case BUFFER_STORE_DWORD : return 1; case BUFFER_STORE_FORMAT_XY : case BUFFER_LOAD_FORMAT_XY : case BUFFER_LOAD_DWORDX2 : case BUFFER_STORE_DWORDX2 : return 2; case BUFFER_STORE_FORMAT_XYZ : case BUFFER_LOAD_FORMAT_XYZ : case BUFFER_LOAD_DWORDX3 : case BUFFER_STORE_DWORDX3 : return 3; case BUFFER_STORE_FORMAT_XYZW : case BUFFER_LOAD_FORMAT_XYZW : case BUFFER_LOAD_DWORDX4 : case BUFFER_STORE_DWORDX4 : return 4; case BUFFER_ATOMIC_SWAP : case BUFFER_ATOMIC_CMPSWAP : case BUFFER_ATOMIC_ADD : case BUFFER_ATOMIC_SUB : case BUFFER_ATOMIC_RSUB : case BUFFER_ATOMIC_SMIN : case BUFFER_ATOMIC_UMIN : case BUFFER_ATOMIC_SMAX : case BUFFER_ATOMIC_UMAX : case BUFFER_ATOMIC_AND : case BUFFER_ATOMIC_OR : case BUFFER_ATOMIC_XOR : case BUFFER_ATOMIC_INC : case BUFFER_ATOMIC_DEC : case BUFFER_ATOMIC_FCMPSWAP : case BUFFER_ATOMIC_FMIN : case BUFFER_ATOMIC_FMAX : return 1; case BUFFER_ATOMIC_SWAP_X2 : case BUFFER_ATOMIC_CMPSWAP_X2 : case BUFFER_ATOMIC_ADD_X2 : case BUFFER_ATOMIC_SUB_X2 : case BUFFER_ATOMIC_RSUB_X2 : case BUFFER_ATOMIC_SMIN_X2 : case BUFFER_ATOMIC_UMIN_X2 : case BUFFER_ATOMIC_SMAX_X2 : case BUFFER_ATOMIC_UMAX_X2 : case BUFFER_ATOMIC_AND_X2 : case BUFFER_ATOMIC_OR_X2 : case BUFFER_ATOMIC_XOR_X2 : case BUFFER_ATOMIC_INC_X2 : case BUFFER_ATOMIC_DEC_X2 : case BUFFER_ATOMIC_FCMPSWAP_X2 : case BUFFER_ATOMIC_FMIN_X2 : case BUFFER_ATOMIC_FMAX_X2 : return 2; case TBUFFER_LOAD_FORMAT_X : case TBUFFER_STORE_FORMAT_X : case TBUFFER_LOAD_FORMAT_D16_X : case TBUFFER_STORE_FORMAT_D16_X : return 1; case TBUFFER_LOAD_FORMAT_XY : case TBUFFER_STORE_FORMAT_XY : case TBUFFER_LOAD_FORMAT_D16_XY : case TBUFFER_STORE_FORMAT_D16_XY: return 2; case TBUFFER_LOAD_FORMAT_XYZ : case TBUFFER_STORE_FORMAT_XYZ : case TBUFFER_LOAD_FORMAT_D16_XYZ : case TBUFFER_STORE_FORMAT_D16_XYZ: return 3; case TBUFFER_LOAD_FORMAT_XYZW : case TBUFFER_STORE_FORMAT_XYZW : case TBUFFER_LOAD_FORMAT_D16_XYZW : case TBUFFER_STORE_FORMAT_D16_XYZW: return 4; case BUFFER_STORE_LDS_DWORD : case BUFFER_LOAD_FORMAT_D16_X : case BUFFER_STORE_FORMAT_D16_X : return 1; case BUFFER_LOAD_FORMAT_D16_XY : case BUFFER_STORE_FORMAT_D16_XY : return 2; case BUFFER_LOAD_FORMAT_D16_XYZ : case BUFFER_STORE_FORMAT_D16_XYZ : return 3; case BUFFER_LOAD_FORMAT_D16_XYZW : case BUFFER_STORE_FORMAT_D16_XYZW : return 4; default: case BUFFER_WBINVL1_VOL : case BUFFER_WBINVL1_SC : case BUFFER_WBINVL1 : return 0; } } bool IsTBufferInstruction( BufferInstructions e ) { switch(e) { case TBUFFER_LOAD_FORMAT_X : case TBUFFER_STORE_FORMAT_X : case TBUFFER_LOAD_FORMAT_XY : case TBUFFER_STORE_FORMAT_XY : case TBUFFER_LOAD_FORMAT_XYZ : case TBUFFER_STORE_FORMAT_XYZ : case TBUFFER_LOAD_FORMAT_XYZW : case TBUFFER_STORE_FORMAT_XYZW : case TBUFFER_LOAD_FORMAT_D16_X : case TBUFFER_LOAD_FORMAT_D16_XY : case TBUFFER_LOAD_FORMAT_D16_XYZ : case TBUFFER_LOAD_FORMAT_D16_XYZW : case TBUFFER_STORE_FORMAT_D16_X : case TBUFFER_STORE_FORMAT_D16_XY : case TBUFFER_STORE_FORMAT_D16_XYZ : case TBUFFER_STORE_FORMAT_D16_XYZW : return true; default: return false; } } bool ScalarInstruction::IsControlFlowOp() const { switch( GetOpcode() ) { case S_CBRANCH_G_FORK : case S_CBRANCH_I_FORK : case S_SETPC_B64 : case S_SWAPPC_B64 : case S_RFE_B64 : case S_CBRANCH_JOIN : case S_ENDPGM : case S_BRANCH : case S_CBRANCH_SCC0 : case S_CBRANCH_SCC1 : case S_CBRANCH_VCCZ : case S_CBRANCH_VCCNZ : case S_CBRANCH_EXECZ : case S_CBRANCH_EXECNZ : case S_BARRIER : case S_SETHALT : case S_SENDMSGHALT : case S_TRAP : case S_CBRANCH_CDBGSYS : case S_CBRANCH_CDBGUSER : case S_CBRANCH_CDBGSYS_OR_USER : case S_CBRANCH_CDBGSYS_AND_USER : case S_RFE_RESTORE_B64: case S_ENDPGM_SAVED: return true; default: return false; } } bool ScalarInstruction::IsConditionalJump() const { switch( GetOpcode() ) { case S_CBRANCH_G_FORK : case S_CBRANCH_I_FORK : case S_CBRANCH_JOIN : case S_CBRANCH_SCC0 : case S_CBRANCH_SCC1 : case S_CBRANCH_VCCZ : case S_CBRANCH_VCCNZ : case S_CBRANCH_EXECZ : case S_CBRANCH_EXECNZ : case S_CBRANCH_CDBGSYS : case S_CBRANCH_CDBGUSER : case S_CBRANCH_CDBGSYS_OR_USER : case S_CBRANCH_CDBGSYS_AND_USER : return true; default: return false; } } bool ScalarInstruction::IsUnconditionalJump() const { switch( GetOpcode() ) { case S_SETPC_B64 : case S_SWAPPC_B64 : case S_RFE_B64 : case S_TRAP : case S_RFE_RESTORE_B64 : case S_BRANCH : return true; default: return false; } } bool ScalarInstruction::IsWavefrontHalt() const { switch( GetOpcode() ) { case S_ENDPGM : case S_SETHALT : case S_SENDMSGHALT : return true; default: return false; } } uint ScalarMemoryInstruction::GetResourceWidthInDWORDs() const { switch( GetOpcode() ) { case S_LOAD_DWORD : case S_LOAD_DWORDX2 : case S_LOAD_DWORDX4 : case S_LOAD_DWORDX8 : case S_LOAD_DWORDX16 : case S_STORE_DWORD : case S_STORE_DWORDX2 : case S_STORE_DWORDX4 : case S_ATC_PROBE : return 2; case S_BUFFER_LOAD_DWORD : case S_BUFFER_LOAD_DWORDX2 : case S_BUFFER_LOAD_DWORDX4 : case S_BUFFER_LOAD_DWORDX8 : case S_BUFFER_LOAD_DWORDX16: case S_BUFFER_STORE_DWORD : case S_BUFFER_STORE_DWORDX2: case S_BUFFER_STORE_DWORDX4: case S_ATC_PROBE_BUFFER : return 4; default: return 0; } } uint ScalarMemoryInstruction::GetResultWidthInDWORDs() const { switch( GetOpcode() ) { case S_LOAD_DWORD : return 1; case S_LOAD_DWORDX2 : return 2; case S_LOAD_DWORDX4 : return 4; case S_LOAD_DWORDX8 : return 8; case S_LOAD_DWORDX16 : return 16; case S_BUFFER_LOAD_DWORD : return 1; case S_BUFFER_LOAD_DWORDX2 : return 2; case S_BUFFER_LOAD_DWORDX4 : return 4; case S_BUFFER_LOAD_DWORDX8 : return 8; case S_BUFFER_LOAD_DWORDX16: return 16; case S_MEMTIME : return 2; case S_STORE_DWORD : return 1; case S_STORE_DWORDX2 : return 2; case S_STORE_DWORDX4 : return 4; case S_BUFFER_STORE_DWORD : return 1; case S_BUFFER_STORE_DWORDX2: return 2; case S_BUFFER_STORE_DWORDX4: return 4; case S_MEMREALTIME : return 2; case S_ATC_PROBE : case S_ATC_PROBE_BUFFER : case S_DCACHE_WB : case S_DCACHE_WB_VOL : case S_DCACHE_INV_VOL : case S_DCACHE_INV : default: return 0; } } uint GetSamplerWidthInDWORDs( ImageInstructions e ) { switch( e ) { case IMAGE_LOAD : case IMAGE_LOAD_MIP : case IMAGE_LOAD_PCK : case IMAGE_LOAD_PCK_SGN : case IMAGE_LOAD_MIP_PCK : case IMAGE_LOAD_MIP_PCK_SGN : case IMAGE_STORE : case IMAGE_STORE_MIP : case IMAGE_STORE_PCK : case IMAGE_STORE_MIP_PCK : case IMAGE_GET_RESINFO : case IMAGE_ATOMIC_SWAP : case IMAGE_ATOMIC_CMPSWAP : case IMAGE_ATOMIC_ADD : case IMAGE_ATOMIC_SUB : case IMAGE_ATOMIC_RSUB : case IMAGE_ATOMIC_SMIN : case IMAGE_ATOMIC_UMIN : case IMAGE_ATOMIC_SMAX : case IMAGE_ATOMIC_UMAX : case IMAGE_ATOMIC_AND : case IMAGE_ATOMIC_OR : case IMAGE_ATOMIC_XOR : case IMAGE_ATOMIC_INC : case IMAGE_ATOMIC_DEC : case IMAGE_ATOMIC_FCMPSWAP : case IMAGE_ATOMIC_FMIN : case IMAGE_ATOMIC_FMAX : return 0; default: return 4; } } uint ImageInstruction::GetResultWidthInDWORDS() const { switch( GetOpcode() ) { // Gathers always return four results, regardless of DMask // The ISA doc does not indicate this // case IMAGE_GATHER4 : case IMAGE_GATHER4_CL : case IMAGE_GATHER4_L : case IMAGE_GATHER4_B : case IMAGE_GATHER4_B_CL : case IMAGE_GATHER4_LZ : case IMAGE_GATHER4_C : case IMAGE_GATHER4_C_CL : case IMAGE_GATHER4_C_L : case IMAGE_GATHER4_C_B : case IMAGE_GATHER4_C_B_CL : case IMAGE_GATHER4_C_LZ : case IMAGE_GATHER4_O : case IMAGE_GATHER4_CL_O : case IMAGE_GATHER4_L_O : case IMAGE_GATHER4_B_O : case IMAGE_GATHER4_B_CL_O : case IMAGE_GATHER4_LZ_O : case IMAGE_GATHER4_C_O : case IMAGE_GATHER4_C_CL_O : case IMAGE_GATHER4_C_L_O : case IMAGE_GATHER4_C_B_O : case IMAGE_GATHER4_C_B_CL_O : case IMAGE_GATHER4_C_LZ_O : return 4; default: { // result width is the number of set bits in the dmask field uint n = GetDMask(); uint c=0; while( n ) { c += (n&1); n>>=1; } return c; } break; } } bool ImageInstruction::IsFilteredFetch( ) const { switch( GetOpcode() ) { case IMAGE_SAMPLE : //: sample texture map. case IMAGE_SAMPLE_CL : //: sample texture map, with LOD clamp specified in shader. case IMAGE_SAMPLE_D : //: sample texture map, with user derivatives. case IMAGE_SAMPLE_D_CL : //: sample texture map, with LOD clamp specified in shader, with user derivatives. case IMAGE_SAMPLE_L : //: sample texture map, with user LOD. case IMAGE_SAMPLE_B : //: sample texture map, with lod bias. case IMAGE_SAMPLE_B_CL : //: sample texture map, with LOD clamp specified in shader, with lod bias. case IMAGE_SAMPLE_LZ : //: sample texture map, from level 0. case IMAGE_SAMPLE_C : //: sample texture map, with PCF. case IMAGE_SAMPLE_C_CL : //: SAMPLE_C, with LOD clamp specified in shader. case IMAGE_SAMPLE_C_D : //: SAMPLE_C, with user derivatives. case IMAGE_SAMPLE_C_D_CL : //: SAMPLE_C, with LOD clamp specified in shader,with user derivatives. case IMAGE_SAMPLE_C_L : //: SAMPLE_C, with user LOD. case IMAGE_SAMPLE_C_B : //: SAMPLE_C, with lod bias. case IMAGE_SAMPLE_C_B_CL : //: SAMPLE_C, with LOD clamp specified in shader, with lod bias. case IMAGE_SAMPLE_C_LZ : // : SAMPLE_C, from level 0. case IMAGE_SAMPLE_O : // : sample texture map, with user offsets. case IMAGE_SAMPLE_CL_O : // : SAMPLE_O with LOD clamp specified in shader. case IMAGE_SAMPLE_D_O : // : SAMPLE_O, with user derivatives. case IMAGE_SAMPLE_D_CL_O : // : SAMPLE_O, with LOD clamp specified in shader,with user derivatives. case IMAGE_SAMPLE_L_O : // : SAMPLE_O, with user LOD. case IMAGE_SAMPLE_B_O : // : SAMPLE_O, with lod bias. case IMAGE_SAMPLE_B_CL_O : // : SAMPLE_O, with LOD clamp specified in shader,with lod bias. case IMAGE_SAMPLE_LZ_O : // : SAMPLE_O, from level 0. case IMAGE_SAMPLE_C_O : // : SAMPLE_C with user specified offsets. case IMAGE_SAMPLE_C_CL_O : // : SAMPLE_C_O, with LOD clamp specified in shader. case IMAGE_SAMPLE_C_D_O : // : SAMPLE_C_O, with user derivatives. case IMAGE_SAMPLE_C_D_CL_O : // : SAMPLE_C_O, with LOD clamp specified in shader, with user derivatives. case IMAGE_SAMPLE_C_L_O : // : SAMPLE_C_O, with user LOD. case IMAGE_SAMPLE_C_B_O : // : SAMPLE_C_O, with lod bias. case IMAGE_SAMPLE_C_B_CL_O : // : SAMPLE_C_O, with LOD clamp specified in shader, with lod bias. case IMAGE_SAMPLE_C_LZ_O : // : SAMPLE_C_O, from level 0. case IMAGE_SAMPLE_CD : // : sample texture map, with user derivatives (LOD per quad) case IMAGE_SAMPLE_CD_CL : // : sample texture map, with LOD clamp specified in shader, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD : // : SAMPLE_C, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD_CL : // : SAMPLE_C, with LOD clamp specified in shader, with user derivatives (LOD per quad). case IMAGE_SAMPLE_CD_O : // : SAMPLE_O, with user derivatives (LOD per quad). case IMAGE_SAMPLE_CD_CL_O : // : SAMPLE_O, with LOD clamp specified in shader, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD_O : // : SAMPLE_C_O, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD_CL_O : return true; default: return false; } } bool ImageInstruction::IsGradientFetch( ) const { switch( GetOpcode() ) { case IMAGE_SAMPLE_D : //: sample texture map, with user derivatives. case IMAGE_SAMPLE_D_CL : //: sample texture map, with LOD clamp specified in shader, with user derivatives. case IMAGE_SAMPLE_C_D : //: SAMPLE_C, with user derivatives. case IMAGE_SAMPLE_C_D_CL : //: SAMPLE_C, with LOD clamp specified in shader,with user derivatives. case IMAGE_SAMPLE_D_O : // : SAMPLE_O, with user derivatives. case IMAGE_SAMPLE_D_CL_O : // : SAMPLE_O, with LOD clamp specified in shader,with user derivatives. case IMAGE_SAMPLE_C_D_O : // : SAMPLE_C_O, with user derivatives. case IMAGE_SAMPLE_C_D_CL_O : // : SAMPLE_C_O, with LOD clamp specified in shader, with user derivatives. case IMAGE_SAMPLE_CD : // : sample texture map, with user derivatives (LOD per quad) case IMAGE_SAMPLE_CD_CL : // : sample texture map, with LOD clamp specified in shader, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD : // : SAMPLE_C, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD_CL : // : SAMPLE_C, with LOD clamp specified in shader, with user derivatives (LOD per quad). case IMAGE_SAMPLE_CD_O : // : SAMPLE_O, with user derivatives (LOD per quad). case IMAGE_SAMPLE_CD_CL_O : // : SAMPLE_O, with LOD clamp specified in shader, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD_O : // : SAMPLE_C_O, with user derivatives (LOD per quad). case IMAGE_SAMPLE_C_CD_CL_O : return true; default: return false; } } bool ImageInstruction::IsGather() const { switch( GetOpcode() ) { case IMAGE_GATHER4 :// : gather 4 single component elements (2x2). case IMAGE_GATHER4_CL :// : gather 4 single component elements (2x2) with user LOD clamp. case IMAGE_GATHER4_L :// : gather 4 single component elements (2x2) with user LOD. case IMAGE_GATHER4_B :// : gather 4 single component elements (2x2) with user bias. case IMAGE_GATHER4_B_CL :// : gather 4 single component elements (2x2) with user bias and clamp. case IMAGE_GATHER4_LZ :// : gather 4 single component elements (2x2) at level 0. case IMAGE_GATHER4_C :// : gather 4 single component elements (2x2) with PCF. case IMAGE_GATHER4_C_CL :// : gather 4 single component elements (2x2) with user LOD clamp and PCF. case IMAGE_GATHER4_C_L :// : gather 4 single component elements (2x2) with user LOD and PCF. case IMAGE_GATHER4_C_B :// : gather 4 single component elements (2x2) with user bias and PCF. case IMAGE_GATHER4_C_B_CL :// : gather 4 single component elements (2x2) with user bias, clamp and PCF. case IMAGE_GATHER4_C_LZ :// : gather 4 single component elements (2x2) at level 0, with PCF. case IMAGE_GATHER4_O :// : GATHER4, with user offsets. case IMAGE_GATHER4_CL_O :// : GATHER4_CL, with user offsets. case IMAGE_GATHER4_L_O :// : GATHER4_L, with user offsets. case IMAGE_GATHER4_B_O :// : GATHER4_B, with user offsets. case IMAGE_GATHER4_B_CL_O :// : GATHER4_B_CL, with user offsets. case IMAGE_GATHER4_LZ_O :// : GATHER4_LZ, with user offsets. case IMAGE_GATHER4_C_O :// : GATHER4_C, with user offsets. case IMAGE_GATHER4_C_CL_O :// : GATHER4_C_CL, with user offsets. case IMAGE_GATHER4_C_L_O :// : GATHER4_C_L, with user offsets. case IMAGE_GATHER4_C_B_O :// : GATHER4_B, with user offsets. case IMAGE_GATHER4_C_B_CL_O:// : GATHER4_B_CL, with user offsets. case IMAGE_GATHER4_C_LZ_O :// : GATHER4_C_LZ, with user offsets. return true; default: return false; } } bool ImageInstruction::IsUnfilteredLoadStore() const { switch( GetOpcode() ) { case IMAGE_LOAD : // Image memory load with format conversion specified in T#. No sampler. case IMAGE_LOAD_MIP : // Image memory load with user-supplied mip level. No sampler. case IMAGE_LOAD_PCK : // Image memory load with no format conversion. No sampler. case IMAGE_LOAD_PCK_SGN : // Image memory load with with no format conversion and sign extension. No sampler. case IMAGE_LOAD_MIP_PCK : // Image memory load with user-supplied mip level, no format conversion. No sampler. case IMAGE_LOAD_MIP_PCK_SGN: // Image memory load with user-supplied mip level, no format conversion and with sign extension. No sampler. case IMAGE_STORE : //: Image memory store with format conversion specified in T#. No sampler. case IMAGE_STORE_MIP : //: Image memory store with format conversion specified in T# to user specified mip level. No sampler. case IMAGE_STORE_PCK : //: Image memory store of packed data without format conversion. No sampler. case IMAGE_STORE_MIP_PCK : //: Image memory store of packed data without format conversion to user-supplied mip level. No sampler. return true; default: return false; } } bool ImageInstruction::IsMemoryWrite() const { switch( GetOpcode() ) { case IMAGE_STORE : //: Image memory store with format conversion specified in T#. No sampler. case IMAGE_STORE_MIP : //: Image memory store with format conversion specified in T# to user specified mip level. No sampler. case IMAGE_STORE_PCK : //: Image memory store of packed data without format conversion. No sampler. case IMAGE_STORE_MIP_PCK : //: Image memory store of packed data without format conversion to user-supplied mip level. No sampler. case IMAGE_ATOMIC_SWAP : //: dst=src, returns previous value if glc==1. case IMAGE_ATOMIC_CMPSWAP : //: dst = (dst==cmp) ? src : dst. Returns previous value if glc==1. case IMAGE_ATOMIC_ADD : //: dst += src. Returns previous value if glc==1. case IMAGE_ATOMIC_SUB : //: dst -= src. Returns previous value if glc==1. case IMAGE_ATOMIC_RSUB : //: dst = src-dst. Returns previous value if glc==1. SI ONLY case IMAGE_ATOMIC_SMIN : //: dst = (src < dst) ? src : dst (signed). Returns previous value if glc==1. case IMAGE_ATOMIC_UMIN : //: dst = (src < dst) ? src : dst (unsigned). Returns previous value if glc==1. case IMAGE_ATOMIC_SMAX : //: dst = (src > dst) ? src : dst (signed). Returns previous value if glc==1. case IMAGE_ATOMIC_UMAX : //: dst = (src > dst) ? src : dst (unsigned). Returns previous value if glc==1. case IMAGE_ATOMIC_AND : //: dst &= src. Returns previous value if glc==1. case IMAGE_ATOMIC_OR : //: dst |= src. Returns previous value if glc==1. case IMAGE_ATOMIC_XOR : //: dst ^= src. Returns previous value if glc==1. case IMAGE_ATOMIC_INC : //: dst = (dst >= src) ? 0 : dst+1. Returns previous value if glc==1. case IMAGE_ATOMIC_DEC : //: dst = ((dst==0 || (dst > src)) ? src : dst-1. Returns previous value if glc==1. case IMAGE_ATOMIC_FCMPSWAP: //: dst = (dst == cmp) ? src : dst, returns previous value of dst if glc==1 - double and float atomic compare swap. Obeys floating point compare rules for special values. case IMAGE_ATOMIC_FMIN : //: dst = (src < dst) ? src : dst, returns previous value of dst if glc==1 - double and float atomic min (handles NaN/INF/denorm). case IMAGE_ATOMIC_FMAX : //: dst = (src > dst) ? src : dst, returns previous value of dst if glc==1 - double and float atomic min (handles NaN/INF/denorm). return true; } return false; } bool BufferInstruction::IsMemoryWrite() const { switch( GetOpcode() ) { case BUFFER_STORE_FORMAT_X : case BUFFER_STORE_FORMAT_XY : case BUFFER_STORE_FORMAT_XYZ : case BUFFER_STORE_FORMAT_XYZW : case BUFFER_STORE_BYTE : case BUFFER_STORE_SHORT : case BUFFER_STORE_DWORD : case BUFFER_STORE_DWORDX2 : case BUFFER_STORE_DWORDX4 : case BUFFER_STORE_DWORDX3 : case BUFFER_ATOMIC_SWAP : case BUFFER_ATOMIC_CMPSWAP : case BUFFER_ATOMIC_ADD : case BUFFER_ATOMIC_SUB : case BUFFER_ATOMIC_RSUB : case BUFFER_ATOMIC_SMIN : case BUFFER_ATOMIC_UMIN : case BUFFER_ATOMIC_SMAX : case BUFFER_ATOMIC_UMAX : case BUFFER_ATOMIC_AND : case BUFFER_ATOMIC_OR : case BUFFER_ATOMIC_XOR : case BUFFER_ATOMIC_INC : case BUFFER_ATOMIC_DEC : case BUFFER_ATOMIC_FCMPSWAP : case BUFFER_ATOMIC_FMIN : case BUFFER_ATOMIC_FMAX : case BUFFER_ATOMIC_SWAP_X2 : case BUFFER_ATOMIC_CMPSWAP_X2 : case BUFFER_ATOMIC_ADD_X2 : case BUFFER_ATOMIC_SUB_X2 : case BUFFER_ATOMIC_RSUB_X2 : case BUFFER_ATOMIC_SMIN_X2 : case BUFFER_ATOMIC_UMIN_X2 : case BUFFER_ATOMIC_SMAX_X2 : case BUFFER_ATOMIC_UMAX_X2 : case BUFFER_ATOMIC_AND_X2 : case BUFFER_ATOMIC_OR_X2 : case BUFFER_ATOMIC_XOR_X2 : case BUFFER_ATOMIC_INC_X2 : case BUFFER_ATOMIC_DEC_X2 : case BUFFER_ATOMIC_FCMPSWAP_X2 : case BUFFER_ATOMIC_FMIN_X2 : case BUFFER_ATOMIC_FMAX_X2 : case BUFFER_STORE_LDS_DWORD : case BUFFER_STORE_FORMAT_D16_X : case BUFFER_STORE_FORMAT_D16_XY : case BUFFER_STORE_FORMAT_D16_XYZ : case BUFFER_STORE_FORMAT_D16_XYZW: case TBUFFER_STORE_FORMAT_X : case TBUFFER_STORE_FORMAT_XY : case TBUFFER_STORE_FORMAT_XYZ : case TBUFFER_STORE_FORMAT_XYZW : case TBUFFER_STORE_FORMAT_D16_X : case TBUFFER_STORE_FORMAT_D16_XY : case TBUFFER_STORE_FORMAT_D16_XYZ : case TBUFFER_STORE_FORMAT_D16_XYZW : return true; } return false; } } ================================================ FILE: src/Wrapper/GCNIsa.h ================================================ // // ASIC-independent data structure for manipulating GCN instructions // // Copyright 2015 Joshua Barczak, all rights reserved. // #ifndef _GCN_ISA_H_ #define _GCN_ISA_H_ #pragma once #include "GCNEnums.h" namespace GCN { typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; typedef unsigned int uint; typedef short int16; static_assert( sizeof(uint8) == 1, "Fix typedefs" ); static_assert( sizeof(int16) == 2, "Fix typedefs" ); static_assert( sizeof(uint16) == 2, "Fix typedefs" ); static_assert( sizeof(uint32) == 4, "Fix typedefs" ); uint GetSourceCountForInstruction( VectorInstructions eOp ); uint GetSrc0WidthInDWORDs( VectorInstructions eOp ); uint GetSrc1WidthInDWORDs( VectorInstructions eOp ); uint GetSrc2WidthInDWORDs( VectorInstructions eOp ); uint GetResultWidthInDWORDs( VectorInstructions eOp ); uint GetDataWidthInDWORDs( DSInstructions eOp ); uint GetResultWidthInDWORDs( BufferInstructions eOp ); bool IsTBufferInstruction( BufferInstructions eOp ); uint GetSamplerWidthInDWORDs( ImageInstructions eOp ); /// The 'Instruction' base class contains all fields for all subclasses in a union /// This is done to allow Instructions to be used in containers without fear of slicing /// /// Code that manipulates instructions should examine the class field and then static_cast to one /// of the concrete classes /// class Instruction { public: Instruction( ) { } InstructionClass GetClass() const { return m_eClass; } protected: Instruction( InstructionClass eClass ) : m_eClass(eClass) { char* pFields = (char*) &Fields; for( size_t i=0; i>lo)&((1<<(1+hi-lo))-1); } int16 GetSIMM16( ) const { return Fields.Scalar.m_nSIMM16; }; uint GetResultWidthInDWORDs() const; uint GetArg0WidthInDWORDs() const; uint GetArg1WidthInDWORDs() const; uint32 GetLiteralAsDWORD() const { return Fields.Scalar.m_Literal.UInt; } ScalarInstructions GetOpcode() const { return Fields.Scalar.m_eOpcode; } uint GetSourceCount() const { return Fields.Scalar.m_nSourceCount; } Sources GetSource(uint i) const { return Fields.Scalar.m_Sources[i]; } Dests GetDest() const { return Fields.Scalar.m_Dest; } bool IsWait() const { return GetOpcode() == S_WAITCNT; }; uint GetVMwaitCount() const { return ReadSIMMBits(3,0); } uint GetEXPWaitCount() const { return ReadSIMMBits(6,4); } uint GetLCGMWaitCount() const { return ReadSIMMBits(12,8); } void EncodeWait( uint vmcnt, uint lcgmcount, uint expcount ) { uint simm = vmcnt | (expcount<<4) | (lcgmcount<<8); Fields.Scalar.m_nSIMM16 = simm; Fields.Scalar.m_eOpcode = S_WAITCNT; } void EncodeSwapPC( ) { Fields.Scalar.m_eOpcode = S_SWAPPC_B64; Fields.Scalar.m_nSourceCount = 1; } }; class ScalarMemoryInstruction : public Instruction { public: ScalarMemoryInstruction() : Instruction(IC_SCALAR_MEM){} uint GetResultWidthInDWORDs() const; uint GetResourceWidthInDWORDs() const ; ScalarMemoryInstructions GetOpcode() const { return Fields.ScalarMem.m_eOpcode; } bool IsOffsetIMM() const { return Fields.ScalarMem.m_bIsOffsetIMM; } bool IsGLC() const { return Fields.ScalarMem.m_bIsGLC; } uint GetOffset() const { return Fields.ScalarMem.m_nOffset; } Dests GetDest() const { return Fields.ScalarMem.m_Dest; } uint GetBase() const { return Fields.ScalarMem.m_nBaseReg; } }; class VectorInstruction : public Instruction { public: VectorInstruction() : Instruction(IC_VECTOR){} VectorInstructions GetOpcode() const { return Fields.Vector.m_eOpcode; } float GetLiteralAsFloat() const { return Fields.Vector.m_Literal.Float; } uint32 GetLiteralAsDWORD() const { return Fields.Vector.m_Literal.UInt; } uint GetSourceAbsMask() const { return Fields.Vector.m_nSourceAbs; } uint GetSourceNegateMask() const { return Fields.Vector.m_nSourceNegate; } uint GetOMod() const { return Fields.Vector.m_nOMOD; } bool GetClamp() const { return Fields.Vector.m_nClamp != 0; } uint GetDestCount() const { return Fields.Vector.m_nDestCount; } uint GetSourceCount() const { return Fields.Vector.m_nSrcCount; } Dests GetSDst() const { return Fields.Vector.m_Dests[1]; }; // VOP3b only Dests GetVDst() const { return Fields.Vector.m_Dests[0]; } Sources GetSrc0() const { return Fields.Vector.m_Sources[0]; } Sources GetVSrc1() const { return Fields.Vector.m_Sources[1]; } Sources GetVSrc2() const { return Fields.Vector.m_Sources[2]; } uint GetSrc0WidthInDWORDS() const { return GetSrc0WidthInDWORDs(GetOpcode()); } uint GetSrc1WidthInDWORDS() const { return GetSrc1WidthInDWORDs(GetOpcode()); } uint GetSrc2WidthInDWORDS() const { return GetSrc2WidthInDWORDs(GetOpcode()); } uint GetResultWidthInDWORDS() const { return GetResultWidthInDWORDs(GetOpcode()); } }; class InterpolationInstruction : public Instruction { public: InterpolationInstruction() : Instruction(IC_VECTOR_INTERP){} VectorInstructions GetOpcode() const { return Fields.Interp.m_eOpcode; } Sources GetVSrc() const { return Fields.Interp.m_VSrc; } Dests GetVDst() const { return Fields.Interp.m_VDst; } uint GetAttributeIndex() const { return Fields.Interp.m_nAttributeIndex; } uint GetAttributeChannel() const { return Fields.Interp.m_nAttributeChannel; } }; class ExportInstruction : public Instruction { public: ExportInstruction() : Instruction(IC_EXPORT){} bool GetCompressBit() const { return Fields.Export.m_Compress; } bool GetDoneBit() const { return Fields.Export.m_Done; } bool GetValidMaskBit() const { return Fields.Export.m_ValidMask; } ExportTargets GetTarget() const { return Fields.Export.m_eTarget; } uint GetExportMask() const { return Fields.Export.m_ChannelMask; } Sources GetVSrc0() const { return Fields.Export.m_Sources[0]; } Sources GetVSrc1() const { return Fields.Export.m_Sources[1]; } Sources GetVSrc2() const { return Fields.Export.m_Sources[2]; } Sources GetVSrc3() const { return Fields.Export.m_Sources[3]; } }; class DataShareInstruction : public Instruction { public: DataShareInstruction() : Instruction(IC_DS){} DSInstructions GetOpcode() const { return Fields.DS.m_eOpcode; } uint GetOffset0() const { return Fields.DS.m_nOffset0; } // Instructions can have one 16 bit offset field or two 8-bit offset fields uint GetOffset1() const { return Fields.DS.m_nOffset1; } uint GetOffset16() const { return Fields.DS.m_nOffset16; } Dests GetVDest() const { return Fields.DS.m_Dest; } Sources GetVData0() const { return Fields.DS.m_VData0; } Sources GetVData1() const { return Fields.DS.m_VData1; } Sources GetVAddr() const { return Fields.DS.m_VAddr; } bool IsGDS() const { return Fields.DS.m_bGDS!=0; } uint GetDataWidthInDWORDS() const { return GetDataWidthInDWORDs( GetOpcode() ); } }; class BufferInstruction : public Instruction { public: BufferInstruction() : Instruction(IC_BUFFER){} BufferInstructions GetOpcode() const { return Fields.Buffer.m_eOpcode; } bool IsDirectToLDS() const { return Fields.Buffer.m_bLDSDirect; } bool GetTFEBit() const { return Fields.Buffer.m_bTFE; } bool GetGLCBit() const { return Fields.Buffer.m_bGLC; } bool GetSLCBit() const { return Fields.Buffer.m_bSLC; } bool IsTBuffer() const { return IsTBufferInstruction( GetOpcode()); } bool IsOffN() const { return Fields.Buffer.m_bOffN; } bool IsIdxN() const { return Fields.Buffer.m_bIdxN;} bool IsAddr64() const { return Fields.Buffer.m_bAddr64; } uint GetOffset() const { return Fields.Buffer.m_nOffset; } TBufferNumberFormats GetNumberFormat() const { return Fields.Buffer.m_eNumberFormat; } TBufferDataFormats GetDataFormat() const { return Fields.Buffer.m_eDataFormat; } Sources GetVData() const { return Fields.Buffer.m_VData; } Sources GetVAddr() const { return Fields.Buffer.m_VAddr; } Sources GetSResource() const { return Fields.Buffer.m_SResource; } Sources GetSOffset() const { return Fields.Buffer.m_SOffset; } uint GetResultWidthInDWORDS() const { return GetResultWidthInDWORDs(GetOpcode()); } /// Test for a store or atomic store bool IsMemoryWrite() const; void SetOpcode( BufferInstructions eOp ) { Fields.Buffer.m_eOpcode = eOp; } }; class ImageInstruction : public Instruction { public: ImageInstruction() : Instruction(IC_IMAGE){} ImageInstructions GetOpcode() const { return Fields.Image.m_eOpcode; } bool IsTFE() const { return Fields.Image.m_bTFE; } bool IsGLC() const { return Fields.Image.m_bGLC; } bool IsSLC() const { return Fields.Image.m_bSLC; } bool IsArray() const { return Fields.Image.m_bArray; } bool IsUnnormalized() const { return Fields.Image.m_bUnnormalized; } bool IsLWE() const { return Fields.Image.m_bLWE; } bool IsD16() const { return Fields.Image.m_bIsD16; } uint GetDMask() const { return Fields.Image.m_nDMask; } Sources GetVData() const { return Fields.Image.m_VData; } Sources GetVAddr() const { return Fields.Image.m_VAddr; } Sources GetSResource() const { return Fields.Image.m_SResource; } Sources GetSSampler() const { return Fields.Image.m_SSampler; } uint GetSamplerWidthInDWORDS() const { return GetSamplerWidthInDWORDs(GetOpcode()); } uint GetResourceWidthInDWORDS() const { return Fields.Image.m_bRes256*4 + 4; } uint GetResultWidthInDWORDS() const; bool IsFilteredFetch() const; bool IsGradientFetch() const; bool IsUnfilteredLoadStore() const; bool IsGather() const; /// Test for a store or atomic store bool IsMemoryWrite() const; }; }; #endif ================================================ FILE: src/Wrapper/GCNSimulator.cpp ================================================ #pragma unmanaged #include "GCNSimulator.h" #include "GCNIsa.h" #include #include #include #include namespace GCN{ namespace Simulator{ namespace _INTERNAL { enum { MAX_WAVES_PER_THREADGROUP = 16, NUM_SIMDS = 4, MAX_WAVES_PER_SIMD = 10, MAX_WAVES_PER_CU = NUM_SIMDS * MAX_WAVES_PER_SIMD, MAX_LCGMCNT = 31, MAX_VMCNT = 15, MAX_EXPCNT = 7, NUM_LDS_QUEUES = 2 }; struct ThreadGroupState; struct WaveState { size_t nCurrentOp; size_t nStartClock; ThreadGroupState* pThreadGroup; uint8 nSIMD; uint8 lkgmcnt; uint8 vmcnt; uint8 expcnt; uint8 nWaveIDInGroup; ///< Index of this wave in its thread group }; struct ThreadGroupState { uint16 nWaitMask; ///< Bit-mask of waves presently waiting at a barrier uint8 nWaves; ///< Number of waves not yet launched uint8 nLaunchedWaves; ///< Number of running waves uint8 nRetiredWaves; ///< Number of waves that have run to completion }; template< class T, int MAX > class RingQueue { public: RingQueue() : m_nFirst(0), m_nLast(0){} bool empty() const { return m_nFirst == m_nLast; } T& front() { return m_Items[(m_nFirst) % MAX]; } void pop_front() { m_nFirst++; }; void push_back( const T& op ) { size_t nLoc = m_nLast++; m_Items[nLoc % MAX] = op; assert( m_nLast - m_nFirst <= MAX ); } size_t size() const { return m_nLast - m_nFirst; } const T& at( size_t i ) const { return m_Items[ (m_nFirst+i)%MAX ]; } private: T m_Items[MAX]; size_t m_nFirst; size_t m_nLast; }; struct SMemOp { size_t nDWORDsLeft; WaveState* pWave; }; struct VMemOp { size_t nClocksLeft; bool bIsExport; WaveState* pWave; }; struct ExportOp { size_t nClocksLeft; WaveState* pWave; }; struct DSOp { size_t nClocksLeft; WaveState* pWave; }; // If your compiler lacks 'PopCount' then you can do something about it here static unsigned int PopCount( unsigned int n ) { return __popcnt((unsigned int)n); } static bool IsBarrier( const Instruction* pOp ) { if( pOp->GetClass() == IC_SCALAR ) { const ScalarInstruction* pScalar = static_cast(pOp); if( pScalar->GetOpcode() == S_BARRIER ) return true; } return false; } /// Search for a threadgroup structure that isn't in use static ThreadGroupState* FindAvailableThreadGroup( ThreadGroupState pGroups[MAX_WAVES_PER_CU], size_t nOccupancyLimit ) { for( size_t i=0; ilkgmcnt == MAX_LCGMCNT ) continue; const GCN::Instruction* pOp = pOps[ppWaves[i]->nCurrentOp].pInstruction; if( pOp->GetClass() != GCN::IC_DS ) continue; const GCN::DataShareInstruction* pDS = static_cast(pOp); if( pDS->IsGDS() ) continue; return ppWaves[i]; } return 0; } /// Search list of waves for oldest one that wants to issue a scalar static WaveState* FindScalarToIssue( const SimOp* pOps, WaveState** pWaves, size_t nWaves ) { WaveState* pIssueWave=0; // look for a wave which has a scalar op, where said scalar op is not // one of the freebies for( size_t i=0; inCurrentOp].pInstruction; if( pOp->GetClass() != GCN::IC_SCALAR_MEM && pOp->GetClass() != GCN::IC_SCALAR ) continue; // Throttle instruction issue of there are more scalars in flight // than we have counter bits for // // CLARIFICATION NEEDED: Is this what HW does? // if( pOp->GetClass() == GCN::IC_SCALAR_MEM && pWaves[i]->lkgmcnt == MAX_LCGMCNT ) continue; if( pOp->GetClass() == IC_SCALAR ) { const GCN::ScalarInstruction* pScalar = static_cast( pOp ); switch( pScalar->GetOpcode() ) { case S_NOP : case S_ENDPGM : case S_BARRIER : case S_SETHALT : case S_SLEEP : case S_SETPRIO : case S_ENDPGM_SAVED : case S_WAITCNT : continue; } } // We can issue this one. // but give priority to older waves if( !pIssueWave || pIssueWave->nStartClock > pWaves[i]->nStartClock ) pIssueWave = pWaves[i]; } return pIssueWave; } /// Search list of waves for oldest one that wants to issue a valu static WaveState* FindVALUToIssue( const SimOp* pOps, WaveState** pWaves, size_t nWaves ) { WaveState* pIssueWave=0; // look for a wave which has a VALU op to issue for( size_t i=0; inCurrentOp].pInstruction; if( pOp->GetClass() != GCN::IC_VECTOR && pOp->GetClass() != GCN::IC_VECTOR_INTERP) continue; // We can issue this one. // but give priority to older waves if( !pIssueWave || pIssueWave->nStartClock > pWaves[i]->nStartClock ) pIssueWave = pWaves[i]; } return pIssueWave; } /// Is instruction a vector memory write? static bool IsVMEMWrite( const GCN::Instruction* pOp ) { switch( pOp->GetClass() ) { default: return false; case GCN::IC_IMAGE: { const GCN::ImageInstruction* pImg = static_cast(pOp); return pImg->IsMemoryWrite(); } break; case GCN::IC_BUFFER: { const GCN::BufferInstruction* pImg = static_cast(pOp); return pImg->IsMemoryWrite(); } break; } } /// Search a list of waves for oldest one that wants to issue a vmem static WaveState* FindVMEMToIssue( const SimOp* pOps, WaveState** pWaves, size_t nWaves ) { WaveState* pIssueWave=0; // look for a wave which has a VALU op to issue for( size_t i=0; inCurrentOp].pInstruction; if( pOp->GetClass() != GCN::IC_BUFFER && pOp->GetClass() != GCN::IC_IMAGE ) continue; // Throttle instruction issue of there are more OPS in flight // than we have counter bits for // // CLARIFICATION NEEDED: Is this what HW does? // if( pWaves[i]->vmcnt == MAX_VMCNT ) continue; if( IsVMEMWrite(pOp) && pWaves[i]->expcnt == MAX_EXPCNT ) continue; // We can issue this one. // but give priority to older waves if( !pIssueWave || pIssueWave->nStartClock > pWaves[i]->nStartClock ) pIssueWave = pWaves[i]; } return pIssueWave; } /// Search a list of waves for oldest one that wants to issue an export static WaveState* FindExportToIssue( const SimOp* pOps, WaveState** pWaves, size_t nWaves ) { WaveState* pIssueWave=0; // look for a wave which has an export to issue for( size_t i=0; inCurrentOp].pInstruction; if( pOp->GetClass() != GCN::IC_EXPORT ) continue; // Throttle instruction issue of there are more OPS in flight // than we have counter bits for // // CLARIFICATION NEEDED: Is this what HW does? // if( pWaves[i]->expcnt == MAX_EXPCNT ) continue; // We can issue this one. // but give priority to older waves if( !pIssueWave || pIssueWave->nStartClock > pWaves[i]->nStartClock ) pIssueWave = pWaves[i]; } return pIssueWave; } /// Determine the cost in cycles of a VMEM instruction, /// Taking format and filtering into account static size_t GetVMEMCost( const SimOp* pSimOp ) { const GCN::Instruction* pOp = pSimOp->pInstruction; switch( pOp->GetClass() ) { default: return 4; case GCN::IC_BUFFER: { // 16 "load store units" --> 4 clocks/wave/dword const GCN::BufferInstruction* pBuff = static_cast(pOp); return pBuff->GetResultWidthInDWORDS()*4; } break; case GCN::IC_IMAGE: { const GCN::ImageInstruction* pImg = static_cast(pOp); if( pImg->IsFilteredFetch() ) { size_t nBaseCost=0; // perf depends on format and filter type if( pSimOp->eFilter == FILT_POINT ) nBaseCost = 16; // point sampling is 4 pix/clk for all formats else { // baseline for bilinear is 4 pixels/clk size_t nCost = 0; switch( pSimOp->eFormat ) { case FMT_RGBA32F: nCost = 64; // 1/4 rate break; case FMT_RGBA16: case FMT_RGBA16F: case FMT_RG32F: case FMT_BC6: nCost = 32; // 1/2 rate break; default: nCost = 16; break; } // modify by filter type switch( pSimOp->eFilter ) { case FILT_TRILINEAR: case FILT_ANISO_2X: nCost *= 2; break; case FILT_ANISO_4X: nCost *= 4; break; case FILT_ANISO_8X: nCost *= 8; break; } nBaseCost= nCost; } // APPROXIMATION: Gradient fetches are approximately 2x cost // // It's actually full rate for 4 dwords/thread of input // and an extra clock for each additional 4 // // This 2x assumes a 2D gradient fetch where derivatives // can all go in one extra clock // 3D is more expensive, 1D possibly less // Unfortunately ISA doesn't tell us // what tx type we're dealing with // // Not clear if a thread can overlap extra argument cost // with expensive filtering and have these cancel out // if( pImg->IsGradientFetch() ) nBaseCost *= 2; return nBaseCost; } else if( pImg->IsGather() ) { // gather is just like a point-sampled fetch. 4x4 pix/clk return 16; } else { // AMD says that Image load/store gets capped at 4 pixels/clk // due to more complicated addressing return 16; } } break; } } /// Determine the cost in cycles of a vector instruction static size_t GetVALUCost( const GCN::Instruction* pOp ) { if( pOp->GetClass() == GCN::IC_VECTOR_INTERP ) { // CLARIFICATION NEEDED: // Assuming that interps are as cheap as regular VALU. Is this correct? return 4; } else { const GCN::VectorInstruction* pVALU = static_cast( pOp ); // Costs based on humus's presentation, here: // http://www.humus.name/Articles/Persson_LowlevelShaderOptimization.pdf // // CLARIFICAITON NEEDED: // What did I miss? switch( pVALU->GetOpcode() ) { // anything not expressly called out below is 4 clocks default: return 4; // Int32 multiply: 1/4 rate case V_MUL_LO_U32: case V_MUL_HI_U32: case V_MUL_LO_I32: case V_MUL_HI_I32: return 16; // float transcendentals: 1/4 rate case V_EXP_F32 : case V_LOG_CLAMP_F32 : case V_LOG_F32 : case V_RCP_CLAMP_F32 : case V_RCP_LEGACY_F32 : case V_RCP_F32 : case V_RCP_IFLAG_F32 : case V_RSQ_CLAMP_F32 : case V_RSQ_LEGACY_F32 : case V_RSQ_F32 : case V_SQRT_F32 : case V_SIN_F32 : case V_COS_F32 : case V_LOG_LEGACY_F32 : case V_EXP_LEGACY_F32 : case V_RCP_F16 : case V_SQRT_F16 : case V_RSQ_F16 : case V_LOG_F16 : case V_EXP_F16 : case V_SIN_F16 : case V_COS_F16 : case V_DIV_SCALE_F32 : case V_DIV_FIXUP_F32 : // Clarification needed case V_DIV_FMAS_F32 : // Do these divs count as transcendentals? return 16; // DP add: case V_ADD_F64 : return 8; // DP mul/mad case V_FMA_F64 : case V_MUL_F64 : return 16; // CLARIFICATION NEEDED // Are DP transcendentals 1/2 float rate? Can't find a source. case V_RCP_F64 : case V_RCP_CLAMP_F64 : case V_RSQ_F64 : case V_RSQ_CLAMP_F64 : case V_SQRT_F64 : case V_DIV_SCALE_F64 : case V_DIV_FIXUP_F64 : case V_DIV_FMAS_F64 : return 32; } } } static uint GetExportCost( const GCN::Instruction* pOp, uint nBaseCost ) { const GCN::ExportInstruction* pExp = static_cast( pOp ); if( pExp->GetCompressBit() ) return nBaseCost; else return nBaseCost*2; } /// Test whether a given wave can issue one of the "free" scalar operations static bool CanIssueFreeScalarOp( const GCN::Instruction* pOp, WaveState* pWave ) { if( pOp->GetClass() != GCN::IC_SCALAR ) return false; const GCN::ScalarInstruction* pScalar = static_cast( pOp ); switch( pScalar->GetOpcode() ) { case S_NOP : case S_SETHALT : case S_SLEEP : case S_SETPRIO : return true; // don't move past a barrier until the wave's corresponding bit in the wait mask // has been cleared. This happens during the barrier processing phase, which // comes before this point in the sim cycle case S_BARRIER: { size_t nWaveBit = 1 << pWave->nWaveIDInGroup; if( pWave->pThreadGroup->nWaitMask & nWaveBit ) return false; return true; } break; // don't issue endpgm until all the counters drop to zero case S_ENDPGM : case S_ENDPGM_SAVED : if( pWave->lkgmcnt == 0 && pWave->expcnt == 0 && pWave->vmcnt == 0 ) { return true; } break; case S_WAITCNT : { if( pWave->lkgmcnt <= pScalar->GetLCGMWaitCount() && pWave->expcnt <= pScalar->GetEXPWaitCount() && pWave->vmcnt <= pScalar->GetVMwaitCount() ) { return true; } } break; } return false; } } void Simulate( Results& rResults, const Settings& rSettings, SimOp* pOps, size_t nOps ) { using namespace _INTERNAL; size_t nClock = 0; size_t nRetiredWaves = 0; size_t nIssuedWaves = 0; size_t nGroupsInFlight = 0; size_t nWavesToExecute = rSettings.nWavesPerThreadGroup*rSettings.nGroupsToExecute; ThreadGroupState pThreadGroups[MAX_WAVES_PER_CU] = {0}; WaveState pWaveFronts[MAX_WAVES_PER_CU] = {0}; WaveState* pWavesInFlight[NUM_SIMDS][MAX_WAVES_PER_SIMD] = {0}; uint8 pWaveCount[NUM_SIMDS] = {0}; ThreadGroupState* pIssuingThreadGroup=0; WaveState* pWavesInVALU[NUM_SIMDS] = {0}; ///< Wave currently occupying each VALU size_t pVALUCycles[NUM_SIMDS] = {0}; ///< Number of cycles remaining on each VALU op RingQueue SMemQueue; RingQueue VMemQueue; RingQueue EXPQueue; // LDS/SIMD interface looks like this: // // SIMD 0/1 SIMD 2/3 // 16 lanes 16 lanes // // However, each "lane" is two dwords wide (so 32 dwords/wave) // At peak, two waves can read two DWORDS/thread over four clocks // RingQueue LDSQueue[NUM_LDS_QUEUES]; size_t nGroupDelay= rSettings.nGroupIssueRate; // Time in cycles since a threadgroup was started while(1) { // Issue new wavefront if its time if( nIssuedWaves < nWavesToExecute ) { if( !pIssuingThreadGroup ) { if( nGroupDelay >= rSettings.nGroupIssueRate ) { // start issuing a new thread group after the specified time interval has elapsed // This is to model the effect of fixed-function units (ACE, VGT, Rasterizer, etc) // round-robining waves across available CUs pIssuingThreadGroup = FindAvailableThreadGroup(pThreadGroups,rSettings.nMaxGroupsPerCU); if( pIssuingThreadGroup ) { pIssuingThreadGroup->nWaves = rSettings.nWavesPerThreadGroup; pIssuingThreadGroup->nLaunchedWaves = 0; pIssuingThreadGroup->nRetiredWaves = 0; pIssuingThreadGroup->nWaitMask = 0; nGroupsInFlight++; } nGroupDelay=0; } else { // count cycles until next group can start nGroupDelay++; } } // If we have a thread group to issue waves from, then issue from it each and every cycle // Layla slides state that the ACE's an issue one wave per clock to the CUs. We'll assume // that the scheduler shoots a wave to the current CU every clock until its done, then moves on ot the next one if( pIssuingThreadGroup ) { WaveState* pWave = FindAvailableWave( pWaveFronts ); if( !pWave ) { // means that the CU is completely full. Good for us. // TODO: Track this...? } else { // CLARIFICATION NEEDED: // I don't know precisely what the rules are for mapping newly issued waves to SIMDs // let's assume simple round-robin until somebody tells us different size_t nSIMD = nIssuedWaves % NUM_SIMDS; if( pWaveCount[nSIMD] < rSettings.nMaxWavesPerSIMD ) { pWavesInFlight[nSIMD][pWaveCount[nSIMD]++] = pWave; pWave->nSIMD = nSIMD; pWave->nStartClock = nClock; pWave->nCurrentOp = 0; pWave->pThreadGroup = pIssuingThreadGroup; pWave->nWaveIDInGroup = pIssuingThreadGroup->nLaunchedWaves; nIssuedWaves++; pIssuingThreadGroup->nLaunchedWaves++; if( pIssuingThreadGroup->nLaunchedWaves == pIssuingThreadGroup->nWaves ) pIssuingThreadGroup = NULL; } } } } // Tick the LDS pipe // Count as busy if either of the two Queues are running for( size_t i=0; ilkgmcnt--; LDSQueue[i].pop_front(); } rResults.nLDSBusy++; } } // tick the vmem pipe if( !VMemQueue.empty() ) { VMemOp& op = VMemQueue.front(); op.nClocksLeft--; if( op.nClocksLeft == 0 ) { op.pWave->vmcnt--; if( op.bIsExport ) op.pWave->expcnt--; VMemQueue.pop_front(); } rResults.nVMemBusy++; } // Tick the SMem pipe // SMem rate is 4 dwords/CU/clk // // CLARIFICATION NEEDED: // For simplicity, assume here that we only retire one instruction per clock // but I don't know if the hardware is smarter than that. They have 16 bytes/clk // of bandwidth, and they might be able to parcel it out to multiple waiting waves. if( !SMemQueue.empty() ) { SMemOp& op = SMemQueue.front(); if( op.nDWORDsLeft <= 4 ) { op.pWave->lkgmcnt--; SMemQueue.pop_front(); } else { op.nDWORDsLeft -= 4; } rResults.nSMemBusy++; } // Tick the EXP pipe if( !EXPQueue.empty() ) { ExportOp& exp = EXPQueue.front(); exp.nClocksLeft--; if( exp.nClocksLeft == 0 ) { exp.pWave->expcnt--; EXPQueue.pop_front(); } rResults.nExpBusy++; } // tick all the VALUs for( size_t i=0; inCurrentOp++; pWavesInVALU[i]=0; } } } size_t nCurrentSIMD = nClock % NUM_SIMDS; WaveState** pSIMDWaves = pWavesInFlight[nCurrentSIMD]; size_t nWaves = pWaveCount[nCurrentSIMD]; // Try and issue an LDS WaveState* pLDSWave = FindLDSToIssue( pOps, pSIMDWaves, nWaves ); if( pLDSWave ) { // TODO: Assuming best-case latency of 4 clocks. What abount Bank conflicts? // How to model this in a way that's useful? DSOp ds; ds.nClocksLeft = 4; ds.pWave = pLDSWave; LDSQueue[nCurrentSIMD/2].push_back( ds ); pLDSWave->lkgmcnt++; } // Try and issue a scalar WaveState* pScalarWave = FindScalarToIssue( pOps, pSIMDWaves, nWaves ); if( pScalarWave ) { const SimOp* pOp = &pOps[pScalarWave->nCurrentOp]; const GCN::Instruction* pInst = pOp->pInstruction; if( pInst->GetClass() == IC_SCALAR_MEM ) { // NOTE: Ignoring the possibility the the counters might overflow // If that happens, the simulator will be unsable // but I'm assuming I won't be asked to simulate incorrect code // pScalarWave->lkgmcnt++; const ScalarMemoryInstruction* pSMem = static_cast(pInst); SMemOp op; op.nDWORDsLeft = pSMem->GetResultWidthInDWORDs(); op.pWave = pScalarWave; SMemQueue.push_back(op); } else { // assume SALU is always free and finishes instantly rResults.nSALUBusy++; } } // Try and issue a valu if the ALU is not busy // ALU can still be busy if it is stuck doing a long-latency op like an rsq WaveState* pVALUWave = 0; if( pWavesInVALU[nCurrentSIMD] == 0 ) { pVALUWave = FindVALUToIssue( pOps, pSIMDWaves, nWaves ); if( pVALUWave ) { size_t nCost = GetVALUCost( pOps[pVALUWave->nCurrentOp].pInstruction ); pVALUCycles[nCurrentSIMD] = nCost; pWavesInVALU[nCurrentSIMD] = pVALUWave; } } // Try and issue a vmem WaveState* pVMemWave = FindVMEMToIssue( pOps, pSIMDWaves, nWaves ); if( pVMemWave ) { VMemOp op; op.nClocksLeft = GetVMEMCost( &pOps[pVMemWave->nCurrentOp] ); op.pWave = pVMemWave; op.bIsExport = IsVMEMWrite( pOps[pVMemWave->nCurrentOp].pInstruction ); if( op.bIsExport ) pVMemWave->expcnt++; pVMemWave->vmcnt++; VMemQueue.push_back( op ); } // Try and issue an export WaveState* pExpWave = FindExportToIssue( pOps, pSIMDWaves, nWaves ); if( pExpWave ) { ExportOp op; op.nClocksLeft = GetExportCost( pOps[pExpWave->nCurrentOp].pInstruction, rSettings.nExportCost ); op.pWave = pExpWave; pExpWave->expcnt++; EXPQueue.push_back(op); } // Barrier pre-processing // - Mark all waves on this SIMD which have reached a barrier instruction // When all threads reach the barrier, their IPs will be advanced // during the "Free Scalar" phase which follows // // This scheme is safe, because a released thread on one SIMD will execute // at most one other instruction before all the remaining threads have been released // // In the case of two S_BARRIER's back to back, the // use of bit-masks should ensure that we do the right thing // because each thread will advance only if ITs mask is cleared // for( size_t i=0; ipThreadGroup; const SimOp* pOp = &pOps[pWave->nCurrentOp]; if( IsBarrier(pOp->pInstruction) ) { // add this wave to the list of waiting waves size_t nWaitMask = pGroup->nWaitMask; nWaitMask |= (1<nWaveIDInGroup); // release waiting waves once all waves' bits have been added to the mask size_t nGroupWaves = (pWave->pThreadGroup->nWaves - pWave->pThreadGroup->nRetiredWaves); if( PopCount(nWaitMask) == nGroupWaves ) pGroup->nWaitMask=0; else pGroup->nWaitMask = (uint16)nWaitMask; } } // Issue "helper" instructions for all waves that can issue them // nop, sleep, wait, barrier, setprio, s_endpgm size_t nFreeOps=0; for( size_t i=0; inCurrentOp]; if( CanIssueFreeScalarOp(pOp->pInstruction, pWave) ) { nFreeOps++; pWave->nCurrentOp++; } } // retire any waves that have finished their trace for( size_t i=0; inRetiredWaves++; if( pWaveFronts[i].pThreadGroup->nRetiredWaves == pWaveFronts[i].pThreadGroup->nWaves ) { // retire thread groups for which all waves are done memset(pWaveFronts[i].pThreadGroup, 0, sizeof(*(pWaveFronts[i].pThreadGroup))); nGroupsInFlight--; } pWaveFronts[i].pThreadGroup = 0; nRetiredWaves++; } } // purge any retired waves from the in-flight lists for( size_t i=0; ipThreadGroup ) pWavesInFlight[i][nLive++] = pWavesInFlight[i][w]; pWaveCount[i] = nLive; } nClock++; if( nRetiredWaves == nWavesToExecute ) break; // track peak occupancy size_t nWaveOcc=0; for( size_t i=0; i rResults.nPeakWaveOccupancy) rResults.nPeakWaveOccupancy = nWaveOcc; if( nWaveOcc == 0 ) rResults.nStarveCycles++; if( nGroupsInFlight > rResults.nPeakGroupOccupancy ) rResults.nPeakGroupOccupancy = nGroupsInFlight; if( pLDSWave ) { rResults.nLDSIssued++; pLDSWave->nCurrentOp++; } if( pScalarWave ) { if( pOps[pScalarWave->nCurrentOp].pInstruction->GetClass() == IC_SCALAR_MEM ) rResults.nSMEMIssued++; else rResults.nSALUIssued++; pScalarWave->nCurrentOp++; } // VALU waves don't get their IP incremented // until after the op completes. This is done to ensure that the wave // blocks itself if it's doing a long-latency operation if( pVALUWave ) { rResults.nVALUIssued++; } if( pVMemWave ) { pVMemWave->nCurrentOp++; rResults.nVMemIssued++; } if( pExpWave ) { pExpWave->nCurrentOp++; rResults.nExpIssued++; } // check for clocks where nothing happens and track them // Don't count as a stall if VALU is occupied by a long-latency op bool bVALUStarved = !pVALUWave && !pWavesInVALU[nCurrentSIMD]; if( !pScalarWave && bVALUStarved && !pVMemWave && !pExpWave && !pLDSWave && !nFreeOps && pWaveCount[nCurrentSIMD] ) { rResults.nStallCycles[nCurrentSIMD]++; // find the set of distinct SimOps on which we're stalled size_t pDistinctSimOps[MAX_WAVES_PER_SIMD]; size_t nDistinctSimOps=0; for( size_t w=0; wnCurrentOp; // de-duplicate, and increment stall count on each stalled SimOp std::sort( pDistinctSimOps, pDistinctSimOps+nDistinctSimOps ); for( size_t i=0; i(); if( !m_bError ) { glslopt_shader_get_stats( pShader, &nMath, &nTexture, &nFlow ); m_nMath = nMath; m_nTexture = nTexture; m_nFlow = nFlow; int nInputs = glslopt_shader_get_input_count( m_pShader ); for( int i=0; iAdd( MakeString(pName) ); } } } Shader_Impl::~Shader_Impl() { glslopt_shader_delete(m_pShader); } Optimizer_Impl::Optimizer_Impl( Pyramid::GLSLOptimizer::Target eTarget ) { switch( eTarget ) { case Target::OPENGL: m_pContext = glslopt_initialize( kGlslTargetOpenGL ); break; case Target::OPENGL_ES2: m_pContext = glslopt_initialize( kGlslTargetOpenGLES20 ); break; case Target::OPENGL_ES3: m_pContext = glslopt_initialize( kGlslTargetOpenGLES30 ); break; } } Optimizer_Impl::~Optimizer_Impl() { glslopt_cleanup(m_pContext); } IShader^ Optimizer_Impl::Optimize(System::String^ text, IOptions^ opts) { glslopt_shader_type eShaderType; switch( opts->ShaderType ) { default: return nullptr; case ShaderType::VERTEX: eShaderType = kGlslOptShaderVertex; break; case ShaderType::FRAGMENT: eShaderType = kGlslOptShaderFragment; break; } MarshalledString marshalledText(text); glslopt_set_max_unroll_iterations( m_pContext, opts->MaxUnrollIterations ); glslopt_shader* pShader = glslopt_optimize( m_pContext, eShaderType, marshalledText, 0 ); return gcnew Shader_Impl(pShader,this); } }} ================================================ FILE: src/Wrapper/GLSLOpt_Impl.h ================================================ #include "Utilities.h" struct glslopt_shader; struct glslopt_ctx; using namespace System::Collections::Generic; using namespace System::Runtime::InteropServices; namespace Pyramid{ namespace GLSLOptimizer{ ref class Optimizer_Impl : IOptimizer { public: Optimizer_Impl( Target eTarget ); ~Optimizer_Impl(); virtual IShader^ Optimize(System::String^ text, IOptions^ opts); private: glslopt_ctx* m_pContext; }; ref class Shader_Impl : IShader { public: Shader_Impl( glslopt_shader* pShader, IOptimizer^ owner ); ~Shader_Impl(); virtual property bool HadError { bool get() { return m_bError; }}; virtual property System::String^ Output { System::String^ get() { return MakeString(m_pOutput); }} virtual property System::String^ RawOutput { System::String^ get() { return MakeString(m_pOutputRaw); }} virtual property System::String^ Log { System::String^ get() { return MakeString(m_pLog); }} virtual property IEnumerable^ Inputs { IEnumerable^ get(){ return m_Inputs; }} virtual property int MathOps { int get() { return m_nMath; }} virtual property int TextureOps { int get() { return m_nTexture; } } virtual property int ControlFlowOps { int get() { return m_nFlow; } } private: glslopt_shader* m_pShader; int m_nMath; int m_nTexture; int m_nFlow; bool m_bError; const char* m_pLog; const char* m_pOutput; const char* m_pOutputRaw; List^ m_Inputs; IOptimizer^ m_Owner; ///< Hold a reference in case .NET tries to destroy shader/optimizer out of order }; }} ================================================ FILE: src/Wrapper/GLSlang_Impl.cpp ================================================ #define _CRT_SECURE_NO_WARNINGS #pragma unmanaged #include "GLSlang/glslang/Public/ShaderLang.h" #include "GLSlang/glslang/Include/ResourceLimits.h" #include "GLSlang/SPIRV/GlslangToSpv.h" #include "GLSlang/SPIRV/disassemble.h" #include #pragma managed #include "Utilities.h" #include "GLSlang_Impl.h" // // These are the default resources for TBuiltInResources, used for both // - parsing this string for the case where the user didn't supply one // - dumping out a template for user construction of a config file // const char* DefaultConfig = "MaxLights 32\n" "MaxClipPlanes 6\n" "MaxTextureUnits 32\n" "MaxTextureCoords 32\n" "MaxVertexAttribs 64\n" "MaxVertexUniformComponents 4096\n" "MaxVaryingFloats 64\n" "MaxVertexTextureImageUnits 32\n" "MaxCombinedTextureImageUnits 80\n" "MaxTextureImageUnits 32\n" "MaxFragmentUniformComponents 4096\n" "MaxDrawBuffers 32\n" "MaxVertexUniformVectors 128\n" "MaxVaryingVectors 8\n" "MaxFragmentUniformVectors 16\n" "MaxVertexOutputVectors 16\n" "MaxFragmentInputVectors 15\n" "MinProgramTexelOffset -8\n" "MaxProgramTexelOffset 7\n" "MaxClipDistances 8\n" "MaxComputeWorkGroupCountX 65535\n" "MaxComputeWorkGroupCountY 65535\n" "MaxComputeWorkGroupCountZ 65535\n" "MaxComputeWorkGroupSizeX 1024\n" "MaxComputeWorkGroupSizeX 1024\n" "MaxComputeWorkGroupSizeZ 64\n" "MaxComputeUniformComponents 1024\n" "MaxComputeTextureImageUnits 16\n" "MaxComputeImageUniforms 8\n" "MaxComputeAtomicCounters 8\n" "MaxComputeAtomicCounterBuffers 1\n" "MaxVaryingComponents 60\n" "MaxVertexOutputComponents 64\n" "MaxGeometryInputComponents 64\n" "MaxGeometryOutputComponents 128\n" "MaxFragmentInputComponents 128\n" "MaxImageUnits 8\n" "MaxCombinedImageUnitsAndFragmentOutputs 8\n" "MaxImageSamples 0\n" "MaxVertexImageUniforms 0\n" "MaxTessControlImageUniforms 0\n" "MaxTessEvaluationImageUniforms 0\n" "MaxGeometryImageUniforms 0\n" "MaxFragmentImageUniforms 8\n" "MaxCombinedImageUniforms 8\n" "MaxGeometryTextureImageUnits 16\n" "MaxGeometryOutputVertices 256\n" "MaxGeometryTotalOutputComponents 1024\n" "MaxGeometryUniformComponents 1024\n" "MaxGeometryVaryingComponents 64\n" "MaxTessControlInputComponents 128\n" "MaxTessControlOutputComponents 128\n" "MaxTessControlTextureImageUnits 16\n" "MaxTessControlUniformComponents 1024\n" "MaxTessControlTotalOutputComponents 4096\n" "MaxTessEvaluationInputComponents 128\n" "MaxTessEvaluationOutputComponents 128\n" "MaxTessEvaluationTextureImageUnits 16\n" "MaxTessEvaluationUniformComponents 1024\n" "MaxTessPatchComponents 120\n" "MaxPatchVertices 32\n" "MaxTessGenLevel 64\n" "MaxViewports 16\n" "MaxVertexAtomicCounters 0\n" "MaxTessControlAtomicCounters 0\n" "MaxTessEvaluationAtomicCounters 0\n" "MaxGeometryAtomicCounters 0\n" "MaxFragmentAtomicCounters 8\n" "MaxCombinedAtomicCounters 8\n" "MaxAtomicCounterBindings 1\n" "MaxVertexAtomicCounterBuffers 0\n" "MaxTessControlAtomicCounterBuffers 0\n" "MaxTessEvaluationAtomicCounterBuffers 0\n" "MaxGeometryAtomicCounterBuffers 0\n" "MaxFragmentAtomicCounterBuffers 1\n" "MaxCombinedAtomicCounterBuffers 1\n" "MaxAtomicCounterBufferSize 16384\n" "MaxTransformFeedbackBuffers 4\n" "MaxTransformFeedbackInterleavedComponents 64\n" "nonInductiveForLoops 1\n" "whileLoops 1\n" "doWhileLoops 1\n" "generalUniformIndexing 1\n" "generalAttributeMatrixVectorIndexing 1\n" "generalVaryingIndexing 1\n" "generalSamplerIndexing 1\n" "generalVariableIndexing 1\n" "generalConstantMatrixVectorIndexing 1\n" ; // // Parse either a .conf file provided by the user or the default string above. // void ProcessConfigFile( TBuiltInResource& Resources, char* config ) { const char* delims = " \t\n\r"; const char* token = strtok(config, delims); while (token) { const char* valueStr = strtok(0, delims); if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) { printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : ""); return; } int value = atoi(valueStr); if (strcmp(token, "MaxLights") == 0) Resources.maxLights = value; else if (strcmp(token, "MaxClipPlanes") == 0) Resources.maxClipPlanes = value; else if (strcmp(token, "MaxTextureUnits") == 0) Resources.maxTextureUnits = value; else if (strcmp(token, "MaxTextureCoords") == 0) Resources.maxTextureCoords = value; else if (strcmp(token, "MaxVertexAttribs") == 0) Resources.maxVertexAttribs = value; else if (strcmp(token, "MaxVertexUniformComponents") == 0) Resources.maxVertexUniformComponents = value; else if (strcmp(token, "MaxVaryingFloats") == 0) Resources.maxVaryingFloats = value; else if (strcmp(token, "MaxVertexTextureImageUnits") == 0) Resources.maxVertexTextureImageUnits = value; else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0) Resources.maxCombinedTextureImageUnits = value; else if (strcmp(token, "MaxTextureImageUnits") == 0) Resources.maxTextureImageUnits = value; else if (strcmp(token, "MaxFragmentUniformComponents") == 0) Resources.maxFragmentUniformComponents = value; else if (strcmp(token, "MaxDrawBuffers") == 0) Resources.maxDrawBuffers = value; else if (strcmp(token, "MaxVertexUniformVectors") == 0) Resources.maxVertexUniformVectors = value; else if (strcmp(token, "MaxVaryingVectors") == 0) Resources.maxVaryingVectors = value; else if (strcmp(token, "MaxFragmentUniformVectors") == 0) Resources.maxFragmentUniformVectors = value; else if (strcmp(token, "MaxVertexOutputVectors") == 0) Resources.maxVertexOutputVectors = value; else if (strcmp(token, "MaxFragmentInputVectors") == 0) Resources.maxFragmentInputVectors = value; else if (strcmp(token, "MinProgramTexelOffset") == 0) Resources.minProgramTexelOffset = value; else if (strcmp(token, "MaxProgramTexelOffset") == 0) Resources.maxProgramTexelOffset = value; else if (strcmp(token, "MaxClipDistances") == 0) Resources.maxClipDistances = value; else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0) Resources.maxComputeWorkGroupCountX = value; else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0) Resources.maxComputeWorkGroupCountY = value; else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0) Resources.maxComputeWorkGroupCountZ = value; else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0) Resources.maxComputeWorkGroupSizeX = value; else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0) Resources.maxComputeWorkGroupSizeY = value; else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0) Resources.maxComputeWorkGroupSizeZ = value; else if (strcmp(token, "MaxComputeUniformComponents") == 0) Resources.maxComputeUniformComponents = value; else if (strcmp(token, "MaxComputeTextureImageUnits") == 0) Resources.maxComputeTextureImageUnits = value; else if (strcmp(token, "MaxComputeImageUniforms") == 0) Resources.maxComputeImageUniforms = value; else if (strcmp(token, "MaxComputeAtomicCounters") == 0) Resources.maxComputeAtomicCounters = value; else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0) Resources.maxComputeAtomicCounterBuffers = value; else if (strcmp(token, "MaxVaryingComponents") == 0) Resources.maxVaryingComponents = value; else if (strcmp(token, "MaxVertexOutputComponents") == 0) Resources.maxVertexOutputComponents = value; else if (strcmp(token, "MaxGeometryInputComponents") == 0) Resources.maxGeometryInputComponents = value; else if (strcmp(token, "MaxGeometryOutputComponents") == 0) Resources.maxGeometryOutputComponents = value; else if (strcmp(token, "MaxFragmentInputComponents") == 0) Resources.maxFragmentInputComponents = value; else if (strcmp(token, "MaxImageUnits") == 0) Resources.maxImageUnits = value; else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0) Resources.maxCombinedImageUnitsAndFragmentOutputs = value; else if (strcmp(token, "MaxImageSamples") == 0) Resources.maxImageSamples = value; else if (strcmp(token, "MaxVertexImageUniforms") == 0) Resources.maxVertexImageUniforms = value; else if (strcmp(token, "MaxTessControlImageUniforms") == 0) Resources.maxTessControlImageUniforms = value; else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0) Resources.maxTessEvaluationImageUniforms = value; else if (strcmp(token, "MaxGeometryImageUniforms") == 0) Resources.maxGeometryImageUniforms = value; else if (strcmp(token, "MaxFragmentImageUniforms") == 0) Resources.maxFragmentImageUniforms = value; else if (strcmp(token, "MaxCombinedImageUniforms") == 0) Resources.maxCombinedImageUniforms = value; else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0) Resources.maxGeometryTextureImageUnits = value; else if (strcmp(token, "MaxGeometryOutputVertices") == 0) Resources.maxGeometryOutputVertices = value; else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0) Resources.maxGeometryTotalOutputComponents = value; else if (strcmp(token, "MaxGeometryUniformComponents") == 0) Resources.maxGeometryUniformComponents = value; else if (strcmp(token, "MaxGeometryVaryingComponents") == 0) Resources.maxGeometryVaryingComponents = value; else if (strcmp(token, "MaxTessControlInputComponents") == 0) Resources.maxTessControlInputComponents = value; else if (strcmp(token, "MaxTessControlOutputComponents") == 0) Resources.maxTessControlOutputComponents = value; else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0) Resources.maxTessControlTextureImageUnits = value; else if (strcmp(token, "MaxTessControlUniformComponents") == 0) Resources.maxTessControlUniformComponents = value; else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0) Resources.maxTessControlTotalOutputComponents = value; else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0) Resources.maxTessEvaluationInputComponents = value; else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0) Resources.maxTessEvaluationOutputComponents = value; else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0) Resources.maxTessEvaluationTextureImageUnits = value; else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0) Resources.maxTessEvaluationUniformComponents = value; else if (strcmp(token, "MaxTessPatchComponents") == 0) Resources.maxTessPatchComponents = value; else if (strcmp(token, "MaxPatchVertices") == 0) Resources.maxPatchVertices = value; else if (strcmp(token, "MaxTessGenLevel") == 0) Resources.maxTessGenLevel = value; else if (strcmp(token, "MaxViewports") == 0) Resources.maxViewports = value; else if (strcmp(token, "MaxVertexAtomicCounters") == 0) Resources.maxVertexAtomicCounters = value; else if (strcmp(token, "MaxTessControlAtomicCounters") == 0) Resources.maxTessControlAtomicCounters = value; else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0) Resources.maxTessEvaluationAtomicCounters = value; else if (strcmp(token, "MaxGeometryAtomicCounters") == 0) Resources.maxGeometryAtomicCounters = value; else if (strcmp(token, "MaxFragmentAtomicCounters") == 0) Resources.maxFragmentAtomicCounters = value; else if (strcmp(token, "MaxCombinedAtomicCounters") == 0) Resources.maxCombinedAtomicCounters = value; else if (strcmp(token, "MaxAtomicCounterBindings") == 0) Resources.maxAtomicCounterBindings = value; else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0) Resources.maxVertexAtomicCounterBuffers = value; else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0) Resources.maxTessControlAtomicCounterBuffers = value; else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0) Resources.maxTessEvaluationAtomicCounterBuffers = value; else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0) Resources.maxGeometryAtomicCounterBuffers = value; else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0) Resources.maxFragmentAtomicCounterBuffers = value; else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0) Resources.maxCombinedAtomicCounterBuffers = value; else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0) Resources.maxAtomicCounterBufferSize = value; else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0) Resources.maxTransformFeedbackBuffers = value; else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0) Resources.maxTransformFeedbackInterleavedComponents = value; else if (strcmp(token, "nonInductiveForLoops") == 0) Resources.limits.nonInductiveForLoops = (value != 0); else if (strcmp(token, "whileLoops") == 0) Resources.limits.whileLoops = (value != 0); else if (strcmp(token, "doWhileLoops") == 0) Resources.limits.doWhileLoops = (value != 0); else if (strcmp(token, "generalUniformIndexing") == 0) Resources.limits.generalUniformIndexing = (value != 0); else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0) Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0); else if (strcmp(token, "generalVaryingIndexing") == 0) Resources.limits.generalVaryingIndexing = (value != 0); else if (strcmp(token, "generalSamplerIndexing") == 0) Resources.limits.generalSamplerIndexing = (value != 0); else if (strcmp(token, "generalVariableIndexing") == 0) Resources.limits.generalVariableIndexing = (value != 0); else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0) Resources.limits.generalConstantMatrixVectorIndexing = (value != 0); else printf("Warning: unrecognized limit (%s) in configuration file.\n", token); token = strtok(0, delims); } } class PyramidIncluder : public glslang::TShader::Includer { public: PyramidIncluder( Pyramid::IIncludeHandler^ pmIncluder ) : m_pmInclude(pmIncluder) { } glslang::TShader::Includer::IncludeResult* Do( Pyramid::IncludeType eType, const char* headerName, const char* includerPath ) { Pyramid::IIncludeHandler^ pmInclude = m_pmInclude; if( pmInclude == nullptr ) return nullptr; Pyramid::IIncludeResult^ pmResult = m_pmInclude->OpenInclude( eType, MakeString(headerName), MakeString(includerPath) ); if( pmResult == nullptr ) return nullptr; array^ bytes = pmResult->Contents; MarshalledString str( pmResult->FullPath ); size_t nLength = bytes->Length; void* pData = malloc( nLength ); Marshal::Copy( bytes,0, System::IntPtr(pData), bytes->Length ); return new glslang::TShader::Includer::IncludeResult( std::string((const char*)str), (const char*)pData, nLength, nullptr); } glslang::TShader::Includer::IncludeResult* DepthLimit() { static const char* DEPTH_LIMIT = "Include depth limit reached"; size_t len = strlen(DEPTH_LIMIT); char* pAlloc = (char*)malloc(len+1); strcpy(pAlloc,DEPTH_LIMIT); glslang::TShader::Includer::IncludeResult* pResult; return new glslang::TShader::Includer::IncludeResult( "", pAlloc, len, nullptr); } // For the "system" or <>-style includes; search the "system" paths. virtual IncludeResult* includeSystem(const char* headerName, const char* includerName, size_t inclusionDepth) { if( inclusionDepth > 1024 ) return DepthLimit(); return Do( Pyramid::IncludeType::System, headerName, includerName ); } // For the "local"-only aspect of a "" include. Should not search in the // "system" paths, because on returning a failure, the parser will // call includeSystem() to look in the "system" locations. virtual IncludeResult* includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) { if( inclusionDepth > 1024 ) return DepthLimit(); return Do( Pyramid::IncludeType::System, headerName, includerName ); } // Signals that the parser will no longer use the contents of the // specified IncludeResult. virtual void releaseInclude(IncludeResult* result) { if( !result ) return; if( result->headerData ) free((void*) result->headerData); delete result; } private: gcroot m_pmInclude; }; namespace Pyramid{ namespace GLSlang{ // The authors of glslang have not seen fit to make // the TIntermediate of a TShader directly accessible // But we need it if we're going to generate SPIRV from it // Lucky for us, they made it public #pragma unmanaged class StubShader : public glslang::TShader { public: StubShader( EShLanguage eType ) : TShader(eType){} glslang::TIntermediate* GetIntermediate() { return this->intermediate; } }; #pragma managed ref class ConfigImpl : IConfig { public: ConfigImpl( const char* pText ) { m_Config = new TBuiltInResource(); // can't use unmanaged struct type in managed class. Doh char* pCopy = new char[strlen(pText)+1]; strcpy(pCopy,pText); ProcessConfigFile( *m_Config, pCopy ); delete[] pCopy; } ~ConfigImpl() { delete m_Config; } TBuiltInResource* m_Config; }; struct SPIRVBlob_Unmanaged { std::vector m_SPIRV; }; ref class SPIRVBlob : Pyramid::SPIRV::IProgram { public: SPIRVBlob( SPIRVBlob_Unmanaged* pBlob ) : m_pBlob(pBlob) { } ~SPIRVBlob() { delete m_pBlob; } virtual System::String^ Disassemble() { std::stringstream stream; spv::Disassemble( stream, m_pBlob->m_SPIRV ); System::String^ str = MakeString( stream.str().c_str() ); return str->Replace( "\n", System::Environment::NewLine ); } virtual array^ GetTokens() { array^ pmArray = gcnew array(m_pBlob->m_SPIRV.size()); for( size_t i=0; im_SPIRV.size(); i++ ) pmArray[i] = m_pBlob->m_SPIRV[i]; return pmArray; } virtual array^ GetBytes() { size_t nSize = m_pBlob->m_SPIRV.size()*sizeof(unsigned int); array^ pmArray = gcnew array(nSize); Marshal::Copy( System::IntPtr((void*)m_pBlob->m_SPIRV.data()), pmArray, 0, nSize ); return pmArray; } SPIRVBlob_Unmanaged* m_pBlob; }; ref class ShaderImpl : IShader { public: ShaderImpl( StubShader* pShader, System::String^ Info, System::String^ InfoDebug, GLSLShaderType eType) : m_pShader(pShader), m_InfoLog( Info ), m_InfoDebugLog( InfoDebug ), m_eType(eType) { } ~ShaderImpl() { if(m_pShader) delete m_pShader; m_pShader=nullptr; } virtual property GLSLShaderType ShaderType { GLSLShaderType get() { return m_eType; } } virtual property bool HasErrors { bool get() { return m_pShader == nullptr; } }; virtual property System::String^ InfoLog { System::String^ get() { return m_InfoLog; } } virtual property System::String^ InfoDebugLog { System::String^ get() { return m_InfoDebugLog; } } virtual Pyramid::SPIRV::IProgram^ CompileSPIRV() { if( !m_pShader ) return nullptr; SPIRVBlob_Unmanaged* pBlob = new SPIRVBlob_Unmanaged(); glslang::GlslangToSpv( *m_pShader->GetIntermediate(), pBlob->m_SPIRV ); return gcnew SPIRVBlob(pBlob); } private: System::String^ m_InfoLog; System::String^ m_InfoDebugLog; StubShader* m_pShader; GLSLShaderType m_eType; }; static volatile long m_nLock=0; static long m_nInstanceCount=0; Compiler_Impl::Compiler_Impl( Pyramid::IIncludeHandler^ pmIncluder ) { while( _InterlockedExchange( &m_nLock, 1 ) != 0 ) ; long n = ++m_nInstanceCount; if( n == 1 ) glslang::InitializeProcess(); m_nLock = 0; m_pmIncluder = pmIncluder; } Compiler_Impl::~Compiler_Impl() { while( _InterlockedExchange( &m_nLock, 1 ) != 0 ) ; long n = --m_nInstanceCount; if( n == 0 ) glslang::FinalizeProcess(); m_nLock=0; } IConfig^ Compiler_Impl::CreateConfig(System::String^ text) { MarshalledString str(text); return gcnew ConfigImpl(str); } IConfig^ Compiler_Impl::CreateDefaultConfig() { return gcnew ConfigImpl(DefaultConfig); } IShader^ Compiler_Impl::Compile( System::String^ text, GLSLShaderType eManagedShaderType, IConfig^ config, System::String^ path ) { EShLanguage eShaderType; switch( eManagedShaderType ) { case GLSLShaderType::VERTEX: eShaderType = EShLangVertex; break; case GLSLShaderType::FRAGMENT: eShaderType = EShLangFragment; break; case GLSLShaderType::GEOMETRY: eShaderType = EShLangGeometry; break; case GLSLShaderType::TESS_CONTROL: eShaderType = EShLangTessControl; break; case GLSLShaderType::TESS_EVALUATION: eShaderType = EShLangTessEvaluation; break; case GLSLShaderType::COMPUTE: eShaderType = EShLangCompute; break; default: return nullptr; } ConfigImpl^ cfg = (ConfigImpl^)config; MarshalledString marshalledText(text); const char* p = marshalledText.GetString(); int len = strlen(p); MarshalledString marshalledPath(path); const char* pnames = marshalledPath.GetString(); StubShader* shader = new StubShader(eShaderType); shader->setStringsWithLengthsAndNames( &p, &len, &pnames, 1 ); PyramidIncluder includer(m_pmIncluder); bool bResult = shader->parse( cfg->m_Config, 100, false, EShMsgDefault, includer ); System::String^ rInfoLog = MakeString( shader->getInfoLog() ); System::String^ rInfoDebugLog = MakeString( shader->getInfoDebugLog() ); if( !bResult ) { delete shader; shader = nullptr; } return gcnew ShaderImpl(shader, rInfoLog, rInfoDebugLog, eManagedShaderType ); } IShader^ Compiler_Impl::CompileHLSL( System::String^ text, IHLSLOptions^ opts, IConfig^ config, System::String^ path ) { System::String^ entrypoint = opts->EntryPoint; GLSLShaderType eManagedType; System::String^ profile = opts->Target.ToString(); if (profile->StartsWith("vs")) eManagedType = GLSLShaderType::VERTEX; else if (profile->StartsWith("ps")) eManagedType = GLSLShaderType::FRAGMENT; else if (profile->StartsWith("gs")) eManagedType = GLSLShaderType::GEOMETRY; else if (profile->StartsWith("hs")) eManagedType = GLSLShaderType::TESS_CONTROL; else if (profile->StartsWith("ds")) eManagedType = GLSLShaderType::TESS_EVALUATION; else if (profile->StartsWith("cs")) eManagedType = GLSLShaderType::COMPUTE; else return nullptr; EShLanguage eShaderType; switch( eManagedType ) { case GLSLShaderType::VERTEX: eShaderType = EShLangVertex; break; case GLSLShaderType::FRAGMENT: eShaderType = EShLangFragment; break; case GLSLShaderType::GEOMETRY: eShaderType = EShLangGeometry; break; case GLSLShaderType::TESS_CONTROL: eShaderType = EShLangTessControl; break; case GLSLShaderType::TESS_EVALUATION: eShaderType = EShLangTessEvaluation; break; case GLSLShaderType::COMPUTE: eShaderType = EShLangCompute; break; default: return nullptr; } ConfigImpl^ cfg = (ConfigImpl^)config; MarshalledString marshalledText(text); MarshalledString marshalledEntryPoint(entrypoint); const char* p = marshalledText.GetString(); int len = strlen(p); MarshalledString marshalledPath(path); const char* pPath = marshalledPath.GetString(); StubShader* shader = new StubShader(eShaderType); shader->setStringsWithLengthsAndNames( &p, &len, &pPath, 1 ); shader->setEntryPoint( marshalledEntryPoint.GetString() ); shader->setHlslIoMapping(true); shader->setAutoMapBindings(true); PyramidIncluder includer(m_pmIncluder); bool bResult = shader->parse( cfg->m_Config, 100, false, (EShMessages)(EShMsgDefault|EShMsgReadHlsl|EShMsgVulkanRules|EShMsgSpvRules), includer ); System::String^ rInfoLog = MakeString( shader->getInfoLog() ); System::String^ rInfoDebugLog = MakeString( shader->getInfoDebugLog() ); if( !bResult ) { delete shader; shader = nullptr; } return gcnew ShaderImpl(shader, rInfoLog, rInfoDebugLog, eManagedType ); } }} ================================================ FILE: src/Wrapper/GLSlang_Impl.h ================================================ namespace Pyramid{ namespace GLSlang{ ref class Compiler_Impl : ICompiler { public: Compiler_Impl( Pyramid::IIncludeHandler^ pmInclude ); ~Compiler_Impl(); virtual IShader^ Compile( System::String^ text, GLSLShaderType eManagedType, IConfig^ cfg, System::String^ filePath ); virtual IShader^ CompileHLSL( System::String^ text, IHLSLOptions^ opts, IConfig^ cfg ,System::String^ filePath ); virtual IConfig^ CreateConfig(System::String^ text); virtual IConfig^ CreateDefaultConfig(); private: Pyramid::IIncludeHandler^ m_pmIncluder; }; }} ================================================ FILE: src/Wrapper/GLSlang_Stubs.cpp ================================================ // GLSLang in library mode needs this crap defined or it won't link.... Lame... #pragma unmanaged #include "GLSlang/glslang/Include/Common.h" #include "GLSlang/glslang/Include/ShHandle.h" #include "GLSlang/glslang/MachineIndependent/Versions.h" #if 0 // // Here is where real machine specific high-level data would be defined. // class TGenericCompiler : public TCompiler { public: TGenericCompiler(EShLanguage l, int dOptions) : TCompiler(l, infoSink), debugOptions(dOptions) { } virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile); TInfoSink infoSink; int debugOptions; }; // // This function must be provided to create the actual // compile object used by higher level code. It returns // a subclass of TCompiler. // TCompiler* ConstructCompiler(EShLanguage language, int debugOptions) { return new TGenericCompiler(language, debugOptions); } // // Delete the compiler made by ConstructCompiler // void DeleteCompiler(TCompiler* compiler) { delete compiler; } // // Generate code from the given parse tree // bool TGenericCompiler::compile(TIntermNode *root, int version, EProfile profile) { haveValidObjectCode = true; return haveValidObjectCode; } // // Actual link object, derived from the shader handle base classes. // class TGenericLinker : public TLinker { public: TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { } bool link(TCompilerList&, TUniformMap*) { return true; } void getAttributeBindings(ShBindingTable const **t) const { } TInfoSink infoSink; int debugOptions; }; // // The internal view of a uniform/float object exchanged with the driver. // class TUniformLinkedMap : public TUniformMap { public: TUniformLinkedMap() { } virtual int getLocation(const char* name) { return 0; } }; TShHandleBase* ConstructLinker(EShExecutable executable, int debugOptions) { return new TGenericLinker(executable, debugOptions); } void DeleteLinker(TShHandleBase* linker) { delete linker; } TUniformMap* ConstructUniformMap() { return new TUniformLinkedMap(); } void DeleteUniformMap(TUniformMap* map) { delete map; } TShHandleBase* ConstructBindings() { return 0; } void DeleteBindingList(TShHandleBase* bindingList) { delete bindingList; } #endif ================================================ FILE: src/Wrapper/Scrutinizer_GCN.cpp ================================================ #include "AMDAsic_Impl.h" #include "AMDShader_Impl.h" #include "Scrutinizer_GCN.h" #include "Utilities.h" #include "D3DCompiler_Impl.h" #pragma unmanaged #include "GCNIsa.h" #include "GCNDecoder.h" #include "GCNDisassembler.h" #include "GCNBufferedPrinter.h" #include "GCNSimulator.h" #include #include #pragma managed using namespace System; using namespace System::Collections::Generic; using namespace Pyramid::Scrutinizer; private ref class GCNInstruction : public IInstruction { public: GCNInstruction( const GCN::Instruction& inst ) { m_pInstruction = new GCN::Instruction(); *m_pInstruction = inst; } virtual ~GCNInstruction() { delete m_pInstruction; } property BasicBlock^ Block { virtual BasicBlock^ get() { return m_pmBlock; } virtual void set( BasicBlock^ bl ) { m_pmBlock = bl; } } property System::String^ Label { virtual System::String^ get() { return m_Label; } virtual void set( System::String^ s ) { m_Label = s; } } property System::String^ SimNotes{ virtual System::String^ get() { return m_Notes; } virtual void set( System::String^ s) { m_Notes = s; } } virtual System::String^ Disassemble() { GCN::Disassembler::BufferedPrinter printer; GCN::Disassembler::Disassemble( printer, m_pInstruction, 0); printer.m_Bytes.push_back(0); System::String^ str = MakeString( printer.m_Bytes.data() ); return str->Replace( "\n", System::Environment::NewLine ); } virtual System::String^ ToString() override { return Disassemble(); } internal: GCN::Instruction* m_pInstruction; BasicBlock^ m_pmBlock; System::String^ m_Notes; System::String^ m_Label; }; private ref class GCNJump : public GCNInstruction, public IJumpInstruction { public: GCNJump( const GCN::Instruction& inst ) : GCNInstruction(inst), m_Target(nullptr) {} property IInstruction^ Target{ virtual IInstruction^ get () { return m_Target; } }; virtual System::String^ Disassemble() override { MarshalledString^ label = gcnew MarshalledString( m_Target->Label ); GCN::Disassembler::BufferedPrinter printer; GCN::Disassembler::Disassemble( printer, m_pInstruction, label->GetString() ); printer.m_Bytes.push_back(0); System::String^ str = MakeString( printer.m_Bytes.data() ); return str->Replace( "\n", System::Environment::NewLine ); } internal: IInstruction^ m_Target; }; private ref class GCNBranch : public GCNInstruction, public IBranchInstruction { public: GCNBranch( const GCN::Instruction& inst ) : GCNInstruction(inst), m_IfTarget(nullptr), m_ElseTarget(nullptr){} property IInstruction^ IfTarget{ virtual IInstruction^ get () { return m_IfTarget; } }; property IInstruction^ ElseTarget{ virtual IInstruction^ get () { return m_ElseTarget; } }; property BranchCategory Category{ virtual BranchCategory get() { return m_eCategory; } virtual void set( BranchCategory e ) { m_eCategory = e; } } virtual System::String^ Disassemble() override { MarshalledString^ label = gcnew MarshalledString( m_IfTarget->Label ); GCN::Disassembler::BufferedPrinter printer; GCN::Disassembler::Disassemble( printer, m_pInstruction, label->GetString() ); printer.m_Bytes.push_back(0); System::String^ str = MakeString( printer.m_Bytes.data() ); return str->Replace( "\n", System::Environment::NewLine ); } internal: IInstruction^ m_IfTarget; IInstruction^ m_ElseTarget; BranchCategory m_eCategory; }; private ref class GCNSamplingOp : public GCNInstruction, public ISamplingInstruction { public: GCNSamplingOp( const GCN::Instruction& inst ) : GCNInstruction(inst), m_eFormat(TexelFormat::RGBA8), m_eFilter(TextureFilter::TRILINEAR) { } property TextureFilter Filter{ virtual TextureFilter get () { return m_eFilter; } virtual void set( TextureFilter e ) { m_eFilter = e; } }; property TexelFormat Format{ virtual TexelFormat get () { return m_eFormat; } virtual void set( TexelFormat e ) { m_eFormat = e; } }; internal: TextureFilter m_eFilter; TexelFormat m_eFormat; }; private ref class GCNTBufferOp : public GCNInstruction, public ITextureInstruction { public: GCNTBufferOp( const GCN::Instruction& inst ) : GCNInstruction(inst), m_eFormat(TexelFormat::RGBA32F) { } property TexelFormat Format{ virtual TexelFormat get () { return m_eFormat; } virtual void set( TexelFormat e ) { m_eFormat = e; } }; internal: TexelFormat m_eFormat; }; List^ Scrutinizer_GCN_Base::BuildProgram( ) { MarshalledBlob^ bl = gcnew MarshalledBlob(m_pmShader->ReadISABytes()); unsigned char* pBytes = bl->GetBlob(); size_t nBytes = bl->GetLength(); GCN::IDecoder* pDecoder = m_pmAsic->m_pDecoder; // // First pass: // 1. Validate // 2. Figure out how many instructions there are // 3. Identify branches and their targets // std::vector< const GCN::uint8* > Branches; std::vector< const GCN::uint8* > Jumps; std::unordered_map< const void*, size_t > IndexMap; List^ pmManagedInstructions = gcnew List(); size_t nOffs=0; while( nOffs < nBytes ) { unsigned char* pLocation = pBytes + nOffs; // read instruction encoding GCN::InstructionFormat eEncoding = pDecoder->ReadInstructionFormat( pBytes + nOffs ); if( eEncoding == GCN::IF_UNKNOWN ) throw gcnew System::Exception("Malformed GCN program"); // check instruction length size_t nLength = pDecoder->DetermineInstructionLength(pLocation, eEncoding ); if( nLength == 0 || (nLength%4) != 0 ) throw gcnew System::Exception("Malformed GCN program"); // check for overrun of instruction buffer nOffs += nLength; if( nOffs > nBytes ) throw gcnew System::Exception("Malformed GCN program"); // decode instruction and see if it's a scalar GCN::Instruction inst; pDecoder->Decode( &inst, pLocation, eEncoding); if( inst.GetClass() == GCN::IC_SCALAR ) { GCN::ScalarInstruction* pI = (GCN::ScalarInstruction*)&inst; if( pI->GetBranchTarget() ) { if( pI->IsConditionalJump() ) { Branches.push_back( pLocation ); pmManagedInstructions->Add( gcnew GCNBranch(inst) ); } else if( pI->IsUnconditionalJump() ) { Jumps.push_back( pLocation ); pmManagedInstructions->Add( gcnew GCNJump(inst) ); } } else { pmManagedInstructions->Add( gcnew GCNInstruction(inst) ); } } else { switch( inst.GetClass() ) { case GCN::IC_IMAGE: { GCN::ImageInstruction* pInst = static_cast( &inst ); if( pInst->IsFilteredFetch() ) pmManagedInstructions->Add( gcnew GCNSamplingOp( *pInst ) ); else if( pInst->IsUnfilteredLoadStore() ) pmManagedInstructions->Add( gcnew GCNTBufferOp( *pInst ) ); else pmManagedInstructions->Add( gcnew GCNInstruction( *pInst ) ); } break; case GCN::IC_BUFFER: { GCN::BufferInstruction* pBuff = static_cast(&inst); // TBuffer means the instruction tells us the format // non-TBuffer means the descriptor tells us, and that is the one where // we need to create the special 'TexelLoad' subclass if( !pBuff->IsTBuffer() ) pmManagedInstructions->Add( gcnew GCNTBufferOp( *pBuff ) ); else pmManagedInstructions->Add( gcnew GCNInstruction( *pBuff ) ); } break; default: pmManagedInstructions->Add( gcnew GCNInstruction(inst) ); } } IndexMap.insert( {pLocation, IndexMap.size()} ); } // Assign branch target instruction refs for( size_t i=0; iReadInstructionFormat( pLocation ); size_t nLength = pDecoder->DetermineInstructionLength(pLocation, eEncoding ); GCN::ScalarInstruction inst; pDecoder->Decode( &inst, pLocation, eEncoding ); IInstruction^ ifTarget = pmManagedInstructions[ IndexMap[inst.GetBranchTarget()] ]; IInstruction^ elseTarget = pmManagedInstructions[ IndexMap[pLocation+nLength] ]; GCNBranch^ branch = dynamic_cast( pmManagedInstructions[ IndexMap[pLocation] ] ); branch->m_IfTarget = ifTarget; branch->m_ElseTarget = elseTarget; } // assign jump instruction refs for( size_t i=0; iReadInstructionFormat( pLocation ); size_t nLength = pDecoder->DetermineInstructionLength(pLocation, eEncoding ); GCN::ScalarInstruction inst; pDecoder->Decode( &inst, pLocation, eEncoding ); IInstruction^ target = pmManagedInstructions[ IndexMap[inst.GetBranchTarget()] ]; GCNJump^ jump = dynamic_cast( pmManagedInstructions[ IndexMap[pLocation] ] ); jump->m_Target = target; } return pmManagedInstructions; } List^ Scrutinizer_GCN_Base::BuildDXFetchShader( Pyramid::IDXShaderReflection^ refl ) { DXShaderReflection_Impl^ reflImpl = dynamic_cast(refl); ID3D11ShaderReflection* pRefl = reflImpl->m_pRef; List^ ops = gcnew List(); if( refl->GetShaderType() != Pyramid::HLSLShaderType::VERTEX ) return ops; D3D11_SHADER_DESC sd; pRefl->GetDesc(&sd); if( !sd.InputParameters ) return ops; // first 'swappc' instruction that called the fetch shader // The second one, which returns, is the one that's at the beginning of the VS GCN::ScalarInstruction swap; swap.EncodeSwapPC(); ops->Add( gcnew GCNInstruction(swap)); for( size_t i=0; iGetInputParameterDesc(i,¶m); // count how many elements we need to fetch UINT nComps=0; while( param.Mask ) { nComps++; param.Mask = param.Mask>>1; } if( !nComps ) continue; // strange... GCN::BufferInstruction inst; switch( nComps ) { case 1: inst.SetOpcode( GCN::BUFFER_LOAD_FORMAT_X ); break; case 2: inst.SetOpcode( GCN::BUFFER_LOAD_FORMAT_XY ); break; case 3: inst.SetOpcode( GCN::BUFFER_LOAD_FORMAT_XYZ ); break; case 4: inst.SetOpcode( GCN::BUFFER_LOAD_FORMAT_XYZW ); break; } GCNTBufferOp^ op = gcnew GCNTBufferOp( inst ); ops->Add(op); } // do a wait if we fetched anything GCN::ScalarInstruction wait; wait.EncodeWait(0,31,7); ops->Add( gcnew GCNInstruction(wait)); return ops; } System::String^ Scrutinizer_GCN_Base::AnalyzeTrace( List^ ops, unsigned int nWaveIssueRate, unsigned int nWaveOccupancy, unsigned int nGroupOccupancy, unsigned int nCUs, unsigned int nWavesPerGroup ) { std::vector pSimOps(ops->Count); for( size_t i=0; iCount; i++ ) { GCNInstruction^ gcnOp = safe_cast( ops[i] ); pSimOps[i].pInstruction = gcnOp->m_pInstruction; pSimOps[i].eFilter = GCN::Simulator::FILT_POINT; pSimOps[i].eFormat = GCN::Simulator::FMT_RGBA8; GCNSamplingOp^ sampling = dynamic_cast( ops[i] ); if( sampling != nullptr ) { // map Scrutinizer's enums onto the unmanaged simulator ones switch( sampling->m_eFilter ) { case TextureFilter::POINT: pSimOps[i].eFilter = GCN::Simulator::FILT_POINT; break; case TextureFilter::BILINEAR: pSimOps[i].eFilter = GCN::Simulator::FILT_BILINEAR; break; case TextureFilter::TRILINEAR: pSimOps[i].eFilter = GCN::Simulator::FILT_TRILINEAR; break; case TextureFilter::ANISO_2X: pSimOps[i].eFilter = GCN::Simulator::FILT_ANISO_2X; break; case TextureFilter::ANISO_4X: pSimOps[i].eFilter = GCN::Simulator::FILT_ANISO_4X; break; case TextureFilter::ANISO_8X: pSimOps[i].eFilter = GCN::Simulator::FILT_ANISO_8X; break; } switch( sampling->m_eFormat ) { case TexelFormat::R8 : pSimOps[i].eFormat = GCN::Simulator::FMT_R8 ; break; case TexelFormat::RG8 : pSimOps[i].eFormat = GCN::Simulator::FMT_RG8 ; break; case TexelFormat::RGBA8 : pSimOps[i].eFormat = GCN::Simulator::FMT_RGBA8 ; break; case TexelFormat::R16 : pSimOps[i].eFormat = GCN::Simulator::FMT_R16 ; break; case TexelFormat::RG16 : pSimOps[i].eFormat = GCN::Simulator::FMT_RG16 ; break; case TexelFormat::RGBA16 : pSimOps[i].eFormat = GCN::Simulator::FMT_RGBA16 ; break; case TexelFormat::R16F : pSimOps[i].eFormat = GCN::Simulator::FMT_R16F ; break; case TexelFormat::RG16F : pSimOps[i].eFormat = GCN::Simulator::FMT_RG16F ; break; case TexelFormat::RGBA16F: pSimOps[i].eFormat = GCN::Simulator::FMT_RGBA16F ; break; case TexelFormat::R32F : pSimOps[i].eFormat = GCN::Simulator::FMT_R32F ; break; case TexelFormat::RG32F : pSimOps[i].eFormat = GCN::Simulator::FMT_RG32F ; break; case TexelFormat::RGBA32F: pSimOps[i].eFormat = GCN::Simulator::FMT_RGBA32F ; break; case TexelFormat::BC1 : pSimOps[i].eFormat = GCN::Simulator::FMT_BC1 ; break; case TexelFormat::BC2 : pSimOps[i].eFormat = GCN::Simulator::FMT_BC2 ; break; case TexelFormat::BC3 : pSimOps[i].eFormat = GCN::Simulator::FMT_BC3 ; break; case TexelFormat::BC4 : pSimOps[i].eFormat = GCN::Simulator::FMT_BC4 ; break; case TexelFormat::BC5 : pSimOps[i].eFormat = GCN::Simulator::FMT_BC5 ; break; case TexelFormat::BC6 : pSimOps[i].eFormat = GCN::Simulator::FMT_BC6 ; break; case TexelFormat::BC7 : pSimOps[i].eFormat = GCN::Simulator::FMT_BC7 ; break; } } } // assign an index to each distinct instruction in the trace Dictionary^ pInstructionIDs = gcnew Dictionary(); List^ pDistinctInstructions = gcnew List(); for( size_t i=0; iCount; i++ ) { if( !pInstructionIDs->ContainsKey( ops[i] ) ) { pInstructionIDs->Add( ops[i], pDistinctInstructions->Count ); pDistinctInstructions->Add( ops[i] ); } pSimOps[i].nInstructionID = pInstructionIDs[ops[i]]; } // allocate and initialize per-instruction stall counters std::vector pInstructionStalls( pDistinctInstructions->Count, 0 ); std::vector pSimOpStalls(ops->Count, 0 ); // setup the sim GCN::Simulator::Settings settings; settings.nExportCost = nCUs*4; settings.nGroupIssueRate = nWaveIssueRate; settings.nGroupsToExecute = 500; settings.nWavesPerThreadGroup = nWavesPerGroup; settings.nMaxWavesPerSIMD = nWaveOccupancy; settings.nMaxGroupsPerCU = nGroupOccupancy; GCN::Simulator::Results results; memset(&results,0,sizeof(results)); results.pInstructionStallCounts = pInstructionStalls.data(); results.pSimOpStallCounts = pSimOpStalls.data(); GCN::Simulator::Simulate( results, settings, pSimOps.data(), pSimOps.size() ); float fClocks = results.nCycles; float fStallClocks = results.nStallCycles[0]+results.nStallCycles[1]+results.nStallCycles[2]+results.nStallCycles[3]; double fUnstarvedClocks = results.nCycles-results.nStarveCycles; float fStallRate = fStallClocks/(fUnstarvedClocks); float fVALUUtil = (results.nVALUBusy[0]+results.nVALUBusy[1]+results.nVALUBusy[2]+results.nVALUBusy[3])/(4*fClocks); float fVMemUtil = (results.nVMemBusy)/fClocks; float fExpUtil = (results.nExpBusy) / fClocks; float fScalarUtil = (results.nSALUBusy)/fClocks; float fSMemUtil = (results.nSMemBusy)/fClocks; float fLDSUtil = (results.nLDSBusy)/(2*fClocks); float fStarveRate = results.nStarveCycles / fClocks; double fWaveTime = fUnstarvedClocks / settings.nGroupsToExecute; double fThroughput = ((settings.nGroupsToExecute*64.0)/(fClocks))*1000000000.0; // annotate instructions with stall counts for( size_t i=0; iSimNotes = notes; } } double fIPC = (results.nSALUIssued + results.nSMEMIssued + results.nVALUIssued + results.nLDSIssued + results.nExpIssued + results.nVMemIssued) / fClocks; char buffer[4096]; sprintf( buffer, "Clocks: (%.2f clocks/wave)\n" "Throughput: (%.2f Mthreads/GHz/CU)\n" "VALU util: %.2f%%\n" "VMem util: %.2f%%\n" "Exp util: %.2f%%\n" "SALU util: %.2f%%\n" "SMem util: %.2f%%\n" "LDS util: %.2f%%\n" "Stall rate: %.2f%%\n" "Starve rate: %.2f%%\n" "Inst/Clk: %.2f\n" "Peak Waves: %u/%u\n" "Peak Groups: %u/%u\n", fWaveTime, fThroughput / 1000000.0, 100.0f*fVALUUtil, 100.0f*fVMemUtil, 100.0f*fExpUtil, 100.0f*fScalarUtil, 100.0f*fSMemUtil, 100.0f*fLDSUtil, 100.0f*fStallRate, 100.0f*fStarveRate, fIPC, results.nPeakWaveOccupancy , settings.nMaxWavesPerSIMD*4 , results.nPeakGroupOccupancy, settings.nMaxGroupsPerCU ); System::String^ str = gcnew System::String(buffer); return str->Replace("\n", System::Environment::NewLine ); } Scrutinizer_GCN_VS::Scrutinizer_GCN_VS( AMDAsic_Impl^ asic, AMDShader_Impl^ shader ) :Scrutinizer_GCN_Base(asic,shader) { m_pmOccupancy = gcnew SimulationParameterInt(1,10,shader->GetWaveOccupancy(),"Occupancy (Waves/SIMD)"); m_pmCUCount = gcnew SimulationParameterInt(1,10000,10,"CU Count"); m_pmACMR = gcnew SimulationParameterDouble( 0.5,3.0, 0.7, "Verts/Tri"); m_pmParams->Add(m_pmOccupancy); m_pmParams->Add(m_pmCUCount); m_pmParams->Add(m_pmACMR); } System::String^ Scrutinizer_GCN_VS::AnalyzeExecutionTrace( List^ ops ) { unsigned int nCUs = (unsigned int) m_pmCUCount->Value; unsigned int nOccupancy = (unsigned int) m_pmOccupancy->Value; // one VS wave every M clocks // round-robined amongst CUs // // http://www.icodebot.com/Playstation%204%20GPU // States that VGT can handle 1 new vert/clk, and tests 3 indices/clk for reuse // // If A = cache hit rate (verts/tri) // then we need on average 64/A triangles to produce a full wave // // It will take min(64, 64/A) clocks to gather that many // double fVertsPerTri = m_pmACMR->Value; double fTrisPerWave = 64.0 / fVertsPerTri; double fClocksPerWave = ( fTrisPerWave>64.0f) ? 64.0 : fTrisPerWave; unsigned int nWaveIssueRate = (unsigned int) (nCUs*fClocksPerWave); return AnalyzeTrace(ops,nWaveIssueRate,nOccupancy,40,nCUs,1); } Scrutinizer_GCN_PS::Scrutinizer_GCN_PS( AMDAsic_Impl^ asic, AMDShader_Impl^ shader ) :Scrutinizer_GCN_Base(asic,shader) { m_pmOccupancy = gcnew SimulationParameterInt(1,10,shader->GetWaveOccupancy(),"Occupancy (Waves/SIMD)"); m_pmCUCount = gcnew SimulationParameterInt(1,10000,10,"CU Count"); m_pmPixelsPerTri = gcnew SimulationParameterDouble( 0, 10000, 16, "Pixels/Tri"); m_pmParams->Add(m_pmOccupancy); m_pmParams->Add(m_pmCUCount); m_pmParams->Add(m_pmPixelsPerTri); } System::String^ Scrutinizer_GCN_PS::AnalyzeExecutionTrace(List^ ops) { unsigned int nCUs = (unsigned int) m_pmCUCount->Value; unsigned int nOccupancy = (unsigned int) m_pmOccupancy->Value; // Assume 16 pix/clk raster rate (4 quads/clk) // Assuming we can repack quads from multiple tris into a wave, // we end up with double fQuadsPerTri = m_pmPixelsPerTri->Value/4.0; double fQuadsPerClock = Math::Min( 4.0, Math::Ceiling(fQuadsPerTri) ); fQuadsPerClock = Math::Max(1.0,fQuadsPerClock); double fClocksPerWave = Math::Ceiling( 16.0 / fQuadsPerClock ); unsigned int nWaveIssueRate = (unsigned int) (nCUs*fClocksPerWave); return AnalyzeTrace(ops,nWaveIssueRate,nOccupancy,40,nCUs,1); } Scrutinizer_GCN_CS::Scrutinizer_GCN_CS( AMDAsic_Impl^ asic, AMDShader_Impl^ shader ) :Scrutinizer_GCN_Base(asic,shader) { m_nWavesPerGroup = (shader->GetThreadsPerThreadGroup()+63)/64; size_t nMinimumWaveOccupancy = (m_nWavesPerGroup+3)/4; size_t nGroup = 40/m_nWavesPerGroup; size_t nMaxGroups = shader->GetGroupOccupancy(); m_pmWaveOccupancy = gcnew SimulationParameterInt(nMinimumWaveOccupancy,10,shader->GetWaveOccupancy(),"Waves/SIMD"); m_pmGroupOccupancy = gcnew SimulationParameterInt(1,nMaxGroups,nMaxGroups,"Groups/CU"); m_pmCUCount = gcnew SimulationParameterInt(1,10000,10,"CU Count"); m_pmParams->Add(m_pmWaveOccupancy); m_pmParams->Add(m_pmCUCount); m_pmParams->Add(m_pmGroupOccupancy); } System::String^ Scrutinizer_GCN_CS::AnalyzeExecutionTrace(List^ ops) { unsigned int nCUs = (unsigned int) m_pmCUCount->Value; unsigned int nWaveOccupancy = (unsigned int) m_pmWaveOccupancy->Value; unsigned int nGroupOccupancy = (unsigned int) m_pmGroupOccupancy->Value; // GCN ACE can create a workgroup OR dispatch a wave every cycle // Time needed to dispatch a group of N waves is N+1 clocks // Assume that our wave load is round-robined across CUs unsigned int nGroupIssueRate = (m_nWavesPerGroup+1)*nCUs; return AnalyzeTrace(ops,nGroupIssueRate,nWaveOccupancy,nGroupOccupancy,nCUs, m_nWavesPerGroup); } ================================================ FILE: src/Wrapper/Scrutinizer_GCN.h ================================================ using namespace System::Collections::Generic; using namespace Pyramid::Scrutinizer; ref class AMDAsic_Impl; ref class AMDShader_Impl; ref class Scrutinizer_GCN_Base abstract : public Pyramid::Scrutinizer::IScrutinizer { public: Scrutinizer_GCN_Base( AMDAsic_Impl^ asic, AMDShader_Impl^ shader ) : m_pmAsic(asic), m_pmShader(shader), m_pmParams(gcnew List()) { } virtual List^ BuildProgram( ); virtual List^ BuildDXFetchShader( Pyramid::IDXShaderReflection^ refl ); property IEnumerable^ SimulationParameters { virtual IEnumerable^ get() { return m_pmParams; } } virtual System::String^ AnalyzeExecutionTrace( List^ ops ) = 0; protected: System::String^ AnalyzeTrace( List^ ops, unsigned int nWaveIssueRate, unsigned int nWaveOccupancy, unsigned int nGroupOccupancy, unsigned int nCUCount, unsigned int nWavesPerGroup ); AMDAsic_Impl^ m_pmAsic; AMDShader_Impl^ m_pmShader; List^ m_pmParams; }; ref class Scrutinizer_GCN_VS : public Scrutinizer_GCN_Base { public: Scrutinizer_GCN_VS( AMDAsic_Impl^ asic, AMDShader_Impl^ shader ); virtual System::String^ AnalyzeExecutionTrace( List^ ops ) override; private: SimulationParameterInt^ m_pmOccupancy; SimulationParameterInt^ m_pmCUCount; SimulationParameterDouble^ m_pmACMR; }; ref class Scrutinizer_GCN_PS : public Scrutinizer_GCN_Base { public: Scrutinizer_GCN_PS( AMDAsic_Impl^ asic, AMDShader_Impl^ shader ); virtual System::String^ AnalyzeExecutionTrace( List^ ops ) override; private: SimulationParameterInt^ m_pmOccupancy; SimulationParameterInt^ m_pmCUCount; SimulationParameterDouble^ m_pmPixelsPerTri; }; ref class Scrutinizer_GCN_CS : public Scrutinizer_GCN_Base { public: Scrutinizer_GCN_CS( AMDAsic_Impl^ asic, AMDShader_Impl^ shader ); virtual System::String^ AnalyzeExecutionTrace( List^ ops ) override; private: SimulationParameterInt^ m_pmWaveOccupancy; SimulationParameterInt^ m_pmGroupOccupancy; SimulationParameterInt^ m_pmCUCount; unsigned int m_nWavesPerGroup; }; ================================================ FILE: src/Wrapper/Utilities.h ================================================ #ifndef _UTILITIES_H_ #define _UTILITIES_H_ #include #pragma unmanaged #include #include #pragma managed typedef unsigned int UINT; using System::Runtime::InteropServices::Marshal; private ref class MarshalledString { public: MarshalledString( System::String^ str ) : m_Ptr( Marshal::StringToHGlobalAnsi(str) ) { } ~MarshalledString() { Marshal::FreeHGlobal(m_Ptr); } operator char* () { return GetString(); } char* GetString() { return (char*)m_Ptr.ToPointer(); } size_t Length() { return strlen( GetString() ); } private: System::IntPtr m_Ptr; }; private ref class MarshalledStringW { public: MarshalledStringW( System::String^ str ) : m_Ptr( Marshal::StringToHGlobalUni( str ) ) { } ~MarshalledStringW() { Marshal::FreeHGlobal( m_Ptr ); } operator wchar_t* () { return GetString(); } wchar_t* GetString() { return (wchar_t*)m_Ptr.ToPointer(); } size_t Length() { return wcslen( GetString() ); } private: System::IntPtr m_Ptr; }; private ref class MarshalledBlob { public: MarshalledBlob( array^ blob ) : m_nLength(0), m_pBlob(0) { if( blob != nullptr && blob->Length > 0 ) { void* pBlob = malloc(blob->Length); if( !pBlob ) throw gcnew System::OutOfMemoryException(); Marshal::Copy( blob, 0, System::IntPtr(pBlob), blob->Length); m_nLength = blob->Length; m_pBlob = (unsigned char*) pBlob; } } ~MarshalledBlob() { free(m_pBlob); } operator unsigned char*() { return GetBlob(); } unsigned char* GetBlob() { return m_pBlob; } size_t GetLength() { return m_nLength; } private: size_t m_nLength; unsigned char* m_pBlob; }; inline System::String^ MakeString( const char* p ) { return Marshal::PtrToStringAnsi(System::IntPtr((char*)p));} inline System::String^ MakeString( const wchar_t* p ) { return Marshal::PtrToStringUni( System::IntPtr( (wchar_t*)p ) ); } #endif ================================================ FILE: src/Wrapper/Wrapper.cpp ================================================ #pragma unmanaged #include #include #pragma managed #include "D3DCompiler_Impl.h" #include "DXILCompiler_Impl.h" #include "GLSLOpt_Impl.h" #include "GLSlang_Impl.h" #include "AMDDriver_Impl.h" #include "Utilities.h" namespace Pyramid { public ref class Wrapper : Pyramid::IWrapper { public: Wrapper() {}; virtual Pyramid::ID3DCompiler^ CreateD3DCompiler( System::String^ DLLPath, IIncludeHandler^ handler ) { return gcnew D3DCompiler_Impl(DLLPath,handler); } virtual Pyramid::IDXILCompiler^ CreateDXILCompiler( System::String^ DLLPath,IIncludeHandler^ handler ) { return gcnew DXILCompiler_Impl( DLLPath,handler ); } virtual Pyramid::GLSLOptimizer::IOptimizer^ CreateGLSLOptimizer( GLSLOptimizer::Target eTarget ) { return gcnew GLSLOptimizer::Optimizer_Impl(eTarget); } virtual Pyramid::GLSlang::ICompiler^ CreateGLSlangCompiler( IIncludeHandler^ handler ) { return gcnew GLSlang::Compiler_Impl(handler); } virtual Pyramid::IAMDDriver^ CreateAMDDriver( System::String^ DLLPath) { return gcnew AMDDriver_Impl(DLLPath); } }; } ================================================ FILE: src/Wrapper/Wrapper.vcxproj ================================================  Debug Win32 Release Win32 {AECCEE3C-29C5-46DE-9AE2-AFB5DF6D110A} v4.5 ManagedCProj Wrapper 10.0.16299.0 DynamicLibrary true v141 true Unicode DynamicLibrary false v141 true NotSet true $(SolutionDir)\bin\$(Configuration)\ false $(SolutionDir)\bin\$(Configuration)\ Level3 Disabled WIN32;_DEBUG;%(PreprocessorDefinitions) MultiThreadedDebugDLL .\amd-codexl-analyzer\Common\Src\DeviceInfo;.\amd-codexl-analyzer\CommonProjects\;%(AdditionalIncludeDirectories) true psapi.lib;%(AdditionalDependencies) GLSlang\lib\2013\x86\Debug;%(AdditionalLibraryDirectories) true Level3 WIN32;NDEBUG;%(PreprocessorDefinitions) .\amd-codexl-analyzer\Common\Src\DeviceInfo;.\amd-codexl-analyzer\CommonProjects\;%(AdditionalIncludeDirectories) true psapi.lib;%(AdditionalDependencies) GLSlang\lib\2013\x86\Release copy $(TargetPath) $(SolutionDir)\..\bin false {3d7db344-0267-4890-8186-9fc22b78b738} {b475a403-9d9b-410d-8a93-ba49fc4dd811} {3b146cc5-b2b8-4573-9d46-6139e2edfea3} ================================================ FILE: src/Wrapper/Wrapper.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} {5412010c-a603-425f-827e-0233c9164358} Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files\CodeXL Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files\CodeXL Source Files ================================================ FILE: src/Wrapper/amd-codexl-analyzer/Common/Src/DeviceInfo/DeviceInfo.h ================================================ //===================================================================== // Copyright 2010-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file DeviceInfo.h /// \brief Device info table /// //===================================================================== #ifndef _DEVICE_INFO_H_ #define _DEVICE_INFO_H_ #ifndef _WIN32 #include // Required by GCC size_t #endif #define DEVICE_INFO_NA 0xFFFFFFFF enum GDT_HW_ASIC_TYPE { GDT_ASIC_TYPE_NONE = -1, ///< undefined asic GDT_TAHITI_PRO = 0, ///< TAHITI GPU PRO GDT_TAHITI_XT, ///< TAHITI GPU XT GDT_PITCAIRN_PRO, ///< PITCAIRN GPU PRO GDT_PITCAIRN_XT, ///< PITCAIRN GPU XT GDT_CAPEVERDE_PRO, ///< CAPE VERDE PRO GPU GDT_CAPEVERDE_XT, ///< CAPE VERDE XT GPU GDT_OLAND, ///< OLAND GPU (mobile is MARS) GDT_HAINAN, ///< HAINAN GPU GDT_BONAIRE, ///< BONAIRE GPU (mobile is SATURN) GDT_HAWAII, ///< HAWAII GPU GDT_KALINDI, ///< KB APU GDT_SPECTRE, ///< KV APU SPECTRE GDT_SPECTRE_SL, ///< KV APU SPECTRE SL GDT_SPECTRE_LITE, ///< KV APU SPECTRE LITE GDT_SPOOKY, ///< KV APU SPOOKY GDT_ICELAND, ///< ICELAND GPU GDT_TONGA, ///< TONGA GPU GDT_CARRIZO, ///< CZ APU GDT_CARRIZO_EMB, ///< CZ APU EMBEDDED GDT_FIJI, ///< FIJI GPU GDT_STONEY, ///< STONEY APU GDT_LAST ///< last }; //------------------------------------------------------------------------------------ // This is used for counter set selection //------------------------------------------------------------------------------------ enum GDT_HW_GENERATION { GDT_HW_GENERATION_NONE, ///< undefined hw generation GDT_HW_GENERATION_NVIDIA, ///< nvidia GPU GDT_HW_GENERATION_SOUTHERNISLAND, ///< GFX IP 6 GDT_HW_GENERATION_SEAISLAND, ///< GFX IP 7 GDT_HW_GENERATION_VOLCANICISLAND, ///< GFX IP 8 GDT_HW_GENERATION_LAST }; //------------------------------------------------------------------------------------ // Card info //------------------------------------------------------------------------------------ struct GDT_GfxCardInfo { GDT_HW_ASIC_TYPE m_asicType; ///< ASIC type, which is also the index to gs_deviceInfo table size_t m_deviceID; ///< numeric device id size_t m_revID; ///< numeric revision id GDT_HW_GENERATION m_generation; ///< hardware generation bool m_bAPU; ///< flag indicating whether or not the device is an APU const char* m_szCALName; ///< CAL name const char* m_szMarketingName; ///< marketing style device name }; //------------------------------------------------------------------------------------ // Device info //------------------------------------------------------------------------------------ struct GDT_DeviceInfo { size_t m_nNumShaderEngines; ///< Number of shader engines size_t m_nMaxWavePerSIMD; ///< Number of wave slots per SIMD size_t m_suClocksPrim; ///< Number of clocks it takes to process a primitive size_t m_nNumSQMaxCounters; ///< Max number of SQ counters size_t m_nNumPrimPipes; ///< Number of primitive pipes size_t m_nWaveSize; ///< Wavefront size size_t m_nNumSHPerSE; ///< Number of shader array per Shader Engine size_t m_nNumCUPerSH; ///< Number of compute unit per Shader Array size_t m_nNumSIMDPerCU; ///< Number of SIMDs per Compute unit bool m_deviceInfoValid; ///< Flag indicating whether or not this device info is valid (as opposed to placeholder data) /// Get total number of SIMDs size_t numberSIMDs() const { return m_nNumSIMDPerCU * numberCUs(); } /// Get total number of shader arrays size_t numberSHs() const { return m_nNumSHPerSE * m_nNumShaderEngines; } /// Get total number of compute units size_t numberCUs() const { return numberSHs() * m_nNumCUPerSH; } }; #endif // _DEVICE_INFO_H_ ================================================ FILE: src/Wrapper/amd-codexl-analyzer/Common/Src/DeviceInfo/DeviceInfoUtils.cpp ================================================ //===================================================================== // Copyright 2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file DeviceInfoUtils.cpp /// \brief Device info utils class /// //===================================================================== #ifdef _WIN32 #include #endif #ifdef _LINUX #include #endif #include "DeviceInfoUtils.h" using namespace std; static GDT_GfxCardInfo gs_cardInfo[] = { { GDT_TAHITI_XT, 0x6790, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "Not Used" }, { GDT_TAHITI_PRO, 0x6792, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "Not Used" }, { GDT_TAHITI_XT, 0x6798, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "AMD Radeon HD 7900 Series" }, { GDT_TAHITI_XT, 0x6799, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "SI NEW ZEALAND" }, { GDT_TAHITI_PRO, 0x679A, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "AMD Radeon HD 7900 Series" }, { GDT_TAHITI_PRO, 0x679B, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "AMD Radeon HD 7900 Series" }, { GDT_TAHITI_PRO, 0x679E, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "AMD Radeon HD 7800 Series" }, { GDT_TAHITI_XT, 0x6780, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "AMD FirePro W9000" }, { GDT_TAHITI_PRO, 0x6784, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "ATI FirePro V (FireGL V) Graphics Adapter" }, { GDT_TAHITI_XT, 0x6788, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "ATI FirePro V (FireGL V) Graphics Adapter" }, { GDT_TAHITI_PRO, 0x678A, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Tahiti", "AMD FirePro W8000" }, { GDT_PITCAIRN_XT, 0x6818, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon HD 7800 Series" }, { GDT_PITCAIRN_PRO, 0x6819, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon HD 7800 Series" }, { GDT_PITCAIRN_XT, 0x6808, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD FirePro W7000" }, { GDT_PITCAIRN_XT, 0x6809, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "ATI FirePro W5000" }, { GDT_PITCAIRN_XT, 0x684C, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "ATI FirePro V(FireGL V) Graphics Adapter" }, { GDT_PITCAIRN_XT, 0x6800, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon HD 7970M" }, { GDT_PITCAIRN_PRO, 0x6801, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon(TM) HD8970M" }, { GDT_PITCAIRN_XT, 0x6806, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "NEPTUNE (6806)" }, { GDT_PITCAIRN_XT, 0x6810, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon R9 200 Series" }, { GDT_PITCAIRN_XT, 0x6810, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon (TM) R9 370 Series" }, { GDT_PITCAIRN_PRO, 0x6811, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon R9 200 Series" }, { GDT_PITCAIRN_PRO, 0x6811, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Pitcairn", "AMD Radeon (TM) R7 370 Series" }, { GDT_CAPEVERDE_XT, 0x6820, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon R9 M275X" }, { GDT_CAPEVERDE_XT, 0x6820, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon (TM) R9 M375" }, { GDT_CAPEVERDE_XT, 0x6820, 0x83, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon (TM) R9 M375X" }, { GDT_CAPEVERDE_XT, 0x6821, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon R9 M200X Series" }, { GDT_CAPEVERDE_XT, 0x6821, 0x83, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon R9 (TM) M370X" }, { GDT_CAPEVERDE_XT, 0x6821, 0x87, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon (TM) R7 M380" }, { GDT_CAPEVERDE_XT, 0x6821, 0x8B, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "DID:6821 RID:8B" }, { GDT_CAPEVERDE_PRO, 0x6822, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon E8860" }, { GDT_CAPEVERDE_PRO, 0x6823, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 8800M Series" }, { GDT_CAPEVERDE_PRO, 0x6824, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "Not Used" }, { GDT_CAPEVERDE_XT, 0x6825, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 7800M Series" }, { GDT_CAPEVERDE_PRO, 0x6826, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 7700M Series" }, { GDT_CAPEVERDE_PRO, 0x6827, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 7800M Series" }, { GDT_CAPEVERDE_PRO, 0x682A, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "VENUS PRO MCM (682A)" }, { GDT_CAPEVERDE_XT, 0x682B, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 8800M Series" }, { GDT_CAPEVERDE_XT, 0x682B, 0x87, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon (TM) R9 M360" }, { GDT_CAPEVERDE_XT, 0x682D, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 7700M Series" }, { GDT_CAPEVERDE_PRO, 0x682F, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 7700M Series" }, { GDT_CAPEVERDE_XT, 0x6828, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD FirePro W600" }, { GDT_CAPEVERDE_PRO, 0x682C, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD FirePro W4100" }, { GDT_CAPEVERDE_XT, 0x6830, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon 7800M Series" }, { GDT_CAPEVERDE_XT, 0x6831, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon 7700M Series" }, { GDT_CAPEVERDE_PRO, 0x6835, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon R7 Series / HD 9000 Series" }, { GDT_CAPEVERDE_XT, 0x6837, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD7700 Series" }, { GDT_CAPEVERDE_XT, 0x6838, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "Not Used" }, { GDT_CAPEVERDE_XT, 0x6839, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "Not Used" }, { GDT_CAPEVERDE_PRO, 0x683B, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "Not Used" }, { GDT_CAPEVERDE_XT, 0x683D, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 7700 Series" }, { GDT_CAPEVERDE_PRO, 0x683F, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Capeverde", "AMD Radeon HD 7700 Series" }, // Oland { GDT_OLAND, 0x6608, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD FirePro W2100" }, { GDT_OLAND, 0x6610, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R7 200 Series" }, { GDT_OLAND, 0x6610, 0x83, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon (TM) R5 340" }, { GDT_OLAND, 0x6610, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon (TM) R7 350" }, { GDT_OLAND, 0x6611, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R7 200 Series" }, { GDT_OLAND, 0x6613, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R7 200 Series" }, { GDT_OLAND, 0x6617, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R7 240 Series" }, { GDT_OLAND, 0x6617, 0xC7, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R7 240 Series" }, { GDT_OLAND, 0x6631, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "OLAND (6631)" }, // Mars (Mobile Oland) { GDT_OLAND, 0x6600, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon HD 8600/8700M" }, { GDT_OLAND, 0x6600, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon (TM) R7 M370" }, { GDT_OLAND, 0x6601, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon (TM) HD 8500M/8700M" }, { GDT_OLAND, 0x6602, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "MARS (6602)" }, { GDT_OLAND, 0x6603, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "MARS (6603)" }, { GDT_OLAND, 0x6604, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R7 M265 Series" }, { GDT_OLAND, 0x6604, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon (TM) R7 M350" }, { GDT_OLAND, 0x6605, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R7 M260 Series" }, { GDT_OLAND, 0x6605, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon (TM) R7 M340" }, { GDT_OLAND, 0x6606, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon HD 8790M" }, { GDT_OLAND, 0x6607, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "AMD Radeon R5 M240" }, { GDT_OLAND, 0x6620, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "MARS (6620)" }, { GDT_OLAND, 0x6621, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "MARS (6621)" }, { GDT_OLAND, 0x6623, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Oland", "MARS (6623)" }, // Hainan { GDT_HAINAN, 0x6660, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon HD 8600M Series" }, { GDT_HAINAN, 0x6660, 0x83, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon (TM) R5 M330" }, { GDT_HAINAN, 0x6660, 0x81, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon (TM) R5 M335" }, { GDT_HAINAN, 0x6663, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon HD 8500M Series" }, { GDT_HAINAN, 0x6663, 0x83, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon (TM) R5 M320" }, { GDT_HAINAN, 0x6664, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon R5 M200 Series" }, { GDT_HAINAN, 0x6665, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon R5 M230 Series" }, { GDT_HAINAN, 0x6665, 0x83, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon (TM) R5 M320" }, { GDT_HAINAN, 0x6665, 0xC3, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon R5 M435 Series" }, { GDT_HAINAN, 0x6666, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon R5 M200 Series" }, { GDT_HAINAN, 0x6667, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon R5 M200 Series" }, { GDT_HAINAN, 0x6667, 0x83, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "EXO ULP (6667)" }, { GDT_HAINAN, 0x666F, 0x00, GDT_HW_GENERATION_SOUTHERNISLAND, false, "Hainan", "AMD Radeon HD 8500M" }, // Bonaire { GDT_BONAIRE, 0x6649, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD FirePro W5100" }, { GDT_BONAIRE, 0x6650, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "BONAIRE (6650)" }, { GDT_BONAIRE, 0x6651, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "BONAIRE (6651)" }, { GDT_BONAIRE, 0x6658, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon R7 200 Series" }, { GDT_BONAIRE, 0x665C, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon HD 7700 Series" }, { GDT_BONAIRE, 0x665D, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon R7 200 Series" }, { GDT_BONAIRE, 0x665F, 0x81, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon (TM) R7 360 Series" }, { GDT_BONAIRE, 0x665F, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "DID:665F RID:00" }, { GDT_BONAIRE, 0x665F, 0x81, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon (TM) R7 360 Series" }, // Saturn (mobile Bonaire) { GDT_BONAIRE, 0x6640, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon HD 8950" }, { GDT_BONAIRE, 0x6640, 0x80, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon (TM) R9 M380" }, { GDT_BONAIRE, 0x6641, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "SATURN (6641)" }, { GDT_BONAIRE, 0x6646, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon R9 M280X" }, { GDT_BONAIRE, 0x6646, 0x80, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon (TM) R9 M385" }, { GDT_BONAIRE, 0x6647, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon R9 M200X Series" }, { GDT_BONAIRE, 0x6647, 0x80, GDT_HW_GENERATION_SEAISLAND, false, "Bonaire", "AMD Radeon (TM) R9 M380" }, // Hawaii { GDT_HAWAII, 0x66A0, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "HAWAII XTGL (67A0)" }, { GDT_HAWAII, 0x67A0, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "AMD FirePro W9100" }, { GDT_HAWAII, 0x67A1, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "AMD FirePro W8100" }, { GDT_HAWAII, 0x67A2, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "HAWAII GL Gemini (67A2)" }, { GDT_HAWAII, 0x67A8, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "" }, { GDT_HAWAII, 0x67A9, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "" }, { GDT_HAWAII, 0x67AA, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "" }, { GDT_HAWAII, 0x67B0, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "AMD Radeon R9 200 Series" }, { GDT_HAWAII, 0x67B0, 0x80, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "AMD Radeon (TM) R9 390 Series" }, { GDT_HAWAII, 0x67B1, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "AMD Radeon R9 200 Series" }, { GDT_HAWAII, 0x67B1, 0x80, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "AMD Radeon (TM) R9 390 Series" }, { GDT_HAWAII, 0x67B8, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "Not used" }, { GDT_HAWAII, 0x67B9, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "AMD Radeon R9 200 Series" }, { GDT_HAWAII, 0x67BA, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "Not used" }, { GDT_HAWAII, 0x67BE, 0x00, GDT_HW_GENERATION_SEAISLAND, false, "Hawaii", "HAWAII LE (67BE)" }, // Kaveri -- will probably need multiple entries in g_deviceInfo for these { GDT_SPECTRE, 0x1304, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "KV SPECTRE MOBILE 35W (1304)" }, { GDT_SPECTRE, 0x1305, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "KV SPECTRE DESKTOP 95W (1305)" }, { GDT_SPECTRE_SL, 0x1306, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "KV SPECTRE SL MOBILE 35W (1306)" }, { GDT_SPECTRE_SL, 0x1307, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "KV SPECTRE SL DESKTOP 95W (1307)" }, { GDT_SPECTRE_LITE, 0x1309, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE_LITE, 0x130A, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R6 Graphics" }, { GDT_SPECTRE, 0x130C, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE_LITE, 0x130D, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R6 Graphics" }, { GDT_SPECTRE_SL, 0x130E, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPECTRE, 0x130F, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE, 0x130F, 0xD4, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE, 0x130F, 0xD5, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE, 0x130F, 0xD6, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE, 0x130F, 0xD7, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE, 0x1310, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "KV SPECTRE WORKSTATION 65W (1310)" }, { GDT_SPECTRE, 0x1311, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "KV SPECTRE WORKSTATION 95W (1311)" }, { GDT_SPECTRE_LITE, 0x1313, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE_LITE, 0x1313, 0xD4, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE_LITE, 0x1313, 0xD5, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE_LITE, 0x1313, 0xD6, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE_SL, 0x1315, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPECTRE_SL, 0x1315, 0xD4, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPECTRE_SL, 0x1315, 0xD5, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPECTRE_SL, 0x1315, 0xD6, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPECTRE_SL, 0x1315, 0xD7, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPECTRE_SL, 0x1318, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPECTRE, 0x131C, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R7 Graphics" }, { GDT_SPECTRE_LITE, 0x131D, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R6 Graphics" }, { GDT_SPOOKY, 0x130B, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R4 Graphics" }, { GDT_SPOOKY, 0x1312, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spooky", "KV SPOOKY DESKTOP 95W (1312)" }, { GDT_SPOOKY, 0x1316, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spooky", "AMD Radeon(TM) R5 Graphics" }, { GDT_SPOOKY, 0x1317, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spooky", "KV SPOOKY MOBILE 35W (1317)" }, { GDT_SPOOKY, 0x131B, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Spectre", "AMD Radeon(TM) R4 Graphics" }, // Kabini { GDT_KALINDI, 0x9830, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon HD 8400 / R3 Series" }, { GDT_KALINDI, 0x9831, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon(TM) HD 8400E" }, { GDT_KALINDI, 0x9832, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon HD 8330" }, { GDT_KALINDI, 0x9833, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon(TM) HD 8330E" }, { GDT_KALINDI, 0x9834, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon HD 8210" }, { GDT_KALINDI, 0x9835, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon(TM) HD 8210E" }, { GDT_KALINDI, 0x9836, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon HD 8200 / R3 Series" }, { GDT_KALINDI, 0x9837, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon(TM) HD 8280E" }, { GDT_KALINDI, 0x9838, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon HD 8200 / R3 series" }, // Temash { GDT_KALINDI, 0x9839, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon HD 8180" }, { GDT_KALINDI, 0x983A, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "Not Used" }, { GDT_KALINDI, 0x983B, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "Not Used" }, { GDT_KALINDI, 0x983C, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "Not Used" }, { GDT_KALINDI, 0x983D, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "AMD Radeon HD 8250" }, { GDT_KALINDI, 0x983E, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "Not Used" }, { GDT_KALINDI, 0x983F, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Kalindi", "Not Used" }, // Beema { GDT_KALINDI, 0x9850, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3 Graphics" }, { GDT_KALINDI, 0x9850, 0x03, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3 Graphics" }, { GDT_KALINDI, 0x9850, 0x40, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9850, 0x45, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3 Graphics" }, { GDT_KALINDI, 0x9851, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R4 Graphics" }, { GDT_KALINDI, 0x9851, 0x01, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R5E Graphics" }, { GDT_KALINDI, 0x9851, 0x05, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R5 Graphics" }, { GDT_KALINDI, 0x9851, 0x06, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R5E Graphics" }, { GDT_KALINDI, 0x9851, 0x40, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R4 Graphics" }, { GDT_KALINDI, 0x9851, 0x45, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R5 Graphics" }, { GDT_KALINDI, 0x9852, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9852, 0x40, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) E1 Graphics" }, { GDT_KALINDI, 0x9853, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9853, 0x01, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R4E Graphics" }, { GDT_KALINDI, 0x9853, 0x03, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9853, 0x05, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R1E Graphics" }, { GDT_KALINDI, 0x9853, 0x06, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R1E Graphics" }, { GDT_KALINDI, 0x9853, 0x40, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, // Mullins { GDT_KALINDI, 0x9854, 0x02, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3 Graphics" }, { GDT_KALINDI, 0x9854, 0x07, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3 Graphics" }, { GDT_KALINDI, 0x9854, 0x05, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9854, 0x06, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3 Graphics" }, { GDT_KALINDI, 0x9854, 0x01, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3E Graphics" }, { GDT_KALINDI, 0x9854, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R3 Graphics" }, { GDT_KALINDI, 0x9855, 0x05, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R4 Graphics" }, { GDT_KALINDI, 0x9855, 0x02, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R6 Graphics" }, { GDT_KALINDI, 0x9856, 0x07, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R1E Graphics" }, { GDT_KALINDI, 0x9856, 0x01, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2E Graphics" }, { GDT_KALINDI, 0x9856, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9856, 0x06, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9856, 0x05, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R1E Graphics" }, { GDT_KALINDI, 0x9856, 0x02, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "AMD Radeon(TM) R2 Graphics" }, { GDT_KALINDI, 0x9857, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (9857)" }, { GDT_KALINDI, 0x9858, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (9858)" }, { GDT_KALINDI, 0x9859, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (9859)" }, { GDT_KALINDI, 0x985A, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (985A)" }, { GDT_KALINDI, 0x985B, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (985B)" }, { GDT_KALINDI, 0x985C, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (985C)" }, { GDT_KALINDI, 0x985D, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (985D)" }, { GDT_KALINDI, 0x985E, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (985E)" }, { GDT_KALINDI, 0x985F, 0x00, GDT_HW_GENERATION_SEAISLAND, true, "Mullins", "MULLINS (985F)" }, // Iceland/Topaz { GDT_ICELAND, 0x6900, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon R7 M260" }, { GDT_ICELAND, 0x6900, 0x81, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon (TM) R7 M360" }, { GDT_ICELAND, 0x6900, 0x83, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon (TM) R7 M340" }, { GDT_ICELAND, 0x6900, 0x87, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "MESO UL (6900)" }, { GDT_ICELAND, 0x6900, 0xC1, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon R5 M465 Series" }, { GDT_ICELAND, 0x6900, 0xC3, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon R5 M445 Series" }, { GDT_ICELAND, 0x6901, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon R5 M255" }, { GDT_ICELAND, 0x6902, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon Series" }, { GDT_ICELAND, 0x6903, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "Not Used" }, { GDT_ICELAND, 0x6907, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon R5 M255" }, { GDT_ICELAND, 0x6907, 0x87, GDT_HW_GENERATION_VOLCANICISLAND, false, "Iceland", "AMD Radeon (TM) R5 M315" }, // Tonga { GDT_TONGA, 0x6920, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD RADEON R9 M395X" }, { GDT_TONGA, 0x6920, 0x01, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD RADEON R9 M390X" }, { GDT_TONGA, 0x6921, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD Radeon (TM) R9 M390X" }, //{ GDT_TONGA, 0x6928, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "" }, { GDT_TONGA, 0x6929, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD FirePro S7150" }, { GDT_TONGA, 0x6929, 0x01, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD FirePro S7100" }, { GDT_TONGA, 0x692B, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD FirePro W7100" }, { GDT_TONGA, 0x692F, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD FirePro S7150VF" }, { GDT_TONGA, 0x6930, 0xF0, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "DID:6930 RID:F0" }, { GDT_TONGA, 0x6930, 0xF1, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "DID:6930 RID:F1" }, { GDT_TONGA, 0x6930, 0xFF, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "DID:6930 RID:FF" }, { GDT_TONGA, 0x6938, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD Radeon R9 200 Series" }, { GDT_TONGA, 0x6938, 0xF1, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD Radeon (TM) R9 380 Series" }, { GDT_TONGA, 0x6938, 0xF0, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD Radeon R9 200 Series" }, { GDT_TONGA, 0x6939, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD Radeon R9 200 Series" }, { GDT_TONGA, 0x6939, 0xF0, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD Radeon R9 200 Series" }, { GDT_TONGA, 0x6939, 0xF1, GDT_HW_GENERATION_VOLCANICISLAND, false, "Tonga", "AMD Radeon (TM) R9 380 Series" }, // Carrizo { GDT_CARRIZO, 0x9870, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "CARRIZO 9870" }, { GDT_CARRIZO, 0x9874, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "CARRIZO 9874" }, { GDT_CARRIZO, 0x9874, 0xC4, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R7 Graphics" }, { GDT_CARRIZO, 0x9874, 0xC5, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xC6, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xC7, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R5 Graphics" }, { GDT_CARRIZO_EMB, 0x9874, 0x84, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R7 Graphics" }, { GDT_CARRIZO_EMB, 0x9874, 0x85, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R6 Graphics" }, { GDT_CARRIZO_EMB, 0x9874, 0x87, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R5 Graphics" }, { GDT_CARRIZO_EMB, 0x9874, 0x81, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R6 Graphics" }, { GDT_CARRIZO_EMB, 0x9874, 0x88, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R7E Graphics" }, { GDT_CARRIZO_EMB, 0x9874, 0x89, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon R6E Graphics" }, { GDT_CARRIZO, 0x9874, 0xC8, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R7 Graphics" }, { GDT_CARRIZO, 0x9874, 0xC9, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xCA, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xCB, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R5 Graphics" }, { GDT_CARRIZO, 0x9874, 0xCC, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R7 Graphics" }, { GDT_CARRIZO, 0x9874, 0xCD, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xCE, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xE1, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R7 Graphics" }, { GDT_CARRIZO, 0x9874, 0xE2, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xE3, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R7 Graphics" }, { GDT_CARRIZO, 0x9874, 0xE4, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R6 Graphics" }, { GDT_CARRIZO, 0x9874, 0xE5, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "AMD Radeon(TM) R5 Graphics" }, { GDT_CARRIZO, 0x9875, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "CARRIZO 9875" }, { GDT_CARRIZO, 0x9876, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "CARRIZO 9876" }, { GDT_CARRIZO, 0x9877, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, true, "Carrizo", "CARRIZO 9877" }, // Fiji { GDT_FIJI, 0x7300, 0x00, GDT_HW_GENERATION_VOLCANICISLAND, false, "Fiji", "AMD Radeon (TM) Graphics Processor" }, { GDT_FIJI, 0x7300, 0xC1, GDT_HW_GENERATION_VOLCANICISLAND, false, "Fiji", "AMD FirePro Processor" }, { GDT_FIJI, 0x7300, 0xC8, GDT_HW_GENERATION_VOLCANICISLAND, false, "Fiji", "AMD Radeon (TM) R9 Fury Series" }, { GDT_FIJI, 0x7300, 0xCB, GDT_HW_GENERATION_VOLCANICISLAND, false, "Fiji", "AMD Radeon (TM) R9 Fury Series" }, { GDT_FIJI, 0x7300, 0xC9, GDT_HW_GENERATION_VOLCANICISLAND, false, "Fiji", "AMD Radeon (TM) Graphics Processor" }, { GDT_FIJI, 0x7300, 0xC0, GDT_HW_GENERATION_VOLCANICISLAND, false, "Fiji", "AMD Radeon Graphics Processor" }, { GDT_FIJI, 0x7300, 0xCA, GDT_HW_GENERATION_VOLCANICISLAND, false, "Fiji", "AMD Radeon (TM) R9 Fury Series" }, }; /// NOTE: Don't update the table below, it's generated from the csv file. /// How to update this table: /// 1. Update device info in the CSV file /// 2. Run deviceinfogen.exe /// 3. Replace GDT_DeviceInfo gs_deviceInfo[] in DeviceInfo.cpp with the content of generated file device_info_table.txt static GDT_DeviceInfo gs_deviceInfo[] = { { 2, 10, 1, 8, 2, 64, 2, 7, 4, true }, // GDT_TAHITI_PRO { 2, 10, 1, 8, 2, 64, 2, 8, 4, true }, // GDT_TAHITI_XT { 2, 10, 1, 8, 2, 64, 2, 4, 4, true }, // GDT_PITCAIRN_PRO { 2, 10, 1, 8, 2, 64, 2, 5, 4, true }, // GDT_PITCAIRN_XT { 1, 10, 1, 8, 1, 64, 2, 4, 4, true }, // GDT_CAPEVERDE_PRO { 1, 10, 1, 8, 1, 64, 2, 5, 4, true }, // GDT_CAPEVERDE_XT { 1, 10, 1, 8, 1, 64, 1, 6, 4, true }, // GDT_OLAND { 1, 10, 1, 8, 1, 64, 1, 5, 4, true }, // GDT_HAINAN { 2, 10, 1, 8, 2, 64, 1, 7, 4, true }, // GDT_BONAIRE { 4, 10, 1, 8, 4, 64, 1, 11, 4, true }, // GDT_HAWAII { 1, 10, 1, 8, 1, 64, 1, 2, 4, true }, // GDT_KALINDI { 1, 10, 1, 8, 1, 64, 1, 8, 4, true }, // GDT_SPECTRE { 1, 10, 1, 8, 1, 64, 1, 4, 4, true }, // GDT_SPECTRE_SL { 1, 10, 1, 8, 1, 64, 1, 6, 4, true }, // GDT_SPECTRE_LITE { 1, 10, 1, 8, 1, 64, 1, 3, 4, true }, // GDT_SPOOKY { 1, 10, 1, 8, 1, 64, 1, 6, 4, true }, // GDT_ICELAND { 4, 10, 1, 8, 4, 64, 1, 8, 4, true }, // GDT_TONGA { 1, 10, 1, 8, 1, 64, 1, 8, 4, true }, // GDT_CARRIZO { 1, 10, 1, 8, 1, 64, 1, 3, 4, true }, // GDT_CARRIZO_EM { 4, 10, 1, 8, 4, 64, 1, 16, 4, true }, // GDT_FIJI { 0, 0, 0, 0, 0, 0, 0, 0, 0, false }, // GDT_STONEY placeholder }; static size_t gs_cardInfoSize = sizeof(gs_cardInfo) / sizeof(GDT_GfxCardInfo); static size_t gs_deviceInfoSize = sizeof(gs_deviceInfo) / sizeof(GDT_DeviceInfo); AMDTDeviceInfoManager::AMDTDeviceInfoManager() { AMDTDeviceInfoUtils* pDeviceInfoUtils = AMDTDeviceInfoUtils::Instance(); for (size_t i = 0; i < gs_cardInfoSize; ++i) { pDeviceInfoUtils->AddDevice(gs_cardInfo[i]); } for (size_t i = 0; i < gs_deviceInfoSize; ++i) { pDeviceInfoUtils->AddDeviceInfo(static_cast(i), gs_deviceInfo[i]); } CallInitInternalDeviceInfo(); } AMDTDeviceInfoManager::~AMDTDeviceInfoManager() {} #ifdef _WIN32 extern "C" IMAGE_DOS_HEADER __ImageBase; #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) #endif void AMDTDeviceInfoManager::CallInitInternalDeviceInfo() const { static const char* initFuncName = "InitInternalDeviceInfo"; static bool initFuncCalled = false; if (!initFuncCalled) { typedef void(*DeviceInfoUtilsReadyFunc)(); DeviceInfoUtilsReadyFunc func = nullptr; #ifdef _WIN32 func = (DeviceInfoUtilsReadyFunc)GetProcAddress(HINST_THISCOMPONENT, initFuncName); #endif #ifdef _LINUX func = (DeviceInfoUtilsReadyFunc)dlsym(nullptr, initFuncName); #endif if (nullptr != func) { func(); initFuncCalled = true; } } } bool AMDTDeviceInfoUtils::GetDeviceInfo(size_t deviceID, size_t revisionID, GDT_DeviceInfo& deviceInfo) const { bool found = false; for (auto it = m_deviceIDMap.find(deviceID); it != m_deviceIDMap.end() && !found; ++it) { size_t thisRevId = (*it).second.m_revID; if (thisRevId == revisionID) { for (auto itr = m_asicTypeDeviceInfoMap.find((*it).second.m_asicType); itr != m_asicTypeDeviceInfoMap.end() && !found; ++itr) { deviceInfo = itr->second; if (deviceInfo.m_deviceInfoValid) { found = true; } } } } return found; } /// NOTE: this might not return the correct GDT_DeviceInfo instance, since some devices with the same CAL name might have different GDT_DeviceInfo instances bool AMDTDeviceInfoUtils::GetDeviceInfo(const char* szCALDeviceName, GDT_DeviceInfo& deviceInfo) const { std::string strDeviceName = TranslateDeviceName(szCALDeviceName); auto it = m_deviceNameMap.find(strDeviceName.c_str()); if (it != m_deviceNameMap.end()) { auto deviceIt = m_asicTypeDeviceInfoMap.find(it->second.m_asicType); if (m_asicTypeDeviceInfoMap.end() != deviceIt) { deviceInfo = deviceIt->second; if (deviceInfo.m_deviceInfoValid) { return true; } } } return false; } bool AMDTDeviceInfoUtils::GetDeviceInfo(size_t deviceID, size_t revisionID, GDT_GfxCardInfo& cardInfo) const { bool found = false; for (auto it = m_deviceIDMap.find(deviceID); it != m_deviceIDMap.end() && !found; ++it) { size_t thisRevId = (*it).second.m_revID; if (thisRevId == revisionID) { cardInfo = (*it).second; found = true; } } return found; } bool AMDTDeviceInfoUtils::GetDeviceInfo(const char* szCalName, vector& cardList) const { std::string strDeviceName = TranslateDeviceName(szCalName); cardList.clear(); pair matches; matches = m_deviceNameMap.equal_range(strDeviceName.c_str()); for (auto it = matches.first; it != matches.second; ++it) { cardList.push_back((*it).second); } return !cardList.empty(); } bool AMDTDeviceInfoUtils::GetDeviceInfoMarketingName(const char* szMarketingName, vector& cardList) const { cardList.clear(); pair matches; matches = m_deviceMarketingNameMap.equal_range(szMarketingName); for (auto it = matches.first; it != matches.second; ++it) { cardList.push_back((*it).second); } return !cardList.empty(); } bool AMDTDeviceInfoUtils::IsAPU(const char* szCALDeviceName, bool& bIsAPU) const { std::string strDeviceName = TranslateDeviceName(szCALDeviceName); auto it = m_deviceNameMap.find(strDeviceName.c_str()); if (it != m_deviceNameMap.end()) { bIsAPU = it->second.m_bAPU; return true; } else { return false; } } bool AMDTDeviceInfoUtils::GetHardwareGeneration(size_t deviceID, GDT_HW_GENERATION& gen) const { // revId not needed here, since all revs will have the same hardware family auto it = m_deviceIDMap.find(deviceID); if (it != m_deviceIDMap.end()) { gen = it->second.m_generation; return true; } else { return false; } } bool AMDTDeviceInfoUtils::GetHardwareGeneration(const char* szName, GDT_HW_GENERATION& gen) const { std::string strDeviceName = TranslateDeviceName(szName); auto it = m_deviceNameMap.find(strDeviceName.c_str()); if (it != m_deviceNameMap.end()) { gen = it->second.m_generation; return true; } else { return false; } } bool AMDTDeviceInfoUtils::GetAllCardsInHardwareGeneration(GDT_HW_GENERATION gen, std::vector& cardList) const { cardList.clear(); pair matches; matches = m_deviceHwGenerationMap.equal_range(gen); for (auto it = matches.first; it != matches.second; ++it) { cardList.push_back((*it).second); } return !cardList.empty(); } bool AMDTDeviceInfoUtils::GetAllCardsWithDeviceId(size_t deviceID, std::vector& cardList) const { cardList.clear(); pair matches; matches = m_deviceIDMap.equal_range(deviceID); for (auto it = matches.first; it != matches.second; ++it) { cardList.push_back((*it).second); } return !cardList.empty(); } bool AMDTDeviceInfoUtils::GetHardwareGenerationDisplayName(GDT_HW_GENERATION gen, std::string& strGenerationDisplayName) const { static const std::string s_SI_FAMILY_NAME = "Graphics IP v6"; static const std::string s_CI_FAMILY_NAME = "Graphics IP v7"; static const std::string s_VI_FAMILY_NAME = "Graphics IP v8"; bool retVal = true; switch (gen) { case GDT_HW_GENERATION_SOUTHERNISLAND: strGenerationDisplayName = s_SI_FAMILY_NAME; break; case GDT_HW_GENERATION_SEAISLAND: strGenerationDisplayName = s_CI_FAMILY_NAME; break; case GDT_HW_GENERATION_VOLCANICISLAND: strGenerationDisplayName = s_VI_FAMILY_NAME; break; default: strGenerationDisplayName.clear(); retVal = false; break; } return retVal; } std::string AMDTDeviceInfoUtils::TranslateDeviceName(const char* strDeviceName) const { std::string retVal(strDeviceName); if (nullptr != m_pDeviceNameTranslatorFunction) { retVal = m_pDeviceNameTranslatorFunction(strDeviceName); } return retVal; } AMDTDeviceInfoUtils* AMDTDeviceInfoUtils::ms_pInstance = nullptr; AMDTDeviceInfoManager AMDTDeviceInfoManager::ms_instance; void AMDTDeviceInfoUtils::AddDeviceInfo(GDT_HW_ASIC_TYPE asicType, const GDT_DeviceInfo& deviceInfo) { if (m_asicTypeDeviceInfoMap.end() == m_asicTypeDeviceInfoMap.find(asicType)) { m_asicTypeDeviceInfoMap.insert(ASICTypeDeviceInfoMapPair(asicType, deviceInfo)); } else { m_asicTypeDeviceInfoMap[asicType] = deviceInfo; } } void AMDTDeviceInfoUtils::AddDevice(const GDT_GfxCardInfo& cardInfo) { m_deviceIDMap.insert(DeviceIDMapPair(cardInfo.m_deviceID, cardInfo)); m_deviceNameMap.insert(DeviceNameMapPair(cardInfo.m_szCALName, cardInfo)); m_deviceMarketingNameMap.insert(DeviceNameMapPair(cardInfo.m_szMarketingName, cardInfo)); m_deviceHwGenerationMap.insert(DeviceHWGenerationMapPair(cardInfo.m_generation, cardInfo)); } void AMDTDeviceInfoUtils::SetDeviceNameTranslator(DeviceNameTranslatorFunction deviceNametranslatorFunction) { m_pDeviceNameTranslatorFunction = deviceNametranslatorFunction; } ================================================ FILE: src/Wrapper/amd-codexl-analyzer/Common/Src/DeviceInfo/DeviceInfoUtils.h ================================================ //===================================================================== // Copyright 2010-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file DeviceInfoUtils.h /// \brief Device info utils class /// //===================================================================== #ifndef _DEVICE_INFO_UTILS_H_ #define _DEVICE_INFO_UTILS_H_ #include #include #include #include #include //------------------------------------------------------------------------------------ /// Device info utils //------------------------------------------------------------------------------------ class AMDTDeviceInfoUtils { public: /// Get AMDTDeviceInfoUtils instance /// \return the dynamically created AMDTDeviceInfoUtils instance static AMDTDeviceInfoUtils* Instance() { if (nullptr == ms_pInstance) { ms_pInstance = new AMDTDeviceInfoUtils(); } return ms_pInstance; } /// Deletes the AMDTDeviceInfoUtils instance static void DeleteInstance() { delete ms_pInstance; ms_pInstance = nullptr; } /// Adds the specified device info /// \param asicType the asic type of the device info being added /// \param deviceInfo the device info being added void AddDeviceInfo(GDT_HW_ASIC_TYPE asicType, const GDT_DeviceInfo& deviceInfo); /// Adds the specified card info /// \param cardInfo the card being added void AddDevice(const GDT_GfxCardInfo& cardInfo); /// Function pointer type for a function that will translate device names typedef std::string(*DeviceNameTranslatorFunction)(const char* strDeviceName); /// Sets the Device name translator function /// \param deviceNametranslatorFunction the function to use to translate device names void SetDeviceNameTranslator(DeviceNameTranslatorFunction deviceNametranslatorFunction); /// Get device info from device ID /// \param[in] deviceID Device ID - usually queried from ADL /// \param[in] revisionID RevisionID - usually queried from ADL /// \param[out] deviceInfo Output device info if device id is found. /// \return True if device info is found bool GetDeviceInfo(size_t deviceID, size_t revisionID, GDT_DeviceInfo& deviceInfo) const; /// Get device info from CAL name string /// NOTE: this might not return the correct GDT_DeviceInfo instance, since some devices with the same CAL name might have different GDT_DeviceInfo instances /// \param[in] szCALDeviceName CAL device name string /// \param[out] deviceInfo Output device info if device id is found. /// \return True if device info is found bool GetDeviceInfo(const char* szCALDeviceName, GDT_DeviceInfo& deviceInfo) const; /// Get Graphics Card Info. /// \param[in] deviceID Device ID - usually queried from ADL /// \param[in] revisionID Revision ID - usually queried from ADL /// \param[out] cardInfo Output graphics card info if device id is found. /// \return True if info for deviceID is found bool GetDeviceInfo(size_t deviceID, size_t revisionID, GDT_GfxCardInfo& cardInfo) const; /// Get a vector of Graphics Card Info. /// \param[in] szCALDeviceName CAL device name string /// \param[out] cardList Output vector of graphics card info. /// \return True if any graphics card info is found for CAL device name. bool GetDeviceInfo(const char* szCALDeviceName, std::vector& cardList) const; /// Get a vector of Graphics Card Info. /// \param[in] szMarketingDeviceName Marketing device name string /// \param[out] cardList Output vector of graphics card info. /// \return True if any graphics card info is found for Marketing device name. bool GetDeviceInfoMarketingName(const char* szMarketingDeviceName, std::vector& cardList) const; /// Query whether or not input device is APU or not /// \param[in] szCALDeviceName CAL device name string /// \param[out] bIsAPU flag indicating whether or not the specified device is an APU /// \return True if device info is found bool IsAPU(const char* szCALDeviceName, bool& bIsAPU) const; /// Get hardware generation from device ID /// \param[in] deviceID Device id /// \param[out] gen Hardware generation /// \return True if device info is found bool GetHardwareGeneration(size_t deviceID, GDT_HW_GENERATION& gen) const; /// Get hardware generation from device name /// \param[in] szCALDeviceName Device name /// \param[out] gen Hardware generation /// \return True if device info is found bool GetHardwareGeneration(const char* szCALDeviceName, GDT_HW_GENERATION& gen) const; /// Get all cards from the specified hardware generation /// \param[in] gen Hardware generation /// \param[out] cardList Output vector of graphics card info. /// \return true if successful, false otherwise bool GetAllCardsInHardwareGeneration(GDT_HW_GENERATION gen, std::vector& cardList) const; /// Get all cards with the specified device id /// \param[in] deviceId DeviceId /// \param[out] cardList Output vector of graphics card info. /// \return true if successful, false otherwise bool GetAllCardsWithDeviceId(size_t deviceID, std::vector& cardList) const; /// Get hardware generation display name /// \param[in] gen Hardware generation /// \param[out] strGenerationDisplayName the display name for the specified hardware generation /// \return true if successful, false otherwise bool GetHardwareGenerationDisplayName(GDT_HW_GENERATION gen, std::string& strGenerationDisplayName) const; /// Determine if the specified device is a member of the specified family /// \param[in] szCALDeviceName CAL device name /// \param[in] generation Generation enum /// \param[out] bRes Set to true if input device name is a specified family card /// \return false if device name is not found bool IsXFamily(const char* szCALDeviceName, GDT_HW_GENERATION generation, bool& bRes) const { GDT_HW_GENERATION gen = GDT_HW_GENERATION_NONE; if (GetHardwareGeneration(szCALDeviceName, gen)) { bRes = gen == generation; return true; } else { return false; } } /// Determine if the specified device is a member of the VI family /// \param[in] szCALDeviceName CAL device name /// \param[out] bIsVI Set to true if input device name is a member of the VI family /// \return false if device name is not found bool IsVIFamily(const char* szCALDeviceName, bool& bIsVI) const { return IsXFamily(szCALDeviceName, GDT_HW_GENERATION_VOLCANICISLAND, bIsVI); } /// Determine if the specified device is a member of the CI family /// \param[in] szCALDeviceName CAL device name /// \param[out] bIsCI Set to true if input device name is a member of the CI family /// \return false if device name is not found bool IsCIFamily(const char* szCALDeviceName, bool& bIsCI) const { return IsXFamily(szCALDeviceName, GDT_HW_GENERATION_SEAISLAND, bIsCI); } /// Determine if the specified device is a member of the SI family /// \param[in] szCALDeviceName CAL device name /// \param[out] bIsSI Set to true if input device name is a member of the SI family /// \return false if device name is not found bool IsSIFamily(const char* szCALDeviceName, bool& bIsSI) const { return IsXFamily(szCALDeviceName, GDT_HW_GENERATION_SOUTHERNISLAND, bIsSI); } /// Determine if the specified device is based on GCN architecture. /// \param[in] szCALDeviceName CAL device name /// \param[out] bIsGCN Set to true if input device name is based on GCN architecture. /// \return false if device name is not found bool IsGCN(const char* szCALDeviceName, bool& bIsGCN) const { bIsGCN = false; bool bRet = IsVIFamily(szCALDeviceName, bIsGCN); if (!bIsGCN) { bRet = IsCIFamily(szCALDeviceName, bIsGCN); } if (!bIsGCN) { bRet = IsSIFamily(szCALDeviceName, bIsGCN); } return bRet; } /// Gets the number of SX blocks in a specific piece of hardware. This is used to override the device base info /// \param pDeviceInfo The device info /// \param generation The hardware generation /// \return The number of SX blocks size_t GetNumSX(const GDT_DeviceInfo* pDeviceInfo, GDT_HW_GENERATION generation) { // We need to figure out how many SX (pixel shader cross bars) there are size_t numSX = 0; if (generation == GDT_HW_GENERATION_SEAISLAND) { numSX = pDeviceInfo->m_nNumShaderEngines * pDeviceInfo->m_nNumSHPerSE; } else { // All other HW uses the following: numSX = pDeviceInfo->m_nNumShaderEngines * 2; } return numSX; } /// Translates the reported device name to the true device name exposed in the DeviceInfo table. /// \param strDeviceName the device name reported by the runtime. /// \return the true device name as exposed by the device info table. std::string TranslateDeviceName(const char* strDeviceName) const; private: /// private constructor AMDTDeviceInfoUtils() : m_pDeviceNameTranslatorFunction(nullptr) {} /// private destructor virtual ~AMDTDeviceInfoUtils() {} //------------------------------------------------------------------------------------ /// const char* comparer used in the DeviceNameMap below //------------------------------------------------------------------------------------ struct cmp_str { /// Operator () overload function /// \param a left operand /// \param b right operand /// \return true if a is less than b bool operator()(const char* a, const char* b) const { return std::strcmp(a, b) < 0; } }; typedef std::multimap DeviceIDMap; ///< typedef for map from device id to card info typedef std::pair DeviceIDMapPair; ///< typedef for device id / card info pair typedef std::multimap DeviceNameMap; ///< typedef for map from CAL device name to card info (with custom comparer) typedef std::pair DeviceNameMapPair; ///< typedef for device name / card info pair typedef std::multimap DeviceHWGenerationMap; ///< typedef for map from hardware generation to card info typedef std::pair DeviceHWGenerationMapPair; ///< typedef for hardware generation / card info pair typedef std::map ASICTypeDeviceInfoMap; ///< typedef for map from asic type to device info typedef std::pair ASICTypeDeviceInfoMapPair; ///< typedef for asic type / device info pair DeviceIDMap m_deviceIDMap; ///< device ID to card info map. DeviceNameMap m_deviceNameMap; ///< cal device name to card info map. DeviceNameMap m_deviceMarketingNameMap; ///< marketing device name to card info map. DeviceHWGenerationMap m_deviceHwGenerationMap; ///< hardware generation to card info map. ASICTypeDeviceInfoMap m_asicTypeDeviceInfoMap; ///< ASIC type to device info map. DeviceNameTranslatorFunction m_pDeviceNameTranslatorFunction; /// the function to call to translate device names static AMDTDeviceInfoUtils* ms_pInstance; }; //------------------------------------------------------------------------------------ /// Device info manager //------------------------------------------------------------------------------------ class AMDTDeviceInfoManager { /// Get singleton AMDTDeviceInfoManager instance /// \return the singleton AMDTDeviceInfoManager instance static AMDTDeviceInfoManager* Instance() { return &ms_instance; } private: /// Constructor AMDTDeviceInfoManager(); /// Destructor ~AMDTDeviceInfoManager(); /// Locates and calls the device info utils function to initialize internal device info. /// This allows internal versions of the tools to expose hardware not exposed in the public /// versions of the tools (i.e. unreleased hardware) void CallInitInternalDeviceInfo() const; static AMDTDeviceInfoManager ms_instance; ///< the singleton AMDTDeviceInfoManager instance }; #endif // _DEVICE_INFO_UTILS_H_ ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/AmdDxGsaCompile.h ================================================ //============================================================================== // Copyright 2012-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// \brief Backdoor GSA compile extension include file. //============================================================================== #ifndef _AMDDXGSACOMPILE_H_ #define _AMDDXGSACOMPILE_H_ #include #if defined(__cplusplus) extern "C" { #endif /** *************************************************************************************************** * @brief Identifies compile options to be modified in AmdDxGsaCompileShader() call. *************************************************************************************************** */ typedef enum _AmdDxGsaCompileOptionEnum { AmdDxGsaBiasScheduleToMinimizeRegs, AmdDxGsaNoIfConversion, AmdDxGsaIfConversionGuarantee, AmdDxGsaIfConversionHeuristic, AmdDxGsaIfConversionHeuristicOgl, AmdDxGsaIfConversionAlways, AmdDxGsaCompileOptionLast } AmdDxGsaCompileOptionEnum; /** *************************************************************************************************** * @brief Compiler settings/value pair specified in AmdDxGsaCompileShader() calls. *************************************************************************************************** */ typedef struct _AmdDxGsaCompileOption { AmdDxGsaCompileOptionEnum setting; INT value; } AmdDxGsaCompileOption; /** *************************************************************************************************** * @brief Stats about the compiled shader. This structure will be stored in the .stats ELF section *************************************************************************************************** */ typedef struct _AmdDxGsaCompileStats { UINT numSgprsUsed; UINT availableSgprs; UINT numVgprsUsed; UINT availableVgprs; UINT usedLdsBytes; UINT availableLdsBytes; UINT usedScratchBytes; UINT numAluInst; ///< Number of ALU instructions in the shader UINT numControlFlowInst; ///< Number of control flow instructions in the shader UINT numTfetchInst; ///< Number of HW TFETCHinstructions / Tx Units used UINT reserved[6]; } AmdDxGsaCompileStats; /** *************************************************************************************************** * @brief AmdDxGsaCompileShader() input structure. *************************************************************************************************** */ typedef struct _AmdDxGsaCompileShaderInput { /// Target GPU chip family (defined in atiid.h, e.g. FAMILY_SI). Only FAMILY_SI and later are /// currently supported. UINT chipFamily; /// Target GPU chip revision (defined in hardware-specific chip headers, e.g. si_id.h). UINT chipRevision; /// Pointer to DXASM bytecode to be compiled. const VOID* pShaderByteCode; /// Length of pShaderByteCode in bytes. SIZE_T byteCodeLength; /// An array of setting/value pairs to control compilation options. NULL is valid, if all /// default options are desired. const AmdDxGsaCompileOption* pCompileOptions; /// Length of pCompileOptions array. UINT numCompileOptions; /// Reserved entry must be set to all 0s. unsigned int reserved[7]; } AmdDxGsaCompileShaderInput; /** *************************************************************************************************** * @brief AmdDxGsaCompileShader() output structure. *************************************************************************************************** */ typedef struct _AmdDxGsaCompileShaderOutput { /// Must be set to sizeof(AmdDxGsaCompileShaderOutput). SIZE_T size; /// Output ELF object. Contains .amdil (IL), .text (ISA), and .stats (AmdDxGsaCompileStats) VOID* pShaderBinary; /// Size of the ELF object in bytes. SIZE_T shaderBinarySize; } AmdDxGsaCompileShaderOutput; HRESULT __cdecl AmdDxGsaCompileShader(const AmdDxGsaCompileShaderInput* pIn, AmdDxGsaCompileShaderOutput* pOut); typedef HRESULT(__cdecl* PfnAmdDxGsaCompileShader)(const AmdDxGsaCompileShaderInput*, AmdDxGsaCompileShaderOutput*); VOID __cdecl AmdDxGsaFreeCompiledShader(VOID* pShaderBinary); typedef VOID (__cdecl* PfnAmdDxGsaFreeCompiledShader)(VOID*); #if defined(__cplusplus) } #endif #endif // _AMDDXGSACOMPILE_H_ ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/atiid.h ================================================ //===================================================================== // Copyright 2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //===================================================================== /*****************************************************************************\ * * Module Name atiid.h * Project R128/M3/R6 WindowsNT * Device R128/M3/R6 * * Description Common Family ID file for R128/M3/R6 driver * \*****************************************************************************/ #ifndef _ATIID_H #define _ATIID_H // // Define Asic Family IDs for different asic family. // //[espiritu - 06/21/00] //TO DO: change enumeration of all asic families including RageProDerivatives, as //these are in conflict (used especially in TVOut). #define FAMILY_UNKNOWN 0 #define FAMILY_RAGE_128 1 #define FAMILY_RAGE_128_4X 2 #define FAMILY_RAGE_128_PRO 3 #define FAMILY_M3 4 #define FAMILY_RAGE_6 5 #define FAMILY_RADEON100 FAMILY_RAGE_6 #define FAMILY_RAGE_6LITE 6 #define FAMILY_M6 7 #define FAMILY_RADEON200 8 #define FAMILY_RAGE_128_PROII 21 /*EPR#40430 temporary only, in conflict with LTPro asic in TVOut.*/ #define FAMILY_U1 22 // CABO family; including A3, A4 and U1 #define FAMILY_RS200 23 // including RS250, RS250M #define FAMILY_RS200M 24 #define FAMILY_RS300 25 // including Device ID: RS300,RS300VE,RS300M,RS300ML #define FAMILY_RS400 26 // including Device ID: RS400,RS400M #define FAMILY_RS480 27 // including Device ID: RS480,RS480M #define FAMILY_RC410 28 // including Device ID: RC410,RC410M #define FAMILY_RS600 29 // including Device ID: RS600,RS600M //Integrated ASICs continued from 65 // // *** CHIP FAMILIES *** // from rprod.h plus 30 // Chip family - sorted by growing capability of the chip. // //#define FAMILY_UNKNOWN 30 //#define FAMILY_VTB, 31 // ATI-264VT3 family //#define FAMILY_VTB_PLUS, 32 // ATI-264VT3 UMC family //#define FAMILY_VTB_VT4, 33 // ATI-264VT4 family //#define FAMILY_GTB, 34 // 3D RAGE II family //#define FAMILY_LTG, 35 // 3D RAGE LT-G family //#define FAMILY_GTB_PLUS, 36 // 3D RAGE II+ family //#define FAMILY_GTB_IIC, 37 // 3D RAGE IIC family //#define FAMILY_GTC, 38 // 3D RAGE PRO family //#define FAMILY_LT_PRO, 39 // 3D RAGE LT PRO family //#define FAMILY_RAGE_XL, 40 // 3D RAGE XL //#define FAMILY_RAGE_XC 41 // 3D RAGE XC // // Define Vendor ID. // #define FAMILY_MORPHEUS 42 #define FAMILY_RV200 FAMILY_MORPHEUS #define FAMILY_M7 43 #define FAMILY_KHAN 44 #define FAMILY_R300 FAMILY_KHAN #define FAMILY_RV350 45 #define FAMILY_M10 46 #define FAMILY_IRIS 47 #define FAMILY_RV250 FAMILY_IRIS #define FAMILY_M9 48 #define FAMILY_ARGUS 49 #define FAMILY_RV280 FAMILY_ARGUS #define FAMILY_R400 50 #define FAMILY_M9PLUS 51 #define FAMILY_R350 52 #define FAMILY_R360 53 #define FAMILY_RV380 54 #define FAMILY_M24 55 #define FAMILY_LOKI 56 #define FAMILY_R420 FAMILY_LOKI // R423 shares the same family id with LOKI #define FAMILY_M18 57 // M28 shares the same family id with M18 #define FAMILY_ALTO 58 #define FAMILY_RV410 FAMILY_ALTO #define FAMILY_M26 59 #define FAMILY_R520 60 #define FAMILY_M58 61 // mobile version of R520 #define FAMILY_RV5XX 62 // RV530, RV535, RV515 #define FAMILY_MV5X 63 // mobile version of RV5xx //Integrated ASICS #define FAMILY_RS690 65 // including Device ID: RS690,RS690C,RS690M,RS690MC,RS690T; RS740, RS740M #define FAMILY_R600 70 // Pele #define FAMILY_RV6XX 71 // RV6xx #define FAMILY_MV6X 72 // Mobile version of RV6xx //R600 based integrated ASICs Family ID start from 75 #define FAMILY_RS780 75 //RS780/RS780M Functionality level will be defined by revision ID. #define FAMILY_R700 80 //FAMILY_RV7XX // FAMILY_R700 will be removed later #define FAMILY_RV7XX 81 // WEKIVA/RV7xx #define FAMILY_MV7X 82 // Mobile version of RV7xx #define FAMILY_KONG 85 // Fusion Roadrunner project - SwiftGPU100/200/300 #define FAMILY_EVERGREEN 90 // EVERGREEN #define FAMILY_RV8XX 90 // Deprecated #define FAMILY_MANHATTAN 91 // MANHATTAN #define FAMILY_MV8X 91 // Deprecated #define FAMILY_SUMO 95 // Fusion Llano/Ontario project - SuperSumo/Sumo/Wrestler variants #define FAMILY_NI 100 // Northern Islands: Ibiza, Cozumel, Kauai #define FAMILY_NORTHERNISLAND FAMILY_NI // Keeping the original name for backward compatibility. FAMILY_NI follows the new naming convention #define FAMILY_SI 110 // Southern Islands: Tahiti (P), Pitcairn (PM), Cape Verde (M), Bali (V) #define FAMILY_TN 105 // Fusion Trinity: Devastator - DVST (M), Scrapper (V) #define FAMILY_CI 120 // Sea Islands: Hawaii (P), Maui (P), Bonaire (M) #define FAMILY_KV 125 // Fusion Kaveri: Spectre, Spooky; Fusion Kabini: Kalindi #define FAMILY_VI 130 // Volcanic Islands: Iceland (V), Tonga (M) #define FAMILY_CZ 135 // Carrizo, Nolan, Amur #define FAMILY_PI 140 // Pirate Islands #define ATI_VENDOR_ID 0x1002 #endif // _ATIID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/ci_id.h ================================================ //===================================================================== // Copyright 2011-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //===================================================================== /***************************************************************************** * * Module Name ci_id.h * Project SEA ISLANDS * Devices SEA ISLANDS * * Description Defining Device IDs, ASIC revision IDs for SEA ISLANDS * *****************************************************************************/ #ifndef _CI_ID_H #define _CI_ID_H enum { CI_TIRAN_P_A0 = 1, // Tiran is obsolete, please do not use CI_BONAIRE_M_A0 = 20, CI_BONAIRE_M_A1 = 21, CI_HAWAII_P_A0 = 40, CI_MAUI_P_A0 = 60, CI_UNKNOWN = 0xFF }; #define ASICREV_IS_TIRAN_P(eChipRev) (eChipRev < CI_BONAIRE_M_A0) #define ASICREV_IS_BONAIRE_M(eChipRev) ((eChipRev >= CI_BONAIRE_M_A0) && (eChipRev < CI_HAWAII_P_A0)) #define ASICREV_IS_HAWAII_P(eChipRev) ((eChipRev >= CI_HAWAII_P_A0) && (eChipRev < CI_MAUI_P_A0)) #define ASICREV_IS_MAUI_P(eChipRev) (eChipRev >= CI_MAUI_P_A0) // // TIRAN/TIRAN MOBILE device IDs (Performance segment) // #define DEVICE_ID_CI_TIRAN_P_6600 0x6600 // unfused // TIRAN ASIC internal revision number #define INTERNAL_REV_CI_TIRAN_P_A0 0x00 // First spin of Tiran #define DEVICE_ID_CI_TIRAN_P_PALLADIUM 0x37 // Palladium ID #define DEVICE_ID_CI_TIRAN_P_LITE_PALLADIUM 0x40 // Palladium ID // // BONAIRE/SATURN/EMERALD/STRATO device IDs (Performance to Mainstream segment) // #define DEVICE_ID_CI_BONAIRE_M_6640 0x6640 // Saturn XT #define DEVICE_ID_CI_BONAIRE_M_6641 0x6641 // Saturn PRO #define DEVICE_ID_CI_BONAIRE_M_6646 0x6646 // Emerald XT; Strato XT #define DEVICE_ID_CI_BONAIRE_M_6647 0x6647 // Emerald PRO; Strato Pro #define DEVICE_ID_CI_BONAIRE_M_6649 0x6649 // Bonaire GL Pro #define DEVICE_ID_CI_BONAIRE_M_664E 0x664E // Strato PRO #define DEVICE_ID_CI_BONAIRE_M_6650 0x6650 // Bonaire XT #define DEVICE_ID_CI_BONAIRE_M_6651 0x6651 // Bonaire Pro #define DEVICE_ID_CI_BONAIRE_M_6658 0x6658 // Bonaire XTX #define DEVICE_ID_CI_BONAIRE_M_665C 0x665C // Bonaire XT #define DEVICE_ID_CI_BONAIRE_M_665D 0x665D // Bonaire Pro // STRATO PCI Reivsion IDs #define PRID_CI_BONAIRE_STRATO_80 0x80 // 0x6646: Strato XT; 0x6647: Strato Pro #define ASICID_IS_STRATO(wDID, bRID) ((bRID == PRID_CI_BONAIRE_STRATO_80) && \ ((wDID == DEVICE_ID_CI_BONAIRE_M_6646) || (wDID == DEVICE_ID_CI_BONAIRE_M_6647))) #define DEVICE_ID_CI_BONAIRE_M_PALLADIUM 0x45 // Palladium ID #define DEVICE_ID_CI_BONAIRE_M_LITE_PALLADIUM 0x46 // Palladium ID // BONAIRE ASIC internal revision number #define INTERNAL_REV_CI_BONAIRE_M_A0 0x00 // First spin of Bonaire #define INTERNAL_REV_CI_BONAIRE_M_A1 0x01 // Second spin of Bonaire // // HAWAII device IDs (Performance segment) // #define DEVICE_ID_CI_HAWAII_P_66A0 0x66A0 // Obsolete #define DEVICE_ID_CI_HAWAII_P_67A0 0x67A0 // Hawaii GL44 #define DEVICE_ID_CI_HAWAII_P_67A1 0x67A1 // Hawaii GL40 #define DEVICE_ID_CI_HAWAII_P_67A2 0x67A2 // Hawaii GL Gemini #define DEVICE_ID_CI_HAWAII_P_67A8 0x67A8 // Hawaii GL XT #define DEVICE_ID_CI_HAWAII_P_67A9 0x67A9 // Hawaii GL Gemini #define DEVICE_ID_CI_HAWAII_P_67AA 0x67AA // Hawaii GL Pro #define DEVICE_ID_CI_HAWAII_P_67B0 0x67B0 // Hawaii XT #define DEVICE_ID_CI_HAWAII_P_67B1 0x67B1 // Hawaii Pro #define DEVICE_ID_CI_HAWAII_P_67B8 0x67B8 // Obsolete #define DEVICE_ID_CI_HAWAII_P_67B9 0x67B9 // Hawaii Gemini #define DEVICE_ID_CI_HAWAII_P_67BA 0x67BA // Obsolete #define DEVICE_ID_CI_HAWAII_P_67BE 0x67BE // Hawaii LE #define DEVICE_ID_CI_HAWAII_P_PALLADIUM 0x00 // Palladium ID #define DEVICE_ID_CI_HAWAII_P_LITE_PALLADIUM 0x0052 // Palladium ID // HAWAII ASIC internal revision number #define INTERNAL_REV_CI_HAWAII_P_A0 0x00 // First spin of Hawaii // // MAUI device IDs (Performance segment) // #define DEVICE_ID_CI_MAUI_P_66E0 0x66E0 // unfused #define DEVICE_ID_CI_MAUI_P_PALLADIUM 0x00 // Palladium ID #define DEVICE_ID_CI_MAUI_P_LITE_PALLADIUM 0x00 // Palladium ID // HAWAII ASIC internal revision number #define INTERNAL_REV_CI_MAUI_P_A0 0x00 // First spin of Maui #endif // _CI_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/cz_id.h ================================================ //===================================================================== // Copyright 2013-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //===================================================================== /*****************************************************************************\ * * Module Name cz_id.h * Project CARRIZO * Devices CARRIZO * * Description Defining Device IDs, ASIC revision IDs for CARRIZO * \*****************************************************************************/ #ifndef _CZ_ID_H #define _CZ_ID_H enum { CARRIZO_A0 = 0x01, CARRIZO_A1 = 0x02, NOLAN_A0 = 0x21, AMUR_A0 = 0x41, STONEY_A0 = 0x61, CZ_UNKNOWN = 0xFF }; #define ASICREV_IS_CARRIZO(eChipRev) ( (eChipRev >= CARRIZO_A0) && (eChipRev < NOLAN_A0) ) #define ASICREV_IS_NOLAN(eChipRev) ( (eChipRev >= NOLAN_A0) && (eChipRev < AMUR_A0) ) #define ASICREV_IS_AMUR(eChipRev) ( (eChipRev >= AMUR_A0) && (eChipRev < STONEY_A0) ) #define ASICREV_IS_STONEY(eChipRev) ( (eChipRev >= STONEY_A0) && (eChipRev < CZ_UNKNOWN) ) // // Carrizo device IDs // #define DEVICE_ID_CZ_9870 0x9870 // Palladium #define DEVICE_ID_CZ_9874 0x9874 #define DEVICE_ID_CZ_9875 0x9875 #define DEVICE_ID_CZ_9876 0x9876 #define DEVICE_ID_CZ_9877 0x9877 // CARRIZO ASIC internal revision number #define INTERNAL_REV_CARRIZO_A0 0x00 // First spin of CARRIZO #define INTERNAL_REV_CARRIZO_A1 0x01 // Second spin of CARRIZO // CARRIZO PCI Reivsion IDs #define PRID_CZ_C4 0xC4 // Client B10 #define PRID_CZ_C5 0xC5 // Client B8 #define PRID_CZ_C6 0xC6 // Client B6 #define PRID_CZ_C7 0xC7 // Client B4 // // Nolan embedded device IDs // #define DEVICE_ID_NL_98C0 0x98C0 // Nolan embedded internal GFX #define DEVICE_ID_NL_98CC 0x98CC // Nolan Emb iTemp Prime 4C #define DEVICE_ID_NL_98CD 0x98CD // Nolan Emb iTemp Prime 2C #define PRID_NOLAN_80 0x80 // Embedded 15W 4CU #define PRID_NOLAN_81 0x81 // Embedded 4W 4CU #define PRID_NOLAN_82 0x82 // Embedded 5W 2CU #define PRID_NOLAN_83 0x83 // Embedded 5W no CU // NOLAN ASIC internal revision number #define INTERNAL_REV_NOLAN_A0 0x00 // First spin of NOLAN // // Amur device IDs // #define DEVICE_ID_AM_9890 0x9890 // AMUR ASIC internal revision number #define INTERNAL_REV_AMUR_A0 0x00 // First spin of AMUR // // Stoney device IDs // #define DEVICE_ID_ST_98E4 0x98E4 // STONEY ASIC internal revision number #define INTERNAL_REV_STONEY_A0 0x00 // First spin of STONEY // STONEY PCI Revision IDs #define PRID_ST_C0 0xC0 // 15W 2C N FT4 98E4 #define PRID_ST_C1 0xC1 // 15W 2C N FP4 98E4 #define PRID_ST_C8 0xC8 // 10W 2C N-4 FT4 98E4 #define PRID_ST_C9 0xC9 // 10W 2C N-4 FP4 98E4 #define PRID_ST_D1 0xD1 // 15W 2C N-1 FP4 98E4 #define PRID_ST_D8 0xD8 // 4.5W 2C N-1 FT4 98E4 #define PRID_ST_E0 0xE0 // 15W 2C N-2 FT4 98E4 #define PRID_ST_E1 0xE1 // 15W 2C N-2 FP4 98E4 #define PRID_ST_F1 0xF1 // 15W 2C N-3 FP4 98E4 #endif // _CZ_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/evergreen_id.h ================================================ //===================================================================== // Copyright 2008-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //=====================================================================/*****************************************************************************\ //* //* Module Name evergreen_id.h //* Project EVERGREEN //* Devices EVERGREEN //* //* Description Defining Device IDs, ASIC revision IDs for EVERGREEN //* //* //* (c) 2008 Advanced Micro Devices, Inc. (unpublished) //* //* All rights reserved. This notice is intended as a precaution against //* inadvertent publication and does not imply publication or any waiver //* of confidentiality. The year included in the foregoing notice is the //* year of creation of the work. //* //* LOG OF CHANGES //* //* 1.0 08/29/2008 - initial revision //* //\*****************************************************************************/ #ifndef _EVERGREEN_ID_H #define _EVERGREEN_ID_H enum { CYPRESS_A11 = 1, CYPRESS_A12 = 2, JUNIPER_A11 = 20, JUNIPER_A12 = 21, REDWOOD_A11 = 40, REDWOOD_A12 = 41, CEDAR_A11 = 60, CEDAR_A12 = 61, EVERGREEN_UNKNOWN = 0xFF }; #define ASICREV_IS_CYPRESS(eChipRev) (eChipRev < JUNIPER_A11) #define ASICREV_IS_JUNIPER(eChipRev) ((eChipRev >= JUNIPER_A11) && (eChipRev < REDWOOD_A11)) #define ASICREV_IS_REDWOOD(eChipRev) ((eChipRev >= REDWOOD_A11) && (eChipRev < CEDAR_A11)) #define ASICREV_IS_CEDAR(eChipRev) (eChipRev >= CEDAR_A11) // // CYPRESS/LEXINGTON device IDs // #define DEVICE_ID_CYPRESS_6888 0x6888 // CYPRESS GL XT #define DEVICE_ID_CYPRESS_6889 0x6889 // CYPRESS GL Pro #define DEVICE_ID_CYPRESS_688A 0x688A // CYPRESS GL XT #define DEVICE_ID_CYPRESS_688C 0x688C // CYPRESS - FS (Osprey) #define DEVICE_ID_CYPRESS_688D 0x688D // CYPRESS - FS (Kestrel) #define DEVICE_ID_CYPRESS_6898 0x6898 // CYPRESS XT #define DEVICE_ID_CYPRESS_6899 0x6899 // CYPRESS PRO #define DEVICE_ID_CYPRESS_689B 0x689B // CYPRESS PRO (Rebranch) #define DEVICE_ID_CYPRESS_689C 0x689C // HEMLOCK XT - CYPRESS Gemini #define DEVICE_ID_CYPRESS_689D 0x689D // HEMLOCK PRO - CYPRESS Gemini #define DEVICE_ID_CYPRESS_689E 0x689E // CYPRESS LE #define DEVICE_ID_CYPRESS_6880 0x6880 // LEXINGTON GL XT - CYPRESS Mobile #define DEVICE_ID_CYPRESS_6890 0x6890 // LEXINGTON XT - CYPRESS Mobile #define DEVICE_ID_CYPRESS_PALLADIUM 0x0010 // Palladium ID #define DEVICE_ID_CYPRESS_LITE_PALLADIUM 0x0012 // Palladium ID // CYPRESS ASIC internal revision number #define INTERNAL_REV_CYPRESS_A11 0x00 // First spin of CYPRESS ASIC #define INTERNAL_REV_CYPRESS_A12 0x01 // Second spin of CYPRESS ASIC // // JUNIPER/BROADWAY device IDs // #define DEVICE_ID_JUNIPER_68A9 0x68A9 // JUNIPER GL Pro #define DEVICE_ID_JUNIPER_68B8 0x68B8 // JUNIPER XT #define DEVICE_ID_JUNIPER_68B9 0x68B9 // JUNIPER PRO #define DEVICE_ID_JUNIPER_68BA 0x68BA // JUNIPER XT (BD3D) #define DEVICE_ID_JUNIPER_68BE 0x68BE // JUNIPER LE #define DEVICE_ID_JUNIPER_68BF 0x68BF // JUNIPER LE (BD3D) #define DEVICE_ID_JUNIPER_68A0 0x68A0 // BROADWAY XGL - JUNIPER Mobile #define DEVICE_ID_JUNIPER_68A1 0x68A1 // BROADWAY GL Pro/LP - JUNIPER Mobile #define DEVICE_ID_JUNIPER_68A8 0x68A8 // BROADWAY PRO & LP - JUNIPER Mobile #define DEVICE_ID_JUNIPER_68B0 0x68B0 // BROADWAY XT - JUNIPER Mobile #define DEVICE_ID_JUNIPER_68B1 0x68B1 // BROADWAY PRO & LP - JUNIPER Mobile #define DEVICE_ID_JUNIPER_PALLADIUM 0x0011 // Palladium ID // JUNIPER ASIC internal revision number #define INTERNAL_REV_JUNIPER_A11 0x00 // First spin of JUNIPER ASIC #define INTERNAL_REV_JUNIPER_A12 0x01 // Second spin of JUNIPER ASIC // // REDWOOD/PINEWOOD/MADISON device IDs // #define DEVICE_ID_REDWOOD_68C8 0x68C8 // Redwood XT GL #define DEVICE_ID_REDWOOD_68C9 0x68C9 // Redwood PRO GL #define DEVICE_ID_REDWOOD_68D8 0x68D8 // Redwood XT #define DEVICE_ID_REDWOOD_68D9 0x68D9 // Redwood PRO #define DEVICE_ID_REDWOOD_68DA 0x68DA // Redwood PRO2 #define DEVICE_ID_REDWOOD_68DE 0x68DE // Redwood LE #define DEVICE_ID_REDWOOD_68C7 0x68C7 // Pinewood #define DEVICE_ID_REDWOOD_68C0 0x68C0 // Madison XT GL #define DEVICE_ID_REDWOOD_68C1 0x68C1 // Madison PRO & LP GL #define DEVICE_ID_REDWOOD_68D0 0x68D0 // Madison XT #define DEVICE_ID_REDWOOD_68D1 0x68D1 // Madison PRO & LP #define DEVICE_ID_REDWOOD_PALLADIUM 0x0013 // Palladium ID // REDWOOD ASIC internal revision number #define INTERNAL_REV_REDWOOD_A11 0x00 // First spin of REDWOOD #define INTERNAL_REV_REDWOOD_A12 0x01 // Second spin of REDWOOD // // CEDAR/PARK/ROBSON device IDs // #define DEVICE_ID_CEDAR_68E8 0x68E8 // Cedar XT GL #define DEVICE_ID_CEDAR_68E9 0x68E9 // Cedar PRO GL #define DEVICE_ID_CEDAR_68F2 0x68F2 // Cedar Prowl #define DEVICE_ID_CEDAR_68F8 0x68F8 // Cedar XT #define DEVICE_ID_CEDAR_68F9 0x68F9 // Cedar PRO #define DEVICE_ID_CEDAR_68FA 0x68FA // Cedar PRO2 #define DEVICE_ID_CEDAR_68FE 0x68FE // Cedar LE #define DEVICE_ID_CEDAR_68E0 0x68E0 // Park PRO & XT GL #define DEVICE_ID_CEDAR_68E1 0x68E1 // Park LP GL #define DEVICE_ID_CEDAR_68E4 0x68E4 // Robson CE #define DEVICE_ID_CEDAR_68E5 0x68E5 // Robson LE #define DEVICE_ID_CEDAR_68F0 0x68F0 // Park PRO & XT #define DEVICE_ID_CEDAR_68F1 0x68F1 // Park LP #define DEVICE_ID_CEDAR_PALLADIUM 0x0014 // Palladium ID // CEDAR ASIC internal revision number #define INTERNAL_REV_CEDAR_A11 0x00 // First spin of CEDAR #define INTERNAL_REV_CEDAR_A12 0x01 // Second spin of CEDAR #endif // _EVERGREEN_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/kv_id.h ================================================ //===================================================================== // Copyright 2011-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //===================================================================== /*****************************************************************************\ * * Module Name kv_id.h * Project Kaveri Family * Device Spectre, Spooky, KALINDI * * Description Identifier file for Kaveri and Kabini driver * LOG OF CHANGES * * 0.1 07/27/11 - initial revision * \*****************************************************************************/ #ifndef KV_ID_H #define KV_ID_H // SW revision section enum { KV_SPECTRE_A0 = 0x01, // KV1 with Spectre GFX core, 8-8-1-2 (CU-Pix-Primitive-RB) KV_SPOOKY_A0 = 0x41, // KV2 with Spooky GFX core, including downgraded from Spectre core, 3-4-1-1 (CU-Pix-Primitive-RB) KB_KALINDI_A0 = 0x81, // KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) KB_KALINDI_A1 = 0x82, // KB with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) BV_KALINDI_A2 = 0x85, // BV with Kalindi GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) ML_GODAVARI_A0 = 0xa1, // ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) ML_GODAVARI_A1 = 0xa2, // ML with Godavari GFX core, 2-4-1-1 (CU-Pix-Primitive-RB) KV_UNKNOWN = 0xFF }; #define ASICREV_IS_SPECTRE(eChipRev) ((eChipRev >= KV_SPECTRE_A0) && (eChipRev < KV_SPOOKY_A0)) // identify all versions of SPRECTRE and supported features set #define ASICREV_IS_SPOOKY(eChipRev) ((eChipRev >= KV_SPOOKY_A0) && (eChipRev < KB_KALINDI_A0)) // identify all versions of SPOOKY and supported features set #define ASICREV_IS_KALINDI(eChipRev) ((eChipRev >= KB_KALINDI_A0) && (eChipRev < KV_UNKNOWN)) // identify all versions of KALINDI and supported features set // Following macros are subset of ASICREV_IS_KALINDI macro #define ASICREV_IS_KALINDI_BHAVANI(eChipRev) ((eChipRev >= BV_KALINDI_A2) && (eChipRev < ML_GODAVARI_A0)) // identify all versions of BHAVANI and supported features set #define ASICREV_IS_KALINDI_GODAVARI(eChipRev) ((eChipRev >= ML_GODAVARI_A0) && (eChipRev < KV_UNKNOWN)) // identify all versions of GODAVARI and supported features set // // Define Chip ID's for Kaveri family // #define DEVICE_ID_SPECTRE_MOBILE 0x1304 // OBSOLETE - TO BE REMOVED //FP3 soldered, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_MOBILE_1304 0x1304 // FP3 soldered, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_DESKTOP 0x1305 // OBSOLETE - TO BE REMOVED //FM2r2 socket, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_DESKTOP_1305 0x1305 // FM2r2 socket, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPOOKY_MOBILE 0x1306 // OBSOLETE - TO BE REMOVED //FS2 socket, 3-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_SL_MOBILE_1306 0x1306 // FP3 soldered, 4-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPOOKY_DESKTOP 0x1307 // OBSOLETE - TO BE REMOVED //FM3 socket,3-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_SL_DESKTOP_1307 0x1307 // FM2r2 socket, 4-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_LITE_MOBILE_1309 0x1309 // FP3 soldered, 6-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_LITE_MOBILE_130A 0x130A // FP3 soldered, 6-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_SL_MOBILE_130B 0x130B // FP3 soldered, 4-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_MOBILE_130C 0x130C // FP3 soldered, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_LITE_MOBILE_130D 0x130D // FP3 soldered, 6-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_SL_MOBILE_130E 0x130E // FP3 soldered, 4-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_DESKTOP_130F 0x130F // FM2r2 socket, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_WORKSTATION_1310 0x1310 // FM2r2 socket, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_WORKSTATION_1311 0x1311 // FM2r2 socket, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPOOKY_DESKTOP_1312 0x1312 // FM2r2, 3-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_LITE_DESKTOP_1313 0x1313 // FM2r2 socket, 6-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_SL_DESKTOP_1315 0x1315 // FM2r2 socket, 4-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPOOKY_DESKTOP_1316 0x1316 // FM2r2 socket, 3-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPOOKY_MOBILE_1317 0x1317 // FP3, 3-4-1-1 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_SL_MOBILE_1318 0x1318 // FP3, 4-4-1-1 (CU-Pix-Primitive-RB), ACP disabled in SW #define DEVICE_ID_SPECTRE_SL_EMBEDDED_131B 0x131B // FP3 soldered, 4-4-1-1 (CU-Pix-Primitive-RB), ACP disabled in SW #define DEVICE_ID_SPECTRE_EMBEDDED_131C 0x131C // FP3 soldered, 8-8-1-2 (CU-Pix-Primitive-RB) #define DEVICE_ID_SPECTRE_LITE_EMBEDDED_131D 0x131D // FP3, 6-8-1-2 (CU-Pix-Primitive-RB) // Define AMD's internal revision numbers. #define INTERNAL_REV_SPECTRE_A0 0x00 // The First revision of SPECTRE GFX. // Define AMD's external revision numbers. #define EXTERNAL_REV_SPECTRE 0x00 // // Define Chip ID's for Kabini // #define DEVICE_ID_KALINDI__9830 0x9830 // FT3 socket and FS1b socket #define DEVICE_ID_KALINDI__9831 0x9831 // FT3 socket, #define DEVICE_ID_KALINDI__9832 0x9832 // FT3 socket, #define DEVICE_ID_KALINDI__9833 0x9833 // FT3 socket, #define DEVICE_ID_KALINDI__9834 0x9834 // FT3 socket, #define DEVICE_ID_KALINDI__9835 0x9835 // FT3 socket, #define DEVICE_ID_KALINDI__9836 0x9836 // FT3 socket and FS1b socket #define DEVICE_ID_KALINDI__9837 0x9837 // FT3 socket, #define DEVICE_ID_KALINDI__9838 0x9838 // FT3 socket and FS1b socket // // Define Chip ID's for Temash // #define DEVICE_ID_TEMASH__9839 0x9839 // FT3 socket, #define DEVICE_ID_TEMASH__983a 0x983a // FT3 socket, #define DEVICE_ID_TEMASH__983b 0x983b // FT3 socket, #define DEVICE_ID_TEMASH__983c 0x983c // FT3 socket, #define DEVICE_ID_TEMASH__983d 0x983d // FT3 socket, #define DEVICE_ID_TEMASH__983e 0x983e // FT3 socket, #define DEVICE_ID_TEMASH__983f 0x983f // FT3 socket, // // Define Chip ID's for Bhavani Desktop // PLEASE DO NOT USE THESE DID! BV DOESN'T SUPPORT THEM! // #define DEVICE_ID_BHAVANI__98b0 0x98b0 // OBSOLETE - don't use #define DEVICE_ID_BHAVANI__98b1 0x98b1 // OBSOLETE - don't use // Define AMD's internal revision numbers. #define INTERNAL_REV_KALINDI_A0 0x00 // The First revision of KALINDI GFX. #define INTERNAL_REV_KALINDI_A1 0x01 // The Second revision of KALINDI GFX. #define INTERNAL_REV_KALINDI_A2 0x02 // GF version of KALINDI GFX which is BHAVANI. // Define AMD's external revision numbers. #define EXTERNAL_REV_KALINDI 0x00 // // Define Chip ID's for Godavari // // Mobile #define DEVICE_ID_GODAVARI__9850 0x9850 // FT3 socket, #define DEVICE_ID_GODAVARI__9851 0x9851 // FT3 socket, #define DEVICE_ID_GODAVARI__9852 0x9852 // FT3 socket, #define DEVICE_ID_GODAVARI__9853 0x9853 // FT3 socket, #define DEVICE_ID_GODAVARI__9854 0x9854 // FT3 socket, #define DEVICE_ID_GODAVARI__9855 0x9855 // FT3 socket, #define DEVICE_ID_GODAVARI__9856 0x9856 // FT3 socket, #define DEVICE_ID_GODAVARI__9857 0x9857 // FT3 socket, #define DEVICE_ID_GODAVARI__9858 0x9858 // FT3 socket, #define DEVICE_ID_GODAVARI__9859 0x9859 // FT3 socket, #define DEVICE_ID_GODAVARI__985a 0x985a // FT3 socket, #define DEVICE_ID_GODAVARI__985b 0x985b // FT3 socket, #define DEVICE_ID_GODAVARI__985c 0x985c // FT3 socket, #define DEVICE_ID_GODAVARI__985d 0x985d // FT3 socket, #define DEVICE_ID_GODAVARI__985e 0x985e // FT3 socket, #define DEVICE_ID_GODAVARI__985f 0x985f // FT3 socket, // Define AMD's internal revision numbers. #define INTERNAL_REV_GODAVARI_A0 0x00 // The First revision of GODAVARI GFX. #define INTERNAL_REV_GODAVARI_A1 0x01 // The Second revision of GODAVARI GFX. // Define AMD's external revision numbers. #define EXTERNAL_REV_GODAVARI 0x00 // This macro will be remove later on (keep it for now for for capability purpose) #define ASICREV_IS_GODAVARI(eChipRev) ((eChipRev >= ML_GODAVARI_A0) && (eChipRev < KV_UNKNOWN)) // identify all versions of KALINDI and supported features set #endif // KV_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/northernisland_id.h ================================================ //===================================================================== // Copyright 2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //=====================================================================/*****************************************************************************\ * * Module Name northernisland_id.h * Project NORTHERNISLANDS * Devices NORTHERNISLANDS * * Description Defining Device IDs, ASIC revision IDs for NORTHERNISLANDS * * * (c) 2009 Advanced Micro Devices, Inc. (unpublished) * * All rights reserved. This notice is intended as a precaution against * inadvertent publication and does not imply publication or any waiver * of confidentiality. The year included in the foregoing notice is the * year of creation of the work. * * LOG OF CHANGES * \*****************************************************************************/ #ifndef _NORTHERNISLAND_ID_H #define _NORTHERNISLAND_ID_H enum { NI_CAYMAN_P_A11 = 1, NI_BARTS_PM_A11 = 20, NI_TURKS_M_A11 = 40, NI_TURKS_LOMBOK_M_A11 = 50, NI_CAICOS_V_A11 = 60, NI_CAICOS_V_A12 = 61, KAUAI_A11 = 80, // not a production part NORTHERNISLAND_UNKNOWN = 0xFF }; #define ASICREV_IS_CAYMAN_P(eChipRev) (eChipRev < NI_BARTS_PM_A11) #define ASICREV_IS_BARTS_PM(eChipRev) ((eChipRev >= NI_BARTS_PM_A11) && (eChipRev < NI_TURKS_M_A11)) #define ASICREV_IS_TURKS_M(eChipRev) ((eChipRev >= NI_TURKS_M_A11) && (eChipRev < NI_CAICOS_V_A11)) #define ASICREV_IS_TURKS_LOMBOK_M(eChipRev) ((eChipRev >= NI_TURKS_LOMBOK_M_A11) && (eChipRev < NI_CAICOS_V_A11)) // this change is intentional. ASICREV_IS_TURKS_LOMBOK_M is a subset of ASICREV_IS_TURKS_M #define ASICREV_IS_CAICOS_V(eChipRev) ((eChipRev >= NI_CAICOS_V_A11) && (eChipRev < KAUAI_A11)) #define ASICREV_IS_KAUAI(eChipRev) (eChipRev >= KAUAI_A11) // // CAYMAN/GRANVILLE ISLAND device IDs // #define DEVICE_ID_NI_CAYMAN_P_6700 0x6700 //Cayman GL XT (Cliffhanger) #define DEVICE_ID_NI_CAYMAN_P_6701 0x6701 //Cayman GL XT (Moonracer) #define DEVICE_ID_NI_CAYMAN_P_6702 0x6702 //Cayman GL XT (Spellbreaker) #define DEVICE_ID_NI_CAYMAN_P_6703 0x6703 //Cayman GL XT #define DEVICE_ID_NI_CAYMAN_P_6704 0x6704 //Cayman GL PRO (Starsaber) #define DEVICE_ID_NI_CAYMAN_P_6705 0x6705 //Cayman GL PRO #define DEVICE_ID_NI_CAYMAN_P_6706 0x6706 //Cayman GL (Doubleheader) #define DEVICE_ID_NI_CAYMAN_P_6707 0x6707 //Cayman GL LE (Jetstorm) #define DEVICE_ID_NI_CAYMAN_P_6708 0x6708 //Cayman GL #define DEVICE_ID_NI_CAYMAN_P_6709 0x6709 //Cayman GL #define DEVICE_ID_NI_CAYMAN_P_6718 0x6718 //Cayman XT #define DEVICE_ID_NI_CAYMAN_P_6719 0x6719 //Cayman Pro #define DEVICE_ID_NI_CAYMAN_P_671C 0x671C //Antilles Pro #define DEVICE_ID_NI_CAYMAN_P_671D 0x671D //Antilles XT #define DEVICE_ID_NI_CAYMAN_P_671F 0x671F //Cayman CE // CAYMAN ASIC internal revision number #define INTERNAL_REV_NI_CAYMAN_P_A11 0x00 // First spin of Cayman #define DEVICE_ID_CAYMAN_PALLADIUM 0x0031 // Palladium ID #define DEVICE_ID_CAYMAN_LITE_PALLADIUM 0x0032 // Palladium ID // // BARTS/BLACKCOMB device IDs // #define DEVICE_ID_NI_BARTS_PM_6722 0x6722 //Barts GL2 #define DEVICE_ID_NI_BARTS_PM_6723 0x6723 //Barts GL3 #define DEVICE_ID_NI_BARTS_PM_6726 0x6726 //Barts GL6 #define DEVICE_ID_NI_BARTS_PM_6727 0x6727 //Barts GL7 #define DEVICE_ID_NI_BARTS_PM_6728 0x6728 //Barts GL XT #define DEVICE_ID_NI_BARTS_PM_6729 0x6729 //Barts GL PRO #define DEVICE_ID_NI_BARTS_PM_6738 0x6738 //Barts XT #define DEVICE_ID_NI_BARTS_PM_6739 0x6739 //Barts PRO #define DEVICE_ID_NI_BARTS_PM_673E 0x673E //Barts LE #define DEVICE_ID_NI_BARTS_PM_6720 0x6720 //Blackcomb XT/PRO and GL XT/PRO #define DEVICE_ID_NI_BARTS_PM_6721 0x6721 //Blackcomb LP and GL LP #define DEVICE_ID_NI_BARTS_PM_6724 0x6724 //Blackcomb XT/PRO Gemini and XT GL/PRO Gemini #define DEVICE_ID_NI_BARTS_PM_6725 0x6725 //Blackcomb LP Gemini and GL LP Gemini #define DEVICE_ID_NI_BARTS_PM_6730 0x6730 //Victoria - Blackcomb for desktop all-in-one // BARTS ASIC internal revision number #define INTERNAL_REV_NI_BARTS_PM_A11 0x00 // First spin of Barts // // TURKS/WHISTLER device IDs // #define DEVICE_ID_NI_TURKS_M_6746 0x6746 // Turks GL6 #define DEVICE_ID_NI_TURKS_M_6747 0x6747 // Turks GL7 #define DEVICE_ID_NI_TURKS_M_6748 0x6748 // Turks GL8 #define DEVICE_ID_NI_TURKS_M_6749 0x6749 // Turks GL9 #define DEVICE_ID_NI_TURKS_M_674A 0x674A // Turks GL #define DEVICE_ID_NI_TURKS_M_6750 0x6750 // Onega #define DEVICE_ID_NI_TURKS_M_6751 0x6751 // Onega2 #define DEVICE_ID_NI_TURKS_M_6758 0x6758 // Turks XT #define DEVICE_ID_NI_TURKS_M_6759 0x6759 // Turks Pro #define DEVICE_ID_NI_TURKS_M_675B 0x675B // Turks XT2 #define DEVICE_ID_NI_TURKS_M_675D 0x675D // Turks Pro2 #define DEVICE_ID_NI_TURKS_M_675F 0x675F // Turks LE #define DEVICE_ID_NI_TURKS_M_6740 0x6740 // Whistler XT/GL XT #define DEVICE_ID_NI_TURKS_M_6741 0x6741 // Whistler Pro/LP/GL Pro/GL LP #define DEVICE_ID_NI_TURKS_M_6742 0x6742 // Whistler LE #define DEVICE_ID_NI_TURKS_M_6743 0x6743 // WhistlerCSP Pro #define DEVICE_ID_NI_TURKS_M_6744 0x6744 // Whistler XT/PRO Gemini and GL XT/PRO Gemini #define DEVICE_ID_NI_TURKS_M_6745 0x6745 // Whistler LP 256 G5 #define DEVICE_ID_NI_TURKS_M_6843 0x6843 // Whistler XTX // TURKS ASIC internal revision number #define INTERNAL_REV_NI_TURKS_M_A11 0x00 // First spin of Turks // // LOMBOK/THAMES MOBILE device IDs // #define DEVICE_ID_NI_LOMBOK_M_6849 0x6849 // Lombok XT GL #define DEVICE_ID_NI_LOMBOK_M_6850 0x6850 // Lombok AIO #define DEVICE_ID_NI_LOMBOK_M_6858 0x6858 // Lombok XT #define DEVICE_ID_NI_LOMBOK_M_6859 0x6859 // Lombok Pro #define DEVICE_ID_NI_LOMBOK_M_6840 0x6840 // Thames XT/GL #define DEVICE_ID_NI_LOMBOK_M_6841 0x6841 // Thames Pro #define DEVICE_ID_NI_LOMBOK_M_6842 0x6842 // Thames LE // Lombok ASIC internal revision number #define INTERNAL_REV_NI_LOMBOK_M_A11 0x00 // First spin of Lombok // // CAICOS/SEYMOUR device IDs // #define DEVICE_ID_NI_CAICOS_V_6762 0x6762 // Caicos GL2 #define DEVICE_ID_NI_CAICOS_V_6763 0x6763 // Caicos CSP512 G5 #define DEVICE_ID_NI_CAICOS_V_6766 0x6766 // Caicos GL6 #define DEVICE_ID_NI_CAICOS_V_6767 0x6767 // Caicos GL7 #define DEVICE_ID_NI_CAICOS_V_6768 0x6768 // Caicos GL PRO #define DEVICE_ID_NI_CAICOS_V_6770 0x6770 // Caspian PRO (Caicos AiO) #define DEVICE_ID_NI_CAICOS_V_6771 0x6771 // Caicos XTX #define DEVICE_ID_NI_CAICOS_V_6772 0x6772 // Caspian PRO2 (Caicos AiO) #define DEVICE_ID_NI_CAICOS_V_6778 0x6778 // Caicos XT #define DEVICE_ID_NI_CAICOS_V_6779 0x6779 // Caicos PRO #define DEVICE_ID_NI_CAICOS_V_677B 0x677B // Caicos PRO2 #define DEVICE_ID_NI_CAICOS_V_6760 0x6760 // Seymour XT/PRO and XT/PRO GL #define DEVICE_ID_NI_CAICOS_V_6761 0x6761 // Seymour LP and LP GL #define DEVICE_ID_NI_CAICOS_V_6764 0x6764 // Seymour XT/PRO GL and GL XT/PRO Gemini #define DEVICE_ID_NI_CAICOS_V_6765 0x6765 // Seymour LP and GL LP Gemini // CAICOS ASIC internal revision number #define INTERNAL_REV_NI_CAICOS_V_A11 0x00 // First spin of Caicos #define INTERNAL_REV_NI_CAICOS_V_A12 0x01 // A12 spin of Caicos #define DEVICE_ID_CAICOS_PALLADIUM 0x0030 // Palladium ID // // KAUAI device IDs - Kauai is not a production part. // #define DEVICE_ID_KAUAI_PALLADIUM 0x0018 // Palladium ID // KAUAI ASIC internal revision number #define INTERNAL_REV_KAUAI_A11 0x00 // First spin of KAUAI // The follow definitions are defined for backward compatibility // when the new naming convention is followed. // Please use the new names instead of these #define CAYMAN_A11 NI_CAYMAN_P_A11 #define BARTS_A11 NI_BARTS_PM_A11 #define TURKS_A11 NI_TURKS_M_A11 #define CAICOS_A11 NI_CAICOS_V_A11 #define ASICREV_IS_CAYMAN(eChipRev) ASICREV_IS_CAYMAN_P(eChipRev) #define ASICREV_IS_BARTS(eChipRev) ASICREV_IS_BARTS_PM(eChipRev) #define ASICREV_IS_TURKS(eChipRev) ASICREV_IS_TURKS_M(eChipRev) #define ASICREV_IS_CAICOS(eChipRev) ASICREV_IS_CAICOS_V(eChipRev) #define INTERNAL_REV_CAYMAN_A11 INTERNAL_REV_NI_CAYMAN_P_A11 #define INTERNAL_REV_BARTS_A11 INTERNAL_REV_NI_BARTS_PM_A11 #define INTERNAL_REV_TURKS_A11 INTERNAL_REV_NI_TURKS_M_A11 #define INTERNAL_REV_CAICOS_A11 INTERNAL_REV_NI_CAICOS_V_A11 #define DEVICE_ID_CAICOS_6768 DEVICE_ID_NI_CAICOS_V_6768 #define DEVICE_ID_CAICOS_6770 DEVICE_ID_NI_CAICOS_V_6770 #define DEVICE_ID_CAICOS_6779 DEVICE_ID_NI_CAICOS_V_6779 #define DEVICE_ID_CAICOS_6760 DEVICE_ID_NI_CAICOS_V_6760 #define DEVICE_ID_CAICOS_6761 DEVICE_ID_NI_CAICOS_V_6761 // the below definitions are obsolete and will be removed at appropriate time. // Please don't use them. #define IBIZA_A11 NI_CAYMAN_P_A11 #define COZUMEL_A11 NI_BARTS_PM_A11 #define ASICREV_IS_IBIZA(eChipRev) (eChipRev < NI_BARTS_PM_A11) #define ASICREV_IS_COZUMEL(eChipRev) ((eChipRev >= NI_BARTS_PM_A11) && (eChipRev < NI_TURKS_M_A11)) // // IBIZA/IBIZA mobile device IDs // #define DEVICE_ID_IBIZA_PALLADIUM 0x0016 // Palladium ID #define DEVICE_ID_IBIZA_LITE_PALLADIUM 0x0020 // Palladium ID // IBIZA ASIC internal revision number #define INTERNAL_REV_IBIZA_A11 0x00 // First spin of IBIZA // // COZUMEL/COZUMEL mobile device IDs // #define DEVICE_ID_COZUMEL_PALLADIUM 0x0017 // Palladium ID // COZUMEL ASIC internal revision number #define INTERNAL_REV_COZUMEL_A11 0x00 // First spin of COZUMEL #endif // _NORTHERNISLAND_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/si_id.h ================================================ //===================================================================== // Copyright 2009-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //===================================================================== /*****************************************************************************\ * * Module Name si_id.h * Project SOUTHERN ISLANDS * Devices SOUTHERN ISLANDS * * Description Defining Device IDs, ASIC revision IDs for SOUTHERN ISLANDS * \*****************************************************************************/ #ifndef _SI_ID_H #define _SI_ID_H enum { SI_TAHITI_P_A11 = 1, SI_TAHITI_P_A0 = SI_TAHITI_P_A11, //A0 is alias of A11 SI_TAHITI_P_A21 = 5, SI_TAHITI_P_B0 = SI_TAHITI_P_A21, //B0 is alias of A21 SI_TAHITI_P_A22 = 6, SI_TAHITI_P_B1 = SI_TAHITI_P_A22, //B1 is alias of A22 SI_PITCAIRN_PM_A11 = 20, SI_PITCAIRN_PM_A0 = SI_PITCAIRN_PM_A11, //A0 is alias of A11 SI_PITCAIRN_PM_A12 = 21, SI_PITCAIRN_PM_A1 = SI_PITCAIRN_PM_A12, //A1 is alias of A12 SI_CAPEVERDE_M_A11 = 40, SI_CAPEVERDE_M_A0 = SI_CAPEVERDE_M_A11, //A0 is alias of A11 SI_CAPEVERDE_M_A12 = 41, SI_CAPEVERDE_M_A1 = SI_CAPEVERDE_M_A12, //A1 is alias of A12 SI_OLAND_M_A0 = 60, SI_HAINAN_V_A0 = 70, SI_UNKNOWN = 0xFF }; #define ASICREV_IS_TAHITI_P(eChipRev) (eChipRev < SI_PITCAIRN_PM_A11) #define ASICREV_IS_PITCAIRN_PM(eChipRev) ((eChipRev >= SI_PITCAIRN_PM_A11) && (eChipRev < SI_CAPEVERDE_M_A11)) #define ASICREV_IS_CAPEVERDE_M(eChipRev) ((eChipRev >= SI_CAPEVERDE_M_A11) && (eChipRev < SI_OLAND_M_A0)) #define ASICREV_IS_OLAND_M(eChipRev) ((eChipRev >= SI_OLAND_M_A0) && (eChipRev < SI_HAINAN_V_A0)) #define ASICREV_IS_HAINAN_V(eChipRev) (eChipRev >= SI_HAINAN_V_A0) // // TAHITI ISLAND device IDs (Performance segment) // #define DEVICE_ID_SI_TAHITI_P_6780 0x6780 //Tahiti XT GL #define DEVICE_ID_SI_TAHITI_P_6784 0x6784 //obsolete #define DEVICE_ID_SI_TAHITI_P_6788 0x6788 //Tahiti XT GL (FirePro) #define DEVICE_ID_SI_TAHITI_P_678A 0x678A //Tahiti PRO GL #define DEVICE_ID_SI_TAHITI_P_6790 0x6790 //Aruba XT #define DEVICE_ID_SI_TAHITI_P_6791 0x6791 //Malta #define DEVICE_ID_SI_TAHITI_P_6792 0x6792 //Aruba PRO #define DEVICE_ID_SI_TAHITI_P_6798 0x6798 //Tahiti XT #define DEVICE_ID_SI_TAHITI_P_6799 0x6799 //New Zeland #define DEVICE_ID_SI_TAHITI_P_679A 0x679A //Tahiti PRO #define DEVICE_ID_SI_TAHITI_P_679B 0x679B //Malta #define DEVICE_ID_SI_TAHITI_P_679E 0x679E //Tahiti LE #define DEVICE_ID_SI_TAHITI_P_679F 0x679F //Aruba Pro // TAHITI ASIC internal revision number #define INTERNAL_REV_SI_TAHITI_P_A11 0x00 // First spin of Tahiti #define INTERNAL_REV_SI_TAHITI_P_A0 INTERNAL_REV_SI_TAHITI_P_A11 #define INTERNAL_REV_SI_TAHITI_P_A21 0x01 // Second spin of Tahiti #define INTERNAL_REV_SI_TAHITI_P_B0 INTERNAL_REV_SI_TAHITI_P_A21 #define INTERNAL_REV_SI_TAHITI_P_A22 0x02 // Third spin of Tahiti #define INTERNAL_REV_SI_TAHITI_P_B1 INTERNAL_REV_SI_TAHITI_P_A22 #define DEVICE_ID_SI_TAHITI_P_LITE_PALLADIUM 0x0022 // Palladium ID // // PITCAIRN/WIMBLEDON device IDs (Performance to Mainstream segment) // #define DEVICE_ID_SI_PITCAIRN_PM_6808 0x6808 //Pitcairn GL1 #define DEVICE_ID_SI_PITCAIRN_PM_6809 0x6809 //Pitcairn GL2 #define DEVICE_ID_SI_PITCAIRN_PM_6810 0x6810 //Curacao XT; Trinidad XT #define DEVICE_ID_SI_PITCAIRN_PM_6811 0x6811 //Curacao Pro; Trinidad Pro #define DEVICE_ID_SI_PITCAIRN_PM_6816 0x6816 //Curacao XT #define DEVICE_ID_SI_PITCAIRN_PM_6817 0x6817 //Curacao PRO #define DEVICE_ID_SI_PITCAIRN_PM_6818 0x6818 //Pitcairn XT #define DEVICE_ID_SI_PITCAIRN_PM_6819 0x6819 //Pitcairn PRO #define DEVICE_ID_SI_PITCAIRN_PM_684C 0x684C //Pitcairn GL #define DEVICE_ID_SI_PITCAIRN_PM_6800 0x6800 //Wimbledon XT #define DEVICE_ID_SI_PITCAIRN_PM_6801 0x6801 //Wimbledon PRO/LP #define DEVICE_ID_SI_PITCAIRN_PM_6802 0x6802 //Wimbledon GL #define DEVICE_ID_SI_PITCAIRN_PM_6806 0x6806 //Neptune XT // TRINIDAD PCI Reivsion IDs #define PRID_SI_PITCAIRN_TRINIDAD_81 0x81 // 0x6810: Trinidad XT; 0x6811: Trinidad Pro #define ASICDID_IS_NEPTUNE(wDID) ((wDID == DEVICE_ID_SI_PITCAIRN_PM_6806)) #define ASICID_IS_TRINIDAD(wDID, bRID) ((bRID == PRID_SI_PITCAIRN_TRINIDAD_81) && \ ((wDID == DEVICE_ID_SI_PITCAIRN_PM_6810) || (wDID == DEVICE_ID_SI_PITCAIRN_PM_6811))) // PITCAIRN ASIC internal revision number #define INTERNAL_REV_SI_PITCAIRN_PM_A11 0x00 // First spin of Pitcairn #define INTERNAL_REV_SI_PITCAIRN_PM_A0 INTERNAL_REV_SI_PITCAIRN_PM_A11 #define INTERNAL_REV_SI_PITCAIRN_PM_A12 0x01 // Second spin of Pitcairn #define INTERNAL_REV_SI_PITCAIRN_PM_A1 INTERNAL_REV_SI_PITCAIRN_PM_A12 // // CAPE VERDE/HEATHROW/CHELSEA/VENUS/TROPO device IDs (Mainstream segment) // #define DEVICE_ID_SI_CAPEVERDE_M_6828 0x6828 //Cape Verde GL XT #define DEVICE_ID_SI_CAPEVERDE_M_6829 0x6829 //unused #define DEVICE_ID_SI_CAPEVERDE_M_682C 0x682C //Cape Verde GL PRO #define DEVICE_ID_SI_CAPEVERDE_M_6830 0x6830 //Summer Palace XT AIO #define DEVICE_ID_SI_CAPEVERDE_M_6831 0x6831 //AIO Great Wall XT #define DEVICE_ID_SI_CAPEVERDE_M_6835 0x6835 //Cape Verde PRX #define DEVICE_ID_SI_CAPEVERDE_M_6837 0x6837 //Cape Verde LE #define DEVICE_ID_SI_CAPEVERDE_M_6838 0x6838 //Cape Verde XTX #define DEVICE_ID_SI_CAPEVERDE_M_6839 0x6839 //Cape Verde XT #define DEVICE_ID_SI_CAPEVERDE_M_683B 0x683B //Cape Verde PRO #define DEVICE_ID_SI_CAPEVERDE_M_683D 0x683D //Cape Verde XT #define DEVICE_ID_SI_CAPEVERDE_M_683F 0x683F //Cape Verde PRO #define DEVICE_ID_SI_CAPEVERDE_M_6820 0x6820 //Venus XTX; Tropo XTX/XT #define DEVICE_ID_SI_CAPEVERDE_M_6821 0x6821 //Venus XT; Tropo PRO #define DEVICE_ID_SI_CAPEVERDE_M_6822 0x6822 //Venus Pro MCM #define DEVICE_ID_SI_CAPEVERDE_M_6823 0x6823 //Venus PRO; Tropo UL #define DEVICE_ID_SI_CAPEVERDE_M_6824 0x6824 //Chelsea PROA #define DEVICE_ID_SI_CAPEVERDE_M_6825 0x6825 //Heathrow XT #define DEVICE_ID_SI_CAPEVERDE_M_6826 0x6826 //Chelsea LP #define DEVICE_ID_SI_CAPEVERDE_M_6827 0x6827 //Heathrow PRO #define DEVICE_ID_SI_CAPEVERDE_M_682A 0x682A //Venus Pro MCM #define DEVICE_ID_SI_CAPEVERDE_M_682B 0x682B //Venus LE; Tropo PROL #define DEVICE_ID_SI_CAPEVERDE_M_682D 0x682D //Chelsea XT #define DEVICE_ID_SI_CAPEVERDE_M_682F 0x682F //Chelsea PRO // TROPO PCI Reivsion IDs #define PRID_SI_CAPEVERDE_TROPO_81 0x81 // 0x6820: Tropo XTX #define PRID_SI_CAPEVERDE_TROPO_83 0x83 // 0x6820: Tropo XT; 0x6821: Tropo PRO; 0x6823: Tropo UL; 0x682B: Tropo PROL #define ASICDID_IS_VENUS(wDID) ((wDID == DEVICE_ID_SI_CAPEVERDE_M_6820) || \ (wDID == DEVICE_ID_SI_CAPEVERDE_M_6821) || \ (wDID == DEVICE_ID_SI_CAPEVERDE_M_6822) || \ (wDID == DEVICE_ID_SI_CAPEVERDE_M_6823) || \ (wDID == DEVICE_ID_SI_CAPEVERDE_M_682A) || \ (wDID == DEVICE_ID_SI_CAPEVERDE_M_682B)) #define ASICID_IS_TROPO(wDID, bRID) (((wDID == DEVICE_ID_SI_CAPEVERDE_M_6820) && ((bRID == PRID_SI_CAPEVERDE_TROPO_81) || (bRID == PRID_SI_CAPEVERDE_TROPO_83))) || \ (((wDID == DEVICE_ID_SI_CAPEVERDE_M_6821) || (wDID == DEVICE_ID_SI_CAPEVERDE_M_6823) || (wDID == DEVICE_ID_SI_CAPEVERDE_M_682B)) && (bRID == PRID_SI_CAPEVERDE_TROPO_83))) // CAPE VERDE ASIC internal revision number #define INTERNAL_REV_SI_CAPEVERDE_M_A11 0x00 // First spin of Cape Verde #define INTERNAL_REV_SI_CAPEVERDE_M_A0 INTERNAL_REV_SI_CAPEVERDE_M_A11 #define INTERNAL_REV_SI_CAPEVERDE_M_A12 0x01 // Second spin of Cape Verde #define INTERNAL_REV_SI_CAPEVERDE_M_A1 INTERNAL_REV_SI_CAPEVERDE_M_A12 #define DEVICE_ID_SI_CAPEVERDE_M_LITE_PALLADIUM 0x0026 // Palladium ID // // OLAND/MARS/OPAL/LITHO device IDs // #define DEVICE_ID_SI_OLAND_M_6608 0x6608 // Oland PRO GL #define DEVICE_ID_SI_OLAND_M_6610 0x6610 // Oland 128 XT #define DEVICE_ID_SI_OLAND_M_6611 0x6611 // Oland 128 PRO (6CU) #define DEVICE_ID_SI_OLAND_M_6613 0x6613 // Oland 128 PRO (5CU) #define DEVICE_ID_SI_OLAND_M_6631 0x6631 // Oland 64 LE #define DEVICE_ID_SI_OLAND_M_6600 0x6600 // Mars 128/64 XT; Litho XT #define DEVICE_ID_SI_OLAND_M_6601 0x6601 // Mars 128/64 PRO, Mars 128 LP #define DEVICE_ID_SI_OLAND_M_6602 0x6602 // Mars 128 XTX #define DEVICE_ID_SI_OLAND_M_6603 0x6603 // obsolete #define DEVICE_ID_SI_OLAND_M_6604 0x6604 // Opal 128 XT; Litho Pro #define DEVICE_ID_SI_OLAND_M_6605 0x6605 // Opal 128 PRO; Litho UL #define DEVICE_ID_SI_OLAND_M_6606 0x6606 // Mars 128 XTX (Generic) #define DEVICE_ID_SI_OLAND_M_6607 0x6607 // Mars LE #define DEVICE_ID_SI_OLAND_M_6620 0x6620 // obsolete #define DEVICE_ID_SI_OLAND_M_6621 0x6621 // Mars 64 PRO #define DEVICE_ID_SI_OLAND_M_6623 0x6623 // Mars 64 LE // LITHO PCI Reivsion IDs #define PRID_SI_OLAND_LITHO_80 0x80 // #define PRID_SI_OLAND_LITHO_81 0x81 // 0x6600: Litho XT; 0x6604: Litho Pro; 0x6605: Litho UL #define ASICDID_IS_MARS(wDID) ((wDID == DEVICE_ID_SI_OLAND_M_6600) || \ (wDID == DEVICE_ID_SI_OLAND_M_6601) || \ (wDID == DEVICE_ID_SI_OLAND_M_6602) || \ (wDID == DEVICE_ID_SI_OLAND_M_6606) || \ (wDID == DEVICE_ID_SI_OLAND_M_6607) || \ (wDID == DEVICE_ID_SI_OLAND_M_6621) || \ (wDID == DEVICE_ID_SI_OLAND_M_6623)) #define ASICDID_IS_OPAL(wDID) ((wDID == DEVICE_ID_SI_OLAND_M_6604) || \ (wDID == DEVICE_ID_SI_OLAND_M_6605)) #define ASICID_IS_LITHO(wDID, bRID) (((wDID == DEVICE_ID_SI_OLAND_M_6600) || (wDID == DEVICE_ID_SI_OLAND_M_6604) || (wDID == DEVICE_ID_SI_OLAND_M_6605)) && \ (bRID == PRID_SI_OLAND_LITHO_81)) // OLAND ASIC internal revision number #define INTERNAL_REV_SI_OLAND_M_A0 0x00 // First spin of Oland // // HAINAN/SUN/EXO device IDs // #define DEVICE_ID_SI_HAINAN_V_6660 0x6660 //Sun XT; Exo XT/PRO #define DEVICE_ID_SI_HAINAN_V_6663 0x6663 //Sun PRO; Exo ULT #define DEVICE_ID_SI_HAINAN_V_6664 0x6664 //Jet XT #define DEVICE_ID_SI_HAINAN_V_6665 0x6665 //Jet PRO; Exo UL #define DEVICE_ID_SI_HAINAN_V_6667 0x6667 //Jet ULT; Exo ULP #define DEVICE_ID_SI_HAINAN_V_666F 0x666F //Sun LE // EXO PCI Reivsion IDs #define PRID_SI_HAINAN_EXO_81 0x81 // 0x6660: Exo XT #define PRID_SI_HAINAN_EXO_83 0x83 // 0x6660: Exo Pro; 0x6663: Exo ULT; 0x6665: Exo UL; 0x6667: Exo ULP #define ASICDID_IS_JET(wDID) ((wDID == DEVICE_ID_SI_HAINAN_V_6664) || \ (wDID == DEVICE_ID_SI_HAINAN_V_6665) || \ (wDID == DEVICE_ID_SI_HAINAN_V_6667)) #define ASICID_IS_EXO(wDID, bRID) (((wDID == DEVICE_ID_SI_HAINAN_V_6660) && ((bRID == PRID_SI_HAINAN_EXO_81) || (bRID == PRID_SI_HAINAN_EXO_83))) || \ (((wDID == DEVICE_ID_SI_HAINAN_V_6663) || (wDID == DEVICE_ID_SI_HAINAN_V_6665) || (wDID == DEVICE_ID_SI_HAINAN_V_6667)) && (bRID == PRID_SI_HAINAN_EXO_83))) // HAINAN ASIC internal revision number #define INTERNAL_REV_SI_HAINAN_V_A0 0x00 // First spin of Hainan #endif // _SI_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/sumo_id.h ================================================ //===================================================================== // Copyright 2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //=====================================================================/*****************************************************************************\ * * Module Name Sumo_id.h * Project Llano/Ontario definitions (SuperSumo, Sumo , Wrestler) * Device Sumo, Wrestler * * Description Identifier file for SUMO driver * * * (c) 2009 AMD (unpublished) * * All rights reserved. This notice is intended as a precaution against * inadvertent publication and does not imply publication or any waiver * of confidentiality. The year included in the foregoing notice is the * year of creation of the work. * * LOG OF CHANGES * * 1.0 07/09/09 [ilitchma] - initial revision * 1.1 01/20/10 [jamesmar] - add Wrestler ID 0x9802 for Ontario. * \*****************************************************************************/ #ifndef _SUMO_ID_H #define _SUMO_ID_H //SUMO section enum { SUPERSUMO_A0 = 0x01, //Sumo 4-5-5-2 SUPERSUMO_B0 = 0x02, SUMO_A0 = 0x11, //Sumo 4-2-2-1 SUMO_B0 = 0x12, WRESTLER_A0 = 0x21, //Sumo-lite 2-2-2-1 WRESTLER_A1 = 0x22, //Sumo-lite 2-2-2-1 WRESTLER_B0 = 0x23, //Sumo-lite 2-2-2-1 WRESTLER_C0 = 0x24, //Sumo-lite 2-2-2-1 BHEEM_A0 = 0x41, //Sumo-lite 2-2-2-1 SUMO_UNKNOWN = 0xFF }; #define ASICREV_IS_SUPERSUMO(eChipRev) ((eChipRev >= SUPERSUMO_A0) && (eChipRev < SUMO_A0)) #define ASICREV_IS_SUMO(eChipRev) ((eChipRev >= SUMO_A0) && (eChipRev < WRESTLER_A0)) #define ASICREV_IS_WRESTLER(eChipRev) ((eChipRev >= WRESTLER_A0) && (eChipRev < BHEEM_A0)) #define ASICREV_IS_WRESTLER_Cx(eChipRev) ((eChipRev >= WRESTLER_C0) && (eChipRev < BHEEM_A0)) #define ASICREV_IS_BHEEM(eChipRev) ((eChipRev >= BHEEM_A0) && (eChipRev < SUMO_UNKNOWN)) #define ASIC_IS_SSTRIPPED_SUMO(ChipID) ( (ChipID == DEVICE_ID_SUMO_SSTRIPPED_DESKTOP) || \ (ChipID == DEVICE_ID_SUMO_SSTRIPPED_MOBILE) ) #define ASICREV_IS_SUMO_B0_OR_NEWER(eChipRev) ( ((eChipRev & 0x0f) >= SUPERSUMO_B0) && (eChipRev < WRESTLER_A0) ) // Low 4 bits to identify ASIC Rev, // high 4 bits to identify SuperSumo/Sumo/Wrestler. // // Define Chip ID's for SUMO family // #define DEVICE_ID_SUMO_SUPER_DESKTOP 0x9640 //FM1 socket,4-5-5-2 (QP-SIMD-TP-RB) #define DEVICE_ID_SUMO_SUPER_MOBILE 0x9641 //FS1 4-5-5-2 #define DEVICE_ID_SUMO_SSTRIPPED_DESKTOP 0x9642 //FM1 socket,4-2-2-1, Same die as SuperSumo fused to Sumo GFX configuration #define DEVICE_ID_SUMO_SSTRIPPED_MOBILE 0x9643 //FS1 4-2-2-1, Same die as SuperSumo fused to Sumo GFX configuration #define DEVICE_ID_SUMO_DESKTOP 0x9644 //FM1 socket,4-2-2-1 #define DEVICE_ID_SUMO_MOBILE 0x9645 //To be removed later. #define DEVICE_ID_SUMO_DESKTOP_9645 0x9645 //FM1 socket,4-2-2-1 #define DEVICE_ID_SUMO_SUPER_MOBILE_9647 0x9647 //FS1 4-4-4-2 #define DEVICE_ID_SUMO_MOBILE_9648 0x9648 //To be removed later. #define DEVICE_ID_SUMO_SUPER_MOBILE_9648 0x9648 //FS1 4-3-3-2 #define DEVICE_ID_SUMO_MOBILE_9649 0x9649 //FS1 4-2-2-1 #define DEVICE_ID_SUMO_SUPER_DESKTOP_964A 0x964A //FM1 socket,4-4-4-2 (QP-SIMD-TP-RB) #define DEVICE_ID_SUMO_SUPER_MOBILE_964E 0x964E //FP1F 4-5-5-2 #define DEVICE_ID_SUMO_SUPER_MOBILE_964F 0x964F //FP1F 4-5-5-2 #define DEVICE_ID_WRESTLER 0x9802 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_9803 0x9803 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_9804 0x9804 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_9805 0x9805 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_9806 0x9806 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_9807 0x9807 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_9808 0x9808 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_9809 0x9809 //FT1 2-2-2-1 #define DEVICE_ID_WRESTLER_980A 0x980A //FT1 2-2-2-1 #define DEVICE_ID_BHEEM 0x1300 //FT1 2-2-2-1 #define DEVICE_ID_BHEEM_1301 0x1301 //FT1 2-2-2-1 #define DEVICE_ID_BHEEM_1302 0x1302 //FT1 2-2-2-1 // // Define AMD's internal revision numbers. // #define INTERNAL_REV_SUMO_A11 0x00 // The First revision of SUMO ASIC. #define INTERNAL_REV_SUMO_A0 0x00 // The First revision of SUMO ASIC. #define INTERNAL_REV_SUMO_A1 0x01 // The Second revision of SUMO ASIC. #define INTERNAL_REV_SUMO_B0 0x02 // The Third revision of SUMO ASIC. // // Define AMD's external revision numbers. // #define EXTERNAL_REV_SUMO 0x00 // // Define AMD's Wrestler internal revision numbers. // #define INTERNAL_REV_WRESTLER_A0 0x00 // The First revision of Wrestler ASIC. #define INTERNAL_REV_WRESTLER_A1 0x01 // The Second revision of Wrestler ASIC. #define INTERNAL_REV_WRESTLER_B0 0x02 // The Third revision of Wrestler ASIC. #define INTERNAL_REV_WRESTLER_C0 0x03 // The Fourth revision of Wrestler ASIC. // // Define AMD's Wrestler external revision numbers. // #define EXTERNAL_REV_WRESTLER 0x00 // Define AMD's Bheem internal revision numbers. // #define INTERNAL_REV_BHEEM_A0 0x00 // The First revision of Bheem ASIC. // // Define AMD's Bheem external revision numbers. // #define EXTERNAL_REV_BHEEM 0x00 #endif // _SUMO_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/tn_id.h ================================================ //===================================================================== // Copyright 2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //=====================================================================/*****************************************************************************\ * * Module Name tn_id.h * Project Trinity Family * Device Devastator, Scrapper * * Description Identifier file for Trinity driver * * * (c) 2010 AMD (unpublished) * * All rights reserved. This notice is intended as a precaution against * inadvertent publication and does not imply publication or any waiver * of confidentiality. The year included in the foregoing notice is the * year of creation of the work. * * LOG OF CHANGES * * 1.0 10/21/10 [ilitchma] - initial revision * 1.1 02/24/11 [ilitchma] - updated IDs based on marketing request * 1.2 10/01/11 [ilitchma] - Add A1 spin definitions * 1.3 11/10/11 [ilitchma] - Add TN1 production DIDs * 1.4 07/12/12 [rdass] - Add RL (Richland - TN refresh) production DIDs * \*****************************************************************************/ #ifndef TN_ID_H #define TN_ID_H //DEVASTATOR section enum { TN_DEVASTATOR_M_A0 = 0x01, //Devastator 4-6-6-2 TN_DEVASTATOR_M_A1 = 0x02, //Devastator 4-6-6-2 TN_DEVASTATOR_W_A0 = 0x11, //Devastator Workstation 4-6-6-2 TN_DEVASTATOR_W_A1 = 0x12, //Devastator Workstation 4-6-6-2 TN_DEVASTATOR_LITE_MV_A0 = 0x21, //Devastator Lite 4-4-4-2 TN_DEVASTATOR_LITE_MV_A1 = 0x22, //Devastator Lite 4-4-4-2 TN_DEVASTATOR_V_A0 = 0x41, //Devastator 4-6-6-2 downconfigured to 4-3-3-1 same as scrapper TN_DEVASTATOR_V_A1 = 0x42, //Devastator 4-6-6-2 downconfigured to 4-3-3-1 same as scrapper //DEVASTATOR_V IDs are depricated do not use TN_SCRAPPER_V_A0 = 0x41, //Scrapper 4-3-3-1 TN_SCRAPPER_V_A1 = 0x42, //Scrapper 4-3-3-1 TN_DVST_DUO_V_A0 = 0x61, //Scrapper 4-2-2-1 TN_SCRAPPER_LV_A0 = 0x61, //Scrapper Lite 4-2-2-1 TN_SCRAPPER_LV_A1 = 0x62, //Scrapper Lite 4-2-2-1 TN_UNKNOWN = 0xFF }; #define ASICREV_IS_DEVASTATOR_M(eChipRev) ((eChipRev >= TN_DEVASTATOR_M_A0) && (eChipRev < TN_DEVASTATOR_LITE_MV_A0)) //ASICREV_IS_DEVASTATOR_M should be used to identify DEVASTATOR full version features and configuration #define ASICREV_IS_DEVASTATOR_W(eChipRev) ((eChipRev >= TN_DEVASTATOR_W_A0) && (eChipRev < TN_DEVASTATOR_LITE_MV_A0)) //ASICREV_IS_DEVASTATOR_W should be used to identify DEVASTATOR Workstation version features and configuration #define ASICREV_IS_DEVASTATOR_M_MV(eChipRev) ((eChipRev >= TN_DEVASTATOR_M_A0) && (eChipRev < TN_DEVASTATOR_V_A0)) //ASICREV_IS_DEVASTATOR_M_MV should be used to identify DEVASTATOR 4-6-2 + 4-4-2 features and configuration #define ASICREV_IS_DEVASTATOR_LITE_MV(eChipRev) ((eChipRev >= TN_DEVASTATOR_LITE_MV_A0) && (eChipRev < TN_DEVASTATOR_V_A0)) //TN_DEVASTATOR_LITE_MV should be used to identify DEVASTATOR LITE features and configuration #define ASICREV_IS_DEVASTATOR(eChipRev) ((eChipRev >= TN_DEVASTATOR_M_A0) && (eChipRev < TN_SCRAPPER_V_A0)) //ASICREV_IS_DEVASTATOR used to identify silicon type including downconfigured parts //DEVASTATOR_V IDs are depricated do not use #define ASICREV_IS_DEVASTATOR_V(eChipRev) ((eChipRev >= TN_DEVASTATOR_V_A0) && (eChipRev < TN_SCRAPPER_V_A0)) //ASICREV_IS_DEVASTATOR_V should be used to identify DEVASTATOR downconfigured to Scrapper #define ASICREV_IS_TN_V(eChipRev) ((eChipRev >= TN_DEVASTATOR_V_A0) && (eChipRev < TN_UNKNOWN)) //ASICREV_IS_SCRAPPER_WIDE should be used to identify Scrapper features and configuration #define ASICREV_IS_SCRAPPER(eChipRev) ((eChipRev >= TN_SCRAPPER_V_A0) && (eChipRev < TN_UNKNOWN)) //ASICREV_IS_SCRAPPER should be used to identify Scrapper variant #define ASICREV_IS_SCRAPPER_V(eChipRev) ((eChipRev >= TN_SCRAPPER_V_A0) && (eChipRev < TN_SCRAPPER_LV_A0)) //ASICREV_IS_SCRAPPERV should be used to identify Scrapper 4-3-3-1 variant #define ASICREV_IS_SCRAPPER_LITE_LV(eChipRev) ((eChipRev >= TN_SCRAPPER_LV_A0) && (eChipRev < TN_UNKNOWN)) //ASICREV_IS_SCRAPPER should be used to identify Scrapper Lite 4-2-2-1 variant #define ASIC_IS_TN_A0(eChipRev) ((eChipRev & 0xF) == 0x1) // ASIC is Trinity A0 #define ASIC_IS_TN_A1(eChipRev) ((eChipRev & 0xF) == 0x2) // ASIC is Trinity A1 // // Define Chip ID's for Trinity family // #define DEVICE_ID_DEVASTATOR_MOBILE 0x9900 //FP2,FS1r2 socket,4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_DESKTOP 0x9901 //FM2 socket,4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_LITE_MOBILE 0x9903 //FP2,FS1r2 socket,4-4-4-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_LITE_DESKTOP 0x9904 //FM2 socket,4-4-4-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_WS_9905 0x9905 //Trinity/DVST - workstation FM2 socket,4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_WS_9906 0x9906 //Trinity/DVST - workstation FM2 socket,4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_MOBILE_FP2_9907 0x9907 //Trinity/DVST - mobile FP2 25W, 4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_MOBILE_FP2_9908 0x9908 //Trinity/DVST - mobile FP2 19W, 4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_MOBILE_FP2_9909 0x9909 //Trinity/DVST - mobile FP2 17W, 4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_LITE_MOBILE_FP2_990A 0x990A //FP2 17W, 4-4-4-2 (QP-SIMD-TP-RB) #define DEVICE_ID_RL_DEVASTATOR_MOBILE 0x990B //FP2,FS1r2 socket,4-6-6-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_DEVASTATOR_DESKTOP 0x990C //FM2 socket,4-6-6-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_DEVASTATOR_LITE_MOBILE 0x990D //FP2,FS1r2 socket,4-4-4-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_DEVASTATOR_LITE_DESKTOP 0x990E //FM2 socket,4-4-4-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_DEVASTATOR_MOBILE_FP2_990F 0x990F //FP2 25W, 4-6-6-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_DEVASTATOR_MOBILE_EMBEDDED 0x9910 //FS1r2 socket,4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_LITE_MOBILE_EMBEDDED 0x9913 //FS1r2 socket,4-4-4-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_FP2_EMBEDDED_9917 0x9917 //FP2 25W, 4-6-6-2 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_FP2_EMBEDDED_9918 0x9918 //FP2 19W, 4-6-6-6 (QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_LITE_FP2_EMBEDDED 0x9919 //FP2 17W, 4-4-4-2 (QP-SIMD-TP-RB) #define DEVICE_ID_SCRAPPER_MOBILE 0x9990 //FP2, FS1r2 socket,4-3-3-1(QP-SIMD-TP-RB) #define DEVICE_ID_SCRAPPER_DESKTOP 0x9991 //FM2 socket,4-3-3-1 (QP-SIMD-TP-RB) #define DEVICE_ID_SCRAPPER_LITE_MOBILE 0x9992 //FS1r2 socket,4-2-2-1(QP-SIMD-TP-RB) #define DEVICE_ID_SCRAPPER_LITE_DESKTOP 0x9993 //FM2 socket,4-2-2-1(QP-SIMD-TP-RB) #define DEVICE_ID_SCRAPPER_MOBILE_FP2 0x9994 //FP2, FS1r2 socket,4-3-3-1(QP-SIMD-TP-RB) #define DEVICE_ID_RL_SCRAPPER_MOBILE 0x9995 //FP2, FS1r2 socket,4-3-3-1(QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_SCRAPPER_DESKTOP 0x9996 //FM2 socket,4-3-3-1 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_SCRAPPER_LITE_MOBILE 0x9997 //FS1r2 socket,4-2-2-1(QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_SCRAPPER_LITE_DESKTOP 0x9998 //FM2 socket,4-2-2-1(QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_DEVASTATOR_MOBILE_FP2_9999 0x9999 //FP2 17W, 4-6-6-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_SCRAPPER_MOBILE_FP2_999A 0x999A //FP2 17W, 4-3-3-1 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_SCRAPPER_LITE_MOBILE_FP2_999B 0x999B //FP2 17W, 4-2-2-1 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_DEVASTATOR_DESKTOP_999C 0x999C //FM2 45W,4-6-6-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_RL_DEVASTATOR_LITE_DESKTOP_999D 0x999D //FM2 45W,4-4-4-2 (QP-SIMD-TP-RB) (Richland) #define DEVICE_ID_SCRAPPER_MOBILE_EMBEDDED 0x99A0 //FS1r2 socket,4-3-3-1(QP-SIMD-TP-RB) #define DEVICE_ID_SCRAPPER_LITE_MOBILE_EMBEDDED 0x99A2 //FS1r2 socket,4-2-2-1(QP-SIMD-TP-RB) #define DEVICE_ID_SCRAPPER_FP2_EMBEDDED 0x99A4 //FP2, 4-3-3-1(QP-SIMD-TP-RB) #define DEVICE_ID_DEVASTATOR_DUO 0x990F //FM2,FP2,FS1r2 socket,4-2-2-1 (QP-SIMD-TP-RB) Non production part //DEVASTATOR_DUO is depricated do not use // // Define AMD's internal revision numbers. // #define INTERNAL_REV_DEVASTATOR_A0 0x00 // The First revision of Trinity TN1 GFX. #define INTERNAL_REV_DEVASTATOR_A1 0x01 // The Second revision of Trinity TN1 GFX. #define INTERNAL_REV_SCRAPPER_TN2_A0 0x02 // The First revision of Trinity TN2 GFX. // // Define AMD's external revision numbers. // #define EXTERNAL_REV_DEVASTATOR 0x00 #endif // TN_ID_H ================================================ FILE: src/Wrapper/amd-codexl-analyzer/CommonProjects/AMDTBackend/Include/Common/asic_reg/vi_id.h ================================================ //===================================================================== // Copyright 2012-2016 (c), Advanced Micro Devices, Inc. All rights reserved. // /// \author AMD Developer Tools Team /// \file /// //===================================================================== /*****************************************************************************\ * * Module Name vi_id.h * Project VOLCANIC ISLANDS * Devices VOLCANIC ISLANDS * * Description Defining Device IDs, ASIC revision IDs for VOLCANIC ISLANDS * \*****************************************************************************/ #ifndef _VI_ID_H #define _VI_ID_H enum { VI_ICELAND_M_A0 = 1, VI_TONGA_P_A0 = 20, VI_TONGA_P_A1 = 21, VI_BERMUDA_P_A0 = 40, VI_FIJI_P_A0 = 60, VI_UNKNOWN = 0xFF }; #define ASICREV_IS_ICELAND_M(eChipRev) (eChipRev < VI_TONGA_P_A0) #define ASICREV_IS_TONGA_P(eChipRev) ((eChipRev >= VI_TONGA_P_A0) && (eChipRev < VI_BERMUDA_P_A0)) #define ASICREV_IS_BERMUDA_P(eChipRev) ((eChipRev >= VI_BERMUDA_P_A0) && (eChipRev < VI_FIJI_P_A0)) #define ASICREV_IS_FIJI_P(eChipRev) (eChipRev >= VI_FIJI_P_A0) // // TONGA/AMETHYST device IDs (performance segment) // #define DEVICE_ID_VI_TONGA_P_6920 0x6920 // unfused #define DEVICE_ID_VI_TONGA_P_6921 0x6921 // Amethyst XT #define DEVICE_ID_VI_TONGA_P_6928 0x6928 // Tonga GL XT #define DEVICE_ID_VI_TONGA_P_692B 0x692B // Tonga GL PRO #define DEVICE_ID_VI_TONGA_P_692F 0x692F // Tonga GL PRO VF #define DEVICE_ID_VI_TONGA_P_6938 0x6938 // Tonga XT #define DEVICE_ID_VI_TONGA_P_6939 0x6939 // Tonga PRO #define DEVICE_ID_VI_TONGA_P_PALLADIUM 0x00 // Palladium ID #define DEVICE_ID_VI_TONGA_P_LITE_PALLADIUM 0x48 // Palladium ID // TONGA ASIC internal revision number #define INTERNAL_REV_VI_TONGA_P_A0 0x00 // First spin of Tonga #define INTERNAL_REV_VI_TONGA_P_A1 0x01 // Second spin of Tonga // // ICELAND/TOPAZ/MESO device IDs (mainstream segment) // #define DEVICE_ID_VI_ICELAND_M_6900 0x6900 // Topaz XT; Meso XT #define DEVICE_ID_VI_ICELAND_M_6901 0x6901 // Topaz Pro #define DEVICE_ID_VI_ICELAND_M_6902 0x6902 // Topaz XTL #define DEVICE_ID_VI_ICELAND_M_6903 0x6903 // Unused - Previous Topaz LE #define DEVICE_ID_VI_ICELAND_M_6907 0x6907 // Topaz LE // MESO PCI Reivsion IDs #define PRID_VI_ICELAND_MESO_81 0x81 // 0x6900: MESO XT #define ASICID_IS_MESO(wDID, bRID) ((wDID == DEVICE_ID_VI_ICELAND_M_6900) && (bRID == PRID_VI_ICELAND_MESO_81)) #define DEVICE_ID_VI_ICELAND_M_PALLADIUM 0x47 // Palladium ID #define DEVICE_ID_VI_ICELAND_M_LITE_PALLADIUM 0x00 // Palladium ID // ICELAND ASIC internal revision number #define INTERNAL_REV_VI_ICELAND_M_A0 0x00 // First spin of ICELAND // // Bermuda device IDs (performance segment) // #define DEVICE_ID_VI_BERMUDA_P_PALLADIUM 0x49 // Palladium ID #define DEVICE_ID_VI_BERMUDA_P_LITE_PALLADIUM 0x00 // Palladium ID // BERMUDA ASIC internal revision number #define INTERNAL_REV_VI_BERMUDA_P_A0 0x00 // First spin of Bermuda // // Fiji device IDs (performance segment) // #define DEVICE_ID_VI_FIJI_P_LITE_PALLADIUM 0x4A // Palladium ID // FIJI ASIC internal revision number #define INTERNAL_REV_VI_FIJI_P_A0 0x00 // First spin of Fiji #endif // _VI_ID_H ================================================ FILE: src/Wrapper/dxc/HLSL/DXIL.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DXIL.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Main public header for DXIL. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilConstants.h" #include "dxc/HLSL/DxilShaderModel.h" #include "dxc/HLSL/DxilCompType.h" #include "dxc/HLSL/DxilInterpolationMode.h" #include "dxc/HLSL/DxilSemantic.h" #include "dxc/HLSL/DxilSignatureElement.h" #include "dxc/HLSL/DxilCBuffer.h" #include "dxc/HLSL/DxilResource.h" #include "dxc/HLSL/DxilSampler.h" #include "dxc/HLSL/DxilOperations.h" #include "dxc/HLSL/DxilRootSignature.h" #include "dxc/HLSL/DxilModule.h" ================================================ FILE: src/Wrapper/dxc/HLSL/DxilCBuffer.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilCBuffer.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL constant buffer (cbuffer). // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilResourceBase.h" namespace hlsl { /// Use this class to represent HLSL cbuffer. class DxilCBuffer : public DxilResourceBase { public: DxilCBuffer(); virtual ~DxilCBuffer(); unsigned GetSize() const; void SetSize(unsigned InstanceSizeInBytes); private: unsigned m_SizeInBytes; // Cbuffer instance size in bytes. }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilCompType.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilCompType.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Represenation of HLSL component type. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "DxilConstants.h" namespace llvm { class Type; class PointerType; class LLVMContext; } namespace hlsl { /// Use this class to represent HLSL component/element types. class CompType { public: using Kind = DXIL::ComponentType; CompType(); CompType(Kind K); CompType(unsigned int K); bool operator==(const CompType &o) const; Kind GetKind() const; static CompType getInvalid(); static CompType getF16(); static CompType getF32(); static CompType getF64(); static CompType getI16(); static CompType getI32(); static CompType getI64(); static CompType getU16(); static CompType getU32(); static CompType getU64(); static CompType getI1(); static CompType getSNormF16(); static CompType getUNormF16(); static CompType getSNormF32(); static CompType getUNormF32(); static CompType getSNormF64(); static CompType getUNormF64(); bool IsInvalid() const; bool IsFloatTy() const; bool IsIntTy() const; bool IsSIntTy() const; bool IsUIntTy() const; bool IsBoolTy() const; bool IsSNorm() const; bool IsUNorm() const; bool Is64Bit() const; /// For min-precision types, returns upconverted (base) type. CompType GetBaseCompType() const; bool HasMinPrec() const; llvm::Type *GetLLVMType(llvm::LLVMContext &Ctx) const; llvm::PointerType *GetLLVMPtrType(llvm::LLVMContext &Ctx, const unsigned AddrSpace = 0) const; llvm::Type *GetLLVMBaseType(llvm::LLVMContext &Ctx) const; /// Get the component type for a given llvm type. /// /// LLVM types do not hold sign information so there is no 1-1 /// correspondence between llvm types and component types. /// This method returns the signed version for all integer /// types. /// /// TODO: decide if we should distinguish between signed /// and unsigned types in this api. static CompType GetCompType(llvm::Type * type); const char *GetName() const; const char *GetHLSLName() const; private: Kind m_Kind; }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilConstants.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilConstants.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Essential DXIL constants. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include namespace hlsl { /* import hctdb_instrhelp */ // TODO: // 2. get rid of DXIL namespace. // 3. use class enum for shader flags. // 4. use class enum for address spaces. namespace DXIL { // DXIL version. const unsigned kDxilMajor = 1; const unsigned kDxilMinor = 0; inline unsigned MakeDxilVersion(unsigned DxilMajor, unsigned DxilMinor) { return 0 | (DxilMajor << 8) | (DxilMinor); } inline unsigned GetCurrentDxilVersion() { return MakeDxilVersion(kDxilMajor, kDxilMinor); } inline unsigned GetDxilVersionMajor(unsigned DxilVersion) { return (DxilVersion >> 8) & 0xFF; } inline unsigned GetDxilVersionMinor(unsigned DxilVersion) { return DxilVersion & 0xFF; } // Shader flags. const unsigned kDisableOptimizations = 0x00000001; // D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION const unsigned kDisableMathRefactoring = 0x00000002; //~D3D10_SB_GLOBAL_FLAG_REFACTORING_ALLOWED const unsigned kEnableDoublePrecision = 0x00000004; // D3D11_SB_GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS const unsigned kForceEarlyDepthStencil = 0x00000008; // D3D11_SB_GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL const unsigned kEnableRawAndStructuredBuffers = 0x00000010; // D3D11_SB_GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS const unsigned kEnableMinPrecision = 0x00000020; // D3D11_1_SB_GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION const unsigned kEnableDoubleExtensions = 0x00000040; // D3D11_1_SB_GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS const unsigned kEnableMSAD = 0x00000080; // D3D11_1_SB_GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS const unsigned kAllResourcesBound = 0x00000100; // D3D12_SB_GLOBAL_FLAG_ALL_RESOURCES_BOUND const unsigned kNumOutputStreams = 4; const unsigned kNumClipPlanes = 6; // TODO: move these to appropriate places (ShaderModel.cpp?) const unsigned kMaxTempRegCount = 4096; // DXBC only const unsigned kMaxCBufferSize = 4096; const unsigned kMaxStructBufferStride = 2048; const unsigned kMaxHSOutputControlPointsTotalScalars = 3968; const unsigned kMaxHSOutputPatchConstantTotalScalars = 32*4; const unsigned kMaxOutputTotalScalars = 32*4; const unsigned kMaxInputTotalScalars = 32*4; const unsigned kMaxClipOrCullDistanceElementCount = 2; const unsigned kMaxClipOrCullDistanceCount = 2 * 4; const unsigned kMaxGSOutputVertexCount = 1024; const unsigned kMaxGSInstanceCount = 32; const unsigned kMaxIAPatchControlPointCount = 32; const float kHSMaxTessFactorLowerBound = 1.0f; const float kHSMaxTessFactorUpperBound = 64.0f; const unsigned kMaxCSThreadsPerGroup = 1024; const unsigned kMaxCSThreadGroupX = 1024; const unsigned kMaxCSThreadGroupY = 1024; const unsigned kMaxCSThreadGroupZ = 64; const unsigned kMinCSThreadGroupX = 1; const unsigned kMinCSThreadGroupY = 1; const unsigned kMinCSThreadGroupZ = 1; const unsigned kMaxCS4XThreadsPerGroup = 768; const unsigned kMaxCS4XThreadGroupX = 768; const unsigned kMaxCS4XThreadGroupY = 768; const unsigned kMaxTGSMSize = 8192*4; const unsigned kMaxGSOutputTotalScalars = 1024; const float kMaxMipLodBias = 15.99f; const float kMinMipLodBias = -16.0f; enum class ComponentType : uint8_t { Invalid = 0, I1, I16, U16, I32, U32, I64, U64, F16, F32, F64, SNormF16, UNormF16, SNormF32, UNormF32, SNormF64, UNormF64, LastEntry }; enum class InterpolationMode : uint8_t { Undefined = 0, Constant = 1, Linear = 2, LinearCentroid = 3, LinearNoperspective = 4, LinearNoperspectiveCentroid = 5, LinearSample = 6, LinearNoperspectiveSample = 7, Invalid = 8 }; enum class SignatureKind { Invalid = 0, Input, Output, PatchConstant, }; enum class ShaderKind { Pixel = 0, Vertex, Geometry, Hull, Domain, Compute, Invalid, }; /* hctdb_instrhelp.get_enum_decl("SemanticKind", hide_val=True, sort_val=False)*/ // SemanticKind-ENUM:BEGIN // Semantic kind; Arbitrary or specific system value. enum class SemanticKind : unsigned { Arbitrary, VertexID, InstanceID, Position, RenderTargetArrayIndex, ViewPortArrayIndex, ClipDistance, CullDistance, OutputControlPointID, DomainLocation, PrimitiveID, GSInstanceID, SampleIndex, IsFrontFace, Coverage, InnerCoverage, Target, Depth, DepthLessEqual, DepthGreaterEqual, StencilRef, DispatchThreadID, GroupID, GroupIndex, GroupThreadID, TessFactor, InsideTessFactor, Invalid, }; // SemanticKind-ENUM:END /* hctdb_instrhelp.get_enum_decl("SigPointKind", hide_val=True, sort_val=False)*/ // SigPointKind-ENUM:BEGIN // Signature Point is more specific than shader stage or signature as it is unique in both stage and item dimensionality or frequency. enum class SigPointKind : unsigned { VSIn, // Ordinary Vertex Shader input from Input Assembler VSOut, // Ordinary Vertex Shader output that may feed Rasterizer PCIn, // Patch Constant function non-patch inputs HSIn, // Hull Shader function non-patch inputs HSCPIn, // Hull Shader patch inputs - Control Points HSCPOut, // Hull Shader function output - Control Point PCOut, // Patch Constant function output - Patch Constant data passed to Domain Shader DSIn, // Domain Shader regular input - Patch Constant data plus system values DSCPIn, // Domain Shader patch input - Control Points DSOut, // Domain Shader output - vertex data that may feed Rasterizer GSVIn, // Geometry Shader vertex input - qualified with primitive type GSIn, // Geometry Shader non-vertex inputs (system values) GSOut, // Geometry Shader output - vertex data that may feed Rasterizer PSIn, // Pixel Shader input PSOut, // Pixel Shader output CSIn, // Compute Shader input Invalid, }; // SigPointKind-ENUM:END /* hctdb_instrhelp.get_enum_decl("SemanticInterpretationKind", hide_val=True, sort_val=False)*/ // SemanticInterpretationKind-ENUM:BEGIN // Defines how a semantic is interpreted at a particular SignaturePoint enum class SemanticInterpretationKind : unsigned { NA, // Not Available SV, // Normal System Value SGV, // System Generated Value (sorted last) Arb, // Treated as Arbitrary NotInSig, // Not included in signature (intrinsic access) NotPacked, // Included in signature, but does not contribute to packing Target, // Special handling for SV_Target TessFactor, // Special handling for tessellation factors Shadow, // Shadow element must be added to a signature for compatibility Invalid, }; // SemanticInterpretationKind-ENUM:END /* hctdb_instrhelp.get_enum_decl("PackingKind", hide_val=True, sort_val=False)*/ // PackingKind-ENUM:BEGIN // Kind of signature point enum class PackingKind : unsigned { None, // No packing should be performed InputAssembler, // Vertex Shader input from Input Assembler Vertex, // Vertex that may feed the Rasterizer PatchConstant, // Patch constant signature Target, // Render Target (Pixel Shader Output) Invalid, }; // PackingKind-ENUM:END enum class PackingStrategy : unsigned { Default = 0, // Choose default packing algorithm based on target (currently PrefixStable) PrefixStable, // Maintain assumption that all elements are packed in order and stable as new elements are added. Optimized, // Optimize packing of all elements together (all elements must be present, in the same order, for identical placement of any individual element) Invalid, }; enum class SamplerKind : unsigned { Default = 0, Comparison, Mono, Invalid, }; enum class ResourceClass { SRV = 0, UAV, CBuffer, Sampler, Invalid }; enum class ResourceKind : unsigned { Invalid = 0, Texture1D, Texture2D, Texture2DMS, Texture3D, TextureCube, Texture1DArray, Texture2DArray, Texture2DMSArray, TextureCubeArray, TypedBuffer, RawBuffer, StructuredBuffer, CBuffer, Sampler, TBuffer, NumEntries, }; // TODO: change opcodes. /* hctdb_instrhelp.get_enum_decl("OpCode")*/ // OPCODE-ENUM:BEGIN // Enumeration for operations specified by DXIL enum class OpCode : unsigned { // Binary float FMax = 35, // returns a if a >= b, else b FMin = 36, // returns a if a < b, else b // Binary int with two outputs IMul = 41, // returns the IMul of the input values UDiv = 43, // returns the UDiv of the input values UMul = 42, // returns the UMul of the input values // Binary int IMax = 37, // returns the IMax of the input values IMin = 38, // returns the IMin of the input values UMax = 39, // returns the UMax of the input values UMin = 40, // returns the UMin of the input values // Binary uint with carry or borrow UAddc = 44, // returns the UAddc of the input values USubb = 45, // returns the USubb of the input values // Bitcasts with different sizes BitcastF16toI16 = 125, // bitcast between different sizes BitcastF32toI32 = 127, // bitcast between different sizes BitcastF64toI64 = 129, // bitcast between different sizes BitcastI16toF16 = 124, // bitcast between different sizes BitcastI32toF32 = 126, // bitcast between different sizes BitcastI64toF64 = 128, // bitcast between different sizes // Compute shader FlattenedThreadIdInGroup = 96, // provides a flattened index for a given thread within a given group (SV_GroupIndex) GroupId = 94, // reads the group ID (SV_GroupID) ThreadId = 93, // reads the thread ID ThreadIdInGroup = 95, // reads the thread ID within the group (SV_GroupThreadID) // Domain and hull shader LoadOutputControlPoint = 103, // LoadOutputControlPoint LoadPatchConstant = 104, // LoadPatchConstant // Domain shader DomainLocation = 105, // DomainLocation // Dot Dot2 = 54, // two-dimensional vector dot-product Dot3 = 55, // three-dimensional vector dot-product Dot4 = 56, // four-dimensional vector dot-product // Double precision LegacyDoubleToFloat = 132, // legacy fuction to convert double to float LegacyDoubleToSInt32 = 133, // legacy fuction to convert double to int32 LegacyDoubleToUInt32 = 134, // legacy fuction to convert double to uint32 MakeDouble = 101, // creates a double value SplitDouble = 102, // splits a double into low and high parts // Geometry shader CutStream = 98, // completes the current primitive topology at the specified stream EmitStream = 97, // emits a vertex to a given stream EmitThenCutStream = 99, // equivalent to an EmitStream followed by a CutStream GSInstanceID = 100, // GSInstanceID // Hull shader OutputControlPointID = 107, // OutputControlPointID PrimitiveID = 108, // PrimitiveID StorePatchConstant = 106, // StorePatchConstant // Legacy floating-point LegacyF16ToF32 = 131, // legacy fuction to convert half (f16) to float (f32) (this is not related to min-precision) LegacyF32ToF16 = 130, // legacy fuction to convert float (f32) to half (f16) (this is not related to min-precision) // Other CycleCounterLegacy = 109, // CycleCounterLegacy // Pixel shader CalculateLOD = 81, // calculates the level of detail Coverage = 91, // returns the coverage mask input in a pixel shader DerivCoarseX = 83, // computes the rate of change of components per stamp DerivCoarseY = 84, // computes the rate of change of components per stamp DerivFineX = 85, // computes the rate of change of components per pixel DerivFineY = 86, // computes the rate of change of components per pixel Discard = 82, // discard the current pixel EvalCentroid = 89, // evaluates an input attribute at pixel center EvalSampleIndex = 88, // evaluates an input attribute at a sample location EvalSnapped = 87, // evaluates an input attribute at pixel center with an offset InnerCoverage = 92, // returns underestimated coverage input from conservative rasterization in a pixel shader SampleIndex = 90, // returns the sample index in a sample-frequency pixel shader // Quaternary Bfi = 53, // given a bit range from the LSB of a number, places that number of bits in another number at any offset // Resources - gather TextureGather = 73, // gathers the four texels that would be used in a bi-linear filtering operation TextureGatherCmp = 74, // same as TextureGather, except this instrution performs comparison on texels, similar to SampleCmp // Resources - sample RenderTargetGetSampleCount = 77, // gets the number of samples for a render target RenderTargetGetSamplePosition = 76, // gets the position of the specified sample Sample = 60, // samples a texture SampleBias = 61, // samples a texture after applying the input bias to the mipmap level SampleCmp = 64, // samples a texture and compares a single component against the specified comparison value SampleCmpLevelZero = 65, // samples a texture and compares a single component against the specified comparison value SampleGrad = 63, // samples a texture using a gradient to influence the way the sample location is calculated SampleLevel = 62, // samples a texture using a mipmap-level offset Texture2DMSGetSamplePosition = 75, // gets the position of the specified sample // Resources BufferLoad = 68, // reads from a TypedBuffer BufferStore = 69, // writes to a RWTypedBuffer BufferUpdateCounter = 70, // atomically increments/decrements the hidden 32-bit counter stored with a Count or Append UAV CBufferLoad = 58, // loads a value from a constant buffer resource CBufferLoadLegacy = 59, // loads a value from a constant buffer resource CheckAccessFullyMapped = 71, // determines whether all values from a Sample, Gather, or Load operation accessed mapped tiles in a tiled resource CreateHandle = 57, // creates the handle to a resource GetDimensions = 72, // gets texture size information TextureLoad = 66, // reads texel data without any filtering or sampling TextureStore = 67, // reads texel data without any filtering or sampling // Synchronization AtomicBinOp = 78, // performs an atomic operation on two operands AtomicCompareExchange = 79, // atomic compare and exchange to memory Barrier = 80, // inserts a memory barrier in the shader // Temporary, indexable, input, output registers LoadInput = 4, // loads the value from shader input MinPrecXRegLoad = 2, // helper load operation for minprecision MinPrecXRegStore = 3, // helper store operation for minprecision StoreOutput = 5, // stores the value to shader output TempRegLoad = 0, // helper load operation TempRegStore = 1, // helper store operation // Tertiary float FMad = 46, // performs a fused multiply add (FMA) of the form a * b + c Fma = 47, // performs a fused multiply add (FMA) of the form a * b + c // Tertiary int IMad = 48, // performs an integral IMad Ibfe = 51, // performs an integral Ibfe Msad = 50, // performs an integral Msad UMad = 49, // performs an integral UMad Ubfe = 52, // performs an integral Ubfe // Unary float - rounding Round_ne = 26, // returns the Round_ne Round_ni = 27, // returns the Round_ni Round_pi = 28, // returns the Round_pi Round_z = 29, // returns the Round_z // Unary float Acos = 15, // returns the Acos Asin = 16, // returns the Asin Atan = 17, // returns the Atan Cos = 12, // returns cosine(theta) for theta in radians. Exp = 21, // returns the Exp FAbs = 6, // returns the absolute value of the input value. Frc = 22, // returns the Frc Hcos = 18, // returns the Hcos Hsin = 19, // returns the Hsin Htan = 20, // returns the Htan IsFinite = 10, // returns the IsFinite IsInf = 9, // returns the IsInf IsNaN = 8, // returns the IsNaN IsNormal = 11, // returns the IsNormal Log = 23, // returns the Log Rsqrt = 25, // returns the Rsqrt Saturate = 7, // clamps the result of a single or double precision floating point value to [0.0f...1.0f] Sin = 13, // returns the Sin Sqrt = 24, // returns the Sqrt Tan = 14, // returns the Tan // Unary int Bfrev = 30, // returns the reverse bit pattern of the input value Countbits = 31, // returns the Countbits FirstbitHi = 33, // returns src != 0? (BitWidth-1 - FirstbitHi) : -1 FirstbitLo = 32, // returns the FirstbitLo FirstbitSHi = 34, // returns src != 0? (BitWidth-1 - FirstbitSHi) : -1 // Wave QuadOp = 123, // returns the result of a quad-level operation QuadReadLaneAt = 122, // reads from a lane in the quad WaveActiveAllEqual = 115, // returns 1 if all the lanes have the same value WaveActiveBallot = 116, // returns a struct with a bit set for each lane where the condition is true WaveActiveBit = 120, // returns the result of the operation across all lanes WaveActiveOp = 119, // returns the result the operation across waves WaveAllBitCount = 135, // returns the count of bits set to 1 across the wave WaveAllTrue = 114, // returns 1 if all the lanes evaluate the value to true WaveAnyTrue = 113, // returns 1 if any of the lane evaluates the value to true WaveGetLaneCount = 112, // returns the number of lanes in the wave WaveGetLaneIndex = 111, // returns the index of the current lane in the wave WaveIsFirstLane = 110, // returns 1 for the first lane in the wave WavePrefixBitCount = 136, // returns the count of bits set to 1 on prior lanes WavePrefixOp = 121, // returns the result of the operation on prior lanes WaveReadLaneAt = 117, // returns the value from the specified lane WaveReadLaneFirst = 118, // returns the value from the first lane NumOpCodes = 137 // exclusive last value of enumeration }; // OPCODE-ENUM:END /* hctdb_instrhelp.get_enum_decl("OpCodeClass")*/ // OPCODECLASS-ENUM:BEGIN // Groups for DXIL operations with equivalent function templates enum class OpCodeClass : unsigned { // Binary int with two outputs BinaryWithTwoOuts, // Binary int Binary, // Binary uint with carry or borrow BinaryWithCarryOrBorrow, // Bitcasts with different sizes BitcastF16toI16, BitcastF32toI32, BitcastF64toI64, BitcastI16toF16, BitcastI32toF32, BitcastI64toF64, // Compute shader FlattenedThreadIdInGroup, GroupId, ThreadId, ThreadIdInGroup, // Domain and hull shader LoadOutputControlPoint, LoadPatchConstant, // Domain shader DomainLocation, // Dot Dot2, Dot3, Dot4, // Double precision LegacyDoubleToFloat, LegacyDoubleToSInt32, LegacyDoubleToUInt32, MakeDouble, SplitDouble, // Geometry shader CutStream, EmitStream, EmitThenCutStream, GSInstanceID, // Hull shader OutputControlPointID, PrimitiveID, StorePatchConstant, // LLVM Instructions LlvmInst, // Legacy floating-point LegacyF16ToF32, LegacyF32ToF16, // Other CycleCounterLegacy, // Pixel shader CalculateLOD, Coverage, Discard, EvalCentroid, EvalSampleIndex, EvalSnapped, InnerCoverage, SampleIndex, Unary, // Quaternary Quaternary, // Resources - gather TextureGather, TextureGatherCmp, // Resources - sample RenderTargetGetSampleCount, RenderTargetGetSamplePosition, Sample, SampleBias, SampleCmp, SampleCmpLevelZero, SampleGrad, SampleLevel, Texture2DMSGetSamplePosition, // Resources BufferLoad, BufferStore, BufferUpdateCounter, CBufferLoad, CBufferLoadLegacy, CheckAccessFullyMapped, CreateHandle, GetDimensions, TextureLoad, TextureStore, // Synchronization AtomicBinOp, AtomicCompareExchange, Barrier, // Temporary, indexable, input, output registers LoadInput, MinPrecXRegLoad, MinPrecXRegStore, StoreOutput, TempRegLoad, TempRegStore, // Tertiary int Tertiary, // Unary float IsSpecialFloat, // Unary int UnaryBits, // Wave QuadOp, QuadReadLaneAt, WaveActiveAllEqual, WaveActiveBallot, WaveActiveBit, WaveActiveOp, WaveAllOp, WaveAllTrue, WaveAnyTrue, WaveGetLaneCount, WaveGetLaneIndex, WaveIsFirstLane, WavePrefixOp, WaveReadLaneAt, WaveReadLaneFirst, NumOpClasses = 93 // exclusive last value of enumeration }; // OPCODECLASS-ENUM:END // Operand Index for every OpCodeClass. namespace OperandIndex { // Opcode is always operand 0. const unsigned kOpcodeIdx = 0; // Unary operators. const unsigned kUnarySrc0OpIdx = 1; // Binary operators. const unsigned kBinarySrc0OpIdx = 1; const unsigned kBinarySrc1OpIdx = 2; // Trinary operators. const unsigned kTrinarySrc0OpIdx = 1; const unsigned kTrinarySrc1OpIdx = 2; const unsigned kTrinarySrc2OpIdx = 3; // LoadInput. const unsigned kLoadInputIDOpIdx = 1; const unsigned kLoadInputRowOpIdx = 2; const unsigned kLoadInputColOpIdx = 3; const unsigned kLoadInputVertexIDOpIdx = 4; // StoreOutput. const unsigned kStoreOutputIDOpIdx = 1; const unsigned kStoreOutputRowOpIdx = 2; const unsigned kStoreOutputColOpIdx = 3; const unsigned kStoreOutputValOpIdx = 4; // DomainLocation. const unsigned kDomainLocationColOpIdx = 1; // BufferLoad. const unsigned kBufferLoadHandleOpIdx = 1; const unsigned kBufferLoadCoord0OpIdx = 2; const unsigned kBufferLoadCoord1OpIdx = 3; // BufferStore. const unsigned kBufferStoreHandleOpIdx = 1; const unsigned kBufferStoreCoord0OpIdx = 2; const unsigned kBufferStoreCoord1OpIdx = 3; const unsigned kBufferStoreVal0OpIdx = 4; const unsigned kBufferStoreVal1OpIdx = 5; const unsigned kBufferStoreVal2OpIdx = 6; const unsigned kBufferStoreVal3OpIdx = 7; const unsigned kBufferStoreMaskOpIdx = 8; // TextureStore. const unsigned kTextureStoreHandleOpIdx = 1; const unsigned kTextureStoreCoord0OpIdx = 2; const unsigned kTextureStoreCoord1OpIdx = 3; const unsigned kTextureStoreCoord2OpIdx = 4; const unsigned kTextureStoreVal0OpIdx = 5; const unsigned kTextureStoreVal1OpIdx = 6; const unsigned kTextureStoreVal2OpIdx = 7; const unsigned kTextureStoreVal3OpIdx = 8; const unsigned kTextureStoreMaskOpIdx = 9; // TextureGather. const unsigned kTextureGatherTexHandleOpIdx = 1; const unsigned kTextureGatherSamplerHandleOpIdx = 2; const unsigned kTextureGatherCoord0OpIdx = 3; const unsigned kTextureGatherCoord1OpIdx = 4; const unsigned kTextureGatherCoord2OpIdx = 5; const unsigned kTextureGatherCoord3OpIdx = 6; const unsigned kTextureGatherOffset0OpIdx = 7; const unsigned kTextureGatherOffset1OpIdx = 8; const unsigned kTextureGatherOffset2OpIdx = 9; const unsigned kTextureGatherChannelOpIdx = 10; // TextureGatherCmp. const unsigned kTextureGatherCmpCmpValOpIdx = 11; // TextureSample. const unsigned kTextureSampleTexHandleOpIdx = 1; const unsigned kTextureSampleSamplerHandleOpIdx = 2; const unsigned kTextureSampleCoord0OpIdx = 3; const unsigned kTextureSampleCoord1OpIdx = 4; const unsigned kTextureSampleCoord2OpIdx = 5; const unsigned kTextureSampleCoord3OpIdx = 6; const unsigned kTextureSampleOffset0OpIdx = 7; const unsigned kTextureSampleOffset1OpIdx = 8; const unsigned kTextureSampleOffset2OpIdx = 9; const unsigned kTextureSampleClampOpIdx = 10; // AtomicBinOp. const unsigned kAtomicBinOpCoord0OpIdx = 3; const unsigned kAtomicBinOpCoord1OpIdx = 4; const unsigned kAtomicBinOpCoord2OpIdx = 5; // AtomicCmpExchange. const unsigned kAtomicCmpExchangeCoord0OpIdx = 2; const unsigned kAtomicCmpExchangeCoord1OpIdx = 3; const unsigned kAtomicCmpExchangeCoord2OpIdx = 4; // CreateHandle const unsigned kCreateHandleResClassOpIdx = 1; const unsigned kCreateHandleResIDOpIdx = 2; const unsigned kCreateHandleResIndexOpIdx = 3; const unsigned kCreateHandleIsUniformOpIdx = 4; // Emit/Cut const unsigned kStreamEmitCutIDOpIdx = 1; // TODO: add operand index for all the OpCodeClass. } // Atomic binary operation kind. enum class AtomicBinOpCode : unsigned { Add, And, Or, Xor, IMin, IMax, UMin, UMax, Exchange, Invalid // Must be last. }; // Barrier/fence modes. enum class BarrierMode : unsigned { SyncThreadGroup = 0x00000001, UAVFenceGlobal = 0x00000002, UAVFenceThreadGroup = 0x00000004, TGSMFence = 0x00000008, }; // Address space. const unsigned kDefaultAddrSpace = 0; const unsigned kDeviceMemoryAddrSpace = 1; const unsigned kCBufferAddrSpace = 2; const unsigned kTGSMAddrSpace = 3; const unsigned kGenericPointerAddrSpace = 4; const unsigned kImmediateCBufferAddrSpace = 5; // Input primitive. enum class InputPrimitive : unsigned { Undefined = 0, Point = 1, Line = 2, Triangle = 3, Reserved4 = 4, Reserved5 = 5, LineWithAdjacency = 6, TriangleWithAdjacency = 7, ControlPointPatch1 = 8, ControlPointPatch2 = 9, ControlPointPatch3 = 10, ControlPointPatch4 = 11, ControlPointPatch5 = 12, ControlPointPatch6 = 13, ControlPointPatch7 = 14, ControlPointPatch8 = 15, ControlPointPatch9 = 16, ControlPointPatch10 = 17, ControlPointPatch11 = 18, ControlPointPatch12 = 19, ControlPointPatch13 = 20, ControlPointPatch14 = 21, ControlPointPatch15 = 22, ControlPointPatch16 = 23, ControlPointPatch17 = 24, ControlPointPatch18 = 25, ControlPointPatch19 = 26, ControlPointPatch20 = 27, ControlPointPatch21 = 28, ControlPointPatch22 = 29, ControlPointPatch23 = 30, ControlPointPatch24 = 31, ControlPointPatch25 = 32, ControlPointPatch26 = 33, ControlPointPatch27 = 34, ControlPointPatch28 = 35, ControlPointPatch29 = 36, ControlPointPatch30 = 37, ControlPointPatch31 = 38, ControlPointPatch32 = 39, LastEntry, }; // Primitive topology. enum class PrimitiveTopology : unsigned { Undefined = 0, PointList = 1, LineList = 2, LineStrip = 3, TriangleList = 4, TriangleStrip = 5, LastEntry, }; enum class TessellatorDomain { Undefined = 0, IsoLine = 1, Tri = 2, Quad = 3, LastEntry, }; enum class TessellatorOutputPrimitive { Undefined = 0, Point = 1, Line = 2, TriangleCW = 3, TriangleCCW = 4, LastEntry, }; // Tessellator partitioning. enum class TessellatorPartitioning : unsigned { Undefined = 0, Integer, Pow2, FractionalOdd, FractionalEven, LastEntry, }; // Kind of quad-level operation enum class QuadOpKind { ReadAcrossX = 0, // returns the value from the other lane in the quad in the horizontal direction ReadAcrossY = 1, // returns the value from the other lane in the quad in the vertical direction ReadAcrossDiagonal = 2, // returns the value from the lane across the quad in horizontal and vertical direction }; /* hctdb_instrhelp.get_enum_decl("WaveBitOpKind")*/ // WAVEBITOPKIND-ENUM:BEGIN // Kind of bitwise cross-lane operation enum class WaveBitOpKind : unsigned { And = 0, // bitwise and of values Or = 1, // bitwise or of values Xor = 2, // bitwise xor of values }; // WAVEBITOPKIND-ENUM:END /* hctdb_instrhelp.get_enum_decl("WaveOpKind")*/ // WAVEOPKIND-ENUM:BEGIN // Kind of cross-lane operation enum class WaveOpKind : unsigned { Max = 3, // maximum value Min = 2, // minimum value Product = 1, // product of values Sum = 0, // sum of values }; // WAVEOPKIND-ENUM:END /* hctdb_instrhelp.get_enum_decl("SignedOpKind")*/ // SIGNEDOPKIND-ENUM:BEGIN // Sign vs. unsigned operands for operation enum class SignedOpKind : unsigned { Signed = 0, // signed integer or floating-point operands Unsigned = 1, // unsigned integer operands }; // SIGNEDOPKIND-ENUM:END // Kind of control flow hint enum class ControlFlowHint : unsigned { Undefined = 0, Branch = 1, Flatten = 2, FastOpt = 3, AllowUavCondition = 4, ForceCase = 5, Call = 6, // Loop and Unroll is using llvm.loop.unroll Metadata. LastEntry, }; // XYZW component mask. const uint8_t kCompMask_X = 0x1; const uint8_t kCompMask_Y = 0x2; const uint8_t kCompMask_Z = 0x4; const uint8_t kCompMask_W = 0x8; const uint8_t kCompMask_All = 0xF; } // namespace DXIL } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilContainer.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilContainer.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides declarations for the DXIL container format. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #ifndef __DXC_CONTAINER__ #define __DXC_CONTAINER__ #include #include #include #include "dxc/HLSL/DxilConstants.h" struct IDxcContainerReflection; namespace llvm { class Module; } namespace hlsl { class AbstractMemoryStream; class RootSignatureHandle; class DxilModule; #pragma pack(push, 1) static const size_t DxilContainerHashSize = 16; static const uint16_t DxilContainerVersionMajor = 1; // Current major version static const uint16_t DxilContainerVersionMinor = 0; // Current minor version static const uint32_t DxilContainerMaxSize = 0x80000000; // Max size for container. /// Use this type to represent the hash for the full container. struct DxilContainerHash { uint8_t Digest[DxilContainerHashSize]; }; struct DxilContainerVersion { uint16_t Major; uint16_t Minor; }; /// Use this type to describe a DXIL container of parts. struct DxilContainerHeader { uint32_t HeaderFourCC; DxilContainerHash Hash; DxilContainerVersion Version; uint32_t ContainerSizeInBytes; // From start of this header uint32_t PartCount; // Structure is followed by uint32_t PartOffset[PartCount]; // The offset is to a DxilPartHeader. }; /// Use this type to describe the size and type of a DXIL container part. struct DxilPartHeader { uint32_t PartFourCC; // Four char code for part type. uint32_t PartSize; // Byte count for PartData. // Structure is followed by uint8_t PartData[PartSize]. }; #define DXIL_FOURCC(ch0, ch1, ch2, ch3) ( \ (uint32_t)(uint8_t)(ch0) | (uint32_t)(uint8_t)(ch1) << 8 | \ (uint32_t)(uint8_t)(ch2) << 16 | (uint32_t)(uint8_t)(ch3) << 24 \ ) enum DxilFourCC { DFCC_Container = DXIL_FOURCC('D', 'X', 'B', 'C'), // for back-compat with tools that look for DXBC containers DFCC_ResourceDef = DXIL_FOURCC('R', 'D', 'E', 'F'), DFCC_InputSignature = DXIL_FOURCC('I', 'S', 'G', '1'), DFCC_OutputSignature = DXIL_FOURCC('O', 'S', 'G', '1'), DFCC_PatchConstantSignature = DXIL_FOURCC('P', 'S', 'G', '1'), DFCC_ShaderStatistics = DXIL_FOURCC('S', 'T', 'A', 'T'), DFCC_ShaderDebugInfoDXIL = DXIL_FOURCC('I', 'L', 'D', 'B'), DFCC_FeatureInfo = DXIL_FOURCC('S', 'F', 'I', '0'), DFCC_PrivateData = DXIL_FOURCC('P', 'R', 'I', 'V'), DFCC_RootSignature = DXIL_FOURCC('R', 'T', 'S', '0'), DFCC_DXIL = DXIL_FOURCC('D', 'X', 'I', 'L'), DFCC_PipelineStateValidation = DXIL_FOURCC('P', 'S', 'V', '0'), }; #undef DXIL_FOURCC // DFCC_FeatureInfo is a uint64_t value with these flags. static const uint64_t ShaderFeatureInfo_Doubles = 0x0001; static const uint64_t ShaderFeatureInfo_ComputeShadersPlusRawAndStructuredBuffersViaShader4X = 0x0002; static const uint64_t ShaderFeatureInfo_UAVsAtEveryStage = 0x0004; static const uint64_t ShaderFeatureInfo_64UAVs = 0x0008; static const uint64_t ShaderFeatureInfo_MininumPrecision = 0x0010; static const uint64_t ShaderFeatureInfo_11_1_DoubleExtensions = 0x0020; static const uint64_t ShaderFeatureInfo_11_1_ShaderExtensions = 0x0040; static const uint64_t ShaderFeatureInfo_LEVEL9ComparisonFiltering = 0x0080; static const uint64_t ShaderFeatureInfo_TiledResources = 0x0100; static const uint64_t ShaderFeatureInfo_StencilRef = 0x0200; static const uint64_t ShaderFeatureInfo_InnerCoverage = 0x0400; static const uint64_t ShaderFeatureInfo_TypedUAVLoadAdditionalFormats = 0x0800; static const uint64_t ShaderFeatureInfo_ROVs = 0x1000; static const uint64_t ShaderFeatureInfo_ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer = 0x2000; static const uint64_t ShaderFeatureInfo_WaveOps = 0x4000; static const uint64_t ShaderFeatureInfo_Int64Ops = 0x8000; static const unsigned ShaderFeatureInfoCount = 16; struct DxilShaderFeatureInfo { uint64_t FeatureFlags; }; // DXIL program information. struct DxilBitcodeHeader { uint32_t DxilMagic; // ACSII "DXIL". uint32_t DxilVersion; // DXIL version. uint32_t BitcodeOffset; // Offset to LLVM bitcode (from start of header). uint32_t BitcodeSize; // Size of LLVM bitcode. }; static const uint32_t DxilMagicValue = 0x4C495844; // 'DXIL' struct DxilProgramHeader { uint32_t ProgramVersion; /// Major and minor version, including type. uint32_t SizeInUint32; /// Size in uint32_t units including this header. DxilBitcodeHeader BitcodeHeader; /// Bitcode-specific header. // Followed by uint8_t[BitcodeHeader.BitcodeOffset] }; struct DxilProgramSignature { uint32_t ParamCount; uint32_t ParamOffset; }; enum class DxilProgramSigMinPrecision : uint32_t { Default = 0, Float16 = 1, Float2_8 = 2, Reserved = 3, SInt16 = 4, UInt16 = 5, Any16 = 0xf0, Any10 = 0xf1 }; enum class DxilProgramSigSemantic : uint32_t { Undefined = 0, Position = 1, ClipDistance = 2, CullDistance = 3, RenderTargetArrayIndex = 4, ViewPortArrayIndex = 5, VertexID = 6, PrimitiveID = 7, InstanceID = 8, IsFrontFace = 9, SampleIndex = 10, FinalQuadEdgeTessfactor = 11, FinalQuadInsideTessfactor = 12, FinalTriEdgeTessfactor = 13, FinalTriInsideTessfactor = 14, FinalLineDetailTessfactor = 15, FinalLineDensityTessfactor = 16, Target = 64, Depth = 65, Coverage = 66, DepthGE = 67, DepthLE = 68, StencilRef = 69, InnerCoverage = 70 }; enum class DxilProgramSigCompType : uint32_t { Unknown = 0, UInt32 = 1, SInt32 = 2, Float32 = 3, UInt16 = 4, SInt16 = 5, Float16 = 6, UInt64 = 7, SInt64 = 8, Float64 = 9, }; static const uint8_t DxilProgramSigMaskX = 1; static const uint8_t DxilProgramSigMaskY = 2; static const uint8_t DxilProgramSigMaskZ = 4; static const uint8_t DxilProgramSigMaskW = 8; struct DxilProgramSignatureElement { uint32_t Stream; // Stream index (parameters must appear in non-decreasing stream order) uint32_t SemanticName; // Offset to LPCSTR from start of DxilProgramSignature. uint32_t SemanticIndex; // Semantic Index DxilProgramSigSemantic SystemValue; // Semantic type. Similar to DxilSemantic::Kind, but a serialized rather than processing rep. DxilProgramSigCompType CompType; // Type of bits. uint32_t Register; // Register Index (row index) uint8_t Mask; // Mask (column allocation) union // Unconditional cases useful for validation of shader linkage. { uint8_t NeverWrites_Mask; // For an output signature, the shader the signature belongs to never // writes the masked components of the output register. uint8_t AlwaysReads_Mask; // For an input signature, the shader the signature belongs to always // reads the masked components of the input register. }; uint16_t Pad; DxilProgramSigMinPrecision MinPrecision; // Minimum precision of input/output data }; // Easy to get this wrong. Earlier assertions can help determine static_assert(sizeof(DxilProgramSignatureElement) == 0x20, "else DxilProgramSignatureElement is misaligned"); #pragma pack(pop) /// Gets a part header by index. inline const DxilPartHeader * GetDxilContainerPart(const DxilContainerHeader *pHeader, uint32_t index) { const uint8_t *pLinearContainer = reinterpret_cast(pHeader); const uint32_t *pPartOffsetTable = reinterpret_cast(pHeader + 1); return reinterpret_cast( pLinearContainer + pPartOffsetTable[index]); } /// Gets a part header by index. inline DxilPartHeader *GetDxilContainerPart(DxilContainerHeader *pHeader, uint32_t index) { return const_cast(GetDxilContainerPart( reinterpret_cast(pHeader), index)); } /// Gets the part data from the header. inline const char *GetDxilPartData(const DxilPartHeader *pPart) { return reinterpret_cast(pPart + 1); } /// Gets the part data from the header. inline char *GetDxilPartData(DxilPartHeader *pPart) { return reinterpret_cast(pPart + 1); } /// Gets a part header by fourCC DxilPartHeader *GetDxilPartByType(DxilContainerHeader *pHeader, DxilFourCC fourCC); /// Gets a part header by fourCC const DxilPartHeader * GetDxilPartByType(const DxilContainerHeader *pHeader, DxilFourCC fourCC); /// Returns valid DxilProgramHeader. nullptr if does not exist. DxilProgramHeader *GetDxilProgramHeader(DxilContainerHeader *pHeader, DxilFourCC fourCC); /// Returns valid DxilProgramHeader. nullptr if does not exist. const DxilProgramHeader * GetDxilProgramHeader(const DxilContainerHeader *pHeader, DxilFourCC fourCC); /// Initializes container with the specified values. void InitDxilContainer(_Out_ DxilContainerHeader *pHeader, uint32_t partCount, uint32_t containerSizeInBytes); /// Checks whether pHeader claims by signature to be a DXIL container. const DxilContainerHeader *IsDxilContainerLike(const void *ptr, size_t length); /// Checks whether the DXIL container is valid and in-bounds. bool IsValidDxilContainer(const DxilContainerHeader *pHeader, size_t length); /// Use this type as a unary predicate functor. struct DxilPartIsType { uint32_t IsFourCC; DxilPartIsType(uint32_t FourCC) : IsFourCC(FourCC) { } bool operator()(const DxilPartHeader *pPart) const { return pPart->PartFourCC == IsFourCC; } }; /// Use this type as an iterator over the part headers. struct DxilPartIterator : public std::iterator { const DxilContainerHeader *pHeader; uint32_t index; DxilPartIterator(const DxilContainerHeader *h, uint32_t i) : pHeader(h), index(i) {} // increment DxilPartIterator &operator++() { ++index; return *this; } DxilPartIterator operator++(int) { DxilPartIterator result(pHeader, index); ++index; return result; } // input iterator - compare and deref bool operator==(const DxilPartIterator &other) const { return index == other.index && pHeader == other.pHeader; } bool operator!=(const DxilPartIterator &other) const { return index != other.index || pHeader != other.pHeader; } const DxilPartHeader *operator*() const { return GetDxilContainerPart(pHeader, index); } }; DxilPartIterator begin(const DxilContainerHeader *pHeader); DxilPartIterator end(const DxilContainerHeader *pHeader); inline bool IsValidDxilBitcodeHeader(const DxilBitcodeHeader *pHeader, uint32_t length) { return length > sizeof(DxilBitcodeHeader) && pHeader->BitcodeOffset + pHeader->BitcodeSize > pHeader->BitcodeOffset && length >= pHeader->BitcodeOffset + pHeader->BitcodeSize && pHeader->DxilMagic == DxilMagicValue; } inline void InitBitcodeHeader(DxilBitcodeHeader &header, uint32_t bitcodeSize) { header.DxilMagic = DxilMagicValue; header.DxilVersion = DXIL::GetCurrentDxilVersion(); header.BitcodeOffset = sizeof(DxilBitcodeHeader); header.BitcodeSize = bitcodeSize; } inline void GetDxilProgramBitcode(const DxilProgramHeader *pHeader, const char **pBitcode, uint32_t *pBitcodeLength) { *pBitcode = reinterpret_cast(&pHeader->BitcodeHeader) + pHeader->BitcodeHeader.BitcodeOffset; *pBitcodeLength = pHeader->BitcodeHeader.BitcodeSize; } inline bool IsValidDxilProgramHeader(const DxilProgramHeader *pHeader, uint32_t length) { return length >= sizeof(DxilProgramHeader) && length >= (pHeader->SizeInUint32 * sizeof(uint32_t)) && IsValidDxilBitcodeHeader( &pHeader->BitcodeHeader, length - offsetof(DxilProgramHeader, BitcodeHeader)); } inline void InitProgramHeader(DxilProgramHeader &header, uint32_t version, uint32_t bitcodeSize) { header.ProgramVersion = version; header.SizeInUint32 = sizeof(DxilProgramHeader) / sizeof(uint32_t) + bitcodeSize / sizeof(uint32_t) + ((bitcodeSize % 4) ? 1 : 0); InitBitcodeHeader(header.BitcodeHeader, bitcodeSize); } inline const char *GetDxilBitcodeData(const DxilProgramHeader *pHeader) { const DxilBitcodeHeader *pBCHdr = &(pHeader->BitcodeHeader); return (const char *)pBCHdr + pBCHdr->BitcodeOffset; } inline uint32_t GetDxilBitcodeSize(const DxilProgramHeader *pHeader) { return pHeader->BitcodeHeader.BitcodeSize; } /// Extract the shader type from the program version value. inline DXIL::ShaderKind GetVersionShaderType(uint32_t programVersion) { return (DXIL::ShaderKind)((programVersion & 0xffff0000) >> 16); } inline uint32_t GetVersionMajor(uint32_t programVersion) { return (programVersion & 0xf0) >> 4; } inline uint32_t GetVersionMinor(uint32_t programVersion) { return (programVersion & 0xf); } inline uint32_t EncodeVersion(DXIL::ShaderKind shaderType, uint32_t major, uint32_t minor) { return ((unsigned)shaderType << 16) | (major << 4) | minor; } class DxilPartWriter { public: virtual uint32_t size() const = 0; virtual void write(AbstractMemoryStream *pStream) = 0; }; DxilPartWriter *NewProgramSignatureWriter(const DxilModule &M, DXIL::SignatureKind Kind); DxilPartWriter *NewRootSignatureWriter(const RootSignatureHandle &S); DxilPartWriter *NewFeatureInfoWriter(const DxilModule &M); DxilPartWriter *NewPSVWriter(const DxilModule &M); class DxilContainerWriter : public DxilPartWriter { public: typedef std::function WriteFn; virtual void AddPart(uint32_t FourCC, uint32_t Size, WriteFn Write) = 0; }; DxilContainerWriter *NewDxilContainerWriter(); void SerializeDxilContainerForModule(hlsl::DxilModule *pModule, AbstractMemoryStream *pModuleBitcode, AbstractMemoryStream *pStream); void SerializeDxilContainerForRootSignature(hlsl::RootSignatureHandle *pRootSigHandle, AbstractMemoryStream *pStream); void CreateDxcContainerReflection(IDxcContainerReflection **ppResult); // Converts uint32_t partKind to char array object. inline char * PartKindToCharArray(uint32_t partKind, _Out_writes_(5) char* pText) { pText[0] = (char)((partKind & 0x000000FF) >> 0); pText[1] = (char)((partKind & 0x0000FF00) >> 8); pText[2] = (char)((partKind & 0x00FF0000) >> 16); pText[3] = (char)((partKind & 0xFF000000) >> 24); pText[4] = '\0'; return pText; } inline size_t GetOffsetTableSize(uint32_t partCount) { return sizeof(uint32_t) * partCount; } // Compute total size of the dxil container from parts information inline size_t GetDxilContainerSizeFromParts(uint32_t partCount, uint32_t partsSize) { return partsSize + (uint32_t)sizeof(DxilContainerHeader) + GetOffsetTableSize(partCount) + (uint32_t)sizeof(DxilPartHeader) * partCount; } } // namespace hlsl #endif // __DXC_CONTAINER__ ================================================ FILE: src/Wrapper/dxc/HLSL/DxilGenerationPass.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilGenerationPass.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // This file provides a DXIL Generation pass. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once namespace llvm { class Module; class ModulePass; class Function; class FunctionPass; class Instruction; class PassRegistry; } namespace hlsl { class DxilResourceBase; class WaveSensitivityAnalysis { public: static WaveSensitivityAnalysis* create(); virtual ~WaveSensitivityAnalysis() { } virtual void Analyze(llvm::Function *F) = 0; virtual bool IsWaveSensitive(llvm::Instruction *op) = 0; }; class HLSLExtensionsCodegenHelper; } namespace llvm { /// \brief Create and return a pass that tranform the module into a DXIL module /// Note that this pass is designed for use with the legacy pass manager. ModulePass *createDxilCondenseResourcesPass(); ModulePass *createDxilGenerationPass(bool NotOptimized, hlsl::HLSLExtensionsCodegenHelper *extensionsHelper); ModulePass *createHLEmitMetadataPass(); ModulePass *createHLEnsureMetadataPass(); ModulePass *createDxilEmitMetadataPass(); ModulePass *createDxilPrecisePropagatePass(); FunctionPass *createDxilLegalizeSampleOffsetPass(); FunctionPass *createSimplifyInstPass(); void initializeDxilCondenseResourcesPass(llvm::PassRegistry&); void initializeDxilGenerationPassPass(llvm::PassRegistry&); void initializeHLEnsureMetadataPass(llvm::PassRegistry&); void initializeHLEmitMetadataPass(llvm::PassRegistry&); void initializeDxilEmitMetadataPass(llvm::PassRegistry&); void initializeDxilPrecisePropagatePassPass(llvm::PassRegistry&); void initializeDxilLegalizeSampleOffsetPassPass(llvm::PassRegistry&); void initializeSimplifyInstPass(llvm::PassRegistry&); bool AreDxilResourcesDense(llvm::Module *M, hlsl::DxilResourceBase **ppNonDense); } ================================================ FILE: src/Wrapper/dxc/HLSL/DxilInstructions.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilInstructions.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // This file provides a library of instruction helper classes. // // MUCH WORK YET TO BE DONE - EXPECT THIS WILL CHANGE - GENERATED FILE // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "llvm/IR/Constants.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" // TODO: add correct include directives // TODO: add accessors with values // TODO: add validation support code, including calling into right fn // TODO: add type hierarchy namespace hlsl { /* import hctdb_instrhelp */ /* hctdb_instrhelp.get_instrhelper()*/ // INSTR-HELPER:BEGIN /// This instruction returns a value (possibly void), from a function. struct LlvmInst_Ret { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Ret(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Ret; } // Validation support bool isAllowed() const { return true; } }; /// This instruction branches (conditional or unconditional) struct LlvmInst_Br { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Br(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Br; } // Validation support bool isAllowed() const { return true; } }; /// This instruction performs a multiway switch struct LlvmInst_Switch { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Switch(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Switch; } // Validation support bool isAllowed() const { return true; } }; /// This instruction branches indirectly struct LlvmInst_IndirectBr { const llvm::Instruction *Instr; // Construction and identification LlvmInst_IndirectBr(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::IndirectBr; } // Validation support bool isAllowed() const { return false; } }; /// This instruction invokes function with normal and exceptional returns struct LlvmInst_Invoke { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Invoke(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Invoke; } // Validation support bool isAllowed() const { return false; } }; /// This instruction resumes the propagation of an exception struct LlvmInst_Resume { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Resume(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Resume; } // Validation support bool isAllowed() const { return false; } }; /// This instruction is unreachable struct LlvmInst_Unreachable { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Unreachable(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Unreachable; } // Validation support bool isAllowed() const { return false; } }; /// This instruction returns the sum of its two operands struct LlvmInst_Add { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Add(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Add; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the sum of its two operands struct LlvmInst_FAdd { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FAdd(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FAdd; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the difference of its two operands struct LlvmInst_Sub { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Sub(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Sub; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the difference of its two operands struct LlvmInst_FSub { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FSub(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FSub; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the product of its two operands struct LlvmInst_Mul { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Mul(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Mul; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the product of its two operands struct LlvmInst_FMul { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FMul(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FMul; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the quotient of its two unsigned operands struct LlvmInst_UDiv { const llvm::Instruction *Instr; // Construction and identification LlvmInst_UDiv(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::UDiv; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the quotient of its two signed operands struct LlvmInst_SDiv { const llvm::Instruction *Instr; // Construction and identification LlvmInst_SDiv(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::SDiv; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the quotient of its two operands struct LlvmInst_FDiv { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FDiv(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FDiv; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the remainder from the unsigned division of its two operands struct LlvmInst_URem { const llvm::Instruction *Instr; // Construction and identification LlvmInst_URem(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::URem; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the remainder from the signed division of its two operands struct LlvmInst_SRem { const llvm::Instruction *Instr; // Construction and identification LlvmInst_SRem(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::SRem; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns the remainder from the division of its two operands struct LlvmInst_FRem { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FRem(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FRem; } // Validation support bool isAllowed() const { return true; } }; /// This instruction shifts left (logical) struct LlvmInst_Shl { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Shl(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Shl; } // Validation support bool isAllowed() const { return true; } }; /// This instruction shifts right (logical), with zero bit fill struct LlvmInst_LShr { const llvm::Instruction *Instr; // Construction and identification LlvmInst_LShr(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::LShr; } // Validation support bool isAllowed() const { return true; } }; /// This instruction shifts right (arithmetic), with 'a' operand sign bit fill struct LlvmInst_AShr { const llvm::Instruction *Instr; // Construction and identification LlvmInst_AShr(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::AShr; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns a bitwise logical and of its two operands struct LlvmInst_And { const llvm::Instruction *Instr; // Construction and identification LlvmInst_And(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::And; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns a bitwise logical or of its two operands struct LlvmInst_Or { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Or(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Or; } // Validation support bool isAllowed() const { return true; } }; /// This instruction returns a bitwise logical xor of its two operands struct LlvmInst_Xor { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Xor(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Xor; } // Validation support bool isAllowed() const { return true; } }; /// This instruction allocates memory on the stack frame of the currently executing function struct LlvmInst_Alloca { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Alloca(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Alloca; } // Validation support bool isAllowed() const { return true; } }; /// This instruction reads from memory struct LlvmInst_Load { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Load(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Load; } // Validation support bool isAllowed() const { return true; } }; /// This instruction writes to memory struct LlvmInst_Store { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Store(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Store; } // Validation support bool isAllowed() const { return true; } }; /// This instruction gets the address of a subelement of an aggregate value struct LlvmInst_GetElementPtr { const llvm::Instruction *Instr; // Construction and identification LlvmInst_GetElementPtr(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::GetElementPtr; } // Validation support bool isAllowed() const { return true; } }; /// This instruction introduces happens-before edges between operations struct LlvmInst_Fence { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Fence(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Fence; } // Validation support bool isAllowed() const { return false; } }; /// This instruction atomically modifies memory struct LlvmInst_AtomicCmpXchg { const llvm::Instruction *Instr; // Construction and identification LlvmInst_AtomicCmpXchg(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::AtomicCmpXchg; } // Validation support bool isAllowed() const { return true; } }; /// This instruction atomically modifies memory struct LlvmInst_AtomicRMW { const llvm::Instruction *Instr; // Construction and identification LlvmInst_AtomicRMW(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::AtomicRMW; } // Validation support bool isAllowed() const { return true; } }; /// This instruction truncates an integer struct LlvmInst_Trunc { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Trunc(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Trunc; } // Validation support bool isAllowed() const { return true; } }; /// This instruction zero extends an integer struct LlvmInst_ZExt { const llvm::Instruction *Instr; // Construction and identification LlvmInst_ZExt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::ZExt; } // Validation support bool isAllowed() const { return true; } }; /// This instruction sign extends an integer struct LlvmInst_SExt { const llvm::Instruction *Instr; // Construction and identification LlvmInst_SExt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::SExt; } // Validation support bool isAllowed() const { return true; } }; /// This instruction converts a floating point to UInt struct LlvmInst_FPToUI { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FPToUI(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FPToUI; } // Validation support bool isAllowed() const { return true; } }; /// This instruction converts a floating point to SInt struct LlvmInst_FPToSI { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FPToSI(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FPToSI; } // Validation support bool isAllowed() const { return true; } }; /// This instruction converts a UInt to floating point struct LlvmInst_UIToFP { const llvm::Instruction *Instr; // Construction and identification LlvmInst_UIToFP(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::UIToFP; } // Validation support bool isAllowed() const { return true; } }; /// This instruction converts a SInt to floating point struct LlvmInst_SIToFP { const llvm::Instruction *Instr; // Construction and identification LlvmInst_SIToFP(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::SIToFP; } // Validation support bool isAllowed() const { return true; } }; /// This instruction truncates a floating point struct LlvmInst_FPTrunc { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FPTrunc(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FPTrunc; } // Validation support bool isAllowed() const { return true; } }; /// This instruction extends a floating point struct LlvmInst_FPExt { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FPExt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FPExt; } // Validation support bool isAllowed() const { return true; } }; /// This instruction converts a pointer to integer struct LlvmInst_PtrToInt { const llvm::Instruction *Instr; // Construction and identification LlvmInst_PtrToInt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::PtrToInt; } // Validation support bool isAllowed() const { return false; } }; /// This instruction converts an integer to Pointer struct LlvmInst_IntToPtr { const llvm::Instruction *Instr; // Construction and identification LlvmInst_IntToPtr(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::IntToPtr; } // Validation support bool isAllowed() const { return false; } }; /// This instruction performs a bit-preserving type cast struct LlvmInst_BitCast { const llvm::Instruction *Instr; // Construction and identification LlvmInst_BitCast(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::BitCast; } // Validation support bool isAllowed() const { return true; } }; /// This instruction casts a value addrspace struct LlvmInst_AddrSpaceCast { const llvm::Instruction *Instr; // Construction and identification LlvmInst_AddrSpaceCast(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::AddrSpaceCast; } // Validation support bool isAllowed() const { return true; } }; /// This instruction compares integers struct LlvmInst_ICmp { const llvm::Instruction *Instr; // Construction and identification LlvmInst_ICmp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::ICmp; } // Validation support bool isAllowed() const { return true; } }; /// This instruction compares floating points struct LlvmInst_FCmp { const llvm::Instruction *Instr; // Construction and identification LlvmInst_FCmp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::FCmp; } // Validation support bool isAllowed() const { return true; } }; /// This instruction is a PHI node instruction struct LlvmInst_PHI { const llvm::Instruction *Instr; // Construction and identification LlvmInst_PHI(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::PHI; } // Validation support bool isAllowed() const { return true; } }; /// This instruction calls a function struct LlvmInst_Call { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Call(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Call; } // Validation support bool isAllowed() const { return true; } }; /// This instruction selects an instruction struct LlvmInst_Select { const llvm::Instruction *Instr; // Construction and identification LlvmInst_Select(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::Select; } // Validation support bool isAllowed() const { return true; } }; /// This instruction may be used internally in a pass struct LlvmInst_UserOp1 { const llvm::Instruction *Instr; // Construction and identification LlvmInst_UserOp1(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::UserOp1; } // Validation support bool isAllowed() const { return false; } }; /// This instruction internal to passes only struct LlvmInst_UserOp2 { const llvm::Instruction *Instr; // Construction and identification LlvmInst_UserOp2(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::UserOp2; } // Validation support bool isAllowed() const { return false; } }; /// This instruction vaarg instruction struct LlvmInst_VAArg { const llvm::Instruction *Instr; // Construction and identification LlvmInst_VAArg(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::VAArg; } // Validation support bool isAllowed() const { return false; } }; /// This instruction extracts from aggregate struct LlvmInst_ExtractValue { const llvm::Instruction *Instr; // Construction and identification LlvmInst_ExtractValue(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::ExtractValue; } // Validation support bool isAllowed() const { return true; } }; /// This instruction represents a landing pad struct LlvmInst_LandingPad { const llvm::Instruction *Instr; // Construction and identification LlvmInst_LandingPad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return Instr->getOpcode() == llvm::Instruction::LandingPad; } // Validation support bool isAllowed() const { return false; } }; /// This instruction helper load operation struct DxilInst_TempRegLoad { const llvm::Instruction *Instr; // Construction and identification DxilInst_TempRegLoad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::TempRegLoad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_index() const { return Instr->getOperand(1); } }; /// This instruction helper store operation struct DxilInst_TempRegStore { const llvm::Instruction *Instr; // Construction and identification DxilInst_TempRegStore(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::TempRegStore); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_index() const { return Instr->getOperand(1); } llvm::Value *get_value() const { return Instr->getOperand(2); } }; /// This instruction helper load operation for minprecision struct DxilInst_MinPrecXRegLoad { const llvm::Instruction *Instr; // Construction and identification DxilInst_MinPrecXRegLoad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::MinPrecXRegLoad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_regIndex() const { return Instr->getOperand(1); } llvm::Value *get_index() const { return Instr->getOperand(2); } llvm::Value *get_component() const { return Instr->getOperand(3); } }; /// This instruction helper store operation for minprecision struct DxilInst_MinPrecXRegStore { const llvm::Instruction *Instr; // Construction and identification DxilInst_MinPrecXRegStore(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::MinPrecXRegStore); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_regIndex() const { return Instr->getOperand(1); } llvm::Value *get_index() const { return Instr->getOperand(2); } llvm::Value *get_component() const { return Instr->getOperand(3); } llvm::Value *get_value() const { return Instr->getOperand(4); } }; /// This instruction loads the value from shader input struct DxilInst_LoadInput { const llvm::Instruction *Instr; // Construction and identification DxilInst_LoadInput(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LoadInput); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_inputSigId() const { return Instr->getOperand(1); } llvm::Value *get_rowIndex() const { return Instr->getOperand(2); } llvm::Value *get_colIndex() const { return Instr->getOperand(3); } llvm::Value *get_gsVertexAxis() const { return Instr->getOperand(4); } }; /// This instruction stores the value to shader output struct DxilInst_StoreOutput { const llvm::Instruction *Instr; // Construction and identification DxilInst_StoreOutput(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::StoreOutput); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_outputtSigId() const { return Instr->getOperand(1); } llvm::Value *get_rowIndex() const { return Instr->getOperand(2); } llvm::Value *get_colIndex() const { return Instr->getOperand(3); } llvm::Value *get_value() const { return Instr->getOperand(4); } }; /// This instruction returns the absolute value of the input value. struct DxilInst_FAbs { const llvm::Instruction *Instr; // Construction and identification DxilInst_FAbs(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FAbs); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction clamps the result of a single or double precision floating point value to [0.0f...1.0f] struct DxilInst_Saturate { const llvm::Instruction *Instr; // Construction and identification DxilInst_Saturate(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Saturate); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the IsNaN struct DxilInst_IsNaN { const llvm::Instruction *Instr; // Construction and identification DxilInst_IsNaN(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IsNaN); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the IsInf struct DxilInst_IsInf { const llvm::Instruction *Instr; // Construction and identification DxilInst_IsInf(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IsInf); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the IsFinite struct DxilInst_IsFinite { const llvm::Instruction *Instr; // Construction and identification DxilInst_IsFinite(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IsFinite); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the IsNormal struct DxilInst_IsNormal { const llvm::Instruction *Instr; // Construction and identification DxilInst_IsNormal(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IsNormal); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns cosine(theta) for theta in radians. struct DxilInst_Cos { const llvm::Instruction *Instr; // Construction and identification DxilInst_Cos(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Cos); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Sin struct DxilInst_Sin { const llvm::Instruction *Instr; // Construction and identification DxilInst_Sin(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Sin); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Tan struct DxilInst_Tan { const llvm::Instruction *Instr; // Construction and identification DxilInst_Tan(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Tan); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Acos struct DxilInst_Acos { const llvm::Instruction *Instr; // Construction and identification DxilInst_Acos(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Acos); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Asin struct DxilInst_Asin { const llvm::Instruction *Instr; // Construction and identification DxilInst_Asin(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Asin); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Atan struct DxilInst_Atan { const llvm::Instruction *Instr; // Construction and identification DxilInst_Atan(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Atan); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Hcos struct DxilInst_Hcos { const llvm::Instruction *Instr; // Construction and identification DxilInst_Hcos(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Hcos); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Hsin struct DxilInst_Hsin { const llvm::Instruction *Instr; // Construction and identification DxilInst_Hsin(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Hsin); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Htan struct DxilInst_Htan { const llvm::Instruction *Instr; // Construction and identification DxilInst_Htan(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Htan); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Exp struct DxilInst_Exp { const llvm::Instruction *Instr; // Construction and identification DxilInst_Exp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Exp); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Frc struct DxilInst_Frc { const llvm::Instruction *Instr; // Construction and identification DxilInst_Frc(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Frc); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Log struct DxilInst_Log { const llvm::Instruction *Instr; // Construction and identification DxilInst_Log(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Log); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Sqrt struct DxilInst_Sqrt { const llvm::Instruction *Instr; // Construction and identification DxilInst_Sqrt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Sqrt); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Rsqrt struct DxilInst_Rsqrt { const llvm::Instruction *Instr; // Construction and identification DxilInst_Rsqrt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Rsqrt); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Round_ne struct DxilInst_Round_ne { const llvm::Instruction *Instr; // Construction and identification DxilInst_Round_ne(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Round_ne); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Round_ni struct DxilInst_Round_ni { const llvm::Instruction *Instr; // Construction and identification DxilInst_Round_ni(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Round_ni); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Round_pi struct DxilInst_Round_pi { const llvm::Instruction *Instr; // Construction and identification DxilInst_Round_pi(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Round_pi); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Round_z struct DxilInst_Round_z { const llvm::Instruction *Instr; // Construction and identification DxilInst_Round_z(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Round_z); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the reverse bit pattern of the input value struct DxilInst_Bfrev { const llvm::Instruction *Instr; // Construction and identification DxilInst_Bfrev(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Bfrev); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the Countbits struct DxilInst_Countbits { const llvm::Instruction *Instr; // Construction and identification DxilInst_Countbits(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Countbits); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the FirstbitLo struct DxilInst_FirstbitLo { const llvm::Instruction *Instr; // Construction and identification DxilInst_FirstbitLo(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FirstbitLo); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns src != 0? (BitWidth-1 - FirstbitHi) : -1 struct DxilInst_FirstbitHi { const llvm::Instruction *Instr; // Construction and identification DxilInst_FirstbitHi(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FirstbitHi); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns src != 0? (BitWidth-1 - FirstbitSHi) : -1 struct DxilInst_FirstbitSHi { const llvm::Instruction *Instr; // Construction and identification DxilInst_FirstbitSHi(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FirstbitSHi); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns a if a >= b, else b struct DxilInst_FMax { const llvm::Instruction *Instr; // Construction and identification DxilInst_FMax(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FMax); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns a if a < b, else b struct DxilInst_FMin { const llvm::Instruction *Instr; // Construction and identification DxilInst_FMin(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FMin); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the IMax of the input values struct DxilInst_IMax { const llvm::Instruction *Instr; // Construction and identification DxilInst_IMax(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IMax); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the IMin of the input values struct DxilInst_IMin { const llvm::Instruction *Instr; // Construction and identification DxilInst_IMin(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IMin); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the UMax of the input values struct DxilInst_UMax { const llvm::Instruction *Instr; // Construction and identification DxilInst_UMax(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::UMax); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the UMin of the input values struct DxilInst_UMin { const llvm::Instruction *Instr; // Construction and identification DxilInst_UMin(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::UMin); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the IMul of the input values struct DxilInst_IMul { const llvm::Instruction *Instr; // Construction and identification DxilInst_IMul(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IMul); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the UMul of the input values struct DxilInst_UMul { const llvm::Instruction *Instr; // Construction and identification DxilInst_UMul(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::UMul); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the UDiv of the input values struct DxilInst_UDiv { const llvm::Instruction *Instr; // Construction and identification DxilInst_UDiv(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::UDiv); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the UAddc of the input values struct DxilInst_UAddc { const llvm::Instruction *Instr; // Construction and identification DxilInst_UAddc(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::UAddc); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction returns the USubb of the input values struct DxilInst_USubb { const llvm::Instruction *Instr; // Construction and identification DxilInst_USubb(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::USubb); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } }; /// This instruction performs a fused multiply add (FMA) of the form a * b + c struct DxilInst_FMad { const llvm::Instruction *Instr; // Construction and identification DxilInst_FMad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FMad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } llvm::Value *get_c() const { return Instr->getOperand(3); } }; /// This instruction performs a fused multiply add (FMA) of the form a * b + c struct DxilInst_Fma { const llvm::Instruction *Instr; // Construction and identification DxilInst_Fma(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Fma); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } llvm::Value *get_c() const { return Instr->getOperand(3); } }; /// This instruction performs an integral IMad struct DxilInst_IMad { const llvm::Instruction *Instr; // Construction and identification DxilInst_IMad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::IMad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } llvm::Value *get_c() const { return Instr->getOperand(3); } }; /// This instruction performs an integral UMad struct DxilInst_UMad { const llvm::Instruction *Instr; // Construction and identification DxilInst_UMad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::UMad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } llvm::Value *get_c() const { return Instr->getOperand(3); } }; /// This instruction performs an integral Msad struct DxilInst_Msad { const llvm::Instruction *Instr; // Construction and identification DxilInst_Msad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Msad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } llvm::Value *get_c() const { return Instr->getOperand(3); } }; /// This instruction performs an integral Ibfe struct DxilInst_Ibfe { const llvm::Instruction *Instr; // Construction and identification DxilInst_Ibfe(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Ibfe); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } llvm::Value *get_c() const { return Instr->getOperand(3); } }; /// This instruction performs an integral Ubfe struct DxilInst_Ubfe { const llvm::Instruction *Instr; // Construction and identification DxilInst_Ubfe(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Ubfe); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_a() const { return Instr->getOperand(1); } llvm::Value *get_b() const { return Instr->getOperand(2); } llvm::Value *get_c() const { return Instr->getOperand(3); } }; /// This instruction given a bit range from the LSB of a number, places that number of bits in another number at any offset struct DxilInst_Bfi { const llvm::Instruction *Instr; // Construction and identification DxilInst_Bfi(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Bfi); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_width() const { return Instr->getOperand(1); } llvm::Value *get_offset() const { return Instr->getOperand(2); } llvm::Value *get_value() const { return Instr->getOperand(3); } llvm::Value *get_replaceCount() const { return Instr->getOperand(4); } }; /// This instruction two-dimensional vector dot-product struct DxilInst_Dot2 { const llvm::Instruction *Instr; // Construction and identification DxilInst_Dot2(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Dot2); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_ax() const { return Instr->getOperand(1); } llvm::Value *get_ay() const { return Instr->getOperand(2); } llvm::Value *get_bx() const { return Instr->getOperand(3); } llvm::Value *get_by() const { return Instr->getOperand(4); } }; /// This instruction three-dimensional vector dot-product struct DxilInst_Dot3 { const llvm::Instruction *Instr; // Construction and identification DxilInst_Dot3(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Dot3); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (7 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_ax() const { return Instr->getOperand(1); } llvm::Value *get_ay() const { return Instr->getOperand(2); } llvm::Value *get_az() const { return Instr->getOperand(3); } llvm::Value *get_bx() const { return Instr->getOperand(4); } llvm::Value *get_by() const { return Instr->getOperand(5); } llvm::Value *get_bz() const { return Instr->getOperand(6); } }; /// This instruction four-dimensional vector dot-product struct DxilInst_Dot4 { const llvm::Instruction *Instr; // Construction and identification DxilInst_Dot4(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Dot4); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (9 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_ax() const { return Instr->getOperand(1); } llvm::Value *get_ay() const { return Instr->getOperand(2); } llvm::Value *get_az() const { return Instr->getOperand(3); } llvm::Value *get_aw() const { return Instr->getOperand(4); } llvm::Value *get_bx() const { return Instr->getOperand(5); } llvm::Value *get_by() const { return Instr->getOperand(6); } llvm::Value *get_bz() const { return Instr->getOperand(7); } llvm::Value *get_bw() const { return Instr->getOperand(8); } }; /// This instruction creates the handle to a resource struct DxilInst_CreateHandle { const llvm::Instruction *Instr; // Construction and identification DxilInst_CreateHandle(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::CreateHandle); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_resourceClass() const { return Instr->getOperand(1); } int8_t get_resourceClass_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(1))->getZExtValue()); } llvm::Value *get_rangeId() const { return Instr->getOperand(2); } llvm::Value *get_index() const { return Instr->getOperand(3); } llvm::Value *get_nonUniformIndex() const { return Instr->getOperand(4); } bool get_nonUniformIndex_val() const { return (bool)(llvm::dyn_cast(Instr->getOperand(4))->getZExtValue()); } }; /// This instruction loads a value from a constant buffer resource struct DxilInst_CBufferLoad { const llvm::Instruction *Instr; // Construction and identification DxilInst_CBufferLoad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::CBufferLoad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_handle() const { return Instr->getOperand(1); } llvm::Value *get_byteOffset() const { return Instr->getOperand(2); } llvm::Value *get_alignment() const { return Instr->getOperand(3); } uint32_t get_alignment_val() const { return (uint32_t)(llvm::dyn_cast(Instr->getOperand(3))->getZExtValue()); } }; /// This instruction loads a value from a constant buffer resource struct DxilInst_CBufferLoadLegacy { const llvm::Instruction *Instr; // Construction and identification DxilInst_CBufferLoadLegacy(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::CBufferLoadLegacy); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_handle() const { return Instr->getOperand(1); } llvm::Value *get_regIndex() const { return Instr->getOperand(2); } }; /// This instruction samples a texture struct DxilInst_Sample { const llvm::Instruction *Instr; // Construction and identification DxilInst_Sample(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Sample); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (11 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_offset2() const { return Instr->getOperand(9); } llvm::Value *get_clamp() const { return Instr->getOperand(10); } }; /// This instruction samples a texture after applying the input bias to the mipmap level struct DxilInst_SampleBias { const llvm::Instruction *Instr; // Construction and identification DxilInst_SampleBias(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::SampleBias); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (12 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_offset2() const { return Instr->getOperand(9); } llvm::Value *get_bias() const { return Instr->getOperand(10); } llvm::Value *get_clamp() const { return Instr->getOperand(11); } }; /// This instruction samples a texture using a mipmap-level offset struct DxilInst_SampleLevel { const llvm::Instruction *Instr; // Construction and identification DxilInst_SampleLevel(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::SampleLevel); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (11 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_offset2() const { return Instr->getOperand(9); } llvm::Value *get_LOD() const { return Instr->getOperand(10); } }; /// This instruction samples a texture using a gradient to influence the way the sample location is calculated struct DxilInst_SampleGrad { const llvm::Instruction *Instr; // Construction and identification DxilInst_SampleGrad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::SampleGrad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (17 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_offset2() const { return Instr->getOperand(9); } llvm::Value *get_ddx0() const { return Instr->getOperand(10); } llvm::Value *get_ddx1() const { return Instr->getOperand(11); } llvm::Value *get_ddx2() const { return Instr->getOperand(12); } llvm::Value *get_ddy0() const { return Instr->getOperand(13); } llvm::Value *get_ddy1() const { return Instr->getOperand(14); } llvm::Value *get_ddy2() const { return Instr->getOperand(15); } llvm::Value *get_clamp() const { return Instr->getOperand(16); } }; /// This instruction samples a texture and compares a single component against the specified comparison value struct DxilInst_SampleCmp { const llvm::Instruction *Instr; // Construction and identification DxilInst_SampleCmp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::SampleCmp); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (12 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_offset2() const { return Instr->getOperand(9); } llvm::Value *get_compareValue() const { return Instr->getOperand(10); } llvm::Value *get_clamp() const { return Instr->getOperand(11); } }; /// This instruction samples a texture and compares a single component against the specified comparison value struct DxilInst_SampleCmpLevelZero { const llvm::Instruction *Instr; // Construction and identification DxilInst_SampleCmpLevelZero(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::SampleCmpLevelZero); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (11 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_offset2() const { return Instr->getOperand(9); } llvm::Value *get_compareValue() const { return Instr->getOperand(10); } }; /// This instruction reads texel data without any filtering or sampling struct DxilInst_TextureLoad { const llvm::Instruction *Instr; // Construction and identification DxilInst_TextureLoad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::TextureLoad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (9 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_mipLevelOrSampleCount() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_offset0() const { return Instr->getOperand(6); } llvm::Value *get_offset1() const { return Instr->getOperand(7); } llvm::Value *get_offset2() const { return Instr->getOperand(8); } }; /// This instruction reads texel data without any filtering or sampling struct DxilInst_TextureStore { const llvm::Instruction *Instr; // Construction and identification DxilInst_TextureStore(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::TextureStore); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (10 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_coord0() const { return Instr->getOperand(2); } llvm::Value *get_coord1() const { return Instr->getOperand(3); } llvm::Value *get_coord2() const { return Instr->getOperand(4); } llvm::Value *get_value0() const { return Instr->getOperand(5); } llvm::Value *get_value1() const { return Instr->getOperand(6); } llvm::Value *get_value2() const { return Instr->getOperand(7); } llvm::Value *get_value3() const { return Instr->getOperand(8); } llvm::Value *get_mask() const { return Instr->getOperand(9); } }; /// This instruction reads from a TypedBuffer struct DxilInst_BufferLoad { const llvm::Instruction *Instr; // Construction and identification DxilInst_BufferLoad(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BufferLoad); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_index() const { return Instr->getOperand(2); } llvm::Value *get_wot() const { return Instr->getOperand(3); } }; /// This instruction writes to a RWTypedBuffer struct DxilInst_BufferStore { const llvm::Instruction *Instr; // Construction and identification DxilInst_BufferStore(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BufferStore); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (9 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_uav() const { return Instr->getOperand(1); } llvm::Value *get_coord0() const { return Instr->getOperand(2); } llvm::Value *get_coord1() const { return Instr->getOperand(3); } llvm::Value *get_value0() const { return Instr->getOperand(4); } llvm::Value *get_value1() const { return Instr->getOperand(5); } llvm::Value *get_value2() const { return Instr->getOperand(6); } llvm::Value *get_value3() const { return Instr->getOperand(7); } llvm::Value *get_mask() const { return Instr->getOperand(8); } }; /// This instruction atomically increments/decrements the hidden 32-bit counter stored with a Count or Append UAV struct DxilInst_BufferUpdateCounter { const llvm::Instruction *Instr; // Construction and identification DxilInst_BufferUpdateCounter(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BufferUpdateCounter); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_uav() const { return Instr->getOperand(1); } llvm::Value *get_inc() const { return Instr->getOperand(2); } }; /// This instruction determines whether all values from a Sample, Gather, or Load operation accessed mapped tiles in a tiled resource struct DxilInst_CheckAccessFullyMapped { const llvm::Instruction *Instr; // Construction and identification DxilInst_CheckAccessFullyMapped(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::CheckAccessFullyMapped); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_status() const { return Instr->getOperand(1); } }; /// This instruction gets texture size information struct DxilInst_GetDimensions { const llvm::Instruction *Instr; // Construction and identification DxilInst_GetDimensions(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::GetDimensions); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_handle() const { return Instr->getOperand(1); } llvm::Value *get_mipLevel() const { return Instr->getOperand(2); } }; /// This instruction gathers the four texels that would be used in a bi-linear filtering operation struct DxilInst_TextureGather { const llvm::Instruction *Instr; // Construction and identification DxilInst_TextureGather(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::TextureGather); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (10 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_channel() const { return Instr->getOperand(9); } }; /// This instruction same as TextureGather, except this instrution performs comparison on texels, similar to SampleCmp struct DxilInst_TextureGatherCmp { const llvm::Instruction *Instr; // Construction and identification DxilInst_TextureGatherCmp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::TextureGatherCmp); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (11 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_coord3() const { return Instr->getOperand(6); } llvm::Value *get_offset0() const { return Instr->getOperand(7); } llvm::Value *get_offset1() const { return Instr->getOperand(8); } llvm::Value *get_channel() const { return Instr->getOperand(9); } llvm::Value *get_compareVale() const { return Instr->getOperand(10); } }; /// This instruction gets the position of the specified sample struct DxilInst_Texture2DMSGetSamplePosition { const llvm::Instruction *Instr; // Construction and identification DxilInst_Texture2DMSGetSamplePosition(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Texture2DMSGetSamplePosition); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_srv() const { return Instr->getOperand(1); } llvm::Value *get_index() const { return Instr->getOperand(2); } }; /// This instruction gets the position of the specified sample struct DxilInst_RenderTargetGetSamplePosition { const llvm::Instruction *Instr; // Construction and identification DxilInst_RenderTargetGetSamplePosition(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::RenderTargetGetSamplePosition); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_index() const { return Instr->getOperand(1); } }; /// This instruction gets the number of samples for a render target struct DxilInst_RenderTargetGetSampleCount { const llvm::Instruction *Instr; // Construction and identification DxilInst_RenderTargetGetSampleCount(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::RenderTargetGetSampleCount); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction performs an atomic operation on two operands struct DxilInst_AtomicBinOp { const llvm::Instruction *Instr; // Construction and identification DxilInst_AtomicBinOp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::AtomicBinOp); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (7 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_handle() const { return Instr->getOperand(1); } llvm::Value *get_atomicOp() const { return Instr->getOperand(2); } llvm::Value *get_offset0() const { return Instr->getOperand(3); } llvm::Value *get_offset1() const { return Instr->getOperand(4); } llvm::Value *get_offset2() const { return Instr->getOperand(5); } llvm::Value *get_newValue() const { return Instr->getOperand(6); } }; /// This instruction atomic compare and exchange to memory struct DxilInst_AtomicCompareExchange { const llvm::Instruction *Instr; // Construction and identification DxilInst_AtomicCompareExchange(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::AtomicCompareExchange); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (7 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_handle() const { return Instr->getOperand(1); } llvm::Value *get_offset0() const { return Instr->getOperand(2); } llvm::Value *get_offset1() const { return Instr->getOperand(3); } llvm::Value *get_offset2() const { return Instr->getOperand(4); } llvm::Value *get_compareValue() const { return Instr->getOperand(5); } llvm::Value *get_newValue() const { return Instr->getOperand(6); } }; /// This instruction inserts a memory barrier in the shader struct DxilInst_Barrier { const llvm::Instruction *Instr; // Construction and identification DxilInst_Barrier(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Barrier); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_barrierMode() const { return Instr->getOperand(1); } int32_t get_barrierMode_val() const { return (int32_t)(llvm::dyn_cast(Instr->getOperand(1))->getZExtValue()); } }; /// This instruction calculates the level of detail struct DxilInst_CalculateLOD { const llvm::Instruction *Instr; // Construction and identification DxilInst_CalculateLOD(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::CalculateLOD); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (7 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_handle() const { return Instr->getOperand(1); } llvm::Value *get_sampler() const { return Instr->getOperand(2); } llvm::Value *get_coord0() const { return Instr->getOperand(3); } llvm::Value *get_coord1() const { return Instr->getOperand(4); } llvm::Value *get_coord2() const { return Instr->getOperand(5); } llvm::Value *get_clamped() const { return Instr->getOperand(6); } }; /// This instruction discard the current pixel struct DxilInst_Discard { const llvm::Instruction *Instr; // Construction and identification DxilInst_Discard(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Discard); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_condition() const { return Instr->getOperand(1); } }; /// This instruction computes the rate of change of components per stamp struct DxilInst_DerivCoarseX { const llvm::Instruction *Instr; // Construction and identification DxilInst_DerivCoarseX(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::DerivCoarseX); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction computes the rate of change of components per stamp struct DxilInst_DerivCoarseY { const llvm::Instruction *Instr; // Construction and identification DxilInst_DerivCoarseY(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::DerivCoarseY); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction computes the rate of change of components per pixel struct DxilInst_DerivFineX { const llvm::Instruction *Instr; // Construction and identification DxilInst_DerivFineX(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::DerivFineX); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction computes the rate of change of components per pixel struct DxilInst_DerivFineY { const llvm::Instruction *Instr; // Construction and identification DxilInst_DerivFineY(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::DerivFineY); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction evaluates an input attribute at pixel center with an offset struct DxilInst_EvalSnapped { const llvm::Instruction *Instr; // Construction and identification DxilInst_EvalSnapped(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::EvalSnapped); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (6 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_inputSigId() const { return Instr->getOperand(1); } llvm::Value *get_inputRowIndex() const { return Instr->getOperand(2); } llvm::Value *get_inputColIndex() const { return Instr->getOperand(3); } llvm::Value *get_offsetX() const { return Instr->getOperand(4); } llvm::Value *get_offsetY() const { return Instr->getOperand(5); } }; /// This instruction evaluates an input attribute at a sample location struct DxilInst_EvalSampleIndex { const llvm::Instruction *Instr; // Construction and identification DxilInst_EvalSampleIndex(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::EvalSampleIndex); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_inputSigId() const { return Instr->getOperand(1); } llvm::Value *get_inputRowIndex() const { return Instr->getOperand(2); } llvm::Value *get_inputColIndex() const { return Instr->getOperand(3); } llvm::Value *get_sampleIndex() const { return Instr->getOperand(4); } }; /// This instruction evaluates an input attribute at pixel center struct DxilInst_EvalCentroid { const llvm::Instruction *Instr; // Construction and identification DxilInst_EvalCentroid(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::EvalCentroid); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_inputSigId() const { return Instr->getOperand(1); } llvm::Value *get_inputRowIndex() const { return Instr->getOperand(2); } llvm::Value *get_inputColIndex() const { return Instr->getOperand(3); } }; /// This instruction returns the sample index in a sample-frequency pixel shader struct DxilInst_SampleIndex { const llvm::Instruction *Instr; // Construction and identification DxilInst_SampleIndex(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::SampleIndex); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction returns the coverage mask input in a pixel shader struct DxilInst_Coverage { const llvm::Instruction *Instr; // Construction and identification DxilInst_Coverage(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::Coverage); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction returns underestimated coverage input from conservative rasterization in a pixel shader struct DxilInst_InnerCoverage { const llvm::Instruction *Instr; // Construction and identification DxilInst_InnerCoverage(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::InnerCoverage); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction reads the thread ID struct DxilInst_ThreadId { const llvm::Instruction *Instr; // Construction and identification DxilInst_ThreadId(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::ThreadId); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_component() const { return Instr->getOperand(1); } }; /// This instruction reads the group ID (SV_GroupID) struct DxilInst_GroupId { const llvm::Instruction *Instr; // Construction and identification DxilInst_GroupId(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::GroupId); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_component() const { return Instr->getOperand(1); } }; /// This instruction reads the thread ID within the group (SV_GroupThreadID) struct DxilInst_ThreadIdInGroup { const llvm::Instruction *Instr; // Construction and identification DxilInst_ThreadIdInGroup(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::ThreadIdInGroup); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_component() const { return Instr->getOperand(1); } }; /// This instruction provides a flattened index for a given thread within a given group (SV_GroupIndex) struct DxilInst_FlattenedThreadIdInGroup { const llvm::Instruction *Instr; // Construction and identification DxilInst_FlattenedThreadIdInGroup(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::FlattenedThreadIdInGroup); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction emits a vertex to a given stream struct DxilInst_EmitStream { const llvm::Instruction *Instr; // Construction and identification DxilInst_EmitStream(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::EmitStream); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_streamId() const { return Instr->getOperand(1); } }; /// This instruction completes the current primitive topology at the specified stream struct DxilInst_CutStream { const llvm::Instruction *Instr; // Construction and identification DxilInst_CutStream(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::CutStream); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_streamId() const { return Instr->getOperand(1); } }; /// This instruction equivalent to an EmitStream followed by a CutStream struct DxilInst_EmitThenCutStream { const llvm::Instruction *Instr; // Construction and identification DxilInst_EmitThenCutStream(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::EmitThenCutStream); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_streamId() const { return Instr->getOperand(1); } }; /// This instruction GSInstanceID struct DxilInst_GSInstanceID { const llvm::Instruction *Instr; // Construction and identification DxilInst_GSInstanceID(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::GSInstanceID); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction creates a double value struct DxilInst_MakeDouble { const llvm::Instruction *Instr; // Construction and identification DxilInst_MakeDouble(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::MakeDouble); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_lo() const { return Instr->getOperand(1); } llvm::Value *get_hi() const { return Instr->getOperand(2); } }; /// This instruction splits a double into low and high parts struct DxilInst_SplitDouble { const llvm::Instruction *Instr; // Construction and identification DxilInst_SplitDouble(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::SplitDouble); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction LoadOutputControlPoint struct DxilInst_LoadOutputControlPoint { const llvm::Instruction *Instr; // Construction and identification DxilInst_LoadOutputControlPoint(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LoadOutputControlPoint); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_inputSigId() const { return Instr->getOperand(1); } llvm::Value *get_row() const { return Instr->getOperand(2); } llvm::Value *get_col() const { return Instr->getOperand(3); } llvm::Value *get_index() const { return Instr->getOperand(4); } }; /// This instruction LoadPatchConstant struct DxilInst_LoadPatchConstant { const llvm::Instruction *Instr; // Construction and identification DxilInst_LoadPatchConstant(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LoadPatchConstant); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_inputSigId() const { return Instr->getOperand(1); } llvm::Value *get_row() const { return Instr->getOperand(2); } llvm::Value *get_col() const { return Instr->getOperand(3); } }; /// This instruction DomainLocation struct DxilInst_DomainLocation { const llvm::Instruction *Instr; // Construction and identification DxilInst_DomainLocation(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::DomainLocation); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_component() const { return Instr->getOperand(1); } int8_t get_component_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(1))->getZExtValue()); } }; /// This instruction StorePatchConstant struct DxilInst_StorePatchConstant { const llvm::Instruction *Instr; // Construction and identification DxilInst_StorePatchConstant(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::StorePatchConstant); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (5 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_outputSigID() const { return Instr->getOperand(1); } llvm::Value *get_row() const { return Instr->getOperand(2); } llvm::Value *get_col() const { return Instr->getOperand(3); } llvm::Value *get_value() const { return Instr->getOperand(4); } }; /// This instruction OutputControlPointID struct DxilInst_OutputControlPointID { const llvm::Instruction *Instr; // Construction and identification DxilInst_OutputControlPointID(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::OutputControlPointID); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction PrimitiveID struct DxilInst_PrimitiveID { const llvm::Instruction *Instr; // Construction and identification DxilInst_PrimitiveID(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::PrimitiveID); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction CycleCounterLegacy struct DxilInst_CycleCounterLegacy { const llvm::Instruction *Instr; // Construction and identification DxilInst_CycleCounterLegacy(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::CycleCounterLegacy); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction returns 1 for the first lane in the wave struct DxilInst_WaveIsFirstLane { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveIsFirstLane(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveIsFirstLane); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction returns the index of the current lane in the wave struct DxilInst_WaveGetLaneIndex { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveGetLaneIndex(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveGetLaneIndex); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction returns the number of lanes in the wave struct DxilInst_WaveGetLaneCount { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveGetLaneCount(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveGetLaneCount); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (1 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } }; /// This instruction returns 1 if any of the lane evaluates the value to true struct DxilInst_WaveAnyTrue { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveAnyTrue(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveAnyTrue); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_cond() const { return Instr->getOperand(1); } }; /// This instruction returns 1 if all the lanes evaluate the value to true struct DxilInst_WaveAllTrue { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveAllTrue(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveAllTrue); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_cond() const { return Instr->getOperand(1); } }; /// This instruction returns 1 if all the lanes have the same value struct DxilInst_WaveActiveAllEqual { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveActiveAllEqual(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveActiveAllEqual); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns a struct with a bit set for each lane where the condition is true struct DxilInst_WaveActiveBallot { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveActiveBallot(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveActiveBallot); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_cond() const { return Instr->getOperand(1); } }; /// This instruction returns the value from the specified lane struct DxilInst_WaveReadLaneAt { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveReadLaneAt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveReadLaneAt); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } llvm::Value *get_lane() const { return Instr->getOperand(2); } }; /// This instruction returns the value from the first lane struct DxilInst_WaveReadLaneFirst { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveReadLaneFirst(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveReadLaneFirst); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the result the operation across waves struct DxilInst_WaveActiveOp { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveActiveOp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveActiveOp); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } llvm::Value *get_op() const { return Instr->getOperand(2); } int8_t get_op_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(2))->getZExtValue()); } llvm::Value *get_sop() const { return Instr->getOperand(3); } int8_t get_sop_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(3))->getZExtValue()); } }; /// This instruction returns the result of the operation across all lanes struct DxilInst_WaveActiveBit { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveActiveBit(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveActiveBit); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } llvm::Value *get_op() const { return Instr->getOperand(2); } int8_t get_op_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(2))->getZExtValue()); } }; /// This instruction returns the result of the operation on prior lanes struct DxilInst_WavePrefixOp { const llvm::Instruction *Instr; // Construction and identification DxilInst_WavePrefixOp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WavePrefixOp); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (4 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } llvm::Value *get_op() const { return Instr->getOperand(2); } int8_t get_op_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(2))->getZExtValue()); } llvm::Value *get_sop() const { return Instr->getOperand(3); } int8_t get_sop_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(3))->getZExtValue()); } }; /// This instruction reads from a lane in the quad struct DxilInst_QuadReadLaneAt { const llvm::Instruction *Instr; // Construction and identification DxilInst_QuadReadLaneAt(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::QuadReadLaneAt); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } llvm::Value *get_quadLane() const { return Instr->getOperand(2); } uint32_t get_quadLane_val() const { return (uint32_t)(llvm::dyn_cast(Instr->getOperand(2))->getZExtValue()); } }; /// This instruction returns the result of a quad-level operation struct DxilInst_QuadOp { const llvm::Instruction *Instr; // Construction and identification DxilInst_QuadOp(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::QuadOp); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (3 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } llvm::Value *get_op() const { return Instr->getOperand(2); } int8_t get_op_val() const { return (int8_t)(llvm::dyn_cast(Instr->getOperand(2))->getZExtValue()); } }; /// This instruction bitcast between different sizes struct DxilInst_BitcastI16toF16 { const llvm::Instruction *Instr; // Construction and identification DxilInst_BitcastI16toF16(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BitcastI16toF16); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction bitcast between different sizes struct DxilInst_BitcastF16toI16 { const llvm::Instruction *Instr; // Construction and identification DxilInst_BitcastF16toI16(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BitcastF16toI16); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction bitcast between different sizes struct DxilInst_BitcastI32toF32 { const llvm::Instruction *Instr; // Construction and identification DxilInst_BitcastI32toF32(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BitcastI32toF32); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction bitcast between different sizes struct DxilInst_BitcastF32toI32 { const llvm::Instruction *Instr; // Construction and identification DxilInst_BitcastF32toI32(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BitcastF32toI32); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction bitcast between different sizes struct DxilInst_BitcastI64toF64 { const llvm::Instruction *Instr; // Construction and identification DxilInst_BitcastI64toF64(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BitcastI64toF64); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction bitcast between different sizes struct DxilInst_BitcastF64toI64 { const llvm::Instruction *Instr; // Construction and identification DxilInst_BitcastF64toI64(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::BitcastF64toI64); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction legacy fuction to convert float (f32) to half (f16) (this is not related to min-precision) struct DxilInst_LegacyF32ToF16 { const llvm::Instruction *Instr; // Construction and identification DxilInst_LegacyF32ToF16(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LegacyF32ToF16); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction legacy fuction to convert half (f16) to float (f32) (this is not related to min-precision) struct DxilInst_LegacyF16ToF32 { const llvm::Instruction *Instr; // Construction and identification DxilInst_LegacyF16ToF32(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LegacyF16ToF32); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction legacy fuction to convert double to float struct DxilInst_LegacyDoubleToFloat { const llvm::Instruction *Instr; // Construction and identification DxilInst_LegacyDoubleToFloat(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LegacyDoubleToFloat); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction legacy fuction to convert double to int32 struct DxilInst_LegacyDoubleToSInt32 { const llvm::Instruction *Instr; // Construction and identification DxilInst_LegacyDoubleToSInt32(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LegacyDoubleToSInt32); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction legacy fuction to convert double to uint32 struct DxilInst_LegacyDoubleToUInt32 { const llvm::Instruction *Instr; // Construction and identification DxilInst_LegacyDoubleToUInt32(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::LegacyDoubleToUInt32); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the count of bits set to 1 across the wave struct DxilInst_WaveAllBitCount { const llvm::Instruction *Instr; // Construction and identification DxilInst_WaveAllBitCount(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WaveAllBitCount); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; /// This instruction returns the count of bits set to 1 on prior lanes struct DxilInst_WavePrefixBitCount { const llvm::Instruction *Instr; // Construction and identification DxilInst_WavePrefixBitCount(llvm::Instruction *pInstr) : Instr(pInstr) {} operator bool() const { return hlsl::OP::IsDxilOpFuncCallInst(Instr, hlsl::OP::OpCode::WavePrefixBitCount); } // Validation support bool isAllowed() const { return true; } bool isArgumentListValid() const { if (2 != llvm::dyn_cast(Instr)->getNumArgOperands()) return false; return true; } // Accessors llvm::Value *get_value() const { return Instr->getOperand(1); } }; // INSTR-HELPER:END } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilInterpolationMode.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilInterpolationMode.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL interpolation mode. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "DxilConstants.h" namespace hlsl { /// Use this class to represent signature element interpolation mode. class InterpolationMode { public: using Kind = DXIL::InterpolationMode; InterpolationMode(); InterpolationMode(Kind Kind); InterpolationMode(unsigned long long Kind); InterpolationMode(bool bNoInterpolation, bool bLinear, bool bNoperspective, bool bCentroid, bool bSample); InterpolationMode &operator=(const InterpolationMode &o); bool operator==(const InterpolationMode &o) const; bool IsValid() const { return m_Kind >= Kind::Undefined && m_Kind < Kind::Invalid; } bool IsUndefined() const { return m_Kind == Kind::Undefined; } bool IsConstant() const { return m_Kind == Kind::Constant; } bool IsLinear() const { return m_Kind == Kind::Linear; } bool IsLinearCentroid() const { return m_Kind == Kind::LinearCentroid; } bool IsLinearNoperspective() const { return m_Kind == Kind::LinearNoperspective; } bool IsLinearNoperspectiveCentroid() const { return m_Kind == Kind::LinearNoperspectiveCentroid; } bool IsLinearSample() const { return m_Kind == Kind::LinearSample; } bool IsLinearNoperspectiveSample() const { return m_Kind == Kind::LinearNoperspectiveSample; } bool IsAnyLinear() const; bool IsAnyNoPerspective() const; bool IsAnyCentroid() const; bool IsAnySample() const; Kind GetKind() const { return m_Kind; } const char *GetName() const; private: Kind m_Kind; }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilMetadataHelper.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilMetadataHelper.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Helper to serialize/desialize metadata for DxilModule. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilConstants.h" #include #include #include namespace llvm { class LLVMContext; class Module; class Function; class Value; class MDOperand; class Metadata; class ConstantAsMetadata; class MDTuple; class MDNode; class NamedMDNode; class GlobalVariable; }; namespace hlsl { class ShaderModel; class DxilSignature; class DxilSignatureElement; class DxilModule; class DxilResourceBase; class DxilCBuffer; class DxilResource; class DxilSampler; class DxilTypeSystem; class DxilStructAnnotation; class DxilFieldAnnotation; class DxilFunctionAnnotation; class DxilParameterAnnotation; class RootSignatureHandle; /// Use this class to manipulate DXIL-spcific metadata. // In our code, only DxilModule and HLModule should use this class. class DxilMDHelper { public: // // Constants for metadata names and field positions. // // Dxil version. static const char kDxilVersionMDName[]; static const unsigned kDxilVersionNumFields = 2; static const unsigned kDxilVersionMajorIdx = 0; // DXIL version major. static const unsigned kDxilVersionMinorIdx = 1; // DXIL version minor. // Shader model. static const char kDxilShaderModelMDName[]; static const unsigned kDxilShaderModelNumFields = 3; static const unsigned kDxilShaderModelTypeIdx = 0; // Shader type (vs,ps,cs,gs,ds,hs). static const unsigned kDxilShaderModelMajorIdx = 1; // Shader model major. static const unsigned kDxilShaderModelMinorIdx = 2; // Shader model minor. // Entry points. static const char kDxilEntryPointsMDName[]; // Root Signature, for intermediate use, not valid in final DXIL module. static const char kDxilRootSignatureMDName[]; static const unsigned kDxilEntryPointNumFields = 5; static const unsigned kDxilEntryPointFunction = 0; // Entry point function symbol. static const unsigned kDxilEntryPointName = 1; // Entry point unmangled name. static const unsigned kDxilEntryPointSignatures = 2; // Entry point signature tuple. static const unsigned kDxilEntryPointResources = 3; // Entry point resource tuple. static const unsigned kDxilEntryPointProperties = 4; // Entry point properties tuple. // Signatures. static const unsigned kDxilNumSignatureFields = 3; static const unsigned kDxilInputSignature = 0; // Shader input signature. static const unsigned kDxilOutputSignature = 1; // Shader output signature. static const unsigned kDxilPatchConstantSignature = 2; // Shader patch constant (PC) signature. // Signature Element. static const unsigned kDxilSignatureElementNumFields = 11; static const unsigned kDxilSignatureElementID = 0; // Unique element ID. static const unsigned kDxilSignatureElementName = 1; // Element name. static const unsigned kDxilSignatureElementType = 2; // Element type. static const unsigned kDxilSignatureElementSystemValue = 3; // Effective system value. static const unsigned kDxilSignatureElementIndexVector = 4; // Semantic index vector. static const unsigned kDxilSignatureElementInterpMode = 5; // Interpolation mode. static const unsigned kDxilSignatureElementRows = 6; // Number of rows. static const unsigned kDxilSignatureElementCols = 7; // Number of columns. static const unsigned kDxilSignatureElementStartRow = 8; // Element packing start row. static const unsigned kDxilSignatureElementStartCol = 9; // Element packing start column. static const unsigned kDxilSignatureElementNameValueList = 10; // Name-value list for extended properties. // Signature Element Extended Properties. static const unsigned kDxilSignatureElementOutputStreamTag = 0; static const unsigned kHLSignatureElementGlobalSymbolTag = 1; // Resources. static const char kDxilResourcesMDName[]; static const unsigned kDxilNumResourceFields = 4; static const unsigned kDxilResourceSRVs = 0; static const unsigned kDxilResourceUAVs = 1; static const unsigned kDxilResourceCBuffers = 2; static const unsigned kDxilResourceSamplers = 3; // ResourceBase. static const unsigned kDxilResourceBaseNumFields = 6; static const unsigned kDxilResourceBaseID = 0; // Unique (per type) resource ID. static const unsigned kDxilResourceBaseVariable = 1; // Resource global variable. static const unsigned kDxilResourceBaseName = 2; // Original (HLSL) name of the resource. static const unsigned kDxilResourceBaseSpaceID = 3; // Resource range space ID. static const unsigned kDxilResourceBaseLowerBound = 4; // Resource range lower bound. static const unsigned kDxilResourceBaseRangeSize = 5; // Resource range size. // SRV-specific. static const unsigned kDxilSRVNumFields = 9; static const unsigned kDxilSRVShape = 6; // SRV shape. static const unsigned kDxilSRVSampleCount = 7; // SRV sample count. static const unsigned kDxilSRVNameValueList = 8; // Name-value list for extended properties. // UAV-specific. static const unsigned kDxilUAVNumFields = 11; static const unsigned kDxilUAVShape = 6; // UAV shape. static const unsigned kDxilUAVGloballyCoherent = 7; // Globally-coherent UAV. static const unsigned kDxilUAVCounter = 8; // UAV with a counter. static const unsigned kDxilUAVRasterizerOrderedView = 9; // UAV that is a ROV. static const unsigned kDxilUAVNameValueList = 10; // Name-value list for extended properties. // CBuffer-specific. static const unsigned kDxilCBufferNumFields = 8; static const unsigned kDxilCBufferSizeInBytes = 6; // CBuffer size in bytes. static const unsigned kDxilCBufferNameValueList = 7; // Name-value list for extended properties. // CBuffer extended properties static const unsigned kHLCBufferIsTBufferTag = 0; // CBuffer is actually TBuffer, not yet converted to SRV. // Sampler-specific. static const unsigned kDxilSamplerNumFields = 8; static const unsigned kDxilSamplerType = 6; // Sampler type. static const unsigned kDxilSamplerNameValueList = 7; // Name-value list for extended properties. // Resource extended property tags. static const unsigned kDxilTypedBufferElementTypeTag = 0; static const unsigned kDxilStructuredBufferElementStrideTag = 1; // Type system. static const char kDxilTypeSystemMDName[]; static const char kDxilTypeSystemHelperVariablePrefix[]; static const unsigned kDxilTypeSystemStructTag = 0; static const unsigned kDxilTypeSystemFunctionTag = 1; static const unsigned kDxilFieldAnnotationSNormTag = 0; static const unsigned kDxilFieldAnnotationUNormTag = 1; static const unsigned kDxilFieldAnnotationMatrixTag = 2; static const unsigned kDxilFieldAnnotationCBufferOffsetTag = 3; static const unsigned kDxilFieldAnnotationSemanticStringTag = 4; static const unsigned kDxilFieldAnnotationInterpolationModeTag = 5; static const unsigned kDxilFieldAnnotationFieldNameTag = 6; static const unsigned kDxilFieldAnnotationCompTypeTag = 7; static const unsigned kDxilFieldAnnotationPreciseTag = 8; // Control flow hint. static const char kDxilControlFlowHintMDName[]; // Precise attribute. static const char kDxilPreciseAttributeMDName[]; // Validator version. static const char kDxilValidatorVersionMDName[]; // Extended shader property tags. static const unsigned kDxilShaderFlagsTag = 0; static const unsigned kDxilGSStateTag = 1; static const unsigned kDxilDSStateTag = 2; static const unsigned kDxilHSStateTag = 3; static const unsigned kDxilNumThreadsTag = 4; // GSState. static const unsigned kDxilGSStateNumFields = 5; static const unsigned kDxilGSStateInputPrimitive = 0; static const unsigned kDxilGSStateMaxVertexCount = 1; static const unsigned kDxilGSStateActiveStreamMask = 2; static const unsigned kDxilGSStateOutputStreamTopology = 3; static const unsigned kDxilGSStateGSInstanceCount = 4; // DSState. static const unsigned kDxilDSStateNumFields = 2; static const unsigned kDxilDSStateTessellatorDomain = 0; static const unsigned kDxilDSStateInputControlPointCount = 1; // HSState. static const unsigned kDxilHSStateNumFields = 7; static const unsigned kDxilHSStatePatchConstantFunction = 0; static const unsigned kDxilHSStateInputControlPointCount = 1; static const unsigned kDxilHSStateOutputControlPointCount = 2; static const unsigned kDxilHSStateTessellatorDomain = 3; static const unsigned kDxilHSStateTessellatorPartitioning = 4; static const unsigned kDxilHSStateTessellatorOutputPrimitive= 5; static const unsigned kDxilHSStateMaxTessellationFactor = 6; public: /// Use this class to manipulate metadata of DXIL or high-level DX IR specific fields in the record. class ExtraPropertyHelper { public: ExtraPropertyHelper(llvm::Module *pModule); virtual void EmitSRVProperties(const DxilResource &SRV, std::vector &MDVals) = 0; virtual void LoadSRVProperties(const llvm::MDOperand &MDO, DxilResource &SRV) = 0; virtual void EmitUAVProperties(const DxilResource &UAV, std::vector &MDVals) = 0; virtual void LoadUAVProperties(const llvm::MDOperand &MDO, DxilResource &UAV) = 0; virtual void EmitCBufferProperties(const DxilCBuffer &CB, std::vector &MDVals) = 0; virtual void LoadCBufferProperties(const llvm::MDOperand &MDO, DxilCBuffer &CB) = 0; virtual void EmitSamplerProperties(const DxilSampler &S, std::vector &MDVals) = 0; virtual void LoadSamplerProperties(const llvm::MDOperand &MDO, DxilSampler &S) = 0; virtual void EmitSignatureElementProperties(const DxilSignatureElement &SE, std::vector &MDVals) = 0; virtual void LoadSignatureElementProperties(const llvm::MDOperand &MDO, DxilSignatureElement &SE) = 0; protected: llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule; }; public: DxilMDHelper(llvm::Module *pModule, std::unique_ptr EPH); ~DxilMDHelper(); void SetShaderModel(const ShaderModel *pSM); const ShaderModel *GetShaderModel() const; // Dxil version. void EmitDxilVersion(unsigned Major, unsigned Minor); void LoadDxilVersion(unsigned &Major, unsigned &Minor); // Shader model. void EmitDxilShaderModel(const ShaderModel *pSM); void LoadDxilShaderModel(const ShaderModel *&pSM); // Entry points. void EmitDxilEntryPoints(std::vector &MDEntries); const llvm::NamedMDNode *GetDxilEntryPoints(); llvm::MDTuple *EmitDxilEntryPointTuple(llvm::Function *pFunc, const std::string &Name, llvm::MDTuple *pSignatures, llvm::MDTuple *pResources, llvm::MDTuple *pProperties); void GetDxilEntryPoint(const llvm::MDNode *MDO, llvm::Function *&pFunc, std::string &Name, const llvm::MDOperand *&pSignatures, const llvm::MDOperand *&pResources, const llvm::MDOperand *&pProperties); // Signatures. llvm::MDTuple *EmitDxilSignatures(const DxilSignature &InputSig, const DxilSignature &OutputSig, const DxilSignature &PCSig); void LoadDxilSignatures(const llvm::MDOperand &MDO, DxilSignature &InputSig, DxilSignature &OutputSig, DxilSignature &PCSig); llvm::MDTuple *EmitSignatureMetadata(const DxilSignature &Sig); void EmitRootSignature(RootSignatureHandle &RootSig); void LoadSignatureMetadata(const llvm::MDOperand &MDO, DxilSignature &Sig); llvm::MDTuple *EmitSignatureElement(const DxilSignatureElement &SE); void LoadSignatureElement(const llvm::MDOperand &MDO, DxilSignatureElement &SE); void LoadRootSignature(RootSignatureHandle &RootSig); // Resources. llvm::MDTuple *EmitDxilResourceTuple(llvm::MDTuple *pSRVs, llvm::MDTuple *pUAVs, llvm::MDTuple *pCBuffers, llvm::MDTuple *pSamplers); void GetDxilResources(const llvm::MDOperand &MDO, const llvm::MDTuple *&pSRVs, const llvm::MDTuple *&pUAVs, const llvm::MDTuple *&pCBuffers, const llvm::MDTuple *&pSamplers); void EmitDxilResourceBase(const DxilResourceBase &R, llvm::Metadata *ppMDVals[]); void LoadDxilResourceBase(const llvm::MDOperand &MDO, DxilResourceBase &R); llvm::MDTuple *EmitDxilSRV(const DxilResource &SRV); void LoadDxilSRV(const llvm::MDOperand &MDO, DxilResource &SRV); llvm::MDTuple *EmitDxilUAV(const DxilResource &UAV); void LoadDxilUAV(const llvm::MDOperand &MDO, DxilResource &UAV); llvm::MDTuple *EmitDxilCBuffer(const DxilCBuffer &CB); void LoadDxilCBuffer(const llvm::MDOperand &MDO, DxilCBuffer &CB); llvm::MDTuple *EmitDxilSampler(const DxilSampler &S); void LoadDxilSampler(const llvm::MDOperand &MDO, DxilSampler &S); // Type system. void EmitDxilTypeSystem(DxilTypeSystem &TypeSystem, std::vector &LLVMUsed); void LoadDxilTypeSystemNode(const llvm::MDTuple &MDT, DxilTypeSystem &TypeSystem); void LoadDxilTypeSystem(DxilTypeSystem &TypeSystem); llvm::Metadata *EmitDxilStructAnnotation(const DxilStructAnnotation &SA); void LoadDxilStructAnnotation(const llvm::MDOperand &MDO, DxilStructAnnotation &SA); llvm::Metadata *EmitDxilFieldAnnotation(const DxilFieldAnnotation &FA); void LoadDxilFieldAnnotation(const llvm::MDOperand &MDO, DxilFieldAnnotation &FA); llvm::Metadata *EmitDxilFunctionAnnotation(const DxilFunctionAnnotation &FA); void LoadDxilFunctionAnnotation(const llvm::MDOperand &MDO, DxilFunctionAnnotation &FA); llvm::Metadata *EmitDxilParamAnnotation(const DxilParameterAnnotation &PA); void LoadDxilParamAnnotation(const llvm::MDOperand &MDO, DxilParameterAnnotation &PA); // Control flow hints. static llvm::MDNode *EmitControlFlowHints(llvm::LLVMContext &Ctx, std::vector &hints); // Shader specific. llvm::MDTuple *EmitDxilGSState(DXIL::InputPrimitive Primitive, unsigned MaxVertexCount, unsigned ActiveStreamMask, DXIL::PrimitiveTopology StreamPrimitiveTopology, unsigned GSInstanceCount); void LoadDxilGSState(const llvm::MDOperand &MDO, DXIL::InputPrimitive &Primitive, unsigned &MaxVertexCount, unsigned &ActiveStreamMask, DXIL::PrimitiveTopology &StreamPrimitiveTopology, unsigned &GSInstanceCount); llvm::MDTuple *EmitDxilDSState(DXIL::TessellatorDomain Domain, unsigned InputControlPointCount); void LoadDxilDSState(const llvm::MDOperand &MDO, DXIL::TessellatorDomain &Domain, unsigned &InputControlPointCount); llvm::MDTuple *EmitDxilHSState(llvm::Function *pPatchConstantFunction, unsigned InputControlPointCount, unsigned OutputControlPointCount, DXIL::TessellatorDomain TessDomain, DXIL::TessellatorPartitioning TessPartitioning, DXIL::TessellatorOutputPrimitive TessOutputPrimitive, float MaxTessFactor); void LoadDxilHSState(const llvm::MDOperand &MDO, llvm::Function *&pPatchConstantFunction, unsigned &InputControlPointCount, unsigned &OutputControlPointCount, DXIL::TessellatorDomain &TessDomain, DXIL::TessellatorPartitioning &TessPartitioning, DXIL::TessellatorOutputPrimitive &TessOutputPrimitive, float &MaxTessFactor); // Utility functions. static bool IsKnownNamedMetaData(llvm::NamedMDNode &Node); static llvm::ConstantAsMetadata *Int32ToConstMD(int32_t v, llvm::LLVMContext &Ctx); llvm::ConstantAsMetadata *Int32ToConstMD(int32_t v); static llvm::ConstantAsMetadata *Uint32ToConstMD(unsigned v, llvm::LLVMContext &Ctx); llvm::ConstantAsMetadata *Uint32ToConstMD(unsigned v); static llvm::ConstantAsMetadata *Uint64ToConstMD(uint64_t v, llvm::LLVMContext &Ctx); llvm::ConstantAsMetadata *Uint64ToConstMD(uint64_t v); llvm::ConstantAsMetadata *Int8ToConstMD(int8_t v); llvm::ConstantAsMetadata *Uint8ToConstMD(uint8_t v); static llvm::ConstantAsMetadata *BoolToConstMD(bool v, llvm::LLVMContext &Ctx); llvm::ConstantAsMetadata *BoolToConstMD(bool v); llvm::ConstantAsMetadata *FloatToConstMD(float v); static int32_t ConstMDToInt32(const llvm::MDOperand &MDO); static unsigned ConstMDToUint32(const llvm::MDOperand &MDO); static uint64_t ConstMDToUint64(const llvm::MDOperand &MDO); static int8_t ConstMDToInt8(const llvm::MDOperand &MDO); static uint8_t ConstMDToUint8(const llvm::MDOperand &MDO); static bool ConstMDToBool(const llvm::MDOperand &MDO); static float ConstMDToFloat(const llvm::MDOperand &MDO); static std::string StringMDToString(const llvm::MDOperand &MDO); static llvm::Value *ValueMDToValue(const llvm::MDOperand &MDO); llvm::MDTuple *Uint32VectorToConstMDTuple(const std::vector &Vec); void ConstMDTupleToUint32Vector(llvm::MDTuple *pTupleMD, std::vector &Vec); private: llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule; const ShaderModel *m_pSM; std::unique_ptr m_ExtraPropertyHelper; }; /// Use this class to manipulate metadata of extra metadata record properties that are specific to DXIL. class DxilExtraPropertyHelper : public DxilMDHelper::ExtraPropertyHelper { public: DxilExtraPropertyHelper(llvm::Module *pModule); virtual void EmitSRVProperties(const DxilResource &SRV, std::vector &MDVals); virtual void LoadSRVProperties(const llvm::MDOperand &MDO, DxilResource &SRV); virtual void EmitUAVProperties(const DxilResource &UAV, std::vector &MDVals); virtual void LoadUAVProperties(const llvm::MDOperand &MDO, DxilResource &UAV); virtual void EmitCBufferProperties(const DxilCBuffer &CB, std::vector &MDVals); virtual void LoadCBufferProperties(const llvm::MDOperand &MDO, DxilCBuffer &CB); virtual void EmitSamplerProperties(const DxilSampler &S, std::vector &MDVals); virtual void LoadSamplerProperties(const llvm::MDOperand &MDO, DxilSampler &S); virtual void EmitSignatureElementProperties(const DxilSignatureElement &SE, std::vector &MDVals); virtual void LoadSignatureElementProperties(const llvm::MDOperand &MDO, DxilSignatureElement &SE); }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilModule.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilModule.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // The main class to work with DXIL, similar to LLVM module. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilMetadataHelper.h" #include "dxc/HLSL/DxilCBuffer.h" #include "dxc/HLSL/DxilResource.h" #include "dxc/HLSL/DxilSampler.h" #include "dxc/HLSL/DxilSignature.h" #include "dxc/HLSL/DxilConstants.h" #include "dxc/HLSL/DxilTypeSystem.h" #include #include #include namespace llvm { class LLVMContext; class Module; class Function; class MDTuple; class MDOperand; class DebugInfoFinder; }; namespace hlsl { class ShaderModel; class OP; class RootSignatureHandle; /// Use this class to manipulate DXIL of a shader. class DxilModule { public: DxilModule(llvm::Module *pModule); ~DxilModule(); // Subsystems. llvm::LLVMContext &GetCtx() const; llvm::Module *GetModule() const; OP *GetOP() const; void SetShaderModel(const ShaderModel *pSM); const ShaderModel *GetShaderModel() const; // Entry functions. llvm::Function *GetEntryFunction(); const llvm::Function *GetEntryFunction() const; void SetEntryFunction(llvm::Function *pEntryFunc); const std::string &GetEntryFunctionName() const; void SetEntryFunctionName(const std::string &name); llvm::Function *GetPatchConstantFunction(); const llvm::Function *GetPatchConstantFunction() const; void SetPatchConstantFunction(llvm::Function *pFunc); // Flags. unsigned GetGlobalFlags() const; // TODO: move out of DxilModule as a util. void CollectShaderFlags(); // Resources. unsigned AddCBuffer(std::unique_ptr pCB); DxilCBuffer &GetCBuffer(unsigned idx); const DxilCBuffer &GetCBuffer(unsigned idx) const; const std::vector > &GetCBuffers() const; unsigned AddSampler(std::unique_ptr pSampler); DxilSampler &GetSampler(unsigned idx); const DxilSampler &GetSampler(unsigned idx) const; const std::vector > &GetSamplers() const; unsigned AddSRV(std::unique_ptr pSRV); DxilResource &GetSRV(unsigned idx); const DxilResource &GetSRV(unsigned idx) const; const std::vector > &GetSRVs() const; unsigned AddUAV(std::unique_ptr pUAV); DxilResource &GetUAV(unsigned idx); const DxilResource &GetUAV(unsigned idx) const; const std::vector > &GetUAVs() const; void RemoveUnusedResources(); void RemoveFunction(llvm::Function *F); // Signatures. DxilSignature &GetInputSignature(); const DxilSignature &GetInputSignature() const; DxilSignature &GetOutputSignature(); const DxilSignature &GetOutputSignature() const; DxilSignature &GetPatchConstantSignature(); const DxilSignature &GetPatchConstantSignature() const; const RootSignatureHandle &GetRootSignature() const; // Remove Root Signature from module metadata void StripRootSignatureFromMetadata(); // DXIL type system. DxilTypeSystem &GetTypeSystem(); /// Emit llvm.used array to make sure that optimizations do not remove unreferenced globals. void EmitLLVMUsed(); std::vector &GetLLVMUsed(); // DXIL metadata manipulation. /// Serialize DXIL in-memory form to metadata form. void EmitDxilMetadata(); /// Deserialize DXIL metadata form into in-memory form. void LoadDxilMetadata(); /// Check if a Named meta data node is known by dxil module. static bool IsKnownNamedMetaData(llvm::NamedMDNode &Node); // Reset functions used to transfer ownership. void ResetInputSignature(DxilSignature *pValue); void ResetOutputSignature(DxilSignature *pValue); void ResetPatchConstantSignature(DxilSignature *pValue); void ResetRootSignature(RootSignatureHandle *pValue); void ResetTypeSystem(DxilTypeSystem *pValue); void ResetOP(hlsl::OP *hlslOP); void StripDebugRelatedCode(); llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder(); static DxilModule *TryGetDxilModule(llvm::Module *pModule); public: // Shader properties. class ShaderFlags { public: ShaderFlags(); unsigned GetGlobalFlags() const; void SetDisableOptimizations(bool flag) { m_bDisableOptimizations = flag; } void SetDisableMathRefactoring(bool flag) { m_bDisableMathRefactoring = flag; } void SetEnableDoublePrecision(bool flag) { m_bEnableDoublePrecision = flag; } void SetForceEarlyDepthStencil(bool flag) { m_bForceEarlyDepthStencil = flag; } void SetEnableRawAndStructuredBuffers(bool flag) { m_bEnableRawAndStructuredBuffers = flag; } void SetEnableMinPrecision(bool flag) { m_bEnableMinPrecision = flag; } void SetEnableDoubleExtensions(bool flag) { m_bEnableDoubleExtensions = flag; } void SetEnableMSAD(bool flag) { m_bEnableMSAD = flag; } void SetAllResourcesBound(bool flag) { m_bAllResourcesBound = flag; } uint64_t GetFeatureInfo() const; bool GetWaveOps() const { return m_bWaveOps; } void SetCSRawAndStructuredViaShader4X(bool flag) { m_bCSRawAndStructuredViaShader4X = flag; } void SetROVs(bool flag) { m_bROVS = flag; } void SetWaveOps(bool flag) { m_bWaveOps = flag; } void SetInt64Ops(bool flag) { m_bInt64Ops = flag; } void SetTiledResources(bool flag) { m_bTiledResources = flag; } void SetStencilRef(bool flag) { m_bStencilRef = flag; } void SetInnerCoverage(bool flag) { m_bInnerCoverage = flag; } void SetViewportAndRTArrayIndex(bool flag) { m_bViewportAndRTArrayIndex = flag; } void SetUAVLoadAdditionalFormats(bool flag) { m_bUAVLoadAdditionalFormats = flag; } void SetLevel9ComparisonFiltering(bool flag) { m_bLevel9ComparisonFiltering = flag; } void Set64UAVs(bool flag) { m_b64UAVs = flag; } void SetUAVsAtEveryStage(bool flag) { m_UAVsAtEveryStage = flag; } static uint64_t GetShaderFlagsRawForCollection(); // some flags are collected (eg use 64-bit), some provided (eg allow refactoring) uint64_t GetShaderFlagsRaw() const; void SetShaderFlagsRaw(uint64_t data); private: unsigned m_bDisableOptimizations :1; // D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION unsigned m_bDisableMathRefactoring :1; //~D3D10_SB_GLOBAL_FLAG_REFACTORING_ALLOWED unsigned m_bEnableDoublePrecision :1; // D3D11_SB_GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS unsigned m_bForceEarlyDepthStencil :1; // D3D11_SB_GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL unsigned m_bEnableRawAndStructuredBuffers :1; // D3D11_SB_GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS unsigned m_bEnableMinPrecision :1; // D3D11_1_SB_GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION unsigned m_bEnableDoubleExtensions :1; // D3D11_1_SB_GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS unsigned m_bEnableMSAD :1; // D3D11_1_SB_GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS unsigned m_bAllResourcesBound :1; // D3D12_SB_GLOBAL_FLAG_ALL_RESOURCES_BOUND unsigned m_bViewportAndRTArrayIndex :1; // SHADER_FEATURE_VIEWPORT_AND_RT_ARRAY_INDEX_FROM_ANY_SHADER_FEEDING_RASTERIZER unsigned m_bInnerCoverage :1; // SHADER_FEATURE_INNER_COVERAGE unsigned m_bStencilRef :1; // SHADER_FEATURE_STENCIL_REF unsigned m_bTiledResources :1; // SHADER_FEATURE_TILED_RESOURCES unsigned m_bUAVLoadAdditionalFormats :1; // SHADER_FEATURE_TYPED_UAV_LOAD_ADDITIONAL_FORMATS unsigned m_bLevel9ComparisonFiltering :1; // SHADER_FEATURE_LEVEL_9_COMPARISON_FILTERING // SHADER_FEATURE_11_1_SHADER_EXTENSIONS shared with EnableMSAD unsigned m_b64UAVs :1; // SHADER_FEATURE_64_UAVS unsigned m_UAVsAtEveryStage :1; // SHADER_FEATURE_UAVS_AT_EVERY_STAGE unsigned m_bCSRawAndStructuredViaShader4X : 1; // SHADER_FEATURE_COMPUTE_SHADERS_PLUS_RAW_AND_STRUCTURED_BUFFERS_VIA_SHADER_4_X // SHADER_FEATURE_COMPUTE_SHADERS_PLUS_RAW_AND_STRUCTURED_BUFFERS_VIA_SHADER_4_X is specifically // about shader model 4.x. unsigned m_bROVS :1; // SHADER_FEATURE_ROVS unsigned m_bWaveOps :1; // SHADER_FEATURE_WAVE_OPS unsigned m_bInt64Ops :1; // SHADER_FEATURE_INT64_OPS unsigned m_align0 :11; // align to 32 bit. uint32_t m_align1; // align to 64 bit. }; ShaderFlags m_ShaderFlags; void CollectShaderFlags(ShaderFlags &Flags); // Compute shader. unsigned m_NumThreads[3]; // Geometry shader. DXIL::InputPrimitive GetInputPrimitive() const; void SetInputPrimitive(DXIL::InputPrimitive IP); unsigned GetMaxVertexCount() const; void SetMaxVertexCount(unsigned Count); DXIL::PrimitiveTopology GetStreamPrimitiveTopology() const; void SetStreamPrimitiveTopology(DXIL::PrimitiveTopology Topology); bool HasMultipleOutputStreams() const; unsigned GetOutputStream() const; unsigned GetGSInstanceCount() const; void SetGSInstanceCount(unsigned Count); bool IsStreamActive(unsigned Stream) const; void SetStreamActive(unsigned Stream, bool bActive); void SetActiveStreamMask(unsigned Mask); unsigned GetActiveStreamMask() const; // Hull and Domain shaders. unsigned GetInputControlPointCount() const; void SetInputControlPointCount(unsigned NumICPs); DXIL::TessellatorDomain GetTessellatorDomain() const; void SetTessellatorDomain(DXIL::TessellatorDomain TessDomain); // Hull shader. unsigned GetOutputControlPointCount() const; void SetOutputControlPointCount(unsigned NumOCPs); DXIL::TessellatorPartitioning GetTessellatorPartitioning() const; void SetTessellatorPartitioning(DXIL::TessellatorPartitioning TessPartitioning); DXIL::TessellatorOutputPrimitive GetTessellatorOutputPrimitive() const; void SetTessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive TessOutputPrimitive); float GetMaxTessellationFactor() const; void SetMaxTessellationFactor(float MaxTessellationFactor); private: // Signatures. std::unique_ptr m_InputSignature; std::unique_ptr m_OutputSignature; std::unique_ptr m_PatchConstantSignature; std::unique_ptr m_RootSignature; // Shader resources. std::vector > m_SRVs; std::vector > m_UAVs; std::vector > m_CBuffers; std::vector > m_Samplers; // Geometry shader. DXIL::InputPrimitive m_InputPrimitive; unsigned m_MaxVertexCount; DXIL::PrimitiveTopology m_StreamPrimitiveTopology; unsigned m_ActiveStreamMask; unsigned m_NumGSInstances; // Hull and Domain shaders. unsigned m_InputControlPointCount; DXIL::TessellatorDomain m_TessellatorDomain; // Hull shader. unsigned m_OutputControlPointCount; DXIL::TessellatorPartitioning m_TessellatorPartitioning; DXIL::TessellatorOutputPrimitive m_TessellatorOutputPrimitive; float m_MaxTessellationFactor; private: llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule; llvm::Function *m_pEntryFunc; llvm::Function *m_pPatchConstantFunc; std::string m_EntryName; std::unique_ptr m_pMDHelper; std::unique_ptr m_pDebugInfoFinder; const ShaderModel *m_pSM; unsigned m_DxilMajor; unsigned m_DxilMinor; std::unique_ptr m_pOP; size_t m_pUnused; // LLVM used. std::vector m_LLVMUsed; // Type annotations. std::unique_ptr m_pTypeSystem; // DXIL metadata serialization/deserialization. llvm::MDTuple *EmitDxilResources(); void LoadDxilResources(const llvm::MDOperand &MDO); llvm::MDTuple *EmitDxilShaderProperties(); void LoadDxilShaderProperties(const llvm::MDOperand &MDO); // Helpers. template unsigned AddResource(std::vector > &Vec, std::unique_ptr pRes); void LoadDxilSignature(const llvm::MDTuple *pSigTuple, DxilSignature &Sig, bool bInput); }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilOperations.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilOperations.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Implementation of DXIL operation tables. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once namespace llvm { class LLVMContext; class Module; class Type; class Function; class Constant; class Value; class Instruction; }; #include "llvm/IR/Attributes.h" #include "DxilConstants.h" #include namespace hlsl { /// Use this utility class to interact with DXIL operations. class OP { public: using OpCode = DXIL::OpCode; using OpCodeClass = DXIL::OpCodeClass; public: OP() = delete; OP(llvm::LLVMContext &Ctx, llvm::Module *pModule); llvm::Function *GetOpFunc(OpCode OpCode, llvm::Type *pOverloadType); llvm::ArrayRef GetOpFuncList(OpCode OpCode) const; void RemoveFunction(llvm::Function *F); llvm::Type *GetOverloadType(OpCode OpCode, llvm::Function *F); llvm::LLVMContext &GetCtx() { return m_Ctx; } llvm::Type *GetHandleType() const; llvm::Type *GetDimensionsType() const; llvm::Type *GetSamplePosType() const; llvm::Type *GetBinaryWithCarryType() const; llvm::Type *GetBinaryWithTwoOutputsType() const; llvm::Type *GetSplitDoubleType() const; llvm::Type *GetInt4Type() const; llvm::Type *GetResRetType(llvm::Type *pOverloadType); llvm::Type *GetCBufferRetType(llvm::Type *pOverloadType); // LLVM helpers. Perhaps, move to a separate utility class. llvm::Constant *GetI1Const(bool v); llvm::Constant *GetI8Const(char v); llvm::Constant *GetU8Const(unsigned char v); llvm::Constant *GetI16Const(int v); llvm::Constant *GetU16Const(unsigned v); llvm::Constant *GetI32Const(int v); llvm::Constant *GetU32Const(unsigned v); llvm::Constant *GetU64Const(unsigned long long v); llvm::Constant *GetFloatConst(float v); llvm::Constant *GetDoubleConst(double v); static OpCode GetDxilOpFuncCallInst(const llvm::Instruction *I); static const char *GetOpCodeName(OpCode OpCode); static const char *GetAtomicOpName(DXIL::AtomicBinOpCode OpCode); static const OpCodeClass GetOpCodeClass(OpCode OpCode); static const char *GetOpCodeClassName(OpCode OpCode); static bool IsOverloadLegal(OpCode OpCode, llvm::Type *pType); static bool CheckOpCodeTable(); static bool IsDxilOpFunc(const llvm::Function *F); static bool IsDxilOpFuncCallInst(const llvm::Instruction *I); static bool IsDxilOpFuncCallInst(const llvm::Instruction *I, OpCode opcode); static bool IsDxilOpWave(OpCode C); static bool IsDxilOpGradient(OpCode C); private: // Per-module properties. llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule; llvm::Type *m_pHandleType; llvm::Type *m_pDimensionsType; llvm::Type *m_pSamplePosType; llvm::Type *m_pBinaryWithCarryType; llvm::Type *m_pBinaryWithTwoOutputsType; llvm::Type *m_pSplitDoubleType; llvm::Type *m_pInt4Type; static const unsigned kNumTypeOverloads = 9; llvm::Type *m_pResRetType[kNumTypeOverloads]; llvm::Type *m_pCBufferRetType[kNumTypeOverloads]; struct OpCodeCacheItem { llvm::Function *pOverloads[kNumTypeOverloads]; }; OpCodeCacheItem m_OpCodeClassCache[(unsigned)OpCodeClass::NumOpClasses]; std::unordered_map m_FunctionToOpClass; void RefreshCache(llvm::Module *pModule); private: // Static properties. struct OpCodeProperty { OpCode OpCode; const char *pOpCodeName; OpCodeClass OpCodeClass; const char *pOpCodeClassName; bool bAllowOverload[kNumTypeOverloads]; // void, h,f,d, i1, i8,i16,i32,i64 llvm::Attribute::AttrKind FuncAttr; }; static const OpCodeProperty m_OpCodeProps[(unsigned)OpCode::NumOpCodes]; static const char *m_OverloadTypeName[kNumTypeOverloads]; static const char *m_NamePrefix; static unsigned GetTypeSlot(llvm::Type *pType); static const char *GetOverloadTypeName(unsigned TypeSlot); }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilPipelineStateValidation.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilPipelineStateValidation.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Defines data used by the D3D runtime for PSO validation. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXIL_PIPELINE_STATE_VALIDATION__H__ #define __DXIL_PIPELINE_STATE_VALIDATION__H__ #include #include // Versioning is additive and based on size struct PSVRuntimeInfo0 { union { struct VSInfo { char OutputPositionPresent; } VS; struct HSInfo { uint32_t InputControlPointCount; // max control points == 32 uint32_t OutputControlPointCount; // max control points == 32 uint32_t TessellatorDomain; // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN uint32_t TessellatorOutputPrimitive; // hlsl::DXIL::TessellatorOutputPrimitive/D3D11_SB_TESSELLATOR_OUTPUT_PRIMITIVE } HS; struct DSInfo { uint32_t InputControlPointCount; // max control points == 32 char OutputPositionPresent; uint32_t TessellatorDomain; // hlsl::DXIL::TessellatorDomain/D3D11_SB_TESSELLATOR_DOMAIN } DS; struct GSInfo { uint32_t InputPrimitive; // hlsl::DXIL::InputPrimitive/D3D10_SB_PRIMITIVE uint32_t OutputTopology; // hlsl::DXIL::PrimitiveTopology/D3D10_SB_PRIMITIVE_TOPOLOGY uint32_t OutputStreamMask; // max streams == 4 char OutputPositionPresent; } GS; struct PSInfo { char DepthOutput; char SampleFrequency; } PS; }; uint32_t MinimumExpectedWaveLaneCount; // minimum lane count required, 0 if unused uint32_t MaximumExpectedWaveLaneCount; // maximum lane count required, 0xffffffff if unused }; // PSVRuntimeInfo1 would derive and extend enum class PSVResourceType { Invalid = 0, Sampler, CBV, SRVTyped, SRVRaw, SRVStructured, UAVTyped, UAVRaw, UAVStructured, UAVStructuredWithCounter, NumEntries }; // Versioning is additive and based on size struct PSVResourceBindInfo0 { uint32_t ResType; // PSVResourceType uint32_t Space; uint32_t LowerBound; uint32_t UpperBound; }; // PSVResourceBindInfo1 would derive and extend class DxilPipelineStateValidation { uint32_t m_uPSVRuntimeInfoSize; PSVRuntimeInfo0* m_pPSVRuntimeInfo0; uint32_t m_uResourceCount; uint32_t m_uPSVResourceBindInfoSize; void* m_pPSVResourceBindInfo; uint32_t m_uSize; public: DxilPipelineStateValidation() : m_uPSVRuntimeInfoSize(0), m_pPSVRuntimeInfo0(nullptr), m_uResourceCount(0), m_uPSVResourceBindInfoSize(0), m_pPSVResourceBindInfo(nullptr) { } // Init() from PSV0 blob part that looks like: // uint32_t PSVRuntimeInfo_size // { PSVRuntimeInfoN structure } // uint32_t ResourceCount // --- end of blob if ResourceCount == 0 --- // uint32_t PSVResourceBindInfo_size // { PSVResourceBindInfoN structure } * ResourceCount // returns true if no errors occurred. bool InitFromPSV0(const void* pBits, uint32_t size) { if(!(pBits != nullptr)) return false; const uint8_t* pCurBits = (uint8_t*)pBits; uint32_t minsize = sizeof(PSVRuntimeInfo0) + sizeof(uint32_t) * 2; if(!(size >= minsize)) return false; m_uPSVRuntimeInfoSize = *((const uint32_t*)pCurBits); if(!(m_uPSVRuntimeInfoSize >= sizeof(PSVRuntimeInfo0))) return false; pCurBits += sizeof(uint32_t); minsize = m_uPSVRuntimeInfoSize + sizeof(uint32_t) * 2; if(!(size >= minsize)) return false; m_pPSVRuntimeInfo0 = const_cast((const PSVRuntimeInfo0*)pCurBits); pCurBits += m_uPSVRuntimeInfoSize; m_uResourceCount = *(const uint32_t*)pCurBits; pCurBits += sizeof(uint32_t); if (m_uResourceCount > 0) { minsize += sizeof(uint32_t); if(!(size >= minsize)) return false; m_uPSVResourceBindInfoSize = *(const uint32_t*)pCurBits; pCurBits += sizeof(uint32_t); minsize += m_uPSVResourceBindInfoSize * m_uResourceCount; if(!(m_uPSVResourceBindInfoSize >= sizeof(PSVResourceBindInfo0))) return false; if(!(size >= minsize)) return false; m_pPSVResourceBindInfo = static_cast(const_cast(pCurBits)); } return true; } // Initialize a new buffer // call with null pBuffer to get required size bool InitNew(uint32_t ResourceCount, void *pBuffer, uint32_t *pSize) { if(!(pSize)) return false; uint32_t size = sizeof(PSVRuntimeInfo0) + sizeof(uint32_t) * 2; if (ResourceCount) { size += sizeof(uint32_t) + (sizeof(PSVResourceBindInfo0) * ResourceCount); } if (pBuffer) { if(!(*pSize >= size)) return false; } else { *pSize = size; return true; } memset(pBuffer, 0, size); m_uPSVRuntimeInfoSize = sizeof(PSVRuntimeInfo0); uint8_t* pCurBits = (uint8_t*)pBuffer; *(uint32_t*)pCurBits = sizeof(PSVRuntimeInfo0); pCurBits += sizeof(uint32_t); m_pPSVRuntimeInfo0 = (PSVRuntimeInfo0*)pCurBits; pCurBits += sizeof(PSVRuntimeInfo0); // Set resource info: m_uResourceCount = ResourceCount; *(uint32_t*)pCurBits = ResourceCount; pCurBits += sizeof(uint32_t); if (ResourceCount > 0) { m_uPSVResourceBindInfoSize = sizeof(PSVResourceBindInfo0); *(uint32_t*)pCurBits = m_uPSVResourceBindInfoSize; pCurBits += sizeof(uint32_t); m_pPSVResourceBindInfo = pCurBits; } return true; } PSVRuntimeInfo0* GetPSVRuntimeInfo0() { return m_pPSVRuntimeInfo0; } uint32_t GetBindCount() const { return m_uResourceCount; } PSVResourceBindInfo0* GetPSVResourceBindInfo0(uint32_t index) { if (index < m_uResourceCount && m_pPSVResourceBindInfo && sizeof(PSVResourceBindInfo0) <= m_uPSVResourceBindInfoSize) { return (PSVResourceBindInfo0*)((uint8_t*)m_pPSVResourceBindInfo + (index * m_uPSVResourceBindInfoSize)); } return nullptr; } }; #endif // __DXIL_PIPELINE_STATE_VALIDATION__H__ ================================================ FILE: src/Wrapper/dxc/HLSL/DxilResource.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilResource.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL SRVs and UAVs. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "DxilConstants.h" #include "dxc/HLSL/DxilResourceBase.h" #include "dxc/HLSL/DxilCompType.h" namespace hlsl { /// Use this class to represent an HLSL resource (SRV/UAV). class DxilResource : public DxilResourceBase { public: /// Total number of coordinates necessary to access resource. static unsigned GetNumCoords(Kind ResourceKind); /// Total number of resource dimensions (Only width and height for cube). static unsigned GetNumDimensions(Kind ResourceKind); /// Total number of resource dimensions for CalcLOD (no array). static unsigned GetNumDimensionsForCalcLOD(Kind ResourceKind); /// Total number of offsets (in [-8,7]) necessary to access resource. static unsigned GetNumOffsets(Kind ResourceKind); DxilResource(); CompType GetCompType() const; void SetCompType(const CompType CT); llvm::Type *GetRetType() const; unsigned GetSampleCount() const; void SetSampleCount(unsigned SampleCount); unsigned GetElementStride() const; void SetElementStride(unsigned ElemStride); bool IsGloballyCoherent() const; void SetGloballyCoherent(bool b); bool HasCounter() const; void SetHasCounter(bool b); bool IsRO() const; bool IsRW() const; void SetRW(bool bRW); bool IsROV() const; void SetROV(bool bROV); bool IsAnyTexture() const; bool IsStructuredBuffer() const; bool IsTypedBuffer() const; bool IsRawBuffer() const; bool IsTBuffer() const; private: unsigned m_SampleCount; unsigned m_ElementStride; // in bytes CompType m_CompType; bool m_bGloballyCoherent; bool m_bHasCounter; bool m_bROV; }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilResourceBase.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilResourceBase.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Base class to represent DXIL SRVs, UAVs, CBuffers, and Samplers. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include #include "DxilConstants.h" namespace llvm { class Value; class Constant; }; namespace hlsl { /// Base class to represent HLSL SRVs, UAVs, CBuffers, and Samplers. class DxilResourceBase { public: using Class = DXIL::ResourceClass; using Kind = DXIL::ResourceKind; public: DxilResourceBase(Class C); virtual ~DxilResourceBase() {} Class GetClass() const; DxilResourceBase::Kind GetKind() const; unsigned GetID() const; unsigned GetSpaceID() const; unsigned GetLowerBound() const; unsigned GetUpperBound() const; unsigned GetRangeSize() const; llvm::Constant *GetGlobalSymbol() const; const std::string &GetGlobalName() const; llvm::Value *GetHandle() const; bool IsAllocated() const; bool IsUnbounded() const; void SetKind(DxilResourceBase::Kind ResourceKind); void SetSpaceID(unsigned SpaceID); void SetLowerBound(unsigned LB); void SetRangeSize(unsigned RangeSize); void SetGlobalSymbol(llvm::Constant *pGV); void SetGlobalName(const std::string &Name); void SetHandle(llvm::Value *pHandle); // TODO: check whether we can make this a protected method. void SetID(unsigned ID); const char *DxilResourceBase::GetResClassName() const; const char *DxilResourceBase::GetResDimName() const; const char *DxilResourceBase::GetResIDPrefix() const; const char *DxilResourceBase::GetResBindPrefix() const; protected: void SetClass(Class C); private: Class m_Class; // Resource class (SRV, UAV, CBuffer, Sampler). Kind m_Kind; // Detail resource kind( texture2D...). unsigned m_ID; // Unique ID within the class. unsigned m_SpaceID; // Root signature space. unsigned m_LowerBound; // Range lower bound. unsigned m_RangeSize; // Range size in entries. llvm::Constant *m_pSymbol; // Global variable. std::string m_Name; // Unmangled name of the global variable. llvm::Value *m_pHandle; // Cached resource handle for SM5.0- (and maybe SM5.1). }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilRootSignature.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilRootSignature.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // HLSL root signature parsing. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #ifndef __DXC_ROOTSIGNATURE__ #define __DXC_ROOTSIGNATURE__ #include struct IDxcBlob; struct IDxcBlobEncoding; namespace llvm { class raw_ostream; } namespace hlsl { // Forward declarations. struct DxilDescriptorRange; struct DxilDescriptorRange1; struct DxilRootConstants; struct DxilRootDescriptor; struct DxilRootDescriptor1; struct DxilRootDescriptorTable; struct DxilRootDescriptorTable1; struct DxilRootParameter; struct DxilRootParameter1; struct DxilRootSignatureDesc; struct DxilRootSignatureDesc1; struct DxilStaticSamplerDesc; struct DxilVersionedRootSignatureDesc; // Constant values. static const uint32_t DxilDescriptorRangeOffsetAppend = 0xffffffff; static const uint32_t DxilSystemReservedRegisterSpaceValuesStart = 0xfffffff0; static const uint32_t DxilSystemReservedRegisterSpaceValuesEnd = 0xffffffff; #define DxilMipLodBiaxMax ( 15.99f ) #define DxilMipLodBiaxMin ( -16.0f ) #define DxilFloat32Max ( 3.402823466e+38f ) static const uint32_t DxilMipLodFractionalBitCount = 8; static const uint32_t DxilMapAnisotropy = 16; // Enumerations and flags. enum class DxilComparisonFunc : unsigned{ Never = 1, Less = 2, Equal = 3, LessEqual = 4, Greater = 5, NotEqual = 6, GreaterEqual = 7, Always = 8 }; enum class DxilDescriptorRangeFlags : unsigned { None = 0, DescriptorsVolatile = 0x1, DataVolatile = 0x2, DataStaticWhileSetAtExecute = 0x4, DataStatic = 0x8, ValidFlags = 0xf, ValidSamplerFlags = DescriptorsVolatile }; enum class DxilDescriptorRangeType : unsigned { SRV = 0, UAV = 1, CBV = 2, Sampler = 3 }; enum class DxilRootDescriptorFlags : unsigned { None = 0, DataVolatile = 0x2, DataStaticWhileSetAtExecute = 0x4, DataStatic = 0x8, ValidFlags = 0xe }; enum class DxilRootSignatureVersion { Version_1 = 1, Version_1_0 = 1, Version_1_1 = 2 }; enum class DxilRootSignatureFlags : uint32_t { None = 0, AllowInputAssemblerInputLayout = 0x1, DenyVertexShaderRootAccess = 0x2, DenyHullShaderRootAccess = 0x4, DenyDomainShaderRootAccess = 0x8, DenyGeometryShaderRootAccess = 0x10, DenyPixelShaderRootAccess = 0x20, AllowStreamOutput = 0x40, AllowLowTierReservedHwCbLimit = 0x80000000, ValidFlags = 0x8000007f }; enum class DxilRootParameterType { DescriptorTable = 0, Constants32Bit = 1, CBV = 2, SRV = 3, UAV = 4 }; enum class DxilFilter { // TODO: make these names consistent with code convention MIN_MAG_MIP_POINT = 0, MIN_MAG_POINT_MIP_LINEAR = 0x1, MIN_POINT_MAG_LINEAR_MIP_POINT = 0x4, MIN_POINT_MAG_MIP_LINEAR = 0x5, MIN_LINEAR_MAG_MIP_POINT = 0x10, MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11, MIN_MAG_LINEAR_MIP_POINT = 0x14, MIN_MAG_MIP_LINEAR = 0x15, ANISOTROPIC = 0x55, COMPARISON_MIN_MAG_MIP_POINT = 0x80, COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81, COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x84, COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x85, COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x90, COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x91, COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x94, COMPARISON_MIN_MAG_MIP_LINEAR = 0x95, COMPARISON_ANISOTROPIC = 0xd5, MINIMUM_MIN_MAG_MIP_POINT = 0x100, MINIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x101, MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x104, MINIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x105, MINIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x110, MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x111, MINIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x114, MINIMUM_MIN_MAG_MIP_LINEAR = 0x115, MINIMUM_ANISOTROPIC = 0x155, MAXIMUM_MIN_MAG_MIP_POINT = 0x180, MAXIMUM_MIN_MAG_POINT_MIP_LINEAR = 0x181, MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x184, MAXIMUM_MIN_POINT_MAG_MIP_LINEAR = 0x185, MAXIMUM_MIN_LINEAR_MAG_MIP_POINT = 0x190, MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x191, MAXIMUM_MIN_MAG_LINEAR_MIP_POINT = 0x194, MAXIMUM_MIN_MAG_MIP_LINEAR = 0x195, MAXIMUM_ANISOTROPIC = 0x1d5 }; enum class DxilShaderVisibility { All = 0, Vertex = 1, Hull = 2, Domain = 3, Geometry = 4, Pixel = 5 }; enum class DxilStaticBorderColor { TransparentBlack = 0, OpaqueBlack = 1, OpaqueWhite = 2 }; enum class DxilTextureAddressMode { Wrap = 1, Mirror = 2, Clamp = 3, Border = 4, MirrorOnce = 5 }; // Structure definitions for serialized structures. #pragma pack(push, 1) struct DxilContainerRootDescriptor1 { uint32_t ShaderRegister; uint32_t RegisterSpace; uint32_t Flags; }; struct DxilContainerDescriptorRange { uint32_t RangeType; uint32_t NumDescriptors; uint32_t BaseShaderRegister; uint32_t RegisterSpace; uint32_t OffsetInDescriptorsFromTableStart; }; struct DxilContainerDescriptorRange1 { uint32_t RangeType; uint32_t NumDescriptors; uint32_t BaseShaderRegister; uint32_t RegisterSpace; uint32_t Flags; uint32_t OffsetInDescriptorsFromTableStart; }; struct DxilContainerRootDescriptorTable { uint32_t NumDescriptorRanges; uint32_t DescriptorRangesOffset; }; struct DxilContainerRootParameter { uint32_t ParameterType; uint32_t ShaderVisibility; uint32_t PayloadOffset; }; struct DxilContainerRootSignatureDesc { uint32_t Version; uint32_t NumParameters; uint32_t RootParametersOffset; uint32_t NumStaticSamplers; uint32_t StaticSamplersOffset; uint32_t Flags; }; #pragma pack(pop) // Structure definitions for in-memory structures. struct DxilDescriptorRange { DxilDescriptorRangeType RangeType; uint32_t NumDescriptors; uint32_t BaseShaderRegister; uint32_t RegisterSpace; uint32_t OffsetInDescriptorsFromTableStart; }; struct DxilRootDescriptorTable { uint32_t NumDescriptorRanges; _Field_size_full_(NumDescriptorRanges) const DxilDescriptorRange *pDescriptorRanges; }; struct DxilRootConstants { uint32_t ShaderRegister; uint32_t RegisterSpace; uint32_t Num32BitValues; }; struct DxilRootDescriptor { uint32_t ShaderRegister; uint32_t RegisterSpace; }; struct DxilRootDescriptor1 { uint32_t ShaderRegister; uint32_t RegisterSpace; DxilRootDescriptorFlags Flags; }; struct DxilRootParameter { DxilRootParameterType ParameterType; union { DxilRootDescriptorTable DescriptorTable; DxilRootConstants Constants; DxilRootDescriptor Descriptor; }; DxilShaderVisibility ShaderVisibility; }; struct DxilDescriptorRange1 { DxilDescriptorRangeType RangeType; uint32_t NumDescriptors; uint32_t BaseShaderRegister; uint32_t RegisterSpace; DxilDescriptorRangeFlags Flags; uint32_t OffsetInDescriptorsFromTableStart; }; struct DxilRootDescriptorTable1 { uint32_t NumDescriptorRanges; _Field_size_full_(NumDescriptorRanges) const DxilDescriptorRange1 *pDescriptorRanges; }; struct DxilRootParameter1 { DxilRootParameterType ParameterType; union { DxilRootDescriptorTable1 DescriptorTable; DxilRootConstants Constants; DxilRootDescriptor1 Descriptor; }; DxilShaderVisibility ShaderVisibility; }; struct DxilRootSignatureDesc { uint32_t NumParameters; _Field_size_full_(NumParameters) const DxilRootParameter *pParameters; uint32_t NumStaticSamplers; _Field_size_full_(NumStaticSamplers) const DxilStaticSamplerDesc *pStaticSamplers; DxilRootSignatureFlags Flags; }; struct DxilStaticSamplerDesc { DxilFilter Filter; DxilTextureAddressMode AddressU; DxilTextureAddressMode AddressV; DxilTextureAddressMode AddressW; float MipLODBias; uint32_t MaxAnisotropy; DxilComparisonFunc ComparisonFunc; DxilStaticBorderColor BorderColor; float MinLOD; float MaxLOD; uint32_t ShaderRegister; uint32_t RegisterSpace; DxilShaderVisibility ShaderVisibility; }; struct DxilRootSignatureDesc1 { uint32_t NumParameters; _Field_size_full_(NumParameters) const DxilRootParameter1 *pParameters; uint32_t NumStaticSamplers; _Field_size_full_(NumStaticSamplers) const DxilStaticSamplerDesc *pStaticSamplers; DxilRootSignatureFlags Flags; }; struct DxilVersionedRootSignatureDesc { DxilRootSignatureVersion Version; union { DxilRootSignatureDesc Desc_1_0; DxilRootSignatureDesc1 Desc_1_1; }; }; // Use this class to represent a root signature that may be in memory or serialized. // There is just enough API surface to help callers not take a dependency on Windows headers. class RootSignatureHandle { private: const DxilVersionedRootSignatureDesc *m_pDesc; IDxcBlob *m_pSerialized; public: RootSignatureHandle() : m_pDesc(nullptr), m_pSerialized(nullptr) {} RootSignatureHandle(const RootSignatureHandle &) = delete; RootSignatureHandle(RootSignatureHandle &&other); ~RootSignatureHandle() { Clear(); } bool IsEmpty() const { return m_pDesc == nullptr && m_pSerialized == nullptr; } IDxcBlob *GetSerialized() const { return m_pSerialized; } const uint8_t *GetSerializedBytes() const; unsigned GetSerializedSize() const; void Assign(const DxilVersionedRootSignatureDesc *pDesc, IDxcBlob *pSerialized); void Clear(); void LoadSerialized(const uint8_t *pData, uint32_t length); void EnsureSerializedAvailable(); void Deserialize(); const DxilVersionedRootSignatureDesc *GetDesc() const { return m_pDesc; } }; void DeleteRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature); // Careful to delete: returns the original root signature, if conversion is not required. void ConvertRootSignature(const DxilVersionedRootSignatureDesc* pRootSignatureIn, DxilRootSignatureVersion RootSignatureVersionOut, const DxilVersionedRootSignatureDesc ** ppRootSignatureOut); void SerializeRootSignature(const DxilVersionedRootSignatureDesc *pRootSignature, _Outptr_ IDxcBlob **ppBlob, _Outptr_ IDxcBlobEncoding **ppErrorBlob, bool bAllowReservedRegisterSpace); void DeserializeRootSignature(__in_bcount(SrcDataSizeInBytes) const void *pSrcData, __in uint32_t SrcDataSizeInBytes, __out const DxilVersionedRootSignatureDesc **ppRootSignature); // Takes PSV - pipeline state validation data, not shader container. bool VerifyRootSignatureWithShaderPSV(__in const DxilVersionedRootSignatureDesc *pDesc, __in DXIL::ShaderKind ShaderKind, _In_reads_bytes_(PSVSize) const void *pPSVData, __in uint32_t PSVSize, __in llvm::raw_ostream &DiagStream); } // namespace hlsl #endif // __DXC_ROOTSIGNATURE__ ================================================ FILE: src/Wrapper/dxc/HLSL/DxilSampler.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilSampler.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL sampler state. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilResourceBase.h" namespace hlsl { /// Use this class to represent HLSL sampler state. class DxilSampler : public DxilResourceBase { public: using SamplerKind = DXIL::SamplerKind; DxilSampler(); SamplerKind GetSamplerKind() const; bool IsCompSampler() const; void SetSamplerKind(SamplerKind K); private: SamplerKind m_SamplerKind; // Sampler mode. }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilSemantic.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilSemantic.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL parameter semantics. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "llvm/ADT/StringRef.h" #include "DxilConstants.h" #include "DxilShaderModel.h" namespace hlsl { /// Use this class to represent HLSL parameter semantic. class Semantic { public: using Kind = DXIL::SemanticKind; static const int kUndefinedRow = -1; static const int kUndefinedCol = -1; static const Semantic *GetByName(llvm::StringRef name); static const Semantic *GetByName(llvm::StringRef Name, DXIL::SigPointKind sigPointKind, unsigned MajorVersion = ShaderModel::kHighestMajor, unsigned MinorVersion = ShaderModel::kHighestMinor); static const Semantic *Get(Kind kind); static const Semantic *Get(Kind kind, DXIL::SigPointKind sigPointKind, unsigned MajorVersion = ShaderModel::kHighestMajor, unsigned MinorVersion = ShaderModel::kHighestMinor); static const Semantic *GetInvalid(); static const Semantic *GetArbitrary(); static bool Semantic::HasSVPrefix(llvm::StringRef Name); static void DecomposeNameAndIndex(llvm::StringRef FullName, llvm::StringRef *pName, unsigned *pIndex); Kind GetKind() const; const char *GetName() const; bool IsArbitrary() const; bool IsInvalid() const; private: Kind m_Kind; // Semantic kind. const char *m_pszName; // Canonical name (for system semantics). Semantic() = delete; Semantic(Kind Kind, const char *pszName); // Table of all semantic properties. static const unsigned kNumSemanticRecords = (unsigned)Kind::Invalid + 1; static const Semantic ms_SemanticTable[kNumSemanticRecords]; friend class ShaderModel; friend class SignatureElement; }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilShaderModel.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilShaderModel.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL shader models. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DXILConstants.h" #include namespace hlsl { class Semantic; /// /// Use this class to represent HLSL shader model. /// class ShaderModel { public: using Kind = DXIL::ShaderKind; // Major/Minor version of highest shader model static const unsigned kHighestMajor = 6; static const unsigned kHighestMinor = 0; bool IsPS() const { return m_Kind == Kind::Pixel; } bool IsVS() const { return m_Kind == Kind::Vertex; } bool IsGS() const { return m_Kind == Kind::Geometry; } bool IsHS() const { return m_Kind == Kind::Hull; } bool IsDS() const { return m_Kind == Kind::Domain; } bool IsCS() const { return m_Kind == Kind::Compute; } bool IsValid() const; Kind GetKind() const { return m_Kind; } unsigned GetMajor() const { return m_Major; } unsigned GetMinor() const { return m_Minor; } bool IsSM50Plus() const { return m_Major >= 5; } bool IsSM51Plus() const { return m_Major > 5 || (m_Major == 5 && m_Minor >= 1); } const char *GetName() const { return m_pszName; } std::string GetKindName() const; unsigned GetNumTempRegs() const { return DXIL::kMaxTempRegCount; } unsigned GetNumInputRegs() const { return m_NumInputRegs; } unsigned GetNumOutputRegs() const { return m_NumOutputRegs; } unsigned GetCBufferSize() const { return DXIL::kMaxCBufferSize; } unsigned SupportsUAV() const { return m_bUAVs; } unsigned SupportsTypedUAVs() const { return m_bTypedUavs; } unsigned GetUAVRegLimit() const { return m_NumUAVRegs; } DXIL::PackingStrategy GetDefaultPackingStrategy() const { return DXIL::PackingStrategy::PrefixStable; } static unsigned Count() { return kNumShaderModels - 1; } static const ShaderModel *Get(unsigned Idx); static const ShaderModel *Get(Kind Kind, unsigned Major, unsigned Minor); static const ShaderModel *GetByName(const char *pszName); private: Kind m_Kind; unsigned m_Major; unsigned m_Minor; const char *m_pszName; unsigned m_NumInputRegs; unsigned m_NumOutputRegs; bool m_bUAVs; bool m_bTypedUavs; unsigned m_NumUAVRegs; ShaderModel() = delete; ShaderModel(Kind Kind, unsigned Major, unsigned Minor, const char *pszName, unsigned m_NumInputRegs, unsigned m_NumOutputRegs, bool m_bUAVs, bool m_bTypedUavs, unsigned m_UAVRegsLim); static const unsigned kNumShaderModels = 27; static const ShaderModel ms_ShaderModels[kNumShaderModels]; static const ShaderModel *GetInvalid(); }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilSigPoint.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilSigPoint.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL signature points. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "llvm/ADT/StringRef.h" #include "DxilConstants.h" namespace hlsl { struct VersionedSemanticInterpretation { VersionedSemanticInterpretation(DXIL::SemanticInterpretationKind k, unsigned MajorVersion=0, unsigned MinorVersion=0) : Kind(k), Major((unsigned short)MajorVersion), Minor((unsigned short)MinorVersion) {} DXIL::SemanticInterpretationKind Kind; unsigned short Major, Minor; }; /// Use this class to describe an HLSL signature point. /// A signature point is a set of signature parameters at a particular shader stage, /// grouped by input/output/patch constant and value frequency. class SigPoint { public: using Kind = DXIL::SigPointKind; SigPoint(DXIL::SigPointKind spk, const char *name, DXIL::SigPointKind rspk, DXIL::ShaderKind shk, DXIL::SignatureKind sigk, DXIL::PackingKind pk); bool IsInput() const { return m_SignatureKind == DXIL::SignatureKind::Input; } bool IsOutput() const { return m_SignatureKind == DXIL::SignatureKind::Output; } bool IsPatchConstant() const { return m_SignatureKind == DXIL::SignatureKind::PatchConstant; } Kind GetKind() const { return m_Kind; } const char *GetName() const { return m_pszName; } DXIL::ShaderKind GetShaderKind() const { return m_ShaderKind; } Kind GetRelatedKind() const { return m_RelatedKind; } DXIL::SignatureKind GetSignatureKind() const { return m_SignatureKind; } DXIL::SignatureKind GetSignatureKindWithFallback() const; DXIL::PackingKind GetPackingKind() const { return m_PackingKind; } bool NeedsInterpMode() const { return m_PackingKind == DXIL::PackingKind::Vertex; } static const SigPoint* GetSigPoint(Kind K); // isSpecialInput selects a signature point outside the normal input/output/patch constant signatures. // These are used for a few system values that should not be included as part of the regular input // structure because they do not have the same dimensionality as other inputs, such as // SV_PrimitiveID for Geometry, Hull, and Patch Constant Functions. static DXIL::SigPointKind GetKind(DXIL::ShaderKind shaderKind, DXIL::SignatureKind sigKind, bool isPatchConstantFunction, bool isSpecialInput); // Interpretations are how system values are intrepeted at a particular signature point. static DXIL::SemanticInterpretationKind GetInterpretation(DXIL::SemanticKind SK, Kind K, unsigned MajorVersion, unsigned MinorVersion); // For Shadow elements, recover original SigPointKind static Kind RecoverKind(DXIL::SemanticKind SK, Kind K); private: static const unsigned kNumSigPointRecords = (unsigned)Kind::Invalid + 1; static const SigPoint ms_SigPoints[kNumSigPointRecords]; static const VersionedSemanticInterpretation ms_SemanticInterpretationTable[(unsigned)DXIL::SemanticKind::Invalid][(unsigned)Kind::Invalid]; Kind m_Kind; Kind m_RelatedKind; DXIL::ShaderKind m_ShaderKind; DXIL::SignatureKind m_SignatureKind; const char *m_pszName; DXIL::PackingKind m_PackingKind; }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilSignature.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilSignature.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL shader signature. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilSignatureElement.h" #include #include #include namespace hlsl { /// Use this class to represent HLSL signature. class DxilSignature { public: using Kind = DXIL::SignatureKind; DxilSignature(DXIL::ShaderKind shaderKind, DXIL::SignatureKind sigKind); DxilSignature(DXIL::SigPointKind sigPointKind); virtual ~DxilSignature(); bool IsInput() const; bool IsOutput() const; virtual std::unique_ptr CreateElement(); unsigned AppendElement(std::unique_ptr pSE, bool bSetID = true); DxilSignatureElement &GetElement(unsigned idx); const DxilSignatureElement &GetElement(unsigned idx) const; const std::vector > &GetElements() const; // Packs the signature elements per DXIL constraints and returns the number of rows used for the signature unsigned PackElements(DXIL::PackingStrategy packing); // Returns true if all signature elements that should be allocated are allocated bool IsFullyAllocated(); private: DXIL::SigPointKind m_sigPointKind; std::vector > m_Elements; }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilSignatureAllocator.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilSignatureAllocation.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Classes used for allocating signature elements. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilSignature.h" namespace hlsl { class DxilSignatureAllocator { public: // index flags static const uint8_t kIndexedUp = 1 << 0; // Indexing continues upwards static const uint8_t kIndexedDown = 1 << 1; // Indexing continues downwards static uint8_t GetIndexFlags(unsigned row, unsigned rows) { return ((row > 0) ? kIndexedUp : 0) | ((row < rows - 1) ? kIndexedDown : 0); } // element flags static const uint8_t kEFOccupied = 1 << 0; static const uint8_t kEFArbitrary = 1 << 1; static const uint8_t kEFSGV = 1 << 2; static const uint8_t kEFSV = 1 << 3; static const uint8_t kEFTessFactor = 1 << 4; static const uint8_t kEFConflictsWithIndexed = kEFSGV | kEFSV; static uint8_t GetElementFlags(const DxilSignatureElement *SE); // The following two functions enforce the rules of component ordering when packing different // kinds of elements into the same register. // given element flags, return element flags that conflict when placed to the left of the element static uint8_t GetConflictFlagsLeft(uint8_t flags); // given element flags, return element flags that conflict when placed to the right of the element static uint8_t GetConflictFlagsRight(uint8_t flags); enum ConflictType { kNoConflict = 0, kConflictsWithIndexed, kConflictsWithIndexedTessFactor, kConflictsWithInterpolationMode, kInsufficientFreeComponents, kOverlapElement, kIllegalComponentOrder, kConflictFit, }; struct PackedRegister { // Flags: // - for occupied components, they signify element flags // - for unoccupied components, they signify conflict flags uint8_t Flags[4]; DXIL::InterpolationMode Interp : 4; uint8_t IndexFlags : 2; uint8_t IndexingFixed : 1; PackedRegister(); ConflictType DetectRowConflict(uint8_t flags, uint8_t indexFlags, DXIL::InterpolationMode interp, unsigned width); ConflictType DetectColConflict(uint8_t flags, unsigned col, unsigned width); void PlaceElement(uint8_t flags, uint8_t indexFlags, DXIL::InterpolationMode interp, unsigned col, unsigned width); }; std::vector Registers; DxilSignatureAllocator(unsigned numRegisters); ConflictType DetectRowConflict(const DxilSignatureElement *SE, unsigned row); ConflictType DetectColConflict(const DxilSignatureElement *SE, unsigned row, unsigned col); void PlaceElement(const DxilSignatureElement *SE, unsigned row, unsigned col); unsigned PackNext(DxilSignatureElement* SE, unsigned startRow, unsigned numRows, unsigned startCol = 0); // Simple greedy in-order packer used by PackOptimized unsigned PackGreedy(std::vector elements, unsigned startRow, unsigned numRows, unsigned startCol = 0); // Optimized packing algorithm - appended elements may affect positions of prior elements. unsigned PackOptimized(std::vector elements, unsigned startRow, unsigned numRows); // Pack in a prefix-stable way - appended elements do not affect positions of prior elements. unsigned PackPrefixStable(std::vector elements, unsigned startRow, unsigned numRows); }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilSignatureElement.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilSignatureElement.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL signature element. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "llvm/ADT/StringRef.h" #include "dxc/HLSL/DxilSemantic.h" #include "dxc/HLSL/DxilInterpolationMode.h" #include "dxc/HLSL/DxilCompType.h" #include #include namespace hlsl { class ShaderModel; /// Use this class to represent HLSL signature elements. class DxilSignatureElement { friend class DxilSignature; public: using Kind = DXIL::SigPointKind; static const unsigned kUndefinedID = UINT_MAX; DxilSignatureElement(Kind K); virtual ~DxilSignatureElement(); void Initialize(llvm::StringRef Name, const CompType &ElementType, const InterpolationMode &InterpMode, unsigned Rows, unsigned Cols, int StartRow = Semantic::kUndefinedRow, int StartCol = Semantic::kUndefinedCol, unsigned ID = kUndefinedID, const std::vector &IndexVector = std::vector()); unsigned GetID() const; void SetID(unsigned ID); DXIL::ShaderKind GetShaderKind() const; DXIL::SigPointKind GetSigPointKind() const; void SetSigPointKind(DXIL::SigPointKind K); bool IsInput() const; bool IsOutput() const; bool IsPatchConstant() const; const char *GetName() const; unsigned GetRows() const; void SetRows(unsigned Rows); unsigned GetCols() const; void SetCols(unsigned Cols); const InterpolationMode *GetInterpolationMode() const; CompType GetCompType() const; unsigned GetOutputStream() const; void SetOutputStream(unsigned Stream); // Semantic properties. const Semantic *GetSemantic() const; void SetKind(Semantic::Kind kind); Semantic::Kind GetKind() const; bool IsArbitrary() const; bool IsDepth() const; bool IsDepthLE() const; bool IsDepthGE() const; bool IsAnyDepth() const; DXIL::SemanticInterpretationKind GetInterpretation() const; llvm::StringRef GetSemanticName() const; unsigned GetSemanticStartIndex() const; // Low-level properties. int GetStartRow() const; void SetStartRow(int StartRow); int GetStartCol() const; void SetStartCol(int Component); const std::vector &GetSemanticIndexVec() const; void SetSemanticIndexVec(const std::vector &Vec); void AppendSemanticIndex(unsigned SemIdx); void SetCompType(CompType CT); uint8_t GetColsAsMask() const; bool IsAllocated() const; protected: DXIL::SigPointKind m_sigPointKind; const Semantic *m_pSemantic; unsigned m_ID; std::string m_Name; llvm::StringRef m_SemanticName; unsigned m_SemanticStartIndex; CompType m_CompType; InterpolationMode m_InterpMode; std::vector m_SemanticIndex; unsigned m_Rows; unsigned m_Cols; int m_StartRow; int m_StartCol; unsigned m_OutputStream; }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilSpanAllocator.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilSpanAllocator.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Allocator for resources or other things that span a range of space // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/Support/Global.h" #include #include namespace hlsl { template class SpanAllocator { public: struct Span { Span(const T_element *element, T_index start, T_index end) : element(element), start(start), end(end) { DXASSERT_NOMSG(!(end < start)); } const T_element *element; T_index start, end; // inclusive bool operator<(const Span &other) const { return end < other.start; } }; typedef std::set SpanSet; public: SpanAllocator(T_index Min, T_index Max) : m_Min(Min), m_Max(Max), m_FirstFree(Min), m_Unbounded(nullptr), m_AllocationFull(false) { DXASSERT_NOMSG(Min <= Max); } T_index GetMin() { return m_Min; } T_index GetMax() { return m_Max; } T_index GetFirstFree() { return m_FirstFree; } bool IsFull() { return m_AllocationFull; } void SetUnbounded(const T_element *element) { m_Unbounded = element; } const T_element *GetUnbounded() const { return m_Unbounded; } const SpanSet &GetSpans() const { return m_Spans; } // Find size gap starting at pos, updating pos, and returning true if successful bool Find(T_index size, T_index &pos, T_index align = 1) { DXASSERT_NOMSG(size); if (size - 1 > m_Max - m_Min) return false; if (pos < m_FirstFree) pos = m_FirstFree; if (!UpdatePos(pos, size, align)) return false; T_index end = pos + (size - 1); auto next = m_Spans.lower_bound(Span(nullptr, pos, end)); if (next == m_Spans.end() || end < next->start) return true; // it fits here return Find(size, result.first, pos, align); } // allocate element size in first available space, returns false on failure bool Allocate(const T_element *element, T_index size, T_index &pos, T_index align = 1) { DXASSERT_NOMSG(size); if (size - 1 > m_Max - m_Min) return false; if (m_AllocationFull) return false; pos = m_FirstFree; if (!UpdatePos(pos, size, align)) return false; auto result = m_Spans.emplace(element, pos, pos + (size - 1)); if (result.second) { AdvanceFirstFree(result.first); return true; } // Collision, find a gap from iterator if (!Find(size, result.first, pos, align)) return false; result = m_Spans.emplace(element, pos, pos + (size - 1)); return result.second; } bool AllocateUnbounded(const T_element *element, T_index &pos, T_index align = 1) { if (m_AllocationFull) return false; if (m_Spans.empty()) { pos = m_Min; if (!UpdatePos(pos, /*size*/1, align)) return false; } else { // This will allocate after the last span auto it = m_Spans.end(); --it; // find last span DXASSERT_NOMSG(it != m_Spans.end()); pos = it->end; if (!IncPos(pos, /*inc*/1, /*size*/1, align)) return false; } const T_element *conflict = Insert(element, pos, m_Max); DXASSERT_NOMSG(!conflict); if (!conflict) SetUnbounded(element); return !conflict; } // Insert at specific location, returning conflicting element on collision const T_element *Insert(const T_element *element, T_index start, T_index end) { DXASSERT_NOMSG(m_Min <= start && start <= end && end <= m_Max); auto result = m_Spans.emplace(element, start, end); if (!result.second) return result.first->element; AdvanceFirstFree(result.first); return nullptr; } private: // Find size gap starting at iterator, updating pos, and returning true if successful bool Find(T_index size, typename SpanSet::const_iterator it, T_index &pos, T_index align = 1) { pos = it->end; if (!IncPos(pos, /*inc*/1, size, align)) return false; for (++it; it != m_Spans.end() && (it->start < pos || it->start - pos < size); ++it) { pos = it->end; if (!IncPos(pos, /*inc*/1, size, align)) return false; } return true; } // Advance m_FirstFree if it's in span void AdvanceFirstFree(typename SpanSet::const_iterator it) { if (it->start <= m_FirstFree && m_FirstFree <= it->end) { for (; it != m_Spans.end(); ) { if (it->end >= m_Max) { m_AllocationFull = true; break; } m_FirstFree = it->end + 1; ++it; if (it != m_Spans.end() && m_FirstFree < it->start) break; } } } T_index Align(T_index pos, T_index align) { T_index rem = (1 < align) ? pos % align : 0; return rem ? pos + (align - rem) : pos; } bool IncPos(T_index &pos, T_index inc = 1, T_index size = 1, T_index align = 1) { DXASSERT_NOMSG(inc > 0); if (pos + inc < pos) return false; // overflow pos += inc; return UpdatePos(pos, size, align); } bool UpdatePos(T_index &pos, T_index size = 1, T_index align = 1) { if ((size - 1) > m_Max - m_Min || pos < m_Min || pos > m_Max - (size - 1)) return false; T_index aligned = Align(pos, align); if (aligned < pos || aligned > m_Max - (size - 1)) return false; // overflow on alignment, or won't fit pos = aligned; return true; } private: SpanSet m_Spans; T_index m_Min, m_Max, m_FirstFree; const T_element *m_Unbounded; bool m_AllocationFull; }; template class SpacesAllocator { public: typedef SpanAllocator Allocator; typedef std::map AllocatorMap; Allocator &Get(T_index SpaceID) { auto it = m_Allocators.find(SpaceID); if (it != m_Allocators.end()) return it->second; auto result = m_Allocators.emplace(SpaceID, Allocator(0, UINT_MAX)); DXASSERT(result.second, "Failed to allocate new Allocator"); return result.first->second; } private: AllocatorMap m_Allocators; }; } ================================================ FILE: src/Wrapper/dxc/HLSL/DxilTypeSystem.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilTypeSystem.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // DXIL extension to LLVM type system. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "llvm/ADT/StringRef.h" #include "llvm/ADT/MapVector.h" #include "dxc/HLSL/DxilCompType.h" #include "dxc/HLSL/DxilInterpolationMode.h" #include #include #include namespace llvm { class LLVMContext; class Module; class Function; class Type; class StructType; class StringRef; }; namespace hlsl { enum class MatrixOrientation { Undefined = 0, RowMajor, ColumnMajor, LastEntry }; struct DxilMatrixAnnotation { unsigned Rows; unsigned Cols; MatrixOrientation Orientation; DxilMatrixAnnotation(); }; /// Use this class to represent type annotation for structure field. class DxilFieldAnnotation { public: DxilFieldAnnotation(); bool IsPrecise() const; void SetPrecise(bool b = true); bool HasMatrixAnnotation() const; const DxilMatrixAnnotation &GetMatrixAnnotation() const; void SetMatrixAnnotation(const DxilMatrixAnnotation &MA); bool HasCBufferOffset() const; unsigned GetCBufferOffset() const; void SetCBufferOffset(unsigned Offset); bool HasCompType() const; const CompType &GetCompType() const; void SetCompType(CompType::Kind kind); bool HasSemanticString() const; const std::string &GetSemanticString() const; llvm::StringRef GetSemanticStringRef() const; void SetSemanticString(const std::string &SemString); bool HasInterpolationMode() const; const InterpolationMode &GetInterpolationMode() const; void SetInterpolationMode(const InterpolationMode &IM); bool HasFieldName() const; const std::string &GetFieldName() const; void SetFieldName(const std::string &FieldName); private: bool m_bPrecise; CompType m_CompType; DxilMatrixAnnotation m_Matrix; unsigned m_CBufferOffset; std::string m_Semantic; InterpolationMode m_InterpMode; std::string m_FieldName; }; /// Use this class to represent LLVM structure annotation. class DxilStructAnnotation { friend class DxilTypeSystem; public: unsigned GetNumFields() const; DxilFieldAnnotation &GetFieldAnnotation(unsigned FieldIdx); const DxilFieldAnnotation &GetFieldAnnotation(unsigned FieldIdx) const; const llvm::StructType *GetStructType() const; unsigned GetCBufferSize() const; void SetCBufferSize(unsigned size); void MarkEmptyStruct(); bool IsEmptyStruct(); private: const llvm::StructType *m_pStructType; std::vector m_FieldAnnotations; unsigned m_CBufferSize; // The size of struct if inside constant buffer. }; enum class DxilParamInputQual { In, Out, Inout, InputPatch, OutputPatch, OutStream0, OutStream1, OutStream2, OutStream3, InputPrimitive, }; /// Use this class to represent type annotation for function parameter. class DxilParameterAnnotation : public DxilFieldAnnotation { public: DxilParameterAnnotation(); const DxilParamInputQual GetParamInputQual() const; void SetParamInputQual(DxilParamInputQual qual); const std::vector &GetSemanticIndexVec() const; void SetSemanticIndexVec(const std::vector &Vec); void AppendSemanticIndex(unsigned SemIdx); private: DxilParamInputQual m_inputQual; std::vector m_semanticIndex; }; /// Use this class to represent LLVM function annotation. class DxilFunctionAnnotation { friend class DxilTypeSystem; public: unsigned GetNumParameters() const; DxilParameterAnnotation &GetParameterAnnotation(unsigned ParamIdx); const DxilParameterAnnotation &GetParameterAnnotation(unsigned ParamIdx) const; const llvm::Function *GetFunction() const; DxilParameterAnnotation &GetRetTypeAnnotation(); const DxilParameterAnnotation &GetRetTypeAnnotation() const; private: const llvm::Function *m_pFunction; std::vector m_parameterAnnotations; DxilParameterAnnotation m_retTypeAnnotation; }; /// Use this class to represent structure type annotations in HL and DXIL. class DxilTypeSystem { public: using StructAnnotationMap = llvm::MapVector >; using FunctionAnnotationMap = llvm::MapVector >; DxilTypeSystem(llvm::Module *pModule); DxilStructAnnotation *AddStructAnnotation(const llvm::StructType *pStructType); DxilStructAnnotation *GetStructAnnotation(const llvm::StructType *pStructType); void EraseStructAnnotation(const llvm::StructType *pStructType); StructAnnotationMap &GetStructAnnotationMap(); DxilFunctionAnnotation *AddFunctionAnnotation(const llvm::Function *pFunction); DxilFunctionAnnotation *GetFunctionAnnotation(const llvm::Function *pFunction); void EraseFunctionAnnotation(const llvm::Function *pFunction); FunctionAnnotationMap &GetFunctionAnnotationMap(); // Utility methods to create stand-alone SNORM and UNORM. // We may want to move them to a more centralized place for most utilities. llvm::StructType *GetSNormF32Type(unsigned NumComps); llvm::StructType *GetUNormF32Type(unsigned NumComps); private: llvm::Module *m_pModule; StructAnnotationMap m_StructAnnotations; FunctionAnnotationMap m_FunctionAnnotations; llvm::StructType *GetNormFloatType(CompType CT, unsigned NumComps); }; DXIL::SigPointKind SigPointFromInputQual(DxilParamInputQual Q, DXIL::ShaderKind SK, bool isPC); } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/DxilValidation.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxilValidation.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // This file provides support for validating DXIL shaders. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include #include "dxc/Support/Global.h" #include "dxc/HLSL/DxilConstants.h" namespace llvm { class Module; class LLVMContext; class raw_ostream; } namespace hlsl { /* hctdb_instrhelp.get_valrule_enum()*/ // VALRULE-ENUM:BEGIN // Known validation rules enum class ValidationRule : unsigned { // Bitcode BitcodeValid, // TODO - Module must be bitcode-valid // Container ContainerPartInvalid, // DXIL Container must not contain unknown parts ContainerPartMatches, // DXIL Container Parts must match Module ContainerPartMissing, // DXIL Container requires certain parts, corresponding to module ContainerPartRepeated, // DXIL Container must have only one of each part type ContainerRootSignatureIncompatible, // Root Signature in DXIL Container must be compatible with shader // Declaration DeclDxilFnExtern, // External function must be a DXIL function DeclDxilNsReserved, // The DXIL reserved prefixes must only be used by built-in functions and types DeclFnFlattenParam, // Function parameters must not use struct types DeclFnIsCalled, // Functions can only be used by call instructions DeclNotUsedExternal, // External declaration should not be used DeclUsedExternalFunction, // External function must be used DeclUsedInternal, // Internal declaration must be used // Instruction InstrAllowed, // Instructions must be of an allowed type InstrBarrierModeForNonCS, // sync in a non-Compute Shader must only sync UAV (sync_uglobal) InstrBarrierModeNoMemory, // sync must include some form of memory barrier - _u (UAV) and/or _g (Thread Group Shared Memory). Only _t (thread group sync) is optional. InstrBarrierModeUselessUGroup, // sync can't specify both _ugroup and _uglobal. If both are needed, just specify _uglobal. InstrBufferUpdateCounterOnUAV, // BufferUpdateCounter valid only on UAV InstrCBufferClassForCBufferHandle, // Expect Cbuffer for CBufferLoad handle InstrCBufferOutOfBound, // Cbuffer access out of bound InstrCallOload, // Call to DXIL intrinsic must match overload signature InstrCannotPullPosition, // pull-model evaluation of position disallowed InstrCoordinateCountForRawTypedBuf, // raw/typed buffer don't need 2 coordinates InstrCoordinateCountForStructBuf, // structured buffer require 2 coordinates InstrDxilStructUser, // Dxil struct types should only used by ExtractValue InstrDxilStructUserOutOfBound, // Index out of bound when extract value from dxil struct types InstrEvalInterpolationMode, // Interpolation mode on %0 used with eval_* instruction must be linear, linear_centroid, linear_noperspective, linear_noperspective_centroid, linear_sample or linear_noperspective_sample InstrExtractValue, // ExtractValue should only be used on dxil struct types and cmpxchg InstrFailToResloveTGSMPointer, // TGSM pointers must originate from an unambiguous TGSM global variable. InstrHandleNotFromCreateHandle, // Resource handle should returned by createHandle InstrImmBiasForSampleB, // bias amount for sample_b must be in the range [%0,%1], but %2 was specified as an immediate InstrInBoundsAccess, // Access to out-of-bounds memory is disallowed InstrMinPrecisionNotPrecise, // Instructions marked precise may not refer to minprecision values InstrMinPrecisonBitCast, // Bitcast on minprecison types is not allowed InstrMipLevelForGetDimension, // Use mip level on buffer when GetDimensions InstrMipOnUAVLoad, // uav load don't support mipLevel/sampleIndex InstrNoGenericPtrAddrSpaceCast, // Address space cast between pointer types must have one part to be generic address space InstrNoIDivByZero, // No signed integer division by zero InstrNoIndefiniteAcos, // No indefinite arccosine InstrNoIndefiniteAsin, // No indefinite arcsine InstrNoIndefiniteDsxy, // No indefinite derivative calculation InstrNoIndefiniteLog, // No indefinite logarithm InstrNoReadingUninitialized, // Instructions should not read uninitialized value InstrNoUDivByZero, // No unsigned integer division by zero InstrOffsetOnUAVLoad, // uav load don't support offset InstrOload, // DXIL intrinsic overload must be valid InstrOnlyOneAllocConsume, // RWStructuredBuffers may increment or decrement their counters, but not both. InstrOpCodeReserved, // Instructions must not reference reserved opcodes InstrOpConst, // DXIL intrinsic requires an immediate constant operand InstrOpConstRange, // Constant values must be in-range for operation InstrOperandRange, // DXIL intrinsic operand must be within defined range InstrPtrBitCast, // Pointer type bitcast must be have same size InstrResourceClassForLoad, // load can only run on UAV/SRV resource InstrResourceClassForSamplerGather, // sample, lod and gather should on srv resource. InstrResourceClassForUAVStore, // store should on uav resource. InstrResourceCoordinateMiss, // coord uninitialized InstrResourceCoordinateTooMany, // out of bound coord must be undef InstrResourceKindForBufferLoadStore, // buffer load/store only works on Raw/Typed/StructuredBuffer InstrResourceKindForCalcLOD, // lod requires resource declared as texture1D/2D/3D/Cube/CubeArray/1DArray/2DArray InstrResourceKindForGather, // gather requires resource declared as texture/2D/Cube/2DArray/CubeArray InstrResourceKindForGetDim, // Invalid resource kind on GetDimensions InstrResourceKindForSample, // sample/_l/_d requires resource declared as texture1D/2D/3D/Cube/1DArray/2DArray/CubeArray InstrResourceKindForSampleC, // samplec requires resource declared as texture1D/2D/Cube/1DArray/2DArray/CubeArray InstrResourceKindForTextureLoad, // texture load only works on Texture1D/1DArray/2D/2DArray/3D/MS2D/MS2DArray InstrResourceKindForTextureStore, // texture store only works on Texture1D/1DArray/2D/2DArray/3D InstrResourceOffsetMiss, // offset uninitialized InstrResourceOffsetTooMany, // out of bound offset must be undef InstrSampleCompType, // sample_* instructions require resource to be declared to return UNORM, SNORM or FLOAT. InstrSampleIndexForLoad2DMS, // load on Texture2DMS/2DMSArray require sampleIndex InstrSamplerModeForLOD, // lod instruction requires sampler declared in default mode InstrSamplerModeForSample, // sample/_l/_d/_cl_s/gather instruction requires sampler declared in default mode InstrSamplerModeForSampleC, // sample_c_*/gather_c instructions require sampler declared in comparison mode InstrStructBitCast, // Bitcast on struct types is not allowed InstrTGSMRaceCond, // Race condition writing to shared memory detected, consider making this write conditional InstrTextureOffset, // offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7 InstrUndefResultForGetDimension, // GetDimensions used undef dimension %0 on %1 InstrWriteMaskForTypedUAVStore, // store on typed uav must write to all four components of the UAV InstrWriteMaskMatchValueForUAVStore, // uav store write mask must match store value mask, write mask is %0 and store value mask is %1 // Metadata MetaBranchFlatten, // Can't use branch and flatten attributes together MetaClipCullMaxComponents, // Combined elements of SV_ClipDistance and SV_CullDistance must fit in 8 components MetaClipCullMaxRows, // Combined elements of SV_ClipDistance and SV_CullDistance must fit in two rows. MetaControlFlowHintNotOnControlFlow, // Control flow hint only works on control flow inst MetaDenseResIDs, // Resource identifiers must be zero-based and dense MetaDuplicateSysValue, // System value may only appear once in signature MetaEntryFunction, // entrypoint not found MetaFlagsUsage, // Flags must match usage MetaForceCaseOnSwitch, // Attribute forcecase only works for switch MetaFunctionAnnotation, // Cannot find function annotation for %0 MetaGlcNotOnAppendConsume, // globallycoherent cannot be used with append/consume buffers MetaIntegerInterpMode, // Interpolation mode on integer must be Constant MetaInterpModeInOneRow, // Interpolation mode must be identical for all elements packed into the same row. MetaInterpModeValid, // Interpolation mode must be valid MetaInvalidControlFlowHint, // Invalid control flow hint MetaKnown, // Named metadata should be known MetaMaxTessFactor, // Hull Shader MaxTessFactor must be [%0..%1]. %2 specified MetaNoSemanticOverlap, // Semantics must not overlap MetaRequired, // TODO - Required metadata missing MetaSemaKindMatchesName, // Semantic name must match system value, when defined. MetaSemaKindValid, // Semantic kind must be valid MetaSemanticCompType, // %0 must be %1 MetaSemanticIndexMax, // System value semantics have a maximum valid semantic index MetaSemanticLen, // Semantic length must be at least 1 and at most 64 MetaSemanticShouldBeAllocated, // Semantic should have a valid packing location MetaSemanticShouldNotBeAllocated, // Semantic should have a packing location of -1 MetaSignatureCompType, // signature %0 specifies unrecognized or invalid component type MetaSignatureIllegalComponentOrder, // Component ordering for packed elements must be: arbitrary < system value < system generated value MetaSignatureIndexConflict, // Only elements with compatible indexing rules may be packed together MetaSignatureOutOfRange, // Signature elements must fit within maximum signature size MetaSignatureOverlap, // Signature elements may not overlap in packing location. MetaStructBufAlignment, // StructuredBuffer stride not aligned MetaStructBufAlignmentOutOfBound, // StructuredBuffer stride out of bounds MetaSystemValueRows, // System value may only have 1 row MetaTarget, // Target triple must be 'dxil-ms-dx' MetaTessellatorOutputPrimitive, // Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW. MetaTessellatorPartition, // Invalid Tessellator Partitioning specified. Must be integer, pow2, fractional_odd or fractional_even. MetaTextureType, // elements of typed buffers and textures must fit in four 32-bit quantities MetaUsed, // All metadata must be used by dxil MetaValidSamplerMode, // Invalid sampler mode on sampler MetaValueRange, // Metadata value must be within range MetaWellFormed, // TODO - Metadata must be well-formed in operand count and types // Program flow FlowDeadLoop, // Loop must have break FlowFunctionCall, // Function with parameter is not permitted FlowNoRecusion, // Recursion is not permitted FlowReducible, // Execution flow must be reducible // Shader model SmAppendAndConsumeOnSameUAV, // BufferUpdateCounter inc and dec on a given UAV (%d) cannot both be in the same shader for shader model less than 5.1. SmCBufferElementOverflow, // CBuffer elements must not overflow SmCBufferOffsetOverlap, // CBuffer offsets must not overlap SmCBufferTemplateTypeMustBeStruct, // D3D12 constant/texture buffer template element can only be a struct SmCSNoReturn, // Compute shaders can't return values, outputs must be written in writable resources (UAVs). SmCompletePosition, // Not all elements of SV_Position were written SmCounterOnlyOnStructBuf, // BufferUpdateCounter valid only on structured buffers SmDSInputControlPointCountRange, // DS input control point count must be [0..%0]. %1 specified SmDomainLocationIdxOOB, // DomainLocation component index out of bounds for the domain. SmGSInstanceCountRange, // GS instance count must be [1..%0]. %1 specified SmGSOutputVertexCountRange, // GS output vertex count must be [0..%0]. %1 specified SmGSTotalOutputVertexDataRange, // Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2. This value cannot be greater than %3 SmGSValidInputPrimitive, // GS input primitive unrecognized SmGSValidOutputPrimitiveTopology, // GS output primitive topology unrecognized SmHSInputControlPointCountRange, // HS input control point count must be [0..%0]. %1 specified SmHullPassThruControlPointCountMatch, // For pass thru hull shader, input control point count must match output control point count SmInsideTessFactorSizeMatchDomain, // InsideTessFactor rows, columns (%0, %1) invalid for domain %2. Expected %3 rows and 1 column. SmInvalidResourceCompType, // Invalid resource return type SmInvalidResourceKind, // Invalid resources kind SmInvalidTextureKindOnUAV, // Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs SmIsoLineOutputPrimitiveMismatch, // Hull Shader declared with IsoLine Domain must specify output primitive point or line. Triangle_cw or triangle_ccw output are not compatible with the IsoLine Domain. SmMaxTGSMSize, // Total Thread Group Shared Memory storage is %0, exceeded %1 SmMaxTheadGroup, // Declared Thread Group Count %0 (X*Y*Z) is beyond the valid maximum of %1 SmMultiStreamMustBePoint, // When multiple GS output streams are used they must be pointlists SmName, // Target shader model name must be known SmNoInterpMode, // Interpolation mode must be undefined for VS input/PS output/patch constant. SmNoPSOutputIdx, // Pixel shader output registers are not indexable. SmOpcode, // Opcode must be defined in target shader model SmOpcodeInInvalidFunction, // Invalid DXIL opcode usage like StorePatchConstant in patch constant function SmOperand, // Operand must be defined in target shader model SmOutputControlPointCountRange, // output control point count must be [0..%0]. %1 specified SmOutputControlPointsTotalScalars, // Total number of scalars across all HS output control points must not exceed SmPSConsistentInterp, // Interpolation mode for PS input position must be linear_noperspective_centroid or linear_noperspective_sample when outputting oDepthGE or oDepthLE and not running at sample frequency (which is forced by inputting SV_SampleIndex or declaring an input linear_sample or linear_noperspective_sample) SmPSCoverageAndInnerCoverage, // InnerCoverage and Coverage are mutually exclusive. SmPSMultipleDepthSemantic, // Pixel Shader only allows one type of depth semantic to be declared SmPSOutputSemantic, // Pixel Shader allows output semantics to be SV_Target, SV_Depth, SV_DepthGreaterEqual, SV_DepthLessEqual, SV_Coverage or SV_StencilRef, %0 found SmPSTargetCol0, // SV_Target packed location must start at column 0 SmPSTargetIndexMatchesRow, // SV_Target semantic index must match packed row location SmPatchConstantOnlyForHSDS, // patch constant signature only valid in HS and DS SmROVOnlyInPS, // RasterizerOrdered objects are only allowed in 5.0+ pixel shaders SmResourceRangeOverlap, // Resource ranges must not overlap SmSampleCountOnlyOn2DMS, // Only Texture2DMS/2DMSArray could has sample count SmSemantic, // Semantic must be defined in target shader model SmStreamIndexRange, // Stream index (%0) must between 0 and %1 SmTessFactorForDomain, // Required TessFactor for domain not found declared anywhere in Patch Constant data SmTessFactorSizeMatchDomain, // TessFactor rows, columns (%0, %1) invalid for domain %2. Expected %3 rows and 1 column. SmThreadGroupChannelRange, // Declared Thread Group %0 size %1 outside valid range [%2..%3] SmTriOutputPrimitiveMismatch, // Hull Shader declared with Tri Domain must specify output primitive point, triangle_cw or triangle_ccw. Line output is not compatible with the Tri domain SmUndefinedOutput, // Not all elements of output %0 were written SmValidDomain, // Invalid Tessellator Domain specified. Must be isoline, tri or quad SmZeroHSInputControlPointWithInput, // When HS input control point count is 0, no input signature should exist // Type system TypesDefined, // Type must be defined based on DXIL primitives TypesI8, // I8 can only used as immediate value for intrinsic TypesIntWidth, // Int type must be of valid width TypesNoMultiDim, // Only one dimension allowed for array type TypesNoVector, // Vector types must not be present // Uniform analysis UniNoWaveSensitiveGradient, // Gradient operations are not affected by wave-sensitive data or control flow. }; // VALRULE-ENUM:END const char *GetValidationRuleText(ValidationRule value); void GetValidationVersion(_Out_ unsigned *pMajor, _Out_ unsigned *pMinor); HRESULT ValidateDxilModule(_In_ llvm::Module *pModule, _In_opt_ llvm::Module *pDebugModule); // DXIL Container Verification Functions (return false on failure) bool VerifySignatureMatches(_In_ llvm::Module *pModule, hlsl::DXIL::SignatureKind SigKind, _In_reads_bytes_(SigSize) const void *pSigData, _In_ uint32_t SigSize); // PSV = data for Pipeline State Validation bool VerifyPSVMatches(_In_ llvm::Module *pModule, _In_reads_bytes_(PSVSize) const void *pPSVData, _In_ uint32_t PSVSize); bool VerifyFeatureInfoMatches(_In_ llvm::Module *pModule, _In_reads_bytes_(FeatureInfoSize) const void *pFeatureInfoData, _In_ uint32_t FeatureInfoSize); // Validate the container parts, assuming supplied module is valid, loaded from the container provided struct DxilContainerHeader; HRESULT ValidateDxilContainerParts(_In_ llvm::Module *pModule, _In_opt_ llvm::Module *pDebugModule, _In_reads_bytes_(ContainerSize) const DxilContainerHeader *pContainer, _In_ uint32_t ContainerSize); // Loads module, validating load, but not module. HRESULT ValidateLoadModule(_In_reads_bytes_(ILLength) const char *pIL, _In_ uint32_t ILLength, _In_ std::unique_ptr &pModule, _In_ llvm::LLVMContext &Ctx, _In_ llvm::raw_ostream &DiagStream); // Load and validate Dxil module from bitcode. HRESULT ValidateDxilBitcode(_In_reads_bytes_(ILLength) const char *pIL, _In_ uint32_t ILLength, _In_ llvm::raw_ostream &DiagStream); // Full container validation, including ValidateDxilModule HRESULT ValidateDxilContainer(_In_reads_bytes_(ContainerSize) const void *pContainer, _In_ uint32_t ContainerSize, _In_ llvm::raw_ostream &DiagStream); } ================================================ FILE: src/Wrapper/dxc/HLSL/HLMatrixLowerHelper.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLMatrixLowerHelper.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // This file provides helper functions to lower high level matrix. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "llvm/IR/IRBuilder.h" namespace llvm { class Type; class Value; template class ArrayRef; } namespace hlsl { namespace HLMatrixLower { // TODO: use type annotation. bool IsMatrixType(llvm::Type *Ty); // Translate matrix type to vector type. llvm::Type *LowerMatrixType(llvm::Type *Ty); // TODO: use type annotation. llvm::Type *GetMatrixInfo(llvm::Type *Ty, unsigned &col, unsigned &row); // TODO: use type annotation. bool IsMatrixArrayPointer(llvm::Type *Ty); // Translate matrix array pointer type to vector array pointer type. llvm::Type *LowerMatrixArrayPointer(llvm::Type *Ty); llvm::Value *BuildMatrix(llvm::Type *EltTy, unsigned col, unsigned row, bool colMajor, llvm::ArrayRef elts, llvm::IRBuilder<> &Builder); } // namespace HLMatrixLower } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/HLMatrixLowerPass.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLMatrixLowerPass.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // This file provides a high level matrix lower pass. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once namespace llvm { class ModulePass; class PassRegistry; /// \brief Create and return a pass that lower high level matrix. /// Note that this pass is designed for use with the legacy pass manager. ModulePass *createHLMatrixLowerPass(); void initializeHLMatrixLowerPassPass(llvm::PassRegistry&); } ================================================ FILE: src/Wrapper/dxc/HLSL/HLModule.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLModule.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // HighLevel DX IR module. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/Support/Global.h" #include "dxc/HLSL/DxilMetadataHelper.h" #include "dxc/HLSL/DxilConstants.h" #include "dxc/HLSL/HLResource.h" #include "dxc/HLSL/HLOperations.h" #include "dxc/HLSL/DxilSampler.h" #include "dxc/HLSL/DxilShaderModel.h" #include "dxc/HLSL/DxilSignature.h" #include #include #include #include namespace llvm { class LLVMContext; class Module; class Function; class Instruction; class MDTuple; class MDNode; class GlobalVariable; class DIGlobalVariable; class DebugInfoFinder; }; namespace hlsl { class ShaderModel; class OP; class RootSignatureHandle; struct HLFunctionProps { union { // TODO: not every function need this union. // Compute shader. struct { unsigned numThreads[3]; } CS; // Geometry shader. struct { DXIL::InputPrimitive inputPrimitive; unsigned maxVertexCount; unsigned instanceCount; DXIL::PrimitiveTopology streamPrimitiveTopologies[DXIL::kNumOutputStreams]; } GS; // Hull shader. struct { llvm::Function *patchConstantFunc; DXIL::TessellatorDomain domain; DXIL::TessellatorPartitioning partition; DXIL::TessellatorOutputPrimitive outputPrimitive; unsigned inputControlPoints; unsigned outputControlPoints; float maxTessFactor; } HS; // Domain shader. struct { DXIL::TessellatorDomain domain; unsigned inputControlPoints; } DS; // Vertex shader. struct { llvm::Constant *clipPlanes[DXIL::kNumClipPlanes]; } VS; // Pixel shader. struct { bool EarlyDepthStencil; } PS; } ShaderProps; DXIL::ShaderKind shaderKind; }; struct HLOptions { HLOptions() : bDefaultRowMajor(false), bIEEEStrict(false), bDisableOptimizations(false), bLegacyCBufferLoad(false), PackingStrategy(0), unused(0) { } uint32_t GetHLOptionsRaw() const; void SetHLOptionsRaw(uint32_t data); unsigned bDefaultRowMajor : 1; unsigned bIEEEStrict : 1; unsigned bAllResourcesBound : 1; unsigned bDisableOptimizations : 1; unsigned bLegacyCBufferLoad : 1; unsigned PackingStrategy : 2; static_assert((unsigned)DXIL::PackingStrategy::Invalid < 4, "otherwise 2 bits is not enough to store PackingStrategy"); unsigned unused : 25; }; /// Use this class to manipulate HLDXIR of a shader. class HLModule { public: HLModule(llvm::Module *pModule); ~HLModule(); using Domain = DXIL::TessellatorDomain; // Subsystems. llvm::LLVMContext &GetCtx() const; llvm::Module *GetModule() const; OP *GetOP() const; void SetShaderModel(const ShaderModel *pSM); const ShaderModel *GetShaderModel() const; // HLOptions void SetHLOptions(HLOptions &opts); const HLOptions &GetHLOptions() const; // Entry function. llvm::Function *GetEntryFunction() const; void SetEntryFunction(llvm::Function *pEntryFunc); const std::string &GetEntryFunctionName() const; void SetEntryFunctionName(const std::string &name); // Resources. unsigned AddCBuffer(std::unique_ptr pCB); DxilCBuffer &GetCBuffer(unsigned idx); const DxilCBuffer &GetCBuffer(unsigned idx) const; const std::vector > &GetCBuffers() const; unsigned AddSampler(std::unique_ptr pSampler); DxilSampler &GetSampler(unsigned idx); const DxilSampler &GetSampler(unsigned idx) const; const std::vector > &GetSamplers() const; unsigned AddSRV(std::unique_ptr pSRV); HLResource &GetSRV(unsigned idx); const HLResource &GetSRV(unsigned idx) const; const std::vector > &GetSRVs() const; unsigned AddUAV(std::unique_ptr pUAV); HLResource &GetUAV(unsigned idx); const HLResource &GetUAV(unsigned idx) const; const std::vector > &GetUAVs() const; void RemoveGlobal(llvm::GlobalVariable *GV); void RemoveFunction(llvm::Function *F); void RemoveResources(llvm::GlobalVariable **ppVariables, unsigned count); // ThreadGroupSharedMemory. typedef std::vector::iterator tgsm_iterator; tgsm_iterator tgsm_begin(); tgsm_iterator tgsm_end(); void AddGroupSharedVariable(llvm::GlobalVariable *GV); // Signatures. DxilSignature &GetInputSignature(); DxilSignature &GetOutputSignature(); DxilSignature &GetPatchConstantSignature(); RootSignatureHandle &GetRootSignature(); // HLFunctionProps. bool HasHLFunctionProps(llvm::Function *F); HLFunctionProps &GetHLFunctionProps(llvm::Function *F); void AddHLFunctionProps(llvm::Function *F, std::unique_ptr &info); DxilFunctionAnnotation *GetFunctionAnnotation(llvm::Function *F); DxilFunctionAnnotation *AddFunctionAnnotation(llvm::Function *F); void AddResourceTypeAnnotation(llvm::Type *Ty, DXIL::ResourceClass resClass, DXIL::ResourceKind kind); DXIL::ResourceClass GetResourceClass(llvm::Type *Ty); DXIL::ResourceKind GetResourceKind(llvm::Type *Ty); // HLDXIR metadata manipulation. /// Serialize HLDXIR in-memory form to metadata form. void EmitHLMetadata(); /// Deserialize HLDXIR metadata form into in-memory form. void LoadHLMetadata(); /// Delete any HLDXIR from the specified module. static void ClearHLMetadata(llvm::Module &M); // Type related methods. static bool IsStreamOutputPtrType(llvm::Type *Ty); static bool IsStreamOutputType(llvm::Type *Ty); static bool IsHLSLObjectType(llvm::Type *Ty); static unsigned GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation, llvm::Type *Ty, DxilTypeSystem &typeSys); static bool IsStaticGlobal(llvm::GlobalVariable *GV); static bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV); static void GetParameterRowsAndCols(llvm::Type *Ty, unsigned &rows, unsigned &cols, DxilParameterAnnotation ¶mAnnotation); static const char *GetLegacyDataLayoutDesc(); // HL code gen. template static llvm::Value *EmitHLOperationCall(BuilderTy &Builder, HLOpcodeGroup group, unsigned opcode, llvm::Type *RetType, llvm::ArrayRef paramList, llvm::Module &M); static unsigned FindCastOp(bool fromUnsigned, bool toUnsigned, llvm::Type *SrcTy, llvm::Type *DstTy); // Precise attribute. // Note: Precise will be marked on alloca inst with metadata in code gen. // But mem2reg will remove alloca inst, so need mark precise with // function call before mem2reg. static bool HasPreciseAttributeWithMetadata(llvm::Instruction *I); static void MarkPreciseAttributeWithMetadata(llvm::Instruction *I); static void ClearPreciseAttributeWithMetadata(llvm::Instruction *I); static void MarkPreciseAttributeOnPtrWithFunctionCall(llvm::Value *Ptr, llvm::Module &M); static bool HasPreciseAttribute(llvm::Function *F); // DXIL type system. DxilTypeSystem &GetTypeSystem(); /// Emit llvm.used array to make sure that optimizations do not remove unreferenced globals. void EmitLLVMUsed(); std::vector &GetLLVMUsed(); // Release functions used to transfer ownership. DxilSignature *ReleaseInputSignature(); DxilSignature *ReleaseOutputSignature(); DxilSignature *ReleasePatchConstantSignature(); DxilTypeSystem *ReleaseTypeSystem(); OP *ReleaseOP(); RootSignatureHandle *ReleaseRootSignature(); llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder(); static llvm::DIGlobalVariable * FindGlobalVariableDebugInfo(llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder); // Create global variable debug info for element global variable based on the // whole global variable. static void CreateElementGlobalVariableDebugInfo( llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder, llvm::GlobalVariable *EltGV, unsigned sizeInBits, unsigned alignInBits, unsigned offsetInBits, llvm::StringRef eltName); // Replace GV with NewGV in GlobalVariable debug info. static void UpdateGlobalVariableDebugInfo(llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder, llvm::GlobalVariable *NewGV); private: // Signatures. std::unique_ptr m_InputSignature; std::unique_ptr m_OutputSignature; std::unique_ptr m_PatchConstantSignature; std::unique_ptr m_RootSignature; // Shader resources. std::vector > m_SRVs; std::vector > m_UAVs; std::vector > m_CBuffers; std::vector > m_Samplers; // ThreadGroupSharedMemory. std::vector m_TGSMVariables; // High level function info. std::unordered_map> m_HLFunctionPropsMap; // Resource type annotation. std::unordered_map> m_ResTypeAnnotation; private: llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule; llvm::Function *m_pEntryFunc; std::string m_EntryName; std::unique_ptr m_pMDHelper; std::unique_ptr m_pDebugInfoFinder; const ShaderModel *m_pSM; unsigned m_DxilMajor; unsigned m_DxilMinor; HLOptions m_Options; std::unique_ptr m_pOP; size_t m_pUnused; // DXIL metadata serialization/deserialization. llvm::MDTuple *EmitHLResources(); void LoadHLResources(const llvm::MDOperand &MDO); llvm::MDTuple *EmitHLShaderProperties(); void LoadHLShaderProperties(const llvm::MDOperand &MDO); llvm::MDTuple *EmitDxilShaderProperties(); llvm::MDTuple *EmitResTyAnnotations(); void LoadResTyAnnotations(const llvm::MDOperand &MDO); // LLVM used. std::vector m_LLVMUsed; // Type annotations. std::unique_ptr m_pTypeSystem; // Helpers. template unsigned AddResource(std::vector > &Vec, std::unique_ptr pRes); }; /// Use this class to manipulate metadata of extra metadata record properties that are specific to high-level DX IR. class HLExtraPropertyHelper : public DxilExtraPropertyHelper { public: HLExtraPropertyHelper(llvm::Module *pModule); virtual void EmitSignatureElementProperties(const DxilSignatureElement &SE, std::vector &MDVals); virtual void LoadSignatureElementProperties(const llvm::MDOperand &MDO, DxilSignatureElement &SE); }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/HLOperationLower.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLOperationLower.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Lower functions to lower HL operations to DXIL operations. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once namespace llvm { class Instruction; class Value; class Function; } namespace hlsl { class HLModule; class DxilResourceBase; class HLSLExtensionsCodegenHelper; void TranslateBuiltinOperations( HLModule &HLM, std::unordered_map &handleMap, HLSLExtensionsCodegenHelper *extCodegenHelper); } ================================================ FILE: src/Wrapper/dxc/HLSL/HLOperationLowerExtension.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLOperationLowerExtension.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Functions to lower HL operations coming from HLSL extensions to DXIL // // operations. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/HLSLExtensionsCodegenHelper.h" #include "llvm/ADT/StringRef.h" #include #include namespace llvm { class Value; class CallInst; class Function; class StringRef; class Instruction; } namespace hlsl { class OP; // Lowers HLSL extensions from HL operation to DXIL operation. class ExtensionLowering { public: // Strategy used for lowering extensions. enum class Strategy { Unknown, // Do not know how to lower. This is an error condition. NoTranslation, // Propagate the call arguments as is down to dxil. Replicate, // Scalarize the vector arguments and replicate the call. Pack, // Convert the vector arguments into structs. Resource, // Convert return value to resource return and explode vectors. }; typedef std::unordered_map HandleMap; // Create the lowering using the given strategy and custom codegen helper. ExtensionLowering(llvm::StringRef strategy, HLSLExtensionsCodegenHelper *helper, const HandleMap &handleMap, OP& hlslOp); ExtensionLowering(Strategy strategy, HLSLExtensionsCodegenHelper *helper, const HandleMap &handleMap, OP& hlslOp); // Translate the HL op call to a DXIL op call. // Returns a new value if translation was successful. // Returns nullptr if translation failed or made no changes. llvm::Value *Translate(llvm::CallInst *CI); // Translate the strategy string to an enum. The strategy string is // added as a custom attribute on the high level extension function. // It is translated as follows: // "r" -> Replicate // "n" -> NoTranslation // "c" -> Custom static Strategy GetStrategy(llvm::StringRef strategy); // Translate the strategy enum into a name. This is the inverse of the // GetStrategy() function. static llvm::StringRef GetStrategyName(Strategy strategy); // Get the name that will be used for the extension function call after // lowering. std::string GetExtensionName(llvm::CallInst *CI); private: Strategy m_strategy; HLSLExtensionsCodegenHelper *m_helper; const HandleMap &m_handleMap; OP &m_hlslOp; llvm::Value *Unknown(llvm::CallInst *CI); llvm::Value *NoTranslation(llvm::CallInst *CI); llvm::Value *Replicate(llvm::CallInst *CI); llvm::Value *Pack(llvm::CallInst *CI); llvm::Value *Resource(llvm::CallInst *CI); }; } ================================================ FILE: src/Wrapper/dxc/HLSL/HLOperations.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLOperations.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Implentation of High Level DXIL operations. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include namespace llvm { class Module; class Function; class CallInst; class Argument; class StringRef; class FunctionType; } namespace hlsl { enum class HLOpcodeGroup { NotHL, HLExtIntrinsic, HLIntrinsic, HLCast, HLInit, HLBinOp, HLUnOp, HLSubscript, HLMatLoadStore, HLSelect, NumOfHLOps }; enum class HLBinaryOpcode { Invalid, Mul, Div, Rem, Add, Sub, Shl, Shr, LT, GT, LE, GE, EQ, NE, And, Xor, Or, LAnd, LOr, UDiv, URem, UShr, ULT, UGT, ULE, UGE, NumOfBO, }; enum class HLUnaryOpcode { Invalid, PostInc, PostDec, PreInc, PreDec, Plus, Minus, Not, LNot, NumOfUO, }; enum class HLSubscriptOpcode { DefaultSubscript, ColMatSubscript, RowMatSubscript, ColMatElement, RowMatElement, DoubleSubscript, CBufferSubscript, VectorSubscript, // Only for bool vector, other vector type will use GEP directly. }; enum class HLCastOpcode { DefaultCast, UnsignedUnsignedCast, FromUnsignedCast, ToUnsignedCast, ColMatrixToVecCast, RowMatrixToVecCast, }; enum class HLMatLoadStoreOpcode { ColMatLoad, ColMatStore, RowMatLoad, RowMatStore, }; extern const char * const HLPrefix; HLOpcodeGroup GetHLOpcodeGroup(llvm::Function *F); HLOpcodeGroup GetHLOpcodeGroupByName(llvm::Function *F); llvm::StringRef GetHLOpcodeGroupNameByAttr(llvm::Function *F); llvm::StringRef GetHLLowerStrategy(llvm::Function *F); unsigned GetHLOpcode(llvm::CallInst *CI); unsigned GetRowMajorOpcode(HLOpcodeGroup group, unsigned opcode); void SetHLLowerStrategy(llvm::Function *F, llvm::StringRef S); // For intrinsic opcode. bool HasUnsignedOpcode(unsigned opcode); unsigned GetUnsignedOpcode(unsigned opcode); // For HLBinaryOpcode. bool HasUnsignedOpcode(HLBinaryOpcode opcode); HLBinaryOpcode GetUnsignedOpcode(HLBinaryOpcode opcode); llvm::StringRef GetHLOpcodeGroupName(HLOpcodeGroup op); namespace HLOperandIndex { // Opcode parameter. const unsigned kOpcodeIdx = 0; // Matrix store. const unsigned kMatStoreDstPtrOpIdx = 1; const unsigned kMatStoreValOpIdx = 2; // Matrix load. const unsigned kMatLoadPtrOpIdx = 1; // Normal subscipts. const unsigned kSubscriptObjectOpIdx = 1; const unsigned kSubscriptIndexOpIdx = 2; // Double subscripts. const unsigned kDoubleSubscriptMipLevelOpIdx = 3; // Matrix subscripts. const unsigned kMatSubscriptMatOpIdx = 1; const unsigned kMatSubscriptSubOpIdx = 2; // Matrix init. const unsigned kMatArrayInitMatOpIdx = 1; const unsigned kMatArrayInitFirstArgOpIdx = 2; // Array Init. const unsigned kArrayInitPtrOpIdx = 1; const unsigned kArrayInitFirstArgOpIdx = 2; // Normal Init. const unsigned kInitFirstArgOpIdx = 1; // Unary operators. const unsigned kUnaryOpSrc0Idx = 1; // Binary operators. const unsigned kBinaryOpSrc0Idx = 1; const unsigned kBinaryOpSrc1Idx = 2; // Trinary operators. const unsigned kTrinaryOpSrc0Idx = 1; const unsigned kTrinaryOpSrc1Idx = 2; const unsigned kTrinaryOpSrc2Idx = 3; // Interlocked. const unsigned kInterlockedDestOpIndex = 1; const unsigned kInterlockedValueOpIndex = 2; const unsigned kInterlockedOriginalValueOpIndex = 3; // InterlockedCompareExchange. const unsigned kInterlockedCmpDestOpIndex = 1; const unsigned kInterlockedCmpCompareValueOpIndex = 2; const unsigned kInterlockedCmpValueOpIndex = 3; const unsigned kInterlockedCmpOriginalValueOpIndex = 4; // Lerp. const unsigned kLerpOpXIdx = 1; const unsigned kLerpOpYIdx = 2; const unsigned kLerpOpSIdx = 3; // ProcessTessFactorIsoline. const unsigned kProcessTessFactorRawDetailFactor = 1; const unsigned kProcessTessFactorRawDensityFactor = 2; const unsigned kProcessTessFactorRoundedDetailFactor = 3; const unsigned kProcessTessFactorRoundedDensityFactor = 4; // ProcessTessFactor. const unsigned kProcessTessFactorRawEdgeFactor = 1; const unsigned kProcessTessFactorInsideScale = 2; const unsigned kProcessTessFactorRoundedEdgeFactor = 3; const unsigned kProcessTessFactorRoundedInsideFactor = 4; const unsigned kProcessTessFactorUnRoundedInsideFactor = 5; // Reflect. const unsigned kReflectOpIIdx = 1; const unsigned kReflectOpNIdx = 2; // Refract const unsigned kRefractOpIIdx = 1; const unsigned kRefractOpNIdx = 2; const unsigned kRefractOpEtaIdx = 3; // SmoothStep. const unsigned kSmoothStepOpMinIdx = 1; const unsigned kSmoothStepOpMaxIdx = 2; const unsigned kSmoothStepOpXIdx = 3; // Clamp const unsigned kClampOpXIdx = 1; const unsigned kClampOpMinIdx = 2; const unsigned kClampOpMaxIdx = 3; // Object functions. const unsigned kHandleOpIdx = 1; // Store. const unsigned kStoreOffsetOpIdx = 2; const unsigned kStoreValOpIdx = 3; // Load. const unsigned kBufLoadAddrOpIdx = 2; const unsigned kBufLoadStatusOpIdx = 3; const unsigned kRWTexLoadStatusOpIdx = 3; const unsigned kTexLoadOffsetOpIdx = 3; const unsigned kTexLoadStatusOpIdx = 4; // Load for Texture2DMS const unsigned kTex2DMSLoadSampleIdxOpIdx = 3; const unsigned kTex2DMSLoadOffsetOpIdx = 4; const unsigned kTex2DMSLoadStatusOpIdx = 5; // mips.Operator. const unsigned kMipLoadAddrOpIdx = 3; const unsigned kMipLoadOffsetOpIdx = 4; const unsigned kMipLoadStatusOpIdx = 5; // Sample. const unsigned kSampleSamplerArgIndex = 2; const unsigned kSampleCoordArgIndex = 3; const unsigned kSampleOffsetArgIndex = 4; const unsigned kSampleClampArgIndex = 5; const unsigned kSampleStatusArgIndex = 6; // SampleG. const unsigned kSampleGDDXArgIndex = 4; const unsigned kSampleGDDYArgIndex = 5; const unsigned kSampleGOffsetArgIndex = 6; const unsigned kSampleGClampArgIndex = 7; const unsigned kSampleGStatusArgIndex = 8; // SampleCmp. const unsigned kSampleCmpCmpValArgIndex = 4; const unsigned kSampleCmpOffsetArgIndex = 5; const unsigned kSampleCmpClampArgIndex = 6; const unsigned kSampleCmpStatusArgIndex = 7; // SampleBias. const unsigned kSampleBBiasArgIndex = 4; const unsigned kSampleBOffsetArgIndex = 5; const unsigned kSampleBClampArgIndex = 6; const unsigned kSampleBStatusArgIndex = 7; // SampleLevel. const unsigned kSampleLLevelArgIndex = 4; const unsigned kSampleLOffsetArgIndex = 5; const unsigned kSampleLStatusArgIndex = 6; // SampleCmpLevelZero. const unsigned kSampleCmpLZCmpValArgIndex = 4; const unsigned kSampleCmpLZOffsetArgIndex = 5; const unsigned kSampleCmpLZStatusArgIndex = 6; // Gather. const unsigned kGatherSamplerArgIndex = 2; const unsigned kGatherCoordArgIndex = 3; const unsigned kGatherOffsetArgIndex = 4; const unsigned kGatherStatusArgIndex = 5; const unsigned kGatherSampleOffsetArgIndex = 5; const unsigned kGatherStatusWithSampleOffsetArgIndex = 8; // GatherCmp. const unsigned kGatherCmpCmpValArgIndex = 4; const unsigned kGatherCmpOffsetArgIndex = 5; const unsigned kGatherCmpStatusArgIndex = 6; const unsigned kGatherCmpSampleOffsetArgIndex = 6; const unsigned kGatherCmpStatusWithSampleOffsetArgIndex = 9; // StreamAppend. const unsigned kStreamAppendStreamOpIndex = 1; const unsigned kStreamAppendDataOpIndex = 2; // Append. const unsigned kAppendValOpIndex = 2; // Interlocked. const unsigned kObjectInterlockedDestOpIndex = 2; const unsigned kObjectInterlockedValueOpIndex = 3; const unsigned kObjectInterlockedOriginalValueOpIndex = 4; // InterlockedCompareExchange. const unsigned kObjectInterlockedCmpDestOpIndex = 2; const unsigned kObjectInterlockedCmpCompareValueOpIndex = 3; const unsigned kObjectInterlockedCmpValueOpIndex = 4; const unsigned kObjectInterlockedCmpOriginalValueOpIndex = 5; // GetSamplePosition. const unsigned kGetSamplePositionSampleIdxOpIndex = 2; // GetDimensions. const unsigned kGetDimensionsMipLevelOpIndex = 2; const unsigned kGetDimensionsMipWidthOpIndex = 3; const unsigned kGetDimensionsNoMipWidthOpIndex = 2; // WaveAllEqual. const unsigned kWaveAllEqualValueOpIdx = 1; } // namespace HLOperandIndex llvm::Function *GetOrCreateHLFunction(llvm::Module &M, llvm::FunctionType *funcTy, HLOpcodeGroup group, unsigned opcode); llvm::Function *GetOrCreateHLFunction(llvm::Module &M, llvm::FunctionType *funcTy, HLOpcodeGroup group, llvm::StringRef *groupName, llvm::StringRef *fnName, unsigned opcode); llvm::Function *GetOrCreateHLFunctionWithBody(llvm::Module &M, llvm::FunctionType *funcTy, HLOpcodeGroup group, unsigned opcode, llvm::StringRef name); } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/HLResource.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLResource.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Representation of HLSL SRVs and UAVs in high-level DX IR. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/HLSL/DxilResource.h" namespace hlsl { /// Use this class to represent an HLSL resource (SRV/UAV) in HLDXIR. class HLResource : public DxilResource { public: //QQQ // TODO: this does not belong here. QQQ //static Kind KeywordToKind(const std::string &keyword); HLResource(); }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/HLSL/HLSLExtensionsCodegenHelper.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLSLExtensionsCodegenHelper.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Codegen support for hlsl extensions. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include #include namespace llvm { class CallInst; class Value; class Module; } namespace hlsl { // Provide DXIL codegen support for private HLSL extensions. // The HLSL extension mechanism has hooks for two cases: // // 1. You can mark certain defines as "semantic" defines which // will be preserved as metadata in the final DXIL. // 2. You can add new HLSL intrinsic functions. // 3. You can read a root signature from a custom define. // // This class provides an interface for generating the DXIL bitcode // needed for the types of extensions above. // class HLSLExtensionsCodegenHelper { public: // Used to indicate a semantic define was used incorrectly. // Since semantic defines have semantic meaning it is possible // that a programmer can use them incorrectly. This class provides // a way to signal the error to the programmer. Semantic define // errors will be propagated as errors to the clang frontend. class SemanticDefineError { public: enum class Level { Warning, Error }; SemanticDefineError(unsigned location, Level level, const std::string &message) : m_location(location) , m_level(level) , m_message(message) { } unsigned Location() const { return m_location; } bool IsWarning() const { return m_level == Level::Warning; } const std::string &Message() const { return m_message; } private: unsigned m_location; // Use an encoded clang::SourceLocation to avoid a clang include dependency. Level m_level; std::string m_message; }; typedef std::vector SemanticDefineErrorList; // Write semantic defines as metadata in the module. virtual SemanticDefineErrorList WriteSemanticDefines(llvm::Module *M) = 0; // Get the name to use for the dxil intrinsic function. virtual std::string GetIntrinsicName(unsigned opcode) = 0; // Struct to hold a root signature that is read from a define. struct CustomRootSignature { std::string RootSignature; unsigned EncodedSourceLocation; enum Status { NOT_FOUND = 0, FOUND }; }; // Get custom defined root signature. virtual CustomRootSignature::Status GetCustomRootSignature(CustomRootSignature *out) = 0; // Virtual destructor. virtual ~HLSLExtensionsCodegenHelper() {}; }; } ================================================ FILE: src/Wrapper/dxc/HLSL/ReducibilityAnalysis.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // ReducibilityAnalysis.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Implements reducibility analysis pass. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once namespace llvm { class Module; class Function; class PassRegistry; class FunctionPass; enum class IrreducibilityAction { ThrowException, PrintLog, Ignore, }; extern char &ReducibilityAnalysisID; llvm::FunctionPass *createReducibilityAnalysisPass(IrreducibilityAction Action = IrreducibilityAction::ThrowException); void initializeReducibilityAnalysisPass(llvm::PassRegistry&); bool IsReducible(const llvm::Module &M, IrreducibilityAction Action = IrreducibilityAction::ThrowException); bool IsReducible(const llvm::Function &F, IrreducibilityAction Action = IrreducibilityAction::ThrowException); } ================================================ FILE: src/Wrapper/dxc/HlslIntrinsicOp.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HlslIntrinsicOp.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Enumeration for HLSL intrinsics operations. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once namespace hlsl { enum class IntrinsicOp { /* import hctdb_instrhelp */ /* hctdb_instrhelp.enum_hlsl_intrinsics()*/ // HLSL-INTRINSICS:BEGIN IOP_AddUint64, IOP_AllMemoryBarrier, IOP_AllMemoryBarrierWithGroupSync, IOP_CheckAccessFullyMapped, IOP_D3DCOLORtoUBYTE4, IOP_DeviceMemoryBarrier, IOP_DeviceMemoryBarrierWithGroupSync, IOP_EvaluateAttributeAtSample, IOP_EvaluateAttributeCentroid, IOP_EvaluateAttributeSnapped, IOP_GetAttributeAtVertex, IOP_GetRenderTargetSampleCount, IOP_GetRenderTargetSamplePosition, IOP_GroupMemoryBarrier, IOP_GroupMemoryBarrierWithGroupSync, IOP_InterlockedAdd, IOP_InterlockedAnd, IOP_InterlockedCompareExchange, IOP_InterlockedCompareStore, IOP_InterlockedExchange, IOP_InterlockedMax, IOP_InterlockedMin, IOP_InterlockedOr, IOP_InterlockedXor, IOP_NonUniformResourceIndex, IOP_Process2DQuadTessFactorsAvg, IOP_Process2DQuadTessFactorsMax, IOP_Process2DQuadTessFactorsMin, IOP_ProcessIsolineTessFactors, IOP_ProcessQuadTessFactorsAvg, IOP_ProcessQuadTessFactorsMax, IOP_ProcessQuadTessFactorsMin, IOP_ProcessTriTessFactorsAvg, IOP_ProcessTriTessFactorsMax, IOP_ProcessTriTessFactorsMin, IOP_QuadReadAcrossDiagonal, IOP_QuadReadAcrossX, IOP_QuadReadAcrossY, IOP_QuadReadLaneAt, IOP_WaveActiveAllEqual, IOP_WaveActiveAllTrue, IOP_WaveActiveAnyTrue, IOP_WaveActiveBallot, IOP_WaveActiveBitAnd, IOP_WaveActiveBitOr, IOP_WaveActiveBitXor, IOP_WaveActiveCountBits, IOP_WaveActiveMax, IOP_WaveActiveMin, IOP_WaveActiveProduct, IOP_WaveActiveSum, IOP_WaveGetLaneCount, IOP_WaveGetLaneIndex, IOP_WaveIsFirstLane, IOP_WavePrefixCountBits, IOP_WavePrefixProduct, IOP_WavePrefixSum, IOP_WaveReadLaneAt, IOP_WaveReadLaneFirst, IOP_abort, IOP_abs, IOP_acos, IOP_all, IOP_any, IOP_asdouble, IOP_asfloat, IOP_asin, IOP_asint, IOP_asuint, IOP_atan, IOP_atan2, IOP_ceil, IOP_clamp, IOP_clip, IOP_cos, IOP_cosh, IOP_countbits, IOP_cross, IOP_ddx, IOP_ddx_coarse, IOP_ddx_fine, IOP_ddy, IOP_ddy_coarse, IOP_ddy_fine, IOP_degrees, IOP_determinant, IOP_distance, IOP_dot, IOP_dst, IOP_exp, IOP_exp2, IOP_f16tof32, IOP_f32tof16, IOP_faceforward, IOP_firstbithigh, IOP_firstbitlow, IOP_floor, IOP_fma, IOP_fmod, IOP_frac, IOP_frexp, IOP_fwidth, IOP_isfinite, IOP_isinf, IOP_isnan, IOP_ldexp, IOP_length, IOP_lerp, IOP_lit, IOP_log, IOP_log10, IOP_log2, IOP_mad, IOP_max, IOP_min, IOP_modf, IOP_msad4, IOP_mul, IOP_normalize, IOP_pow, IOP_radians, IOP_rcp, IOP_reflect, IOP_refract, IOP_reversebits, IOP_round, IOP_rsqrt, IOP_saturate, IOP_sign, IOP_sin, IOP_sincos, IOP_sinh, IOP_smoothstep, IOP_source_mark, IOP_sqrt, IOP_step, IOP_tan, IOP_tanh, IOP_tex1D, IOP_tex1Dbias, IOP_tex1Dgrad, IOP_tex1Dlod, IOP_tex1Dproj, IOP_tex2D, IOP_tex2Dbias, IOP_tex2Dgrad, IOP_tex2Dlod, IOP_tex2Dproj, IOP_tex3D, IOP_tex3Dbias, IOP_tex3Dgrad, IOP_tex3Dlod, IOP_tex3Dproj, IOP_texCUBE, IOP_texCUBEbias, IOP_texCUBEgrad, IOP_texCUBElod, IOP_texCUBEproj, IOP_transpose, IOP_trunc, MOP_Append, MOP_RestartStrip, MOP_CalculateLevelOfDetail, MOP_CalculateLevelOfDetailUnclamped, MOP_GetDimensions, MOP_Load, MOP_Sample, MOP_SampleBias, MOP_SampleCmp, MOP_SampleCmpLevelZero, MOP_SampleGrad, MOP_SampleLevel, MOP_Gather, MOP_GatherAlpha, MOP_GatherBlue, MOP_GatherCmp, MOP_GatherCmpAlpha, MOP_GatherCmpBlue, MOP_GatherCmpGreen, MOP_GatherCmpRed, MOP_GatherGreen, MOP_GatherRed, MOP_GetSamplePosition, MOP_Load2, MOP_Load3, MOP_Load4, MOP_InterlockedAdd, MOP_InterlockedAnd, MOP_InterlockedCompareExchange, MOP_InterlockedCompareStore, MOP_InterlockedExchange, MOP_InterlockedMax, MOP_InterlockedMin, MOP_InterlockedOr, MOP_InterlockedXor, MOP_Store, MOP_Store2, MOP_Store3, MOP_Store4, MOP_DecrementCounter, MOP_IncrementCounter, MOP_Consume, // unsigned IOP_InterlockedUMax, IOP_InterlockedUMin, IOP_WaveActiveUMax, IOP_WaveActiveUMin, IOP_WaveActiveUProduct, IOP_WaveActiveUSum, IOP_WavePrefixUProduct, IOP_WavePrefixUSum, IOP_uclamp, IOP_ufirstbithigh, IOP_umad, IOP_umax, IOP_umin, IOP_umul, MOP_InterlockedUMax, MOP_InterlockedUMin, Num_Intrinsics, // HLSL-INTRINSICS:END }; inline bool HasUnsignedIntrinsicOpcode(IntrinsicOp opcode) { switch (opcode) { /* import hctdb_instrhelp */ /* hctdb_instrhelp.has_unsigned_hlsl_intrinsics()*/ // HLSL-HAS-UNSIGNED-INTRINSICS:BEGIN case IntrinsicOp::IOP_InterlockedMax: case IntrinsicOp::IOP_InterlockedMin: case IntrinsicOp::IOP_WaveActiveMax: case IntrinsicOp::IOP_WaveActiveMin: case IntrinsicOp::IOP_WaveActiveProduct: case IntrinsicOp::IOP_WaveActiveSum: case IntrinsicOp::IOP_WavePrefixProduct: case IntrinsicOp::IOP_WavePrefixSum: case IntrinsicOp::IOP_clamp: case IntrinsicOp::IOP_firstbithigh: case IntrinsicOp::IOP_mad: case IntrinsicOp::IOP_max: case IntrinsicOp::IOP_min: case IntrinsicOp::IOP_mul: case IntrinsicOp::MOP_InterlockedMax: case IntrinsicOp::MOP_InterlockedMin: // HLSL-HAS-UNSIGNED-INTRINSICS:END return true; default: return false; } } inline unsigned GetUnsignedIntrinsicOpcode(IntrinsicOp opcode) { switch (opcode) { /* import hctdb_instrhelp */ /* hctdb_instrhelp.get_unsigned_hlsl_intrinsics()*/ // HLSL-GET-UNSIGNED-INTRINSICS:BEGIN case IntrinsicOp::IOP_InterlockedMax: return static_cast(IntrinsicOp::IOP_InterlockedUMax); case IntrinsicOp::IOP_InterlockedMin: return static_cast(IntrinsicOp::IOP_InterlockedUMin); case IntrinsicOp::IOP_WaveActiveMax: return static_cast(IntrinsicOp::IOP_WaveActiveUMax); case IntrinsicOp::IOP_WaveActiveMin: return static_cast(IntrinsicOp::IOP_WaveActiveUMin); case IntrinsicOp::IOP_WaveActiveProduct: return static_cast(IntrinsicOp::IOP_WaveActiveUProduct); case IntrinsicOp::IOP_WaveActiveSum: return static_cast(IntrinsicOp::IOP_WaveActiveUSum); case IntrinsicOp::IOP_WavePrefixProduct: return static_cast(IntrinsicOp::IOP_WavePrefixUProduct); case IntrinsicOp::IOP_WavePrefixSum: return static_cast(IntrinsicOp::IOP_WavePrefixUSum); case IntrinsicOp::IOP_clamp: return static_cast(IntrinsicOp::IOP_uclamp); case IntrinsicOp::IOP_firstbithigh: return static_cast(IntrinsicOp::IOP_ufirstbithigh); case IntrinsicOp::IOP_mad: return static_cast(IntrinsicOp::IOP_umad); case IntrinsicOp::IOP_max: return static_cast(IntrinsicOp::IOP_umax); case IntrinsicOp::IOP_min: return static_cast(IntrinsicOp::IOP_umin); case IntrinsicOp::IOP_mul: return static_cast(IntrinsicOp::IOP_umul); case IntrinsicOp::MOP_InterlockedMax: return static_cast(IntrinsicOp::MOP_InterlockedUMax); case IntrinsicOp::MOP_InterlockedMin: return static_cast(IntrinsicOp::MOP_InterlockedUMin); // HLSL-GET-UNSIGNED-INTRINSICS:END default: return static_cast(opcode); } } } ================================================ FILE: src/Wrapper/dxc/Support/CMakeLists.txt ================================================ # Copyright (C) Microsoft Corporation. All rights reserved. # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. # TableGen HLSL options. set(LLVM_TARGET_DEFINITIONS HLSLOptions.td) tablegen(LLVM HLSLOptions.inc -gen-opt-parser-defs) add_public_tablegen_target(TablegenHLSLOptions) ================================================ FILE: src/Wrapper/dxc/Support/DxcLangExtensionsHelper.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // DxcLangExtensionsHelper.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides a helper class to implement language extensions to HLSL. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXCLANGEXTENSIONSHELPER_H__ #define __DXCLANGEXTENSIONSHELPER_H__ #include "dxc/Support/Unicode.h" #include "dxc/Support/FileIOHelper.h" #include namespace llvm { class raw_string_ostream; class CallInst; class Value; } namespace clang { class CompilerInstance; } namespace hlsl { class DxcLangExtensionsHelper : public DxcLangExtensionsHelperApply { private: llvm::SmallVector m_semanticDefines; llvm::SmallVector m_semanticDefineExclusions; llvm::SmallVector m_defines; llvm::SmallVector, 2> m_intrinsicTables; CComPtr m_semanticDefineValidator; std::string m_semanticDefineMetaDataName; HRESULT STDMETHODCALLTYPE RegisterIntoVector(LPCWSTR name, llvm::SmallVector& here) { try { IFTPTR(name); std::string s; if (!Unicode::UTF16ToUTF8String(name, &s)) { throw ::hlsl::Exception(E_INVALIDARG); } here.push_back(s); return S_OK; } CATCH_CPP_RETURN_HRESULT(); } public: const llvm::SmallVector& GetSemanticDefines() const { return m_semanticDefines; } const llvm::SmallVector& GetSemanticDefineExclusions() const { return m_semanticDefineExclusions; } const llvm::SmallVector& GetDefines() const { return m_defines; } llvm::SmallVector, 2>& GetIntrinsicTables(){ return m_intrinsicTables; } const std::string &GetSemanticDefineMetadataName() { return m_semanticDefineMetaDataName; } HRESULT STDMETHODCALLTYPE RegisterSemanticDefine(LPCWSTR name) { return RegisterIntoVector(name, m_semanticDefines); } HRESULT STDMETHODCALLTYPE RegisterSemanticDefineExclusion(LPCWSTR name) { return RegisterIntoVector(name, m_semanticDefineExclusions); } HRESULT STDMETHODCALLTYPE RegisterDefine(LPCWSTR name) { return RegisterIntoVector(name, m_defines); } HRESULT STDMETHODCALLTYPE RegisterIntrinsicTable(_In_ IDxcIntrinsicTable* pTable) { try { IFTPTR(pTable); LPCSTR tableName = nullptr; IFT(pTable->GetTableName(&tableName)); IFTPTR(tableName); IFTARG(strcmp(tableName, "op") != 0); // "op" is reserved for builtin intrinsics for (auto &&table : m_intrinsicTables) { LPCSTR otherTableName = nullptr; IFT(table->GetTableName(&otherTableName)); IFTPTR(otherTableName); IFTARG(strcmp(tableName, otherTableName) != 0); // Added a duplicate table name } m_intrinsicTables.push_back(pTable); return S_OK; } CATCH_CPP_RETURN_HRESULT(); } // Set the validator used to validate semantic defines. // Only one validator stored and used to run validation. HRESULT STDMETHODCALLTYPE SetSemanticDefineValidator(_In_ IDxcSemanticDefineValidator* pValidator) { if (pValidator == nullptr) return E_POINTER; m_semanticDefineValidator = pValidator; return S_OK; } HRESULT STDMETHODCALLTYPE SetSemanticDefineMetaDataName(LPCSTR name) { try { m_semanticDefineMetaDataName = name; return S_OK; } CATCH_CPP_RETURN_HRESULT(); } // Get the name of the dxil intrinsic function. std::string GetIntrinsicName(UINT opcode) { LPCSTR pName = ""; for (IDxcIntrinsicTable *table : m_intrinsicTables) { if (SUCCEEDED(table->GetIntrinsicName(opcode, &pName))) { return pName; } } return ""; } // Result of validating a semantic define. // Stores any warning or error messages produced by the validator. // Successful validation means that there are no warning or error messages. struct SemanticDefineValidationResult { std::string Warning; std::string Error; bool HasError() { return Error.size() > 0; } bool HasWarning() { return Warning.size() > 0; } static SemanticDefineValidationResult Success() { return SemanticDefineValidationResult(); } }; // Use the contained semantice define validator to validate the given semantic define. SemanticDefineValidationResult ValidateSemanticDefine(const std::string &name, const std::string &value) { if (!m_semanticDefineValidator) return SemanticDefineValidationResult::Success(); // Blobs for getting restul from validator. Strings for returning results to caller. CComPtr pError; CComPtr pWarning; std::string error; std::string warning; // Run semantic define validator. HRESULT result = m_semanticDefineValidator->GetSemanticDefineWarningsAndErrors(name.c_str(), value.c_str(), &pWarning, &pError); if (FAILED(result)) { // Failure indicates it was not able to even run validation so // we cannot say whether the define is invalid or not. Return a // generic error message about failure to run the valiadator. error = "failed to run semantic define validator for: "; error.append(name); error.append("="); error.append(value); return SemanticDefineValidationResult{ warning, error }; } // Define a little function to convert encoded blob into a string. auto GetErrorAsString = [&name](const CComPtr &pBlobString) -> std::string { CComPtr pUTF8BlobStr; if (SUCCEEDED(hlsl::DxcGetBlobAsUtf8(pBlobString, &pUTF8BlobStr))) return std::string(static_cast(pUTF8BlobStr->GetBufferPointer()), pUTF8BlobStr->GetBufferSize()); else return std::string("invalid semantic define " + name); }; // Check to see if any warnings or errors were produced. if (pError && pError->GetBufferSize()) { error = GetErrorAsString(pError); } if (pWarning && pWarning->GetBufferSize()) { warning = GetErrorAsString(pWarning); } return SemanticDefineValidationResult{ warning, error }; } __override void SetupSema(clang::Sema &S) { clang::ExternalASTSource *astSource = S.getASTContext().getExternalSource(); if (clang::ExternalSemaSource *externalSema = llvm::dyn_cast_or_null(astSource)) { for (auto &&table : m_intrinsicTables) { hlsl::RegisterIntrinsicTable(externalSema, table); } } } __override void SetupPreprocessorOptions(clang::PreprocessorOptions &PPOpts) { for (const auto & define : m_defines) { PPOpts.addMacroDef(llvm::StringRef(define.c_str())); } } __override DxcLangExtensionsHelper *GetDxcLangExtensionsHelper() { return this; } DxcLangExtensionsHelper() : m_semanticDefineMetaDataName("hlsl.semdefs") {} }; // Use this macro to embed an implementation that will delegate to a field. // Note that QueryInterface still needs to return the vtable. #define DXC_LANGEXTENSIONS_HELPER_IMPL(_helper_field_) \ __override HRESULT STDMETHODCALLTYPE RegisterIntrinsicTable(_In_ IDxcIntrinsicTable *pTable) { \ return (_helper_field_).RegisterIntrinsicTable(pTable); \ } \ __override HRESULT STDMETHODCALLTYPE RegisterSemanticDefine(LPCWSTR name) { \ return (_helper_field_).RegisterSemanticDefine(name); \ } \ __override HRESULT STDMETHODCALLTYPE RegisterSemanticDefineExclusion(LPCWSTR name) { \ return (_helper_field_).RegisterSemanticDefineExclusion(name); \ } \ __override HRESULT STDMETHODCALLTYPE RegisterDefine(LPCWSTR name) { \ return (_helper_field_).RegisterDefine(name); \ } \ __override HRESULT STDMETHODCALLTYPE SetSemanticDefineValidator(_In_ IDxcSemanticDefineValidator* pValidator) { \ return (_helper_field_).SetSemanticDefineValidator(pValidator); \ } \ __override HRESULT STDMETHODCALLTYPE SetSemanticDefineMetaDataName(LPCSTR name) { \ return (_helper_field_).SetSemanticDefineMetaDataName(name); \ } \ // A parsed semantic define is a semantic define that has actually been // parsed by the compiler. It has a name (required), a value (could be // the empty string), and a location. We use an encoded clang::SourceLocation // for the location to avoid a clang include dependency. struct ParsedSemanticDefine{ std::string Name; std::string Value; unsigned Location; }; typedef std::vector ParsedSemanticDefineList; // Return the collection of semantic defines parsed by the compiler instance. ParsedSemanticDefineList CollectSemanticDefinesParsedByCompiler(clang::CompilerInstance &compiler, _In_ DxcLangExtensionsHelper *helper); } // namespace hlsl #endif ================================================ FILE: src/Wrapper/dxc/Support/ErrorCodes.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // ErrorCodes.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides error code values for the DirectX compiler and tools. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once // Redeclare some macros to not depend on winerror.h #define DXC_SEVERITY_ERROR 1 #define DXC_MAKE_HRESULT(sev,fac,code) \ ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) #define HRESULT_IS_WIN32ERR(hr) ((hr & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0)) #define HRESULT_AS_WIN32ERR(hr) (HRESULT_CODE(hr)) // Error codes from C libraries (0n150) - 0x8096xxxx #define FACILITY_ERRNO (0x96) #define HRESULT_FROM_ERRNO(x) MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_ERRNO,(x)) // Error codes from DXC libraries (0n170) - 0x8013xxxx #define FACILITY_DXC (0xAA) // 0x00000000 - The operation succeeded. #define DXC_S_OK 0 // _HRESULT_TYPEDEF_(0x00000000L) // 0x80AA0001 - The operation failed because overlapping semantics were found. #define DXC_E_OVERLAPPING_SEMANTICS DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0001)) // 0x80AA0002 - The operation failed because multiple depth semantics were found. #define DXC_E_MULTIPLE_DEPTH_SEMANTICS DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0002)) // 0x80AA0003 - Input file is too large. #define DXC_E_INPUT_FILE_TOO_LARGE DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0003)) // 0x80AA0004 - Error parsing DXBC container. #define DXC_E_INCORRECT_DXBC DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0004)) // 0x80AA0005 - Error parsing DXBC bytecode. #define DXC_E_ERROR_PARSING_DXBC_BYTECODE DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0005)) // 0x80AA0006 - Data is too large. #define DXC_E_DATA_TOO_LARGE DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0006)) // 0x80AA0007 - Incompatible converter options. #define DXC_E_INCOMPATIBLE_CONVERTER_OPTIONS DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0007)) // 0x80AA0008 - Irreducible control flow graph. #define DXC_E_IRREDUCIBLE_CFG DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0008)) // 0x80AA0009 - IR verification error. #define DXC_E_IR_VERIFICATION_FAILED DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0009)) // 0x80AA000A - Scope-nested control flow recovery failed. #define DXC_E_SCOPE_NESTED_FAILED DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x000A)) // 0x80AA000B - Operation is not supported. #define DXC_E_NOT_SUPPORTED DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x000B)) // 0x80AA000C - Unable to encode string. #define DXC_E_STRING_ENCODING_FAILED DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x000C)) // 0x80AA000D - DXIL container is invalid. #define DXC_E_CONTAINER_INVALID DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x000D)) // 0x80AA000E - DXIL container is missing the DXIL part. #define DXC_E_CONTAINER_MISSING_DXIL DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x000E)) // 0x80AA000F - Unable to parse DxilModule metadata. #define DXC_E_INCORRECT_DXIL_METADATA DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x000F)) // 0x80AA0010 - Error parsing DDI signature. #define DXC_E_INCORRECT_DDI_SIGNATURE DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0010)) // 0x80AA0011 - Duplicate part exists in dxil container. #define DXC_E_DUPLICATE_PART DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0011)) // 0x80AA0012 - Error finding part in dxil container. #define DXC_E_MISSING_PART DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0012)) // 0x80AA0013 - Malformed DXIL Container. #define DXC_E_MALFORMED_CONTAINER DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0013)) // 0x80AA0014 - Incorrect Root Signature for shader. #define DXC_E_INCORRECT_ROOT_SIGNATURE DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0014)) // 0X80AA0015 - DXIL container is missing DebugInfo part. #define DXC_E_CONTAINER_MISSING_DEBUG DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0015)) // 0X80AA0016 - Unexpected failure in macro expansion. #define DXC_E_MACRO_EXPANSION_FAILURE DXC_MAKE_HRESULT(DXC_SEVERITY_ERROR,FACILITY_DXC,(0x0016)) ================================================ FILE: src/Wrapper/dxc/Support/FileIOHelper.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // FileIOHelper.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides utitlity functions to work with files. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once // Forward declarations. struct IDxcBlob; struct IDxcBlobEncoding; namespace hlsl { void ReadBinaryFile(_In_z_ LPCWSTR pFileName, _Outptr_result_bytebuffer_(*pDataSize) void **ppData, _Out_ DWORD *pDataSize); void WriteBinaryFile(_In_z_ LPCWSTR pFileName, _In_reads_bytes_(DataSize) const void *pData, _In_ DWORD DataSize); /////////////////////////////////////////////////////////////////////////////// // Blob and encoding manipulation functions. UINT32 DxcCodePageFromBytes(_In_count_(byteLen) const char *bytes, size_t byteLen) throw(); HRESULT DxcCreateBlobFromFile(LPCWSTR pFileName, _In_opt_ UINT32 *pCodePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); // Given a blob, creates a subrange view. HRESULT DxcCreateBlobFromBlob(_In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) throw(); HRESULT DxcCreateBlobOnHeap(_In_bytecount_(size) LPCVOID pData, UINT32 size, _COM_Outptr_ IDxcBlob **ppResult) throw(); HRESULT DxcCreateBlobOnHeapCopy(_In_bytecount_(size) LPCVOID pData, UINT32 size, _COM_Outptr_ IDxcBlob **ppResult) throw(); // Given a blob, creates a new instance with a specific code page set. HRESULT DxcCreateBlobWithEncodingSet(_In_ IDxcBlob *pBlob, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT DxcCreateBlobWithEncodingFromPinned( _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT DxcCreateBlobWithEncodingFromStream( IStream *pStream, bool newInstanceAlways, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT DxcCreateBlobWithEncodingOnHeap(_In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT DxcCreateBlobWithEncodingOnHeapCopy( _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT DxcCreateBlobWithEncodingOnMalloc( _In_bytecount_(size) LPCVOID pText, IMalloc *pIMalloc, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT DxcGetBlobAsUtf8(_In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT DxcGetBlobAsUtf8NullTerm( _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) throw(); HRESULT DxcGetBlobAsUtf16(_In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); bool IsBlobNullOrEmpty(_In_opt_ IDxcBlob *pBlob) throw(); /////////////////////////////////////////////////////////////////////////////// // Stream implementations. class AbstractMemoryStream : public IStream { public: virtual LPBYTE GetPtr() throw() = 0; virtual ULONG GetPtrSize() throw() = 0; virtual LPBYTE Detach() throw() = 0; virtual UINT64 GetPosition() throw() = 0; virtual HRESULT Reserve(ULONG targetSize) throw() = 0; }; HRESULT CreateMemoryStream(_In_ IMalloc *pMalloc, _COM_Outptr_ AbstractMemoryStream** ppResult) throw(); HRESULT CreateReadOnlyBlobStream(_In_ IDxcBlob *pSource, _COM_Outptr_ IStream** ppResult) throw(); template HRESULT WriteStreamValue(AbstractMemoryStream *pStream, const T& value) { ULONG cb; return pStream->Write(&value, sizeof(value), &cb); } } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/Support/Global.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // Global.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides important declarations global to all DX Compiler code. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once // Redeclare some macros to not depend on winerror.h #define DXC_FAILED(hr) (((HRESULT)(hr)) < 0) #ifndef _HRESULT_DEFINED #define _HRESULT_DEFINED #ifndef _Return_type_success_ typedef long HRESULT; #else typedef _Return_type_success_(return >= 0) long HRESULT; #endif // _Return_type_success_ #endif // !_HRESULT_DEFINED #include #include "dxc/Support/Exception.h" namespace std { class error_code; } void CheckLLVMErrorCode(const std::error_code &ec); /****************************************************************************** Project-wide macros ******************************************************************************/ #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = nullptr; } } #define SAFE_ADDREF(p) { if (p) { (p)->AddRef(); } } #define SAFE_DELETE_ARRAY(p) { delete [](p); p = nullptr; } #define SAFE_DELETE(p) { delete (p); p = nullptr; } // VH is used in other DXC projects, but it's also a typedef in llvm. // Use the IFC (IfFailedCleanup) set of conventions. #define IFC(x) { hr = (x); if (DXC_FAILED(hr)) goto Cleanup; } #define IFR(x) { HRESULT __hr = (x); if (DXC_FAILED(__hr)) return __hr; } #define IFRBOOL(x,y){ if (!(x)) return (y); } #define IFCBOOL(x,y){ if (!(x)) { hr = (y); goto Cleanup; } } #define IFCOOM(x) { if (nullptr == (x)) { hr = E_OUTOFMEMORY; goto Cleanup; } } #define IFROOM(x) { if (nullptr == (x)) { return E_OUTOFMEMORY; } } #define IFCPTR(x) { if (nullptr == (x)) { hr = E_POINTER; goto Cleanup; }} #define IFT(x) { HRESULT __hr = (x); if (DXC_FAILED(__hr)) throw ::hlsl::Exception(__hr); } #define IFTBOOL(x,y){ if (!(x)) throw ::hlsl::Exception(y); } #define IFTOOM(x) { if (nullptr == (x)) { throw ::hlsl::Exception(E_OUTOFMEMORY); }} #define IFTPTR(x) { if (nullptr == (x)) { throw ::hlsl::Exception(E_POINTER); }} #define IFTARG(x) { if (!(x)) { throw ::hlsl::Exception(E_INVALIDARG); }} #define IFTLLVM(x) { CheckLLVMErrorCode(x); } #define IFTMSG(x, msg) { HRESULT __hr = (x); if (DXC_FAILED(__hr)) throw ::hlsl::Exception(__hr, msg); } #define IFTBOOLMSG(x, y, msg) { if (!(x)) throw ::hlsl::Exception(y, msg); } // Propagate an C++ exception into an HRESULT. #define CATCH_CPP_ASSIGN_HRESULT() \ catch (std::bad_alloc&) { hr = E_OUTOFMEMORY; } \ catch (hlsl::Exception& _hlsl_exception_) { \ _Analysis_assume_(DXC_FAILED(_hlsl_exception_.hr)); \ hr = _hlsl_exception_.hr; \ } \ catch (...) { hr = E_FAIL; } #define CATCH_CPP_RETURN_HRESULT() \ catch (std::bad_alloc&) { return E_OUTOFMEMORY; } \ catch (hlsl::Exception& _hlsl_exception_) { \ _Analysis_assume_(DXC_FAILED(_hlsl_exception_.hr)); \ return _hlsl_exception_.hr; \ } \ catch (...) { return E_FAIL; } template T *VerifyNullAndThrow(T *p) { if (p == nullptr) throw std::bad_alloc(); return p; } #define VNT(__p) VerifyNullAndThrow(__p) extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(_In_opt_ const char *msg); inline void OutputDebugBytes(const void *ptr, size_t len) { const char digits[] = "0123456789abcdef"; const unsigned char *pBytes = (const unsigned char *)ptr; const int bytesPerLine = 16; char buffer[bytesPerLine * 3 + 2 + 1]; buffer[_countof(buffer) - 3] = '\r'; buffer[_countof(buffer) - 2] = '\n'; buffer[_countof(buffer) - 1] = '\0'; char *pWrite = buffer; char *pEnd = buffer + _countof(buffer) - 3; while (len) { *pWrite++ = digits[(*pBytes & 0xF0) >> 4]; *pWrite++ = digits[*pBytes & 0x0f]; *pWrite++ = ' '; if (pWrite == pEnd) { OutputDebugStringA(buffer); pWrite = buffer; } --len; ++pBytes; } if (pWrite != buffer) { *pWrite = '\0'; OutputDebugStringA(buffer); OutputDebugStringA("\r\n"); } } inline void OutputDebugFormatA(_In_ _Printf_format_string_ _Null_terminated_ const char* pszFormat, ...) { char buffer[1024]; va_list argList; va_start(argList, pszFormat); int count = vsprintf_s(buffer, _countof(buffer), pszFormat, argList); va_end(argList); OutputDebugStringA(buffer); if (count < 0) { OutputDebugStringA("...\n"); } } #ifdef DBG // DXASSERT is used to debug break when 'exp' evaluates to false and is only // intended for internal developer use. It is compiled out in free // builds. This means that code that should be in the final exe should // NOT be inside of of an DXASSERT test. // // 'fmt' is a printf-like format string; positional arguments aren't // supported. // // Example: DXASSERT(i > 10, "Hello %s", "World"); // This prints 'Hello World (i > 10)' and breaks in the debugger if the // assertion doesn't hold. // #define DXASSERT(exp, fmt, ...)\ do { _Analysis_assume_(exp); if(!(exp)) { \ OutputDebugFormatA("Error: \t%s\t\nFile:\n%s(%d)\t\nFunc:\t%s.\n\t" fmt "\n", "!(" #exp ")", __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \ __debugbreak();\ } } while(0) #define DXASSERT_LOCALVAR(local, exp, s, ...) DXASSERT(exp, s, __VA_ARGS__) #define DXASSERT_NOMSG(exp) DXASSERT(exp, "") #define DXVERIFY_NOMSG(exp) DXASSERT(exp, "") // This should be improved with global enabled mask rather than a compile-time mask. #define DXTRACE_MASK_ENABLED 0 #define DXTRACE_MASK_APIFS 1 #define DXTRACE_ENABLED(subsystem) (DXTRACE_MASK_ENABLED & subsystem) // DXTRACE_FMT formats a debugger trace message if DXTRACE_MASK allows it. #define DXTRACE_FMT(subsystem, fmt, ...) do { \ if (DXTRACE_ENABLED(subsystem)) OutputDebugFormatA(fmt, __VA_ARGS__); \ } while (0) /// DXTRACE_FMT_APIFS is used by the API-based virtual filesystem. #define DXTRACE_FMT_APIFS(fmt, ...) DXTRACE_FMT(DXTRACE_MASK_APIFS, fmt, __VA_ARGS__) #else // DXASSERT is disabled in free builds. #define DXASSERT(exp, s, ...) _Analysis_assume_(exp) // DXASSERT_LOCALVAR is disabled in free builds, but we keep the local referenced to avoid a warning. #define DXASSERT_LOCALVAR(local, exp, s, ...) do { (local); _Analysis_assume_(exp); } while (0) // DXASSERT_NOMSG is disabled in free builds. #define DXASSERT_NOMSG(exp) _Analysis_assume_(exp) // DXVERIFY is patterned after NT_VERIFY and will evaluate the expression #define DXVERIFY_NOMSG(exp) do { (exp); _Analysis_assume_(exp); } while (0) // DXTRACE_FMT and the subsystem versions are disabled in free builds. #define DXTRACE_FMT(...) (void)(0) #define DXTRACE_FMT_APIFS(...) (void)(0) #endif // DBG ================================================ FILE: src/Wrapper/dxc/Support/HLSLOptions.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // HLSLOptions.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Support for command-line-style option parsing. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #ifndef LLVM_HLSL_OPTIONS_H #define LLVM_HLSL_OPTIONS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" #include "dxc/dxcapi.h" namespace llvm { namespace opt { class OptTable; class raw_ostream; } } namespace dxc { class DxcDllSupport; } namespace hlsl { namespace options { /// Flags specifically for clang options. Must not overlap with /// llvm::opt::DriverFlag or (for clarity) with clang::driver::options. enum HlslFlags { DriverOption = (1 << 13), NoArgumentUnused = (1 << 14), CoreOption = (1 << 15), ISenseOption = (1 << 16), }; enum ID { OPT_INVALID = 0, // This is not an option ID. #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELPTEXT, METAVAR) OPT_##ID, #include "dxc/Support/HLSLOptions.inc" LastOption #undef OPTION }; const llvm::opt::OptTable *getHlslOptTable(); /////////////////////////////////////////////////////////////////////////////// // Helper classes to deal with options. /// Flags for IDxcCompiler APIs. static const unsigned CompilerFlags = HlslFlags::CoreOption; /// Flags for dxc.exe command-line tool. static const unsigned DxcFlags = HlslFlags::CoreOption | HlslFlags::DriverOption; /// Flags for dxr.exe command-line tool. static const unsigned DxrFlags = HlslFlags::CoreOption | HlslFlags::DriverOption; /// Flags for IDxcIntelliSense APIs. static const unsigned ISenseFlags = HlslFlags::CoreOption | HlslFlags::ISenseOption; /// Use this class to capture preprocessor definitions and manage their lifetime. class DxcDefines { public: void push_back(llvm::StringRef value); LPWSTR DefineValues = nullptr; llvm::SmallVector DefineStrings; llvm::SmallVector DefineVector; ~DxcDefines() { delete[] DefineValues; } DxcDefines(const DxcDefines &) = delete; DxcDefines() {} void BuildDefines(); // Must be called after all defines are pushed back UINT32 ComputeNumberOfWCharsNeededForDefines(); const DxcDefine *data() const { return DefineVector.data(); } unsigned size() const { return DefineVector.size(); } }; /// Use this class to capture all options. class DxcOpts { public: DxcDefines Defines; llvm::opt::InputArgList Args = llvm::opt::InputArgList(nullptr, nullptr); // Original arguments. llvm::StringRef AssemblyCode; // OPT_Fc llvm::StringRef DebugFile; // OPT_Fd llvm::StringRef EntryPoint; // OPT_entrypoint llvm::StringRef ExternalFn; // OPT_external_fn llvm::StringRef ExternalLib; // OPT_external_lib llvm::StringRef ExtractPrivateFile; // OPT_getprivate llvm::StringRef ForceRootSigVer; // OPT_force_rootsig_ver llvm::StringRef InputFile; // OPT_INPUT llvm::StringRef OutputHeader; // OPT_Fh llvm::StringRef OutputObject; // OPT_Fo llvm::StringRef OutputWarningsFile; // OPT_Fe llvm::StringRef Preprocess; // OPT_P llvm::StringRef TargetProfile; // OPT_target_profile llvm::StringRef VariableName; // OPT_Vn llvm::StringRef PrivateSource; // OPT_setprivate llvm::StringRef RootSignatureSource; // OPT_setrootsignature llvm::StringRef VerifyRootSignatureSource; //OPT_verifyrootsignature llvm::StringRef RootSignatureDefine; // OPT_rootsig_define bool AllResourcesBound; // OPT_all_resources_bound bool AstDump; // OPT_ast_dump bool ColorCodeAssembly; // OPT_Cc bool CodeGenHighLevel; // OPT_fcgl bool DebugInfo; // OPT__SLASH_Zi bool DumpBin; // OPT_dumpbin bool WarningAsError; // OPT__SLASH_WX bool IEEEStrict; // OPT_Gis bool DefaultColMajor; // OPT_Zpc bool DefaultRowMajor; // OPT_Zpr bool DisableValidation; // OPT_VD unsigned OptLevel; // OPT_O0/O1/O2/O3 bool DisableOptimizations; // OPT_Od bool AvoidFlowControl; // OPT_Gfa bool PreferFlowControl; // OPT_Gfp bool EnableStrictMode; // OPT_Ges bool HLSL2015; // OPT_hlsl_version (=2015) bool HLSL2016; // OPT_hlsl_version (=2016) bool OptDump; // OPT_ODump - dump optimizer commands bool OutputWarnings = true; // OPT_no_warnings bool ShowHelp = false; // OPT_help bool UseColor; // OPT_Cc bool UseHexLiterals; // OPT_Lx bool UseInstructionByteOffsets; // OPT_No bool UseInstructionNumbers; // OPT_Ni bool NotUseLegacyCBufLoad; // OPT_not_use_legacy_cbuf_load bool PackPrefixStable; // OPT_pack_prefix_stable bool PackOptimized; // OPT_pack_optimized bool DisplayIncludeProcess; // OPT__vi bool RecompileFromBinary; // OPT _Recompile (Recompiling the DXBC binary file not .hlsl file) bool StripDebug; // OPT Qstrip_debug bool StripRootSignature; // OPT_Qstrip_rootsignature bool StripPrivate; // OPT_Qstrip_priv bool StripReflection; // OPT_Qstrip_reflect bool ExtractRootSignature; // OPT_extractrootsignature bool DisassembleColorCoded; // OPT_Cc bool DisassembleInstNumbers; //OPT_Ni bool DisassembleByteOffset; //OPT_No bool DisaseembleHex; //OPT_Lx bool IsRootSignatureProfile(); }; /// Use this class to capture, convert and handle the lifetime for the /// command-line arguments to a program. class MainArgs { public: llvm::SmallVector Utf8StringVector; llvm::SmallVector Utf8CharPtrVector; MainArgs() = default; MainArgs(int argc, const wchar_t **argv, int skipArgCount = 1); MainArgs(llvm::ArrayRef args); MainArgs& operator=(const MainArgs &other); llvm::ArrayRef getArrayRef() const { return llvm::ArrayRef(Utf8CharPtrVector.data(), Utf8CharPtrVector.size()); } }; /// Use this class to convert a StringRef into a wstring, handling empty values as nulls. class StringRefUtf16 { private: std::wstring m_value; public: StringRefUtf16(llvm::StringRef value); operator LPCWSTR() const { return m_value.size() ? m_value.data() : nullptr; } }; /// Reads all options from the given argument strings, populates opts, and /// validates reporting errors and warnings. int ReadDxcOpts(const llvm::opt::OptTable *optionTable, unsigned flagsToInclude, const MainArgs &argStrings, DxcOpts &opts, llvm::raw_ostream &errors); /// Sets up the specified DxcDllSupport instance as per the given options. int SetupDxcDllSupport(const DxcOpts &opts, dxc::DxcDllSupport &dxcSupport, llvm::raw_ostream &errors); void CopyArgsToWStrings(const llvm::opt::InputArgList &inArgs, unsigned flagsToInclude, std::vector &outArgs); } } #endif ================================================ FILE: src/Wrapper/dxc/Support/HLSLOptions.td ================================================ //===--- HLSLOptions.td - Options for HLSL --------------------------------===// /////////////////////////////////////////////////////////////////////////////// // // // HLSLOptions.td // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // This file defines the options accepted by HLSL. // // // /////////////////////////////////////////////////////////////////////////////// // Include the common option parsing interfaces. // include "llvm/Option/OptParser.td" ////////////////////////////////////////////////////////////////////////////// // Flags // DriverOption - The option is a "driver" option, and should not be forwarded // to other tools. def DriverOption : OptionFlag; // CoreOption - This is considered a "core" HLSL option. def CoreOption : OptionFlag; // ISenseOption - This option is only supported for IntelliSense. def ISenseOption : OptionFlag; ////////////////////////////////////////////////////////////////////////////// // Groups // Meta-group for options which are only used for compilation, // and not linking etc. def CompileOnly_Group : OptionGroup<"">; def Action_Group : OptionGroup<"">; def I_Group : OptionGroup<"">, Group; def M_Group : OptionGroup<"">, Group; def T_Group : OptionGroup<"">; def O_Group : OptionGroup<"">, Group; def R_Group : OptionGroup<"">, Group; def R_value_Group : OptionGroup<"">, Group; def W_Group : OptionGroup<"">, Group; def W_value_Group : OptionGroup<"">, Group; def d_Group : OptionGroup<"">; def f_Group : OptionGroup<"">, Group; def f_clang_Group : OptionGroup<"">, Group; def g_Group : OptionGroup<"">; def g_flags_Group : OptionGroup<"">; def i_Group : OptionGroup<"">, Group; def clang_i_Group : OptionGroup<"">, Group; def m_Group : OptionGroup<"">, Group; def u_Group : OptionGroup<"">; // Developer Driver Options def internal_Group : OptionGroup<"">; def internal_driver_Group : OptionGroup<"">, Group, HelpText<"DRIVER OPTIONS">; def internal_debug_Group : OptionGroup<"">, Group, HelpText<"DEBUG/DEVELOPMENT OPTIONS">; def hlslcomp_Group : OptionGroup<"HLSL Compilation">, HelpText<"Compilation Options">; def hlsloptz_Group : OptionGroup<"HLSL Optimization">, HelpText<"Optimization Options">; def hlslutil_Group : OptionGroup<"HLSL Utility">, HelpText<"Utility Options">; def hlslcore_Group : OptionGroup<"HLSL Core">, HelpText<"Common Options">; ////////////////////////////////////////////////////////////////////////////// // Options // The internal option ID must be a valid C++ identifier and results in a // hlsl::options::OPT_XX enum constant for XX. // // See tools/clang/include/clang/Driver/Options.td for more notes. // These options are based on those used by clang. // fxc-based options kept for compatiblity are below. // // The general approach is to include only things that are in use, in the // same order as in Options.td. def D : JoinedOrSeparate<["-", "/"], "D">, Group, Flags<[CoreOption]>, HelpText<"Define macro">; def H : Flag<["-"], "H">, Flags<[CoreOption]>, Group, HelpText<"Show header includes and nesting depth">; def I : JoinedOrSeparate<["-", "/"], "I">, Group, Flags<[CoreOption]>, HelpText<"Add directory to include search path">; def O0 : Flag<["-", "/"], "O0">, Group, Flags<[CoreOption]>, HelpText<"Optimization Level 0">; def O1 : Flag<["-", "/"], "O1">, Group, Flags<[CoreOption]>, HelpText<"Optimization Level 1">; def O2 : Flag<["-", "/"], "O2">, Group, Flags<[CoreOption]>, HelpText<"Optimization Level 2">; def O3 : Flag<["-", "/"], "O3">, Group, Flags<[CoreOption]>, HelpText<"Optimization Level 3 (Default)">; def O4 : Flag<["-", "/"], "O4">, Group, Flags<[CoreOption]>, HelpText<"Optimization Level 4">; def Odump : Flag<["-", "/"], "Odump">, Group, Flags<[CoreOption]>, HelpText<"Print the optimizer commands.">; def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Group, Flags<[CoreOption]>, HelpText<"Don't emit warning for unused driver arguments">; def Wall : Flag<["-"], "Wall">, Group, Flags<[CoreOption]>; def Wdeprecated : Flag<["-"], "Wdeprecated">, Group, Flags<[CoreOption]>; //def W_Joined : Joined<["-"], "W">, Group, Flags<[CoreOption]>, // MetaVarName<"">, HelpText<"Enable the specified warning">; def d_Flag : Flag<["-"], "d">, Group; def d_Joined : Joined<["-"], "d">, Group; //def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group, // Flags<[CoreOption, DriverOption]>, HelpText<"Use colors in diagnostics">; def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group, Flags<[CoreOption, DriverOption]>; def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group; //def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group, // HLSL Change: disable ANSI escape codes // Flags<[CoreOption, CC1Option]>, HelpText<"Use ANSI escape codes for diagnostics">; def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group; def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group; def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">, Group; //def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group, // Flags<[CoreOption]>, HelpText<"Print option name with mappable diagnostics">; def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group; def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group, Flags<[CoreOption]>; def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, Group; def fassociative_math : Flag<["-"], "fassociative-math">, Group; def fno_associative_math : Flag<["-"], "fno-associative-math">, Group; //def freciprocal_math : // Flag<["-"], "freciprocal-math">, Group, Flags<[CoreOption]>, // HelpText<"Allow division operations to be reassociated">; def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group; def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group, Flags<[CoreOption]>; def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group; def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group; //def fno_signed_zeros : // Flag<["-"], "fno-signed-zeros">, Group, Flags<[CoreOption]>, // HelpText<"Allow optimizations that ignore the sign of floating point zeros">; def fhonor_nans : Flag<["-"], "fhonor-nans">, Group; def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group; def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group; def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group; //def ftrapping_math : Flag<["-"], "ftrapping-math">, Group; //def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group; //def ffp_contract : Joined<["-"], "ffp-contract=">, Group, // Flags<[CoreOption]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" // " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group; /* def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group, Flags<[CoreOption]>; def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group, Flags<[CoreOption]>; def fno_diagnostics_color : Flag<["-"], "fno-diagnostics-color">, Group, Flags<[CoreOption, DriverOption]>; def fno_show_column : Flag<["-"], "fno-show-column">, Group, Flags<[CoreOption]>, HelpText<"Do not include column number on diagnostics">; def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group, Flags<[CoreOption]>, HelpText<"Disable spell-checking">; def fshow_column : Flag<["-"], "fshow-column">, Group, Flags<[CoreOption]>; def fshow_source_location : Flag<["-"], "fshow-source-location">, Group; def fspell_checking : Flag<["-"], "fspell-checking">, Group; def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group; def funroll_loops : Flag<["-"], "funroll-loops">, Group, HelpText<"Turn on loop unroller">, Flags<[CoreOption]>; def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group, HelpText<"Turn off loop unroller">, Flags<[CoreOption]>; def freroll_loops : Flag<["-"], "freroll-loops">, Group, HelpText<"Turn on loop reroller">, Flags<[CoreOption]>; def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group, HelpText<"Turn off loop reroller">; */ def help : Flag<["-", "--", "/"], "help">, Flags<[DriverOption]>, Group, HelpText<"Display available options">; /* def imacros : JoinedOrSeparate<["-", "--"], "imacros">, Group, Flags<[CoreOption]>, HelpText<"Include macros from file before parsing">, MetaVarName<"">; def include_ : JoinedOrSeparate<["-", "--"], "include">, Group, EnumName<"include">, MetaVarName<"">, HelpText<"Include file before parsing">, Flags<[CoreOption]>; def mllvm : Separate<["-"], "mllvm">, Flags<[CoreOption]>, HelpText<"Additional arguments to forward to LLVM's option processing">; def mms_bitfields : Flag<["-"], "mms-bitfields">, Group, Flags<[CoreOption]>, HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">; def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CoreOption]>, HelpText<"Write output to ">, MetaVarName<"">; def time : Flag<["-"], "time">, HelpText<"Time individual commands">; // def U : JoinedOrSeparate<["-"], "U">, Group, Flags<[CoreOption]>; def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CoreOption]>; def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CoreOption]>, MetaVarName<"">, HelpText<"Resolve file paths relative to the specified directory">; def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CoreOption]>, MetaVarName<"">, Alias; */ // Double dash options, which are usually an alias for one of the previous // options. def _all_warnings : Flag<["--"], "all-warnings">, Flags<[CoreOption]>, Alias; def _help_hidden : Flag<["--"], "help-hidden">, Flags<[DriverOption]>; def _help_question : Flag<["-", "/"], "?">, Flags<[DriverOption]>, Alias; ////////////////////////////////////////////////////////////////////////////// // New HLSL-specific flags. def ast_dump : Flag<["-", "/"], "ast-dump">, Flags<[CoreOption, DriverOption, HelpHidden]>, HelpText<"Dumps the parsed Abstract Syntax Tree.">; // should not be core, but handy workaround until explicit API written def external_lib : Separate<["-", "/"], "external">, Group, Flags<[DriverOption, HelpHidden]>, HelpText<"External DLL name to load for compiler support">; def external_fn : Separate<["-", "/"], "external-fn">, Group, Flags<[DriverOption, HelpHidden]>, HelpText<"External function name to load for compiler support">; def fcgl : Flag<["-", "/"], "fcgl">, Group, Flags<[CoreOption, HelpHidden]>, HelpText<"Generate high-level code only">; def not_use_legacy_cbuf_load : Flag<["-", "/"], "not_use_legacy_cbuf_load">, Group, Flags<[CoreOption]>, HelpText<"Do not use legacy cbuffer load">; def pack_prefix_stable : Flag<["-", "/"], "pack_prefix_stable">, Group, Flags<[CoreOption]>, HelpText<"(default) Pack signatures preserving prefix-stable property - appended elements will not disturb placement of prior elements">; def pack_optimized : Flag<["-", "/"], "pack_optimized">, Group, Flags<[CoreOption]>, HelpText<"Optimize signature packing assuming identical signature provided for each connecting stage">; def hlsl_version : Separate<["-", "/"], "HV">, Group, Flags<[CoreOption]>, HelpText<"HLSL version (Only supports 2016 for now)">; def no_warnings : Flag<["-", "/"], "no-warnings">, Group, Flags<[CoreOption]>, HelpText<"Suppress warnings">; def rootsig_define : Separate<["-", "/"], "rootsig-define">, Group, Flags<[CoreOption]>, HelpText<"Read root signature from a #define">; ////////////////////////////////////////////////////////////////////////////// // fxc-based flags that don't match those previously defined. def target_profile : JoinedOrSeparate<["-", "/"], "T">, Flags<[CoreOption]>, Group, HelpText<"Target profile">; def entrypoint : JoinedOrSeparate<["-", "/"], "E">, Flags<[CoreOption]>, Group, HelpText<"Entry point name">; // /I - already defined above def _vi : Flag<["-", "/"], "Vi">, Alias, Flags<[CoreOption]>, Group, HelpText<"Display details about the include process.">; def Od : Flag<["-", "/"], "Od">, Flags<[CoreOption]>, Group, HelpText<"Disable optimizations">; def _SLASH_WX : Flag<["-", "/"], "WX">, Flags<[CoreOption]>, Group, HelpText<"Treat warnings as errors">; def VD : Flag<["-", "/"], "Vd">, Flags<[CoreOption]>, Group, HelpText<"Disable validation">; def _SLASH_Zi : Flag<["-", "/"], "Zi">, Flags<[CoreOption]>, Group, HelpText<"Enable debug information">; def recompile : Flag<["-", "/"], "recompile">, Flags<[CoreOption]>, Group, HelpText<"recompile from DXIL container with Debug Info or Debug Info bitcode file">; def Zpr : Flag<["-", "/"], "Zpr">, Flags<[CoreOption]>, Group, HelpText<"Pack matrices in row-major order">; def Zpc : Flag<["-", "/"], "Zpc">, Flags<[CoreOption]>, Group, HelpText<"Pack matrices in column-major order">; // deprecated /Gpp def Gpp : Flag<["-", "/"], "Gpp">, HelpText<"Force partial precision">; def Gfa : Flag<["-", "/"], "Gfa">, HelpText<"Avoid flow control constructs">, Flags<[CoreOption]>, Group; def Gfp : Flag<["-", "/"], "Gfp">, HelpText<"Prefer flow control constructs">, Flags<[CoreOption]>, Group; // /Gdp - disable effect performance mode - unsupported def Ges : Flag<["-", "/"], "Ges">, HelpText<"Enable strict mode">, Flags<[CoreOption]>, Group; def Gis : Flag<["-", "/"], "Gis">, HelpText<"Force IEEE strictness">, Flags<[CoreOption]>, Group; def Fo : JoinedOrSeparate<["-", "/"], "Fo">, MetaVarName<"">, HelpText<"Output object file">, Flags<[DriverOption]>, Group; // def Fl : JoinedOrSeparate<["-", "/"], "Fl">, MetaVarName<"">, HelpText<"Output a library">; def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"">, HelpText<"Output assembly code listing file">, Flags<[DriverOption]>, Group; //def Fx : JoinedOrSeparate<["-", "/"], "Fx">, MetaVarName<"">, HelpText<"Output assembly code and hex listing file">; def Fh : JoinedOrSeparate<["-", "/"], "Fh">, MetaVarName<"">, HelpText<"Output header file containing object code">, Flags<[DriverOption]>, Group; def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"">, HelpText<"Output warnings and errors to a specific file">, Flags<[DriverOption]>, Group; def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"">, HelpText<"Extract LLVM Debug IR and write to given file">, Flags<[DriverOption]>, Group; def Vn : JoinedOrSeparate<["-", "/"], "Vn">, MetaVarName<"">, HelpText<"Use as variable name in header file">, Flags<[DriverOption]>, Group; def Cc : Flag<["-", "/"], "Cc">, HelpText<"Output color coded assembly listings">, Group, Flags<[DriverOption]>; def Ni : Flag<["-", "/"], "Ni">, HelpText<"Output instruction numbers in assembly listings">, Group, Flags<[DriverOption]>; def No : Flag<["-", "/"], "No">, HelpText<"Output instruction byte offsets in assembly listings">, Group, Flags<[DriverOption]>; def Lx : Flag<["-", "/"], "Lx">, HelpText<"Output hexadecimal literals">, Group, Flags<[DriverOption]>; // In place of 'E' for clang; fxc uses 'E' for entry point. def P : Separate<["-", "/"], "P">, Flags<[DriverOption]>, Group, HelpText<"Preprocess to file (must be used alone)">; // @ - options response file def dumpbin : Flag<["-", "/"], "dumpbin">, Flags<[DriverOption]>, Group, HelpText<"Load a binary file rather than compiling">; def Qstrip_reflect : Flag<["-", "/"], "Qstrip_reflect">, Flags<[DriverOption]>, Group, HelpText<"Strip reflection data from shader bytecode (must be used with /Fo )">; def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[DriverOption]>, Group, HelpText<"Strip debug information from 4_0+ shader bytecode (must be used with /Fo )">; def Qstrip_priv : Flag<["-", "/"], "Qstrip_priv">, Flags<[DriverOption]>, Group, HelpText<"Strip private data from shader bytecode (must be used with /Fo )">; def Qstrip_rootsignature : Flag<["-", "/"], "Qstrip_rootsignature">, Flags<[DriverOption]>, Group, HelpText<"Strip root signature data from shader bytecode (must be used with /Fo )">; def setrootsignature : JoinedOrSeparate<["-", "/"], "setrootsignature">, MetaVarName<"">, Flags<[DriverOption]>, Group, HelpText<"Attach root signature to shader bytecode">; def extractrootsignature : Flag<["-", "/"], "extractrootsignature">, Flags<[DriverOption]>, Group, HelpText<"Extract root signature from shader bytecode (must be used with /Fo )">; def verifyrootsignature : JoinedOrSeparate<["-", "/"], "verifyrootsignature">, MetaVarName<"">, Flags<[DriverOption]>, Group, HelpText<"Verify shader bytecode with root signature">; def force_rootsig_ver : JoinedOrSeparate<["-", "/"], "force_rootsig_ver">, Flags<[CoreOption]>, MetaVarName<"">, Group, HelpText<"force root signature version (rootsig_1_1 if omitted)">; /* def shtemplate : JoinedOrSeparate<["-", "/"], "shtemplate">, MetaVarName<"">, Group, HelpText<"Template shader file for merging/matching resources">; def mergeUAVs : JoinedOrSeparate<["-", "/"], "mergeUAVs">, MetaVarName<"">, Group, HelpText<"Merge UAV slots of template shader and current shader">; def matchUAVs : JoinedOrSeparate<["-", "/"], "matchUAVs">, MetaVarName<"">, Group, HelpText<"Match template shader UAV slots in current shader">; def res_may_alias : Flag<["-", "/"], "res_may_alias">, Flags<[CoreOption]>, Group, HelpText<"Assume that UAVs/SRVs may alias">; def enable_unbounded_descriptor_tables : Flag<["-", "/"], "enable_unbounded_descriptor_tables">, Flags<[CoreOption]>, Group, HelpText<"Enables unbounded descriptor tables">; */ def all_resources_bound : Flag<["-", "/"], "all_resources_bound">, Flags<[CoreOption]>, Group, HelpText<"Enables agressive flattening">; def setprivate : JoinedOrSeparate<["-", "/"], "setprivate">, Flags<[DriverOption]>, MetaVarName<"">, Group, HelpText<"Private data to add to compiled shader blob">; def getprivate : JoinedOrSeparate<["-", "/"], "getprivate">, Flags<[DriverOption]>, MetaVarName<"">, Group, HelpText<"Save private data from shader blob">; def nologo : Flag<["-", "/"], "nologo">, Group, Flags<[DriverOption]>, HelpText<"Suppress copyright message">; // Also removed: compress, decompress, /Gch (child effect), /Gec (back compat), /Gpp (partial precision) // /Op - no support for preshaders. ================================================ FILE: src/Wrapper/dxc/Support/Unicode.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // Unicode.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides utitlity functions to work with Unicode and other encodings. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include #include namespace Unicode { // Based on http://msdn.microsoft.com/en-us/library/windows/desktop/dd374101(v=vs.85).aspx. enum class Encoding { ASCII = 0, UTF8, UTF8_BOM, UTF16_LE, UTF16_BE, UTF32_LE, UTF32_BE }; // An acp_char is a character encoded in the current Windows ANSI code page. typedef char acp_char; // A ccp_char is a character encoded in the console code page. typedef char ccp_char; _Success_(return != false) bool UTF8ToConsoleString(_In_z_ const char* text, _Inout_ std::string* pValue, _Out_opt_ bool* lossy); _Success_(return != false) bool UTF16ToConsoleString(_In_z_ const wchar_t* text, _Inout_ std::string* pValue, _Out_opt_ bool* lossy); _Success_(return != false) bool UTF8ToUTF16String(_In_opt_z_ const char *pUTF8, _Inout_ std::wstring *pUTF16); _Success_(return != false) bool UTF8ToUTF16String(_In_opt_count_(cbUTF8) const char *pUTF8, size_t cbUTF8, _Inout_ std::wstring *pUTF16); std::wstring UTF8ToUTF16StringOrThrow(_In_z_ const char *pUTF8); _Success_(return != false) bool UTF16ToUTF8String(_In_z_ const wchar_t *pUTF16, _Inout_ std::string *pUTF8); std::string UTF16ToUTF8StringOrThrow(_In_z_ const wchar_t *pUTF16); bool IsStarMatchUTF8(_In_reads_opt_(maskLen) const char *pMask, size_t maskLen, _In_reads_opt_(nameLen) const char *pName, size_t nameLen); bool IsStarMatchUTF16(_In_reads_opt_(maskLen) const wchar_t *pMask, size_t maskLen, _In_reads_opt_(nameLen) const wchar_t *pName, size_t nameLen); _Success_(return != false) bool UTF8BufferToUTF16Buffer( _In_NLS_string_(cbUTF8) const char *pUTF8, int cbUTF8, _Outptr_result_buffer_(*pcchUTF16) wchar_t **ppUTF16, size_t *pcchUTF16) throw(); _Success_(return != false) bool UTF16BufferToUTF8Buffer( _In_NLS_string_(cchUTF16) const wchar_t *pUTF16, int cchUTF16, _Outptr_result_buffer_(*pcbUTF8) char **ppUTF8, size_t *pcbUTF8) throw(); } // namespace Unicode ================================================ FILE: src/Wrapper/dxc/Support/WinIncludes.h ================================================ //===- WinIncludes.h --------------------------------------------*- C++ -*-===// /////////////////////////////////////////////////////////////////////////////// // // // WinIncludes.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #define NOATOM 1 #define NOGDICAPMASKS 1 #define NOMETAFILE 1 #define NOMINMAX 1 #define NOOPENFILE 1 #define NORASTEROPS 1 #define NOSCROLL 1 #define NOSOUND 1 #define NOSYSMETRICS 1 #define NOWH 1 #define NOCOMM 1 #define NOKANJI 1 #define NOCRYPT 1 #define NOMCX 1 #define WIN32_LEAN_AND_MEAN 1 #define VC_EXTRALEAN 1 #include #include #include // atlbase.h needs to come before strsafe.h #include #include /// Swap two ComPtr classes. template void swap(CComHeapPtr &a, CComHeapPtr &b) { T *c(a.m_pData); a.m_pData = b.m_pData; b.m_pData = c; } ================================================ FILE: src/Wrapper/dxc/Support/dxcapi.impl.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // dxcapi.impl.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides support for DXC API implementations. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXCAPI_IMPL__ #define __DXCAPI_IMPL__ #include "dxc/dxcapi.h" #include "dxc/Support/microcom.h" #include "llvm/Support/raw_ostream.h" // Simple adaptor for IStream. Can probably do better. class raw_stream_ostream : public llvm::raw_ostream { private: CComPtr m_pStream; void write_impl(const char *Ptr, size_t Size) override { ULONG cbWritten; IFT(m_pStream->Write(Ptr, Size, &cbWritten)); } uint64_t current_pos() const { return m_pStream->GetPosition(); } public: raw_stream_ostream(hlsl::AbstractMemoryStream* pStream) : m_pStream(pStream) { } ~raw_stream_ostream() override { flush(); } }; class DxcOperationResult : public IDxcOperationResult { private: DXC_MICROCOM_REF_FIELD(m_dwRef) DxcOperationResult(_In_opt_ IDxcBlob *pResultBlob, _In_opt_ IDxcBlobEncoding *pErrorBlob, HRESULT status) : m_dwRef(0), m_status(status), m_result(pResultBlob), m_errors(pErrorBlob) {} public: DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) HRESULT m_status; CComPtr m_result; CComPtr m_errors; HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return DoBasicQueryInterface(this, iid, ppvObject); } static HRESULT CreateFromResultErrorStatus(_In_opt_ IDxcBlob *pResultBlob, _In_opt_ IDxcBlobEncoding *pErrorBlob, HRESULT status, _COM_Outptr_ IDxcOperationResult **ppResult) { *ppResult = nullptr; CComPtr result = new (std::nothrow) DxcOperationResult(pResultBlob, pErrorBlob, status); if (result.p == nullptr) return E_OUTOFMEMORY; *ppResult = result.Detach(); return S_OK; } static HRESULT CreateFromUtf8Strings(_In_opt_z_ LPCSTR pErrorStr, _In_opt_z_ LPCSTR pResultStr, HRESULT status, _COM_Outptr_ IDxcOperationResult **pResult) { *pResult = nullptr; CComPtr resultBlob; CComPtr errorBlob; CComPtr result; HRESULT hr = S_OK; if (pErrorStr != nullptr) { hr = hlsl::DxcCreateBlobWithEncodingOnHeapCopy( pErrorStr, strlen(pErrorStr), CP_UTF8, &errorBlob); if (FAILED(hr)) { return hr; } } if (pResultStr != nullptr) { hr = hlsl::DxcCreateBlobWithEncodingOnHeap( pResultStr, strlen(pResultStr), CP_UTF8, &resultBlob); if (FAILED(hr)) { return hr; } } return CreateFromResultErrorStatus(resultBlob, errorBlob, status, pResult); } __override HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) { if (pStatus == nullptr) return E_INVALIDARG; *pStatus = m_status; return S_OK; } __override HRESULT STDMETHODCALLTYPE GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **ppResult) { return m_result.CopyTo(ppResult); } __override HRESULT STDMETHODCALLTYPE GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **ppErrors) { return m_errors.CopyTo(ppErrors); } }; #endif ================================================ FILE: src/Wrapper/dxc/Support/dxcapi.use.h ================================================ ////////////////////////////////////////////////////////////////////////////// // // // dxcapi.use.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides support for DXC API users. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXCAPI_USE_H__ #define __DXCAPI_USE_H__ #include "dxc/dxcapi.h" namespace dxc { // Helper class to dynamically load the dxcompiler or a compatible libraries. class DxcDllSupport { protected: HMODULE m_dll; DxcCreateInstanceProc m_createFn; HRESULT InitializeInternal(LPCWSTR dllName, LPCSTR fnName) { if (m_dll != nullptr) return S_OK; m_dll = LoadLibraryW(dllName); if (m_dll == nullptr) return HRESULT_FROM_WIN32(GetLastError()); m_createFn = (DxcCreateInstanceProc)GetProcAddress(m_dll, fnName); if (m_createFn == nullptr) { HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); FreeLibrary(m_dll); m_dll = nullptr; return hr; } return S_OK; } public: DxcDllSupport() : m_dll(nullptr), m_createFn(nullptr) { } DxcDllSupport(DxcDllSupport&& other) { m_dll = other.m_dll; other.m_dll = nullptr; m_createFn = other.m_createFn; other.m_dll = nullptr; } ~DxcDllSupport() { Cleanup(); } HRESULT Initialize() { return InitializeInternal(L"dxcompiler.dll", "DxcCreateInstance"); } HRESULT InitializeForDll(_In_z_ const wchar_t* dll, _In_z_ const char* entryPoint) { return InitializeInternal(dll, entryPoint); } template HRESULT CreateInstance(REFCLSID clsid, _Outptr_ TInterface** pResult) { return CreateInstance(clsid, __uuidof(TInterface), (IUnknown**)pResult); } HRESULT CreateInstance(REFCLSID clsid, REFIID riid, _Outptr_ IUnknown **pResult) { if (pResult == nullptr) return E_POINTER; if (m_dll == nullptr) return E_FAIL; HRESULT hr = m_createFn(clsid, riid, (LPVOID*)pResult); return hr; } bool IsEnabled() const { return m_dll != nullptr; } void Cleanup() { if (m_dll != nullptr) { m_createFn = nullptr; FreeLibrary(m_dll); m_dll = nullptr; } } HMODULE Detach() { HMODULE module = m_dll; m_dll = nullptr; return module; } }; inline DxcDefine GetDefine(_In_ LPCWSTR name, LPCWSTR value) { DxcDefine result; result.Name = name; result.Value = value; return result; } // Checks an HRESULT and formats an error message with the appended data. void IFT_Data(HRESULT hr, _In_opt_ LPCWSTR data); void EnsureEnabled(DxcDllSupport &dxcSupport); void ReadFileIntoBlob(DxcDllSupport &dxcSupport, _In_ LPCWSTR pFileName, _Outptr_ IDxcBlobEncoding **ppBlobEncoding); void WriteBlobToConsole(_In_opt_ IDxcBlob *pBlob, DWORD streamType = STD_OUTPUT_HANDLE); void WriteBlobToFile(_In_opt_ IDxcBlob *pBlob, _In_ LPCWSTR pFileName); void WriteBlobToHandle(_In_opt_ IDxcBlob *pBlob, HANDLE hFile, _In_opt_ LPCWSTR pFileName); void WriteUtf8ToConsole(_In_opt_count_(charCount) const char *pText, int charCount, DWORD streamType = STD_OUTPUT_HANDLE); void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText, size_t charCount, DWORD streamType = STD_OUTPUT_HANDLE); void WriteOperationErrorsToConsole(_In_ IDxcOperationResult *pResult, bool outputWarnings); void WriteOperationResultToConsole(_In_ IDxcOperationResult *pRewriteResult, bool outputWarnings); } // namespace dxc #endif ================================================ FILE: src/Wrapper/dxc/Support/exception.h ================================================ //===- exception.h ----------------------------------------------*- C++ -*-===// /////////////////////////////////////////////////////////////////////////////// // // // exception.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/Support/ErrorCodes.h" #include #include namespace hlsl { /// /// Exception stores off information about an error and its error message for /// later consumption by the hlsl compiler tools. /// struct Exception : public std::exception { /// HRESULT error code. Must be a failure. HRESULT hr; std::string msg; Exception(HRESULT errCode) : hr(errCode) { } Exception(HRESULT errCode, const std::string &errMsg) : hr(errCode), msg(errMsg) { } // what returns a formatted message with the error code and the message used // to create the message. virtual const char *what() const throw() { return msg.c_str(); } }; } // namespace hlsl ================================================ FILE: src/Wrapper/dxc/Support/microcom.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // microcom.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides support for basic COM-like constructs. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXC_MICROCOM__ #define __DXC_MICROCOM__ template class CComInterfaceArray { private: TIface **m_pData; unsigned m_length; public: CComInterfaceArray() : m_pData(nullptr), m_length(0) { } ~CComInterfaceArray() { clear(); } bool empty() const { return m_length == 0; } unsigned size() const { return m_length; } TIface ***data_ref() { return &m_pData; } unsigned *size_ref() { return &m_length; } TIface **begin() { return m_pData; } TIface **end() { return m_pData + m_length; } void clear() { if (m_length) { for (unsigned i = 0; i < m_length; ++i) { if (m_pData[i] != nullptr) { m_pData[i]->Release(); m_pData[i] = nullptr; } } m_length = 0; } if (m_pData) { CoTaskMemFree(m_pData); m_pData = nullptr; } } HRESULT alloc(unsigned count) { clear(); m_pData = (TIface**)CoTaskMemAlloc(sizeof(TIface*) * count); if (m_pData == nullptr) return E_OUTOFMEMORY; m_length = count; ZeroMemory(m_pData, sizeof(TIface*) * count); return S_OK; } TIface **get_address_of(unsigned index) { return &(m_pData[index]); } TIface **release() { TIface **result = m_pData; m_pData = nullptr; m_length = 0; return result; } void release(TIface ***pValues, unsigned *length) { *pValues = m_pData; m_pData = nullptr; *length = m_length; m_length = 0; } }; #define DXC_MICROCOM_REF_FIELD(m_dwRef) volatile ULONG m_dwRef; #define DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) \ bool HasSingleRef() { return 1 == m_dwRef; } \ ULONG STDMETHODCALLTYPE AddRef() {\ return InterlockedIncrement(&m_dwRef); \ } \ ULONG STDMETHODCALLTYPE Release() { \ ULONG result = InterlockedDecrement(&m_dwRef); \ if (result == 0) delete this; \ return result; \ } /// /// Provides a QueryInterface implementation for a class that supports /// a single interface in addition to IUnknown. /// /// /// This implementation will also report the instance as not supporting /// marshaling. This will help catch marshaling problems early or avoid /// them altogether. /// template HRESULT DoBasicQueryInterface(TObject* self, REFIID iid, void** ppvObject) { if (ppvObject == nullptr) return E_POINTER; // Support INoMarshal to void GIT shenanigans. if (IsEqualIID(iid, __uuidof(IUnknown)) || IsEqualIID(iid, __uuidof(INoMarshal))) { *ppvObject = reinterpret_cast(self); reinterpret_cast(self)->AddRef(); return S_OK; } if (IsEqualIID(iid, __uuidof(TInterface))) { *(TInterface**)ppvObject = self; self->AddRef(); return S_OK; } return E_NOINTERFACE; } /// /// Provides a QueryInterface implementation for a class that supports /// two interfaces in addition to IUnknown. /// /// /// This implementation will also report the instance as not supporting /// marshaling. This will help catch marshaling problems early or avoid /// them altogether. /// template HRESULT DoBasicQueryInterface2(TObject* self, REFIID iid, void** ppvObject) { if (ppvObject == nullptr) return E_POINTER; // Support INoMarshal to void GIT shenanigans. if (IsEqualIID(iid, __uuidof(IUnknown)) || IsEqualIID(iid, __uuidof(INoMarshal))) { *ppvObject = reinterpret_cast(self); reinterpret_cast(self)->AddRef(); return S_OK; } if (IsEqualIID(__uuidof(TInterface), iid)) { *(TInterface**)ppvObject = self; self->AddRef(); return S_OK; } if (IsEqualIID(__uuidof(TInterface2), iid)) { *(TInterface2**)ppvObject = self; self->AddRef(); return S_OK; } return E_NOINTERFACE; } /// /// Provides a QueryInterface implementation for a class that supports /// three interfaces in addition to IUnknown. /// /// /// This implementation will also report the instance as not supporting /// marshaling. This will help catch marshaling problems early or avoid /// them altogether. /// template HRESULT DoBasicQueryInterface3(TObject* self, REFIID iid, void** ppvObject) { if (ppvObject == nullptr) return E_POINTER; if (IsEqualIID(iid, __uuidof(TInterface3))) { *(TInterface3**)ppvObject = self; self->AddRef(); return S_OK; } return DoBasicQueryInterface2(self, iid, ppvObject); } template HRESULT AssignToOut(T value, _Out_ T* pResult) { if (pResult == nullptr) return E_POINTER; *pResult = value; return S_OK; } template HRESULT AssignToOut(nullptr_t value, _Out_ T* pResult) { if (pResult == nullptr) return E_POINTER; *pResult = value; return S_OK; } template HRESULT ZeroMemoryToOut(_Out_ T* pResult) { if (pResult == nullptr) return E_POINTER; ZeroMemory(pResult, sizeof(*pResult)); return S_OK; } template void AssignToOutOpt(T value, _Out_opt_ T* pResult) { if (pResult != nullptr) *pResult = value; } template void AssignToOutOpt(nullptr_t value, _Out_opt_ T* pResult) { if (pResult != nullptr) *pResult = value; } #endif ================================================ FILE: src/Wrapper/dxc/Tracing/CMakeLists.txt ================================================ # Copyright (C) Microsoft Corporation. All rights reserved. # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. # Generate ETW instrumentation. # Create the header in a temporary file and only update when necessary, # to avoid invalidating targets that depend on it. add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dxc/Tracing/tmpdxcetw.h COMMAND mc -r ${CMAKE_CURRENT_BINARY_DIR} -h ${CMAKE_CURRENT_BINARY_DIR} -p DxcEtw_ -um -z tmpdxcetw ${CMAKE_CURRENT_SOURCE_DIR}/dxcetw.man DEPENDS {CMAKE_CURRENT_SOURCE_DIR}/dxcetw.man COMMENT "Building instrumentation manifest ..." ) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dxc/Tracing/dxcetw.h COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/tmpdxcetw.h ${CMAKE_CURRENT_BINARY_DIR}/dxcetw.h COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/tmpdxcetw.rc ${CMAKE_CURRENT_BINARY_DIR}/dxcetw.rc COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/tmpdxcetwTEMP.bin ${CMAKE_CURRENT_BINARY_DIR}/dxcetwTEMP.bin COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/tmpdxcetw_MSG00001.bin ${CMAKE_CURRENT_BINARY_DIR}/MSG00001.bin DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dxc/Tracing/tmpdxcetw.h COMMENT "Updating instrumentation manifest ..." ) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/dxcetw.h PROPERTIES GENERATED 1) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/dxcetw.rc PROPERTIES GENERATED 1) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/dxcetwTEMP.bin PROPERTIES GENERATED 1) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/MSG00001.bin PROPERTIES GENERATED 1) add_custom_target(DxcEtw DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dxc/Tracing/dxcetw.h SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/dxcetw.man ) # Not quite tablegen, but close enough. set_target_properties(DxcEtw PROPERTIES FOLDER "Tablegenning") ================================================ FILE: src/Wrapper/dxc/Tracing/dxcetw.man ================================================  ================================================ FILE: src/Wrapper/dxc/dxcapi.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // dxcapi.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides declarations for the DirectX Compiler API entry point. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXC_API__ #define __DXC_API__ #ifndef DXC_API_IMPORT #define DXC_API_IMPORT __declspec(dllimport) #endif struct IMalloc; struct IDxcIncludeHandler; /// /// Creates a single uninitialized object of the class associated with a specified CLSID. /// /// /// The CLSID associated with the data and code that will be used to create the object. /// /// /// A reference to the identifier of the interface to be used to communicate /// with the object. /// /// /// Address of pointer variable that receives the interface pointer requested /// in riid. Upon successful return, *ppv contains the requested interface /// pointer. Upon failure, *ppv contains NULL. /// /// While this function is similar to CoCreateInstance, there is no COM involvement. /// typedef HRESULT (__stdcall *DxcCreateInstanceProc)( _In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID* ppv ); typedef HRESULT(__stdcall *DxcCreateInstance2Proc)( _In_ IMalloc *pMalloc, _In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID* ppv ); /// /// Creates a single uninitialized object of the class associated with a specified CLSID. /// /// /// The CLSID associated with the data and code that will be used to create the object. /// /// /// A reference to the identifier of the interface to be used to communicate /// with the object. /// /// /// Address of pointer variable that receives the interface pointer requested /// in riid. Upon successful return, *ppv contains the requested interface /// pointer. Upon failure, *ppv contains NULL. /// /// While this function is similar to CoCreateInstance, there is no COM involvement. /// DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance( _In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID* ppv ); DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2( _In_ IMalloc *pMalloc, _In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID* ppv ); // IDxcBlob is an alias of ID3D10Blob and ID3DBlob struct __declspec(uuid("8BA5FB08-5195-40e2-AC58-0D989C3A0102")) IDxcBlob : public IUnknown { public: virtual LPVOID STDMETHODCALLTYPE GetBufferPointer(void) = 0; virtual SIZE_T STDMETHODCALLTYPE GetBufferSize(void) = 0; }; struct __declspec(uuid("7241d424-2646-4191-97c0-98e96e42fc68")) IDxcBlobEncoding : public IDxcBlob { public: virtual HRESULT STDMETHODCALLTYPE GetEncoding(_Out_ BOOL *pKnown, _Out_ UINT32 *pCodePage) = 0; }; struct __declspec(uuid("e5204dc7-d18c-4c3c-bdfb-851673980fe7")) IDxcLibrary : public IUnknown { virtual HRESULT STDMETHODCALLTYPE SetMalloc(_In_opt_ IMalloc *pMalloc) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBlobFromBlob( _In_ IDxcBlob *pBlob, UINT32 offset, UINT32 length, _COM_Outptr_ IDxcBlob **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBlobFromFile( LPCWSTR pFileName, _In_opt_ UINT32* codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingFromPinned( LPBYTE pText, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnHeapCopy( _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBlobWithEncodingOnMalloc( _In_bytecount_(size) LPCVOID pText, IMalloc *pIMalloc, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; virtual HRESULT STDMETHODCALLTYPE CreateIncludeHandler( _COM_Outptr_ IDxcIncludeHandler **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE CreateStreamFromBlobReadOnly( _In_ IDxcBlob *pBlob, _COM_Outptr_ IStream **ppStream) = 0; virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf8( _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf16( _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0; }; struct __declspec(uuid("CEDB484A-D4E9-445A-B991-CA21CA157DC2")) IDxcOperationResult : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) = 0; virtual HRESULT STDMETHODCALLTYPE GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **pErrors) = 0; }; struct __declspec(uuid("7f61fc7d-950d-467f-b3e3-3c02fb49187c")) IDxcIncludeHandler : public IUnknown { virtual HRESULT STDMETHODCALLTYPE LoadSource( _In_ LPCWSTR pFilename, // Candidate filename. _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource // Resultant source object for included file, nullptr if not found. ) = 0; }; struct DxcDefine { LPCWSTR Name; _Maybenull_ LPCWSTR Value; }; struct __declspec(uuid("8c210bf3-011f-4422-8d70-6f9acb8db617")) IDxcCompiler : public IUnknown { // Compile a single entry point to the target shader model virtual HRESULT STDMETHODCALLTYPE Compile( _In_ IDxcBlob *pSource, // Source text to compile _In_opt_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. _In_ LPCWSTR pEntryPoint, // entry point name _In_ LPCWSTR pTargetProfile, // shader profile to compile _In_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments _In_ UINT32 argCount, // Number of arguments _In_count_(defineCount) const DxcDefine *pDefines, // Array of defines _In_ UINT32 defineCount, // Number of defines _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) _COM_Outptr_ IDxcOperationResult **ppResult // Compiler output status, buffer, and errors ) = 0; // Preprocess source text virtual HRESULT STDMETHODCALLTYPE Preprocess( _In_ IDxcBlob *pSource, // Source text to preprocess _In_opt_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. _In_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments _In_ UINT32 argCount, // Number of arguments _In_count_(defineCount) const DxcDefine *pDefines, // Array of defines _In_ UINT32 defineCount, // Number of defines _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) _COM_Outptr_ IDxcOperationResult **ppResult // Preprocessor output status, buffer, and errors ) = 0; // Disassemble a program. virtual HRESULT STDMETHODCALLTYPE Disassemble( _In_ IDxcBlob *pSource, // Program to disassemble. _COM_Outptr_ IDxcBlobEncoding **ppDisassembly // Disassembly text. ) = 0; }; struct __declspec(uuid("A005A9D9-B8BB-4594-B5C9-0E633BEC4D37")) IDxcCompiler2 : public IDxcCompiler { // Compile a single entry point to the target shader model with debug information. virtual HRESULT STDMETHODCALLTYPE CompileWithDebug( _In_ IDxcBlob *pSource, // Source text to compile _In_opt_ LPCWSTR pSourceName, // Optional file name for pSource. Used in errors and include handlers. _In_ LPCWSTR pEntryPoint, // Entry point name _In_ LPCWSTR pTargetProfile, // Shader profile to compile _In_count_(argCount) LPCWSTR *pArguments, // Array of pointers to arguments _In_ UINT32 argCount, // Number of arguments _In_count_(defineCount) const DxcDefine *pDefines, // Array of defines _In_ UINT32 defineCount, // Number of defines _In_opt_ IDxcIncludeHandler *pIncludeHandler, // user-provided interface to handle #include directives (optional) _COM_Outptr_ IDxcOperationResult **ppResult, // Compiler output status, buffer, and errors _Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob. _COM_Outptr_opt_ IDxcBlob **ppDebugBlob // Debug blob ) = 0; }; struct __declspec(uuid("F1B5BE2A-62DD-4327-A1C2-42AC1E1E78E6")) IDxcLinker : public IUnknown { public: // Register a library with name to ref it later. virtual HRESULT RegisterLibrary( _In_opt_ LPCWSTR pLibName, // Name of the library. _In_ IDxcBlob *pLib // Library blob. ) = 0; // Links the shader and produces a shader blob that the Direct3D runtime can // use. virtual HRESULT STDMETHODCALLTYPE Link( _In_opt_ LPCWSTR pEntryName, // Entry point name _In_ LPCWSTR pTargetProfile, // shader profile to link _In_count_(libCount) const LPCWSTR *pLibNames, // Array of library names to link UINT32 libCount, // Number of libraries to link _In_count_(argCount) const LPCWSTR *pArguments, // Array of pointers to arguments _In_ UINT32 argCount, // Number of arguments _COM_Outptr_ IDxcOperationResult * *ppResult // Linker output status, buffer, and errors ) = 0; }; static const UINT32 DxcValidatorFlags_Default = 0; static const UINT32 DxcValidatorFlags_InPlaceEdit = 1; // Validator is allowed to update shader blob in-place. static const UINT32 DxcValidatorFlags_RootSignatureOnly = 2; static const UINT32 DxcValidatorFlags_ModuleOnly = 4; static const UINT32 DxcValidatorFlags_ValidMask = 0x7; struct __declspec(uuid("A6E82BD2-1FD7-4826-9811-2857E797F49A")) IDxcValidator : public IUnknown { // Validate a shader. virtual HRESULT STDMETHODCALLTYPE Validate( _In_ IDxcBlob *pShader, // Shader to validate. _In_ UINT32 Flags, // Validation flags. _COM_Outptr_ IDxcOperationResult **ppResult // Validation output status, buffer, and errors ) = 0; }; struct __declspec(uuid("334b1f50-2292-4b35-99a1-25588d8c17fe")) IDxcContainerBuilder : public IUnknown { virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pDxilContainerHeader) = 0; // Loads DxilContainer to the builder virtual HRESULT STDMETHODCALLTYPE AddPart(_In_ UINT32 fourCC, _In_ IDxcBlob *pSource) = 0; // Part to add to the container virtual HRESULT STDMETHODCALLTYPE RemovePart(_In_ UINT32 fourCC) = 0; // Remove the part with fourCC virtual HRESULT STDMETHODCALLTYPE SerializeContainer(_Out_ IDxcOperationResult **ppResult) = 0; // Builds a container of the given container builder state }; struct __declspec(uuid("091f7a26-1c1f-4948-904b-e6e3a8a771d5")) IDxcAssembler : public IUnknown { // Assemble dxil in ll or llvm bitcode to DXIL container. virtual HRESULT STDMETHODCALLTYPE AssembleToContainer( _In_ IDxcBlob *pShader, // Shader to assemble. _COM_Outptr_ IDxcOperationResult **ppResult // Assembly output status, buffer, and errors ) = 0; }; struct __declspec(uuid("d2c21b26-8350-4bdc-976a-331ce6f4c54c")) IDxcContainerReflection : public IUnknown { virtual HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pContainer) = 0; // Container to load. virtual HRESULT STDMETHODCALLTYPE GetPartCount(_Out_ UINT32 *pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetPartKind(UINT32 idx, _Out_ UINT32 *pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetPartReflection(UINT32 idx, REFIID iid, void **ppvObject) = 0; }; struct __declspec(uuid("AE2CD79F-CC22-453F-9B6B-B124E7A5204C")) IDxcOptimizerPass : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetOptionName(_COM_Outptr_ LPWSTR *ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetDescription(_COM_Outptr_ LPWSTR *ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetOptionArgCount(_Out_ UINT32 *pCount) = 0; virtual HRESULT STDMETHODCALLTYPE GetOptionArgName(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetOptionArgDescription(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0; }; struct __declspec(uuid("25740E2E-9CBA-401B-9119-4FB42F39F270")) IDxcOptimizer : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetAvailablePassCount(_Out_ UINT32 *pCount) = 0; virtual HRESULT STDMETHODCALLTYPE GetAvailablePass(UINT32 index, _COM_Outptr_ IDxcOptimizerPass** ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE RunOptimizer(IDxcBlob *pBlob, _In_count_(optionCount) LPCWSTR *ppOptions, UINT32 optionCount, _COM_Outptr_ IDxcBlob **pOutputModule, _COM_Outptr_opt_ IDxcBlobEncoding **ppOutputText) = 0; }; static const UINT32 DxcVersionInfoFlags_None = 0; static const UINT32 DxcVersionInfoFlags_Debug = 1; // Matches VS_FF_DEBUG static const UINT32 DxcVersionInfoFlags_Internal = 2; // Internal Validator (non-signing) struct __declspec(uuid("b04f5b50-2059-4f12-a8ff-a1e0cde1cc7e")) IDxcVersionInfo : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0; }; // {73e22d93-e6ce-47f3-b5bf-f0664f39c1b0} __declspec(selectany) extern const CLSID CLSID_DxcCompiler = { 0x73e22d93, 0xe6ce, 0x47f3, { 0xb5, 0xbf, 0xf0, 0x66, 0x4f, 0x39, 0xc1, 0xb0 } }; // {EF6A8087-B0EA-4D56-9E45-D07E1A8B7806} __declspec(selectany) extern const GUID CLSID_DxcLinker = { 0xef6a8087, 0xb0ea, 0x4d56, {0x9e, 0x45, 0xd0, 0x7e, 0x1a, 0x8b, 0x78, 0x6} }; // {CD1F6B73-2AB0-484D-8EDC-EBE7A43CA09F} __declspec(selectany) extern const CLSID CLSID_DxcDiaDataSource = { 0xcd1f6b73, 0x2ab0, 0x484d, { 0x8e, 0xdc, 0xeb, 0xe7, 0xa4, 0x3c, 0xa0, 0x9f } }; // {6245D6AF-66E0-48FD-80B4-4D271796748C} __declspec(selectany) extern const GUID CLSID_DxcLibrary = { 0x6245d6af, 0x66e0, 0x48fd, { 0x80, 0xb4, 0x4d, 0x27, 0x17, 0x96, 0x74, 0x8c } }; // {8CA3E215-F728-4CF3-8CDD-88AF917587A1} __declspec(selectany) extern const GUID CLSID_DxcValidator = { 0x8ca3e215, 0xf728, 0x4cf3, { 0x8c, 0xdd, 0x88, 0xaf, 0x91, 0x75, 0x87, 0xa1 } }; // {D728DB68-F903-4F80-94CD-DCCF76EC7151} __declspec(selectany) extern const GUID CLSID_DxcAssembler = { 0xd728db68, 0xf903, 0x4f80, { 0x94, 0xcd, 0xdc, 0xcf, 0x76, 0xec, 0x71, 0x51 } }; // {b9f54489-55b8-400c-ba3a-1675e4728b91} __declspec(selectany) extern const GUID CLSID_DxcContainerReflection = { 0xb9f54489, 0x55b8, 0x400c, { 0xba, 0x3a, 0x16, 0x75, 0xe4, 0x72, 0x8b, 0x91 } }; // {AE2CD79F-CC22-453F-9B6B-B124E7A5204C} __declspec(selectany) extern const GUID CLSID_DxcOptimizer = { 0xae2cd79f, 0xcc22, 0x453f, {0x9b, 0x6b, 0xb1, 0x24, 0xe7, 0xa5, 0x20, 0x4c} }; // {94134294-411f-4574-b4d0-8741e25240d2} __declspec(selectany) extern const GUID CLSID_DxcContainerBuilder = { 0x94134294, 0x411f, 0x4574, { 0xb4, 0xd0, 0x87, 0x41, 0xe2, 0x52, 0x40, 0xd2 } }; #endif ================================================ FILE: src/Wrapper/dxc/dxcapi.internal.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // dxcapi.internal.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides non-public declarations for the DirectX Compiler component. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXC_API_INTERNAL__ #define __DXC_API_INTERNAL__ #include "dxcapi.h" /////////////////////////////////////////////////////////////////////////////// // Forward declarations. typedef interface ITextFont ITextFont; typedef interface IEnumSTATSTG IEnumSTATSTG; typedef interface ID3D10Blob ID3D10Blob; /////////////////////////////////////////////////////////////////////////////// // Intrinsic definitions. #define AR_QUAL_IN 0x0000000000000010UI64 #define AR_QUAL_OUT 0x0000000000000020UI64 #define AR_QUAL_CONST 0x0000000000000200UI64 #define AR_QUAL_ROWMAJOR 0x0000000000000400UI64 #define AR_QUAL_COLMAJOR 0x0000000000000800UI64 #define AR_QUAL_IN_OUT (AR_QUAL_IN | AR_QUAL_OUT) static const BYTE INTRIN_TEMPLATE_FROM_TYPE = 0xff; static const BYTE INTRIN_TEMPLATE_VARARGS = 0xfe; // Use this enumeration to describe allowed templates (layouts) in intrinsics. enum LEGAL_INTRINSIC_TEMPLATES { LITEMPLATE_VOID = 0, // No return type. LITEMPLATE_SCALAR = 1, // Scalar types. LITEMPLATE_VECTOR = 2, // Vector types (eg. float3). LITEMPLATE_MATRIX = 3, // Matrix types (eg. float3x3). LITEMPLATE_ANY = 4, // Any one of scalar, vector or matrix types (but not object). LITEMPLATE_OBJECT = 5, // Object types. LITEMPLATE_COUNT = 6 }; // INTRIN_COMPTYPE_FROM_TYPE_ELT0 is for object method intrinsics to indicate // that the component type of the type is taken from the first subelement of the // object's template type; see for example Texture2D.Gather static const BYTE INTRIN_COMPTYPE_FROM_TYPE_ELT0 = 0xff; enum LEGAL_INTRINSIC_COMPTYPES { LICOMPTYPE_VOID = 0, // void, used for function returns LICOMPTYPE_BOOL = 1, // bool LICOMPTYPE_INT = 2, // i32, int-literal LICOMPTYPE_UINT = 3, // u32, int-literal LICOMPTYPE_ANY_INT = 4, // i32, u32, i64, u64, int-literal LICOMPTYPE_ANY_INT32 = 5, // i32, u32, int-literal LICOMPTYPE_UINT_ONLY = 6, // u32, u64, int-literal; no casts allowed LICOMPTYPE_FLOAT = 7, // f32, partial-precision-f32, float-literal LICOMPTYPE_ANY_FLOAT = 8, // f32, partial-precision-f32, f64, float-literal, min10-float, min16-float LICOMPTYPE_FLOAT_LIKE = 9, // f32, partial-precision-f32, float-literal, min10-float, min16-float LICOMPTYPE_FLOAT_DOUBLE = 10, // f32, partial-precision-f32, f64, float-literal LICOMPTYPE_DOUBLE = 11, // f64, float-literal LICOMPTYPE_DOUBLE_ONLY = 12, // f64; no casts allowed LICOMPTYPE_NUMERIC = 13, // float-literal, f32, partial-precision-f32, f64, min10-float, min16-float, int-literal, i32, u32, min12-int, min16-int, min16-uint, i64, u64 LICOMPTYPE_NUMERIC32 = 14, // float-literal, f32, partial-precision-f32, int-literal, i32, u32 LICOMPTYPE_NUMERIC32_ONLY = 15, // float-literal, f32, partial-precision-f32, int-literal, i32, u32; no casts allowed LICOMPTYPE_ANY = 16, // float-literal, f32, partial-precision-f32, f64, min10-float, min16-float, int-literal, i32, u32, min12-int, min16-int, min16-uint, bool, i64, u64 LICOMPTYPE_SAMPLER1D = 17, LICOMPTYPE_SAMPLER2D = 18, LICOMPTYPE_SAMPLER3D = 19, LICOMPTYPE_SAMPLERCUBE = 20, LICOMPTYPE_SAMPLERCMP = 21, LICOMPTYPE_SAMPLER = 22, LICOMPTYPE_STRING = 23, LICOMPTYPE_WAVE = 24, LICOMPTYPE_UINT64 = 25, // u64, int-literal LICOMPTYPE_UINT32_64 = 26, // u32, u64, int-literal LICOMPTYPE_COUNT = 27 }; static const BYTE IA_SPECIAL_BASE = 0xf0; static const BYTE IA_R = 0xf0; static const BYTE IA_C = 0xf1; static const BYTE IA_R2 = 0xf2; static const BYTE IA_C2 = 0xf3; static const BYTE IA_SPECIAL_SLOTS = 4; struct HLSL_INTRINSIC_ARGUMENT { LPCSTR pName; // Name of the argument; the first argument has the function name. UINT64 qwUsage; // A combination of AR_QUAL_IN|AR_QUAL_OUT|AR_QUAL_COLMAJOR|AR_QUAL_ROWMAJOR in parameter tables; other values possible elsewhere. BYTE uTemplateId; // One of INTRIN_TEMPLATE_FROM_TYPE, INTRIN_TEMPLATE_VARARGS or the argument # the template (layout) must match (trivially itself). BYTE uLegalTemplates; // A LEGAL_INTRINSIC_TEMPLATES value for allowed templates. BYTE uComponentTypeId; // INTRIN_COMPTYPE_FROM_TYPE_ELT0, or the argument # the component (element type) must match (trivially itself). BYTE uLegalComponentTypes; // A LEGAL_INTRINSIC_COMPTYPES value for allowed components. BYTE uRows; // Required number of rows, or one of IA_R/IA_C/IA_R2/IA_C2 for matching input constraints. BYTE uCols; // Required number of cols, or one of IA_R/IA_C/IA_R2/IA_C2 for matching input constraints. }; struct HLSL_INTRINSIC { UINT Op; // Intrinsic Op ID BOOL bReadOnly; // Only read memory BOOL bReadNone; // Not read memory INT iOverloadParamIndex; // Parameter decide the overload type, -1 means ret type UINT uNumArgs; // Count of arguments in pArgs. const HLSL_INTRINSIC_ARGUMENT* pArgs; // Pointer to first argument. }; /////////////////////////////////////////////////////////////////////////////// // Interfaces. struct __declspec(uuid("f0d4da3f-f863-4660-b8b4-dfd94ded6215")) IDxcIntrinsicTable : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetTableName(_Outptr_ LPCSTR *pTableName) = 0; virtual HRESULT STDMETHODCALLTYPE LookupIntrinsic( LPCWSTR typeName, LPCWSTR functionName, const HLSL_INTRINSIC** pIntrinsic, _Inout_ UINT64* pLookupCookie) = 0; // Get the lowering strategy for an hlsl extension intrinsic. virtual HRESULT STDMETHODCALLTYPE GetLoweringStrategy(UINT opcode, LPCSTR *pStrategy) = 0; // Callback to support custom naming of hlsl extension intrinsic functions in dxil. // Return the empty string to get the default intrinsic name, which is the mangled // name of the high level intrinsic function. // // Overloaded intrinsics are supported by use of an overload place holder in the // name. The string "$o" in the name will be replaced by the return type of the // intrinsic. virtual HRESULT STDMETHODCALLTYPE GetIntrinsicName(UINT opcode, LPCSTR *pName) = 0; // Callback to support the 'dxil' lowering strategy. // Returns the dxil opcode that the intrinsic should use for lowering. virtual HRESULT STDMETHODCALLTYPE GetDxilOpCode(UINT opcode, UINT *pDxilOpcode) = 0; }; struct __declspec(uuid("1d063e4f-515a-4d57-a12a-431f6a44cfb9")) IDxcSemanticDefineValidator : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetSemanticDefineWarningsAndErrors(LPCSTR pName, LPCSTR pValue, IDxcBlobEncoding **ppWarningBlob, IDxcBlobEncoding **ppErrorBlob) = 0; }; struct __declspec(uuid("282a56b4-3f56-4360-98c7-9ea04a752272")) IDxcLangExtensions : public IUnknown { public: /// /// Registers the name of a preprocessor define that has semantic meaning /// and should be preserved for downstream consumers. /// virtual HRESULT STDMETHODCALLTYPE RegisterSemanticDefine(LPCWSTR name) = 0; /// Registers a name to exclude from semantic defines. virtual HRESULT STDMETHODCALLTYPE RegisterSemanticDefineExclusion(LPCWSTR name) = 0; /// Registers a definition for compilation. virtual HRESULT STDMETHODCALLTYPE RegisterDefine(LPCWSTR name) = 0; /// Registers a table of built-in intrinsics. virtual HRESULT STDMETHODCALLTYPE RegisterIntrinsicTable(_In_ IDxcIntrinsicTable* pTable) = 0; /// Sets an (optional) validator for parsed semantic defines. /// This provides a hook to check that the semantic defines present in the source /// contain valid data. One validator is used to validate all parsed semantic defines. virtual HRESULT STDMETHODCALLTYPE SetSemanticDefineValidator(_In_ IDxcSemanticDefineValidator* pValidator) = 0; /// Sets the name for the root metadata node used in DXIL to hold the semantic defines. virtual HRESULT STDMETHODCALLTYPE SetSemanticDefineMetaDataName(LPCSTR name) = 0; }; struct __declspec(uuid("454b764f-3549-475b-958c-a7a6fcd05fbc")) IDxcSystemAccess : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumFiles(LPCWSTR fileName, IEnumSTATSTG** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE OpenStorage( _In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, IUnknown** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE SetStorageTime(_In_ IUnknown* storage, _In_opt_ const FILETIME *lpCreationTime, _In_opt_ const FILETIME *lpLastAccessTime, _In_opt_ const FILETIME *lpLastWriteTime) = 0; virtual HRESULT STDMETHODCALLTYPE GetFileInformationForStorage(_In_ IUnknown* storage, _Out_ LPBY_HANDLE_FILE_INFORMATION lpFileInformation) = 0; virtual HRESULT STDMETHODCALLTYPE GetFileTypeForStorage(_In_ IUnknown* storage, _Out_ DWORD* fileType) = 0; virtual HRESULT STDMETHODCALLTYPE CreateHardLinkInStorage(_In_ LPCWSTR lpFileName, _In_ LPCWSTR lpExistingFileName) = 0; virtual HRESULT STDMETHODCALLTYPE MoveStorage(_In_ LPCWSTR lpExistingFileName, _In_opt_ LPCWSTR lpNewFileName, _In_ DWORD dwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE GetFileAttributesForStorage(_In_ LPCWSTR lpFileName, _Out_ DWORD* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE DeleteStorage(_In_ LPCWSTR lpFileName) = 0; virtual HRESULT STDMETHODCALLTYPE RemoveDirectoryStorage(LPCWSTR lpFileName) = 0; virtual HRESULT STDMETHODCALLTYPE CreateDirectoryStorage(_In_ LPCWSTR lpPathName) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentDirectoryForStorage(DWORD nBufferLength, _Out_writes_(nBufferLength) LPWSTR lpBuffer, _Out_ DWORD* written) = 0; virtual HRESULT STDMETHODCALLTYPE GetMainModuleFileNameW(DWORD nBufferLength, _Out_writes_(nBufferLength) LPWSTR lpBuffer, _Out_ DWORD* written) = 0; virtual HRESULT STDMETHODCALLTYPE GetTempStoragePath(DWORD nBufferLength, _Out_writes_(nBufferLength) LPWSTR lpBuffer, _Out_ DWORD* written) = 0; virtual HRESULT STDMETHODCALLTYPE SupportsCreateSymbolicLink(_Out_ BOOL* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE CreateSymbolicLinkInStorage(_In_ LPCWSTR lpSymlinkFileName, _In_ LPCWSTR lpTargetFileName, DWORD dwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE CreateStorageMapping( _In_ IUnknown* hFile, _In_ DWORD flProtect, _In_ DWORD dwMaximumSizeHigh, _In_ DWORD dwMaximumSizeLow, _Outptr_ IUnknown** pResult) = 0; virtual HRESULT MapViewOfFile( _In_ IUnknown* hFileMappingObject, _In_ DWORD dwDesiredAccess, _In_ DWORD dwFileOffsetHigh, _In_ DWORD dwFileOffsetLow, _In_ SIZE_T dwNumberOfBytesToMap, _Outptr_ ID3D10Blob** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE OpenStdStorage(int standardFD, _Outptr_ IUnknown** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetStreamDisplay(_COM_Outptr_result_maybenull_ ITextFont** textFont, _Out_ unsigned* columnCount) = 0; }; struct __declspec(uuid("e991ca8d-2045-413c-a8b8-788b2c06e14d")) IDxcContainerEventsHandler : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE OnDxilContainerBuilt(_In_ IDxcBlob *pSource, _Out_ IDxcBlob **ppTarget) = 0; }; struct __declspec(uuid("0cfc5058-342b-4ff2-83f7-04c12aad3d01")) IDxcContainerEvent : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE RegisterDxilContainerEventHandler(IDxcContainerEventsHandler *pHandler, UINT64 *pCookie) = 0; virtual HRESULT STDMETHODCALLTYPE UnRegisterDxilContainerEventHandler(UINT64 cookie) = 0; }; #endif ================================================ FILE: src/Wrapper/dxc/dxcisense.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // dxcisense.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides declarations for the DirectX Compiler IntelliSense component. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXC_ISENSE__ #define __DXC_ISENSE__ typedef enum DxcGlobalOptions { DxcGlobalOpt_None = 0x0, DxcGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1, DxcGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2, DxcGlobalOpt_ThreadBackgroundPriorityForAll = DxcGlobalOpt_ThreadBackgroundPriorityForIndexing | DxcGlobalOpt_ThreadBackgroundPriorityForEditing } DxcGlobalOptions; typedef enum DxcTokenKind { DxcTokenKind_Punctuation = 0, // A token that contains some kind of punctuation. DxcTokenKind_Keyword = 1, // A language keyword. DxcTokenKind_Identifier = 2, // An identifier (that is not a keyword). DxcTokenKind_Literal = 3, // A numeric, string, or character literal. DxcTokenKind_Comment = 4, // A comment. DxcTokenKind_Unknown = 5, // An unknown token (possibly known to a future version). DxcTokenKind_BuiltInType = 6, // A built-in type like int, void or float3. } DxcTokenKind; typedef enum DxcTypeKind { DxcTypeKind_Invalid = 0, // Reprents an invalid type (e.g., where no type is available). DxcTypeKind_Unexposed = 1, // A type whose specific kind is not exposed via this interface. // Builtin types DxcTypeKind_Void = 2, DxcTypeKind_Bool = 3, DxcTypeKind_Char_U = 4, DxcTypeKind_UChar = 5, DxcTypeKind_Char16 = 6, DxcTypeKind_Char32 = 7, DxcTypeKind_UShort = 8, DxcTypeKind_UInt = 9, DxcTypeKind_ULong = 10, DxcTypeKind_ULongLong = 11, DxcTypeKind_UInt128 = 12, DxcTypeKind_Char_S = 13, DxcTypeKind_SChar = 14, DxcTypeKind_WChar = 15, DxcTypeKind_Short = 16, DxcTypeKind_Int = 17, DxcTypeKind_Long = 18, DxcTypeKind_LongLong = 19, DxcTypeKind_Int128 = 20, DxcTypeKind_Float = 21, DxcTypeKind_Double = 22, DxcTypeKind_LongDouble = 23, DxcTypeKind_NullPtr = 24, DxcTypeKind_Overload = 25, DxcTypeKind_Dependent = 26, DxcTypeKind_ObjCId = 27, DxcTypeKind_ObjCClass = 28, DxcTypeKind_ObjCSel = 29, DxcTypeKind_FirstBuiltin = DxcTypeKind_Void, DxcTypeKind_LastBuiltin = DxcTypeKind_ObjCSel, DxcTypeKind_Complex = 100, DxcTypeKind_Pointer = 101, DxcTypeKind_BlockPointer = 102, DxcTypeKind_LValueReference = 103, DxcTypeKind_RValueReference = 104, DxcTypeKind_Record = 105, DxcTypeKind_Enum = 106, DxcTypeKind_Typedef = 107, DxcTypeKind_ObjCInterface = 108, DxcTypeKind_ObjCObjectPointer = 109, DxcTypeKind_FunctionNoProto = 110, DxcTypeKind_FunctionProto = 111, DxcTypeKind_ConstantArray = 112, DxcTypeKind_Vector = 113, DxcTypeKind_IncompleteArray = 114, DxcTypeKind_VariableArray = 115, DxcTypeKind_DependentSizedArray = 116, DxcTypeKind_MemberPointer = 117 } DxcTypeKind; // Describes the severity of a particular diagnostic. typedef enum DxcDiagnosticSeverity { // A diagnostic that has been suppressed, e.g., by a command-line option. DxcDiagnostic_Ignored = 0, // This diagnostic is a note that should be attached to the previous (non-note) diagnostic. DxcDiagnostic_Note = 1, // This diagnostic indicates suspicious code that may not be wrong. DxcDiagnostic_Warning = 2, // This diagnostic indicates that the code is ill-formed. DxcDiagnostic_Error = 3, // This diagnostic indicates that the code is ill-formed such that future // parser rec unlikely to produce useful results. DxcDiagnostic_Fatal = 4 } DxcDiagnosticSeverity; // Options to control the display of diagnostics. typedef enum DxcDiagnosticDisplayOptions { // Display the source-location information where the diagnostic was located. DxcDiagnostic_DisplaySourceLocation = 0x01, // If displaying the source-location information of the diagnostic, // also include the column number. DxcDiagnostic_DisplayColumn = 0x02, // If displaying the source-location information of the diagnostic, // also include information about source ranges in a machine-parsable format. DxcDiagnostic_DisplaySourceRanges = 0x04, // Display the option name associated with this diagnostic, if any. DxcDiagnostic_DisplayOption = 0x08, // Display the category number associated with this diagnostic, if any. DxcDiagnostic_DisplayCategoryId = 0x10, // Display the category name associated with this diagnostic, if any. DxcDiagnostic_DisplayCategoryName = 0x20, // Display the severity of the diagnostic message. DxcDiagnostic_DisplaySeverity = 0x200 } DxcDiagnosticDisplayOptions; typedef enum DxcTranslationUnitFlags { // Used to indicate that no special translation-unit options are needed. DxcTranslationUnitFlags_None = 0x0, // Used to indicate that the parser should construct a "detailed" // preprocessing record, including all macro definitions and instantiations. DxcTranslationUnitFlags_DetailedPreprocessingRecord = 0x01, // Used to indicate that the translation unit is incomplete. DxcTranslationUnitFlags_Incomplete = 0x02, // Used to indicate that the translation unit should be built with an // implicit precompiled header for the preamble. DxcTranslationUnitFlags_PrecompiledPreamble = 0x04, // Used to indicate that the translation unit should cache some // code-completion results with each reparse of the source file. DxcTranslationUnitFlags_CacheCompletionResults = 0x08, // Used to indicate that the translation unit will be serialized with // SaveTranslationUnit. DxcTranslationUnitFlags_ForSerialization = 0x10, // DEPRECATED DxcTranslationUnitFlags_CXXChainedPCH = 0x20, // Used to indicate that function/method bodies should be skipped while parsing. DxcTranslationUnitFlags_SkipFunctionBodies = 0x40, // Used to indicate that brief documentation comments should be // included into the set of code completions returned from this translation // unit. DxcTranslationUnitFlags_IncludeBriefCommentsInCodeCompletion = 0x80, // Used to indicate that compilation should occur on the caller's thread. DxcTranslationUnitFlags_UseCallerThread = 0x800 } DxcTranslationUnitFlags; typedef enum DxcCursorFormatting { DxcCursorFormatting_Default = 0x0, // Default rules, language-insensitive formatting. DxcCursorFormatting_UseLanguageOptions = 0x1, // Language-sensitive formatting. DxcCursorFormatting_SuppressSpecifiers = 0x2, // Supresses type specifiers. DxcCursorFormatting_SuppressTagKeyword = 0x4, // Suppressed tag keyword (eg, 'class'). DxcCursorFormatting_IncludeNamespaceKeyword = 0x8, // Include namespace keyword. } DxcCursorFormatting; enum DxcCursorKind { /* Declarations */ DxcCursor_UnexposedDecl = 1, // A declaration whose specific kind is not exposed via this interface. DxcCursor_StructDecl = 2, // A C or C++ struct. DxcCursor_UnionDecl = 3, // A C or C++ union. DxcCursor_ClassDecl = 4, // A C++ class. DxcCursor_EnumDecl = 5, // An enumeration. DxcCursor_FieldDecl = 6, // A field (in C) or non-static data member (in C++) in a struct, union, or C++ class. DxcCursor_EnumConstantDecl = 7, // An enumerator constant. DxcCursor_FunctionDecl = 8, // A function. DxcCursor_VarDecl = 9, // A variable. DxcCursor_ParmDecl = 10, // A function or method parameter. DxcCursor_ObjCInterfaceDecl = 11, // An Objective-C interface. DxcCursor_ObjCCategoryDecl = 12, // An Objective-C interface for a category. DxcCursor_ObjCProtocolDecl = 13, // An Objective-C protocol declaration. DxcCursor_ObjCPropertyDecl = 14, // An Objective-C property declaration. DxcCursor_ObjCIvarDecl = 15, // An Objective-C instance variable. DxcCursor_ObjCInstanceMethodDecl = 16, // An Objective-C instance method. DxcCursor_ObjCClassMethodDecl = 17, // An Objective-C class method. DxcCursor_ObjCImplementationDecl = 18, // An Objective-C \@implementation. DxcCursor_ObjCCategoryImplDecl = 19, // An Objective-C \@implementation for a category. DxcCursor_TypedefDecl = 20, // A typedef DxcCursor_CXXMethod = 21, // A C++ class method. DxcCursor_Namespace = 22, // A C++ namespace. DxcCursor_LinkageSpec = 23, // A linkage specification, e.g. 'extern "C"'. DxcCursor_Constructor = 24, // A C++ constructor. DxcCursor_Destructor = 25, // A C++ destructor. DxcCursor_ConversionFunction = 26, // A C++ conversion function. DxcCursor_TemplateTypeParameter = 27, // A C++ template type parameter. DxcCursor_NonTypeTemplateParameter = 28, // A C++ non-type template parameter. DxcCursor_TemplateTemplateParameter = 29, // A C++ template template parameter. DxcCursor_FunctionTemplate = 30, // A C++ function template. DxcCursor_ClassTemplate = 31, // A C++ class template. DxcCursor_ClassTemplatePartialSpecialization = 32, // A C++ class template partial specialization. DxcCursor_NamespaceAlias = 33, // A C++ namespace alias declaration. DxcCursor_UsingDirective = 34, // A C++ using directive. DxcCursor_UsingDeclaration = 35, // A C++ using declaration. DxcCursor_TypeAliasDecl = 36, // A C++ alias declaration DxcCursor_ObjCSynthesizeDecl = 37, // An Objective-C \@synthesize definition. DxcCursor_ObjCDynamicDecl = 38, // An Objective-C \@dynamic definition. DxcCursor_CXXAccessSpecifier = 39, // An access specifier. DxcCursor_FirstDecl = DxcCursor_UnexposedDecl, DxcCursor_LastDecl = DxcCursor_CXXAccessSpecifier, /* References */ DxcCursor_FirstRef = 40, /* Decl references */ DxcCursor_ObjCSuperClassRef = 40, DxcCursor_ObjCProtocolRef = 41, DxcCursor_ObjCClassRef = 42, /** * \brief A reference to a type declaration. * * A type reference occurs anywhere where a type is named but not * declared. For example, given: * * \code * typedef unsigned size_type; * size_type size; * \endcode * * The typedef is a declaration of size_type (DxcCursor_TypedefDecl), * while the type of the variable "size" is referenced. The cursor * referenced by the type of size is the typedef for size_type. */ DxcCursor_TypeRef = 43, // A reference to a type declaration. DxcCursor_CXXBaseSpecifier = 44, DxcCursor_TemplateRef = 45, // A reference to a class template, function template, template template parameter, or class template partial specialization. DxcCursor_NamespaceRef = 46, // A reference to a namespace or namespace alias. DxcCursor_MemberRef = 47, // A reference to a member of a struct, union, or class that occurs in some non-expression context, e.g., a designated initializer. /** * \brief A reference to a labeled statement. * * This cursor kind is used to describe the jump to "start_over" in the * goto statement in the following example: * * \code * start_over: * ++counter; * * goto start_over; * \endcode * * A label reference cursor refers to a label statement. */ DxcCursor_LabelRef = 48, // A reference to a labeled statement. // A reference to a set of overloaded functions or function templates // that has not yet been resolved to a specific function or function template. // // An overloaded declaration reference cursor occurs in C++ templates where // a dependent name refers to a function. DxcCursor_OverloadedDeclRef = 49, DxcCursor_VariableRef = 50, // A reference to a variable that occurs in some non-expression context, e.g., a C++ lambda capture list. DxcCursor_LastRef = DxcCursor_VariableRef, /* Error conditions */ DxcCursor_FirstInvalid = 70, DxcCursor_InvalidFile = 70, DxcCursor_NoDeclFound = 71, DxcCursor_NotImplemented = 72, DxcCursor_InvalidCode = 73, DxcCursor_LastInvalid = DxcCursor_InvalidCode, /* Expressions */ DxcCursor_FirstExpr = 100, /** * \brief An expression whose specific kind is not exposed via this * interface. * * Unexposed expressions have the same operations as any other kind * of expression; one can extract their location information, * spelling, children, etc. However, the specific kind of the * expression is not reported. */ DxcCursor_UnexposedExpr = 100, // An expression whose specific kind is not exposed via this interface. DxcCursor_DeclRefExpr = 101, // An expression that refers to some value declaration, such as a function, varible, or enumerator. DxcCursor_MemberRefExpr = 102, // An expression that refers to a member of a struct, union, class, Objective-C class, etc. DxcCursor_CallExpr = 103, // An expression that calls a function. DxcCursor_ObjCMessageExpr = 104, // An expression that sends a message to an Objective-C object or class. DxcCursor_BlockExpr = 105, // An expression that represents a block literal. DxcCursor_IntegerLiteral = 106, // An integer literal. DxcCursor_FloatingLiteral = 107, // A floating point number literal. DxcCursor_ImaginaryLiteral = 108, // An imaginary number literal. DxcCursor_StringLiteral = 109, // A string literal. DxcCursor_CharacterLiteral = 110, // A character literal. DxcCursor_ParenExpr = 111, // A parenthesized expression, e.g. "(1)". This AST node is only formed if full location information is requested. DxcCursor_UnaryOperator = 112, // This represents the unary-expression's (except sizeof and alignof). DxcCursor_ArraySubscriptExpr = 113, // [C99 6.5.2.1] Array Subscripting. DxcCursor_BinaryOperator = 114, // A builtin binary operation expression such as "x + y" or "x <= y". DxcCursor_CompoundAssignOperator = 115, // Compound assignment such as "+=". DxcCursor_ConditionalOperator = 116, // The ?: ternary operator. DxcCursor_CStyleCastExpr = 117, // An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr, eg: (int)f. DxcCursor_CompoundLiteralExpr = 118, // [C99 6.5.2.5] DxcCursor_InitListExpr = 119, // Describes an C or C++ initializer list. DxcCursor_AddrLabelExpr = 120, // The GNU address of label extension, representing &&label. DxcCursor_StmtExpr = 121, // This is the GNU Statement Expression extension: ({int X=4; X;}) DxcCursor_GenericSelectionExpr = 122, // Represents a C11 generic selection. /** \brief Implements the GNU __null extension, which is a name for a null * pointer constant that has integral type (e.g., int or long) and is the same * size and alignment as a pointer. * * The __null extension is typically only used by system headers, which define * NULL as __null in C++ rather than using 0 (which is an integer that may not * match the size of a pointer). */ DxcCursor_GNUNullExpr = 123, DxcCursor_CXXStaticCastExpr = 124, // C++'s static_cast<> expression. DxcCursor_CXXDynamicCastExpr = 125, // C++'s dynamic_cast<> expression. DxcCursor_CXXReinterpretCastExpr = 126, // C++'s reinterpret_cast<> expression. DxcCursor_CXXConstCastExpr = 127, // C++'s const_cast<> expression. /** \brief Represents an explicit C++ type conversion that uses "functional" * notion (C++ [expr.type.conv]). * * Example: * \code * x = int(0.5); * \endcode */ DxcCursor_CXXFunctionalCastExpr = 128, DxcCursor_CXXTypeidExpr = 129, // A C++ typeid expression (C++ [expr.typeid]). DxcCursor_CXXBoolLiteralExpr = 130, // [C++ 2.13.5] C++ Boolean Literal. DxcCursor_CXXNullPtrLiteralExpr = 131, // [C++0x 2.14.7] C++ Pointer Literal. DxcCursor_CXXThisExpr = 132, // Represents the "this" expression in C++ DxcCursor_CXXThrowExpr = 133, // [C++ 15] C++ Throw Expression, both 'throw' and 'throw' assignment-expression. DxcCursor_CXXNewExpr = 134, // A new expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)". DxcCursor_CXXDeleteExpr = 135, // A delete expression for memory deallocation and destructor calls, e.g. "delete[] pArray". DxcCursor_UnaryExpr = 136, // A unary expression. DxcCursor_ObjCStringLiteral = 137, // An Objective-C string literal i.e. @"foo". DxcCursor_ObjCEncodeExpr = 138, // An Objective-C \@encode expression. DxcCursor_ObjCSelectorExpr = 139, // An Objective-C \@selector expression. DxcCursor_ObjCProtocolExpr = 140, // An Objective-C \@protocol expression. /** \brief An Objective-C "bridged" cast expression, which casts between * Objective-C pointers and C pointers, transferring ownership in the process. * * \code * NSString *str = (__bridge_transfer NSString *)CFCreateString(); * \endcode */ DxcCursor_ObjCBridgedCastExpr = 141, /** \brief Represents a C++0x pack expansion that produces a sequence of * expressions. * * A pack expansion expression contains a pattern (which itself is an * expression) followed by an ellipsis. For example: * * \code * template * void forward(F f, Types &&...args) { * f(static_cast(args)...); * } * \endcode */ DxcCursor_PackExpansionExpr = 142, /** \brief Represents an expression that computes the length of a parameter * pack. * * \code * template * struct count { * static const unsigned value = sizeof...(Types); * }; * \endcode */ DxcCursor_SizeOfPackExpr = 143, /* \brief Represents a C++ lambda expression that produces a local function * object. * * \code * void abssort(float *x, unsigned N) { * std::sort(x, x + N, * [](float a, float b) { * return std::abs(a) < std::abs(b); * }); * } * \endcode */ DxcCursor_LambdaExpr = 144, DxcCursor_ObjCBoolLiteralExpr = 145, // Objective-c Boolean Literal. DxcCursor_ObjCSelfExpr = 146, // Represents the "self" expression in a ObjC method. DxcCursor_LastExpr = DxcCursor_ObjCSelfExpr, /* Statements */ DxcCursor_FirstStmt = 200, /** * \brief A statement whose specific kind is not exposed via this * interface. * * Unexposed statements have the same operations as any other kind of * statement; one can extract their location information, spelling, * children, etc. However, the specific kind of the statement is not * reported. */ DxcCursor_UnexposedStmt = 200, /** \brief A labelled statement in a function. * * This cursor kind is used to describe the "start_over:" label statement in * the following example: * * \code * start_over: * ++counter; * \endcode * */ DxcCursor_LabelStmt = 201, DxcCursor_CompoundStmt = 202, // A group of statements like { stmt stmt }. This cursor kind is used to describe compound statements, e.g. function bodies. DxcCursor_CaseStmt = 203, // A case statement. DxcCursor_DefaultStmt = 204, // A default statement. DxcCursor_IfStmt = 205, // An if statement DxcCursor_SwitchStmt = 206, // A switch statement. DxcCursor_WhileStmt = 207, // A while statement. DxcCursor_DoStmt = 208, // A do statement. DxcCursor_ForStmt = 209, // A for statement. DxcCursor_GotoStmt = 210, // A goto statement. DxcCursor_IndirectGotoStmt = 211, // An indirect goto statement. DxcCursor_ContinueStmt = 212, // A continue statement. DxcCursor_BreakStmt = 213, // A break statement. DxcCursor_ReturnStmt = 214, // A return statement. DxcCursor_GCCAsmStmt = 215, // A GCC inline assembly statement extension. DxcCursor_AsmStmt = DxcCursor_GCCAsmStmt, DxcCursor_ObjCAtTryStmt = 216, // Objective-C's overall \@try-\@catch-\@finally statement. DxcCursor_ObjCAtCatchStmt = 217, // Objective-C's \@catch statement. DxcCursor_ObjCAtFinallyStmt = 218, // Objective-C's \@finally statement. DxcCursor_ObjCAtThrowStmt = 219, // Objective-C's \@throw statement. DxcCursor_ObjCAtSynchronizedStmt = 220, // Objective-C's \@synchronized statement. DxcCursor_ObjCAutoreleasePoolStmt = 221, // Objective-C's autorelease pool statement. DxcCursor_ObjCForCollectionStmt = 222, // Objective-C's collection statement. DxcCursor_CXXCatchStmt = 223, // C++'s catch statement. DxcCursor_CXXTryStmt = 224, // C++'s try statement. DxcCursor_CXXForRangeStmt = 225, // C++'s for (* : *) statement. DxcCursor_SEHTryStmt = 226, // Windows Structured Exception Handling's try statement. DxcCursor_SEHExceptStmt = 227, // Windows Structured Exception Handling's except statement. DxcCursor_SEHFinallyStmt = 228, // Windows Structured Exception Handling's finally statement. DxcCursor_MSAsmStmt = 229, // A MS inline assembly statement extension. DxcCursor_NullStmt = 230, // The null satement ";": C99 6.8.3p3. DxcCursor_DeclStmt = 231, // Adaptor class for mixing declarations with statements and expressions. DxcCursor_OMPParallelDirective = 232, // OpenMP parallel directive. DxcCursor_OMPSimdDirective = 233, // OpenMP SIMD directive. DxcCursor_OMPForDirective = 234, // OpenMP for directive. DxcCursor_OMPSectionsDirective = 235, // OpenMP sections directive. DxcCursor_OMPSectionDirective = 236, // OpenMP section directive. DxcCursor_OMPSingleDirective = 237, // OpenMP single directive. DxcCursor_OMPParallelForDirective = 238, // OpenMP parallel for directive. DxcCursor_OMPParallelSectionsDirective = 239, // OpenMP parallel sections directive. DxcCursor_OMPTaskDirective = 240, // OpenMP task directive. DxcCursor_OMPMasterDirective = 241, // OpenMP master directive. DxcCursor_OMPCriticalDirective = 242, // OpenMP critical directive. DxcCursor_OMPTaskyieldDirective = 243, // OpenMP taskyield directive. DxcCursor_OMPBarrierDirective = 244, // OpenMP barrier directive. DxcCursor_OMPTaskwaitDirective = 245, // OpenMP taskwait directive. DxcCursor_OMPFlushDirective = 246, // OpenMP flush directive. DxcCursor_SEHLeaveStmt = 247, // Windows Structured Exception Handling's leave statement. DxcCursor_OMPOrderedDirective = 248, // OpenMP ordered directive. DxcCursor_OMPAtomicDirective = 249, // OpenMP atomic directive. DxcCursor_OMPForSimdDirective = 250, // OpenMP for SIMD directive. DxcCursor_OMPParallelForSimdDirective = 251, // OpenMP parallel for SIMD directive. DxcCursor_OMPTargetDirective = 252, // OpenMP target directive. DxcCursor_OMPTeamsDirective = 253, // OpenMP teams directive. DxcCursor_OMPTaskgroupDirective = 254, // OpenMP taskgroup directive. DxcCursor_OMPCancellationPointDirective = 255, // OpenMP cancellation point directive. DxcCursor_OMPCancelDirective = 256, // OpenMP cancel directive. DxcCursor_LastStmt = DxcCursor_OMPCancelDirective, DxcCursor_TranslationUnit = 300, // Cursor that represents the translation unit itself. /* Attributes */ DxcCursor_FirstAttr = 400, /** * \brief An attribute whose specific kind is not exposed via this * interface. */ DxcCursor_UnexposedAttr = 400, DxcCursor_IBActionAttr = 401, DxcCursor_IBOutletAttr = 402, DxcCursor_IBOutletCollectionAttr = 403, DxcCursor_CXXFinalAttr = 404, DxcCursor_CXXOverrideAttr = 405, DxcCursor_AnnotateAttr = 406, DxcCursor_AsmLabelAttr = 407, DxcCursor_PackedAttr = 408, DxcCursor_PureAttr = 409, DxcCursor_ConstAttr = 410, DxcCursor_NoDuplicateAttr = 411, DxcCursor_CUDAConstantAttr = 412, DxcCursor_CUDADeviceAttr = 413, DxcCursor_CUDAGlobalAttr = 414, DxcCursor_CUDAHostAttr = 415, DxcCursor_CUDASharedAttr = 416, DxcCursor_LastAttr = DxcCursor_CUDASharedAttr, /* Preprocessing */ DxcCursor_PreprocessingDirective = 500, DxcCursor_MacroDefinition = 501, DxcCursor_MacroExpansion = 502, DxcCursor_MacroInstantiation = DxcCursor_MacroExpansion, DxcCursor_InclusionDirective = 503, DxcCursor_FirstPreprocessing = DxcCursor_PreprocessingDirective, DxcCursor_LastPreprocessing = DxcCursor_InclusionDirective, /* Extra Declarations */ /** * \brief A module import declaration. */ DxcCursor_ModuleImportDecl = 600, DxcCursor_FirstExtraDecl = DxcCursor_ModuleImportDecl, DxcCursor_LastExtraDecl = DxcCursor_ModuleImportDecl }; enum DxcCursorKindFlags { DxcCursorKind_None = 0, DxcCursorKind_Declaration = 0x1, DxcCursorKind_Reference = 0x2, DxcCursorKind_Expression = 0x4, DxcCursorKind_Statement = 0x8, DxcCursorKind_Attribute = 0x10, DxcCursorKind_Invalid = 0x20, DxcCursorKind_TranslationUnit = 0x40, DxcCursorKind_Preprocessing = 0x80, DxcCursorKind_Unexposed = 0x100, }; struct IDxcCursor; struct IDxcDiagnostic; struct IDxcFile; struct IDxcInclusion; struct IDxcIntelliSense; struct IDxcIndex; struct IDxcSourceLocation; struct IDxcSourceRange; struct IDxcToken; struct IDxcTranslationUnit; struct IDxcType; struct IDxcUnsavedFile; struct __declspec(uuid("1467b985-288d-4d2a-80c1-ef89c42c40bc")) IDxcCursor : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetExtent(_Outptr_result_nullonfailure_ IDxcSourceRange** pRange) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocation(_Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetKind(_Out_ DxcCursorKind* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetKindFlags(_Out_ DxcCursorKindFlags* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetSemanticParent(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetLexicalParent(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetCursorType(_Outptr_result_nullonfailure_ IDxcType** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumArguments(_Out_ int* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetArgumentAt(int index, _Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetReferencedCursor(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0; /// For a cursor that is either a reference to or a declaration of some entity, retrieve a cursor that describes the definition of that entity. /// Some entities can be declared multiple times within a translation unit, but only one of those declarations can also be a definition. /// A cursor to the definition of this entity; nullptr if there is no definition in this translation unit. virtual HRESULT STDMETHODCALLTYPE GetDefinitionCursor(_Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE FindReferencesInFile( _In_ IDxcFile* file, unsigned skip, unsigned top, _Out_ unsigned* pResultLength, _Outptr_result_buffer_maybenull_(*pResultLength) IDxcCursor*** pResult) = 0; /// Gets the name for the entity references by the cursor, e.g. foo for an 'int foo' variable. virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Outptr_result_maybenull_ LPSTR* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcCursor* other, _Out_ BOOL* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE IsNull(_Out_ BOOL* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE IsDefinition(_Out_ BOOL* pResult) = 0; /// Gets the display name for the cursor, including e.g. parameter types for a function. virtual HRESULT STDMETHODCALLTYPE GetDisplayName(_Out_ BSTR* pResult) = 0; /// Gets the qualified name for the symbol the cursor refers to. virtual HRESULT STDMETHODCALLTYPE GetQualifiedName(BOOL includeTemplateArgs, _Outptr_result_maybenull_ BSTR* pResult) = 0; /// Gets a name for the cursor, applying the specified formatting flags. virtual HRESULT STDMETHODCALLTYPE GetFormattedName(DxcCursorFormatting formatting , _Outptr_result_maybenull_ BSTR* pResult) = 0; /// Gets children in pResult up to top elements. virtual HRESULT STDMETHODCALLTYPE GetChildren( unsigned skip, unsigned top, _Out_ unsigned* pResultLength, _Outptr_result_buffer_maybenull_(*pResultLength) IDxcCursor*** pResult) = 0; /// Gets the cursor following a location within a compound cursor. virtual HRESULT STDMETHODCALLTYPE GetSnappedChild(_In_ IDxcSourceLocation* location, _Outptr_result_maybenull_ IDxcCursor** pResult) = 0; }; struct __declspec(uuid("4f76b234-3659-4d33-99b0-3b0db994b564")) IDxcDiagnostic : public IUnknown { virtual HRESULT STDMETHODCALLTYPE FormatDiagnostic( DxcDiagnosticDisplayOptions options, _Outptr_result_maybenull_ LPSTR* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetSeverity(_Out_ DxcDiagnosticSeverity* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocation(_Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Outptr_result_maybenull_ LPSTR* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetCategoryText(_Outptr_result_maybenull_ LPSTR* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumRanges(_Out_ unsigned* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetRangeAt(unsigned index, _Outptr_result_nullonfailure_ IDxcSourceRange** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumFixIts(_Out_ unsigned* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetFixItAt(unsigned index, _Outptr_result_nullonfailure_ IDxcSourceRange** pReplacementRange, _Outptr_result_maybenull_ LPSTR* pText) = 0; }; struct __declspec(uuid("bb2fca9e-1478-47ba-b08c-2c502ada4895")) IDxcFile : public IUnknown { /// Gets the file name for this file. virtual HRESULT STDMETHODCALLTYPE GetName(_Outptr_result_maybenull_ LPSTR* pResult) = 0; /// Checks whether this file is equal to the other specified file. virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcFile* other, _Out_ BOOL* pResult) = 0; }; struct __declspec(uuid("0c364d65-df44-4412-888e-4e552fc5e3d6")) IDxcInclusion : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetIncludedFile(_Outptr_result_nullonfailure_ IDxcFile** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackLength(_Out_ unsigned *pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackItem(unsigned index, _Outptr_result_nullonfailure_ IDxcSourceLocation **pResult) = 0; }; struct __declspec(uuid("b1f99513-46d6-4112-8169-dd0d6053f17d")) IDxcIntelliSense : public IUnknown { virtual HRESULT STDMETHODCALLTYPE CreateIndex(_Outptr_result_nullonfailure_ IDxcIndex** index) = 0; virtual HRESULT STDMETHODCALLTYPE GetNullLocation(_Outptr_result_nullonfailure_ IDxcSourceLocation** location) = 0; virtual HRESULT STDMETHODCALLTYPE GetNullRange(_Outptr_result_nullonfailure_ IDxcSourceRange** location) = 0; virtual HRESULT STDMETHODCALLTYPE GetRange( _In_ IDxcSourceLocation* start, _In_ IDxcSourceLocation* end, _Outptr_result_nullonfailure_ IDxcSourceRange** location) = 0; virtual HRESULT STDMETHODCALLTYPE GetDefaultDiagnosticDisplayOptions( _Out_ DxcDiagnosticDisplayOptions* pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetDefaultEditingTUOptions(_Out_ DxcTranslationUnitFlags* pValue) = 0; virtual HRESULT STDMETHODCALLTYPE CreateUnsavedFile(_In_ LPCSTR fileName, _In_ LPCSTR contents, unsigned contentLength, _Outptr_result_nullonfailure_ IDxcUnsavedFile** pResult) = 0; }; struct __declspec(uuid("937824a0-7f5a-4815-9ba7-7fc0424f4173")) IDxcIndex : public IUnknown { virtual HRESULT STDMETHODCALLTYPE SetGlobalOptions(DxcGlobalOptions options) = 0; virtual HRESULT STDMETHODCALLTYPE GetGlobalOptions(_Out_ DxcGlobalOptions* options) = 0; virtual HRESULT STDMETHODCALLTYPE ParseTranslationUnit( _In_z_ const char *source_filename, _In_count_(num_command_line_args) const char * const *command_line_args, int num_command_line_args, _In_count_(num_unsaved_files) IDxcUnsavedFile** unsaved_files, unsigned num_unsaved_files, DxcTranslationUnitFlags options, _Out_ IDxcTranslationUnit** pTranslationUnit) = 0; }; struct __declspec(uuid("8e7ddf1c-d7d3-4d69-b286-85fccba1e0cf")) IDxcSourceLocation : public IUnknown { virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcSourceLocation* other, _Out_ BOOL* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetSpellingLocation( _Outptr_opt_ IDxcFile** pFile, _Out_opt_ unsigned* pLine, _Out_opt_ unsigned* pCol, _Out_opt_ unsigned* pOffset) = 0; virtual HRESULT STDMETHODCALLTYPE IsNull(_Out_ BOOL* pResult) = 0; }; struct __declspec(uuid("f1359b36-a53f-4e81-b514-b6b84122a13f")) IDxcSourceRange : public IUnknown { virtual HRESULT STDMETHODCALLTYPE IsNull(_Out_ BOOL* pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetStart(_Out_ IDxcSourceLocation** pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetEnd(_Out_ IDxcSourceLocation** pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetOffsets(_Out_ unsigned* startOffset, _Out_ unsigned* endOffset) = 0; }; struct __declspec(uuid("7f90b9ff-a275-4932-97d8-3cfd234482a2")) IDxcToken : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetKind(_Out_ DxcTokenKind* pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocation(_Out_ IDxcSourceLocation** pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetExtent(_Out_ IDxcSourceRange** pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Out_ LPSTR* pValue) = 0; }; struct __declspec(uuid("9677dee0-c0e5-46a1-8b40-3db3168be63d")) IDxcTranslationUnit : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetCursor(_Out_ IDxcCursor** pCursor) = 0; virtual HRESULT STDMETHODCALLTYPE Tokenize( _In_ IDxcSourceRange* range, _Outptr_result_buffer_maybenull_(*pTokenCount) IDxcToken*** pTokens, _Out_ unsigned* pTokenCount) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocation( _In_ IDxcFile* file, unsigned line, unsigned column, _Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumDiagnostics(_Out_ unsigned* pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetDiagnostic(unsigned index, _Outptr_result_nullonfailure_ IDxcDiagnostic** pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetFile(_In_ const char* name, _Outptr_result_nullonfailure_ IDxcFile** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetFileName(_Outptr_result_maybenull_ LPSTR* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE Reparse( _In_count_(num_unsaved_files) IDxcUnsavedFile** unsaved_files, unsigned num_unsaved_files) = 0; virtual HRESULT STDMETHODCALLTYPE GetCursorForLocation(_In_ IDxcSourceLocation* location, _Outptr_result_nullonfailure_ IDxcCursor** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocationForOffset(_In_ IDxcFile* file, unsigned offset, _Outptr_result_nullonfailure_ IDxcSourceLocation** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetSkippedRanges(_In_ IDxcFile* file, _Out_ unsigned* pResultCount, _Outptr_result_buffer_(*pResultCount) IDxcSourceRange*** pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetDiagnosticDetails(unsigned index, DxcDiagnosticDisplayOptions options, _Out_ unsigned* errorCode, _Out_ unsigned* errorLine, _Out_ unsigned* errorColumn, _Out_ BSTR* errorFile, _Out_ unsigned* errorOffset, _Out_ unsigned* errorLength, _Out_ BSTR* errorMessage) = 0; virtual HRESULT STDMETHODCALLTYPE GetInclusionList(_Out_ unsigned* pResultCount, _Outptr_result_buffer_(*pResultCount) IDxcInclusion*** pResult) = 0; }; struct __declspec(uuid("2ec912fd-b144-4a15-ad0d-1c5439c81e46")) IDxcType : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetSpelling(_Outptr_result_z_ LPSTR* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE IsEqualTo(_In_ IDxcType* other, _Out_ BOOL* pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetKind(_Out_ DxcTypeKind* pResult) = 0; }; struct __declspec(uuid("8ec00f98-07d0-4e60-9d7c-5a50b5b0017f")) IDxcUnsavedFile : public IUnknown { virtual HRESULT STDMETHODCALLTYPE GetFileName(_Outptr_result_z_ LPSTR* pFileName) = 0; virtual HRESULT STDMETHODCALLTYPE GetContents(_Outptr_result_z_ LPSTR* pContents) = 0; virtual HRESULT STDMETHODCALLTYPE GetLength(_Out_ unsigned* pLength) = 0; }; // Fun fact: 'extern' is required because const is by default static in C++, so // CLSID_DxcIntelliSense is not visible externally (this is OK in C, since const is // not by default static in C) __declspec(selectany) extern const CLSID CLSID_DxcIntelliSense = { /* 3047833c-d1c0-4b8e-9d40-102878605985 */ 0x3047833c, 0xd1c0, 0x4b8e, {0x9d, 0x40, 0x10, 0x28, 0x78, 0x60, 0x59, 0x85} }; #endif ================================================ FILE: src/Wrapper/dxc/dxctools.h ================================================ /////////////////////////////////////////////////////////////////////////////// // // // dxctools.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // Provides declarations for the DirectX Compiler tooling components. // // // /////////////////////////////////////////////////////////////////////////////// #ifndef __DXC_TOOLS__ #define __DXC_TOOLS__ #include enum RewriterOptionMask { Default = 0, SkipFunctionBody = 1, SkipStatic = 2, GlobalExternByDefault = 4, KeepUserMacro = 8, }; struct __declspec(uuid("c012115b-8893-4eb9-9c5a-111456ea1c45")) IDxcRewriter : public IUnknown { virtual HRESULT STDMETHODCALLTYPE RemoveUnusedGlobals(_In_ IDxcBlobEncoding *pSource, _In_z_ LPCWSTR entryPoint, _In_count_(defineCount) DxcDefine *pDefines, _In_ UINT32 defineCount, _COM_Outptr_ IDxcOperationResult **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE RewriteUnchanged(_In_ IDxcBlobEncoding *pSource, _In_count_(defineCount) DxcDefine *pDefines, _In_ UINT32 defineCount, _COM_Outptr_ IDxcOperationResult **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE RewriteUnchangedWithInclude(_In_ IDxcBlobEncoding *pSource, // Optional file name for pSource. Used in errors and include handlers. _In_opt_ LPCWSTR pSourceName, _In_count_(defineCount) DxcDefine *pDefines, _In_ UINT32 defineCount, // user-provided interface to handle #include directives (optional) _In_opt_ IDxcIncludeHandler *pIncludeHandler, _In_ UINT32 rewriteOption, _COM_Outptr_ IDxcOperationResult **ppResult) = 0; }; __declspec(selectany) extern const CLSID CLSID_DxcRewriter = { /* b489b951-e07f-40b3-968d-93e124734da4 */ 0xb489b951, 0xe07f, 0x40b3, { 0x96, 0x8d, 0x93, 0xe1, 0x24, 0x73, 0x4d, 0xa4 } }; #endif ================================================ FILE: src/Wrapper/elf.h ================================================ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #ifndef _SYS_ELF_H #define _SYS_ELF_H #include /* Type for a 16-bit quantity. */ typedef uint16_t Elf32_Half; typedef uint16_t Elf64_Half; /* Types for signed and unsigned 32-bit quantities. */ typedef uint32_t Elf32_Word; typedef int32_t Elf32_Sword; typedef uint32_t Elf64_Word; typedef int32_t Elf64_Sword; /* Types for signed and unsigned 64-bit quantities. */ typedef uint64_t Elf32_Xword; typedef int64_t Elf32_Sxword; typedef uint64_t Elf64_Xword; typedef int64_t Elf64_Sxword; /* Type of addresses. */ typedef uint32_t Elf32_Addr; typedef uint64_t Elf64_Addr; /* Type of file offsets. */ typedef uint32_t Elf32_Off; typedef uint64_t Elf64_Off; #ifdef __cplusplus extern "C" { #endif #define ELF32_FSZ_ADDR 4 #define ELF32_FSZ_HALF 2 #define ELF32_FSZ_OFF 4 #define ELF32_FSZ_SWORD 4 #define ELF32_FSZ_WORD 4 #define ELF64_FSZ_ADDR 8 #define ELF64_FSZ_HALF 2 #define ELF64_FSZ_OFF 8 #define ELF64_FSZ_SWORD 4 #define ELF64_FSZ_WORD 4 #define ELF64_FSZ_SXWORD 8 #define ELF64_FSZ_XWORD 8 /* * "Enumerations" below use ...NUM as the number of * values in the list. It should be 1 greater than the * highest "real" value. */ /* * ELF header */ #define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; /* ident bytes */ Elf32_Half e_type; /* file type */ Elf32_Half e_machine; /* target machine */ Elf32_Word e_version; /* file version */ Elf32_Addr e_entry; /* start address */ Elf32_Off e_phoff; /* phdr file offset */ Elf32_Off e_shoff; /* shdr file offset */ Elf32_Word e_flags; /* file flags */ Elf32_Half e_ehsize; /* sizeof ehdr */ Elf32_Half e_phentsize; /* sizeof phdr */ Elf32_Half e_phnum; /* number phdrs */ Elf32_Half e_shentsize; /* sizeof shdr */ Elf32_Half e_shnum; /* number shdrs */ Elf32_Half e_shstrndx; /* shdr string index */ } Elf32_Ehdr; #define EI_MAG0 0 /* e_ident[] indexes */ #define EI_MAG1 1 #define EI_MAG2 2 #define EI_MAG3 3 #define EI_CLASS 4 /* File class */ #define EI_DATA 5 /* Data encoding */ #define EI_VERSION 6 /* File version */ #define EI_OSABI 7 /* Operating system/ABI identification */ #define EI_ABIVERSION 8 /* ABI version */ #define EI_PAD 9 /* Start of padding bytes */ #define ELFMAG0 0x7f /* EI_MAG */ #define ELFMAG1 'E' #define ELFMAG2 'L' #define ELFMAG3 'F' #define ELFMAG "\177ELF" #define SELFMAG 4 #define ELFCLASSNONE 0 /* EI_CLASS */ #define ELFCLASS32 1 #define ELFCLASS64 2 #define ELFCLASSNUM 3 #define ELFDATANONE 0 /* EI_DATA */ #define ELFDATA2LSB 1 #define ELFDATA2MSB 2 #define ELFDATANUM 3 #define ET_NONE 0 /* e_type */ #define ET_REL 1 #define ET_EXEC 2 #define ET_DYN 3 #define ET_CORE 4 #define ET_NUM 5 #define ET_LOOS 0xfe00 /* OS specific range */ #define ET_LOSUNW 0xfeff #define ET_SUNWPSEUDO 0xfeff #define ET_HISUNW 0xfeff #define ET_HIOS 0xfeff #define ET_LOPROC 0xff00 /* processor specific range */ #define ET_HIPROC 0xffff #define ET_LOPROC 0xff00 /* processor specific range */ #define ET_HIPROC 0xffff #define EM_NONE 0 /* e_machine */ #define EM_M32 1 /* AT&T WE 32100 */ #define EM_SPARC 2 /* Sun SPARC */ #define EM_386 3 /* Intel 80386 */ #define EM_68K 4 /* Motorola 68000 */ #define EM_88K 5 /* Motorola 88000 */ #define EM_486 6 /* Intel 80486 */ #define EM_860 7 /* Intel i860 */ #define EM_MIPS 8 /* MIPS RS3000 Big-Endian */ #define EM_S370 9 /* IBM System/370 Processor */ #define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-Endian */ #define EM_RS6000 11 /* RS6000 */ #define EM_UNKNOWN12 12 #define EM_UNKNOWN13 13 #define EM_UNKNOWN14 14 #define EM_PA_RISC 15 /* PA-RISC */ #define EM_PARISC EM_PA_RISC /* Alias: GNU compatibility */ #define EM_nCUBE 16 /* nCUBE */ #define EM_VPP500 17 /* Fujitsu VPP500 */ #define EM_SPARC32PLUS 18 /* Sun SPARC 32+ */ #define EM_960 19 /* Intel 80960 */ #define EM_PPC 20 /* PowerPC */ #define EM_PPC64 21 /* 64-bit PowerPC */ #define EM_S390 22 /* IBM System/390 Processor */ #define EM_UNKNOWN22 EM_S390 /* Alias: Older published name */ #define EM_UNKNOWN23 23 #define EM_UNKNOWN24 24 #define EM_UNKNOWN25 25 #define EM_UNKNOWN26 26 #define EM_UNKNOWN27 27 #define EM_UNKNOWN28 28 #define EM_UNKNOWN29 29 #define EM_UNKNOWN30 30 #define EM_UNKNOWN31 31 #define EM_UNKNOWN32 32 #define EM_UNKNOWN33 33 #define EM_UNKNOWN34 34 #define EM_UNKNOWN35 35 #define EM_V800 36 /* NEX V800 */ #define EM_FR20 37 /* Fujitsu FR20 */ #define EM_RH32 38 /* TRW RH-32 */ #define EM_RCE 39 /* Motorola RCE */ #define EM_ARM 40 /* Advanced RISC Marchines ARM */ #define EM_ALPHA 41 /* Digital Alpha */ #define EM_SH 42 /* Hitachi SH */ #define EM_SPARCV9 43 /* Sun SPARC V9 (64-bit) */ #define EM_TRICORE 44 /* Siemens Tricore embedded processor */ #define EM_ARC 45 /* Argonaut RISC Core, */ /* Argonaut Technologies Inc. */ #define EM_H8_300 46 /* Hitachi H8/300 */ #define EM_H8_300H 47 /* Hitachi H8/300H */ #define EM_H8S 48 /* Hitachi H8S */ #define EM_H8_500 49 /* Hitachi H8/500 */ #define EM_IA_64 50 /* Intel IA64 */ #define EM_MIPS_X 51 /* Stanford MIPS-X */ #define EM_COLDFIRE 52 /* Motorola ColdFire */ #define EM_68HC12 53 /* Motorola M68HC12 */ #define EM_MMA 54 /* Fujitsu MMA Mulimedia Accelerator */ #define EM_PCP 55 /* Siemens PCP */ #define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ #define EM_NDR1 57 /* Denso NDR1 microprocessor */ #define EM_STARCORE 58 /* Motorola Star*Core processor */ #define EM_ME16 59 /* Toyota ME16 processor */ #define EM_ST100 60 /* STMicroelectronics ST100 processor */ #define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ */ /* embedded processor family */ #define EM_AMD64 62 /* AMDs x86-64 architecture */ #define EM_X86_64 EM_AMD64 /* (compatibility) */ #define EM_PDSP 63 /* Sony DSP Processor */ #define EM_UNKNOWN64 64 #define EM_UNKNOWN65 65 #define EM_FX66 66 /* Siemens FX66 microcontroller */ #define EM_ST9PLUS 67 /* STMicroelectronics ST9+8/16 bit */ /* microcontroller */ #define EM_ST7 68 /* STMicroelectronics ST7 8-bit */ /* microcontroller */ #define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ #define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ #define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ #define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ #define EM_SVX 73 /* Silicon Graphics SVx */ #define EM_ST19 74 /* STMicroelectronics ST19 8-bit */ /* microcontroller */ #define EM_VAX 75 /* Digital VAX */ #define EM_CRIS 76 /* Axis Communications 32-bit */ /* embedded processor */ #define EM_JAVELIN 77 /* Infineon Technologies 32-bit */ /* embedded processor */ #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ #define EM_MMIX 80 /* Donald Knuth's educational */ /* 64-bit processor */ #define EM_HUANY 81 /* Harvard University */ /* machine-independent */ /* object files */ #define EM_PRISM 82 /* SiTera Prism */ #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ #define EM_FR30 84 /* Fujitsu FR30 */ #define EM_D10V 85 /* Mitsubishi D10V */ #define EM_D30V 86 /* Mitsubishi D30V */ #define EM_V850 87 /* NEC v850 */ #define EM_M32R 88 /* Mitsubishi M32R */ #define EM_MN10300 89 /* Matsushita MN10300 */ #define EM_MN10200 90 /* Matsushita MN10200 */ #define EM_PJ 91 /* picoJava */ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ #define EM_XTENSA 94 /* Tensilica Xtensa architecture */ #define EM_NUM 95 #define EV_NONE 0 /* e_version, EI_VERSION */ #define EV_CURRENT 1 #define EV_NUM 2 #define ELFOSABI_NONE 0 /* No extensions or unspecified */ #define ELFOSABI_SYSV ELFOSABI_NONE #define ELFOSABI_HPUX 1 /* Hewlett-Packard HP-UX */ #define ELFOSABI_NETBSD 2 /* NetBSD */ #define ELFOSABI_LINUX 3 /* Linux */ #define ELFOSABI_UNKNOWN4 4 #define ELFOSABI_UNKNOWN5 5 #define ELFOSABI_SOLARIS 6 /* Sun Solaris */ #define ELFOSABI_AIX 7 /* AIX */ #define ELFOSABI_IRIX 8 /* IRIX */ #define ELFOSABI_FREEBSD 9 /* FreeBSD */ #define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX */ #define ELFOSABI_MODESTO 11 /* Novell Modesto */ #define ELFOSABI_OPENBSD 12 /* Open BSD */ #define ELFOSABI_OPENVMS 13 /* Open VMS */ #define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ #define ELFOSABI_AROS 15 /* Amiga Research OS */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* standalone (embedded) application */ /* * Program header */ typedef struct { Elf32_Word p_type; /* entry type */ Elf32_Off p_offset; /* file offset */ Elf32_Addr p_vaddr; /* virtual address */ Elf32_Addr p_paddr; /* physical address */ Elf32_Word p_filesz; /* file size */ Elf32_Word p_memsz; /* memory size */ Elf32_Word p_flags; /* entry flags */ Elf32_Word p_align; /* memory/file alignment */ } Elf32_Phdr; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Word p_type; /* entry type */ Elf64_Word p_flags; /* entry flags */ Elf64_Off p_offset; /* file offset */ Elf64_Addr p_vaddr; /* virtual address */ Elf64_Addr p_paddr; /* physical address */ Elf64_Xword p_filesz; /* file size */ Elf64_Xword p_memsz; /* memory size */ Elf64_Xword p_align; /* memory/file alignment */ } Elf64_Phdr; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #define PT_NULL 0 /* p_type */ #define PT_LOAD 1 #define PT_DYNAMIC 2 #define PT_INTERP 3 #define PT_NOTE 4 #define PT_SHLIB 5 #define PT_PHDR 6 #define PT_TLS 7 #define PT_NUM 8 #define PT_LOOS 0x60000000 /* OS specific range */ /* * Note: The amd64 psABI defines that the UNWIND program header * should reside in the OS specific range of the program * headers. */ #define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ #define PT_GNU_EH_FRAME PT_SUNW_UNWIND #define PT_LOSUNW 0x6ffffffa #define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ #define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ #define PT_SUNWDTRACE 0x6ffffffc /* private */ #define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ #define PT_HISUNW 0x6fffffff #define PT_HIOS 0x6fffffff #define PT_LOPROC 0x70000000 /* processor specific range */ #define PT_HIPROC 0x7fffffff #define PF_R 0x4 /* p_flags */ #define PF_W 0x2 #define PF_X 0x1 #define PF_MASKOS 0x0ff00000 /* OS specific values */ #define PF_MASKPROC 0xf0000000 /* processor specific values */ #define PF_SUNW_FAILURE 0x00100000 /* mapping absent due to failure */ #define PN_XNUM 0xffff /* extended program header index */ /* * Section header */ typedef struct { Elf32_Word sh_name; /* section name */ Elf32_Word sh_type; /* SHT_... */ Elf32_Word sh_flags; /* SHF_... */ Elf32_Addr sh_addr; /* virtual address */ Elf32_Off sh_offset; /* file offset */ Elf32_Word sh_size; /* section size */ Elf32_Word sh_link; /* misc info */ Elf32_Word sh_info; /* misc info */ Elf32_Word sh_addralign; /* memory alignment */ Elf32_Word sh_entsize; /* entry size if table */ } Elf32_Shdr; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Word sh_name; /* section name */ Elf64_Word sh_type; /* SHT_... */ Elf64_Xword sh_flags; /* SHF_... */ Elf64_Addr sh_addr; /* virtual address */ Elf64_Off sh_offset; /* file offset */ Elf64_Xword sh_size; /* section size */ Elf64_Word sh_link; /* misc info */ Elf64_Word sh_info; /* misc info */ Elf64_Xword sh_addralign; /* memory alignment */ Elf64_Xword sh_entsize; /* entry size if table */ } Elf64_Shdr; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #define SHT_NULL 0 /* sh_type */ #define SHT_PROGBITS 1 #define SHT_SYMTAB 2 #define SHT_STRTAB 3 #define SHT_RELA 4 #define SHT_HASH 5 #define SHT_DYNAMIC 6 #define SHT_NOTE 7 #define SHT_NOBITS 8 #define SHT_REL 9 #define SHT_SHLIB 10 #define SHT_DYNSYM 11 #define SHT_UNKNOWN12 12 #define SHT_UNKNOWN13 13 #define SHT_INIT_ARRAY 14 #define SHT_FINI_ARRAY 15 #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 #define SHT_NUM 19 /* Solaris ABI specific values */ #define SHT_LOOS 0x60000000 /* OS specific range */ #define SHT_LOSUNW 0x6ffffff1 #define SHT_SUNW_symsort 0x6ffffff1 #define SHT_SUNW_tlssort 0x6ffffff2 #define SHT_SUNW_LDYNSYM 0x6ffffff3 #define SHT_SUNW_dof 0x6ffffff4 #define SHT_SUNW_cap 0x6ffffff5 #define SHT_SUNW_SIGNATURE 0x6ffffff6 #define SHT_SUNW_ANNOTATE 0x6ffffff7 #define SHT_SUNW_DEBUGSTR 0x6ffffff8 #define SHT_SUNW_DEBUG 0x6ffffff9 #define SHT_SUNW_move 0x6ffffffa #define SHT_SUNW_COMDAT 0x6ffffffb #define SHT_SUNW_syminfo 0x6ffffffc #define SHT_SUNW_verdef 0x6ffffffd #define SHT_SUNW_verneed 0x6ffffffe #define SHT_SUNW_versym 0x6fffffff #define SHT_HISUNW 0x6fffffff #define SHT_HIOS 0x6fffffff /* GNU/Linux ABI specific values */ #define SHT_GNU_verdef 0x6ffffffd #define SHT_GNU_verneed 0x6ffffffe #define SHT_GNU_versym 0x6fffffff #define SHT_LOPROC 0x70000000 /* processor specific range */ #define SHT_HIPROC 0x7fffffff #define SHT_LOUSER 0x80000000 #define SHT_HIUSER 0xffffffff #define SHF_WRITE 0x01 /* sh_flags */ #define SHF_ALLOC 0x02 #define SHF_EXECINSTR 0x04 #define SHF_MERGE 0x10 #define SHF_STRINGS 0x20 #define SHF_INFO_LINK 0x40 #define SHF_LINK_ORDER 0x80 #define SHF_OS_NONCONFORMING 0x100 #define SHF_GROUP 0x200 #define SHF_TLS 0x400 #define SHF_MASKOS 0x0ff00000 /* OS specific values */ #define SHF_MASKPROC 0xf0000000 /* processor specific values */ #define SHN_UNDEF 0 /* special section numbers */ #define SHN_LORESERVE 0xff00 #define SHN_LOPROC 0xff00 /* processor specific range */ #define SHN_HIPROC 0xff1f #define SHN_LOOS 0xff20 /* OS specific range */ #define SHN_LOSUNW 0xff3f #define SHN_SUNW_IGNORE 0xff3f #define SHN_HISUNW 0xff3f #define SHN_HIOS 0xff3f #define SHN_ABS 0xfff1 #define SHN_COMMON 0xfff2 #if defined(__APPLE__) #define SHN_MACHO_64 0xfffd /* Mach-o_64 direct string access */ #define SHN_MACHO 0xfffe /* Mach-o direct string access */ #endif /* __APPLE__ */ #define SHN_XINDEX 0xffff /* extended sect index */ #define SHN_HIRESERVE 0xffff /* * Symbol table */ typedef struct { Elf32_Word st_name; Elf32_Addr st_value; Elf32_Word st_size; unsigned char st_info; /* bind, type: ELF_32_ST_... */ unsigned char st_other; Elf32_Half st_shndx; /* SHN_... */ } Elf32_Sym; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { #if !defined(__APPLE__) Elf64_Word st_name; #else Elf64_Sxword st_name; #endif /* __APPLE__ */ unsigned char st_info; /* bind, type: ELF_64_ST_... */ unsigned char st_other; Elf64_Half st_shndx; /* SHN_... */ Elf64_Addr st_value; Elf64_Xword st_size; } Elf64_Sym; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #define STN_UNDEF 0 /* * The macros compose and decompose values for S.st_info * * bind = ELF32_ST_BIND(S.st_info) * type = ELF32_ST_TYPE(S.st_info) * S.st_info = ELF32_ST_INFO(bind, type) */ #define ELF32_ST_BIND(info) ((info) >> 4) #define ELF32_ST_TYPE(info) ((info) & 0xf) #define ELF32_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf)) #define ELF64_ST_BIND(info) ((info) >> 4) #define ELF64_ST_TYPE(info) ((info) & 0xf) #define ELF64_ST_INFO(bind, type) (((bind)<<4)+((type)&0xf)) #define STB_LOCAL 0 /* BIND */ #define STB_GLOBAL 1 #define STB_WEAK 2 #define STB_NUM 3 #define STB_LOPROC 13 /* processor specific range */ #define STB_HIPROC 15 #define STT_NOTYPE 0 /* TYPE */ #define STT_OBJECT 1 #define STT_FUNC 2 #define STT_SECTION 3 #define STT_FILE 4 #define STT_COMMON 5 #define STT_TLS 6 #define STT_NUM 7 #define STT_LOPROC 13 /* processor specific range */ #define STT_HIPROC 15 /* * The macros decompose values for S.st_other * * visibility = ELF32_ST_VISIBILITY(S.st_other) */ #define ELF32_ST_VISIBILITY(other) ((other)&0x7) #define ELF64_ST_VISIBILITY(other) ((other)&0x7) #define STV_DEFAULT 0 #define STV_INTERNAL 1 #define STV_HIDDEN 2 #define STV_PROTECTED 3 #define STV_EXPORTED 4 #define STV_SINGLETON 5 #define STV_ELIMINATE 6 #define STV_NUM 7 /* * Relocation */ typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; /* sym, type: ELF32_R_... */ } Elf32_Rel; typedef struct { Elf32_Addr r_offset; Elf32_Word r_info; /* sym, type: ELF32_R_... */ Elf32_Sword r_addend; } Elf32_Rela; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; /* sym, type: ELF64_R_... */ } Elf64_Rel; typedef struct { Elf64_Addr r_offset; Elf64_Xword r_info; /* sym, type: ELF64_R_... */ Elf64_Sxword r_addend; } Elf64_Rela; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ /* * The macros compose and decompose values for Rel.r_info, Rela.f_info * * sym = ELF32_R_SYM(R.r_info) * type = ELF32_R_TYPE(R.r_info) * R.r_info = ELF32_R_INFO(sym, type) */ #define ELF32_R_SYM(info) ((info)>>8) #define ELF32_R_TYPE(info) ((unsigned char)(info)) #define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type)) #define ELF64_R_SYM(info) ((info)>>32) #define ELF64_R_TYPE(info) ((Elf64_Word)(info)) #define ELF64_R_INFO(sym, type) (((Elf64_Xword)(sym)<<32)+(Elf64_Xword)(type)) /* * The r_info field is composed of two 32-bit components: the symbol * table index and the relocation type. The relocation type for SPARC V9 * is further decomposed into an 8-bit type identifier and a 24-bit type * dependent data field. For the existing Elf32 relocation types, * that data field is zero. */ #define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) #define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) #define ELF64_R_TYPE_INFO(data, type) \ (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) /* * Section Group Flags (SHT_GROUP) */ #define GRP_COMDAT 0x01 /* * Note entry header */ typedef struct { Elf32_Word n_namesz; /* length of note's name */ Elf32_Word n_descsz; /* length of note's "desc" */ Elf32_Word n_type; /* type of note */ } Elf32_Nhdr; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Word n_namesz; /* length of note's name */ Elf64_Word n_descsz; /* length of note's "desc" */ Elf64_Word n_type; /* type of note */ } Elf64_Nhdr; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ /* * Move entry */ #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf32_Lword m_value; /* symbol value */ Elf32_Word m_info; /* size + index */ Elf32_Word m_poffset; /* symbol offset */ Elf32_Half m_repeat; /* repeat count */ Elf32_Half m_stride; /* stride info */ } Elf32_Move; /* * The macros compose and decompose values for Move.r_info * * sym = ELF32_M_SYM(M.m_info) * size = ELF32_M_SIZE(M.m_info) * M.m_info = ELF32_M_INFO(sym, size) */ #define ELF32_M_SYM(info) ((info)>>8) #define ELF32_M_SIZE(info) ((unsigned char)(info)) #define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) typedef struct { Elf64_Lword m_value; /* symbol value */ Elf64_Xword m_info; /* size + index */ Elf64_Xword m_poffset; /* symbol offset */ Elf64_Half m_repeat; /* repeat count */ Elf64_Half m_stride; /* stride info */ } Elf64_Move; #define ELF64_M_SYM(info) ((info)>>8) #define ELF64_M_SIZE(info) ((unsigned char)(info)) #define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ /* * Hardware/Software capabilities entry */ #ifndef _ASM typedef struct { Elf32_Word c_tag; /* how to interpret value */ union { Elf32_Word c_val; Elf32_Addr c_ptr; } c_un; } Elf32_Cap; #if defined(_LP64) || defined(_LONGLONG_TYPE) typedef struct { Elf64_Xword c_tag; /* how to interpret value */ union { Elf64_Xword c_val; Elf64_Addr c_ptr; } c_un; } Elf64_Cap; #endif /* defined(_LP64) || defined(_LONGLONG_TYPE) */ #endif #define CA_SUNW_NULL 0 #define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ #define CA_SUNW_SF_1 2 /* first software capabilities entry */ /* * Define software capabilities (CA_SUNW_SF_1 values). Note, hardware * capabilities (CA_SUNW_HW_1 values) are taken directly from sys/auxv_$MACH.h. */ #define SF1_SUNW_FPKNWN 0x001 /* use/non-use of frame pointer is */ #define SF1_SUNW_FPUSED 0x002 /* known, and frame pointer is */ /* in use */ #define SF1_SUNW_MASK 0x003 /* known software capabilities mask */ /* * Known values for note entry types (e_type == ET_CORE) */ #define NT_PRSTATUS 1 /* prstatus_t */ #define NT_PRFPREG 2 /* prfpregset_t */ #define NT_PRPSINFO 3 /* prpsinfo_t */ #define NT_PRXREG 4 /* prxregset_t */ #define NT_PLATFORM 5 /* string from sysinfo(SI_PLATFORM) */ #define NT_AUXV 6 /* auxv_t array */ #define NT_GWINDOWS 7 /* gwindows_t SPARC only */ #define NT_ASRS 8 /* asrset_t SPARC V9 only */ #define NT_LDT 9 /* ssd array IA32 only */ #define NT_PSTATUS 10 /* pstatus_t */ #define NT_PSINFO 13 /* psinfo_t */ #define NT_PRCRED 14 /* prcred_t */ #define NT_UTSNAME 15 /* struct utsname */ #define NT_LWPSTATUS 16 /* lwpstatus_t */ #define NT_LWPSINFO 17 /* lwpsinfo_t */ #define NT_PRPRIV 18 /* prpriv_t */ #define NT_PRPRIVINFO 19 /* priv_impl_info_t */ #define NT_CONTENT 20 /* core_content_t */ #define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */ #define NT_NUM 21 #ifdef _KERNEL /* * The following routine checks the processor-specific * fields of an ELF header. */ int elfheadcheck(unsigned char, Elf32_Half, Elf32_Word); #endif #ifdef __cplusplus } #endif #if defined(ELF_TARGET_ALL) || defined(ELF_TARGET_SPARC) #include #endif #if defined(ELF_TARGET_ALL) || defined(ELF_TARGET_386) #if !defined(__APPLE__) #include #else /* is Apple Mac OS X */ #include "elf_386.h" /* In lieu of Solaris */ #endif /* __APPLE__ */ #endif #if defined(ELF_TARGET_ALL) || defined(ELF_TARGET_AMD64) #include #endif #endif /* _SYS_ELF_H */ ================================================ FILE: test/ShadowMaps.txt ================================================ Texture2D tShadowMap; SamplerComparisonState sShadowSampler; Texture2D tTexture; sampler sTexture; float2 vShadowMapSize; struct VSOut { float3 N : TEXCOORD0; float4 vPosSM : TEXCOORD1; float3 L : TEXCOORD2; float2 uv : TEXCOORD3; float4 vPos : SV_POSITION; }; float PCFGather7x7( float3 vPosSM, float2 Size, Texture2D t, SamplerComparisonState s ) { float z = saturate(vPosSM.z); float2 uv = (vPosSM.xy*Size); float2 vWeights = frac(uv.xy); // grab bilinear weights // snap UV to texel center // If we don't do this, we can end up rouning differently // than the sampler does, and our weights will be wrong uv = (floor(uv)+0.5)/Size; float4 v0 = t.GatherCmp( s, uv, z, int2(-3, -3) ); float4 v1 = t.GatherCmp( s, uv, z, int2(-1, -3) ); float4 v2 = t.GatherCmp( s, uv, z, int2( 1, -3) ); float4 v3 = t.GatherCmp( s, uv, z, int2( 3, -3) ); float4 v4 = t.GatherCmp( s, uv, z, int2(-3, -1) ); float4 v5 = t.GatherCmp( s, uv, z, int2(-1, -1) ); float4 v6 = t.GatherCmp( s, uv, z, int2( 1, -1) ); float4 v7 = t.GatherCmp( s, uv, z, int2( 3, -1) ); float4 v8 = t.GatherCmp( s, uv, z, int2(-3, 1) ); float4 v9 = t.GatherCmp( s, uv, z, int2(-1, 1) ); float4 v10 = t.GatherCmp( s, uv, z, int2( 1, 1) ); float4 v11 = t.GatherCmp( s, uv, z, int2( 3, 1) ); float4 v12 = t.GatherCmp( s, uv, z, int2(-3, 3) ); float4 v13 = t.GatherCmp( s, uv, z, int2(-1, 3) ); float4 v14 = t.GatherCmp( s, uv, z, int2( 1, 3) ); float4 v15 = t.GatherCmp( s, uv, z, int2( 3, 3) ); // tap locations // . . . . . . . . // 0 1 2 3 // . . . . . . . . // // . . . . . . . . // 4 5 6 7 // . . . . . . . . // x // . . . . . . . . // 8 9 10 11 // . . . . . . . . // // . . . . . . . . // 12 13 14 15 // . . . . . . . . // // gather4 texel ordering: // w z // x y // float u = vWeights.x; float v = vWeights.y; float r0 = ( v0.z + v1.z + v1.w + v2.z + v2.w + v3.w ) + u*v3.z + (1-u)*v0.w; float r1 = ( v0.y + v1.y + v1.x + v2.y + v2.x + v3.x ) + u*v3.y + (1-u)*v0.x; float r2 = ( v4.z + v5.z + v5.w + v6.z + v6.w + v7.w ) + u*v7.z + (1-u)*v4.w; float r3 = ( v4.y + v5.y + v5.x + v6.y + v6.x + v7.x ) + u*v7.y + (1-u)*v4.x; float r4 = ( v8.z + v9.z + v9.w + v10.z + v10.w + v11.w ) + u*v11.z + (1-u)*v8.w; float r5 = ( v8.y + v9.y + v9.x + v10.y + v10.x + v11.x ) + u*v11.y + (1-u)*v8.x; float r6 = ( v12.z + v13.z + v13.w + v14.z + v14.w + v15.w ) + u*v15.z + (1-u)*v12.w; float r7 = ( v12.y + v13.y + v13.x + v14.y + v14.x + v15.x ) + u*v15.y + (1-u)*v12.x; float blend = r0*(1-v) + r1 + r2 + r3 + r4 + r5 + r6 + r7*v; return blend/49; } // Simple grid of NxN bilinear taps // taps == 2*n+1. use n=0 for 1x1, n=1 for 3x3, n=2 for 5x5, etc float PCFBilin(float3 vPosSM, Texture2D t, SamplerComparisonState s, int n ) { float2 uv = vPosSM.xy; float z = saturate(vPosSM.z); float v=0; [unroll] for( int x=-n; x<=n; x+= 1 ) [unroll] for( int y=-n; y<=n; y+= 1 ) v += t.SampleCmp(s,uv,z,int2(x,y) ); float ntaps = (2*n+1)*(2*n+1); return v/(ntaps); } float PCFBilin3x3(float3 vPosSM, Texture2D t, SamplerComparisonState s, int n ) { float2 uv = vPosSM.xy; float z = saturate(vPosSM.z); float t0 = t.SampleCmp( s,uv,z,int2(-2,-2) ); float t1 = t.SampleCmp( s,uv,z,int2(-2,-1) ); float t2 = t.SampleCmp( s,uv,z,int2(-2,-0) ); float t3 = t.SampleCmp( s,uv,z,int2(-2,1) ); float t4 = t.SampleCmp( s,uv,z,int2(-2,2) ); t0 += t.SampleCmp( s,uv,z,int2(-1,-2) ); t1 += t.SampleCmp( s,uv,z,int2(-1,-1) ); t2 += t.SampleCmp( s,uv,z,int2(-1,-0) ); t3 += t.SampleCmp( s,uv,z,int2(-1, 1) ); t4 += t.SampleCmp( s,uv,z,int2(-1, 2) ); t0 += t.SampleCmp( s,uv,z,int2(0,-2) ); t1 += t.SampleCmp( s,uv,z,int2(0,-1) ); t2 += t.SampleCmp( s,uv,z,int2(0,-0) ); t3 += t.SampleCmp( s,uv,z,int2(0, 1) ); t4 += t.SampleCmp( s,uv,z,int2(0, 2) ); t0 += t.SampleCmp( s,uv,z,int2(1,-2) ); t1 += t.SampleCmp( s,uv,z,int2(1,-1) ); t2 += t.SampleCmp( s,uv,z,int2(1,-0) ); t3 += t.SampleCmp( s,uv,z,int2(1, 1) ); t4 += t.SampleCmp( s,uv,z,int2(1, 2) ); t0 += t.SampleCmp( s,uv,z,int2(2,-2) ); t1 += t.SampleCmp( s,uv,z,int2(2,-1) ); t2 += t.SampleCmp( s,uv,z,int2(2,-0) ); t3 += t.SampleCmp( s,uv,z,int2(2, 1) ); t4 += t.SampleCmp( s,uv,z,int2(2, 2) ); float v = (t0+t1)+t2+(t3+t4); float ntaps = (2*n+1)*(2*n+1); return v/(ntaps); } float4 main( VSOut input ) : SV_TARGET { float3 vPosSM = input.vPosSM.xyz / input.vPosSM.w; float2 vClip = ( abs(vPosSM.xy) > 1 ? 1 : 0 ); vPosSM.xy = vPosSM.xy*float2(0.5,-0.5) + float2(0.5,0.5); //float fShadow = tShadowMap.SampleCmp( sShadowSampler, vPosSM.xy, saturate(vPosSM.z) ); //float fShadow = PCFGather5x5(vPosSM, vShadowMapSize, tShadowMap, sShadowSampler ); float fShadow = PCFBilin(vPosSM,tShadowMap,sShadowSampler,2); float3 L = normalize( input.L ); float3 N = normalize( input.N ); float3 C = saturate(dot(N,L)) * saturate(fShadow-vClip.x-vClip.y) * tTexture.Sample(sTexture,input.uv) ; return float4(pow(C.xyz,1/2.2),1); } ================================================ FILE: test/branches_test ================================================ bool b; bool c; bool d; int n; Buffer f; float4 main() : SV_TARGET { int i=0; float q=0; while(1) { q+= f[i++]; if( i >= n ) break; } [branch] if( d ) q += 42; if( b ) { if(c) { return 1+q; } else { return 2+q; } } else { return 3+q; } } ================================================ FILE: test/cs_addreturntest ================================================ groupshared uint LDS; Buffer counts; Buffer data; RWBuffer vout; [numthreads(64,1,1)] void main( uint3 idx : SV_DispatchThreadID ) { LDS=0; GroupMemoryBarrierWithGroupSync(); uint N = counts[idx.x]; uint loc; InterlockedAdd(LDS,N,loc); for( uint i=0; i StuffToDraw; float4 g_Frustum[6]; Buffer Spheres; Buffer Draws; [numthreads(64,1,1)] void main( uint3 tid : SV_DispatchThreadID ) { float4 sph = Spheres[tid.x]; [unroll] for( uint i=0; i<6; i++ ) { float d = dot(g_Frustum[i].xyzw,float4(sph.xyz,1)); if( d < 0 ) return; } StuffToDraw.Append(Draws[tid.x]); } ================================================ FILE: test/cs_barrier_test ================================================ Texture2D tTx; RWTexture2D tAvg; groupshared float Foo[16][16]; [numthreads(16,16,1)] void main( uint3 tid : SV_DispatchThreadID, uint3 gid : SV_GroupThreadID ) { float f = tTx.Load( uint3( tid.xy,0) ); Foo[gid.x][gid.y] = f; GroupMemoryBarrierWithGroupSync(); float avg=0; for( int i=0; i<16; i++ ) for( int j=0; j<16; j++ ) avg += Foo[i][j]; tAvg[ uint2(tid.x>>4,tid.y>>4)] = avg; } ================================================ FILE: test/cs_cull ================================================ #define THREADGROUP_WIDTH 1024 cbuffer globals { row_major float4x4 mViewProj; float2 g_vResolution; }; cbuffer drawcall { row_major float4x4 mWorld; }; struct TriGroup { uint nFirstIndex; uint nFirstVertex; uint nTriangles; uint nVerts; }; StructuredBuffer g_Groups; // Public service announcement. Raw buffers are SIGNIFICANTLY more efficient than TBuffers // Buffer and friends. Because of stupid DX constraint that R32G32B32 views cannot be used on VB/IB // it is necessary to load single elements from these. // Using ByteAddressBuffer instead gives me a sizable boost because we can load multiple dwords at once ByteAddressBuffer g_VertexBuffer; ByteAddressBuffer g_IndexBuffer; struct IndexStruct { uint3 Indices; }; AppendStructuredBuffer g_OutIndices; groupshared float3 g_Verts[THREADGROUP_WIDTH]; [numthreads(THREADGROUP_WIDTH,1,1)] void main( uint3 ThreadID : SV_DispatchThreadID, uint3 GroupID : SV_GroupID, uint3 GroupThreadID : SV_GroupThreadID ) { uint tid = ThreadID.x; uint tid_local = GroupThreadID.x; // initialize stuff uint3 Indices = 0; bool bKeepTri = false; // fetch tri-group information TriGroup kGroup = g_Groups[GroupID.x]; // load this thread's triangle indices uint IndexLocation = 12*tid_local + kGroup.nFirstIndex; Indices = g_IndexBuffer.Load3( IndexLocation ); // fetch and transform this thread's vertex [branch] if( gid < kGroup.nVerts ) { float3 P0 = asfloat( g_VertexBuffer.Load3( 12*(gid+kGroup.nFirstVertex) ) ); float3 P0w = mul( float4(P0,1), mWorld ).xyz; float4 P0p = mul( float4(P0w,1), mViewProj ); g_Verts[gid] = P0p.xyw; } // sync up GroupMemoryBarrierWithGroupSync(); // perform triangle backface tests [branch] if( gid < kGroup.nTriangles ) { float3 P0p = g_Verts[Indices.x]; float3 P1p = g_Verts[Indices.y]; float3 P2p = g_Verts[Indices.z]; // Culling in homogenous coordinates // Read: "Triangle Scan Conversion using 2D Homogeneous Coordinates" // by Marc Olano, Trey Greer // http://www.cs.unc.edu/~olano/papers/2dh-tri/2dh-tri.pdf float3x3 m = { P0p.xyz, P1p.xyz, P2p.xyz }; if( determinant(m)>0 ) { IndexStruct id; id.Indices = Indices + kGroup.nFirstVertex; g_OutIndices.Append(id); } } } groupshared uint g_Prefix[THREADGROUP_WIDTH]; groupshared uint OutputBaseAddress; RWByteAddressBuffer g_DrawIndirectBuffer; RWByteAddressBuffer g_OutputIB; [numthreads(THREADGROUP_WIDTH,1,1)] void main_prefix( uint3 ThreadID : SV_DispatchThreadID, uint3 GroupID : SV_GroupID, uint3 GroupThreadID : SV_GroupThreadID ) { uint tid = ThreadID.x; uint gid = GroupThreadID.x; // initialize stuff uint3 Indices = 0; bool bKeepTri = false; g_Prefix[gid] = 0; // fetch tri-group information TriGroup kGroup = g_Groups[GroupID.x]; // load this thread's triangle indices Indices = g_IndexBuffer.Load3( 12*gid + kGroup.nFirstIndex ); // fetch and transform this thread's vertex [branch] if( gid < kGroup.nVerts ) { float3 P0 = asfloat( g_VertexBuffer.Load3( 12*(gid+kGroup.nFirstVertex) ) ); float3 P0w = mul( float4(P0,1), mWorld ).xyz; float4 P0p = mul( float4(P0w,1), mViewProj ); g_Verts[gid] = P0p.xyw; } // sync up GroupMemoryBarrierWithGroupSync(); // perform triangle backface tests [branch] if( gid < kGroup.nTriangles ) { float3 P0p = g_Verts[Indices.x]; float3 P1p = g_Verts[Indices.y]; float3 P2p = g_Verts[Indices.z]; // Culling in homogenous coordinates // Read: "Triangle Scan Conversion using 2D Homogeneous Coordinates" // by Marc Olano, Trey Greer // http://www.cs.unc.edu/~olano/papers/2dh-tri/2dh-tri.pdf float3x3 m = { P0p.xyz, P1p.xyz, P2p.xyz }; g_Prefix[gid] = (determinant(m)>0) ? 1 : 0; } // prefix-sum on cull results GroupMemoryBarrierWithGroupSync(); [unroll] for(int t=1; t= t) g_Prefix[gid] += g_Prefix[gid-t]; GroupMemoryBarrier(); } // one thread does one single atomic inc to offset into output IB if( gid == kGroup.nTriangles-1 ) { uint nIndices = 3*g_Prefix[gid]; g_DrawIndirectBuffer.InterlockedAdd(0,nIndices, OutputBaseAddress); } GroupMemoryBarrierWithGroupSync(); if( gid < kGroup.nTriangles ) { uint nLoc = 4*(OutputBaseAddress + 3*g_Prefix[gid]); g_OutputIB.Store3(nLoc, Indices); } } /* [numthreads(THREADGROUP_WIDTH,1,1)] void main( uint3 ThreadID : SV_DispatchThreadID, uint3 GroupID : SV_GroupID, uint3 GroupThreadID : SV_GroupThreadID ) { uint tid = ThreadID.x; [branch] if( tid < g_nTriangles ) { // fetch verts // NOTE: No Vertex re-use. Possible to add some? uint3 Indices = g_Indices.Load3( 12*tid ); float3 P0 = asfloat( g_Verts.Load3( 12*Indices.x ) ); float3 P1 = asfloat( g_Verts.Load3( 12*Indices.y ) ); float3 P2 = asfloat( g_Verts.Load3( 12*Indices.z ) ); // transform verts float3 P0w = mul( float4(P0,1), mWorld ).xyz; float3 P1w = mul( float4(P1,1), mWorld ).xyz; float3 P2w = mul( float4(P2,1), mWorld ).xyz; float4 P0p = mul( float4(P0w,1), mViewProj ); float4 P1p = mul( float4(P1w,1), mViewProj ); float4 P2p = mul( float4(P2w,1), mViewProj ); P0p.w = rcp(P0p.w); P1p.w = rcp(P1p.w); P2p.w = rcp(P2p.w); P0p.xyz *= P0p.w; P1p.xyz *= P1p.w; P2p.xyz *= P2p.w; // clip-space to viewport transform P0p.xy = g_vResolution*(float2(0.5,-0.5)*P0p.xy + float2(0.5,0.5)); P1p.xy = g_vResolution*(float2(0.5,-0.5)*P1p.xy + float2(0.5,0.5)); P2p.xy = g_vResolution*(float2(0.5,-0.5)*P2p.xy + float2(0.5,0.5)); // compute AABB float2 vBBMin = min(P0p.xy,min(P1p.xy,P2p.xy)); float2 vBBMax = max(P0p.xy,max(P1p.xy,P2p.xy)); // clip AABB to screen vBBMin = max(vBBMin.xy,0); vBBMax = min(vBBMax.xy,g_vResolution); // reject out-of-bounds triangles [branch] if( all(vBBMin < vBBMax) ) { // back-face test float2 v01 = P1p.xy-P0p.xy; float2 v20 = P0p.xy-P2p.xy; [branch] if( (v01.x*v20.y - v20.x*v01.y) < 0 ) { // Setup Edge functions float2 N01 = float2(-v01.y,v01.x); float2 N20 = float2(-v20.y,v20.x); float3 E01 = float3(N01.xy,-dot(N01,P0p.xy)); float3 E20 = float3(N20.xy,-dot(N20,P0p.xy)); E01 *= rcp(dot(E01,float3(P2p.xy,1))); E20 *= rcp(dot(E20,float3(P1p.xy,1))); // Setup interpolation functions for Z and 1/w float3 ZPlane = float3(P0p.z, P2p.z-P0p.z, P1p.z-P0p.z); float3 WPlane = float3(P0p.w, P2p.w-P0p.w, P1p.w-P0p.w); // Round AABB to pixels float2 TriMin = floor(vBBMin); float2 TriMax = ceil(vBBMax); // offset to pixel center TriMin += 0.5f; TriMax += 0.5f; // iterate pixels float2 vPos; for( vPos.y=TriMin.y; vPos.y < TriMax.y; vPos.y++ ) { for( vPos.x=TriMin.x; vPos.x < TriMax.x; vPos.x++ ) { // TODO: Incremental? float u = dot( float3(vPos,1), E01 ); float v = dot( float3(vPos,1), E20 ); [branch] if( u>=0 && v>=0 && (u+v)<=1 ) { // Interpolate depth float z = dot( float3(1,u,v),ZPlane ); float w = dot( float3(1,u,v),WPlane ); float depth = z/w; // Surprisingly, reading the Z-buffer first // and then skipping redundant Interlocked ops // results in a massive boost // // I'm not so sure whether this is due to depth complexity or // if we're somehow speeding up the atomics by ensuring // that the pixels are in cache first // uint zb = g_ZBuffer[uint2(vPos.xy)]; [branch] if( zb > asuint(depth) ) InterlockedMin(g_ZBuffer[uint2(vPos.xy)], asuint(depth) ); } } } } } } } */ ================================================ FILE: test/cs_raster.hlsl ================================================ #define THREADGROUP_WIDTH 160 // 1 SIMD16 thread per EU cbuffer globals { row_major float4x4 mViewProj; float2 g_vResolution; }; cbuffer drawcall { row_major float4x4 mWorld; uint g_nTriangles; }; // Public service announcement. Raw buffers are SIGNIFICANTLY more efficient than TBuffers // Buffer and friends. Because of stupid DX constraint that R32G32B32 views cannot be used on VB/IB // it is necessary to load single elements from these. // Using ByteAddressBuffer instead gives me a sizable boost because we can load multiple dwords at once ByteAddressBuffer g_Verts; ByteAddressBuffer g_Indices; RWTexture2D g_ZBuffer : register(u0); [numthreads(THREADGROUP_WIDTH,1,1)] void main( uint3 ThreadID : SV_DispatchThreadID, uint3 GroupID : SV_GroupID, uint3 GroupThreadID : SV_GroupThreadID ) { uint tid = ThreadID.x; [branch] if( tid < g_nTriangles ) { // fetch verts // NOTE: No Vertex re-use. Possible to add some? uint3 Indices = g_Indices.Load3( 12*tid ); float3 P0 = asfloat( g_Verts.Load3( 12*Indices.x ) ); float3 P1 = asfloat( g_Verts.Load3( 12*Indices.y ) ); float3 P2 = asfloat( g_Verts.Load3( 12*Indices.z ) ); // transform verts float3 P0w = mul( float4(P0,1), mWorld ).xyz; float3 P1w = mul( float4(P1,1), mWorld ).xyz; float3 P2w = mul( float4(P2,1), mWorld ).xyz; float4 P0p = mul( float4(P0w,1), mViewProj ); float4 P1p = mul( float4(P1w,1), mViewProj ); float4 P2p = mul( float4(P2w,1), mViewProj ); P0p.w = rcp(P0p.w); P1p.w = rcp(P1p.w); P2p.w = rcp(P2p.w); P0p.xyz *= P0p.w; P1p.xyz *= P1p.w; P2p.xyz *= P2p.w; // clip-space to viewport transform P0p.xy = g_vResolution*(float2(0.5,-0.5)*P0p.xy + float2(0.5,0.5)); P1p.xy = g_vResolution*(float2(0.5,-0.5)*P1p.xy + float2(0.5,0.5)); P2p.xy = g_vResolution*(float2(0.5,-0.5)*P2p.xy + float2(0.5,0.5)); // compute AABB float2 vBBMin = min(P0p.xy,min(P1p.xy,P2p.xy)); float2 vBBMax = max(P0p.xy,max(P1p.xy,P2p.xy)); // clip AABB to screen vBBMin = max(vBBMin.xy,0); vBBMax = min(vBBMax.xy,g_vResolution); // reject out-of-bounds triangles [branch] if( all(vBBMin < vBBMax) ) { // back-face test float2 v01 = P1p.xy-P0p.xy; float2 v20 = P0p.xy-P2p.xy; [branch] if( (v01.x*v20.y - v20.x*v01.y) < 0 ) { // Setup Edge functions float2 N01 = float2(-v01.y,v01.x); float2 N20 = float2(-v20.y,v20.x); float3 E01 = float3(N01.xy,-dot(N01,P0p.xy)); float3 E20 = float3(N20.xy,-dot(N20,P0p.xy)); E01 *= rcp(dot(E01,float3(P2p.xy,1))); E20 *= rcp(dot(E20,float3(P1p.xy,1))); // Setup interpolation functions for Z and 1/w float3 ZPlane = float3(P0p.z, P2p.z-P0p.z, P1p.z-P0p.z); float3 WPlane = float3(P0p.w, P2p.w-P0p.w, P1p.w-P0p.w); // Round AABB to pixels float2 TriMin = floor(vBBMin); float2 TriMax = ceil(vBBMax); // offset to pixel center TriMin += 0.5f; TriMax += 0.5f; // iterate pixels float2 vPos; for( vPos.y=TriMin.y; vPos.y < TriMax.y; vPos.y++ ) { for( vPos.x=TriMin.x; vPos.x < TriMax.x; vPos.x++ ) { // TODO: Incremental? float u = dot( float3(vPos,1), E01 ); float v = dot( float3(vPos,1), E20 ); [branch] if( u>=0 && v>=0 && (u+v)<=1 ) { // Interpolate depth float z = dot( float3(1,u,v),ZPlane ); float w = dot( float3(1,u,v),WPlane ); float depth = z/w; // Surprisingly, reading the Z-buffer first // and then skipping redundant Interlocked ops // results in a massive boost // // I'm not so sure whether this is due to depth complexity or // if we're somehow speeding up the atomics by ensuring // that the pixels are in cache first // uint zb = g_ZBuffer[uint2(vPos.xy)]; [branch] if( zb > asuint(depth) ) InterlockedMin(g_ZBuffer[uint2(vPos.xy)], asuint(depth) ); } } } } } } } ================================================ FILE: test/cs_raycaster ================================================ static const float HUGE = 100000000; struct Vertex { float3 P; float3 N; }; struct Box { float3 Min; float3 Max; }; struct Node { Box box; int ChildIndex; int PrimCount; }; struct TriHit { float T; float U; float V; }; struct Ray { float3 Origin; float3 Direction; float tmax; int nTriHit; float u; float v; }; float hmax( float3 v ) { return max( max(v.x,v.y), v.z ); } float hmin( float3 v ) { return min( min(v.x,v.y), v.z ); } bool RayBoxTest( Box box, float3 O, float3 DInv, float tmax ) { float3 tMin = (O.xyz - box.Min.xyz)*DInv.xyz; float3 tMax = (O.xyz - box.Max.xyz)*DInv.xyz; float3 t0 = min(tMin,tMax); float3 t1 = max(tMin,tMax); t0.x = hmax( t0 ); t1.x = hmin( t1 ); return (t0.x < min(t1.x,tmax)) && t1.x > 0; } bool RayTriangleTest( float3 P0, float3 P1, float3 P2, float3 O, float3 D, float TMax, out TriHit hit ) { float3 v10 = P1 - P0; float3 v02 = P0 - P2; float3 v10x02 = cross(v10,v02); float3 v0a = P0 - O; float3 v02x0a = cross(v02,v0a); float V = 1 / dot( v10x02, D ); float A = V * dot( v02x0a, D ); if( A >= 0.0) { float3 v10x0a = cross(v10,v0a); float B = V * dot( v10x0a, D ); if( B >= 0.0 && (A+B) <= 1.0 ) { float VA = dot( v10x02, v0a ); float T = VA*V; if( T > 0 && T < TMax ) { hit.T = T; hit.U = 1.0 - (A+B); hit.V = A; return true; } } } return false; } StructuredBuffer bvh; StructuredBuffer verts; Buffer indices; RWStructuredBuffer rays; [numthreads(64,1,1)] void main( uint3 tid : SV_DispatchThreadID ) { Ray ray = rays[tid.x]; float3 O = ray.Origin; float3 D = ray.Direction; float3 DInv = 1/D; float tmax = ray.tmax; ray.nTriHit = -1; int n = 0; int sp=0; int stack[64]; while( true ) { while( RayBoxTest( bvh[n].box, O, DInv, tmax ) ) { if( bvh[n].PrimCount > 0 ) { for( int i=0; i Texels; RWTexture2D Output; groupshared float4 SCRATCH[N+6][N+6]; groupshared float4 H[N][N+6]; static const float KERNEL[7] = { 0.1,0.3,0.5,1.0,0.5,0.3,0.1 // note: wrong weights }; [numthreads(N,N,1)] void main( uint3 TID : SV_DispatchThreadID, uint3 gid : SV_GroupThreadID, uint3 group : SV_GroupID ) { // fetch the full NxN neighborhood, along with // a 3 texel border aroudn it uint3 addr = uint3(TID.xy,0); SCRATCH[gid.x][gid.y] = Texels.Load(addr,int2(-3,-3)); SCRATCH[gid.x][gid.y+5] = Texels.Load(addr,int2(-3,3)); SCRATCH[gid.x+5][gid.y] = Texels.Load(addr,int2(3,-3)); SCRATCH[gid.x+5][gid.y+5] = Texels.Load(addr,int2(3,3)); GroupMemoryBarrierWithGroupSync(); { float4 htop=0; float4 hbottom=0; [unroll] for( int i=0; i<7; i++ ) { htop += KERNEL[i]*SCRATCH[gid.x+i][gid.y]; hbottom += KERNEL[i]*SCRATCH[gid.x+i][gid.y+5]; } H[gid.x][gid.y] = htop; H[gid.x][gid.y+5] = hbottom; } GroupMemoryBarrierWithGroupSync(); // vertical pass float4 v=0; [unroll] for( int i=0; i<7; i++ ) v += KERNEL[i]*H[3+gid.x][gid.y+(i-3)]; Output[TID.xy] = v; } ================================================ FILE: test/include/include_d.txt ================================================ #include "include_e.txt" ================================================ FILE: test/include/include_e.txt ================================================ static const float E = 16; ================================================ FILE: test/include_a.txt ================================================ #include "include_b.txt" float Function() { return B + 5; } ================================================ FILE: test/include_b.txt ================================================ static const float B = 42; ================================================ FILE: test/include_root.txt ================================================ //#extension GL_GOOGLE_include_directive : require #include "include_a.txt" #include "include_d.txt" float main() : SV_Target { return Function() + E; } ================================================ FILE: test/manual_trilerp ================================================ float2 g_fSize; Texture2D tx; float4 bilerp( float2 uv, float lod ) { float2 coords = (uv)/exp(lod); coords = coords-0.5; float2 weights = frac(coords); int3 icoords = int3(coords,lod); float4 t0 = tx.Load( icoords, uint2(0,0) ); float4 t1 = tx.Load( icoords, uint2(1,0) ); float4 t2 = tx.Load( icoords, uint2(0,1) ); float4 t3 = tx.Load( icoords, uint2(1,1) ); return lerp( lerp(t0,t1,weights.x), lerp(t2,t3,weights.x), weights.y ); } float4 main( float2 uv : uv ) : SV_Target { uv = uv*g_fSize; float2 sizes = abs(ddx(uv)+ddy(uv)); float lod = log2( max(sizes.x,sizes.y) ); float4 l0 = bilerp(uv,floor(lod)); float4 l1 = bilerp(uv,floor(lod)+1); return lerp(l0,l1,frac(lod)); } ================================================ FILE: test/manual_trilerp_glsl ================================================ #version 300 es precision highp float; uniform vec2 g_fSize; uniform sampler2D tx; vec4 bilerp( vec2 uv, float lod ) { vec2 coords = (uv)/exp(lod); coords = coords-vec2(0.5); vec2 weights = fract(coords); ivec2 icoords = ivec2(coords); int ilod = int(lod); vec4 t0 = texelFetch( tx, icoords + ivec2(0,0), ilod ); vec4 t1 = texelFetch( tx, icoords + ivec2(1,0), ilod ); vec4 t2 = texelFetch( tx, icoords + ivec2(0,1), ilod ); vec4 t3 = texelFetch( tx, icoords + ivec2(1,1), ilod ); return mix( mix(t0,t1,weights.x), mix(t2,t3,weights.x), weights.y ); } in vec2 UV; out vec4 Color; void main( ) { vec2 uv = UV*g_fSize; vec2 sizes = abs(dFdx(uv)+dFdy(uv)); float lod = log2( max(sizes.x,sizes.y) ); vec4 l0 = bilerp(uv,floor(lod)); vec4 l1 = bilerp(uv,floor(lod)+1.f); Color= mix(l0,l1,fract(lod)); } ================================================ FILE: test/matthias_bug ================================================ Texture2D myTexture : register(t0); SamplerState mySampler : register(s0); float linearToSRGB( float cl ) { float cs; if( isnan(cl) ) { /* Map IEEE-754 Not-a-number to zero. */ cs = 0.0; } else if (cl > 1.0) { cs = 1.0; } else if (cl < 0.0) { cs = 0.0; } else if (cl < 0.0031308) { cs = 12.92 * cl; } else { cs = 1.055 * pow(cl, 0.41666) - 0.055; } return cs; } float3 linearToSRGB( float3 cl ) { return float3( linearToSRGB(cl.x), linearToSRGB(cl.y), linearToSRGB(cl.z) ); } float4 main( float2 uv : TEXCOORD0 ) : SV_Target { uv.y = 1.0f - uv.y; float4 colour = myTexture.Sample( mySampler, uv ).xyzw; return float4( linearToSRGB( colour.xyz ), colour.w ); } ================================================ FILE: test/mips ================================================ float3 accurateSRGBToLinear (in float3 sRGBCol ) { float3 linearRGBLo = sRGBCol / 12.92; float3 linearRGBHi = pow (( sRGBCol + 0.055) / 1.055 , 2.4) ; float3 linearRGB = ( sRGBCol <= 0.04045) ? linearRGBLo : linearRGBHi ; return linearRGB ; } float3 accurateLinearToSRGB (in float3 linearCol ) { float3 sRGBLo = linearCol * 12.92; float3 sRGBHi = ( pow( abs ( linearCol ) , 1.0/2.4) * 1.055) - 0.055; float3 sRGB = ( linearCol <= 0.0031308) ? sRGBLo : sRGBHi ; return sRGB; } #define NUMTHREADS 8 Texture2D SrcMip : register(t0); RWTexture2D DstMip : register(u0); sampler SS_DEFAULT : register(s0); float2 vDims; uint g_bSRGB; [numthreads(NUMTHREADS,NUMTHREADS,1)] void main( uint2 gid : SV_GroupID, uint2 tid : SV_GroupThreadID ) { uint2 vPixel = gid*NUMTHREADS + tid; uint2 dims; SrcMip.GetDimensions(dims.x,dims.y); float2 uv = (vPixel + float2(0.5f,0.5f)) * rcp(dims.xy); float4 vTap = SrcMip.SampleLevel( SS_DEFAULT, uv, 0 ); DstMip[vPixel] = g_bSRGB ? accurateLinearToSRGB(vTap) : vTap; } ================================================ FILE: test/moblur_reduc ================================================ #define TILE_SIZE 32 #define THREAD_COUNT TILE_SIZE*TILE_SIZE Texture2D tx_velocity; RWTexture2D tx_tile_out; groupshared float2 SCRATCH[TILE_SIZE*TILE_SIZE]; [numthreads(THREAD_COUNT,1,1)] void main( uint3 tid : SV_DispatchThreadID, uint3 tid_local : SV_GroupThreadID, uint3 gid : SV_GroupID ) { uint x = tid_local.x % TILE_SIZE; uint y = tid_local.y / TILE_SIZE; uint2 fetch = gid.xy*TILE_SIZE + uint2(x,y); float2 v = tx_velocity.Load( uint3(fetch.xy,0) ); SCRATCH[tid_local.x] = v; uint n = THREAD_COUNT/2; do { GroupMemoryBarrierWithGroupSync(); if( tid_local.x < n ) { float2 v0 = SCRATCH[tid_local.x]; float2 v1 = SCRATCH[tid_local.x+n]; float m0 = dot(v0,v0); float m1 = dot(v1,v1); float2 big = (m0>m1) ? v0 : v1; SCRATCH[tid_local.x] = big; } n = n/2; } while( n > 1 ); if( tid_local.x == 0 ) tx_tile_out[gid.xy] = SCRATCH[0]; } ================================================ FILE: test/ps_lighting.txt ================================================ uint nLights; Buffer g_LightPositions; Buffer g_LightColors; Texture2D g_Tx; sampler g_S; float4 main( float3 P : P, float3 N : N ) : SV_Target { float3 Diff = g_Tx.Sample(g_S,P.xy); float3 C=0; for( uint i=0; i g_LightPositions; // w == radius Buffer g_LightColors; uint g_nLights; float3 g_CamPos; Texture2D tNormalMap; Texture2D tTexture; TextureCube tCube; sampler sTexture; float4 main( VSOut input ) : SV_TARGET { float3 vN = tNormalMap.Sample( sTexture, input.uv ); float3 N = ( input.N ); float3 T = ( input.T ); float3 B = ( input.B ); N = N*vN.z + T*vN.y + B*vN.x; float3 vTex = tTexture.Sample( sTexture, input.uv ); float3 diff = tCube.SampleBias( sTexture, N, 15 ); float3 R = reflect( N, input.P-g_CamPos); float3 spec = tCube.Sample( sTexture, R ); for( int i=0; i tDiff; Texture2D tNormal; Texture2D tRough; TextureCube tCube; Texture2D tShadowMap; SamplerComparisonState sCmp; sampler s; struct Inputs { float3 N : N; float2 UV : uv; float3 T : T; float3 Pos : P; }; float PCFGather5x5( float3 vPosSM, float2 Size, Texture2D t, SamplerComparisonState s ) { float2 uv = (vPosSM.xy*Size); float z = saturate(vPosSM.z); float2 vWeights = frac(uv.xy); // grab bilinear weights // snap UV to texel center // If we don't do this, our texels won't agree with the sampler's texels uv = (floor(uv)+0.5)/Size; float4 v0 = t.GatherCmp( s, uv, z, int2(-2, -2) ); float4 v1 = t.GatherCmp( s, uv, z, int2( 0, -2) ); float4 v2 = t.GatherCmp( s, uv, z, int2( 2, -2) ); float4 v3 = t.GatherCmp( s, uv, z, int2(-2, 0) ); float4 v4 = t.GatherCmp( s, uv, z, int2( 0, 0) ); float4 v5 = t.GatherCmp( s, uv, z, int2( 2, 0) ); float4 v6 = t.GatherCmp( s, uv, z, int2(-2, 2) ); float4 v7 = t.GatherCmp( s, uv, z, int2( 0, 2) ); float4 v8 = t.GatherCmp( s, uv, z, int2( 2, 2) ); // tap locations // . . . . . . // 0 1 2 // . . . . . . // // . . . . . . // 3 4 5 // . . . . . . // // . . . . . . // 6 7 8 // . . . . . . // // gather4 texel ordering: // w z // x y // float u = vWeights.x; float v = vWeights.y; float r0 = ( v0.z + v1.z + v1.w + v2.w ) + u*v2.z + (1-u)*v0.w; float r1 = ( v0.y + v1.y + v1.x + v2.x ) + u*v2.y + (1-u)*v0.x; float r2 = ( v3.z + v4.z + v4.w + v5.w ) + u*v5.z + (1-u)*v3.w; float r3 = ( v3.y + v4.y + v4.x + v5.x ) + u*v5.y + (1-u)*v3.x; float r4 = ( v6.z + v7.z + v7.w + v8.w ) + u*v8.z + (1-u)*v6.w; float r5 = ( v6.y + v7.y + v7.x + v8.x ) + u*v8.y + (1-u)*v6.x; float blend = r0*(1-v) + r1 + r2 + r3 + r4 + r5*v; return blend/25; } float4 SHADE( Inputs input, bool NORMAL_MAP, bool TANGENT_SPACE_NM, bool SPEC, bool METALLIC, bool ROUGHNESS_MAP, bool CUBE_MAP, bool SHADOWS ) : SV_TARGET { float2 UV = input.UV; float4 diff = tDiff.Sample(s,UV); float3 V = normalize(input.Pos - g_EyePos); float3 N = normalize(input.N); [branch] if( NORMAL_MAP ) { float3 normaltx = tNormal.Sample(s,UV).xyz; [branch] if( TANGENT_SPACE_NM ) { float3 T = normalize(input.T); float3 B = cross(N,T); N = B * normaltx.x + T * normaltx.y + N * normaltx.z; } } float3 vDirect = diff.xyz*saturate( dot(N,g_LightDir) ); [branch] if( SPEC ) { float rough = g_StaticRoughness; [branch] if( ROUGHNESS_MAP ) { rough = tRough.Sample( s, UV ); } float3 H = normalize( g_LightDir +V ); float fSpec = ((rough+1)/(2.0f*PI))*pow( saturate(dot(N,H)), rough ); float3 vSpec = fSpec; [branch] if( METALLIC ) vSpec *= diff.xyz; vDirect += vSpec; } float3 vIndirect = 0; [branch] if( CUBE_MAP ) { float3 cube = tCube.Sample( s, reflect(N,V) ); [branch] if( METALLIC ) cube *= diff.xyz; vIndirect += cube; } [branch] if( SHADOWS ) { float4 vPosSM = mul( float4(input.Pos,1), g_mShadowMap ); float sh = PCFGather5x5( vPosSM.xyz/vPosSM.w, g_ShadowMapSize, tShadowMap, sCmp ); vDirect *= sh; } return float4(vDirect*g_LightColor + vIndirect,1); } float4 main( Inputs input ) : SV_TARGET { //return SHADE_GOOD(input); return SHADE(input,true,true,true,true,true, true, true ); //return SHADE(input,g_bNM, g_bObjectSpaceNM, g_bSpec,g_bMetallic, g_bCube, g_bRough, g_bSMap ); } ================================================ FILE: test/trivial_test_shaders.txt ================================================ float4 mainPS() : SV_Target { return 0; } float4 mainVS() : SV_Position { return 0; } struct GSIn { float4 v : SV_Position; }; struct GSOut { float4 vPos : SV_Position; }; [maxvertexcount(4)] void mainGS( point GSIn p[1], inout TriangleStream triStream ) { GSOut v; v.vPos = p[0].v; triStream.Append(v); triStream.Append(v); triStream.Append(v); } struct VertexDS { float3 p : SV_Position; }; struct PatchInfoDS { float v[2] : SV_InsideTessFactor; float edges[4] : SV_TessFactor; }; [domain("quad")] float4 mainDS( in PatchInfoDS info, float2 UV : SV_DomainLocation, const OutputPatch bezpatch ) : SV_Position { float4 v = 0; v.xyz = lerp( lerp( bezpatch[0].p, bezpatch[1].p, UV.x ), lerp( bezpatch[2].p, bezpatch[3].p, UV.x ), UV.y ); v.w = 1; return v; } struct VertexHS { float3 p : Pos; }; struct PatchInfoHS { float v[2] : SV_InsideTessFactor; float edges[4] : SV_TessFactor; }; PatchInfoHS HSConstants() { PatchInfoHS info; info.v[0] = 0; info.v[1] = 0; info.edges[0] = 0; info.edges[1] = 0; info.edges[2] = 0; info.edges[3] = 0; return info; } [domain("quad")] [partitioning("integer")] [outputtopology("triangle_cw")] [outputcontrolpoints(16)] [patchconstantfunc("HSConstants")] VertexHS mainHS( InputPatch ip, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID ) { VertexHS Output; Output.p.xyz = 0; return Output; } RWBuffer Out; [numthreads(64,1,1)] void mainCS( uint id : SV_DispatchThreadID ) { Out[id] = 0; } ================================================ FILE: test/trivial_vs_glsl ================================================ #version 300 es precision highp float; in vec4 Pos; out vec4 Pos_x; void main( ) { Pos_x = Pos; } ================================================ FILE: test/vs_rigid ================================================ float4x4 mViewProj; float4x4 mWorld; struct VSOut { float4 P : SV_Position; float3 N : n; float2 uv : uv; }; VSOut main( float3 P : p, float3 N : n, float2 uv : uv ) { float3 vP=0; float3 vN=0; vP = mul( float4(P,1), mWorld ); vN = mul( float4(N,0), mWorld ); VSOut o; o.P = mul( float4(vP,1), mViewProj ); o.N = normalize(vN); o.uv = uv; return o; } ================================================ FILE: test/vs_skinning ================================================ float4x4 mViewProj; float4x4 mSkin[30]; struct VSOut { float4 P : SV_Position; float4 N : n; float2 uv : uv; }; VSOut main( float3 P : p, float3 N : n, float2 uv : uv, float4 w : weights, uint4 idx : indices, float3 foo : foo) { float3 vP=0; float3 vN=0; [unroll] for( int i=0; i<4; i++ ) { vP += mul( float4(P,1), mSkin[idx[i]] ) * w[i]; vN += mul( float4(N,0), mSkin[idx[i]] ) * w[i]; } VSOut o; o.P = mul( float4(vP,1), mViewProj ); o.N = float4(vN.xyz,1); o.uv = uv.xy; return o; }