├── .gitattributes ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── data ├── Test_Loop.cpp ├── Test_Loop.frag ├── Test_Loop.frag.spv ├── complex.cpp ├── complex.frag ├── complex.frag.cpp ├── complex.frag.spv ├── complex.frag.test ├── glslangValidator.exe ├── light.frag ├── light.frag.cpp ├── light.frag.spv ├── light.frag.txt ├── sampler.frag ├── sampler.frag.cpp ├── sampler.frag.spv ├── testin.bmp └── testout.bmp ├── ext ├── cygglsl.std.450.dll ├── glsl.std.450.dll └── libglsl.std.450.so └── src ├── ext ├── CMakeLists.txt └── glsl.std.450 │ ├── CMakeLists.txt │ └── glsl.std.450.cpp ├── main ├── CMakeLists.txt ├── codegen.cpp ├── codegen.h ├── interpreted_vm.cpp ├── interpreted_vm.h ├── otherside_main.cpp ├── parser.cpp ├── parser.h ├── validation.cpp └── validation.h ├── shared ├── CMakeLists.txt ├── Khronos │ ├── GLSL450Lib.h │ └── spirv.h ├── common_ops.h ├── lookups.cpp ├── lookups.h ├── lookups_gen.cpp ├── lookups_gen.h ├── parser_definitions.h ├── stb │ ├── stb_image.h │ └── stb_image_write.h ├── types.h ├── utils.cpp ├── utils.h └── vm.h ├── test ├── CMakeLists.txt ├── otherside_test_codegen.cpp └── otherside_test_parser.cpp └── tools ├── CMakeLists.txt ├── SpecParser ├── App.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── SpecParser.csproj └── packages.config ├── assembler ├── CMakeLists.txt └── assembler_main.cpp └── disassembler ├── CMakeLists.txt └── disassembler_main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.filters 3 | *.sdf 4 | *.opensdf 5 | /compile 6 | /build 7 | /build64 8 | *.user 9 | /FFTs/Debug 10 | /bcryptprimitives.pdb/D2918AA6339744EDA39204642A7D65E71 11 | /msvcrt.pdb/E4A7E37FD2E545B3B369E4DFE67957CE1 12 | /packages/HtmlAgilityPack.1.4.9 13 | /SpecParser/bin/Debug 14 | /SpecParser/obj/Debug 15 | /System.Data.DataSetExtensions.pdb/74804A74014B4184B3C124DCE2A693A11 16 | /System.Xml.pdb/E364FACDD53C48F4B4FDE9C8C3A3FFDC2 17 | /src/x64/Debug 18 | /x64/Debug 19 | /tools/SpecParser/obj/Debug/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs 20 | /tools/SpecParser/obj/Debug/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs 21 | /tools/SpecParser/obj/Debug/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs 22 | /tools/SpecParser/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache 23 | /src/tools/SpecParser/bin/Release 24 | /src/tools/SpecParser/obj/Debug 25 | /src/tools/SpecParser/obj/Release 26 | 27 | /.idea 28 | *.stackdump 29 | src/tools/SpecParser/bin/ 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: gcc 3 | sudo: required 4 | install: 5 | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 6 | - sudo add-apt-repository -y ppa:george-edison55/cmake-3.x 7 | - sudo apt-get clean 8 | - sudo apt-get update 9 | - sudo apt-get purge cmake 10 | - sudo apt-get install -yq build-essential gcc-4.8 g++-4.8 gcc-4.8-multilib g++-4.8-multilib 11 | - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.6 12 | - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 80 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8 13 | - echo 2 | sudo update-alternatives --config gcc 14 | - wget http://www.cmake.org/files/v3.3/cmake-3.3.0-Linux-x86_64.tar.gz --no-check-certificate 15 | - tar -xzf cmake-3.3.0-Linux-x86_64.tar.gz 16 | - sudo cp -fR cmake-3.3.0-Linux-x86_64/* /usr 17 | - rm -rf cmake-3.3.0-Linux-x86_64 18 | - rm cmake-3.3.0-Linux-x86_64.tar.gz 19 | - g++ --version 20 | - cmake --version 21 | script: 22 | - cmake -G "Unix Makefiles" 23 | - make 24 | - make test 25 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (otherside) 3 | 4 | enable_testing() 5 | 6 | if(MSVC) 7 | # Force to always compile with W4 8 | if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") 9 | string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 10 | else() 11 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") 12 | endif() 13 | elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) 14 | # Update if necessary 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic") 16 | endif() 17 | 18 | set(CMAKE_CXX_STANDARD 11) 19 | set(CMAKE_CXX_STANDARD_REQUIRED on) 20 | 21 | add_subdirectory(src/main) 22 | add_subdirectory(src/shared) 23 | add_subdirectory(src/ext) 24 | add_subdirectory(src/test) 25 | add_subdirectory(src/tools) 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dario Seyb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # otherside 2 | 3 | [![Join the chat at https://gitter.im/daseyb/otherside](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/daseyb/otherside?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | [![Build Status](https://travis-ci.org/daseyb/otherside.svg?branch=master)](https://travis-ci.org/daseyb/otherside) 5 | 6 | A VM running SPIR-V code on the CPU 7 | 8 | This is an implementation of the SPIR-V, the new intermediate language defined by Khronos. 9 | See the official specification here: [SPIR-V 1.0](https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html) 10 | 11 | It also produces C like code that represents the given SPIR-V file (for easier reading). 12 | 13 | #### Why? 14 | I'm mostly working on this out of academic interest. I do plan on using it in my universities "write a software rasterizer" project. 15 | Once verification is implemented it could be used to verify the output of tools that produce SPIR-V (and right now, I guess if the program runs and gives the correct output, that is some kind of verification as well). 16 | 17 | #### Note 18 | This is very much a work in progress. Not all instructions are implemented and performance has not been a priority so far. 19 | 20 | #### Spec Parser 21 | This project downloads the latest spec and generates C++ files with useful declerations from it. Mostly information about op codes and structs to represent them to help with parsing and processing. 22 | 23 | #### Todo 24 | 25 | * SPIR-V Validation ([validation rules described here]( https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html#_a_id_validation_a_validation_rules)) 26 | * Implement all OpCodes 27 | * Improve performance 28 | * Better human readable parsing output (at least match the reference compiler) 29 | 30 | #### Example Code 31 | Input File: 32 | ![Input File](https://raw.githubusercontent.com/bonus2113/otherside/4f9a9b915d84ed1de4681e9d2433c29179134896/data/testin.bmp) 33 | 34 | Output File: 35 | ![Output File](https://raw.githubusercontent.com/bonus2113/otherside/4f9a9b915d84ed1de4681e9d2433c29179134896/data/testout.bmp) 36 | 37 | Shader code: 38 | 39 | #version 110 40 | varying vec2 uv; 41 | uniform sampler2D testTex; 42 | 43 | void main() { 44 | vec4 col = texture2D(testTex, uv); 45 | col.rgb = col.rbr; 46 | gl_FragColor = col; 47 | gl_FragColor.a = 1.0; 48 | } 49 | 50 | C++ code: 51 | 52 | int main(int argc, const char** argv) { 53 | CmdArgs args; 54 | if (!ParseArgs(argc, argv, &args)) { 55 | std::cout << "Could not parse arguments. Usage: " << USAGE << std::endl; 56 | return -1; 57 | } 58 | 59 | Parser parser(args.InputFile); 60 | Program prog; 61 | 62 | if (!parser.Parse(&prog)) { 63 | std::cout << "Could not parse program." << std::endl; 64 | return -1; 65 | } 66 | 67 | std::cout << "Validating program:..."; 68 | if(!validate(prog, std::cout)) { 69 | std::cout << "Validation failed." << std::endl; 70 | return -1; 71 | } 72 | std::cout << "done" << std::endl; 73 | 74 | std::cout << "Generationg code:..."; 75 | if (!genCode(args.OutputFile, prog)) { 76 | std::cout << "Could not generate code for program." << std::endl; 77 | return -1; 78 | } 79 | std::cout << "done" << std::endl; 80 | 81 | Environment env; 82 | InterpretedVM vm(prog, env); 83 | if(!vm.Setup()) { 84 | std::cout << "Could not setup the VM." << std::endl; 85 | return -1; 86 | } 87 | 88 | std::cout << "Running program:..."; 89 | 90 | Texture inTex = load_tex("data/testin.bmp"); 91 | 92 | Sampler* sampler = new Sampler{ 2, (uint32*)&inTex, inTex.data, FilterMode::FMPoint, WrapMode::WMRepeat }; 93 | Vec2* texSize = new Vec2{ (float)inTex.width, (float)inTex.height}; 94 | Light* light = new Light{ {1, 0, 0, 1}, {0.5f, 0.5f} }; 95 | Color* fragColor = new Color{ 0, 0, 0, 0 }; 96 | Vec2* uv = new Vec2{ 1.0f, 1.0f }; 97 | 98 | bool allVariablesSet = true; 99 | allVariablesSet &= vm.SetVariable("uv", &uv); 100 | allVariablesSet &= vm.SetVariable("texSize", &texSize); 101 | allVariablesSet &= vm.SetVariable("testTex", &sampler); 102 | allVariablesSet &= vm.SetVariable("light", &light); 103 | allVariablesSet &= vm.SetVariable("gl_FragColor", &fragColor); 104 | 105 | if(!allVariablesSet) { 106 | std::cout << "Could not set all variables." << std::endl; 107 | return -1; 108 | } 109 | 110 | Texture outTex = MakeFlatTexture(inTex.width, inTex.height, { 0, 0, 0, 1 }); 111 | bool didFail = false; 112 | for (int x = 0; x < outTex.width && !didFail; x++) { 113 | for (int y = 0; y < outTex.height; y++) { 114 | uv->x = float(x) / outTex.width; 115 | uv->y = float(y) / outTex.height; 116 | 117 | if (!vm.Run()) { 118 | std::cout << "Program failed to run."; 119 | getchar(); 120 | return -1; 121 | } 122 | 123 | outTex.data[x + y * outTex.width] = **(Color**)vm.ReadVariable("gl_FragColor"); 124 | } 125 | } 126 | 127 | save_bmp("data/testout.bmp", outTex); 128 | 129 | std::cout << " done"; 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /data/Test_Loop.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Version: 99 3 | Generator Magic: 85590203 4 | ID Bound: 42 5 | Instruction Schema: 0 6 | ================================================= 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "GLSL.std.450.h" 14 | 15 | // Predefined types: 16 | // ================================================= 17 | typedef double float64; 18 | typedef float float32; 19 | typedef uint8_t uint8; 20 | typedef uint16_t uint16; 21 | typedef uint32_t uint32; 22 | typedef uint64_t uint64; 23 | typedef int8_t int8; 24 | typedef int16_t int16; 25 | typedef int32_t int32; 26 | typedef int64_t int64; 27 | // ================================================= 28 | 29 | struct v_float32_3 { 30 | float32 v[3]; 31 | 32 | friend v_float32_3 operator+(v_float32_3 a, const v_float32_3& b) { 33 | a.v[0] += b.v[0]; 34 | a.v[1] += b.v[1]; 35 | a.v[2] += b.v[2]; 36 | return a; 37 | } 38 | 39 | 40 | friend v_float32_3 operator-(v_float32_3 a, const v_float32_3& b) { 41 | a.v[0] -= b.v[0]; 42 | a.v[1] -= b.v[1]; 43 | a.v[2] -= b.v[2]; 44 | return a; 45 | } 46 | 47 | 48 | friend v_float32_3 operator*(v_float32_3 a, const v_float32_3& b) { 49 | a.v[0] *= b.v[0]; 50 | a.v[1] *= b.v[1]; 51 | a.v[2] *= b.v[2]; 52 | return a; 53 | } 54 | 55 | 56 | friend v_float32_3 operator/(v_float32_3 a, const v_float32_3& b) { 57 | a.v[0] /= b.v[0]; 58 | a.v[1] /= b.v[1]; 59 | a.v[2] /= b.v[2]; 60 | return a; 61 | } 62 | 63 | }; 64 | typedef v_float32_3* p_v_float32_3; 65 | typedef v_float32_3* p_v_float32_3; 66 | typedef int32* p_int32; 67 | typedef int32* p_int32; 68 | struct v_float32_4 { 69 | float32 v[4]; 70 | 71 | friend v_float32_4 operator+(v_float32_4 a, const v_float32_4& b) { 72 | a.v[0] += b.v[0]; 73 | a.v[1] += b.v[1]; 74 | a.v[2] += b.v[2]; 75 | a.v[3] += b.v[3]; 76 | return a; 77 | } 78 | 79 | 80 | friend v_float32_4 operator-(v_float32_4 a, const v_float32_4& b) { 81 | a.v[0] -= b.v[0]; 82 | a.v[1] -= b.v[1]; 83 | a.v[2] -= b.v[2]; 84 | a.v[3] -= b.v[3]; 85 | return a; 86 | } 87 | 88 | 89 | friend v_float32_4 operator*(v_float32_4 a, const v_float32_4& b) { 90 | a.v[0] *= b.v[0]; 91 | a.v[1] *= b.v[1]; 92 | a.v[2] *= b.v[2]; 93 | a.v[3] *= b.v[3]; 94 | return a; 95 | } 96 | 97 | 98 | friend v_float32_4 operator/(v_float32_4 a, const v_float32_4& b) { 99 | a.v[0] /= b.v[0]; 100 | a.v[1] /= b.v[1]; 101 | a.v[2] /= b.v[2]; 102 | a.v[3] /= b.v[3]; 103 | return a; 104 | } 105 | 106 | }; 107 | typedef v_float32_4* p_v_float32_4; 108 | 109 | static p_v_float32_3 color; 110 | static p_int32 iterations; 111 | static p_v_float32_4 gl_FragColor; 112 | 113 | const int32 c_17 = 0; 114 | const int32 c_31 = 1; 115 | const float32 c_37 = 1.000000f; 116 | 117 | void spv_main() { 118 | p_v_float32_3 currColor = (p_v_float32_3)malloc(sizeof(v_float32_3)); 119 | p_int32 i = (p_int32)malloc(sizeof(int32)); 120 | v_float32_3 var_13; 121 | int32 var_21; 122 | int32 var_24; 123 | bool var_26; 124 | v_float32_3 var_27; 125 | v_float32_3 var_28; 126 | v_float32_3 var_29; 127 | int32 var_30; 128 | int32 var_32; 129 | v_float32_3 var_36; 130 | float32 var_38; 131 | float32 var_39; 132 | float32 var_40; 133 | v_float32_4 var_41; 134 | label_5: 135 | 136 | 137 | var_13 = *color; 138 | *currColor = var_13; 139 | *i = c_17; 140 | goto label_18; 141 | label_18: 142 | var_21 = *i; 143 | var_24 = *iterations; 144 | var_26 = var_21 < var_24; 145 | // LoopMerge [19] Unroll 146 | 147 | if(var_26) { goto label_20; } 148 | else { goto label_19; } 149 | label_20: 150 | var_27 = *color; 151 | var_28 = *currColor; 152 | var_29 = var_28 + var_27; 153 | *currColor = var_29; 154 | var_30 = *i; 155 | var_32 = var_30 + c_31; 156 | *i = var_32; 157 | goto label_18; 158 | label_19: 159 | var_36 = *currColor; 160 | var_38 = var_36.v[0]; 161 | var_39 = var_36.v[1]; 162 | var_40 = var_36.v[2]; 163 | var_41 = {var_38, var_39, var_40, c_37}; 164 | *gl_FragColor = var_41; 165 | goto label_6; 166 | label_6: 167 | return; 168 | } 169 | 170 | -------------------------------------------------------------------------------- /data/Test_Loop.frag: -------------------------------------------------------------------------------- 1 | #version 110 2 | uniform int iterations; 3 | varying vec3 color; 4 | 5 | void main() { 6 | vec3 currColor = color; 7 | 8 | for(int i = 0; i < iterations; i++) { 9 | currColor += color; 10 | } 11 | 12 | gl_FragColor = vec4(currColor, 1.0); 13 | } -------------------------------------------------------------------------------- /data/Test_Loop.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/data/Test_Loop.frag.spv -------------------------------------------------------------------------------- /data/complex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Version: 99 3 | Generator Magic: 85590203 4 | ID Bound: 91 5 | Instruction Schema: 0 6 | ================================================= 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "GLSL.std.450.h" 14 | 15 | // Predefined types: 16 | // ================================================= 17 | typedef double float64; 18 | typedef float float32; 19 | typedef uint8_t uint8; 20 | typedef uint16_t uint16; 21 | typedef uint32_t uint32; 22 | typedef uint64_t uint64; 23 | typedef int8_t int8; 24 | typedef int16_t int16; 25 | typedef int32_t int32; 26 | typedef int64_t int64; 27 | // ================================================= 28 | 29 | struct v_float32_3 { 30 | float32 v[3]; 31 | 32 | friend v_float32_3 operator+(v_float32_3 a, const v_float32_3& b) { 33 | a.v[0] += b.v[0]; 34 | a.v[1] += b.v[1]; 35 | a.v[2] += b.v[2]; 36 | return a; 37 | } 38 | 39 | 40 | friend v_float32_3 operator-(v_float32_3 a, const v_float32_3& b) { 41 | a.v[0] -= b.v[0]; 42 | a.v[1] -= b.v[1]; 43 | a.v[2] -= b.v[2]; 44 | return a; 45 | } 46 | 47 | 48 | friend v_float32_3 operator*(v_float32_3 a, const v_float32_3& b) { 49 | a.v[0] *= b.v[0]; 50 | a.v[1] *= b.v[1]; 51 | a.v[2] *= b.v[2]; 52 | return a; 53 | } 54 | 55 | 56 | friend v_float32_3 operator/(v_float32_3 a, const v_float32_3& b) { 57 | a.v[0] /= b.v[0]; 58 | a.v[1] /= b.v[1]; 59 | a.v[2] /= b.v[2]; 60 | return a; 61 | } 62 | 63 | }; 64 | typedef v_float32_3* p_v_float32_3; 65 | typedef float32* p_float32; 66 | struct lerp_res { 67 | v_float32_3 val1; 68 | v_float32_3 val1; 69 | }; 70 | typedef lerp_res* p_lerp_res; 71 | typedef v_float32_3* p_v_float32_3; 72 | typedef bool* p_bool; 73 | typedef int32* p_int32; 74 | typedef int32* p_int32; 75 | struct v_float32_4 { 76 | float32 v[4]; 77 | 78 | friend v_float32_4 operator+(v_float32_4 a, const v_float32_4& b) { 79 | a.v[0] += b.v[0]; 80 | a.v[1] += b.v[1]; 81 | a.v[2] += b.v[2]; 82 | a.v[3] += b.v[3]; 83 | return a; 84 | } 85 | 86 | 87 | friend v_float32_4 operator-(v_float32_4 a, const v_float32_4& b) { 88 | a.v[0] -= b.v[0]; 89 | a.v[1] -= b.v[1]; 90 | a.v[2] -= b.v[2]; 91 | a.v[3] -= b.v[3]; 92 | return a; 93 | } 94 | 95 | 96 | friend v_float32_4 operator*(v_float32_4 a, const v_float32_4& b) { 97 | a.v[0] *= b.v[0]; 98 | a.v[1] *= b.v[1]; 99 | a.v[2] *= b.v[2]; 100 | a.v[3] *= b.v[3]; 101 | return a; 102 | } 103 | 104 | 105 | friend v_float32_4 operator/(v_float32_4 a, const v_float32_4& b) { 106 | a.v[0] /= b.v[0]; 107 | a.v[1] /= b.v[1]; 108 | a.v[2] /= b.v[2]; 109 | a.v[3] /= b.v[3]; 110 | return a; 111 | } 112 | 113 | }; 114 | typedef v_float32_4* p_v_float32_4; 115 | 116 | static p_v_float32_3 color; 117 | static p_bool loopFlag; 118 | static p_int32 iterations; 119 | static p_v_float32_4 gl_FragColor; 120 | 121 | const float32 c_22 = 0.000000f; 122 | const int32 c_47 = 0; 123 | const int32 c_68 = 1; 124 | const float32 c_81 = 1.000000f; 125 | 126 | void spv_main() { 127 | label_5: 128 | } 129 | 130 | lerp_res spv_mlerp()vf3;vf3;f1;(p_v_float32_3 a, p_v_float32_3 b, p_float32 t) { 131 | = (p_lerp_res)malloc(sizeof(lerp_res));v_float32_3 var_24;v_float32_3 var_25;v_float32_3 var_26;float32 var_28;v_float32_3 var_30;lerp_res var_31;lerp_res var_32; label_17: 132 | p_lerp_res Result 133 | var_24 = *; 134 | var_25 = *; 135 | var_26 = *; 136 | // FSub [8] [27] [25] [26] 137 | 138 | var_28 = *; 139 | // VectorTimesScalar [8] [29] [27] [28] 140 | 141 | var_30 = var_24 + ; 142 | var_31 = {, var_30}; 143 | *Result = var_31; 144 | var_32 = *Result; 145 | // ReturnValue [32] 146 | 147 | } 148 | 149 | void spv_main()() { 150 | = (p_v_float32_3)malloc(sizeof(v_float32_3)); = (p_int32)malloc(sizeof(int32)); = (p_lerp_res)malloc(sizeof(lerp_res)); = (p_v_float32_3)malloc(sizeof(v_float32_3)); = (p_v_float32_3)malloc(sizeof(v_float32_3)); = (p_float32)malloc(sizeof(float32));v_float32_3 var_37;bool var_41;int32 var_51;int32 var_54;bool var_55;int32 var_57;int32 var_59;v_float32_3 var_63;v_float32_3 var_65;v_float32_3 var_70;v_float32_3 var_71;v_float32_3 var_72;int32 var_73;int32 var_74;int32 var_76;bool var_77;v_float32_3 var_86;float32 var_87;float32 var_88;float32 var_89;v_float32_4 var_90; label_19: 151 | p_v_float32_3 currColor 152 | p_int32 i 153 | p_lerp_res res 154 | p_v_float32_3 mlerp()vf3;vf3;f1;param0 155 | p_v_float32_3 mlerp()vf3;vf3;f1;param1 156 | p_float32 mlerp()vf3;vf3;f1;param2 157 | var_37 = *color; 158 | *currColor = var_37; 159 | var_41 = *loopFlag; 160 | // SelectionMerge [43] Flatten 161 | 162 | if(var_41) { goto label_42; } 163 | else { goto label_75; } 164 | label_42: 165 | *i = c_47; 166 | goto label_48; 167 | label_48: 168 | var_51 = *i; 169 | var_54 = *iterations; 170 | var_55 = var_51 < var_54; 171 | // LoopMerge [49] Unroll 172 | 173 | if(var_55) { goto label_50; } 174 | else { goto label_49; } 175 | label_50: 176 | var_57 = *i; 177 | // ConvertSToF [7] [58] [57] 178 | 179 | var_59 = *iterations; 180 | // ConvertSToF [7] [60] [59] 181 | 182 | // FDiv [7] [61] [58] [60] 183 | 184 | var_63 = *currColor; 185 | *mlerp()vf3;vf3;f1;param0 = var_63; 186 | var_65 = *color; 187 | *mlerp()vf3;vf3;f1;param1 = var_65; 188 | *mlerp()vf3;vf3;f1;param2 = ; 189 | // FunctionCall [11(lerp_res)] [67] [16(mlerp()vf3;vf3;f1;)] [[62(mlerp()vf3;vf3;f1;param0)], [64(mlerp()vf3;vf3;f1;param1)], [66(mlerp()vf3;vf3;f1;param2)]] 190 | 191 | *res = ; 192 | // AccessChain [9] [69] [56(res)] [[68]] 193 | 194 | var_70 = *; 195 | var_71 = *currColor; 196 | var_72 = var_71 + var_70; 197 | *currColor = var_72; 198 | var_73 = *i; 199 | var_74 = var_73 + c_68; 200 | *i = var_74; 201 | goto label_48; 202 | label_49: 203 | goto label_43; 204 | label_75: 205 | var_76 = *iterations; 206 | var_77 = var_76 > c_47; 207 | // SelectionMerge [79] Flatten 208 | 209 | if(var_77) { goto label_78; } 210 | else { goto label_80; } 211 | label_78: 212 | *currColor = ; 213 | goto label_79; 214 | label_80: 215 | *currColor = ; 216 | goto label_79; 217 | label_79: 218 | goto label_43; 219 | label_43: 220 | var_86 = *currColor; 221 | var_87 = var_86.v[0]; 222 | var_88 = var_86.v[1]; 223 | var_89 = var_86.v[2]; 224 | var_90 = {var_87, var_88, var_89, c_81}; 225 | *gl_FragColor = var_90; 226 | return; 227 | } 228 | 229 | -------------------------------------------------------------------------------- /data/complex.frag: -------------------------------------------------------------------------------- 1 | #version 110 2 | uniform int iterations; 3 | uniform bool loopFlag; 4 | varying vec3 color; 5 | 6 | struct lerp_res { 7 | vec3 val1; 8 | vec3 val2; 9 | }; 10 | 11 | lerp_res mlerp(vec3 a, vec3 b, float t) { 12 | lerp_res Result = lerp_res(vec3(0, 0, 0), a + (b - a) * t); 13 | return Result; 14 | } 15 | 16 | void main() { 17 | lerp_res res; 18 | vec3 currColor = color; 19 | 20 | if(loopFlag) { 21 | for(int i = 0; i < iterations; i++) { 22 | res = mlerp(currColor, color, float(i)/float(iterations)); 23 | currColor += res.val2; 24 | } 25 | } else { 26 | if(iterations > 0) { 27 | currColor = vec3(0, 0, 0); 28 | } else { 29 | currColor = vec3(1, 0, 1); 30 | } 31 | } 32 | 33 | gl_FragColor = vec4(currColor, 1.0); 34 | } -------------------------------------------------------------------------------- /data/complex.frag.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Version: 99 3 | Generator Magic: 85590203 4 | ID Bound: 89 5 | Instruction Schema: 0 6 | ================================================= 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "GLSL.std.450.h" 13 | 14 | 15 | // Predefined types: 16 | // ================================================= 17 | typedef double float64; 18 | typedef float float32; 19 | typedef uint8_t uint8; 20 | typedef uint16_t uint16; 21 | typedef uint32_t uint32; 22 | typedef uint64_t uint64; 23 | typedef int8_t int8; 24 | typedef int16_t int16; 25 | typedef int32_t int32; 26 | typedef int64_t int64; 27 | // ================================================= 28 | 29 | typedef void void_2; 30 | typedef float32 float_7; 31 | struct v_float_7_3_8 { 32 | float_7 v[3]; 33 | }; 34 | typedef v_float_7_3_8* p_v_float_7_3_8_9; 35 | typedef float_7* p_float_7_10; 36 | struct lerp_res { 37 | v_float_7_3_8 val1; 38 | v_float_7_3_8 val1; 39 | }; 40 | typedef lerp_res* p_lerp_res_18; 41 | typedef v_float_7_3_8* p_v_float_7_3_8_33; 42 | typedef bool bool_36; 43 | typedef bool_36* p_bool_36_37; 44 | typedef int32 int_42; 45 | typedef int_42* p_int_42_43; 46 | typedef int_42* p_int_42_50; 47 | struct v_float_7_4_81 { 48 | float_7 v[4]; 49 | }; 50 | typedef v_float_7_4_81* p_v_float_7_4_81_82; 51 | 52 | static p_v_float_7_3_8_33 color; 53 | static p_bool_36_37 loopFlag; 54 | static p_int_42_50 iterations; 55 | static p_v_float_7_4_81_82 gl_FragColor; 56 | 57 | float_7 c_20 = 0; 58 | int_42 c_45 = 0; 59 | int_42 c_66 = 1; 60 | float_7 c_79 = 1; 61 | 62 | static void_2 main() { 63 | //Label [5] 64 | //Variable [9] [32] Function [0] 65 | //Variable [43] [44] Function [0] 66 | //Variable [18] [54] Function [0] 67 | //Variable [9] [60] Function [0] 68 | //Variable [9] [62] Function [0] 69 | //Variable [10] [64] Function [0] 70 | //Load [8] [35] [34] [] 71 | //Store [32] [35] [] 72 | //Load [36] [39] [38] [] 73 | //SelectionMerge [41] Flatten 74 | //BranchConditional [39] [40] [73] [] 75 | // Label [40] 76 | // Store [44] [45] [] 77 | // Branch [46] 78 | // Label [46] 79 | // Load [42] [49] [44] [] 80 | // Load [42] [52] [51] [] 81 | // SLessThan [36] [53] [49] [52] 82 | // LoopMerge [47] Unroll 83 | // BranchConditional [53] [48] [47] [] 84 | // Label [48] 85 | // Load [42] [55] [44] [] 86 | // ConvertSToF [7] [56] [55] 87 | // Load [42] [57] [51] [] 88 | // ConvertSToF [7] [58] [57] 89 | // FDiv [7] [59] [56] [58] 90 | // Load [8] [61] [32] [] 91 | // Store [60] [61] [] 92 | // Load [8] [63] [34] [] 93 | // Store [62] [63] [] 94 | // Store [64] [59] [] 95 | // FunctionCall [11] [65] [16] [[60], [62], [64]] 96 | // Store [54] [65] [] 97 | // AccessChain [9] [67] [54] [[66]] 98 | // Load [8] [68] [67] [] 99 | // Load [8] [69] [32] [] 100 | // FAdd [8] [70] [69] [68] 101 | // Store [32] [70] [] 102 | // Load [42] [71] [44] [] 103 | // IAdd [42] [72] [71] [66] 104 | // Store [44] [72] [] 105 | // Branch [46] 106 | // Label [47] 107 | // Branch [41] 108 | // Label [73] 109 | // Load [42] [74] [51] [] 110 | // SGreaterThan [36] [75] [74] [45] 111 | // SelectionMerge [77] Flatten 112 | // BranchConditional [75] [76] [78] [] 113 | // Label [76] 114 | // Store [32] [21] [] 115 | // Branch [77] 116 | // Label [78] 117 | // Store [32] [80] [] 118 | // Branch [77] 119 | // Label [77] 120 | // Branch [41] 121 | //Label [41] 122 | //Load [8] [84] [32] [] 123 | //CompositeExtract [7] [85] [84] [0] 124 | //CompositeExtract [7] [86] [84] [1] 125 | //CompositeExtract [7] [87] [84] [2] 126 | //CompositeConstruct [81] [88] [[85], [86], [87], [79]] 127 | //Store [83] [88] [] 128 | //Branch [6] 129 | //Label [6] 130 | //Return 131 | } 132 | 133 | static lerp_res mlerp(vf3;vf3;f1;(p_v_float_7_3_8_9 a, p_v_float_7_3_8_9 b, p_float_7_10 t) { 134 | //Label [17] 135 | //Variable [18] [19] Function [0] 136 | //Load [8] [22] [13] [] 137 | //Load [8] [23] [14] [] 138 | //Load [8] [24] [13] [] 139 | //FSub [8] [25] [23] [24] 140 | //Load [7] [26] [15] [] 141 | //VectorTimesScalar [8] [27] [25] [26] 142 | //FAdd [8] [28] [22] [27] 143 | //CompositeConstruct [11] [29] [[21], [28]] 144 | //Store [19] [29] [] 145 | //Load [11] [30] [19] [] 146 | //ReturnValue [30] 147 | } 148 | 149 | -------------------------------------------------------------------------------- /data/complex.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/data/complex.frag.spv -------------------------------------------------------------------------------- /data/complex.frag.test: -------------------------------------------------------------------------------- 1 | shader: 2 | complex.frag 3 | cpp: 4 | complex.cpp 5 | run: 6 | true 7 | input: 8 | v f 3 color: 1, 0.5, 0.25 9 | i 32 iterations: 1 10 | b loopFlag: 1 11 | expect: 12 | v f 4 gl_FragColor -------------------------------------------------------------------------------- /data/glslangValidator.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/data/glslangValidator.exe -------------------------------------------------------------------------------- /data/light.frag: -------------------------------------------------------------------------------- 1 | #version 110 2 | varying vec2 uv; 3 | 4 | uniform vec2 texSize; 5 | uniform sampler2D testTex; 6 | 7 | struct Light { 8 | vec4 color; 9 | vec2 pos; 10 | }; 11 | 12 | uniform Light light; 13 | 14 | void main() { 15 | vec4 col = texture2D(testTex, uv); 16 | col.rgb = col.rbr; 17 | 18 | float lightDist = distance(uv, light.pos); 19 | float intensity = clamp(1.0 - (lightDist / light.color.a), 0.0, 1.0); 20 | 21 | gl_FragColor.rgb = col.rgb + pow(light.color.rgb * intensity, vec3(2.0, 2.0, 2.0)); 22 | gl_FragColor.a = 1.0; 23 | } -------------------------------------------------------------------------------- /data/light.frag.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Version: 99 3 | Generator Magic: 85590203 4 | ID Bound: 68 5 | Instruction Schema: 0 6 | ================================================= 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "GLSL.std.450.h" 13 | 14 | 15 | // Predefined types: 16 | // ================================================= 17 | typedef double float64; 18 | typedef float float32; 19 | typedef uint8_t uint8; 20 | typedef uint16_t uint16; 21 | typedef uint32_t uint32; 22 | typedef uint64_t uint64; 23 | typedef int8_t int8; 24 | typedef int16_t int16; 25 | typedef int32_t int32; 26 | typedef int64_t int64; 27 | // ================================================= 28 | 29 | typedef void void_2; 30 | typedef float32 float_7; 31 | struct v_float_7_4_8 { 32 | float_7 v[4]; 33 | }; 34 | typedef v_float_7_4_8* p_v_float_7_4_8_9; 35 | typedef * p__13; 36 | struct v_float_7_2_16 { 37 | float_7 v[2]; 38 | }; 39 | typedef v_float_7_2_16* p_v_float_7_2_16_17; 40 | struct v_float_7_3_22 { 41 | float_7 v[3]; 42 | }; 43 | typedef float_7* p_float_7_26; 44 | struct Light { 45 | v_float_7_4_8 color; 46 | v_float_7_2_16 color; 47 | }; 48 | typedef Light* p_Light_30; 49 | typedef int32 int_32; 50 | typedef v_float_7_2_16* p_v_float_7_2_16_34; 51 | typedef v_float_7_4_8* p_v_float_7_4_8_42; 52 | typedef v_float_7_4_8* p_v_float_7_4_8_50; 53 | 54 | static p__13 testTex; 55 | static p_v_float_7_2_16_17 uv; 56 | static p_Light_30 light; 57 | static p_v_float_7_4_8_50 gl_FragColor; 58 | static p_v_float_7_2_16_34 texSize; 59 | 60 | int_32 c_33 = 1; 61 | float_7 c_39 = 1; 62 | int_32 c_41 = 0; 63 | float_7 c_48 = 0; 64 | float_7 c_59 = 2; 65 | 66 | static void_2 main() { 67 | // [5] = Label 68 | // [9] = Variable [10(col)] Function [0] 69 | // [26] = Variable [27(lightDist)] Function [0] 70 | // [26] = Variable [38(intensity)] Function [0] 71 | // [12] = Load [15] [14(testTex)] [] 72 | // [16] = Load [19] [18(uv)] [] 73 | // [8] = ImageSampleImplicitLod [20] [15] [19] [] 74 | // [10(col)] = Store [20] [] 75 | // [8] = Load [21] [10(col)] [] 76 | // [22] = VectorShuffle [23] [21] [21] [0, 2, 0] 77 | // [8] = Load [24] [10(col)] [] 78 | // [8] = VectorShuffle [25] [24] [23] [4, 5, 6, 3] 79 | // [10(col)] = Store [25] [] 80 | // [16] = Load [28] [18(uv)] [] 81 | // [34] = AccessChain [35] [31(light)] [[33]] 82 | // [16] = Load [36] [35] [] 83 | // [7] = ExtInst [37] [1] 66 [[28], [36]] 84 | // [27(lightDist)] = Store [37] [] 85 | // [7] = Load [40] [27(lightDist)] [] 86 | // [42] = AccessChain [43] [31(light)] [[41]] 87 | // [8] = Load [44] [43] [] 88 | // [7] = CompositeExtract [45] [44] [3] 89 | // [7] = FDiv [46] [40] [45] 90 | // [7] = FSub [47] [39] [46] 91 | // [7] = ExtInst [49] [1] 43 [[47], [48], [39]] 92 | // [38(intensity)] = Store [49] [] 93 | // [8] = Load [52] [10(col)] [] 94 | // [22] = VectorShuffle [53] [52] [52] [0, 1, 2] 95 | // [42] = AccessChain [54] [31(light)] [[41]] 96 | // [8] = Load [55] [54] [] 97 | // [22] = VectorShuffle [56] [55] [55] [0, 1, 2] 98 | // [7] = Load [57] [38(intensity)] [] 99 | // [22] = VectorTimesScalar [58] [56] [57] 100 | // [22] = ExtInst [61] [1] 26 [[58], [60]] 101 | // [22] = FAdd [62] [53] [61] 102 | // [8] = Load [63] [51(gl_FragColor)] [] 103 | // [8] = VectorShuffle [64] [63] [62] [4, 5, 6, 3] 104 | // [51(gl_FragColor)] = Store [64] [] 105 | // [8] = Load [65] [51(gl_FragColor)] [] 106 | // [8] = CompositeInsert [66] [39] [65] [3] 107 | // [51(gl_FragColor)] = Store [66] [] 108 | // [6] = Branch 109 | // [6] = Label 110 | //Return 111 | } 112 | 113 | -------------------------------------------------------------------------------- /data/light.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/data/light.frag.spv -------------------------------------------------------------------------------- /data/light.frag.txt: -------------------------------------------------------------------------------- 1 | Version: 99 2 | Generator Magic: 85590203 3 | ID Bound: 68 4 | Instruction Schema: 0 5 | ================================================= 6 | 0: Source GLSL 110 7 | 1: Capability Shader 8 | 2: ExtInstImport [1] GLSL.std.450 9 | 3: MemoryModel Logical GLSL450 10 | 4: EntryPoint Fragment [4] main 11 | 5: ExecutionMode [4] OriginLowerLeft [] 12 | 6: Name [4] main 13 | 7: Name [10] col 14 | 8: Name [14] testTex 15 | 9: Name [18] uv 16 | 10: Name [27] lightDist 17 | 11: Name [29] Light 18 | 12: MemberName [29] 0 color 19 | 13: MemberName [29] 1 pos 20 | 14: Name [31] light 21 | 15: Name [38] intensity 22 | 16: Name [51] gl_FragColor 23 | 17: Name [67] texSize 24 | 18: Decorate [18] Smooth [] 25 | 19: Decorate [51] BuiltIn [21] 26 | 20: Decorate [67] NoStaticUse [] 27 | 21: TypeVoid [2] 28 | 22: TypeFunction [3] [2] [] 29 | 23: TypeFloat [7] 32 30 | 24: TypeVector [8] [7] 4 31 | 25: TypePointer [9] Function [8] 32 | 26: TypeImage [11] [7] 2D 0 0 0 1 Unknown [] 33 | 27: TypeSampledImage [12] [11] 34 | 28: TypePointer [13] UniformConstant [12] 35 | 29: Variable [13] [14] UniformConstant [0] 36 | 30: TypeVector [16] [7] 2 37 | 31: TypePointer [17] Input [16] 38 | 32: Variable [17] [18] Input [0] 39 | 33: TypeVector [22] [7] 3 40 | 34: TypePointer [26] Function [7] 41 | 35: TypeStruct [29] [[8], [16]] 42 | 36: TypePointer [30] UniformConstant [29] 43 | 37: Variable [30] [31] UniformConstant [0] 44 | 38: TypeInt [32] 32 1 45 | 39: Constant [32] [33] [1] 46 | 40: TypePointer [34] UniformConstant [16] 47 | 41: Constant [7] [39] [1065353216] 48 | 42: Constant [32] [41] [0] 49 | 43: TypePointer [42] UniformConstant [8] 50 | 44: Constant [7] [48] [0] 51 | 45: TypePointer [50] Output [8] 52 | 46: Variable [50] [51] Output [0] 53 | 47: Constant [7] [59] [1073741824] 54 | 48: ConstantComposite [22] [60] [[59], [59], [59]] 55 | 49: Variable [34] [67] UniformConstant [0] 56 | 50: Function [2] [4] Inline [3] 57 | 51: Label [5] 58 | 52: Variable [9] [10] Function [0] 59 | 53: Variable [26] [27] Function [0] 60 | 54: Variable [26] [38] Function [0] 61 | 55: Load [12] [15] [14] [] 62 | 56: Load [16] [19] [18] [] 63 | 57: ImageSampleImplicitLod [8] [20] [15] [19] [] 64 | 58: Store [10] [20] [] 65 | 59: Load [8] [21] [10] [] 66 | 60: VectorShuffle [22] [23] [21] [21] [0, 2, 0] 67 | 61: Load [8] [24] [10] [] 68 | 62: VectorShuffle [8] [25] [24] [23] [4, 5, 6, 3] 69 | 63: Store [10] [25] [] 70 | 64: Load [16] [28] [18] [] 71 | 65: AccessChain [34] [35] [31] [[33]] 72 | 66: Load [16] [36] [35] [] 73 | 67: ExtInst [7] [37] [1] 66 [[28], [36]] 74 | 68: Store [27] [37] [] 75 | 69: Load [7] [40] [27] [] 76 | 70: AccessChain [42] [43] [31] [[41]] 77 | 71: Load [8] [44] [43] [] 78 | 72: CompositeExtract [7] [45] [44] [3] 79 | 73: FDiv [7] [46] [40] [45] 80 | 74: FSub [7] [47] [39] [46] 81 | 75: ExtInst [7] [49] [1] 43 [[47], [48], [39]] 82 | 76: Store [38] [49] [] 83 | 77: Load [8] [52] [10] [] 84 | 78: VectorShuffle [22] [53] [52] [52] [0, 1, 2] 85 | 79: AccessChain [42] [54] [31] [[41]] 86 | 80: Load [8] [55] [54] [] 87 | 81: VectorShuffle [22] [56] [55] [55] [0, 1, 2] 88 | 82: Load [7] [57] [38] [] 89 | 83: VectorTimesScalar [22] [58] [56] [57] 90 | 84: ExtInst [22] [61] [1] 26 [[58], [60]] 91 | 85: FAdd [22] [62] [53] [61] 92 | 86: Load [8] [63] [51] [] 93 | 87: VectorShuffle [8] [64] [63] [62] [4, 5, 6, 3] 94 | 88: Store [51] [64] [] 95 | 89: Load [8] [65] [51] [] 96 | 90: CompositeInsert [8] [66] [39] [65] [3] 97 | 91: Store [51] [66] [] 98 | 92: Branch [6] 99 | 93: Label [6] 100 | 94: Return 101 | 95: FunctionEnd 102 | -------------------------------------------------------------------------------- /data/sampler.frag: -------------------------------------------------------------------------------- 1 | #version 110 2 | varying vec2 uv; 3 | uniform sampler2D testTex; 4 | 5 | void main() { 6 | vec4 col = texture2D(testTex, uv); 7 | col.rgb = col.rbr; 8 | gl_FragColor = col; 9 | gl_FragColor.a = 1.0; 10 | } -------------------------------------------------------------------------------- /data/sampler.frag.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Version: 99 3 | Generator Magic: 85590203 4 | ID Bound: 31 5 | Instruction Schema: 0 6 | ================================================= 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "GLSL.std.450.h" 13 | 14 | 15 | // Predefined types: 16 | // ================================================= 17 | typedef double float64; 18 | typedef float float32; 19 | typedef uint8_t uint8; 20 | typedef uint16_t uint16; 21 | typedef uint32_t uint32; 22 | typedef uint64_t uint64; 23 | typedef int8_t int8; 24 | typedef int16_t int16; 25 | typedef int32_t int32; 26 | typedef int64_t int64; 27 | // ================================================= 28 | 29 | typedef void void_2; 30 | typedef float32 float_7; 31 | struct v_float_7_4_8 { 32 | float_7 v[4]; 33 | }; 34 | typedef v_float_7_4_8* p_v_float_7_4_8_9; 35 | typedef * p__12; 36 | struct v_float_7_2_15 { 37 | float_7 v[2]; 38 | }; 39 | typedef v_float_7_2_15* p_v_float_7_2_15_16; 40 | struct v_float_7_3_21 { 41 | float_7 v[3]; 42 | }; 43 | typedef v_float_7_4_8* p_v_float_7_4_8_25; 44 | 45 | static p__12 testTex; 46 | static p_v_float_7_2_15_16 uv; 47 | static p_v_float_7_4_8_25 gl_FragColor; 48 | 49 | float_7 c_28 = 1; 50 | 51 | static void_2 main() { 52 | //Label [5] 53 | //Variable [9] [10] Function [0] 54 | //Load [11] [14] [13] [] 55 | //Load [15] [18] [17] [] 56 | //TextureSample [8] [19] [14] [18] [0] 57 | //Store [10] [19] [] 58 | //Load [8] [20] [10] [] 59 | //VectorShuffle [21] [22] [20] [20] [, 0, 20] 60 | //Load [8] [23] [10] [] 61 | //VectorShuffle [8] [24] [23] [22] [, 4, 5, 63] 62 | //Store [10] [24] [] 63 | //Load [8] [27] [10] [] 64 | //Store [26] [27] [] 65 | //Load [8] [29] [26] [] 66 | //CompositeInsert [8] [30] [28] [29] [3] 67 | //Store [26] [30] [] 68 | //Branch [6] 69 | //Label [6] 70 | //Return 71 | } 72 | 73 | -------------------------------------------------------------------------------- /data/sampler.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/data/sampler.frag.spv -------------------------------------------------------------------------------- /data/testout.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/data/testout.bmp -------------------------------------------------------------------------------- /ext/cygglsl.std.450.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/ext/cygglsl.std.450.dll -------------------------------------------------------------------------------- /ext/glsl.std.450.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/ext/glsl.std.450.dll -------------------------------------------------------------------------------- /ext/libglsl.std.450.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daseyb/otherside/1d394e32d93aaecf3cb2eaf7baecb814c62075a4/ext/libglsl.std.450.so -------------------------------------------------------------------------------- /src/ext/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (ext C CXX) 3 | 4 | # We need C++ 11 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED on) 7 | 8 | add_subdirectory(glsl.std.450) 9 | -------------------------------------------------------------------------------- /src/ext/glsl.std.450/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (glsl.std.450 C CXX) 3 | 4 | # We need C++ 11 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED on) 7 | 8 | add_subdirectory(./../../shared shared) 9 | 10 | include_directories(${SHARED_LIB_INCLUDE_DIR}) 11 | 12 | set(SRCS glsl.std.450.cpp) 13 | add_library(glsl.std.450 MODULE ${SRCS}) 14 | target_link_libraries(glsl.std.450 shared) 15 | 16 | set_property(TARGET glsl.std.450 PROPERTY CXX_STANDARD 11) 17 | 18 | add_custom_command(TARGET glsl.std.450 POST_BUILD 19 | COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_SOURCE_DIR}/ext/ 20 | ) 21 | 22 | file(COPY DESTINATION ${CMAKE_SOURCE_DIR}/ext) -------------------------------------------------------------------------------- /src/ext/glsl.std.450/glsl.std.450.cpp: -------------------------------------------------------------------------------- 1 | #include "vm.h" 2 | #include 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #define ONE_ARG_OP(func, type) \ 10 | assert(valueCount == 1); \ 11 | return vm->DoOp(resultTypeId, [](Value val) {return func(*(type*)val.Memory); }, values[0]); \ 12 | 13 | #define TWO_ARG_OP(func, type) \ 14 | assert(valueCount == 2); \ 15 | return vm->DoOp(resultTypeId, [](Value op1, Value op2) {return func(*(type*)op1.Memory, *(type*)op2.Memory); }, values[0], values[1]); \ 16 | 17 | #define THREE_ARG_OP(func, type) \ 18 | assert(valueCount == 3); \ 19 | return vm->DoOp(resultTypeId, [](Value op1, Value op2, Value op3) {return func(*(type*)op1.Memory, *(type*)op2.Memory, *(type*)op3.Memory); }, values[0], values[1], values[2]); \ 20 | 21 | 22 | #define ONE_ARG_OP_F(func) ONE_ARG_OP(func, float) 23 | #define TWO_ARG_OP_F(func) TWO_ARG_OP(func, float) 24 | #define THREE_ARG_OP_F(func) TWO_ARG_OP(func, float) 25 | 26 | #define ONE_ARG_OP_S(func) ONE_ARG_OP(func, int) 27 | #define TWO_ARG_OP_S(func) TWO_ARG_OP(func, int) 28 | #define THREE_ARG_OP_S(func) TWO_ARG_OP(func, int) 29 | 30 | #define THREE_ARG_OP_D(func) \ 31 | assert(valueCount == 3); \ 32 | return vm->DoOp(resultTypeId, func, values[0], values[1], values[2]); \ 33 | 34 | EXT_INST_FUNC(round_ext) { 35 | ONE_ARG_OP_F(roundf); 36 | }; 37 | 38 | EXT_INST_FUNC(roundEven_ext) { 39 | return values[0]; 40 | }; 41 | 42 | EXT_INST_FUNC(trunc_ext) { 43 | ONE_ARG_OP_F(trunc); 44 | }; 45 | 46 | EXT_INST_FUNC(fabs_ext) { 47 | ONE_ARG_OP_F(fabsf); 48 | }; 49 | 50 | EXT_INST_FUNC(sabs_ext) { 51 | ONE_ARG_OP_S([](int s) { return s < 0 ? -s : s; }); 52 | }; 53 | 54 | EXT_INST_FUNC(fsign_ext) { 55 | ONE_ARG_OP_F([](float f) { return signbit(f) ? 0 : 1;}) 56 | }; 57 | 58 | EXT_INST_FUNC(ssign_ext) { 59 | ONE_ARG_OP_S([](int s) { return s < 0 ? 0 : 1;}) 60 | }; 61 | 62 | EXT_INST_FUNC(floor_ext) { 63 | ONE_ARG_OP_F(floorf); 64 | }; 65 | 66 | EXT_INST_FUNC(ceil_ext) { 67 | ONE_ARG_OP_F(ceilf); 68 | }; 69 | 70 | EXT_INST_FUNC(fract_ext) { 71 | return values[0]; 72 | }; 73 | 74 | EXT_INST_FUNC(radians_ext) { 75 | return values[0]; 76 | }; 77 | 78 | EXT_INST_FUNC(degrees_ext) { 79 | return values[0]; 80 | }; 81 | 82 | EXT_INST_FUNC(sin_ext) { 83 | ONE_ARG_OP_F(sinf); 84 | }; 85 | 86 | EXT_INST_FUNC(cos_ext) { 87 | ONE_ARG_OP_F(cosf); 88 | }; 89 | 90 | EXT_INST_FUNC(tan_ext) { 91 | ONE_ARG_OP_F(tanf); 92 | }; 93 | 94 | EXT_INST_FUNC(asin_ext) { 95 | ONE_ARG_OP_F(asinf); 96 | }; 97 | 98 | EXT_INST_FUNC(acos_ext) { 99 | ONE_ARG_OP_F(acosf); 100 | }; 101 | 102 | EXT_INST_FUNC(atan_ext) { 103 | ONE_ARG_OP_F(atanf); 104 | }; 105 | 106 | EXT_INST_FUNC(sinh_ext) { 107 | ONE_ARG_OP_F(sinhf); 108 | } 109 | 110 | EXT_INST_FUNC(cosh_ext) { 111 | ONE_ARG_OP_F(coshf); 112 | } 113 | 114 | EXT_INST_FUNC(tanh_ext) { 115 | ONE_ARG_OP_F(tanhf); 116 | } 117 | 118 | EXT_INST_FUNC(asinh_ext) { 119 | ONE_ARG_OP_F(asinhf); 120 | } 121 | 122 | EXT_INST_FUNC(acosh_ext) { 123 | ONE_ARG_OP_F(acoshf); 124 | } 125 | 126 | EXT_INST_FUNC(atanh_ext) { 127 | ONE_ARG_OP_F(atanhf); 128 | } 129 | 130 | EXT_INST_FUNC(atan2_ext) { 131 | TWO_ARG_OP_F(atan2f); 132 | } 133 | 134 | EXT_INST_FUNC(pow_ext) { 135 | assert(valueCount == 2); 136 | Value toPow = values[0]; 137 | Value power = values[1]; 138 | 139 | if (vm->IsVectorType(power.TypeId)) { 140 | return vm->DoOp(resultTypeId, 141 | [](Value op1, Value op2) { return powf(*(float*)op1.Memory, *(float*)op2.Memory); }, 142 | toPow, power); 143 | } else { 144 | return vm->DoOp(resultTypeId, 145 | [power](Value op1) { return powf(*(float*)op1.Memory, *(float*)power.Memory); }, 146 | toPow); 147 | } 148 | } 149 | 150 | EXT_INST_FUNC(exp_ext) { ONE_ARG_OP_F(expf); } 151 | EXT_INST_FUNC(log_ext) { ONE_ARG_OP_F(logf); } 152 | EXT_INST_FUNC(exp2_ext) { ONE_ARG_OP_F(exp2f); } 153 | EXT_INST_FUNC(log2_ext) { ONE_ARG_OP_F(log2f); } 154 | EXT_INST_FUNC(sqrt_ext) { ONE_ARG_OP_F(sqrtf); } 155 | EXT_INST_FUNC(inverseSqrt_ext) { ONE_ARG_OP_F([](float f) {return 1.0f / sqrtf(f);}) } 156 | 157 | EXT_INST_FUNC(determinant_ext) { return values [0]; } 158 | EXT_INST_FUNC(matrixInverse_ext) { return values [0]; } 159 | 160 | EXT_INST_FUNC(modf_ext) { TWO_ARG_OP_F(fmodf); } 161 | 162 | EXT_INST_FUNC(modf_struct_ext) { TWO_ARG_OP_F(fmodf); } 163 | 164 | EXT_INST_FUNC(fmin_ext) { return values [0]; } 165 | EXT_INST_FUNC(umin_ext) { return values [0]; } 166 | EXT_INST_FUNC(smin_ext) { return values [0]; } 167 | 168 | EXT_INST_FUNC(fmax_ext) { return values [0]; } 169 | EXT_INST_FUNC(umax_ext) { return values [0]; } 170 | EXT_INST_FUNC(smax_ext) { return values [0]; } 171 | 172 | EXT_INST_FUNC(fclamp_ext) { THREE_ARG_OP_D(Clamp); } 173 | EXT_INST_FUNC(uclamp_ext) { THREE_ARG_OP_D(Clamp); } 174 | EXT_INST_FUNC(sclamp_ext) { THREE_ARG_OP_D(Clamp); } 175 | 176 | EXT_INST_FUNC(mix_ext) { return values [0]; } 177 | EXT_INST_FUNC(step_ext) { return values [0]; } 178 | EXT_INST_FUNC(smoothStep_ext) { return values [0]; } 179 | 180 | EXT_INST_FUNC(floatBitsToInt_ext) { return values [0]; } 181 | EXT_INST_FUNC(floatBitsToUint_ext) { return values [0]; } 182 | EXT_INST_FUNC(intBitsToFloat_ext) { return values [0]; } 183 | EXT_INST_FUNC(uintBitsToFloat_ext) { return values [0]; } 184 | 185 | EXT_INST_FUNC(fma_ext) { return values [0]; } 186 | EXT_INST_FUNC(frexp_ext) { return values [0]; } 187 | EXT_INST_FUNC(frexp_struct_ext) { return values [0]; } 188 | EXT_INST_FUNC(ldexp_ext) { return values [0]; } 189 | 190 | EXT_INST_FUNC(packSnorm4x8_ext) { return values [0]; } 191 | EXT_INST_FUNC(packUnorm4x8_ext) { return values [0]; } 192 | EXT_INST_FUNC(packSnorm2x16_ext) { return values [0]; } 193 | EXT_INST_FUNC(packUnorm2x16_ext) { return values [0]; } 194 | EXT_INST_FUNC(packHalf2x16_ext) { return values [0]; } 195 | EXT_INST_FUNC(packDouble2x32_ext) { return values [0]; } 196 | EXT_INST_FUNC(unpackSnorm2x16_ext) { return values [0]; } 197 | EXT_INST_FUNC(unpackUnorm2x16_ext) { return values [0]; } 198 | EXT_INST_FUNC(unpackHalf2x16_ext) { return values [0]; } 199 | EXT_INST_FUNC(unpackSnorm4x8_ext) { return values [0]; } 200 | EXT_INST_FUNC(unpackUnorm4x8_ext) { return values [0]; } 201 | EXT_INST_FUNC(unpackDouble2x32_ext) { return values [0]; } 202 | 203 | EXT_INST_FUNC(length_ext) { 204 | assert(valueCount == 1); 205 | Value a = values[0]; 206 | if (!vm->IsVectorType(a.TypeId)) { 207 | return vm->VmInit(resultTypeId, a.Memory); 208 | } 209 | 210 | uint32 elCount = vm->ElementCount(a.TypeId); 211 | float sum = 0; 212 | for (int i = 0; i < elCount; i++) { 213 | float val = *(float*)vm->IndexMemberValue(a, i).Memory; 214 | sum += val * val; 215 | } 216 | float res = sqrtf(sum); 217 | return vm->VmInit(resultTypeId, &res); 218 | } 219 | 220 | EXT_INST_FUNC(distance_ext) { 221 | assert(valueCount == 2); 222 | Value start = values[0]; 223 | Value end = values[1]; 224 | Value diff = vm->DoOp(start.TypeId, Sub, start, end); 225 | return length_ext(vm, resultTypeId, 1, &diff); 226 | } 227 | 228 | EXT_INST_FUNC(cross_ext) { return values [0]; } 229 | EXT_INST_FUNC(normalize_ext) { return values [0]; } 230 | EXT_INST_FUNC(faceForward_ext) { return values [0]; } 231 | EXT_INST_FUNC(reflect_ext) { return values [0]; } 232 | EXT_INST_FUNC(refract_ext) { return values [0]; } 233 | 234 | EXT_INST_FUNC(findILSB_ext) { return values [0]; } 235 | EXT_INST_FUNC(findSMSB_ext) { return values [0]; } 236 | EXT_INST_FUNC(findUMSB_ext) { return values [0]; } 237 | 238 | EXT_INST_FUNC(interpolateAtCentroid_ext) { return values [0]; } 239 | EXT_INST_FUNC(interpolateAtSample_ext) { return values [0]; } 240 | EXT_INST_FUNC(interpolateAtOffset_ext) { return values [0]; } 241 | 242 | EXT_INST_FUNC(addCarry_ext) { return values [0]; } 243 | EXT_INST_FUNC(subBorrow_ext) { return values [0]; } 244 | EXT_INST_FUNC(mulExtended_ext) { return values [0]; } 245 | 246 | 247 | ExtInstFunc* exports[]{ 248 | nullptr, 249 | 250 | round_ext, 251 | roundEven_ext, 252 | trunc_ext, 253 | fabs_ext, 254 | sabs_ext, 255 | fsign_ext, 256 | ssign_ext, 257 | floor_ext, 258 | ceil_ext, 259 | fract_ext, 260 | 261 | radians_ext, 262 | degrees_ext, 263 | sin_ext, 264 | cos_ext, 265 | tan_ext, 266 | asin_ext, 267 | acos_ext, 268 | atan_ext, 269 | sinh_ext, 270 | cosh_ext, 271 | tanh_ext, 272 | asinh_ext, 273 | acosh_ext, 274 | atanh_ext, 275 | atan2_ext, 276 | 277 | pow_ext, 278 | exp_ext, 279 | log_ext, 280 | exp2_ext, 281 | log2_ext, 282 | sqrt_ext, 283 | inverseSqrt_ext, 284 | 285 | determinant_ext, 286 | matrixInverse_ext, 287 | 288 | modf_ext, // second argument needs the OpVariable_ext, not an OpLoad 289 | modf_struct_ext, 290 | fmin_ext, 291 | umin_ext, 292 | smin_ext, 293 | fmax_ext, 294 | umax_ext, 295 | smax_ext, 296 | fclamp_ext, 297 | uclamp_ext, 298 | sclamp_ext, 299 | mix_ext, 300 | step_ext, 301 | smoothStep_ext, 302 | 303 | fma_ext, 304 | frexp_ext, 305 | frexp_struct_ext, 306 | ldexp_ext, 307 | 308 | packSnorm4x8_ext, 309 | packUnorm4x8_ext, 310 | packSnorm2x16_ext, 311 | packUnorm2x16_ext, 312 | packHalf2x16_ext, 313 | packDouble2x32_ext, 314 | unpackSnorm2x16_ext, 315 | unpackUnorm2x16_ext, 316 | unpackHalf2x16_ext, 317 | unpackSnorm4x8_ext, 318 | unpackUnorm4x8_ext, 319 | unpackDouble2x32_ext, 320 | 321 | length_ext, 322 | distance_ext, 323 | cross_ext, 324 | normalize_ext, 325 | faceForward_ext, 326 | reflect_ext, 327 | refract_ext, 328 | 329 | findILSB_ext, 330 | findSMSB_ext, 331 | findUMSB_ext, 332 | 333 | interpolateAtCentroid_ext, 334 | interpolateAtSample_ext, 335 | interpolateAtOffset_ext, 336 | 337 | addCarry_ext, 338 | subBorrow_ext, 339 | mulExtended_ext, 340 | }; 341 | 342 | EXT_EXPORT_TABLE_FUNC(exports) 343 | 344 | #ifdef __cplusplus 345 | } 346 | #endif 347 | -------------------------------------------------------------------------------- /src/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (otherside C CXX) 3 | 4 | # We need C++ 11 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED on) 7 | 8 | add_subdirectory(./../shared shared) 9 | 10 | include_directories(${CMAKE_SOURCE_DIR}/src/main) 11 | include_directories(${SHARED_LIB_INCLUDE_DIR}) 12 | 13 | set(SRCS parser.cpp validation.cpp codegen.cpp interpreted_vm.cpp) 14 | add_library(otherside STATIC ${SRCS}) 15 | 16 | add_executable(otherside_exe otherside_main.cpp) 17 | SET_TARGET_PROPERTIES ( otherside_exe PROPERTIES OUTPUT_NAME otherside) 18 | 19 | IF (WIN32) 20 | target_link_libraries(otherside_exe otherside shared) 21 | ELSE() 22 | target_link_libraries(otherside_exe otherside shared dl) 23 | ENDIF() 24 | 25 | add_test(NAME otherside_exe_end2end COMMAND otherside_exe -i data/light.frag.spv -o data/light.frag.cpp WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) 26 | -------------------------------------------------------------------------------- /src/main/codegen.cpp: -------------------------------------------------------------------------------- 1 | #include "codegen.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "parser_definitions.h" 7 | #include "lookups_gen.h" 8 | #include "parser.h" 9 | 10 | std::map ids; 11 | 12 | void startComment(std::stringstream* ss) { 13 | *ss << "/*" << std::endl; 14 | } 15 | 16 | void endComment(std::stringstream* ss) { 17 | *ss << "*/" << std::endl; 18 | } 19 | 20 | bool g_header(std::stringstream* ss, const Program& prog) { 21 | startComment(ss); 22 | *ss << "Version: " << prog.Version << std::endl; 23 | *ss << "Generator Magic: " << prog.GeneratorMagic << std::endl; 24 | *ss << "ID Bound: " << prog.IDBound << std::endl; 25 | *ss << "Instruction Schema: " << prog.InstructionSchema << std::endl; 26 | *ss << "=================================================" << std::endl; 27 | endComment(ss); 28 | return true; 29 | } 30 | 31 | bool g_imports(std::stringstream* ss, const Program& prog) { 32 | *ss << std::endl; 33 | *ss << "#include " << std::endl; 34 | *ss << "#include " << std::endl; 35 | *ss << "#include " << std::endl; 36 | *ss << "#include " << std::endl; 37 | 38 | for (auto inc : prog.ExtensionImports) { 39 | *ss << "#include \"" << inc.second.Name << ".h\"" << std::endl; 40 | } 41 | 42 | return true; 43 | } 44 | 45 | bool g_types(std::stringstream* ss, const Program& prog) { 46 | *ss << std::endl; 47 | *ss << "// Predefined types: " << std::endl; 48 | *ss << "// =================================================" << std::endl; 49 | *ss << "typedef double float64;" << std::endl; 50 | *ss << "typedef float float32;" << std::endl; 51 | *ss << "typedef uint8_t uint8;" << std::endl; 52 | *ss << "typedef uint16_t uint16;" << std::endl; 53 | *ss << "typedef uint32_t uint32;" << std::endl; 54 | *ss << "typedef uint64_t uint64;" << std::endl; 55 | *ss << "typedef int8_t int8;" << std::endl; 56 | *ss << "typedef int16_t int16;" << std::endl; 57 | *ss << "typedef int32_t int32;" << std::endl; 58 | *ss << "typedef int64_t int64;" << std::endl; 59 | *ss << "// =================================================" << std::endl; 60 | *ss << std::endl; 61 | 62 | for (auto type : prog.DefinedTypes) { 63 | std::stringstream idName; 64 | 65 | switch (type.second.Op) 66 | { 67 | case Op::OpTypeFloat: 68 | { 69 | STypeFloat* opFloat = (STypeFloat*)type.second.Memory; 70 | idName << "float" << opFloat->Width; 71 | break; 72 | } 73 | case Op::OpTypeBool: 74 | { 75 | STypeBool* opBool = (STypeBool*)type.second.Memory; 76 | idName << "bool"; 77 | break; 78 | } 79 | case Op::OpTypeInt: 80 | { 81 | STypeInt* opInt = (STypeInt*)type.second.Memory; 82 | std::stringstream baseType; 83 | if (opInt->Signedness == 0) idName << "u"; 84 | idName << "int" << opInt->Width; 85 | break; 86 | } 87 | case Op::OpTypeVoid: 88 | { 89 | STypeVoid* opBool = (STypeVoid*)type.second.Memory; 90 | idName << "void"; 91 | break; 92 | } 93 | case Op::OpTypePointer: 94 | { 95 | STypePointer* opPointer = (STypePointer*)type.second.Memory; 96 | idName << "p_" << ids[opPointer->TypeId]; 97 | *ss << "typedef " << ids[opPointer->TypeId] << "* " << idName.str() << ";" << std::endl; 98 | break; 99 | } 100 | case Op::OpTypeVector: 101 | { 102 | STypeVector* opVector = (STypeVector*)type.second.Memory; 103 | idName << "v_" << ids[opVector->ComponentTypeId] << "_" << opVector->ComponentCount; 104 | auto idNameStr = idName.str(); 105 | auto makeElementWiseOp = [opVector, idNameStr, ss](std::string op) { 106 | *ss << std::endl; 107 | *ss << " friend " << idNameStr << " operator"<< op << "(" << idNameStr << " a, const " << idNameStr << "& b) {" << std::endl; 108 | for (int i = 0; i < opVector->ComponentCount; i++) { 109 | *ss << " a.v[" << i << "] " << op << "= b.v[" << i << "];" << std::endl; 110 | } 111 | *ss << " return a;" << std::endl; 112 | *ss << " }" << std::endl; 113 | *ss << std::endl; 114 | }; 115 | 116 | *ss << "struct " << idName.str() << " {" << std::endl; 117 | *ss << " " << ids[opVector->ComponentTypeId] << " " << "v[" << opVector->ComponentCount << "];" << std::endl; 118 | makeElementWiseOp("+"); 119 | makeElementWiseOp("-"); 120 | makeElementWiseOp("*"); 121 | makeElementWiseOp("/"); 122 | *ss << "};" << std::endl; 123 | break; 124 | } 125 | case Op::OpTypeStruct: 126 | { 127 | STypeStruct* opStruct = (STypeStruct*)type.second.Memory; 128 | if (prog.Names.find(opStruct->ResultId) != prog.Names.end()) { 129 | idName << prog.Names.at(opStruct->ResultId).Name; 130 | } else { 131 | idName << "s_" << opStruct->ResultId; 132 | } 133 | 134 | *ss << "struct " << idName.str() << " {" << std::endl; 135 | for (uint32 i = 0; i < opStruct->MembertypeIdsCount; i++) { 136 | std::stringstream memberName; 137 | uint32 key = (opStruct->ResultId << 16) & i; 138 | if (prog.MemberNames.find(key) != prog.MemberNames.end()) { 139 | memberName << prog.MemberNames.at(key).Name; 140 | } 141 | else { 142 | memberName << "m_" << i; 143 | } 144 | 145 | *ss << " " << ids[opStruct->MembertypeIds[i]] << " " << memberName.str() << ";" << std::endl; 146 | } 147 | *ss << "};" << std::endl; 148 | break; 149 | } 150 | default: 151 | break; 152 | } 153 | 154 | ids.insert(std::pair(type.first, idName.str())); 155 | } 156 | 157 | return true; 158 | } 159 | 160 | void writeName(std::stringstream* name, const Program& prog, int id, const std::string& prefix) { 161 | if (prog.Names.find(id) != prog.Names.end()) { 162 | *name << prog.Names.at(id).Name; 163 | } 164 | else { 165 | *name << prefix << id; 166 | } 167 | } 168 | 169 | bool g_literal(std::stringstream* ss, const Program& prog, int typeId, int valuesCount, uint32* values) { 170 | assert(values); 171 | auto type = prog.DefinedTypes.at(typeId); 172 | 173 | switch (type.Op) 174 | { 175 | case Op::OpTypeFloat: { 176 | assert(valuesCount == 1 || valuesCount == 2); 177 | std::string fstring = ""; 178 | if (valuesCount == 1) { 179 | fstring = std::to_string(*(float*)values); 180 | } 181 | else if (valuesCount == 2) { 182 | fstring = std::to_string(*(double*)values); 183 | } 184 | 185 | *ss << fstring << "f"; 186 | 187 | break; 188 | } 189 | case Op::OpTypeInt: 190 | assert(valuesCount == 1 || valuesCount == 2); 191 | if (valuesCount == 1) { 192 | *ss << *(uint32*)values; 193 | } 194 | else if (valuesCount == 2) { 195 | *ss << *(uint64*)values; 196 | } 197 | break; 198 | case Op::OpTypeStruct: 199 | case Op::OpTypeVector: 200 | break; 201 | } 202 | 203 | return true; 204 | } 205 | 206 | bool g_constants(std::stringstream* ss, const Program& prog) { 207 | *ss << std::endl; 208 | for (auto constant : prog.Constants) { 209 | std::stringstream idName; 210 | 211 | switch (constant.second.Op) { 212 | case Op::OpConstant: { 213 | auto opConst = (SConstant*)constant.second.Memory; 214 | writeName(&idName, prog, opConst->ResultId, "c_"); 215 | *ss << "const " << ids[opConst->ResultTypeId] << " " << idName.str() << " = "; 216 | if (!g_literal(ss, prog, opConst->ResultTypeId, opConst->ValuesCount, opConst->Values)) { 217 | return false; 218 | } 219 | 220 | *ss << ";" << std::endl; 221 | break; 222 | } 223 | } 224 | 225 | ids.insert(std::pair(constant.first, idName.str())); 226 | } 227 | 228 | return true; 229 | } 230 | 231 | bool g_variable(std::stringstream* ss, SVariable* var, const Program& prog) { 232 | std::stringstream idName; 233 | if (prog.Names.find(var->ResultId) != prog.Names.end()) { 234 | idName << prog.Names.at(var->ResultId).Name; 235 | } else { 236 | idName << "var" << var->ResultId; 237 | } 238 | 239 | *ss << (var->StorageClass != StorageClass::Function ? "static " : "") << ids[var->ResultTypeId] << " " << idName.str(); 240 | 241 | ids.insert(std::pair(var->ResultId, idName.str())); 242 | return true; 243 | } 244 | 245 | bool g_variables(std::stringstream* ss, const Program& prog) { 246 | *ss << std::endl; 247 | 248 | for (auto var : prog.Variables) { 249 | g_variable(ss, &var.second, prog); 250 | *ss << ";" << std::endl; 251 | } 252 | 253 | return true; 254 | } 255 | 256 | void indent(char* indentStr) { 257 | int len = strlen(indentStr); 258 | indentStr[len] = ' '; 259 | indentStr[len + 1] = ' '; 260 | } 261 | 262 | 263 | void unindent(char* indentStr) { 264 | int len = strlen(indentStr); 265 | indentStr[len - 2] = 0; 266 | } 267 | 268 | bool g_block(std::stringstream* ops, std::stringstream* variableDefinitions, const Program& prog, const Function& func, const Block& block, char* indentStr) { 269 | 270 | bool doIndent = block.MergeInfo.Memory != nullptr; 271 | if (doIndent) { 272 | indent(indentStr); 273 | } 274 | 275 | for (auto op : block.Ops) { 276 | *ops << indentStr; 277 | switch (op.Op) { 278 | case Op::OpLabel: { 279 | SLabel* label = (SLabel*)op.Memory; 280 | ids[label->ResultId] = "label_" + std::to_string(label->ResultId); 281 | *ops << ids[label->ResultId] << ":"; 282 | break; 283 | } 284 | case Op::OpBranch: { 285 | SBranch* branch = (SBranch*)op.Memory; 286 | *ops << "goto label_" << branch->TargetLabelId << ";"; 287 | break; 288 | } 289 | case Op::OpBranchConditional: { 290 | SBranchConditional* branch = (SBranchConditional*)op.Memory; 291 | *ops << "if(" << ids[branch->ConditionId] << ") { " << "goto label_" << branch->TrueLabelId << "; }" << std::endl; 292 | *ops << indentStr << "else { goto label_" << branch->FalseLabelId << "; }"; 293 | break; 294 | } 295 | case Op::OpVariable: { 296 | SVariable* variable = (SVariable*)op.Memory; 297 | 298 | *variableDefinitions << " "; 299 | g_variable(variableDefinitions, variable, prog); 300 | auto resultTypeName = ids[variable->ResultTypeId]; 301 | *variableDefinitions << " = (" << resultTypeName 302 | << ")malloc(sizeof(" << resultTypeName.substr(2, resultTypeName.length() - 2) 303 | << "));" << std::endl; 304 | break; 305 | } 306 | case Op::OpReturn: { 307 | *ops << "return;"; 308 | break; 309 | } 310 | case Op::OpLoad: { 311 | SLoad* load = (SLoad*)op.Memory; 312 | ids[load->ResultId] = "var_" + std::to_string(load->ResultId); 313 | *variableDefinitions << " " << ids[load->ResultTypeId] << " " << ids[load->ResultId] << ";" << std::endl; 314 | *ops << ids[load->ResultId] << " = *" << ids[load->PointerId] << ";"; 315 | break; 316 | } 317 | case Op::OpStore: { 318 | SStore* store = (SStore*)op.Memory; 319 | *ops << "*" << ids[store->PointerId] << " = " << ids[store->ObjectId] << ";"; 320 | break; 321 | } 322 | case Op::OpSGreaterThan: { 323 | SSGreaterThan* greaterThan = (SSGreaterThan*)op.Memory; 324 | ids[greaterThan->ResultId] = "var_" + std::to_string(greaterThan->ResultId); 325 | *variableDefinitions << " bool " << ids[greaterThan->ResultId] << ";" << std::endl; 326 | *ops << ids[greaterThan->ResultId] << " = " << ids[greaterThan->Operand1Id] << " > " << ids[greaterThan->Operand2Id] << ";"; 327 | break; 328 | } 329 | case Op::OpSLessThan: { 330 | SSLessThan* lessThan = (SSLessThan*)op.Memory; 331 | ids[lessThan->ResultId] = "var_" + std::to_string(lessThan->ResultId); 332 | *variableDefinitions << " bool " << ids[lessThan->ResultId] << ";" << std::endl; 333 | *ops << ids[lessThan->ResultId] << " = " << ids[lessThan->Operand1Id] << " < " << ids[lessThan->Operand2Id] << ";"; 334 | break; 335 | } 336 | case Op::OpFAdd: 337 | case Op::OpIAdd: { 338 | SFAdd* fadd = (SFAdd*)op.Memory; 339 | ids[fadd->ResultId] = "var_" + std::to_string(fadd->ResultId); 340 | *variableDefinitions << " " << ids[fadd->ResultTypeId] << " " << ids[fadd->ResultId] << ";" << std::endl; 341 | *ops << ids[fadd->ResultId] << " = " << ids[fadd->Operand1Id] << " + " << ids[fadd->Operand2Id] << ";"; 342 | break; 343 | } 344 | case Op::OpCompositeExtract: { 345 | SCompositeExtract* ce = (SCompositeExtract*)op.Memory; 346 | ids[ce->ResultId] = "var_" + std::to_string(ce->ResultId); 347 | *variableDefinitions << " " << ids[ce->ResultTypeId] << " " << ids[ce->ResultId] << ";" << std::endl; 348 | *ops << ids[ce->ResultId] << " = " << ids[ce->CompositeId] << ".v[" << ce->Indexes[0] << "];"; 349 | break; 350 | } 351 | case Op::OpCompositeConstruct: { 352 | SCompositeConstruct* cc = (SCompositeConstruct*)op.Memory; 353 | ids[cc->ResultId] = "var_" + std::to_string(cc->ResultId); 354 | *variableDefinitions << " " << ids[cc->ResultTypeId] << " " << ids[cc->ResultId] << ";" << std::endl; 355 | *ops << ids[cc->ResultId] << " = {"; 356 | for (int i = 0; i < cc->ConstituentsIdsCount; i++) { 357 | *ops << ids[cc->ConstituentsIds[i]]; 358 | if (i < cc->ConstituentsIdsCount - 1) { 359 | *ops << ", "; 360 | } 361 | } 362 | *ops << "};"; 363 | break; 364 | } 365 | default: { 366 | *ops << "// " << writeOp(op, &prog); 367 | break; 368 | } 369 | } 370 | *ops << std::endl; 371 | } 372 | 373 | for (auto child : block.Children) { 374 | if (!g_block(ops, variableDefinitions, prog, func, func.Blocks.at(child), indentStr)) { 375 | return false; 376 | } 377 | } 378 | 379 | if (doIndent) { 380 | unindent(indentStr); 381 | } 382 | 383 | return true; 384 | } 385 | 386 | bool g_function(std::stringstream* ss, const Program& prog, const Function& func) { 387 | std::stringstream idName; 388 | if (prog.Names.find(func.Info.ResultId) != prog.Names.end()) { 389 | idName << "spv_" << prog.Names.at(func.Info.ResultId).Name; 390 | } else { 391 | idName << "spv_fun" << func.Info.ResultId; 392 | } 393 | 394 | *ss << ids[func.Info.ResultTypeId] << " " << idName.str() << "("; 395 | 396 | uint32 paramIndex = 0; 397 | for (auto param : func.Parameters) { 398 | std::stringstream paramName; 399 | if (prog.Names.find(param.ResultId) != prog.Names.end()) { 400 | paramName << prog.Names.at(param.ResultId).Name; 401 | } else { 402 | paramName << "param" << param.ResultId; 403 | } 404 | 405 | *ss << ids[param.ResultTypeId] << " " << paramName.str(); 406 | if (paramIndex + 1 < func.Parameters.size()) { 407 | *ss << ", "; 408 | } 409 | 410 | paramIndex++; 411 | } 412 | 413 | *ss << ")" << (func.Blocks.size() == 0 ? ";" : " {") << std::endl; 414 | 415 | if (func.Blocks.size() > 0) { 416 | char indentBuff[255]; 417 | memset(indentBuff, 0, 255); 418 | indent(indentBuff); 419 | 420 | std::stringstream opStream; 421 | std::stringstream variableStream; 422 | if (!g_block(&opStream, &variableStream, prog, func, func.Blocks.at(0), indentBuff)) { 423 | return false; 424 | } 425 | unindent(indentBuff); 426 | 427 | *ss << variableStream.str() << opStream.str(); 428 | 429 | *ss << "}" << std::endl; 430 | } 431 | 432 | *ss << std::endl; 433 | 434 | 435 | ids.insert(std::pair(func.Info.ResultId, idName.str())); 436 | return true; 437 | } 438 | 439 | bool g_functions(std::stringstream* ss, const Program& prog) { 440 | *ss << std::endl; 441 | 442 | for (auto var : prog.FunctionDeclarations) { 443 | if (!g_function(ss, prog, var.second)) { 444 | return false; 445 | } 446 | } 447 | 448 | for (auto var : prog.FunctionDefinitions) { 449 | if (!g_function(ss, prog, var.second)) { 450 | return false; 451 | } 452 | } 453 | 454 | return true; 455 | } 456 | 457 | bool genCode(std::stringstream* ss, const Program& prog) { 458 | if (!g_header(ss, prog)) { 459 | return false; 460 | } 461 | 462 | if (!g_imports(ss, prog)) { 463 | return false; 464 | } 465 | 466 | if (!g_types(ss, prog)) { 467 | return false; 468 | } 469 | 470 | if (!g_variables(ss, prog)) { 471 | return false; 472 | } 473 | 474 | if (!g_constants(ss, prog)) { 475 | return false; 476 | } 477 | 478 | if (!g_functions(ss, prog)) { 479 | return false; 480 | } 481 | 482 | 483 | return true; 484 | } 485 | 486 | 487 | bool genCode(const char* outFileName, const Program& prog) { 488 | std::stringstream out; 489 | if (!genCode(&out, prog)) { 490 | return false; 491 | } 492 | std::ofstream outFile; 493 | outFile.open(outFileName, std::ofstream::out); 494 | outFile << out.str(); 495 | outFile.close(); 496 | return true; 497 | } 498 | -------------------------------------------------------------------------------- /src/main/codegen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct Program; 5 | 6 | bool genCode(std::stringstream* ss, const Program& prog); 7 | 8 | bool genCode(const char* outFileName, const Program& prog); -------------------------------------------------------------------------------- /src/main/interpreted_vm.cpp: -------------------------------------------------------------------------------- 1 | #include "interpreted_vm.h" 2 | #include "parser.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) // note the underscore: without it, it's not msdn official! 8 | #include 9 | #define LOAD_LIBRARY(path) LoadLibrary(path) 10 | #define LOAD_SYMBOL GetProcAddress 11 | #define LIBRARY_EXT ".dll" 12 | 13 | #ifdef __CYGWIN__ 14 | #define LIB_NAME(name) ("cyg" + name) 15 | #else 16 | #define LIB_NAME(name) name 17 | #endif 18 | 19 | #define LIB_ERROR "" 20 | #define HANDLE_TYPE HINSTANCE 21 | #elif defined(__unix__) || defined(__linux__) || defined(__APPLE__) // all unices, not all compilers 22 | #include 23 | #define LOAD_LIBRARY(path) dlopen(path, RTLD_LAZY) 24 | #define LOAD_SYMBOL dlsym 25 | #define LIBRARY_EXT ".so" 26 | #define LIB_NAME(name) ("lib" + name) 27 | #define LIB_ERROR dlerror() 28 | #define HANDLE_TYPE void* 29 | #define TEXT(txt) txt 30 | #endif 31 | 32 | 33 | byte* InterpretedVM::VmAlloc(uint32 typeId) { 34 | uint32 compositeSize = GetTypeByteSize(typeId); 35 | byte* mem = (byte*)malloc(compositeSize); 36 | VmMemory.push_back(std::unique_ptr(mem)); 37 | return (byte*)mem; 38 | } 39 | 40 | Value InterpretedVM::IndexMemberValue(Value val, uint32 index) const { 41 | return IndexMemberValue(val.TypeId, val.Memory, index); 42 | } 43 | 44 | Value InterpretedVM::IndexMemberValue(uint32 typeId, byte* val, uint32 index) const { 45 | Value result; 46 | 47 | SOp compDef = prog.DefinedTypes.at(typeId); 48 | switch (compDef.Op) { 49 | case Op::OpTypeVector: { 50 | auto vec = (STypeVector*)compDef.Memory; 51 | uint32 offset = GetTypeByteSize(vec->ComponentTypeId) * index; 52 | result.TypeId = vec->ComponentTypeId; 53 | result.Memory = val + offset; 54 | break; 55 | } 56 | case Op::OpTypeStruct: { 57 | auto s = (STypeStruct*)compDef.Memory; 58 | result.TypeId = s->MembertypeIds[index]; 59 | result.Memory = val; 60 | for (uint32 i = 0; i < index; i++) { 61 | result.Memory += GetTypeByteSize(s->MembertypeIds[i]); 62 | } 63 | break; 64 | } 65 | case Op::OpTypePointer: { 66 | auto p = (STypePointer*)compDef.Memory; 67 | result = IndexMemberValue(p->TypeId, (byte*)*(void**)val, index); 68 | break; 69 | } 70 | default: 71 | result.Memory = nullptr; 72 | result.TypeId = 0; 73 | std::cout << "Not a composite type def: " << writeOp(compDef); 74 | } 75 | 76 | return result; 77 | } 78 | 79 | byte* InterpretedVM::GetPointerInComposite(uint32 typeId, byte* composite, uint32 indexCount, uint32* indices, uint32 currLevel = 0) const { 80 | if (currLevel == indexCount) { 81 | return composite; 82 | } 83 | 84 | uint32 index = indices[currLevel]; 85 | Value member = IndexMemberValue(typeId, composite, index); 86 | return GetPointerInComposite(member.TypeId, member.Memory, indexCount, indices, currLevel + 1); 87 | } 88 | 89 | SOp InterpretedVM::GetType(uint32 typeId) const { 90 | return prog.DefinedTypes.at(typeId); 91 | } 92 | 93 | bool InterpretedVM::IsVectorType(uint32 typeId) const { 94 | return GetType(typeId).Op == Op::OpTypeVector; 95 | } 96 | 97 | uint32 InterpretedVM::ElementCount(uint32 typeId) const { 98 | auto def = GetType(typeId); 99 | switch (def.Op) 100 | { 101 | case Op::OpTypeArray: { 102 | uint32 lengthId = ((STypeArray*)def.Memory)->LengthId; 103 | return *(uint32*)env.Values.at(lengthId).Memory; 104 | } 105 | case Op::OpTypeVector: { 106 | auto vec = (STypeVector*)def.Memory; 107 | return vec->ComponentCount; 108 | } 109 | default: 110 | return 0; 111 | } 112 | } 113 | 114 | Value InterpretedVM::VmInit(uint32 typeId, void* value) { 115 | Value val = { typeId, VmAlloc(typeId) }; 116 | if (value) { 117 | std::memcpy(val.Memory, value, GetTypeByteSize(val.TypeId)); 118 | } else { 119 | std::memset(val.Memory, 0, GetTypeByteSize(val.TypeId)); 120 | } 121 | return val; 122 | } 123 | 124 | Value InterpretedVM::Dereference(Value val) const { 125 | auto def = GetType(val.TypeId); 126 | if (def.Op != Op::OpTypePointer) { 127 | return val; 128 | } 129 | 130 | Value res { ((STypePointer*)def.Memory)->TypeId, (byte*)*(void**)val.Memory }; 131 | return res; 132 | } 133 | 134 | Value InterpretedVM::TextureSample(Value sampler, Value coord, Value bias, uint32 resultTypeId) { 135 | STypeSampledImage* samplerType =(STypeSampledImage*)GetType(sampler.TypeId).Memory; 136 | STypeImage* imageType = (STypeImage*)GetType(samplerType->ImageTypeId).Memory; 137 | assert(imageType->Sampled == 1); 138 | assert(ElementCount(coord.TypeId) >= (int)imageType->Dim + imageType->Arrayed); 139 | Sampler* s = ((Sampler*)sampler.Memory); 140 | 141 | uint32 index = 0; 142 | uint32 acc = 1; 143 | for (uint32 d = 0; d < s->DimCount; d++) { 144 | uint32 dd = s->Dims[d]; 145 | uint32 add = (uint32)(*(float*)IndexMemberValue(coord, d).Memory * (dd - 1) + 0.5f); 146 | switch (s->Wrap) { 147 | case WrapMode::WMClamp: add = add < 0 ? 0 : add > dd - 1 ? dd - 1 : add; break; 148 | case WrapMode::WMRepeat: add = add % dd; break; 149 | } 150 | index += add * acc; 151 | acc *= dd; 152 | } 153 | return VmInit(resultTypeId, ((float*)s->Data) + index * 4); 154 | } 155 | 156 | uint32 InterpretedVM::Execute(Function* func) { 157 | currentFunction = func; 158 | 159 | int pc = 0; 160 | 161 | for (;;) { 162 | auto op = func->Ops[pc]; 163 | switch (op.Op) { 164 | case Op::OpBranch: { 165 | auto branch = (SBranch*)op.Memory; 166 | pc = func->Labels.at(branch->TargetLabelId); 167 | break; 168 | } 169 | case Op::OpBranchConditional: { 170 | auto branch = (SBranchConditional*)op.Memory; 171 | uint32 labelID; 172 | Value val = Dereference(env.Values[branch->ConditionId]); 173 | if (*(bool*)val.Memory) { 174 | labelID = branch->TrueLabelId; 175 | } else { 176 | labelID = branch->FalseLabelId; 177 | } 178 | pc = func->Labels.at(labelID); 179 | break; 180 | } 181 | case Op::OpFunctionCall: { 182 | auto call = (SFunctionCall*)op.Memory; 183 | Function toCall = prog.FunctionDefinitions.at(call->FunctionId); 184 | for (uint32 i = 0; i < call->ArgumentIdsCount; i++) { 185 | env.Values[toCall.Parameters[i].ResultId] = Dereference(env.Values.at(call->ArgumentIds[i])); 186 | } 187 | uint32 resultId = Execute(&toCall); 188 | // This works since (uint32)-1 is never a valid ID. 189 | if (resultId == -1) { 190 | return -1; 191 | } 192 | currentFunction = func; 193 | env.Values[call->ResultId] = env.Values[resultId]; 194 | break; 195 | } 196 | case Op::OpExtInst: { 197 | auto extInst = (SExtInst*)op.Memory; 198 | Value* ops = new Value[extInst->OperandIdsCount]; 199 | for (uint32 i = 0; i < extInst->OperandIdsCount; i++) { 200 | ops[i] = Dereference(env.Values.at(extInst->OperandIds[i])); 201 | } 202 | 203 | ExtInstFunc* extFunc = env.Extensions[extInst->SetId][extInst->Instruction]; 204 | env.Values[extInst->ResultId] = extFunc(this, extInst->ResultTypeId, extInst->OperandIdsCount, ops); 205 | break; 206 | } 207 | case Op::OpConvertSToF: { 208 | auto convert = (SConvertSToF*)op.Memory; 209 | Value op1 = Dereference(env.Values[convert->SignedValueId]); 210 | env.Values[convert->ResultId] = DoOp(convert->ResultTypeId, Convert, op1); 211 | break; 212 | } 213 | case Op::OpFAdd: { 214 | auto add = (SFAdd*)op.Memory; 215 | Value op1 = Dereference(env.Values[add->Operand1Id]); 216 | Value op2 = Dereference(env.Values[add->Operand2Id]); 217 | env.Values[add->ResultId] = DoOp(add->ResultTypeId, Add, op1, op2); 218 | break; 219 | } 220 | case Op::OpIAdd: { 221 | auto add = (SIAdd*)op.Memory; 222 | Value op1 = Dereference(env.Values[add->Operand1Id]); 223 | Value op2 = Dereference(env.Values[add->Operand2Id]); 224 | env.Values[add->ResultId] = DoOp(add->ResultTypeId, Add, op1, op2); 225 | break; 226 | } 227 | case Op::OpFSub: { 228 | auto sub = (SFSub*)op.Memory; 229 | Value op1 = Dereference(env.Values[sub->Operand1Id]); 230 | Value op2 = Dereference(env.Values[sub->Operand2Id]); 231 | env.Values[sub->ResultId] = DoOp(sub->ResultTypeId, Sub, op1, op2); 232 | break; 233 | } 234 | case Op::OpISub: { 235 | auto sub = (SISub*)op.Memory; 236 | Value op1 = Dereference(env.Values[sub->Operand1Id]); 237 | Value op2 = Dereference(env.Values[sub->Operand2Id]); 238 | env.Values[sub->ResultId] = DoOp(sub->ResultTypeId, Sub, op1, op2); 239 | break; 240 | } 241 | case Op::OpFDiv: { 242 | auto div = (SFDiv*)op.Memory; 243 | Value op1 = Dereference(env.Values[div->Operand1Id]); 244 | Value op2 = Dereference(env.Values[div->Operand2Id]); 245 | env.Values[div->ResultId] = DoOp(div->ResultTypeId, Div, op1, op2); 246 | break; 247 | } 248 | case Op::OpFMul: { 249 | auto mul = (SFMul*)op.Memory; 250 | Value op1 = Dereference(env.Values[mul->Operand1Id]); 251 | Value op2 = Dereference(env.Values[mul->Operand2Id]); 252 | env.Values[mul->ResultId] = DoOp(mul->ResultTypeId, Mul, op1, op2); 253 | break; 254 | } 255 | case Op::OpIMul: { 256 | auto mul = (SFMul*)op.Memory; 257 | Value op1 = Dereference(env.Values[mul->Operand1Id]); 258 | Value op2 = Dereference(env.Values[mul->Operand2Id]); 259 | env.Values[mul->ResultId] = DoOp(mul->ResultTypeId, Mul, op1, op2); 260 | break; 261 | } 262 | case Op::OpVectorTimesScalar: { 263 | auto vts = (SVectorTimesScalar*)op.Memory; 264 | Value scalar = Dereference(env.Values[vts->ScalarId]); 265 | Value vector = Dereference(env.Values[vts->VectorId]); 266 | env.Values[vts->ResultId] = DoOp(vts->ResultTypeId, [scalar](Value comp) {return Mul(scalar, comp);}, vector); 267 | break; 268 | } 269 | case Op::OpSLessThan: { 270 | auto lessThan = (SSLessThan*)op.Memory; 271 | Value op1 = Dereference(env.Values[lessThan->Operand1Id]); 272 | Value op2 = Dereference(env.Values[lessThan->Operand2Id]); 273 | env.Values[lessThan->ResultId] = DoOp(lessThan->ResultTypeId, [](Value a, Value b) { return Cmp(a, b) == -1; }, op1, op2); 274 | break; 275 | } 276 | case Op::OpSGreaterThan: { 277 | auto greaterThan = (SSLessThan*)op.Memory; 278 | Value op1 = Dereference(env.Values[greaterThan->Operand1Id]); 279 | Value op2 = Dereference(env.Values[greaterThan->Operand2Id]); 280 | env.Values[greaterThan->ResultId] = DoOp(greaterThan->ResultTypeId, [](Value a, Value b) { return Cmp(a, b) == 1; }, op1, op2); 281 | break; 282 | } 283 | case Op::OpLoad: { 284 | auto load = (SLoad*)op.Memory; 285 | auto valueToLoad = env.Values.at(load->PointerId); 286 | env.Values[load->ResultId] = valueToLoad; 287 | break; 288 | } 289 | case Op::OpStore: { 290 | auto store = (SStore*)op.Memory; 291 | auto val = env.Values[store->ObjectId]; 292 | auto var = GetType(val.TypeId); 293 | if (var.Op == Op::OpTypePointer) { 294 | SetVariable(store->PointerId, val.Memory); 295 | } else { 296 | SetVariable(store->PointerId, &val.Memory); 297 | } 298 | break; 299 | } 300 | case Op::OpImageSampleImplicitLod: { 301 | auto sample = (SImageSampleImplicitLod*)op.Memory; 302 | auto sampledImage = Dereference(env.Values.at(sample->SampledImageId)); 303 | auto coord = Dereference(env.Values.at(sample->CoordinateId)); 304 | Value bias = { 0, 0 }; 305 | 306 | //TODO (Dario): Use sample->ImageOperandsIds 307 | env.Values[sample->ResultId] = TextureSample(sampledImage, coord, bias, sample->ResultTypeId); 308 | break; 309 | } 310 | case Op::OpLabel: 311 | case Op::OpSelectionMerge: 312 | case Op::OpLoopMerge: 313 | break; 314 | case Op::OpAccessChain: { 315 | auto access = (SAccessChain*)op.Memory; 316 | auto val = Dereference(env.Values.at(access->BaseId)); 317 | 318 | uint32* indices = new uint32[access->IndexesIdsCount]; 319 | for (int i = 0; i < access->IndexesIdsCount; i++) { 320 | indices[i] = *(uint32*)Dereference(env.Values[access->IndexesIds[i]]).Memory; 321 | } 322 | 323 | byte* mem = GetPointerInComposite(val.TypeId, val.Memory, access->IndexesIdsCount, indices); 324 | delete indices; 325 | 326 | Value res = VmInit(access->ResultTypeId, &mem); 327 | env.Values[access->ResultId] = res; 328 | break; 329 | } 330 | case Op::OpVectorShuffle: { 331 | auto vecShuffle = (SVectorShuffle*)op.Memory; 332 | auto vec1 = Dereference(env.Values.at(vecShuffle->Vector1Id)); 333 | auto vec2 = Dereference(env.Values.at(vecShuffle->Vector2Id)); 334 | 335 | auto result = VmInit(vecShuffle->ResultTypeId, nullptr); 336 | int v1ElCount = ElementCount(vec1.TypeId); 337 | for (uint32 i = 0; i < vecShuffle->ComponentsCount; i++) { 338 | int index = vecShuffle->Components[i]; 339 | Value toCopy; 340 | if (index < v1ElCount) { 341 | toCopy = vec1; 342 | } else { 343 | index -= v1ElCount; 344 | toCopy = vec2; 345 | } 346 | 347 | Value elToCopy = IndexMemberValue(toCopy, index); 348 | std::memcpy(IndexMemberValue(result, i).Memory, elToCopy.Memory, GetTypeByteSize(elToCopy.TypeId)); 349 | } 350 | 351 | env.Values[vecShuffle->ResultId] = result; 352 | break; 353 | } 354 | //TODO: FIX INDICES (NOT HIERARCHY!) 355 | case Op::OpCompositeExtract: { 356 | auto extract = (SCompositeExtract*)op.Memory; 357 | auto composite = env.Values[extract->CompositeId]; 358 | byte* mem = GetPointerInComposite(composite.TypeId, composite.Memory, extract->IndexesCount, extract->Indexes); 359 | Value val = { extract->ResultTypeId, VmAlloc(extract->ResultTypeId) }; 360 | std::memcpy(val.Memory, mem, GetTypeByteSize(val.TypeId)); 361 | env.Values[extract->ResultId] = val; 362 | break; 363 | } 364 | case Op::OpCompositeInsert: { 365 | auto insert = (SCompositeInsert*)op.Memory; 366 | auto composite = Dereference(env.Values[insert->CompositeId]); 367 | Value val = Dereference(env.Values.at(insert->ObjectId)); 368 | byte* mem = GetPointerInComposite(composite.TypeId, composite.Memory, insert->IndexesCount, insert->Indexes); 369 | std::memcpy(mem, val.Memory, GetTypeByteSize(val.TypeId)); 370 | env.Values[insert->ResultId] = VmInit(composite.TypeId, composite.Memory); 371 | break; 372 | } 373 | case Op::OpCompositeConstruct: { 374 | auto construct = (SCompositeConstruct*)op.Memory; 375 | Value val = { construct->ResultTypeId, VmAlloc(construct->ResultTypeId) }; 376 | env.Values[construct->ResultId] = val; 377 | byte* memPtr = val.Memory; 378 | for (int i = 0; i < construct->ConstituentsIdsCount; i++) { 379 | auto memVal = env.Values[construct->ConstituentsIds[i]]; 380 | uint32 memSize = GetTypeByteSize(memVal.TypeId); 381 | std::memcpy(memPtr, memVal.Memory, memSize); 382 | memPtr += memSize; 383 | } 384 | assert(memPtr - val.Memory == GetTypeByteSize(construct->ResultTypeId)); 385 | break; 386 | } 387 | case Op::OpVariable: { 388 | auto var = (SVariable*)op.Memory; 389 | Value val = { var->ResultTypeId, VmAlloc(var->ResultTypeId) }; 390 | if (var->InitializerId) { 391 | std::memcpy(val.Memory, env.Values[var->InitializerId].Memory, GetTypeByteSize(val.TypeId)); 392 | } 393 | else { 394 | memset(val.Memory, 0, GetTypeByteSize(val.TypeId)); 395 | } 396 | env.Values[var->ResultId] = val; 397 | break; 398 | } 399 | case Op::OpReturnValue: { 400 | auto ret = (SReturnValue*)op.Memory; 401 | return ret->ValueId; 402 | } 403 | case Op::OpReturn: 404 | return 0; 405 | default: 406 | std::cout << "Unimplemented operation: " << writeOp(op); 407 | return -1; 408 | } 409 | 410 | pc++; 411 | } 412 | } 413 | 414 | void* InterpretedVM::ReadVariable(uint32 id) const { 415 | auto var = prog.Variables.at(id); 416 | if (env.Values.find(var.ResultId) == env.Values.end()) { 417 | return nullptr; 418 | } 419 | return env.Values[var.ResultId].Memory; 420 | } 421 | 422 | void* InterpretedVM::ReadVariable(std::string name) const { 423 | for (auto& nameOp : prog.Names) { 424 | if (nameOp.second.Name == name) { 425 | return ReadVariable(nameOp.second.TargetId); 426 | } 427 | } 428 | return nullptr; 429 | } 430 | 431 | bool InterpretedVM::SetVariable(uint32 id, void* value) { 432 | SVariable var; 433 | 434 | if (currentFunction && currentFunction->Variables.find(id) != currentFunction->Variables.end()) { 435 | var = currentFunction->Variables.at(id); 436 | } else { 437 | var = prog.Variables.at(id); 438 | } 439 | 440 | if (env.Values.find(var.ResultId) == env.Values.end()) { 441 | Value val = { var.ResultTypeId, VmAlloc(var.ResultTypeId) }; 442 | if (value) { 443 | std::memcpy(val.Memory, value, GetTypeByteSize(val.TypeId)); 444 | } else { 445 | memset(val.Memory, 0, GetTypeByteSize(val.TypeId)); 446 | } 447 | env.Values[var.ResultId] = val; 448 | } else { 449 | Value val = env.Values[var.ResultId]; 450 | std::memcpy(val.Memory, value, GetTypeByteSize(val.TypeId)); 451 | } 452 | return true; 453 | } 454 | 455 | bool InterpretedVM::SetVariable(std::string name, void* value) { 456 | for (auto& nameOp : prog.Names) { 457 | if (nameOp.second.Name == name) { 458 | return SetVariable(nameOp.second.TargetId, value); 459 | } 460 | } 461 | return false; 462 | } 463 | 464 | uint32 InterpretedVM::GetTypeByteSize(uint32 typeId) const { 465 | if (TypeByteSizes.find(typeId) != TypeByteSizes.end()) { 466 | return TypeByteSizes.at(typeId); 467 | } 468 | 469 | auto definedType = prog.DefinedTypes.at(typeId); 470 | uint32 size = 0; 471 | 472 | switch (definedType.Op) 473 | { 474 | case Op::OpTypeArray: { 475 | auto arr = (STypeArray*)definedType.Memory; 476 | size = GetTypeByteSize(size) * *(uint32*)env.Values[arr->LengthId].Memory; 477 | break; 478 | } 479 | case Op::OpTypeInt: { 480 | auto i = (STypeInt*)definedType.Memory; 481 | assert(i->Width % 8 == 0); 482 | size = i->Width / 8; 483 | break; 484 | } 485 | case Op::OpTypeFloat: { 486 | auto f = (STypeFloat*)definedType.Memory; 487 | assert(f->Width % 8 == 0); 488 | size = f->Width / 8; 489 | break; 490 | } 491 | case Op::OpTypeBool: { 492 | size = sizeof(bool); 493 | break; 494 | } 495 | case Op::OpTypePointer: { 496 | size = sizeof(void*); 497 | break; 498 | } 499 | case Op::OpTypeStruct: { 500 | auto s = (STypeStruct*)definedType.Memory; 501 | for (uint32 i = 0; i < s->MembertypeIdsCount; i++) { 502 | uint32 id = s->MembertypeIds[i]; 503 | size += GetTypeByteSize(id); 504 | } 505 | break; 506 | } 507 | case Op::OpTypeVector: { 508 | auto v = (STypeVector*)definedType.Memory; 509 | size = GetTypeByteSize(v->ComponentTypeId) * v->ComponentCount; 510 | break; 511 | } 512 | default: 513 | std::cout << "Not a type definition: " << writeOp(definedType); 514 | } 515 | 516 | //TODO: Precalc type sizes 517 | //TypeByteSizes[typeId] = size; 518 | return size; 519 | } 520 | 521 | bool InterpretedVM::InitializeConstants() { 522 | for (auto& constant : prog.Constants) { 523 | auto op = constant.second; 524 | switch (op.Op) { 525 | case Op::OpConstant: { 526 | auto constant = (SConstant*)op.Memory; 527 | Value val = { constant->ResultTypeId, (byte*)constant->Values }; 528 | env.Values[constant->ResultId] = val; 529 | break; 530 | } 531 | case Op::OpConstantComposite: { 532 | auto constant = (SConstantComposite*)op.Memory; 533 | Value val = { constant->ResultTypeId, VmAlloc(constant->ResultTypeId) }; 534 | env.Values[constant->ResultId] = val; 535 | byte* memPtr = val.Memory; 536 | for (int i = 0; i < constant->ConstituentsIdsCount; i++) { 537 | auto memVal = env.Values[constant->ConstituentsIds[i]]; 538 | uint32 memSize = GetTypeByteSize(memVal.TypeId); 539 | std::memcpy(memPtr, memVal.Memory, memSize); 540 | memPtr += memSize; 541 | } 542 | assert( memPtr - val.Memory == GetTypeByteSize(constant->ResultTypeId)); 543 | break; 544 | } 545 | case Op::OpConstantFalse: { 546 | auto constant = (SConstantFalse*)op.Memory; 547 | Value val = { constant->ResultTypeId, VmAlloc(constant->ResultTypeId) }; 548 | *(bool*)val.Memory = false; 549 | break; 550 | } 551 | case Op::OpConstantTrue: { 552 | auto constant = (SConstantTrue*)op.Memory; 553 | Value val = { constant->ResultTypeId, VmAlloc(constant->ResultTypeId) }; 554 | *(bool*)val.Memory = true; 555 | break; 556 | } 557 | default: 558 | std::cout << "Operation does not define a constant: " << writeOp(op); 559 | return false; 560 | } 561 | } 562 | 563 | return true; 564 | } 565 | 566 | bool InterpretedVM::ImportExt(SExtInstImport import) { 567 | std::string name(import.Name); 568 | std::transform(name.begin(), name.end(), name.begin(), ::tolower); 569 | auto filename = ("ext/" + LIB_NAME(name) + LIBRARY_EXT); 570 | 571 | HANDLE_TYPE extInst = LOAD_LIBRARY(filename.c_str()); 572 | 573 | if (extInst) { 574 | const char* funcName = xstr(EXT_EXPORT_TABLE_FUNC_NAME); 575 | GetExtTableFunc* func = (GetExtTableFunc*)LOAD_SYMBOL(extInst, TEXT(funcName)); 576 | if (func) { 577 | auto res = func(); 578 | env.Extensions[import.ResultId] = res; 579 | return true; 580 | } 581 | } 582 | 583 | std::cout << LIB_ERROR << std::endl; 584 | return false; 585 | } 586 | 587 | bool InterpretedVM::Setup() { 588 | for (auto& ext : prog.ExtensionImports) { 589 | if(!ImportExt(ext.second)) { 590 | std::cout << "Loading externsion " << ext.second.Name << " failed!" << std::endl; 591 | return false; 592 | } 593 | } 594 | 595 | if (!InitializeConstants()) { 596 | std::cout << "Could not define constants!" << std::endl; 597 | return false; 598 | } 599 | 600 | return true; 601 | } 602 | 603 | bool InterpretedVM::Run() { 604 | for (auto& ep : prog.EntryPoints) { 605 | auto func = prog.FunctionDefinitions.at(ep.second.EntryPointId); 606 | if (Execute(&func) != 0) { 607 | return false; 608 | } 609 | } 610 | return true; 611 | } 612 | -------------------------------------------------------------------------------- /src/main/interpreted_vm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vm.h" 3 | #include 4 | #include 5 | #include "parser_definitions.h" 6 | 7 | struct Function; 8 | 9 | class InterpretedVM : public VM { 10 | private: 11 | Program& prog; 12 | Environment& env; 13 | Function* currentFunction; 14 | std::map TypeByteSizes; 15 | std::vector> VmMemory; 16 | 17 | byte* VmAlloc(uint32 typeId) override; 18 | 19 | Value TextureSample(Value sampler, Value coord, Value bias, uint32 resultTypeId); 20 | 21 | uint32 Execute(Function* func); 22 | 23 | void * ReadVariable(uint32 id) const; 24 | bool SetVariable(uint32 id, void * value); 25 | 26 | 27 | bool InitializeConstants(); 28 | 29 | bool ImportExt(SExtInstImport import); 30 | 31 | public: 32 | InterpretedVM(Program& prog, Environment& env) : prog(prog), env(env), currentFunction(nullptr) { } 33 | 34 | virtual bool Setup() override; 35 | virtual bool Run() override; 36 | bool SetVariable(std::string name, void * value) override; 37 | void * ReadVariable(std::string name) const override; 38 | Value VmInit(uint32 typeId, void * val) override; 39 | 40 | Value Dereference(Value val) const override; 41 | Value IndexMemberValue(Value val, uint32 index) const override; 42 | Value IndexMemberValue(uint32 typeId, byte * val, uint32 index) const override; 43 | 44 | uint32 GetTypeByteSize(uint32 typeId) const override; 45 | byte * GetPointerInComposite(uint32 typeId, byte * composite, uint32 indexCount, uint32 * indices, uint32 currLevel) const override; 46 | SOp GetType(uint32 typeId) const override; 47 | bool IsVectorType(uint32 typeId) const override; 48 | uint32 ElementCount(uint32 typeId) const override; 49 | }; -------------------------------------------------------------------------------- /src/main/otherside_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "types.h" 7 | 8 | #include "parser_definitions.h" 9 | #include "parser.h" 10 | #include "codegen.h" 11 | #include "validation.h" 12 | #include "interpreted_vm.h" 13 | #include "utils.h" 14 | 15 | std::string USAGE = "-i -o "; 16 | 17 | struct TestArgs { 18 | const char* ShaderFile; 19 | const char* CppFile; 20 | std::map inputValues; 21 | }; 22 | 23 | struct CmdArgs { 24 | const char* InputFile; 25 | const char* OutputFile; 26 | }; 27 | 28 | bool ParseArgs(int argc, const char** argv, CmdArgs* args) { 29 | for (int i = 1; i < argc; i++) { 30 | const char* arg = argv[i]; 31 | 32 | if (strcmp(arg, "-i") == 0) { 33 | i++; 34 | if (i == argc) { 35 | return false; 36 | } 37 | args->InputFile = argv[i]; 38 | } else if (strcmp(arg, "-o") == 0) { 39 | i++; 40 | if (i == argc) { 41 | return false; 42 | } 43 | args->OutputFile = argv[i]; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | int main(int argc, const char** argv) { 50 | CmdArgs args; 51 | if (!ParseArgs(argc, argv, &args)) { 52 | std::cout << "Could not parse arguments. Usage: " << USAGE << std::endl; 53 | return -1; 54 | } 55 | 56 | Parser parser(args.InputFile); 57 | Program prog; 58 | 59 | if (!parser.Parse(&prog)) { 60 | std::cout << "Could not parse program." << std::endl; 61 | return -1; 62 | } 63 | 64 | std::cout << "Validating program:..."; 65 | if(!validate(prog, std::cout)) { 66 | std::cout << "Validation failed." << std::endl; 67 | return -1; 68 | } 69 | std::cout << "done" << std::endl; 70 | 71 | std::cout << writeProgram(prog); 72 | 73 | std::cout << "Generationg code:..."; 74 | if (!genCode(args.OutputFile, prog)) { 75 | std::cout << "Could not generate code for program." << std::endl; 76 | return -1; 77 | } 78 | std::cout << "done" << std::endl; 79 | 80 | Environment env; 81 | InterpretedVM vm(prog, env); 82 | if(!vm.Setup()) { 83 | std::cout << "Could not setup the VM." << std::endl; 84 | return -1; 85 | } 86 | 87 | std::cout << "Running program:..."; 88 | 89 | Texture inTex = load_tex("data/testin.bmp"); 90 | 91 | Sampler* sampler = new Sampler{ 2, (uint32*)&inTex, inTex.data, FilterMode::FMPoint, WrapMode::WMRepeat }; 92 | Vec2* texSize = new Vec2{ (float)inTex.width, (float)inTex.height}; 93 | Light* light = new Light{ {1, 0, 0, 1}, {0.5f, 0.5f} }; 94 | Color* fragColor = new Color{ 0, 0, 0, 0 }; 95 | Vec2* uv = new Vec2{ 1.0f, 1.0f }; 96 | 97 | bool allVariablesSet = true; 98 | allVariablesSet &= vm.SetVariable("uv", &uv); 99 | allVariablesSet &= vm.SetVariable("texSize", &texSize); 100 | allVariablesSet &= vm.SetVariable("testTex", &sampler); 101 | allVariablesSet &= vm.SetVariable("light", &light); 102 | allVariablesSet &= vm.SetVariable("gl_FragColor", &fragColor); 103 | 104 | if(!allVariablesSet) { 105 | std::cout << "Could not set all variables." << std::endl; 106 | return -1; 107 | } 108 | 109 | Texture outTex = MakeFlatTexture(inTex.width, inTex.height, { 0, 0, 0, 1 }); 110 | 111 | for (int x = 0; x < outTex.width; x++) { 112 | for (int y = 0; y < outTex.height; y++) { 113 | uv->x = float(x) / outTex.width; 114 | uv->y = float(y) / outTex.height; 115 | 116 | if (!vm.Run()) { 117 | std::cout << "Program failed to run."; 118 | return -1; 119 | } 120 | 121 | outTex.data[x + y * outTex.width] = **(Color**)vm.ReadVariable("gl_FragColor"); 122 | } 123 | } 124 | 125 | save_bmp("data/testout.bmp", outTex); 126 | 127 | std::cout << " done"; 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /src/main/parser.cpp: -------------------------------------------------------------------------------- 1 | #include "parser.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "types.h" 9 | #include "parser_definitions.h" 10 | 11 | 12 | uint32 Parser::get() const { 13 | return *buffer; 14 | } 15 | 16 | bool Parser::end() const { 17 | return index >= length; 18 | } 19 | 20 | void Parser::eat() { 21 | index++; 22 | buffer++; 23 | } 24 | 25 | uint32 Parser::getAndEat() { 26 | uint32 result = get(); 27 | eat(); 28 | return result; 29 | } 30 | 31 | bool Parser::expectAndEat(uint32 e) { 32 | assert(e == get()); 33 | eat(); 34 | return true; 35 | } 36 | 37 | bool Parser::expect(uint32 e) const { 38 | assert(e == get()); 39 | return true; 40 | } 41 | 42 | 43 | SOp Parser::readInstruction() { 44 | uint32* opData = buffer; 45 | uint32 word = getAndEat(); 46 | spv::Op op = (spv::Op)(word & spv::OpCodeMask); 47 | uint32 wordCount = (uint32)(word >> spv::WordCountShift); 48 | 49 | WordType wordTypes[255]; 50 | 51 | uint32 opWordCount = wordCount; 52 | 53 | if (sizeof(LUTOpWordTypes) / sizeof(void*) <= (int)op) { 54 | wordTypes[0] = WordType::TOp; 55 | for (uint32 i = 1; i < wordCount; i++) { 56 | wordTypes[i] = WordType::TLiteralNumber; 57 | } 58 | } 59 | else { 60 | WordType* opWordTypes = (WordType*)LUTOpWordTypes[(int)op]; 61 | opWordCount = LUTOpWordTypesCount[(int)op]; 62 | 63 | for (int i = 0; i < wordCount; i++) { 64 | wordTypes[i] = opWordTypes[i > opWordCount - 1 ? opWordCount - 1 : i]; 65 | } 66 | } 67 | 68 | uint32* opMem = new uint32[opWordCount + 1]; 69 | memset(opMem, 0, sizeof(uint32) * (opWordCount + 1)); 70 | SOp Result = { op, opMem }; 71 | auto bufferBegin = buffer; 72 | int indexBegin = index; 73 | 74 | for (uint32 i = 1; i < wordCount; i++) { 75 | word = getAndEat(); 76 | void* currMem = opMem + i - 1; 77 | uint32* currMemU32 = (uint32*)currMem; 78 | if (wordTypes[i] == WordType::TIdList || wordTypes[i] == WordType::TLiteralNumberList) { 79 | assert(i + 1 == opWordCount); 80 | *currMemU32++ = (uint32) (wordCount - opWordCount + 1); 81 | currMem = currMemU32; 82 | *(uint32 **) currMem = (uint32 *) (buffer - 1); 83 | break; 84 | } else if (wordTypes[i] == WordType::TLiteralString) { 85 | assert(i + 1 == opWordCount); 86 | *(char **) currMem = (char *) (buffer - 1); 87 | break; 88 | } else { 89 | *currMemU32 = word; 90 | } 91 | } 92 | 93 | buffer = bufferBegin + wordCount - 1; 94 | index = indexBegin + wordCount - 1; 95 | 96 | return Result; 97 | } 98 | 99 | bool Parser::Parse(Program *outProg) { 100 | if (!expectAndEat(spv::MagicNumber)) { 101 | return false; 102 | } 103 | 104 | ParseProgram prog; 105 | prog.Version = getAndEat(); 106 | prog.GeneratorMagic = getAndEat(); 107 | prog.IDBound = getAndEat(); 108 | prog.InstructionSchema = getAndEat(); 109 | 110 | int instructionIndex = 0; 111 | prog.NextOp = readInstruction(); 112 | 113 | do { 114 | SOp op = prog.NextOp; 115 | instructionIndex++; 116 | if (!end()) { 117 | prog.NextOp = readInstruction(); 118 | } else { 119 | prog.NextOp = SOp{ Op::OpNop, nullptr }; 120 | } 121 | 122 | LUTHandlerMethods[(int)op.Op]((void*)op.Memory, &prog); 123 | prog.Ops.push_back(op); 124 | 125 | if (prog.InFunction && prog.CurrentFunction->InBlock) { 126 | addOp(&prog, op); 127 | } 128 | } while (prog.NextOp.Op != Op::OpNop); 129 | 130 | *outProg = (Program)prog; 131 | return true; 132 | } 133 | 134 | std::string getDescriptor(uint32 id, const Program* prog) { 135 | if(prog->Names.find(id) != prog->Names.end()) { 136 | return prog->Names.at(id).Name; 137 | } else if(prog->Variables.find(id) != prog->Variables.end()) { 138 | SVariable variable = prog->Variables.at(id); 139 | return getDescriptor(variable.ResultId, prog); 140 | } 141 | return ""; 142 | } 143 | 144 | bool writeOpArg(std::stringstream& opline, SOp op, int i, const Program* prog, const WordType* wordTypes) { 145 | uint32 word = *((uint32*)op.Memory + i - 1); 146 | 147 | if (wordTypes[i] == WordType::TLiteralNumber) { 148 | opline << " " << word; 149 | } 150 | else if (wordTypes[i] == WordType::TId) { 151 | opline << " [" << word; 152 | if (prog != nullptr && op.Op != Op::OpName && op.Op != Op::OpMemberName) { 153 | auto desc = getDescriptor(word, prog); 154 | if (desc.size() > 0) { 155 | opline << "(" << getDescriptor(word, prog) << ")"; 156 | } 157 | } 158 | opline << "]"; 159 | } 160 | else if (wordTypes[i] == WordType::TIdList) { 161 | uint32 count = word; 162 | uint32* ptr = *(uint32**)((uint32*)op.Memory + i); 163 | opline << " ["; 164 | for (uint32 j = 0; j < count; j++) { 165 | word = ptr[j]; 166 | opline << "[" << word; 167 | if (prog != nullptr && op.Op != Op::OpName && op.Op != Op::OpMemberName) { 168 | auto desc = getDescriptor(word, prog); 169 | if (desc.size() > 0) { 170 | opline << "(" << getDescriptor(word, prog) << ")"; 171 | } 172 | } 173 | opline << "]" << (j != count - 1 ? ", " : ""); 174 | } 175 | opline << "]"; 176 | 177 | return false; 178 | } 179 | else if (wordTypes[i] == WordType::TLiteralNumberList) { 180 | uint32 count = word; 181 | uint32* ptr = *(uint32**)((uint32*)op.Memory + i); 182 | opline << " ["; 183 | for (uint32 j = 0; j < count; j++) { 184 | word = ptr[j]; 185 | opline << word << (j != count - 1 ? ", " : ""); 186 | } 187 | opline << "]"; 188 | 189 | return false; 190 | } 191 | else if (wordTypes[i] == WordType::TLiteralString) { 192 | if (wordTypes[i - 1] != WordType::TLiteralString) { 193 | char* str = *((char**)((uint32*)op.Memory + i - 1)); 194 | opline << " " << str; 195 | } 196 | } 197 | else { 198 | std::string* lutPointer = *((std::string**)LUTPointers + (uint32)wordTypes[i]); 199 | std::string name = lutPointer[word]; 200 | opline << " " << name; 201 | } 202 | 203 | } 204 | 205 | std::string writeOp(SOp op, const Program* prog) { 206 | std::stringstream opline; 207 | 208 | WordType wordTypes[255]; 209 | 210 | uint32 opWordCount = 0; 211 | 212 | if (sizeof(LUTOpWordTypes) / sizeof(void*) <= (int)op.Op) { 213 | return ""; 214 | } else { 215 | WordType* opWordTypes = (WordType*)LUTOpWordTypes[(int)op.Op]; 216 | opWordCount = LUTOpWordTypesCount[(int)op.Op]; 217 | 218 | for (uint32 i = 0; i < opWordCount; i++) { 219 | wordTypes[i] = opWordTypes[i]; 220 | } 221 | } 222 | 223 | opline << OpStrings[(int)op.Op]; 224 | 225 | for (uint32 i = 1; i < opWordCount && writeOpArg(opline, op, i, prog, wordTypes); i++); 226 | 227 | opline << std::endl; 228 | return opline.str(); 229 | } 230 | 231 | std::string writeProgram(const Program& prog) { 232 | std::stringstream progStream; 233 | progStream << "Version: " << prog.Version << std::endl; 234 | progStream << "Generator Magic: " << prog.GeneratorMagic << std::endl; 235 | progStream << "ID Bound: " << prog.IDBound << std::endl; 236 | progStream << "Instruction Schema: " << prog.InstructionSchema << std::endl; 237 | progStream << "=================================================" << std::endl; 238 | int instructionIndex = 0; 239 | for(auto& op : prog.Ops) { 240 | progStream << std::setw(3) << instructionIndex << ": " << writeOp(op, &prog); 241 | instructionIndex++; 242 | } 243 | return progStream.str(); 244 | } 245 | 246 | std::string writeOp(SOp op) { 247 | return writeOp(op, nullptr); 248 | } 249 | -------------------------------------------------------------------------------- /src/main/parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct Program; 10 | struct SOp; 11 | 12 | class Parser { 13 | private: 14 | std::unique_ptr bufferStart; 15 | uint32* buffer; 16 | int length; 17 | int index; 18 | 19 | uint32 get() const; 20 | bool end() const; 21 | void eat(); 22 | uint32 getAndEat(); 23 | bool expectAndEat(uint32 e); 24 | bool expect(uint32 e) const; 25 | SOp readInstruction(); 26 | 27 | public: 28 | Parser(int length) { 29 | this->index = 0; 30 | this->length = length; 31 | this->bufferStart = std::unique_ptr(new uint32[length]); 32 | this->buffer = bufferStart.get(); 33 | } 34 | 35 | Parser(const char* inputFileName) { 36 | assert(inputFileName); 37 | 38 | this->index = 0; 39 | 40 | std::ifstream inputFile; 41 | 42 | inputFile.open(inputFileName, std::ifstream::in | std::ifstream::binary); 43 | assert(inputFile.is_open()); 44 | inputFile.seekg(0, std::ios::end); 45 | std::streamsize size = inputFile.tellg(); 46 | inputFile.seekg(0, std::ios::beg); 47 | assert(size % 4 == 0); 48 | 49 | this->length = size / 4; 50 | this->bufferStart = std::unique_ptr(new uint32[length]); 51 | this->buffer = bufferStart.get(); 52 | 53 | if (!inputFile.read((char*)GetBufferPtr(), size)) { 54 | std::cout << "Could not read file." << std::endl; 55 | } 56 | 57 | inputFile.close(); 58 | } 59 | 60 | bool Parse(Program *prog); 61 | uint32* GetBufferPtr() const { 62 | return bufferStart.get(); 63 | } 64 | 65 | }; 66 | 67 | std::string writeProgram(const Program& prog); 68 | std::string writeOp(SOp op); 69 | std::string writeOp(SOp op, const Program* prog); 70 | -------------------------------------------------------------------------------- /src/main/validation.cpp: -------------------------------------------------------------------------------- 1 | #include "validation.h" 2 | #include "parser_definitions.h" 3 | #include "lookups_gen.h" 4 | #include 5 | #include "parser.h" 6 | 7 | #define CURRENT_OP prog.Ops[opIndex] 8 | #define CURRENT_OP_TYPE CURRENT_OP.Op 9 | #define FORBID(op) forbiddenOps.insert(op) 10 | #define ALLOW(op) forbiddenOps.erase(forbiddenOps.find(op)) 11 | #define NOT_FORBIDDEN(op) \ 12 | if(forbiddenOps.find(op) != forbiddenOps.end()) { errorOut << "Instruction " << writeOp(prog.Ops[opIndex]) << "was not allowed here. (Index: " << opIndex << ")" << std::endl; return false; } 13 | 14 | #define NOT_END (opIndex < prog.Ops.size()) 15 | #define EXPECT_OP(op) if(!NOT_END) { errorOut << "Unexpected end of instruction stream. Expected: " << OpStrings[(int)op] << std::endl; return false; } 16 | 17 | #define REQUIRED_F(func) \ 18 | EXPECT_OP(CURRENT_OP_TYPE) \ 19 | if(func(CURRENT_OP_TYPE)) { \ 20 | NOT_FORBIDDEN(CURRENT_OP_TYPE) opIndex++; \ 21 | } else { \ 22 | errorOut << "Instruction " << writeOp(prog.Ops[opIndex]) << "was not allowed here. (L" << opIndex << ")" << std::endl; \ 23 | return false; \ 24 | } 25 | 26 | #define REQUIRED(op) \ 27 | EXPECT_OP(op) \ 28 | if(CURRENT_OP_TYPE == op) { \ 29 | NOT_FORBIDDEN(op) opIndex++; \ 30 | } else { \ 31 | errorOut << "Instruction " << writeOp(prog.Ops[opIndex]) << "was not allowed here. (L" << opIndex << ") Required: " << OpStrings[(int)op] << std::endl; \ 32 | return false; \ 33 | } 34 | 35 | #define REQUIRED_USE(op) \ 36 | REQUIRED(op) \ 37 | FORBID(op); 38 | 39 | #define OPTIONAL_USE(op) { EXPECT_OP(op) if(CURRENT_OP_TYPE == op) { NOT_FORBIDDEN(op) opIndex++; } FORBID(op); } 40 | #define MANY(op) EXPECT_OP(op) while(NOT_END && CURRENT_OP_TYPE == op) { NOT_FORBIDDEN(op) opIndex++; } 41 | #define MANY_USE(op) { EXPECT_OP(op) MANY(op) FORBID(op); } 42 | #define MANY_F(func) while(NOT_END && func(CURRENT_OP)) {NOT_FORBIDDEN(CURRENT_OP_TYPE) opIndex++; } 43 | 44 | 45 | bool v_ids(const Program& prog, std::ostream& errorOut) { 46 | return true; 47 | } 48 | 49 | bool v_layout(const Program& prog, std::ostream& errorOut) { 50 | int opIndex = 0; 51 | std::set forbiddenOps; 52 | 53 | OPTIONAL_USE(spv::Op::OpSource) 54 | OPTIONAL_USE(spv::Op::OpSourceExtension) 55 | MANY_USE(spv::Op::OpCapability) 56 | MANY_USE(spv::Op::OpExtension) 57 | MANY_USE(spv::Op::OpExtInstImport) 58 | REQUIRED_USE(spv::Op::OpMemoryModel) 59 | MANY_USE(spv::Op::OpEntryPoint) 60 | MANY_USE(spv::Op::OpExecutionMode) 61 | MANY_USE(spv::Op::OpString) 62 | 63 | MANY_F([](SOp op) { 64 | return op.Op == spv::Op::OpName || 65 | op.Op == spv::Op::OpMemberName; 66 | }) 67 | FORBID(spv::Op::OpName), FORBID(spv::Op::OpMemberName); 68 | 69 | MANY_USE(spv::Op::OpLine) 70 | 71 | MANY_F([](SOp op) { 72 | return op.Op == spv::Op::OpDecorate || 73 | op.Op == spv::Op::OpMemberDecorate || 74 | op.Op == spv::Op::OpGroupDecorate || 75 | op.Op == spv::Op::OpGroupMemberDecorate || 76 | op.Op == spv::Op::OpDecorationGroup; 77 | }) 78 | 79 | FORBID(spv::Op::OpDecorate), FORBID(spv::Op::OpMemberDecorate), FORBID(spv::Op::OpGroupDecorate), 80 | FORBID(spv::Op::OpGroupMemberDecorate), FORBID(spv::Op::OpDecorationGroup); 81 | 82 | MANY_F([](SOp op) { 83 | return 84 | OpStrings[(int)op.Op].find("Type") != std::string::npos || 85 | OpStrings[(int)op.Op].find("Constant") != std::string::npos || 86 | (op.Op == spv::Op::OpVariable && ((SVariable*)op.Memory)->StorageClass != spv::StorageClass::Function); 87 | }) 88 | 89 | while(NOT_END && CURRENT_OP_TYPE == spv::Op::OpFunction) { 90 | REQUIRED(spv::Op::OpFunction) 91 | MANY(spv::Op::OpFunctionParameter) 92 | bool isFirstBlock = true; 93 | while(NOT_END && CURRENT_OP_TYPE != spv::Op::OpFunctionEnd) { 94 | REQUIRED(spv::Op::OpLabel) 95 | 96 | if(isFirstBlock) { 97 | MANY_F([](SOp op) { 98 | return op.Op == spv::Op::OpVariable && 99 | ((SVariable*)op.Memory)->StorageClass == spv::StorageClass::Function; 100 | }) 101 | FORBID(spv::Op::OpVariable); 102 | } 103 | 104 | auto isBranch = [](spv::Op op) { 105 | return 106 | op == spv::Op::OpBranch || 107 | op == spv::Op::OpBranchConditional || 108 | op == spv::Op::OpSwitch || 109 | op == spv::Op::OpKill || 110 | op == spv::Op::OpReturn || 111 | op == spv::Op::OpReturnValue || 112 | op == spv::Op::OpUnreachable; 113 | }; 114 | 115 | auto blockMany = [isFirstBlock, isBranch](SOp op) { 116 | return (op.Op != spv::Op::OpPhi || !isFirstBlock) && 117 | op.Op != spv::Op::OpLabel && 118 | !isBranch(op.Op); 119 | }; 120 | 121 | MANY_F(blockMany) 122 | 123 | REQUIRED_F(isBranch) 124 | 125 | isFirstBlock = false; 126 | } 127 | 128 | ALLOW(spv::Op::OpVariable); 129 | REQUIRED(spv::Op::OpFunctionEnd) 130 | } 131 | 132 | if(NOT_END) { 133 | errorOut << "Expected end of module but found (Index: " << opIndex << ") " << writeOp(CURRENT_OP); 134 | return false; 135 | } 136 | 137 | return true; 138 | } 139 | 140 | bool validate(const Program& prog, std::ostream& errorOut) { 141 | if(!v_layout(prog, errorOut)) { 142 | errorOut << "Logical layout is not correct!" << std::endl; 143 | return false; 144 | } 145 | return true; 146 | } -------------------------------------------------------------------------------- /src/main/validation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct Program; 5 | 6 | bool validate(const Program& prog, std::ostream& errorOut); -------------------------------------------------------------------------------- /src/shared/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | project(shared C CXX) 4 | 5 | set(SHARED_LIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | set(SHARED_LIB_INCLUDE_DIR ${SHARED_LIB_INCLUDE_DIR} PARENT_SCOPE) 8 | 9 | if(TARGET shared) 10 | 11 | message("shared is already defined") 12 | 13 | else() 14 | 15 | include_directories(${SHARED_LIB_INCLUDE_DIR}) 16 | 17 | set(SRCS lookups.cpp lookups_gen.cpp utils.cpp) 18 | 19 | # We need C++ 11 20 | set(CMAKE_CXX_STANDARD 11) 21 | set(CMAKE_CXX_STANDARD_REQUIRED on) 22 | 23 | add_library(shared STATIC ${SRCS}) 24 | 25 | endif() 26 | 27 | -------------------------------------------------------------------------------- /src/shared/Khronos/GLSL450Lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2014-2015 The Khronos Group Inc. 3 | ** 4 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 5 | ** of this software and/or associated documentation files (the "Materials"), 6 | ** to deal in the Materials without restriction, including without limitation 7 | ** the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | ** and/or sell copies of the Materials, and to permit persons to whom the 9 | ** Materials are furnished to do so, subject to the following conditions: 10 | ** 11 | ** The above copyright notice and this permission notice shall be included in 12 | ** all copies or substantial portions of the Materials. 13 | ** 14 | ** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS 15 | ** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND 16 | ** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ 17 | ** 18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | ** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | ** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS 24 | ** IN THE MATERIALS. 25 | */ 26 | 27 | #ifndef GLSLstd450_H 28 | #define GLSLstd450_H 29 | 30 | const int GLSLstd450Version = 99; 31 | const int GLSLstd450Revision = 2; 32 | 33 | enum GLSLstd450 { 34 | Bad = 0, // Don't use 35 | 36 | Round = 1, 37 | RoundEven = 2, 38 | Trunc = 3, 39 | FAbs = 4, 40 | SAbs = 5, 41 | FSign = 6, 42 | SSign = 7, 43 | Floor = 8, 44 | Ceil = 9, 45 | Fract = 10, 46 | 47 | Radians = 11, 48 | Degrees = 12, 49 | Sin = 13, 50 | Cos = 14, 51 | Tan = 15, 52 | Asin = 16, 53 | Acos = 17, 54 | Atan = 18, 55 | Sinh = 19, 56 | Cosh = 20, 57 | Tanh = 21, 58 | Asinh = 22, 59 | Acosh = 23, 60 | Atanh = 24, 61 | Atan2 = 25, 62 | 63 | Pow = 26, 64 | Exp = 27, 65 | Log = 28, 66 | Exp2 = 29, 67 | Log2 = 30, 68 | Sqrt = 31, 69 | InverseSqrt = 32, 70 | 71 | Determinant = 33, 72 | MatrixInverse = 34, 73 | 74 | Modf = 35, // second operand needs an OpVariable to write to 75 | ModfStruct = 36, // no OpVariable operand 76 | FMin = 37, 77 | UMin = 38, 78 | SMin = 39, 79 | FMax = 40, 80 | UMax = 41, 81 | SMax = 42, 82 | FClamp = 43, 83 | UClamp = 44, 84 | SClamp = 45, 85 | Mix = 46, 86 | Step = 47, 87 | SmoothStep = 48, 88 | 89 | Fma = 49, 90 | Frexp = 50, // second operand needs an OpVariable to write to 91 | FrexpStruct = 51, // no OpVariable operand 92 | Ldexp = 52, 93 | 94 | PackSnorm4x8 = 53, 95 | PackUnorm4x8 = 54, 96 | PackSnorm2x16 = 55, 97 | PackUnorm2x16 = 56, 98 | PackHalf2x16 = 57, 99 | PackDouble2x32 = 58, 100 | UnpackSnorm2x16 = 59, 101 | UnpackUnorm2x16 = 60, 102 | UnpackHalf2x16 = 61, 103 | UnpackSnorm4x8 = 62, 104 | UnpackUnorm4x8 = 63, 105 | UnpackDouble2x32 = 64, 106 | 107 | Length = 65, 108 | Distance = 66, 109 | Cross = 67, 110 | Normalize = 68, 111 | FaceForward = 69, 112 | Reflect = 70, 113 | Refract = 71, 114 | 115 | FindILSB = 72, 116 | FindSMSB = 73, 117 | FindUMSB = 74, 118 | 119 | InterpolateAtCentroid = 75, 120 | InterpolateAtSample = 76, 121 | InterpolateAtOffset = 77, 122 | 123 | AddCarry = 78, // These three should move to the core instruction set 124 | SubBorrow = 79, 125 | MulExtended = 80, 126 | 127 | Count 128 | }; 129 | 130 | #endif // #ifndef GLSLstd450_H -------------------------------------------------------------------------------- /src/shared/Khronos/spirv.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-2015 The Khronos Group Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and/or associated documentation files (the "Materials"), 5 | // to deal in the Materials without restriction, including without limitation 6 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | // and/or sell copies of the Materials, and to permit persons to whom the 8 | // Materials are furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Materials. 12 | // 13 | // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS 14 | // STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND 15 | // HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ 16 | // 17 | // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS 23 | // IN THE MATERIALS. 24 | 25 | // This header is automatically generated by the same tool that creates 26 | // the Binary Section of the SPIR-V specification. 27 | 28 | // Specification revision 31. 29 | // Enumeration tokens for SPIR-V, in various styles: 30 | // C, C++, C++11, JSON, Lua, Python 31 | // 32 | // - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL 33 | // - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL 34 | // - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL 35 | // - Lua will use tables, e.g.: spv.SourceLanguage.GLSL 36 | // - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] 37 | // 38 | // Some tokens act like mask values, which can be OR'd together, 39 | // while others are mutually exclusive. The mask-like ones have 40 | // "Mask" in their name, and a parallel enum that has the shift 41 | // amount (1 << x) for each corresponding enumerant. 42 | 43 | #ifndef spirv_H 44 | #define spirv_H 45 | 46 | namespace spv { 47 | 48 | typedef unsigned int Id; 49 | 50 | static const unsigned int MagicNumber = 0x07230203; 51 | static const unsigned int Version = 99; 52 | static const unsigned int Revision = 31; 53 | static const unsigned int OpCodeMask = 0xffff; 54 | static const unsigned int WordCountShift = 16; 55 | 56 | enum class SourceLanguage : unsigned { 57 | Unknown = 0, 58 | ESSL = 1, 59 | GLSL = 2, 60 | OpenCL = 3, 61 | }; 62 | 63 | enum class ExecutionModel : unsigned { 64 | Vertex = 0, 65 | TessellationControl = 1, 66 | TessellationEvaluation = 2, 67 | Geometry = 3, 68 | Fragment = 4, 69 | GLCompute = 5, 70 | Kernel = 6, 71 | }; 72 | 73 | enum class AddressingModel : unsigned { 74 | Logical = 0, 75 | Physical32 = 1, 76 | Physical64 = 2, 77 | }; 78 | 79 | enum class MemoryModel : unsigned { 80 | Simple = 0, 81 | GLSL450 = 1, 82 | OpenCL = 2, 83 | }; 84 | 85 | enum class ExecutionMode : unsigned { 86 | Invocations = 0, 87 | SpacingEqual = 1, 88 | SpacingFractionalEven = 2, 89 | SpacingFractionalOdd = 3, 90 | VertexOrderCw = 4, 91 | VertexOrderCcw = 5, 92 | PixelCenterInteger = 6, 93 | OriginUpperLeft = 7, 94 | OriginLowerLeft = 8, 95 | EarlyFragmentTests = 9, 96 | PointMode = 10, 97 | Xfb = 11, 98 | DepthReplacing = 12, 99 | DepthAny = 13, 100 | DepthGreater = 14, 101 | DepthLess = 15, 102 | DepthUnchanged = 16, 103 | LocalSize = 17, 104 | LocalSizeHint = 18, 105 | InputPoints = 19, 106 | InputLines = 20, 107 | InputLinesAdjacency = 21, 108 | InputTriangles = 22, 109 | InputTrianglesAdjacency = 23, 110 | InputQuads = 24, 111 | InputIsolines = 25, 112 | OutputVertices = 26, 113 | OutputPoints = 27, 114 | OutputLineStrip = 28, 115 | OutputTriangleStrip = 29, 116 | VecTypeHint = 30, 117 | ContractionOff = 31, 118 | }; 119 | 120 | enum class StorageClass : unsigned { 121 | UniformConstant = 0, 122 | Input = 1, 123 | Uniform = 2, 124 | Output = 3, 125 | WorkgroupLocal = 4, 126 | WorkgroupGlobal = 5, 127 | PrivateGlobal = 6, 128 | Function = 7, 129 | Generic = 8, 130 | AtomicCounter = 10, 131 | Image = 11, 132 | }; 133 | 134 | enum class Dim : unsigned { 135 | Dim1D = 0, 136 | Dim2D = 1, 137 | Dim3D = 2, 138 | Cube = 3, 139 | Rect = 4, 140 | Buffer = 5, 141 | }; 142 | 143 | enum class SamplerAddressingMode : unsigned { 144 | None = 0, 145 | ClampToEdge = 1, 146 | Clamp = 2, 147 | Repeat = 3, 148 | RepeatMirrored = 4, 149 | }; 150 | 151 | enum class SamplerFilterMode : unsigned { 152 | Nearest = 0, 153 | Linear = 1, 154 | }; 155 | 156 | enum class ImageFormat : unsigned { 157 | Unknown = 0, 158 | Rgba32f = 1, 159 | Rgba16f = 2, 160 | R32f = 3, 161 | Rgba8 = 4, 162 | Rgba8Snorm = 5, 163 | Rg32f = 6, 164 | Rg16f = 7, 165 | R11fG11fB10f = 8, 166 | R16f = 9, 167 | Rgba16 = 10, 168 | Rgb10A2 = 11, 169 | Rg16 = 12, 170 | Rg8 = 13, 171 | R16 = 14, 172 | R8 = 15, 173 | Rgba16Snorm = 16, 174 | Rg16Snorm = 17, 175 | Rg8Snorm = 18, 176 | R16Snorm = 19, 177 | R8Snorm = 20, 178 | Rgba32i = 21, 179 | Rgba16i = 22, 180 | Rgba8i = 23, 181 | R32i = 24, 182 | Rg32i = 25, 183 | Rg16i = 26, 184 | Rg8i = 27, 185 | R16i = 28, 186 | R8i = 29, 187 | Rgba32ui = 30, 188 | Rgba16ui = 31, 189 | Rgba8ui = 32, 190 | R32ui = 33, 191 | Rgb10a2ui = 34, 192 | Rg32ui = 35, 193 | Rg16ui = 36, 194 | Rg8ui = 37, 195 | R16ui = 38, 196 | R8ui = 39, 197 | }; 198 | 199 | enum class ImageChannelOrder : unsigned { 200 | R = 0, 201 | A = 1, 202 | RG = 2, 203 | RA = 3, 204 | RGB = 4, 205 | RGBA = 5, 206 | BGRA = 6, 207 | ARGB = 7, 208 | Intensity = 8, 209 | Luminance = 9, 210 | Rx = 10, 211 | RGx = 11, 212 | RGBx = 12, 213 | Depth = 13, 214 | DepthStencil = 14, 215 | sRGB = 15, 216 | sRGBx = 16, 217 | sRGBA = 17, 218 | sBGRA = 18, 219 | }; 220 | 221 | enum class ImageChannelDataType : unsigned { 222 | SnormInt8 = 0, 223 | SnormInt16 = 1, 224 | UnormInt8 = 2, 225 | UnormInt16 = 3, 226 | UnormShort565 = 4, 227 | UnormShort555 = 5, 228 | UnormInt101010 = 6, 229 | SignedInt8 = 7, 230 | SignedInt16 = 8, 231 | SignedInt32 = 9, 232 | UnsignedInt8 = 10, 233 | UnsignedInt16 = 11, 234 | UnsignedInt32 = 12, 235 | HalfFloat = 13, 236 | Float = 14, 237 | UnormInt24 = 15, 238 | }; 239 | 240 | enum class ImageOperandsShift : unsigned { 241 | Bias = 0, 242 | Lod = 1, 243 | Grad = 2, 244 | ConstOffset = 3, 245 | Offset = 4, 246 | ConstOffsets = 5, 247 | Sample = 6, 248 | }; 249 | 250 | enum class ImageOperandsMask : unsigned { 251 | MaskNone = 0, 252 | Bias = 0x00000001, 253 | Lod = 0x00000002, 254 | Grad = 0x00000004, 255 | ConstOffset = 0x00000008, 256 | Offset = 0x00000010, 257 | ConstOffsets = 0x00000020, 258 | Sample = 0x00000040, 259 | }; 260 | 261 | enum class FPFastMathModeShift : unsigned { 262 | NotNaN = 0, 263 | NotInf = 1, 264 | NSZ = 2, 265 | AllowRecip = 3, 266 | Fast = 4, 267 | }; 268 | 269 | enum class FPFastMathModeMask : unsigned { 270 | MaskNone = 0, 271 | NotNaN = 0x00000001, 272 | NotInf = 0x00000002, 273 | NSZ = 0x00000004, 274 | AllowRecip = 0x00000008, 275 | Fast = 0x00000010, 276 | }; 277 | 278 | enum class FPRoundingMode : unsigned { 279 | RTE = 0, 280 | RTZ = 1, 281 | RTP = 2, 282 | RTN = 3, 283 | }; 284 | 285 | enum class LinkageType : unsigned { 286 | Export = 0, 287 | Import = 1, 288 | }; 289 | 290 | enum class AccessQualifier : unsigned { 291 | ReadOnly = 0, 292 | WriteOnly = 1, 293 | ReadWrite = 2, 294 | }; 295 | 296 | enum class FunctionParameterAttribute : unsigned { 297 | Zext = 0, 298 | Sext = 1, 299 | ByVal = 2, 300 | Sret = 3, 301 | NoAlias = 4, 302 | NoCapture = 5, 303 | NoWrite = 6, 304 | NoReadWrite = 7, 305 | }; 306 | 307 | enum class Decoration : unsigned { 308 | RelaxedPrecision = 0, 309 | SpecId = 1, 310 | Block = 2, 311 | BufferBlock = 3, 312 | RowMajor = 4, 313 | ColMajor = 5, 314 | ArrayStride = 6, 315 | MatrixStride = 7, 316 | GLSLShared = 8, 317 | GLSLPacked = 9, 318 | CPacked = 10, 319 | BuiltIn = 11, 320 | Smooth = 12, 321 | Noperspective = 13, 322 | Flat = 14, 323 | Patch = 15, 324 | Centroid = 16, 325 | Sample = 17, 326 | Invariant = 18, 327 | Restrict = 19, 328 | Aliased = 20, 329 | Volatile = 21, 330 | Constant = 22, 331 | Coherent = 23, 332 | Nonwritable = 24, 333 | Nonreadable = 25, 334 | Uniform = 26, 335 | NoStaticUse = 27, 336 | SaturatedConversion = 28, 337 | Stream = 29, 338 | Location = 30, 339 | Component = 31, 340 | Index = 32, 341 | Binding = 33, 342 | DescriptorSet = 34, 343 | Offset = 35, 344 | XfbBuffer = 36, 345 | XfbStride = 37, 346 | FuncParamAttr = 38, 347 | FPRoundingMode = 39, 348 | FPFastMathMode = 40, 349 | LinkageAttributes = 41, 350 | }; 351 | 352 | enum class BuiltIn : unsigned { 353 | Position = 0, 354 | PointSize = 1, 355 | ClipDistance = 3, 356 | CullDistance = 4, 357 | VertexId = 5, 358 | InstanceId = 6, 359 | PrimitiveId = 7, 360 | InvocationId = 8, 361 | Layer = 9, 362 | ViewportIndex = 10, 363 | TessLevelOuter = 11, 364 | TessLevelInner = 12, 365 | TessCoord = 13, 366 | PatchVertices = 14, 367 | FragCoord = 15, 368 | PointCoord = 16, 369 | FrontFacing = 17, 370 | SampleId = 18, 371 | SamplePosition = 19, 372 | SampleMask = 20, 373 | FragColor = 21, 374 | FragDepth = 22, 375 | HelperInvocation = 23, 376 | NumWorkgroups = 24, 377 | WorkgroupSize = 25, 378 | WorkgroupId = 26, 379 | LocalInvocationId = 27, 380 | GlobalInvocationId = 28, 381 | LocalInvocationIndex = 29, 382 | WorkDim = 30, 383 | GlobalSize = 31, 384 | EnqueuedWorkgroupSize = 32, 385 | GlobalOffset = 33, 386 | GlobalLinearId = 34, 387 | WorkgroupLinearId = 35, 388 | SubgroupSize = 36, 389 | SubgroupMaxSize = 37, 390 | NumSubgroups = 38, 391 | NumEnqueuedSubgroups = 39, 392 | SubgroupId = 40, 393 | SubgroupLocalInvocationId = 41, 394 | }; 395 | 396 | enum class SelectionControlShift : unsigned { 397 | Flatten = 0, 398 | DontFlatten = 1, 399 | }; 400 | 401 | enum class SelectionControlMask : unsigned { 402 | MaskNone = 0, 403 | Flatten = 0x00000001, 404 | DontFlatten = 0x00000002, 405 | }; 406 | 407 | enum class LoopControlShift : unsigned { 408 | Unroll = 0, 409 | DontUnroll = 1, 410 | }; 411 | 412 | enum class LoopControlMask : unsigned { 413 | MaskNone = 0, 414 | Unroll = 0x00000001, 415 | DontUnroll = 0x00000002, 416 | }; 417 | 418 | enum class FunctionControlShift : unsigned { 419 | Inline = 0, 420 | DontInline = 1, 421 | Pure = 2, 422 | Const = 3, 423 | }; 424 | 425 | enum class FunctionControlMask : unsigned { 426 | MaskNone = 0, 427 | Inline = 0x00000001, 428 | DontInline = 0x00000002, 429 | Pure = 0x00000004, 430 | Const = 0x00000008, 431 | }; 432 | 433 | enum class MemorySemanticsShift : unsigned { 434 | Relaxed = 0, 435 | SequentiallyConsistent = 1, 436 | Acquire = 2, 437 | Release = 3, 438 | UniformMemory = 4, 439 | SubgroupMemory = 5, 440 | WorkgroupLocalMemory = 6, 441 | WorkgroupGlobalMemory = 7, 442 | AtomicCounterMemory = 8, 443 | ImageMemory = 9, 444 | }; 445 | 446 | enum class MemorySemanticsMask : unsigned { 447 | MaskNone = 0, 448 | Relaxed = 0x00000001, 449 | SequentiallyConsistent = 0x00000002, 450 | Acquire = 0x00000004, 451 | Release = 0x00000008, 452 | UniformMemory = 0x00000010, 453 | SubgroupMemory = 0x00000020, 454 | WorkgroupLocalMemory = 0x00000040, 455 | WorkgroupGlobalMemory = 0x00000080, 456 | AtomicCounterMemory = 0x00000100, 457 | ImageMemory = 0x00000200, 458 | }; 459 | 460 | enum class MemoryAccessShift : unsigned { 461 | Volatile = 0, 462 | Aligned = 1, 463 | }; 464 | 465 | enum class MemoryAccessMask : unsigned { 466 | MaskNone = 0, 467 | Volatile = 0x00000001, 468 | Aligned = 0x00000002, 469 | }; 470 | 471 | enum class Scope : unsigned { 472 | CrossDevice = 0, 473 | Device = 1, 474 | Workgroup = 2, 475 | Subgroup = 3, 476 | Invocation = 4, 477 | }; 478 | 479 | enum class GroupOperation : unsigned { 480 | Reduce = 0, 481 | InclusiveScan = 1, 482 | ExclusiveScan = 2, 483 | }; 484 | 485 | enum class KernelEnqueueFlags : unsigned { 486 | NoWait = 0, 487 | WaitKernel = 1, 488 | WaitWorkGroup = 2, 489 | }; 490 | 491 | enum class KernelProfilingInfoShift : unsigned { 492 | CmdExecTime = 0, 493 | }; 494 | 495 | enum class KernelProfilingInfoMask : unsigned { 496 | MaskNone = 0, 497 | CmdExecTime = 0x00000001, 498 | }; 499 | 500 | enum class Capability : unsigned { 501 | Matrix = 0, 502 | Shader = 1, 503 | Geometry = 2, 504 | Tessellation = 3, 505 | Addresses = 4, 506 | Linkage = 5, 507 | Kernel = 6, 508 | Vector16 = 7, 509 | Float16Buffer = 8, 510 | Float16 = 9, 511 | Float64 = 10, 512 | Int64 = 11, 513 | Int64Atomics = 12, 514 | ImageBasic = 13, 515 | ImageReadWrite = 14, 516 | ImageMipmap = 15, 517 | ImageSRGBWrite = 16, 518 | Pipes = 17, 519 | Groups = 18, 520 | DeviceEnqueue = 19, 521 | LiteralSampler = 20, 522 | AtomicStorage = 21, 523 | Int16 = 22, 524 | TessellationPointSize = 23, 525 | GeometryPointSize = 24, 526 | ImageGatherExtended = 25, 527 | StorageImageExtendedFormats = 26, 528 | StorageImageMultisample = 27, 529 | UniformBufferArrayDynamicIndexing = 28, 530 | SampledImageArrayDynamicIndexing = 29, 531 | StorageBufferArrayDynamicIndexing = 30, 532 | StorageImageArrayDynamicIndexing = 31, 533 | ClipDistance = 32, 534 | CullDistance = 33, 535 | ImageCubeArray = 34, 536 | SampleRateShading = 35, 537 | }; 538 | 539 | enum class Op : unsigned { 540 | OpNop = 0, 541 | OpUndef = 1, 542 | OpSource = 3, 543 | OpSourceExtension = 4, 544 | OpName = 5, 545 | OpMemberName = 6, 546 | OpString = 7, 547 | OpLine = 8, 548 | OpExtension = 10, 549 | OpExtInstImport = 11, 550 | OpExtInst = 12, 551 | OpMemoryModel = 14, 552 | OpEntryPoint = 15, 553 | OpExecutionMode = 16, 554 | OpCapability = 17, 555 | OpTypeVoid = 19, 556 | OpTypeBool = 20, 557 | OpTypeInt = 21, 558 | OpTypeFloat = 22, 559 | OpTypeVector = 23, 560 | OpTypeMatrix = 24, 561 | OpTypeImage = 25, 562 | OpTypeSampler = 26, 563 | OpTypeSampledImage = 27, 564 | OpTypeArray = 28, 565 | OpTypeRuntimeArray = 29, 566 | OpTypeStruct = 30, 567 | OpTypeOpaque = 31, 568 | OpTypePointer = 32, 569 | OpTypeFunction = 33, 570 | OpTypeEvent = 34, 571 | OpTypeDeviceEvent = 35, 572 | OpTypeReserveId = 36, 573 | OpTypeQueue = 37, 574 | OpTypePipe = 38, 575 | OpConstantTrue = 41, 576 | OpConstantFalse = 42, 577 | OpConstant = 43, 578 | OpConstantComposite = 44, 579 | OpConstantSampler = 45, 580 | OpConstantNull = 46, 581 | OpSpecConstantTrue = 48, 582 | OpSpecConstantFalse = 49, 583 | OpSpecConstant = 50, 584 | OpSpecConstantComposite = 51, 585 | OpSpecConstantOp = 52, 586 | OpFunction = 54, 587 | OpFunctionParameter = 55, 588 | OpFunctionEnd = 56, 589 | OpFunctionCall = 57, 590 | OpVariable = 59, 591 | OpImageTexelPointer = 60, 592 | OpLoad = 61, 593 | OpStore = 62, 594 | OpCopyMemory = 63, 595 | OpCopyMemorySized = 64, 596 | OpAccessChain = 65, 597 | OpInBoundsAccessChain = 66, 598 | OpPtrAccessChain = 67, 599 | OpArrayLength = 68, 600 | OpGenericPtrMemSemantics = 69, 601 | OpDecorate = 71, 602 | OpMemberDecorate = 72, 603 | OpDecorationGroup = 73, 604 | OpGroupDecorate = 74, 605 | OpGroupMemberDecorate = 75, 606 | OpVectorExtractDynamic = 77, 607 | OpVectorInsertDynamic = 78, 608 | OpVectorShuffle = 79, 609 | OpCompositeConstruct = 80, 610 | OpCompositeExtract = 81, 611 | OpCompositeInsert = 82, 612 | OpCopyObject = 83, 613 | OpTranspose = 84, 614 | OpSampledImage = 86, 615 | OpImageSampleImplicitLod = 87, 616 | OpImageSampleExplicitLod = 88, 617 | OpImageSampleDrefImplicitLod = 89, 618 | OpImageSampleDrefExplicitLod = 90, 619 | OpImageSampleProjImplicitLod = 91, 620 | OpImageSampleProjExplicitLod = 92, 621 | OpImageSampleProjDrefImplicitLod = 93, 622 | OpImageSampleProjDrefExplicitLod = 94, 623 | OpImageFetch = 95, 624 | OpImageGather = 96, 625 | OpImageDrefGather = 97, 626 | OpImageRead = 98, 627 | OpImageWrite = 99, 628 | OpImageQueryDim = 100, 629 | OpImageQueryFormat = 101, 630 | OpImageQueryOrder = 102, 631 | OpImageQuerySizeLod = 103, 632 | OpImageQuerySize = 104, 633 | OpImageQueryLod = 105, 634 | OpImageQueryLevels = 106, 635 | OpImageQuerySamples = 107, 636 | OpConvertFToU = 109, 637 | OpConvertFToS = 110, 638 | OpConvertSToF = 111, 639 | OpConvertUToF = 112, 640 | OpUConvert = 113, 641 | OpSConvert = 114, 642 | OpFConvert = 115, 643 | OpQuantizeToF16 = 116, 644 | OpConvertPtrToU = 117, 645 | OpSatConvertSToU = 118, 646 | OpSatConvertUToS = 119, 647 | OpConvertUToPtr = 120, 648 | OpPtrCastToGeneric = 121, 649 | OpGenericCastToPtr = 122, 650 | OpGenericCastToPtrExplicit = 123, 651 | OpBitcast = 124, 652 | OpSNegate = 126, 653 | OpFNegate = 127, 654 | OpIAdd = 128, 655 | OpFAdd = 129, 656 | OpISub = 130, 657 | OpFSub = 131, 658 | OpIMul = 132, 659 | OpFMul = 133, 660 | OpUDiv = 134, 661 | OpSDiv = 135, 662 | OpFDiv = 136, 663 | OpUMod = 137, 664 | OpSRem = 138, 665 | OpSMod = 139, 666 | OpFRem = 140, 667 | OpFMod = 141, 668 | OpVectorTimesScalar = 142, 669 | OpMatrixTimesScalar = 143, 670 | OpVectorTimesMatrix = 144, 671 | OpMatrixTimesVector = 145, 672 | OpMatrixTimesMatrix = 146, 673 | OpOuterProduct = 147, 674 | OpDot = 148, 675 | OpIAddCarry = 149, 676 | OpISubBorrow = 150, 677 | OpIMulExtended = 151, 678 | OpAny = 154, 679 | OpAll = 155, 680 | OpIsNan = 156, 681 | OpIsInf = 157, 682 | OpIsFinite = 158, 683 | OpIsNormal = 159, 684 | OpSignBitSet = 160, 685 | OpLessOrGreater = 161, 686 | OpOrdered = 162, 687 | OpUnordered = 163, 688 | OpLogicalEqual = 164, 689 | OpLogicalNotEqual = 165, 690 | OpLogicalOr = 166, 691 | OpLogicalAnd = 167, 692 | OpLogicalNot = 168, 693 | OpSelect = 169, 694 | OpIEqual = 170, 695 | OpINotEqual = 171, 696 | OpUGreaterThan = 172, 697 | OpSGreaterThan = 173, 698 | OpUGreaterThanEqual = 174, 699 | OpSGreaterThanEqual = 175, 700 | OpULessThan = 176, 701 | OpSLessThan = 177, 702 | OpULessThanEqual = 178, 703 | OpSLessThanEqual = 179, 704 | OpFOrdEqual = 180, 705 | OpFUnordEqual = 181, 706 | OpFOrdNotEqual = 182, 707 | OpFUnordNotEqual = 183, 708 | OpFOrdLessThan = 184, 709 | OpFUnordLessThan = 185, 710 | OpFOrdGreaterThan = 186, 711 | OpFUnordGreaterThan = 187, 712 | OpFOrdLessThanEqual = 188, 713 | OpFUnordLessThanEqual = 189, 714 | OpFOrdGreaterThanEqual = 190, 715 | OpFUnordGreaterThanEqual = 191, 716 | OpShiftRightLogical = 194, 717 | OpShiftRightArithmetic = 195, 718 | OpShiftLeftLogical = 196, 719 | OpBitwiseOr = 197, 720 | OpBitwiseXor = 198, 721 | OpBitwiseAnd = 199, 722 | OpNot = 200, 723 | OpBitFieldInsert = 201, 724 | OpBitFieldSExtract = 202, 725 | OpBitFieldUExtract = 203, 726 | OpBitReverse = 204, 727 | OpBitCount = 205, 728 | OpDPdx = 207, 729 | OpDPdy = 208, 730 | OpFwidth = 209, 731 | OpDPdxFine = 210, 732 | OpDPdyFine = 211, 733 | OpFwidthFine = 212, 734 | OpDPdxCoarse = 213, 735 | OpDPdyCoarse = 214, 736 | OpFwidthCoarse = 215, 737 | OpEmitVertex = 218, 738 | OpEndPrimitive = 219, 739 | OpEmitStreamVertex = 220, 740 | OpEndStreamPrimitive = 221, 741 | OpControlBarrier = 224, 742 | OpMemoryBarrier = 225, 743 | OpAtomicLoad = 227, 744 | OpAtomicStore = 228, 745 | OpAtomicExchange = 229, 746 | OpAtomicCompareExchange = 230, 747 | OpAtomicCompareExchangeWeak = 231, 748 | OpAtomicIIncrement = 232, 749 | OpAtomicIDecrement = 233, 750 | OpAtomicIAdd = 234, 751 | OpAtomicISub = 235, 752 | OpAtomicSMin = 236, 753 | OpAtomicUMin = 237, 754 | OpAtomicSMax = 238, 755 | OpAtomicUMax = 239, 756 | OpAtomicAnd = 240, 757 | OpAtomicOr = 241, 758 | OpAtomicXor = 242, 759 | OpPhi = 245, 760 | OpLoopMerge = 246, 761 | OpSelectionMerge = 247, 762 | OpLabel = 248, 763 | OpBranch = 249, 764 | OpBranchConditional = 250, 765 | OpSwitch = 251, 766 | OpKill = 252, 767 | OpReturn = 253, 768 | OpReturnValue = 254, 769 | OpUnreachable = 255, 770 | OpLifetimeStart = 256, 771 | OpLifetimeStop = 257, 772 | OpAsyncGroupCopy = 259, 773 | OpWaitGroupEvents = 260, 774 | OpGroupAll = 261, 775 | OpGroupAny = 262, 776 | OpGroupBroadcast = 263, 777 | OpGroupIAdd = 264, 778 | OpGroupFAdd = 265, 779 | OpGroupFMin = 266, 780 | OpGroupUMin = 267, 781 | OpGroupSMin = 268, 782 | OpGroupFMax = 269, 783 | OpGroupUMax = 270, 784 | OpGroupSMax = 271, 785 | OpReadPipe = 274, 786 | OpWritePipe = 275, 787 | OpReservedReadPipe = 276, 788 | OpReservedWritePipe = 277, 789 | OpReserveReadPipePackets = 278, 790 | OpReserveWritePipePackets = 279, 791 | OpCommitReadPipe = 280, 792 | OpCommitWritePipe = 281, 793 | OpIsValidReserveId = 282, 794 | OpGetNumPipePackets = 283, 795 | OpGetMaxPipePackets = 284, 796 | OpGroupReserveReadPipePackets = 285, 797 | OpGroupReserveWritePipePackets = 286, 798 | OpGroupCommitReadPipe = 287, 799 | OpGroupCommitWritePipe = 288, 800 | OpEnqueueMarker = 291, 801 | OpEnqueueKernel = 292, 802 | OpGetKernelNDrangeSubGroupCount = 293, 803 | OpGetKernelNDrangeMaxSubGroupSize = 294, 804 | OpGetKernelWorkGroupSize = 295, 805 | OpGetKernelPreferredWorkGroupSizeMultiple = 296, 806 | OpRetainEvent = 297, 807 | OpReleaseEvent = 298, 808 | OpCreateUserEvent = 299, 809 | OpIsValidEvent = 300, 810 | OpSetUserEventStatus = 301, 811 | OpCaptureEventProfilingInfo = 302, 812 | OpGetDefaultQueue = 303, 813 | OpBuildNDRange = 304, 814 | 815 | COUNT 816 | }; 817 | 818 | // Overload operator| for mask bit combining 819 | 820 | inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } 821 | inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } 822 | inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } 823 | inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } 824 | inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } 825 | inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } 826 | inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } 827 | inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } 828 | 829 | } // end namespace spv 830 | 831 | #endif // #ifndef spirv_H 832 | 833 | -------------------------------------------------------------------------------- /src/shared/common_ops.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | template 3 | inline int Cmp(Value op1, Value op2) { 4 | T a = *(T*)op1.Memory; 5 | T b = *(T*)op2.Memory; 6 | return a < b ? -1 : a == b ? 0 : 1; 7 | } 8 | 9 | template 10 | inline T Add(Value op1, Value op2) { 11 | T a = *(T*)op1.Memory; 12 | T b = *(T*)op2.Memory; 13 | return a + b; 14 | } 15 | 16 | template 17 | inline T Sub(Value op1, Value op2) { 18 | T a = *(T*)op1.Memory; 19 | T b = *(T*)op2.Memory; 20 | return a - b; 21 | } 22 | 23 | template 24 | inline T Div(Value op1, Value op2) { 25 | T a = *(T*)op1.Memory; 26 | T b = *(T*)op2.Memory; 27 | return a / b; 28 | } 29 | 30 | template 31 | inline T Mul(Value op1, Value op2) { 32 | T a = *(T*)op1.Memory; 33 | T b = *(T*)op2.Memory; 34 | return a * b; 35 | } 36 | 37 | template 38 | inline D Convert(Value op) { 39 | return (D)*(S*)op.Memory; 40 | } 41 | 42 | template 43 | inline T Clamp(Value val, Value min, Value max) { 44 | T tval = *(T*)val.Memory; 45 | T tmin = *(T*)min.Memory; 46 | T tmax = *(T*)max.Memory; 47 | return tval < tmin ? tmin : tval > tmax ? tmax : tval; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/shared/lookups.cpp: -------------------------------------------------------------------------------- 1 | #include "lookups.h" 2 | 3 | void* LUTPointers[] = { 4 | &SourceLanguageStrings, 5 | &ExecutionModelStrings, 6 | &AddressingModelStrings, 7 | &MemoryModelStrings, 8 | &ExecutionModeStrings, 9 | &StorageClassStrings, 10 | &DimStrings, 11 | &SamplerAddressingModeStrings, 12 | &SamplerFilterModeStrings, 13 | &ImageFormatStrings, 14 | &ImageChannelOrderStrings, 15 | &ImageChannelDataTypeStrings, 16 | &ImageOperandsShiftStrings, 17 | &ImageOperandsMaskStrings, 18 | &FPFastMathModeShiftStrings, 19 | &FPFastMathModeMaskStrings, 20 | &FPRoundingModeStrings, 21 | &LinkageTypeStrings, 22 | &AccessQualifierStrings, 23 | &FunctionParameterAttributeStrings, 24 | &DecorationStrings, 25 | &BuiltInStrings, 26 | &SelectionControlStrings, 27 | &SelectionControlShiftStrings, 28 | &SelectionControlMaskStrings, 29 | &LoopControlStrings, 30 | &LoopControlShiftStrings, 31 | &LoopControlMaskStrings, 32 | &FunctionControlStrings, 33 | &FunctionControlShiftStrings, 34 | &FunctionControlMaskStrings, 35 | &MemorySemanticsStrings, 36 | &MemorySemanticsShiftStrings, 37 | &MemorySemanticsMaskStrings, 38 | &MemoryAccessStrings, 39 | &MemoryAccessShiftStrings, 40 | &MemoryAccessMaskStrings, 41 | &ScopeStrings, 42 | &GroupOperationStrings, 43 | &KernelEnqueueFlagsStrings, 44 | &KernelProfilingInfoStrings, 45 | &KernelProfilingInfoShiftStrings, 46 | &KernelProfilingInfoMaskStrings, 47 | &CapabilityStrings, 48 | &OpStrings, 49 | }; -------------------------------------------------------------------------------- /src/shared/lookups.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Khronos/spirv.h" 3 | #include 4 | 5 | using namespace spv; 6 | 7 | enum WordType { 8 | TSourceLanguage, 9 | TExecutionModel, 10 | TAddressingModel, 11 | TMemoryModel, 12 | TExecutionMode, 13 | TStorageClass, 14 | TDim, 15 | TSamplerAddressingMode, 16 | TSamplerFilterMode, 17 | TImageFormat, 18 | TImageChannelOrder, 19 | TImageChannelDataType, 20 | TImageOperandsShift, 21 | TImageOperandsMask, 22 | TFPFastMathModeShift, 23 | TFPFastMathModeMask, 24 | TFPRoundingMode, 25 | TLinkageType, 26 | TAccessQualifier, 27 | TFunctionParameterAttribute, 28 | TDecoration, 29 | TBuiltIn, 30 | TSelectionControl, 31 | TSelectionControlShift, 32 | TSelectionControlMask, 33 | TLoopControl, 34 | TLoopControlShift, 35 | TLoopControlMask, 36 | TFunctionControl, 37 | TFunctionControlShift, 38 | TFunctionControlMask, 39 | TMemorySemantics, 40 | TMemorySemanticsShift, 41 | TMemorySemanticsMask, 42 | TMemoryAccess, 43 | TMemoryAccessShift, 44 | TMemoryAccessMask, 45 | TScope, 46 | TGroupOperation, 47 | TKernelEnqueueFlags, 48 | TKernelProfilingInfo, 49 | TKernelProfilingInfoShift, 50 | TKernelProfilingInfoMask, 51 | TCapability, 52 | TOp, 53 | TId, 54 | TLiteralNumber, 55 | TLiteralString, 56 | TIdList, 57 | TLiteralNumberList 58 | }; 59 | 60 | static std::string SourceLanguageStrings[] { 61 | "Unknown", 62 | "ESSL", 63 | "GLSL", 64 | "OpenCL", 65 | }; 66 | 67 | static std::string ExecutionModelStrings[] { 68 | "Vertex", 69 | "TessellationControl", 70 | "TessellationEvaluation", 71 | "Geometry", 72 | "Fragment", 73 | "GLCompute", 74 | "Kernel", 75 | }; 76 | 77 | static std::string AddressingModelStrings[] { 78 | "Logical", 79 | "Physical32", 80 | "Physical64", 81 | }; 82 | 83 | static std::string MemoryModelStrings[] { 84 | "Simple", 85 | "GLSL450", 86 | "OpenCL", 87 | }; 88 | 89 | static std::string ExecutionModeStrings[] { 90 | "Invocations", 91 | "SpacingEqual", 92 | "SpacingFractionalEven", 93 | "SpacingFractionalOdd", 94 | "VertexOrderCw", 95 | "VertexOrderCcw", 96 | "PixelCenterInteger", 97 | "OriginUpperLeft", 98 | "OriginLowerLeft", 99 | "EarlyFragmentTests", 100 | "PointMode", 101 | "Xfb", 102 | "DepthReplacing", 103 | "DepthAny", 104 | "DepthGreater", 105 | "DepthLess", 106 | "DepthUnchanged", 107 | "LocalSize", 108 | "LocalSizeHint", 109 | "InputPoints", 110 | "InputLines", 111 | "InputLinesAdjacency", 112 | "InputTriangles", 113 | "InputTrianglesAdjacency", 114 | "InputQuads", 115 | "InputIsolines", 116 | "OutputVertices", 117 | "OutputPoints", 118 | "OutputLineStrip", 119 | "OutputTriangleStrip", 120 | "VecTypeHint", 121 | "ContractionOff", 122 | }; 123 | 124 | static std::string StorageClassStrings[] { 125 | "UniformConstant", 126 | "Input", 127 | "Uniform", 128 | "Output", 129 | "WorkgroupLocal", 130 | "WorkgroupGlobal", 131 | "PrivateGlobal", 132 | "Function", 133 | "Generic", 134 | "AtomicCounter", 135 | "Image", 136 | }; 137 | 138 | static std::string DimStrings[] { 139 | "1D", 140 | "2D", 141 | "3D", 142 | "Cube", 143 | "Rect", 144 | "Buffer", 145 | }; 146 | 147 | static std::string SamplerAddressingModeStrings[] { 148 | "None", 149 | "ClampToEdge", 150 | "Clamp", 151 | "Repeat", 152 | "RepeatMirrored", 153 | }; 154 | 155 | static std::string SamplerFilterModeStrings[] { 156 | "Nearest", 157 | "Linear", 158 | }; 159 | 160 | static std::string ImageFormatStrings[] { 161 | "Unknown", 162 | "Rgba32f", 163 | "Rgba16f", 164 | "R32f", 165 | "Rgba8", 166 | "Rgba8Snorm", 167 | "Rg32f", 168 | "Rg16f", 169 | "R11fG11fB10f", 170 | "R16f", 171 | "Rgba16", 172 | "Rgb10A2", 173 | "Rg16", 174 | "Rg8", 175 | "R16", 176 | "R8", 177 | "Rgba16Snorm", 178 | "Rg16Snorm", 179 | "Rg8Snorm", 180 | "R16Snorm", 181 | "R8Snorm", 182 | "Rgba32i", 183 | "Rgba16i", 184 | "Rgba8i", 185 | "R32i", 186 | "Rg32i", 187 | "Rg16i", 188 | "Rg8i", 189 | "R16i", 190 | "R8i", 191 | "Rgba32ui", 192 | "Rgba16ui", 193 | "Rgba8ui", 194 | "R32ui", 195 | "Rgb10a2ui", 196 | "Rg32ui", 197 | "Rg16ui", 198 | "Rg8ui", 199 | "R16ui", 200 | "R8ui", 201 | }; 202 | 203 | static std::string ImageChannelOrderStrings[] { 204 | "R", 205 | "A", 206 | "RG", 207 | "RA", 208 | "RGB", 209 | "RGBA", 210 | "BGRA", 211 | "ARGB", 212 | "Intensity", 213 | "Luminance", 214 | "Rx", 215 | "RGx", 216 | "RGBx", 217 | "Depth", 218 | "DepthStencil", 219 | "sRGB", 220 | "sRGBx", 221 | "sRGBA", 222 | "sBGRA", 223 | }; 224 | 225 | static std::string ImageChannelDataTypeStrings[] { 226 | "SnormInt8", 227 | "SnormInt16", 228 | "UnormInt8", 229 | "UnormInt16", 230 | "UnormShort565", 231 | "UnormShort555", 232 | "UnormInt101010", 233 | "SignedInt8", 234 | "SignedInt16", 235 | "SignedInt32", 236 | "UnsignedInt8", 237 | "UnsignedInt16", 238 | "UnsignedInt32", 239 | "HalfFloat", 240 | "Float", 241 | "UnormInt24", 242 | }; 243 | 244 | static std::string ImageOperandsShiftStrings[] { 245 | "Bias", 246 | "Lod", 247 | "Grad", 248 | "ConstOffset", 249 | "Offset", 250 | "ConstOffsets", 251 | "Sample", 252 | }; 253 | 254 | static std::string ImageOperandsMaskStrings[] { 255 | "MaskNone", 256 | "Bias", 257 | "Lod", 258 | "Grad", 259 | "ConstOffset", 260 | "Offset", 261 | "ConstOffsets", 262 | "Sample", 263 | }; 264 | 265 | static std::string FPFastMathModeShiftStrings[] { 266 | "NotNaNShift", 267 | "NotInfShift", 268 | "NSZShift", 269 | "AllowRecipShift", 270 | "FastShift", 271 | }; 272 | 273 | static std::string FPFastMathModeMaskStrings[] { 274 | "MaskNone", 275 | "NotNaNMask", 276 | "NotInfMask", 277 | "NSZMask", 278 | "AllowRecipMask", 279 | "FastMask", 280 | }; 281 | 282 | static std::string FPRoundingModeStrings[] { 283 | "RTE", 284 | "RTZ", 285 | "RTP", 286 | "RTN", 287 | }; 288 | 289 | static std::string LinkageTypeStrings[] { 290 | "Export", 291 | "Import", 292 | }; 293 | 294 | static std::string AccessQualifierStrings[] { 295 | "ReadOnly", 296 | "WriteOnly", 297 | "ReadWrite", 298 | }; 299 | 300 | static std::string FunctionParameterAttributeStrings[] { 301 | "Zext", 302 | "Sext", 303 | "ByVal", 304 | "Sret", 305 | "NoAlias", 306 | "NoCapture", 307 | "SVM", 308 | "NoWrite", 309 | "NoReadWrite", 310 | }; 311 | 312 | static std::string DecorationStrings[] { 313 | "RelaxedPrecision", 314 | "SpecId", 315 | "Block", 316 | "BufferBlock", 317 | "RowMajor", 318 | "ColMajor", 319 | "ArrayStride", 320 | "MatrixStride", 321 | "GLSLShared", 322 | "GLSLPacked", 323 | "CPacked", 324 | "BuiltIn", 325 | "Smooth", 326 | "Noperspective", 327 | "Flat", 328 | "Patch", 329 | "Centroid", 330 | "Sample", 331 | "Invariant", 332 | "Restrict", 333 | "Aliased", 334 | "Volatile", 335 | "Constant", 336 | "Coherent", 337 | "Nonwritable", 338 | "Nonreadable", 339 | "Uniform", 340 | "NoStaticUse", 341 | "SaturatedConversion", 342 | "Stream", 343 | "Location", 344 | "Component", 345 | "Index", 346 | "Binding", 347 | "DescriptorSet", 348 | "Offset", 349 | "XfbBuffer", 350 | "XfbStride", 351 | "FuncParamAttr", 352 | "FPRoundingMode", 353 | "FPFastMathMode", 354 | "LinkageAttributes", 355 | }; 356 | 357 | static std::string BuiltInStrings[] { 358 | "Position", 359 | "PointSize", 360 | "ClipDistance", 361 | "CullDistance", 362 | "VertexId", 363 | "InstanceId", 364 | "PrimitiveId", 365 | "InvocationId", 366 | "Layer", 367 | "ViewportIndex", 368 | "TessLevelOuter", 369 | "TessLevelInner", 370 | "TessCoord", 371 | "PatchVertices", 372 | "FragCoord", 373 | "PointCoord", 374 | "FrontFacing", 375 | "SampleId", 376 | "SamplePosition", 377 | "SampleMask", 378 | "FragColor", 379 | "FragDepth", 380 | "HelperInvocation", 381 | "NumWorkgroups", 382 | "WorkgroupSize", 383 | "WorkgroupId", 384 | "LocalInvocationId", 385 | "GlobalInvocationId", 386 | "LocalInvocationIndex", 387 | "WorkDim", 388 | "GlobalSize", 389 | "EnqueuedWorkgroupSize", 390 | "GlobalOffset", 391 | "GlobalLinearId", 392 | "WorkgroupLinearId", 393 | "SubgroupSize", 394 | "SubgroupMaxSize", 395 | "NumSubgroups", 396 | "NumEnqueuedSubgroups", 397 | "SubgroupId", 398 | "SubgroupLocalInvocationId", 399 | }; 400 | 401 | static std::string SelectionControlStrings[]{ 402 | "Flatten", 403 | "DontFlatten", 404 | }; 405 | 406 | static std::string SelectionControlShiftStrings[] { 407 | "FlattenShift", 408 | "DontFlattenShift", 409 | }; 410 | 411 | static std::string SelectionControlMaskStrings[] { 412 | "MaskNone", 413 | "FlattenMask", 414 | "DontFlattenMask", 415 | }; 416 | 417 | static std::string LoopControlStrings[]{ 418 | "Unroll", 419 | "DontUnroll", 420 | }; 421 | 422 | static std::string LoopControlShiftStrings[] { 423 | "UnrollShift", 424 | "DontUnrollShift", 425 | }; 426 | 427 | static std::string LoopControlMaskStrings[] { 428 | "MaskNone", 429 | "UnrollMask", 430 | "DontUnrollMask", 431 | }; 432 | 433 | static std::string FunctionControlStrings[]{ 434 | "Inline", 435 | "DontInline", 436 | "Pure", 437 | "Const", 438 | }; 439 | 440 | static std::string FunctionControlShiftStrings[] { 441 | "InlineShift", 442 | "DontInlineShift", 443 | "PureShift", 444 | "ConstShift", 445 | }; 446 | 447 | static std::string FunctionControlMaskStrings[] { 448 | "MaskNone", 449 | "InlineMask", 450 | "DontInlineMask", 451 | "PureMask", 452 | "ConstMask", 453 | }; 454 | 455 | static std::string MemorySemanticsStrings[]{ 456 | "Relaxed", 457 | "SequentiallyConsistent", 458 | "Acquire", 459 | "Release", 460 | "UniformMemory", 461 | "SubgroupMemory", 462 | "WorkgroupLocalMemory", 463 | "WorkgroupGlobalMemory", 464 | "AtomicCounterMemory", 465 | "ImageMemory", 466 | }; 467 | 468 | static std::string MemorySemanticsShiftStrings[] { 469 | "RelaxedShift", 470 | "SequentiallyConsistentShift", 471 | "AcquireShift", 472 | "ReleaseShift", 473 | "UniformMemoryShift", 474 | "SubgroupMemoryShift", 475 | "WorkgroupLocalMemoryShift", 476 | "WorkgroupGlobalMemoryShift", 477 | "AtomicCounterMemoryShift", 478 | "ImageMemoryShift", 479 | }; 480 | 481 | static std::string MemorySemanticsMaskStrings[] { 482 | "MaskNone", 483 | "RelaxedMask", 484 | "SequentiallyConsistentMask", 485 | "AcquireMask", 486 | "ReleaseMask", 487 | "UniformMemoryMask", 488 | "SubgroupMemoryMask", 489 | "WorkgroupLocalMemoryMask", 490 | "WorkgroupGlobalMemoryMask", 491 | "AtomicCounterMemoryMask", 492 | "ImageMemoryMask", 493 | }; 494 | 495 | static std::string MemoryAccessStrings[]{ 496 | "Volatile", 497 | "Aligned", 498 | }; 499 | 500 | static std::string MemoryAccessShiftStrings[] { 501 | "VolatileShift", 502 | "AlignedShift", 503 | }; 504 | 505 | static std::string MemoryAccessMaskStrings[] { 506 | "MaskNone", 507 | "VolatileMask", 508 | "AlignedMask", 509 | }; 510 | 511 | static std::string ScopeStrings[] { 512 | "CrossDevice", 513 | "Device", 514 | "Workgroup", 515 | "Subgroup", 516 | "Invocation", 517 | }; 518 | 519 | static std::string GroupOperationStrings[] { 520 | "Reduce", 521 | "InclusiveScan", 522 | "ExclusiveScan", 523 | }; 524 | 525 | static std::string KernelEnqueueFlagsStrings[] { 526 | "NoWait", 527 | "WaitKernel", 528 | "WaitWorkGroup", 529 | }; 530 | 531 | static std::string KernelProfilingInfoStrings[]{ 532 | "CmdExecTime", 533 | }; 534 | 535 | static std::string KernelProfilingInfoShiftStrings[] { 536 | "CmdExecTimeShift", 537 | }; 538 | 539 | static std::string KernelProfilingInfoMaskStrings[] { 540 | "MaskNone", 541 | "CmdExecTimeMask", 542 | }; 543 | 544 | static std::string CapabilityStrings[] { 545 | "Matrix", 546 | "Shader", 547 | "Geometry", 548 | "Tessellation", 549 | "Addresses", 550 | "Linkage", 551 | "Kernel", 552 | "Vector16", 553 | "Float16Buffer", 554 | "Float16", 555 | "Float64", 556 | "Int64", 557 | "Int64Atomics", 558 | "ImageBasic", 559 | "ImageReadWrite", 560 | "ImageMipmap", 561 | "ImageSRGBWrite", 562 | "Pipes", 563 | "Groups", 564 | "DeviceEnqueue", 565 | "LiteralSampler", 566 | "AtomicStorage", 567 | "Int16", 568 | "TessellationPointSize", 569 | "GeometryPointSize", 570 | "ImageGatherExtended", 571 | "StorageImageExtendedFormats", 572 | "StorageImageMultisample", 573 | "UniformBufferArrayDynamicIndexing", 574 | "SampledImageArrayDynamicIndexing", 575 | "StorageBufferArrayDynamicIndexing", 576 | "StorageImageArrayDynamicIndexing", 577 | "ClipDistance", 578 | "CullDistance", 579 | "ImageCubeArray", 580 | "SampleRateShading", 581 | }; 582 | 583 | static std::string OpStrings[(int)spv::Op::COUNT+1]{ 584 | "Nop", 585 | "Undef", 586 | "", 587 | "Source", 588 | "SourceExtension", 589 | "Name", 590 | "MemberName", 591 | "String", 592 | "Line", 593 | "", 594 | "Extension", 595 | "ExtInstImport", 596 | "ExtInst", 597 | "", 598 | "MemoryModel", 599 | "EntryPoint", 600 | "ExecutionMode", 601 | "Capability", 602 | "", 603 | "TypeVoid", 604 | "TypeBool", 605 | "TypeInt", 606 | "TypeFloat", 607 | "TypeVector", 608 | "TypeMatrix", 609 | "TypeImage", 610 | "TypeSampler", 611 | "TypeSampledImage", 612 | "TypeArray", 613 | "TypeRuntimeArray", 614 | "TypeStruct", 615 | "TypeOpaque", 616 | "TypePointer", 617 | "TypeFunction", 618 | "TypeEvent", 619 | "TypeDeviceEvent", 620 | "TypeReserveId", 621 | "TypeQueue", 622 | "TypePipe", 623 | "", 624 | "", 625 | "ConstantTrue", 626 | "ConstantFalse", 627 | "Constant", 628 | "ConstantComposite", 629 | "ConstantSampler", 630 | "ConstantNull", 631 | "", 632 | "SpecConstantTrue", 633 | "SpecConstantFalse", 634 | "SpecConstant", 635 | "SpecConstantComposite", 636 | "SpecConstantOp", 637 | "", 638 | "Function", 639 | "FunctionParameter", 640 | "FunctionEnd", 641 | "FunctionCall", 642 | "", 643 | "Variable", 644 | "ImageTexelPointer", 645 | "Load", 646 | "Store", 647 | "CopyMemory", 648 | "CopyMemorySized", 649 | "AccessChain", 650 | "InBoundsAccessChain", 651 | "PtrAccessChain", 652 | "ArrayLength", 653 | "GenericPtrMemSemantics", 654 | "", 655 | "Decorate", 656 | "MemberDecorate", 657 | "DecorationGroup", 658 | "GroupDecorate", 659 | "GroupMemberDecorate", 660 | "", 661 | "VectorExtractDynamic", 662 | "VectorInsertDynamic", 663 | "VectorShuffle", 664 | "CompositeConstruct", 665 | "CompositeExtract", 666 | "CompositeInsert", 667 | "CopyObject", 668 | "Transpose", 669 | "", 670 | "SampledImage", 671 | "ImageSampleImplicitLod", 672 | "ImageSampleExplicitLod", 673 | "ImageSampleDrefImplicitLod", 674 | "ImageSampleDrefExplicitLod", 675 | "ImageSampleProjImplicitLod", 676 | "ImageSampleProjExplicitLod", 677 | "ImageSampleProjDrefImplicitLod", 678 | "ImageSampleProjDrefExplicitLod", 679 | "ImageFetch", 680 | "ImageGather", 681 | "ImageDrefGather", 682 | "ImageRead", 683 | "ImageWrite", 684 | "ImageQueryDim", 685 | "ImageQueryFormat", 686 | "ImageQueryOrder", 687 | "ImageQuerySizeLod", 688 | "ImageQuerySize", 689 | "ImageQueryLod", 690 | "ImageQueryLevels", 691 | "ImageQuerySamples", 692 | "", 693 | "ConvertFToU", 694 | "ConvertFToS", 695 | "ConvertSToF", 696 | "ConvertUToF", 697 | "UConvert", 698 | "SConvert", 699 | "FConvert", 700 | "QuantizeToF16", 701 | "ConvertPtrToU", 702 | "SatConvertSToU", 703 | "SatConvertUToS", 704 | "ConvertUToPtr", 705 | "PtrCastToGeneric", 706 | "GenericCastToPtr", 707 | "GenericCastToPtrExplicit", 708 | "Bitcast", 709 | "", 710 | "SNegate", 711 | "FNegate", 712 | "IAdd", 713 | "FAdd", 714 | "ISub", 715 | "FSub", 716 | "IMul", 717 | "FMul", 718 | "UDiv", 719 | "SDiv", 720 | "FDiv", 721 | "UMod", 722 | "SRem", 723 | "SMod", 724 | "FRem", 725 | "FMod", 726 | "VectorTimesScalar", 727 | "MatrixTimesScalar", 728 | "VectorTimesMatrix", 729 | "MatrixTimesVector", 730 | "MatrixTimesMatrix", 731 | "OuterProduct", 732 | "Dot", 733 | "IAddCarry", 734 | "ISubBorrow", 735 | "IMulExtended", 736 | "", 737 | "", 738 | "Any", 739 | "All", 740 | "IsNan", 741 | "IsInf", 742 | "IsFinite", 743 | "IsNormal", 744 | "SignBitSet", 745 | "LessOrGreater", 746 | "Ordered", 747 | "Unordered", 748 | "LogicalEqual", 749 | "LogicalNotEqual", 750 | "LogicalOr", 751 | "LogicalAnd", 752 | "LogicalNot", 753 | "Select", 754 | "IEqual", 755 | "INotEqual", 756 | "UGreaterThan", 757 | "SGreaterThan", 758 | "UGreaterThanEqual", 759 | "SGreaterThanEqual", 760 | "ULessThan", 761 | "SLessThan", 762 | "ULessThanEqual", 763 | "SLessThanEqual", 764 | "FOrdEqual", 765 | "FUnordEqual", 766 | "FOrdNotEqual", 767 | "FUnordNotEqual", 768 | "FOrdLessThan", 769 | "FUnordLessThan", 770 | "FOrdGreaterThan", 771 | "FUnordGreaterThan", 772 | "FOrdLessThanEqual", 773 | "FUnordLessThanEqual", 774 | "FOrdGreaterThanEqual", 775 | "FUnordGreaterThanEqual", 776 | "", 777 | "", 778 | "ShiftRightLogical", 779 | "ShiftRightArithmetic", 780 | "ShiftLeftLogical", 781 | "BitwiseOr", 782 | "BitwiseXor", 783 | "BitwiseAnd", 784 | "Not", 785 | "BitFieldInsert", 786 | "BitFieldSExtract", 787 | "BitFieldUExtract", 788 | "BitReverse", 789 | "BitCount", 790 | "", 791 | "DPdx", 792 | "DPdy", 793 | "Fwidth", 794 | "DPdxFine", 795 | "DPdyFine", 796 | "FwidthFine", 797 | "DPdxCoarse", 798 | "DPdyCoarse", 799 | "FwidthCoarse", 800 | "", 801 | "", 802 | "EmitVertex", 803 | "EndPrimitive", 804 | "EmitStreamVertex", 805 | "EndStreamPrimitive", 806 | "", 807 | "", 808 | "ControlBarrier", 809 | "MemoryBarrier", 810 | "", 811 | "AtomicLoad", 812 | "AtomicStore", 813 | "AtomicExchange", 814 | "AtomicCompareExchange", 815 | "AtomicCompareExchangeWeak", 816 | "AtomicIIncrement", 817 | "AtomicIDecrement", 818 | "AtomicIAdd", 819 | "AtomicISub", 820 | "AtomicSMin", 821 | "AtomicUMin", 822 | "AtomicSMax", 823 | "AtomicUMax", 824 | "AtomicAnd", 825 | "AtomicOr", 826 | "AtomicXor", 827 | "", 828 | "", 829 | "Phi", 830 | "LoopMerge", 831 | "SelectionMerge", 832 | "Label", 833 | "Branch", 834 | "BranchConditional", 835 | "Switch", 836 | "Kill", 837 | "Return", 838 | "ReturnValue", 839 | "Unreachable", 840 | "LifetimeStart", 841 | "LifetimeStop", 842 | "", 843 | "AsyncGroupCopy", 844 | "WaitGroupEvents", 845 | "GroupAll", 846 | "GroupAny", 847 | "GroupBroadcast", 848 | "GroupIAdd", 849 | "GroupFAdd", 850 | "GroupFMin", 851 | "GroupUMin", 852 | "GroupSMin", 853 | "GroupFMax", 854 | "GroupUMax", 855 | "GroupSMax", 856 | "", 857 | "", 858 | "ReadPipe", 859 | "WritePipe", 860 | "ReservedReadPipe", 861 | "ReservedWritePipe", 862 | "ReserveReadPipePackets", 863 | "ReserveWritePipePackets", 864 | "CommitReadPipe", 865 | "CommitWritePipe", 866 | "IsValidReserveId", 867 | "GetNumPipePackets", 868 | "GetMaxPipePackets", 869 | "GroupReserveReadPipePackets", 870 | "GroupReserveWritePipePackets", 871 | "GroupCommitReadPipe", 872 | "GroupCommitWritePipe", 873 | "", 874 | "", 875 | "", 876 | "EnqueueMarker", 877 | "EnqueueKernel", 878 | "GetKernelNDrangeSubGroupCount", 879 | "GetKernelNDrangeMaxSubGroupSize", 880 | "GetKernelWorkGroupSize", 881 | "GetKernelPreferredWorkGroupSizeMultiple", 882 | "RetainEvent", 883 | "ReleaseEvent", 884 | "CreateUserEvent", 885 | "IsValidEvent", 886 | "SetUserEventStatus", 887 | "CaptureEventProfilingInfo", 888 | "GetDefaultQueue", 889 | "BuildNDRange", 890 | }; 891 | 892 | extern void* LUTPointers[]; -------------------------------------------------------------------------------- /src/shared/parser_definitions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "types.h" 9 | #include "lookups.h" 10 | #include "lookups_gen.h" 11 | 12 | struct SOp { 13 | spv::Op Op; 14 | void* Memory; 15 | }; 16 | 17 | struct Block { 18 | SOp MergeInfo; 19 | SOp BranchInfo; 20 | uint32 Id; 21 | std::vector Ops; 22 | std::vector Children; 23 | }; 24 | 25 | 26 | struct Function { 27 | SFunction Info; 28 | std::vector Parameters; 29 | std::vector Ops; 30 | std::map Blocks; 31 | std::map Variables; 32 | std::map Labels; 33 | }; 34 | 35 | struct ParseFunction : public Function { 36 | std::stack BlockStack; 37 | Block* CurrentBlock; 38 | bool InBlock = false; 39 | SOp NextBranchInfo = SOp{ Op::OpNop, nullptr }; 40 | SOp NextMergeInfo = SOp{ Op::OpNop, nullptr }; 41 | }; 42 | 43 | 44 | struct Program { 45 | uint32 Version; 46 | uint32 GeneratorMagic; 47 | uint32 IDBound; 48 | uint32 InstructionSchema; 49 | SSource SourceLanguage; 50 | SMemoryModel MemoryModel; 51 | std::vector SourceExtensions; 52 | std::vector SPIRVExtensions; 53 | 54 | std::map Strings; 55 | std::map Names; 56 | std::map MemberNames; 57 | std::map Lines; 58 | 59 | std::map EntryPoints; 60 | std::map ExecutionModes; 61 | std::map ExtensionImports; 62 | std::map DefinedTypes; 63 | std::map Constants; 64 | std::map Variables; 65 | 66 | std::map FunctionDeclarations; 67 | std::map FunctionDefinitions; 68 | std::vector Ops; 69 | }; 70 | 71 | struct ParseProgram : public Program { 72 | SOp NextOp; 73 | ParseFunction* CurrentFunction; 74 | bool InFunction = false; 75 | }; 76 | 77 | static void addVariable(ParseProgram* prog, SVariable var) { 78 | if (prog->InFunction) { 79 | prog->CurrentFunction->Variables.insert({var.ResultId, var }); 80 | } 81 | else { 82 | prog->Variables.insert({var.ResultId, var}); 83 | } 84 | } 85 | 86 | static Block* getBlock(ParseProgram* prog, uint32 id) { 87 | return &prog->CurrentFunction->Blocks.find(id)->second; 88 | } 89 | 90 | static void startNewBlock(ParseProgram* prog, SLabel label) { 91 | assert(prog->InFunction && !prog->CurrentFunction->InBlock); 92 | prog->CurrentFunction->Blocks.insert({label.ResultId, Block()}); 93 | Block* newBlockPtr = getBlock(prog, label.ResultId); 94 | 95 | getBlock(prog, prog->CurrentFunction->BlockStack.top())->Children.push_back(label.ResultId); 96 | 97 | newBlockPtr->Ops.clear(); 98 | newBlockPtr->Id = label.ResultId; 99 | newBlockPtr->BranchInfo = prog->CurrentFunction->NextBranchInfo; 100 | prog->CurrentFunction->NextBranchInfo = SOp{ Op::OpNop, nullptr }; 101 | newBlockPtr->MergeInfo = prog->CurrentFunction->NextMergeInfo; 102 | prog->CurrentFunction->NextMergeInfo = SOp{ Op::OpNop, nullptr }; 103 | prog->CurrentFunction->InBlock = true; 104 | 105 | if (newBlockPtr->MergeInfo.Memory != nullptr) { 106 | prog->CurrentFunction->BlockStack.push(label.ResultId); 107 | } 108 | 109 | prog->CurrentFunction->CurrentBlock = newBlockPtr; 110 | } 111 | 112 | static void startLoop(ParseProgram* prog, SLoopMerge* loop) { 113 | assert(prog->InFunction && prog->CurrentFunction->InBlock); 114 | prog->CurrentFunction->NextMergeInfo = SOp{ Op::OpLoopMerge, loop }; 115 | } 116 | 117 | static void startSelection(ParseProgram* prog, SSelectionMerge* selection) { 118 | assert(prog->InFunction && prog->CurrentFunction->InBlock); 119 | prog->CurrentFunction->NextMergeInfo = SOp{ Op::OpSelectionMerge, selection}; 120 | } 121 | 122 | static void endBlock(ParseProgram* prog, SOp branchInfo) { 123 | assert(prog->InFunction && prog->CurrentFunction->InBlock); 124 | 125 | prog->CurrentFunction->InBlock = false; 126 | 127 | prog->CurrentFunction->NextBranchInfo = branchInfo; 128 | 129 | prog->CurrentFunction->CurrentBlock = getBlock(prog, prog->CurrentFunction->BlockStack.top()); 130 | 131 | if (prog->CurrentFunction->CurrentBlock->MergeInfo.Memory == nullptr) { 132 | return; 133 | } 134 | 135 | int mergeId = *((uint32*)prog->CurrentFunction->CurrentBlock->MergeInfo.Memory); 136 | assert(prog->NextOp.Op == Op::OpLabel); 137 | int labelId = *((uint32*)prog->NextOp.Memory); 138 | 139 | if (labelId == mergeId) { 140 | prog->CurrentFunction->CurrentBlock = getBlock(prog, prog->CurrentFunction->BlockStack.top()); 141 | prog->CurrentFunction->BlockStack.pop(); 142 | } 143 | } 144 | 145 | static void startFunction(ParseProgram* prog, const SFunction& func) { 146 | assert(!prog->InFunction); 147 | 148 | prog->CurrentFunction = new ParseFunction(); 149 | prog->CurrentFunction->Info = func; 150 | prog->InFunction = true; 151 | prog->CurrentFunction->Blocks.insert(std::pair(0, Block())); 152 | prog->CurrentFunction->CurrentBlock = getBlock(prog, 0); 153 | prog->CurrentFunction->BlockStack.push(0); 154 | } 155 | 156 | static void endFunction(ParseProgram* prog) { 157 | assert(prog->InFunction); 158 | if (prog->CurrentFunction->InBlock) { 159 | endBlock(prog, SOp{ Op::OpNop, nullptr }); 160 | } 161 | assert(prog->CurrentFunction->BlockStack.top() == 0); 162 | 163 | prog->CurrentFunction->BlockStack.pop(); 164 | assert(prog->CurrentFunction->BlockStack.size() == 0); 165 | 166 | if (prog->CurrentFunction->Blocks.size() == 1) { 167 | prog->FunctionDeclarations.insert({prog->CurrentFunction->Info.ResultId, (Function)*prog->CurrentFunction}); 168 | } else { 169 | prog->FunctionDefinitions.insert({prog->CurrentFunction->Info.ResultId, (Function)*prog->CurrentFunction}); 170 | } 171 | prog->InFunction = false; 172 | } 173 | 174 | static void addLabel(ParseProgram* prog, SLabel* label) { 175 | assert(prog->InFunction); 176 | prog->CurrentFunction->Labels[label->ResultId] = (uint32)prog->CurrentFunction->Ops.size(); 177 | } 178 | 179 | static void addOp(ParseProgram* prog, SOp op) { 180 | prog->CurrentFunction->Ops.push_back(op); 181 | prog->CurrentFunction->CurrentBlock->Ops.push_back(op); 182 | } 183 | -------------------------------------------------------------------------------- /src/shared/stb/stb_image_write.h: -------------------------------------------------------------------------------- 1 | /* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h 2 | writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 3 | no warranty implied; use at your own risk 4 | 5 | 6 | Before #including, 7 | 8 | #define STB_IMAGE_WRITE_IMPLEMENTATION 9 | 10 | in the file that you want to have the implementation. 11 | 12 | Will probably not work correctly with strict-aliasing optimizations. 13 | 14 | ABOUT: 15 | 16 | This header file is a library for writing images to C stdio. It could be 17 | adapted to write to memory or a general streaming interface; let me know. 18 | 19 | The PNG output is not optimal; it is 20-50% larger than the file 20 | written by a decent optimizing implementation. This library is designed 21 | for source code compactness and simplicitly, not optimal image file size 22 | or run-time performance. 23 | 24 | BUILDING: 25 | 26 | You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. 27 | You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace 28 | malloc,realloc,free. 29 | You can define STBIW_MEMMOVE() to replace memmove() 30 | 31 | USAGE: 32 | 33 | There are four functions, one for each image file format: 34 | 35 | int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 36 | int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 37 | int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); 38 | int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data); 39 | 40 | Each function returns 0 on failure and non-0 on success. 41 | 42 | The functions create an image file defined by the parameters. The image 43 | is a rectangle of pixels stored from left-to-right, top-to-bottom. 44 | Each pixel contains 'comp' channels of data stored interleaved with 8-bits 45 | per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is 46 | monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. 47 | The *data pointer points to the first byte of the top-left-most pixel. 48 | For PNG, "stride_in_bytes" is the distance in bytes from the first byte of 49 | a row of pixels to the first byte of the next row of pixels. 50 | 51 | PNG creates output files with the same number of components as the input. 52 | The BMP format expands Y to RGB in the file format and does not 53 | output alpha. 54 | 55 | PNG supports writing rectangles of data even when the bytes storing rows of 56 | data are not consecutive in memory (e.g. sub-rectangles of a larger image), 57 | by supplying the stride between the beginning of adjacent rows. The other 58 | formats do not. (Thus you cannot write a native-format BMP through the BMP 59 | writer, both because it is in BGR order and because it may have padding 60 | at the end of the line.) 61 | 62 | HDR expects linear float data. Since the format is always 32-bit rgb(e) 63 | data, alpha (if provided) is discarded, and for monochrome data it is 64 | replicated across all three channels. 65 | 66 | CREDITS: 67 | 68 | PNG/BMP/TGA 69 | Sean Barrett 70 | HDR 71 | Baldur Karlsson 72 | TGA monochrome: 73 | Jean-Sebastien Guay 74 | misc enhancements: 75 | Tim Kelsey 76 | bugfixes: 77 | github:Chribba 78 | */ 79 | 80 | #ifndef INCLUDE_STB_IMAGE_WRITE_H 81 | #define INCLUDE_STB_IMAGE_WRITE_H 82 | 83 | #ifdef __cplusplus 84 | extern "C" { 85 | #endif 86 | 87 | extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 88 | extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 89 | extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); 90 | extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif//INCLUDE_STB_IMAGE_WRITE_H 97 | 98 | #ifdef STB_IMAGE_WRITE_IMPLEMENTATION 99 | 100 | #include 101 | #include 102 | #include 103 | #include 104 | #include 105 | 106 | #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC) 107 | // ok 108 | #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) 109 | // ok 110 | #else 111 | #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC." 112 | #endif 113 | 114 | #ifndef STBIW_MALLOC 115 | #define STBIW_MALLOC(sz) malloc(sz) 116 | #define STBIW_REALLOC(p,sz) realloc(p,sz) 117 | #define STBIW_FREE(p) free(p) 118 | #endif 119 | #ifndef STBIW_MEMMOVE 120 | #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) 121 | #endif 122 | 123 | 124 | #ifndef STBIW_ASSERT 125 | #include 126 | #define STBIW_ASSERT(x) assert(x) 127 | #endif 128 | 129 | typedef unsigned int stbiw_uint32; 130 | typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; 131 | 132 | static void writefv(FILE *f, const char *fmt, va_list v) 133 | { 134 | while (*fmt) { 135 | switch (*fmt++) { 136 | case ' ': break; 137 | case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; } 138 | case '2': { int x = va_arg(v,int); unsigned char b[2]; 139 | b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8); 140 | fwrite(b,2,1,f); break; } 141 | case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4]; 142 | b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8); 143 | b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24); 144 | fwrite(b,4,1,f); break; } 145 | default: 146 | STBIW_ASSERT(0); 147 | return; 148 | } 149 | } 150 | } 151 | 152 | static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c) 153 | { 154 | unsigned char arr[3]; 155 | arr[0] = a, arr[1] = b, arr[2] = c; 156 | fwrite(arr, 3, 1, f); 157 | } 158 | 159 | static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) 160 | { 161 | unsigned char bg[3] = { 255, 0, 255}, px[3]; 162 | stbiw_uint32 zero = 0; 163 | int i,j,k, j_end; 164 | 165 | if (y <= 0) 166 | return; 167 | 168 | if (vdir < 0) 169 | j_end = -1, j = y-1; 170 | else 171 | j_end = y, j = 0; 172 | 173 | for (; j != j_end; j += vdir) { 174 | for (i=0; i < x; ++i) { 175 | unsigned char *d = (unsigned char *) data + (j*x+i)*comp; 176 | if (write_alpha < 0) 177 | fwrite(&d[comp-1], 1, 1, f); 178 | switch (comp) { 179 | case 1: fwrite(d, 1, 1, f); 180 | break; 181 | case 2: if (expand_mono) 182 | write3(f, d[0],d[0],d[0]); // monochrome bmp 183 | else 184 | fwrite(d, 1, 1, f); // monochrome TGA 185 | break; 186 | case 4: 187 | if (!write_alpha) { 188 | // composite against pink background 189 | for (k=0; k < 3; ++k) 190 | px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255; 191 | write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]); 192 | break; 193 | } 194 | /* FALLTHROUGH */ 195 | case 3: 196 | write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]); 197 | break; 198 | } 199 | if (write_alpha > 0) 200 | fwrite(&d[comp-1], 1, 1, f); 201 | } 202 | fwrite(&zero,scanline_pad,1,f); 203 | } 204 | } 205 | 206 | static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) 207 | { 208 | FILE *f; 209 | if (y < 0 || x < 0) return 0; 210 | f = fopen(filename, "wb"); 211 | if (f) { 212 | va_list v; 213 | va_start(v, fmt); 214 | writefv(f, fmt, v); 215 | va_end(v); 216 | write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono); 217 | fclose(f); 218 | } 219 | return f != NULL; 220 | } 221 | 222 | int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) 223 | { 224 | int pad = (-x*3) & 3; 225 | return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad, 226 | "11 4 22 4" "4 44 22 444444", 227 | 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 228 | 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header 229 | } 230 | 231 | int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) 232 | { 233 | int has_alpha = (comp == 2 || comp == 4); 234 | int colorbytes = has_alpha ? comp-1 : comp; 235 | int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 236 | return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0, 237 | "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8); 238 | } 239 | 240 | // ************************************************************************************************* 241 | // Radiance RGBE HDR writer 242 | // by Baldur Karlsson 243 | #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) 244 | 245 | void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) 246 | { 247 | int exponent; 248 | float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); 249 | 250 | if (maxcomp < 1e-32) { 251 | rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; 252 | } else { 253 | float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; 254 | 255 | rgbe[0] = (unsigned char)(linear[0] * normalize); 256 | rgbe[1] = (unsigned char)(linear[1] * normalize); 257 | rgbe[2] = (unsigned char)(linear[2] * normalize); 258 | rgbe[3] = (unsigned char)(exponent + 128); 259 | } 260 | } 261 | 262 | void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) 263 | { 264 | unsigned char lengthbyte = (unsigned char) (length+128); 265 | STBIW_ASSERT(length+128 <= 255); 266 | fwrite(&lengthbyte, 1, 1, f); 267 | fwrite(&databyte, 1, 1, f); 268 | } 269 | 270 | void stbiw__write_dump_data(FILE *f, int length, unsigned char *data) 271 | { 272 | unsigned char lengthbyte = (unsigned char )(length & 0xff); 273 | STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code 274 | fwrite(&lengthbyte, 1, 1, f); 275 | fwrite(data, length, 1, f); 276 | } 277 | 278 | void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline) 279 | { 280 | unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; 281 | unsigned char rgbe[4]; 282 | float linear[3]; 283 | int x; 284 | 285 | scanlineheader[2] = (width&0xff00)>>8; 286 | scanlineheader[3] = (width&0x00ff); 287 | 288 | /* skip RLE for images too small or large */ 289 | if (width < 8 || width >= 32768) { 290 | for (x=0; x < width; x++) { 291 | switch (comp) { 292 | case 4: /* fallthrough */ 293 | case 3: linear[2] = scanline[x*comp + 2]; 294 | linear[1] = scanline[x*comp + 1]; 295 | linear[0] = scanline[x*comp + 0]; 296 | break; 297 | case 2: /* fallthrough */ 298 | case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; 299 | break; 300 | } 301 | stbiw__linear_to_rgbe(rgbe, linear); 302 | fwrite(rgbe, 4, 1, f); 303 | } 304 | } else { 305 | int c,r; 306 | /* encode into scratch buffer */ 307 | for (x=0; x < width; x++) { 308 | switch(comp) { 309 | case 4: /* fallthrough */ 310 | case 3: linear[2] = scanline[x*comp + 2]; 311 | linear[1] = scanline[x*comp + 1]; 312 | linear[0] = scanline[x*comp + 0]; 313 | break; 314 | case 2: /* fallthrough */ 315 | case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0]; 316 | break; 317 | } 318 | stbiw__linear_to_rgbe(rgbe, linear); 319 | scratch[x + width*0] = rgbe[0]; 320 | scratch[x + width*1] = rgbe[1]; 321 | scratch[x + width*2] = rgbe[2]; 322 | scratch[x + width*3] = rgbe[3]; 323 | } 324 | 325 | fwrite(scanlineheader, 4, 1, f); 326 | 327 | /* RLE each component separately */ 328 | for (c=0; c < 4; c++) { 329 | unsigned char *comp = &scratch[width*c]; 330 | 331 | x = 0; 332 | while (x < width) { 333 | // find first run 334 | r = x; 335 | while (r+2 < width) { 336 | if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) 337 | break; 338 | ++r; 339 | } 340 | if (r+2 >= width) 341 | r = width; 342 | // dump up to first run 343 | while (x < r) { 344 | int len = r-x; 345 | if (len > 128) len = 128; 346 | stbiw__write_dump_data(f, len, &comp[x]); 347 | x += len; 348 | } 349 | // if there's a run, output it 350 | if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd 351 | // find next byte after run 352 | while (r < width && comp[r] == comp[x]) 353 | ++r; 354 | // output run up to r 355 | while (x < r) { 356 | int len = r-x; 357 | if (len > 127) len = 127; 358 | stbiw__write_run_data(f, len, comp[x]); 359 | x += len; 360 | } 361 | } 362 | } 363 | } 364 | } 365 | } 366 | 367 | int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) 368 | { 369 | int i; 370 | FILE *f; 371 | if (y <= 0 || x <= 0 || data == NULL) return 0; 372 | f = fopen(filename, "wb"); 373 | if (f) { 374 | /* Each component is stored separately. Allocate scratch space for full output scanline. */ 375 | unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); 376 | fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" ); 377 | fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x); 378 | for(i=0; i < y; i++) 379 | stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x); 380 | STBIW_FREE(scratch); 381 | fclose(f); 382 | } 383 | return f != NULL; 384 | } 385 | 386 | ///////////////////////////////////////////////////////// 387 | // PNG 388 | 389 | // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() 390 | #define stbiw__sbraw(a) ((int *) (a) - 2) 391 | #define stbiw__sbm(a) stbiw__sbraw(a)[0] 392 | #define stbiw__sbn(a) stbiw__sbraw(a)[1] 393 | 394 | #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) 395 | #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) 396 | #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) 397 | 398 | #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) 399 | #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) 400 | #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) 401 | 402 | static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) 403 | { 404 | int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; 405 | void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); 406 | STBIW_ASSERT(p); 407 | if (p) { 408 | if (!*arr) ((int *) p)[1] = 0; 409 | *arr = (void *) ((int *) p + 2); 410 | stbiw__sbm(*arr) = m; 411 | } 412 | return *arr; 413 | } 414 | 415 | static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) 416 | { 417 | while (*bitcount >= 8) { 418 | stbiw__sbpush(data, (unsigned char) *bitbuffer); 419 | *bitbuffer >>= 8; 420 | *bitcount -= 8; 421 | } 422 | return data; 423 | } 424 | 425 | static int stbiw__zlib_bitrev(int code, int codebits) 426 | { 427 | int res=0; 428 | while (codebits--) { 429 | res = (res << 1) | (code & 1); 430 | code >>= 1; 431 | } 432 | return res; 433 | } 434 | 435 | static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) 436 | { 437 | int i; 438 | for (i=0; i < limit && i < 258; ++i) 439 | if (a[i] != b[i]) break; 440 | return i; 441 | } 442 | 443 | static unsigned int stbiw__zhash(unsigned char *data) 444 | { 445 | stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); 446 | hash ^= hash << 3; 447 | hash += hash >> 5; 448 | hash ^= hash << 4; 449 | hash += hash >> 17; 450 | hash ^= hash << 25; 451 | hash += hash >> 6; 452 | return hash; 453 | } 454 | 455 | #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) 456 | #define stbiw__zlib_add(code,codebits) \ 457 | (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) 458 | #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) 459 | // default huffman tables 460 | #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) 461 | #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) 462 | #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) 463 | #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) 464 | #define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) 465 | #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) 466 | 467 | #define stbiw__ZHASH 16384 468 | 469 | unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) 470 | { 471 | static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; 472 | static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; 473 | static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; 474 | static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; 475 | unsigned int bitbuf=0; 476 | int i,j, bitcount=0; 477 | unsigned char *out = NULL; 478 | unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack! 479 | if (quality < 5) quality = 5; 480 | 481 | stbiw__sbpush(out, 0x78); // DEFLATE 32K window 482 | stbiw__sbpush(out, 0x5e); // FLEVEL = 1 483 | stbiw__zlib_add(1,1); // BFINAL = 1 484 | stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman 485 | 486 | for (i=0; i < stbiw__ZHASH; ++i) 487 | hash_table[i] = NULL; 488 | 489 | i=0; 490 | while (i < data_len-3) { 491 | // hash next 3 bytes of data to be compressed 492 | int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; 493 | unsigned char *bestloc = 0; 494 | unsigned char **hlist = hash_table[h]; 495 | int n = stbiw__sbcount(hlist); 496 | for (j=0; j < n; ++j) { 497 | if (hlist[j]-data > i-32768) { // if entry lies within window 498 | int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); 499 | if (d >= best) best=d,bestloc=hlist[j]; 500 | } 501 | } 502 | // when hash table entry is too long, delete half the entries 503 | if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { 504 | STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); 505 | stbiw__sbn(hash_table[h]) = quality; 506 | } 507 | stbiw__sbpush(hash_table[h],data+i); 508 | 509 | if (bestloc) { 510 | // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal 511 | h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); 512 | hlist = hash_table[h]; 513 | n = stbiw__sbcount(hlist); 514 | for (j=0; j < n; ++j) { 515 | if (hlist[j]-data > i-32767) { 516 | int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); 517 | if (e > best) { // if next match is better, bail on current match 518 | bestloc = NULL; 519 | break; 520 | } 521 | } 522 | } 523 | } 524 | 525 | if (bestloc) { 526 | int d = (int) (data+i - bestloc); // distance back 527 | STBIW_ASSERT(d <= 32767 && best <= 258); 528 | for (j=0; best > lengthc[j+1]-1; ++j); 529 | stbiw__zlib_huff(j+257); 530 | if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); 531 | for (j=0; d > distc[j+1]-1; ++j); 532 | stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); 533 | if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); 534 | i += best; 535 | } else { 536 | stbiw__zlib_huffb(data[i]); 537 | ++i; 538 | } 539 | } 540 | // write out final bytes 541 | for (;i < data_len; ++i) 542 | stbiw__zlib_huffb(data[i]); 543 | stbiw__zlib_huff(256); // end of block 544 | // pad with 0 bits to byte boundary 545 | while (bitcount) 546 | stbiw__zlib_add(0,1); 547 | 548 | for (i=0; i < stbiw__ZHASH; ++i) 549 | (void) stbiw__sbfree(hash_table[i]); 550 | 551 | { 552 | // compute adler32 on input 553 | unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552; 554 | int j=0; 555 | while (j < data_len) { 556 | for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; 557 | s1 %= 65521, s2 %= 65521; 558 | j += blocklen; 559 | blocklen = 5552; 560 | } 561 | stbiw__sbpush(out, (unsigned char) (s2 >> 8)); 562 | stbiw__sbpush(out, (unsigned char) s2); 563 | stbiw__sbpush(out, (unsigned char) (s1 >> 8)); 564 | stbiw__sbpush(out, (unsigned char) s1); 565 | } 566 | *out_len = stbiw__sbn(out); 567 | // make returned pointer freeable 568 | STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); 569 | return (unsigned char *) stbiw__sbraw(out); 570 | } 571 | 572 | unsigned int stbiw__crc32(unsigned char *buffer, int len) 573 | { 574 | static unsigned int crc_table[256]; 575 | unsigned int crc = ~0u; 576 | int i,j; 577 | if (crc_table[1] == 0) 578 | for(i=0; i < 256; i++) 579 | for (crc_table[i]=i, j=0; j < 8; ++j) 580 | crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0); 581 | for (i=0; i < len; ++i) 582 | crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; 583 | return ~crc; 584 | } 585 | 586 | #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4) 587 | #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); 588 | #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) 589 | 590 | static void stbiw__wpcrc(unsigned char **data, int len) 591 | { 592 | unsigned int crc = stbiw__crc32(*data - len - 4, len+4); 593 | stbiw__wp32(*data, crc); 594 | } 595 | 596 | static unsigned char stbiw__paeth(int a, int b, int c) 597 | { 598 | int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); 599 | if (pa <= pb && pa <= pc) return (unsigned char) a; 600 | if (pb <= pc) return (unsigned char) b; 601 | return (unsigned char) c; 602 | } 603 | 604 | unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) 605 | { 606 | int ctype[5] = { -1, 0, 4, 2, 6 }; 607 | unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; 608 | unsigned char *out,*o, *filt, *zlib; 609 | signed char *line_buffer; 610 | int i,j,k,p,zlen; 611 | 612 | if (stride_bytes == 0) 613 | stride_bytes = x * n; 614 | 615 | filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; 616 | line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } 617 | for (j=0; j < y; ++j) { 618 | static int mapping[] = { 0,1,2,3,4 }; 619 | static int firstmap[] = { 0,1,0,5,6 }; 620 | int *mymap = j ? mapping : firstmap; 621 | int best = 0, bestval = 0x7fffffff; 622 | for (p=0; p < 2; ++p) { 623 | for (k= p?best:0; k < 5; ++k) { 624 | int type = mymap[k],est=0; 625 | unsigned char *z = pixels + stride_bytes*j; 626 | for (i=0; i < n; ++i) 627 | switch (type) { 628 | case 0: line_buffer[i] = z[i]; break; 629 | case 1: line_buffer[i] = z[i]; break; 630 | case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; 631 | case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; 632 | case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; 633 | case 5: line_buffer[i] = z[i]; break; 634 | case 6: line_buffer[i] = z[i]; break; 635 | } 636 | for (i=n; i < x*n; ++i) { 637 | switch (type) { 638 | case 0: line_buffer[i] = z[i]; break; 639 | case 1: line_buffer[i] = z[i] - z[i-n]; break; 640 | case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; 641 | case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; 642 | case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; 643 | case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; 644 | case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; 645 | } 646 | } 647 | if (p) break; 648 | for (i=0; i < x*n; ++i) 649 | est += abs((signed char) line_buffer[i]); 650 | if (est < bestval) { bestval = est; best = k; } 651 | } 652 | } 653 | // when we get here, best contains the filter type, and line_buffer contains the data 654 | filt[j*(x*n+1)] = (unsigned char) best; 655 | STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); 656 | } 657 | STBIW_FREE(line_buffer); 658 | zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory 659 | STBIW_FREE(filt); 660 | if (!zlib) return 0; 661 | 662 | // each tag requires 12 bytes of overhead 663 | out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); 664 | if (!out) return 0; 665 | *out_len = 8 + 12+13 + 12+zlen + 12; 666 | 667 | o=out; 668 | STBIW_MEMMOVE(o,sig,8); o+= 8; 669 | stbiw__wp32(o, 13); // header length 670 | stbiw__wptag(o, "IHDR"); 671 | stbiw__wp32(o, x); 672 | stbiw__wp32(o, y); 673 | *o++ = 8; 674 | *o++ = (unsigned char) ctype[n]; 675 | *o++ = 0; 676 | *o++ = 0; 677 | *o++ = 0; 678 | stbiw__wpcrc(&o,13); 679 | 680 | stbiw__wp32(o, zlen); 681 | stbiw__wptag(o, "IDAT"); 682 | STBIW_MEMMOVE(o, zlib, zlen); 683 | o += zlen; 684 | STBIW_FREE(zlib); 685 | stbiw__wpcrc(&o, zlen); 686 | 687 | stbiw__wp32(o,0); 688 | stbiw__wptag(o, "IEND"); 689 | stbiw__wpcrc(&o,0); 690 | 691 | STBIW_ASSERT(o == out + *out_len); 692 | 693 | return out; 694 | } 695 | 696 | int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) 697 | { 698 | FILE *f; 699 | int len; 700 | unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); 701 | if (!png) return 0; 702 | f = fopen(filename, "wb"); 703 | if (!f) { STBIW_FREE(png); return 0; } 704 | fwrite(png, 1, len, f); 705 | fclose(f); 706 | STBIW_FREE(png); 707 | return 1; 708 | } 709 | #endif // STB_IMAGE_WRITE_IMPLEMENTATION 710 | 711 | /* Revision history 712 | 0.98 (2015-04-08) 713 | added STBIW_MALLOC, STBIW_ASSERT etc 714 | 0.97 (2015-01-18) 715 | fixed HDR asserts, rewrote HDR rle logic 716 | 0.96 (2015-01-17) 717 | add HDR output 718 | fix monochrome BMP 719 | 0.95 (2014-08-17) 720 | add monochrome TGA output 721 | 0.94 (2014-05-31) 722 | rename private functions to avoid conflicts with stb_image.h 723 | 0.93 (2014-05-27) 724 | warning fixes 725 | 0.92 (2010-08-01) 726 | casts to unsigned char to fix warnings 727 | 0.91 (2010-07-17) 728 | first public release 729 | 0.90 first internal release 730 | */ 731 | -------------------------------------------------------------------------------- /src/shared/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef uint8_t byte; 5 | typedef uint16_t uint16; 6 | typedef uint32_t uint32; 7 | typedef uint64_t uint64; 8 | typedef int32_t int32; 9 | typedef int64_t int64; 10 | 11 | #ifdef _MSC_VER 12 | #define abstract abstract 13 | #else 14 | #define abstract = 0 15 | #endif -------------------------------------------------------------------------------- /src/shared/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #define STB_IMAGE_IMPLEMENTATION 4 | #include "stb/stb_image.h" 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | #include "stb/stb_image_write.h" 7 | 8 | Texture MakeFlatTexture(int w, int h, Color col) { 9 | Color* data = new Color[w * h]; 10 | for (int i = 0; i < w * h; i++) { 11 | data[i] = col; 12 | } 13 | return Texture{ w, h, data }; 14 | } 15 | 16 | Texture MakeGradientTexture(int w, int h) { 17 | Color* data = new Color[w * h]; 18 | float a = 1; 19 | for (int x = 0; x < w; x++) { 20 | float r = float(x) / (w - 1); 21 | for (int y = 0; y < h; y++) { 22 | float g = float(y) / (h - 1); 23 | float b = r*g; 24 | data[x + y * w] = { r, g, b, a }; 25 | } 26 | } 27 | return Texture{ w, h, data }; 28 | } 29 | 30 | BColor* ConvertToByte(uint32 w, uint32 h, Color* in) { 31 | BColor* data = new BColor[w *h]; 32 | for (int x = 0; x < w; x++) { 33 | for (int y = 0; y < h; y++) { 34 | auto p = in[x + y * w]; 35 | data[x + y * w] = BColor { byte(p.r * 255), byte(p.g * 255), byte(p.b * 255), byte(p.a * 255) }; 36 | } 37 | } 38 | return data; 39 | } 40 | 41 | Color* ConvertToFloat(uint32 w, uint32 h, BColor* in) { 42 | Color* data = new Color[w *h]; 43 | for (int x = 0; x < w; x++) { 44 | for (int y = 0; y < h; y++) { 45 | auto p = in[x + y * w]; 46 | data[x + y * w] = { float(p.r) / 255, float(p.g) / 255, float(p.b) / 255, float(p.a) / 255 }; 47 | } 48 | } 49 | return data; 50 | } 51 | 52 | Texture load_tex(const char* filename) { 53 | Texture result; 54 | int comps; 55 | BColor* inputData = (BColor*)stbi_load(filename, &result.width, &result.height, &comps, 4); 56 | 57 | if(!inputData) 58 | { 59 | result.data = nullptr; 60 | return result; 61 | } 62 | 63 | result.data = ConvertToFloat(result.width, result.height, inputData); 64 | free(inputData); 65 | return result; 66 | } 67 | 68 | void save_bmp(const char* filename, const Texture& texture) { 69 | BColor* outData = ConvertToByte(texture.width, texture.height, texture.data); 70 | stbi_write_bmp(filename, texture.width, texture.height, 4, outData); 71 | delete outData; 72 | } 73 | -------------------------------------------------------------------------------- /src/shared/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | 4 | template 5 | struct TColor { 6 | T r; 7 | T g; 8 | T b; 9 | T a; 10 | }; 11 | 12 | typedef TColor Color; 13 | typedef TColor BColor; 14 | 15 | struct Texture { 16 | int width; 17 | int height; 18 | Color* data; 19 | }; 20 | 21 | struct Vec2 { 22 | float x; 23 | float y; 24 | }; 25 | 26 | struct Light { 27 | Color color; 28 | Vec2 pos; 29 | }; 30 | 31 | Texture MakeFlatTexture(int w, int h, Color col); 32 | Texture MakeGradientTexture(int w, int h); 33 | Texture load_tex(const char* filename); 34 | void save_bmp(const char* filename, const Texture& texture); -------------------------------------------------------------------------------- /src/shared/vm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "types.h" 4 | #include 5 | 6 | struct Program; 7 | struct SOp; 8 | 9 | struct Value { 10 | uint32 TypeId; 11 | byte* Memory; 12 | }; 13 | 14 | enum FilterMode { 15 | FMPoint, 16 | FMBilinear 17 | }; 18 | 19 | enum WrapMode { 20 | WMClamp, 21 | WMRepeat 22 | }; 23 | 24 | struct Sampler { 25 | uint32 DimCount; 26 | uint32* Dims; 27 | void* Data; 28 | FilterMode Filter; 29 | WrapMode Wrap; 30 | }; 31 | 32 | 33 | class VM { 34 | private: 35 | virtual byte* VmAlloc(uint32 typeId) abstract; 36 | 37 | public: 38 | virtual bool Setup() abstract; 39 | virtual bool Run() abstract; 40 | virtual bool SetVariable(std::string name, void * value) abstract; 41 | virtual void * ReadVariable(std::string name) const abstract; 42 | virtual Value VmInit(uint32 typeId, void * val) abstract; 43 | 44 | template 45 | Value DoOp(uint32 resultTypeId, Func op, Arg op1, Args && ...args); 46 | 47 | virtual Value Dereference(Value val) const abstract; 48 | virtual Value IndexMemberValue(Value val, uint32 index) const abstract; 49 | virtual Value IndexMemberValue(uint32 typeId, byte * val, uint32 index) const abstract; 50 | 51 | virtual uint32 GetTypeByteSize(uint32 typeId) const abstract; 52 | virtual byte * GetPointerInComposite(uint32 typeId, byte * composite, uint32 indexCount, uint32 * indices, uint32 currLevel) const abstract; 53 | virtual SOp GetType(uint32 typeId) const abstract; 54 | virtual bool IsVectorType(uint32 typeId) const abstract; 55 | virtual uint32 ElementCount(uint32 typeId) const abstract; 56 | }; 57 | 58 | #define BUILDING_DLL 59 | #if defined _WIN32 || defined __CYGWIN__ 60 | #ifdef BUILDING_DLL 61 | #ifdef __GNUC__ 62 | #define DLL_PUBLIC __attribute__ ((dllexport)) 63 | #else 64 | #define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. 65 | #endif 66 | #else 67 | #ifdef __GNUC__ 68 | #define DLL_PUBLIC __attribute__ ((dllimport)) 69 | #else 70 | #define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. 71 | #endif 72 | #endif 73 | #define DLL_LOCAL 74 | #else 75 | #if __GNUC__ >= 4 76 | #define DLL_PUBLIC __attribute__ ((visibility ("default"))) 77 | #define DLL_LOCAL __attribute__ ((visibility ("hidden"))) 78 | #else 79 | #define DLL_PUBLIC 80 | #define DLL_LOCAL 81 | #endif 82 | #endif 83 | 84 | #define EXT_INST_FUNC(x) Value x(VM* vm, uint32 resultTypeId, int valueCount, Value* values) 85 | typedef EXT_INST_FUNC(ExtInstFunc); 86 | typedef ExtInstFunc** GetExtTableFunc(void); 87 | 88 | #define xstr(s) str(s) 89 | #define str(s) #s 90 | #define EXT_EXPORT_TABLE_FUNC_NAME GetExtTable 91 | #define EXT_EXPORT_TABLE_FUNC(x) DLL_PUBLIC ExtInstFunc** EXT_EXPORT_TABLE_FUNC_NAME(void) { return x; } 92 | 93 | struct Environment { 94 | std::map Values; 95 | std::map Extensions; 96 | }; 97 | 98 | template 99 | inline Value VM::DoOp(uint32 resultTypeId, Func op, Arg op1, Args && ...args) { 100 | Value val = VmInit(resultTypeId, 0); 101 | 102 | if (IsVectorType(op1.TypeId)) { 103 | int elCount = ElementCount(op1.TypeId); 104 | for (int i = 0; i < elCount; i++) { 105 | auto result = op(IndexMemberValue(op1, i), IndexMemberValue(args, i)...); 106 | std::memcpy(IndexMemberValue(val, i).Memory, &result, GetTypeByteSize(resultTypeId) / elCount); 107 | } 108 | } else { 109 | auto result = op(op1, std::forward(args)...); 110 | std::memcpy(val.Memory, &result, GetTypeByteSize(resultTypeId)); 111 | } 112 | 113 | return val; 114 | } 115 | 116 | #include "common_ops.h" 117 | -------------------------------------------------------------------------------- /src/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (otherside_test C CXX) 3 | 4 | # We need C++ 11 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED on) 7 | 8 | add_subdirectory(./../shared shared) 9 | 10 | include_directories(${CMAKE_SOURCE_DIR}/src/main) 11 | include_directories(${SHARED_LIB_INCLUDE_DIR}) 12 | 13 | add_executable(otherside_test_parser otherside_test_parser.cpp) 14 | add_executable(otherside_test_codegen otherside_test_codegen.cpp) 15 | 16 | IF (WIN32) 17 | target_link_libraries(otherside_test_parser otherside shared) 18 | target_link_libraries(otherside_test_codegen otherside shared) 19 | ELSE() 20 | target_link_libraries(otherside_test_parser otherside shared dl) 21 | target_link_libraries(otherside_test_codegen otherside shared dl) 22 | ENDIF() 23 | 24 | add_test(NAME parser_test COMMAND otherside_test_parser data/light.frag.spv WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) 25 | add_test(NAME codegen_test COMMAND otherside_test_codegen data/light.frag.spv data/light.frag.cpp WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) -------------------------------------------------------------------------------- /src/test/otherside_test_codegen.cpp: -------------------------------------------------------------------------------- 1 | #include "parser_definitions.h" 2 | #include "parser.h" 3 | #include "codegen.h" 4 | 5 | int main(int argc, char** argv) { 6 | Parser parser(argv[1]); 7 | 8 | Program prog; 9 | if(!parser.Parse(&prog)) { 10 | return -1; 11 | } 12 | 13 | if (!genCode(argv[2], prog)) { 14 | return -1; 15 | } 16 | 17 | return 0; 18 | } -------------------------------------------------------------------------------- /src/test/otherside_test_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "parser_definitions.h" 2 | #include "parser.h" 3 | 4 | int main(int argc, char** argv) { 5 | Parser parser(argv[1]); 6 | 7 | Program prog; 8 | if(!parser.Parse(&prog)) { 9 | return -1; 10 | } 11 | 12 | return 0; 13 | } -------------------------------------------------------------------------------- /src/tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (tools C CXX) 3 | 4 | # We need C++ 11 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED on) 7 | 8 | add_subdirectory(assembler) 9 | add_subdirectory(disassembler) -------------------------------------------------------------------------------- /src/tools/SpecParser/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/tools/SpecParser/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Text; 7 | using HtmlAgilityPack; 8 | 9 | namespace SpecParser 10 | { 11 | class Program 12 | { 13 | struct Parameter 14 | { 15 | public bool IsList; 16 | public string Type; 17 | public string Name; 18 | 19 | public override string ToString() 20 | { 21 | return Name + ":" + Type + (IsList ? "[1..n]" : ""); 22 | } 23 | } 24 | 25 | struct Op 26 | { 27 | public string Name; 28 | public int Index; 29 | public List Parameters; 30 | 31 | public Op(string name = "", int index = -1) 32 | { 33 | Name = name; 34 | Index = index; 35 | Parameters = new List(); 36 | } 37 | 38 | public override string ToString() 39 | { 40 | var ret = Name + "(" + Index + "): "; 41 | foreach (var param in Parameters) 42 | { 43 | ret += param + " | "; 44 | } 45 | return ret; 46 | } 47 | 48 | public string GenerateHandlerDecleration() 49 | { 50 | return "static void Handle" + Name + " (void* op, Program* prog)"; 51 | } 52 | 53 | public string GenerateStructCode() 54 | { 55 | string paramList = ""; 56 | foreach (var param in Parameters) 57 | { 58 | var typename = param.Type; 59 | 60 | switch (param.Type) 61 | { 62 | case "LiteralNumber": 63 | case "Id": typename = "uint32"; break; 64 | case "LiteralString": typename = "char*"; break; 65 | default: typename = "spv::" + typename; break; 66 | } 67 | 68 | if (param.IsList) 69 | { 70 | paramList += String.Format("\n uint32 {0}Count;", param.Name); 71 | typename = typename + "*"; 72 | } 73 | 74 | paramList += String.Format("\n {0} {1};", typename, param.Name); 75 | } 76 | 77 | return string.Format("struct S{0} {{{1}\n}};\n", Name, paramList); 78 | } 79 | 80 | public string GenerateLookupCode() 81 | { 82 | string paramList = ""; 83 | foreach (var param in Parameters) 84 | { 85 | paramList += String.Format("\n WordType::T{0},", param.Type + (param.IsList ? "List" : "")); 86 | } 87 | 88 | return string.Format("static WordType {0}WordTypes[] {{\n WordType::TOp,{1}\n}};\nstatic uint32 {2}WordTypesCount = {3};\n", Name, paramList, Name, Parameters.Count + 1); 89 | } 90 | } 91 | 92 | static void Main(string[] args) 93 | { 94 | string htmlCode = null; 95 | using (WebClient client = new WebClient()) // WebClient class inherits IDisposable 96 | { 97 | htmlCode = client.DownloadString("http://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html"); 98 | } 99 | 100 | if (htmlCode == null) 101 | { 102 | return; 103 | } 104 | 105 | HtmlDocument doc = new HtmlDocument(); 106 | doc.LoadHtml(htmlCode); 107 | var nodes = doc.DocumentNode.SelectNodes(@"html[1]/body[1]/div[2]/div[4]/div[1]/div[33]/div/table"); 108 | 109 | var ops = new List(); 110 | 111 | foreach (var node in nodes) 112 | { 113 | var opNode = node.SelectSingleNode("tbody/tr[1]/td/p/a"); 114 | var defNodes = node.SelectNodes("tbody/tr[2]/td/p"); 115 | var wordCount = int.Parse(defNodes[0].InnerText.Split(' ')[0]); 116 | 117 | Op op = new Op(opNode.Attributes[0].Value.Substring(2), int.Parse(defNodes[1].InnerText)); 118 | 119 | for (int i = 2; i < defNodes.Count; i++) 120 | { 121 | var defNodeText = defNodes[i].InnerText; 122 | var paramType = ""; 123 | var paramName = (i - 2).ToString(); 124 | bool isList = defNodeText.Contains("…"); 125 | 126 | if (defNodeText.Contains("<id>")) 127 | { 128 | paramType = "Id"; 129 | if (defNodeText.Contains("Result <id>")) 130 | { 131 | paramName = "ResultId"; 132 | } 133 | else 134 | { 135 | var strings = defNodeText.Split('\n'); 136 | if (strings.Length > 1) 137 | { 138 | paramName = strings[1].Split(',')[0].Replace(" ", "").Trim('[', ']') + "Id"; 139 | } 140 | else 141 | { 142 | paramName = "Id" + paramName; 143 | } 144 | } 145 | 146 | } 147 | else 148 | { 149 | var strings = defNodeText.Split('\n'); 150 | paramType = strings[0].Split(',')[0].Replace(" ", ""); 151 | 152 | if (strings.Length > 1) 153 | { 154 | paramName = strings[1].Split(',')[0].Replace(" ", "").Trim('[', ']'); 155 | } 156 | else 157 | { 158 | paramName = paramType; 159 | } 160 | 161 | if (paramType == "literal") 162 | { 163 | paramType = "LiteralNumber"; 164 | paramName = paramName.Replace("See", "").Replace(".", "").Trim('[', ']'); 165 | } 166 | else if(paramType == "optionalliteral(s)") 167 | { 168 | isList = true; 169 | paramType = "LiteralNumber"; 170 | paramName = paramName.Replace("See", "").Replace(".", "").Trim('[', ']'); 171 | } 172 | } 173 | 174 | if (isList) 175 | { 176 | paramName = paramName.Replace("0", "").Replace("1", "").Replace(",", "").Trim('[', ']'); 177 | if (!paramName.EndsWith("s")) 178 | { 179 | paramName += "s"; 180 | } 181 | } 182 | 183 | switch (paramName) 184 | { 185 | case "Thenameoftheopaquetype.": paramName = "OpaqueTypeName"; break; 186 | } 187 | 188 | op.Parameters.Add(new Parameter() { Type = paramType, Name = paramName, IsList = isList }); 189 | } 190 | ops.Add(op); 191 | } 192 | 193 | ops = ops.OrderBy(o => o.Index).ToList(); 194 | 195 | ops.ForEach(o => Console.WriteLine(o)); 196 | 197 | StringBuilder fileContents = new StringBuilder(); 198 | 199 | fileContents.AppendLine("#pragma once"); 200 | fileContents.AppendLine("#include \"types.h\""); 201 | fileContents.AppendLine("#include \"lookups.h\""); 202 | fileContents.AppendLine(""); 203 | 204 | fileContents.AppendLine("struct Program;"); 205 | 206 | fileContents.AppendLine(""); 207 | fileContents.AppendLine("#pragma pack(push, 1)"); 208 | 209 | foreach (var op in ops) 210 | { 211 | fileContents.AppendLine(op.GenerateHandlerDecleration() + ";"); 212 | fileContents.AppendLine(op.GenerateStructCode()); 213 | } 214 | fileContents.AppendLine("#pragma pack(pop)"); 215 | 216 | fileContents.AppendLine(""); 217 | foreach (var op in ops) 218 | { 219 | fileContents.AppendLine(op.GenerateLookupCode()); 220 | } 221 | 222 | fileContents.AppendLine("static void* LUTOpWordTypes[] {"); 223 | foreach (var op in ops) 224 | { 225 | fileContents.AppendLine(string.Format(" &{0}WordTypes,", op.Name)); 226 | } 227 | fileContents.AppendLine("};"); 228 | fileContents.AppendLine(""); 229 | 230 | fileContents.AppendLine("static uint32 LUTOpWordTypesCount[] {"); 231 | foreach (var op in ops) 232 | { 233 | fileContents.AppendLine(string.Format(" {0}WordTypesCount,", op.Name)); 234 | } 235 | fileContents.AppendLine("};"); 236 | fileContents.AppendLine(""); 237 | 238 | fileContents.AppendLine("typedef void(*OpHandler)(void*, Program*);"); 239 | fileContents.AppendLine("static OpHandler LUTHandlerMethods[] {"); 240 | foreach (var op in ops) 241 | { 242 | fileContents.AppendLine(string.Format(" Handle{0},", op.Name)); 243 | } 244 | fileContents.AppendLine("};"); 245 | File.WriteAllText("lookups_gen.h", fileContents.ToString()); 246 | 247 | 248 | fileContents.Clear(); 249 | fileContents.AppendLine("#include \"lookups_gen.h\""); 250 | fileContents.AppendLine("#include \"parser_definitions.h\""); 251 | fileContents.AppendLine(""); 252 | 253 | foreach (var op in ops) 254 | { 255 | fileContents.AppendLine(op.GenerateHandlerDecleration() + " {"); 256 | fileContents.AppendLine(String.Format(" S{0}* op{0} = (S{0}*)op;", op.Name)); 257 | fileContents.AppendLine("}\n"); 258 | } 259 | File.WriteAllText("lookups_gen.cpp", fileContents.ToString()); 260 | } 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/tools/SpecParser/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SpecParser")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SpecParser")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5ae845f6-4e1f-4966-bc0f-6708ae42cbd9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/tools/SpecParser/SpecParser.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5AE845F6-4E1F-4966-BC0F-6708AE42CBD9} 8 | Exe 9 | Properties 10 | SpecParser 11 | SpecParser 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | AllRules.ruleset 34 | 35 | 36 | 37 | ..\..\..\packages\HtmlAgilityPack.1.4.9\lib\Net45\HtmlAgilityPack.dll 38 | True 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 65 | -------------------------------------------------------------------------------- /src/tools/SpecParser/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/tools/assembler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (assembler C CXX) 3 | 4 | # We need C++ 11 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED on) 7 | 8 | add_subdirectory(./../../shared shared) 9 | 10 | include_directories(${CMAKE_SOURCE_DIR}/src/main) 11 | include_directories(${SHARED_LIB_INCLUDE_DIR}) 12 | 13 | add_executable(assembler assembler_main.cpp) 14 | 15 | IF (WIN32) 16 | target_link_libraries(assembler otherside shared) 17 | ELSE() 18 | target_link_libraries(assembler otherside shared dl) 19 | ENDIF() -------------------------------------------------------------------------------- /src/tools/assembler/assembler_main.cpp: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "parser_definitions.h" 3 | #include "parser.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | const int GENERATOR_MAGIC = 0xFEEDFEED; 10 | 11 | int main(int argc, char** argv) { 12 | assert(argc == 3); 13 | char* infilename = argv[1]; 14 | char* outfilename = argv[2]; 15 | 16 | std::ifstream inFile; 17 | inFile.open(infilename, std::ifstream::in); 18 | if(!inFile.is_open()) { 19 | std::cout << "Could not open file " << infilename << std::endl; 20 | return -1; 21 | } 22 | 23 | std::ofstream outFile; 24 | outFile.open(outfilename, std::ofstream::out | std::ofstream::binary); 25 | if(!outFile.is_open()) { 26 | std::cout << "Could not open file " << outfilename << std::endl; 27 | return -1; 28 | } 29 | 30 | /* 31 | std::string valueString; 32 | inFile >> valueString; 33 | assert(valueString.find("Version: ") == valueString.begin()); 34 | uint32 version = getValue(valueString); 35 | inFile >> valueString; 36 | uint32 generatorMagic = getValue(valueString); 37 | 38 | outFile << spv::MagicNumber; 39 | outFile << version; 40 | outFile << generatorMagic; 41 | 42 | Program program; 43 | Parser parser(argv[1]); 44 | parser.Parse(&program); 45 | std::cout << writeProgram(program);*/ 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/tools/disassembler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project (disassembler C CXX) 3 | 4 | # We need C++ 11 5 | set(CMAKE_CXX_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD_REQUIRED on) 7 | 8 | add_subdirectory(./../../shared shared) 9 | 10 | include_directories(${CMAKE_SOURCE_DIR}/src/main) 11 | include_directories(${SHARED_LIB_INCLUDE_DIR}) 12 | 13 | add_executable(disassembler disassembler_main.cpp) 14 | 15 | IF (WIN32) 16 | target_link_libraries(disassembler otherside shared) 17 | ELSE() 18 | target_link_libraries(disassembler otherside shared dl) 19 | ENDIF() -------------------------------------------------------------------------------- /src/tools/disassembler/disassembler_main.cpp: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include "parser_definitions.h" 3 | #include "parser.h" 4 | #include 5 | #include 6 | 7 | int main(int argc, char** argv) { 8 | assert(argc == 2); 9 | Program program; 10 | Parser parser(argv[1]); 11 | parser.Parse(&program); 12 | std::cout << writeProgram(program); 13 | } 14 | 15 | 16 | --------------------------------------------------------------------------------