Browse Source
[cmake] sirit, spirv-headers -> CPM, update spirv headers and invoc
[cmake] sirit, spirv-headers -> CPM, update spirv headers and invoc
Signed-off-by: crueter <crueter@eden-emu.dev>pull/143/head
No known key found for this signature in database
GPG Key ID: 425ACD2D4830EBC6
39 changed files with 22 additions and 3470 deletions
-
3.gitmodules
-
19externals/CMakeLists.txt
-
88externals/sirit/.clang-format
-
2externals/sirit/.gitignore
-
3externals/sirit/.gitmodules
-
103externals/sirit/CMakeLists.txt
-
24externals/sirit/LICENSE.txt
-
53externals/sirit/README.md
-
1externals/sirit/externals/SPIRV-Headers
-
1365externals/sirit/include/sirit/sirit.h
-
1externals/sirit/src/.gitignore
-
32externals/sirit/src/CMakeLists.txt
-
31externals/sirit/src/common_types.h
-
27externals/sirit/src/instructions/annotation.cpp
-
46externals/sirit/src/instructions/arithmetic.cpp
-
104externals/sirit/src/instructions/atomic.cpp
-
23externals/sirit/src/instructions/barrier.cpp
-
76externals/sirit/src/instructions/bit.cpp
-
48externals/sirit/src/instructions/constant.cpp
-
29externals/sirit/src/instructions/conversion.cpp
-
36externals/sirit/src/instructions/debug.cpp
-
29externals/sirit/src/instructions/derivatives.cpp
-
80externals/sirit/src/instructions/extension.cpp
-
109externals/sirit/src/instructions/flow.cpp
-
34externals/sirit/src/instructions/function.cpp
-
88externals/sirit/src/instructions/group.cpp
-
169externals/sirit/src/instructions/image.cpp
-
65externals/sirit/src/instructions/logical.cpp
-
74externals/sirit/src/instructions/memory.cpp
-
38externals/sirit/src/instructions/misc.cpp
-
130externals/sirit/src/instructions/type.cpp
-
142externals/sirit/src/sirit.cpp
-
0externals/sirit/src/stream.cpp
-
267externals/sirit/src/stream.h
-
6externals/sirit/tests/CMakeLists.txt
-
139externals/sirit/tests/main.cpp
-
4src/shader_recompiler/backend/spirv/emit_spirv.cpp
-
2src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
-
2src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
@ -1,88 +0,0 @@ |
|||||
--- |
|
||||
Language: Cpp |
|
||||
# BasedOnStyle: LLVM |
|
||||
AccessModifierOffset: -4 |
|
||||
AlignAfterOpenBracket: Align |
|
||||
AlignConsecutiveAssignments: false |
|
||||
AlignConsecutiveDeclarations: false |
|
||||
AlignEscapedNewlinesLeft: false |
|
||||
AlignOperands: true |
|
||||
AlignTrailingComments: true |
|
||||
AllowAllParametersOfDeclarationOnNextLine: true |
|
||||
AllowShortBlocksOnASingleLine: false |
|
||||
AllowShortCaseLabelsOnASingleLine: false |
|
||||
AllowShortFunctionsOnASingleLine: Empty |
|
||||
AllowShortIfStatementsOnASingleLine: false |
|
||||
AllowShortLoopsOnASingleLine: false |
|
||||
AlwaysBreakAfterDefinitionReturnType: None |
|
||||
AlwaysBreakAfterReturnType: None |
|
||||
AlwaysBreakBeforeMultilineStrings: false |
|
||||
AlwaysBreakTemplateDeclarations: true |
|
||||
BinPackArguments: true |
|
||||
BinPackParameters: true |
|
||||
BraceWrapping: |
|
||||
AfterClass: false |
|
||||
AfterControlStatement: false |
|
||||
AfterEnum: false |
|
||||
AfterFunction: false |
|
||||
AfterNamespace: false |
|
||||
AfterObjCDeclaration: false |
|
||||
AfterStruct: false |
|
||||
AfterUnion: false |
|
||||
BeforeCatch: false |
|
||||
BeforeElse: false |
|
||||
IndentBraces: false |
|
||||
BreakBeforeBinaryOperators: None |
|
||||
BreakBeforeBraces: Attach |
|
||||
BreakBeforeTernaryOperators: true |
|
||||
BreakConstructorInitializersBeforeComma: false |
|
||||
ColumnLimit: 100 |
|
||||
CommentPragmas: '^ IWYU pragma:' |
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false |
|
||||
ConstructorInitializerIndentWidth: 4 |
|
||||
ContinuationIndentWidth: 4 |
|
||||
Cpp11BracedListStyle: true |
|
||||
DerivePointerAlignment: false |
|
||||
DisableFormat: false |
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] |
|
||||
IncludeCategories: |
|
||||
- Regex: '^\<[^Q][^/.>]*\>' |
|
||||
Priority: -2 |
|
||||
- Regex: '^\<' |
|
||||
Priority: -1 |
|
||||
- Regex: '^\"' |
|
||||
Priority: 0 |
|
||||
IndentCaseLabels: false |
|
||||
IndentWidth: 4 |
|
||||
IndentWrappedFunctionNames: false |
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true |
|
||||
MacroBlockBegin: '' |
|
||||
MacroBlockEnd: '' |
|
||||
MaxEmptyLinesToKeep: 1 |
|
||||
NamespaceIndentation: None |
|
||||
ObjCBlockIndentWidth: 2 |
|
||||
ObjCSpaceAfterProperty: false |
|
||||
ObjCSpaceBeforeProtocolList: true |
|
||||
PenaltyBreakBeforeFirstCallParameter: 19 |
|
||||
PenaltyBreakComment: 300 |
|
||||
PenaltyBreakFirstLessLess: 120 |
|
||||
PenaltyBreakString: 1000 |
|
||||
PenaltyExcessCharacter: 1000000 |
|
||||
PenaltyReturnTypeOnItsOwnLine: 150 |
|
||||
PointerAlignment: Left |
|
||||
ReflowComments: true |
|
||||
SortIncludes: true |
|
||||
SpaceAfterCStyleCast: false |
|
||||
SpaceBeforeAssignmentOperators: true |
|
||||
SpaceBeforeParens: ControlStatements |
|
||||
SpaceInEmptyParentheses: false |
|
||||
SpacesBeforeTrailingComments: 1 |
|
||||
SpacesInAngles: false |
|
||||
SpacesInContainerLiterals: true |
|
||||
SpacesInCStyleCastParentheses: false |
|
||||
SpacesInParentheses: false |
|
||||
SpacesInSquareBrackets: false |
|
||||
Standard: Cpp11 |
|
||||
TabWidth: 4 |
|
||||
UseTab: Never |
|
||||
... |
|
||||
@ -1,2 +0,0 @@ |
|||||
build |
|
||||
*.o |
|
||||
@ -1,3 +0,0 @@ |
|||||
[submodule "externals/SPIRV-Headers"] |
|
||||
path = externals/SPIRV-Headers |
|
||||
url = https://github.com/KhronosGroup/SPIRV-Headers |
|
||||
@ -1,103 +0,0 @@ |
|||||
# This file has been adapted from dynarmic |
|
||||
|
|
||||
cmake_minimum_required(VERSION 3.12) |
|
||||
project(sirit CXX) |
|
||||
|
|
||||
# Determine if we're built as a subproject (using add_subdirectory) |
|
||||
# or if this is the master project. |
|
||||
set(MASTER_PROJECT OFF) |
|
||||
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) |
|
||||
set(MASTER_PROJECT ON) |
|
||||
endif() |
|
||||
|
|
||||
# Sirit project options |
|
||||
option(SIRIT_TESTS "Build tests" OFF) |
|
||||
option(SIRIT_USE_SYSTEM_SPIRV_HEADERS "Use system SPIR-V headers" OFF) |
|
||||
|
|
||||
# Default to a Release build |
|
||||
if (NOT CMAKE_BUILD_TYPE) |
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) |
|
||||
message(STATUS "Defaulting to a Release build") |
|
||||
endif() |
|
||||
|
|
||||
# Set hard requirements for C++ |
|
||||
set(CMAKE_CXX_STANDARD 20) |
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON) |
|
||||
set(CMAKE_CXX_EXTENSIONS OFF) |
|
||||
|
|
||||
# Warn on CMake API deprecations |
|
||||
set(CMAKE_WARN_DEPRECATED ON) |
|
||||
|
|
||||
# Disable in-source builds |
|
||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON) |
|
||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) |
|
||||
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") |
|
||||
message(SEND_ERROR "In-source builds are not allowed.") |
|
||||
endif() |
|
||||
|
|
||||
# Add the module directory to the list of paths |
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules") |
|
||||
|
|
||||
# Compiler flags |
|
||||
if (MSVC) |
|
||||
set(SIRIT_CXX_FLAGS |
|
||||
/std:c++latest # CMAKE_CXX_STANDARD as no effect on MSVC until CMake 3.10. |
|
||||
/W4 |
|
||||
/w34263 # Non-virtual member function hides base class virtual function |
|
||||
/w44265 # Class has virtual functions, but destructor is not virtual |
|
||||
/w34456 # Declaration of 'var' hides previous local declaration |
|
||||
/w34457 # Declaration of 'var' hides function parameter |
|
||||
/w34458 # Declaration of 'var' hides class member |
|
||||
/w34459 # Declaration of 'var' hides global definition |
|
||||
/w34946 # Reinterpret-cast between related types |
|
||||
/wd4592 # Symbol will be dynamically initialized (implementation limitation) |
|
||||
/permissive- # Stricter C++ standards conformance |
|
||||
/MP |
|
||||
/Zi |
|
||||
/Zo |
|
||||
/EHsc |
|
||||
/Zc:throwingNew # Assumes new never returns null |
|
||||
/Zc:inline # Omits inline functions from object-file output |
|
||||
/DNOMINMAX |
|
||||
/WX) |
|
||||
|
|
||||
if (CMAKE_VS_PLATFORM_TOOLSET MATCHES "LLVM-vs[0-9]+") |
|
||||
list(APPEND SIRIT_CXX_FLAGS |
|
||||
-Qunused-arguments |
|
||||
-Wno-missing-braces) |
|
||||
endif() |
|
||||
else() |
|
||||
set(SIRIT_CXX_FLAGS |
|
||||
-Wall |
|
||||
-Wextra |
|
||||
-Wcast-qual |
|
||||
-pedantic |
|
||||
-pedantic-errors |
|
||||
-Wfatal-errors |
|
||||
-Wno-missing-braces |
|
||||
-Wconversion |
|
||||
-Wsign-conversion |
|
||||
-Wshadow |
|
||||
-Werror) |
|
||||
endif() |
|
||||
|
|
||||
# Enable unit-testing. |
|
||||
enable_testing(true) |
|
||||
|
|
||||
# SPIR-V headers |
|
||||
if (SIRIT_USE_SYSTEM_SPIRV_HEADERS) |
|
||||
find_package(SPIRV-Headers REQUIRED) |
|
||||
else() |
|
||||
add_subdirectory(externals/SPIRV-Headers EXCLUDE_FROM_ALL) |
|
||||
|
|
||||
if (NOT TARGET SPIRV-Headers::SPIRV-Headers) |
|
||||
add_library(SPIRV-Headers::SPIRV-Headers ALIAS SPIRV-Headers) |
|
||||
endif() |
|
||||
endif() |
|
||||
|
|
||||
|
|
||||
# Sirit project files |
|
||||
add_subdirectory(src) |
|
||||
if (SIRIT_TESTS) |
|
||||
add_subdirectory(tests) |
|
||||
endif() |
|
||||
@ -1,24 +0,0 @@ |
|||||
Copyright (c) 2019, sirit |
|
||||
All rights reserved. |
|
||||
|
|
||||
Redistribution and use in source and binary forms, with or without |
|
||||
modification, are permitted provided that the following conditions are met: |
|
||||
* Redistributions of source code must retain the above copyright |
|
||||
notice, this list of conditions and the following disclaimer. |
|
||||
* Redistributions in binary form must reproduce the above copyright |
|
||||
notice, this list of conditions and the following disclaimer in the |
|
||||
documentation and/or other materials provided with the distribution. |
|
||||
* Neither the name of the <organization> nor the |
|
||||
names of its contributors may be used to endorse or promote products |
|
||||
derived from this software without specific prior written permission. |
|
||||
|
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY |
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||
@ -1,53 +0,0 @@ |
|||||
Sirit |
|
||||
===== |
|
||||
A runtime SPIR-V assembler. It aims to ease dynamic SPIR-V code generation |
|
||||
without calling external applications (like Khronos' `spirv-as`) |
|
||||
|
|
||||
Its design aims to move code that does not belong in the application to the |
|
||||
library, without limiting its functionality. |
|
||||
|
|
||||
What Sirit does for you: |
|
||||
* Sort declaration opcodes |
|
||||
* Handle types and constant duplicates |
|
||||
* Emit SPIR-V opcodes |
|
||||
|
|
||||
What Sirit won't do for you: |
|
||||
* Avoid ID duplicates (e.g. emitting the same label twice) |
|
||||
* Dump code to disk |
|
||||
* Handle control flow |
|
||||
* Compile from a higher level language |
|
||||
|
|
||||
|
|
||||
It's in early stages of development, many instructions are missing since |
|
||||
they are written manually instead of being generated from a file. |
|
||||
|
|
||||
Example |
|
||||
------- |
|
||||
|
|
||||
```cpp |
|
||||
class MyModule : public Sirit::Module { |
|
||||
public: |
|
||||
MyModule() {} |
|
||||
~MyModule() = default; |
|
||||
|
|
||||
void Generate() { |
|
||||
AddCapability(spv::Capability::Shader); |
|
||||
SetMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450); |
|
||||
|
|
||||
auto main_type{TypeFunction(TypeVoid())}; |
|
||||
auto main_func{OpFunction(TypeVoid(), spv::FunctionControlMask::MaskNone, main_type)}; |
|
||||
AddLabel(OpLabel()); |
|
||||
OpReturn(); |
|
||||
OpFunctionEnd(); |
|
||||
|
|
||||
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main"); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
// Then... |
|
||||
|
|
||||
MyModule module; |
|
||||
module.Generate(); |
|
||||
|
|
||||
std::vector<std::uint32_t> code{module.Assemble()}; |
|
||||
``` |
|
||||
@ -1 +0,0 @@ |
|||||
Subproject commit 04b76709bf40a7ce8df3382060ef3620f19de566 |
|
||||
1365
externals/sirit/include/sirit/sirit.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1 +0,0 @@ |
|||||
sirit.h |
|
||||
@ -1,32 +0,0 @@ |
|||||
add_library(sirit |
|
||||
../include/sirit/sirit.h |
|
||||
sirit.cpp |
|
||||
stream.h |
|
||||
common_types.h |
|
||||
instructions/type.cpp |
|
||||
instructions/constant.cpp |
|
||||
instructions/function.cpp |
|
||||
instructions/flow.cpp |
|
||||
instructions/debug.cpp |
|
||||
instructions/derivatives.cpp |
|
||||
instructions/memory.cpp |
|
||||
instructions/annotation.cpp |
|
||||
instructions/misc.cpp |
|
||||
instructions/logical.cpp |
|
||||
instructions/conversion.cpp |
|
||||
instructions/bit.cpp |
|
||||
instructions/arithmetic.cpp |
|
||||
instructions/extension.cpp |
|
||||
instructions/image.cpp |
|
||||
instructions/group.cpp |
|
||||
instructions/barrier.cpp |
|
||||
instructions/atomic.cpp |
|
||||
) |
|
||||
|
|
||||
target_compile_options(sirit PRIVATE ${SIRIT_CXX_FLAGS}) |
|
||||
|
|
||||
target_include_directories(sirit |
|
||||
PUBLIC ../include |
|
||||
PRIVATE .) |
|
||||
|
|
||||
target_link_libraries(sirit PUBLIC SPIRV-Headers::SPIRV-Headers) |
|
||||
@ -1,31 +0,0 @@ |
|||||
/* This file is part of the sirit project. |
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <cstddef> |
|
||||
#include <cstdint> |
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
using u8 = std::uint8_t; |
|
||||
using u16 = std::uint16_t; |
|
||||
using u32 = std::uint32_t; |
|
||||
using u64 = std::uint64_t; |
|
||||
using uptr = std::uintptr_t; |
|
||||
|
|
||||
using s8 = std::int8_t; |
|
||||
using s16 = std::int16_t; |
|
||||
using s32 = std::int32_t; |
|
||||
using s64 = std::int64_t; |
|
||||
using sptr = std::intptr_t; |
|
||||
|
|
||||
using f32 = float; |
|
||||
using f64 = double; |
|
||||
static_assert(sizeof(f32) == sizeof(u32), "f32 must be 32 bits wide"); |
|
||||
static_assert(sizeof(f64) == sizeof(u64), "f64 must be 64 bits wide"); |
|
||||
|
|
||||
} // namespace Sirit |
|
||||
@ -1,27 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <span>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::Decorate(Id target, spv::Decoration decoration, std::span<const Literal> literals) { |
|
||||
annotations->Reserve(3 + literals.size()); |
|
||||
return *annotations << spv::Op::OpDecorate << target << decoration << literals << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::MemberDecorate(Id structure_type, Literal member, spv::Decoration decoration, |
|
||||
std::span<const Literal> literals) { |
|
||||
annotations->Reserve(4 + literals.size()); |
|
||||
return *annotations << spv::Op::OpMemberDecorate << structure_type << member << decoration |
|
||||
<< literals << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,46 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
#define DEFINE_UNARY(funcname, opcode) \
|
|
||||
Id Module::funcname(Id result_type, Id operand) { \ |
|
||||
code->Reserve(4); \ |
|
||||
return *code << OpId{opcode, result_type} << operand << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_BINARY(funcname, opcode) \
|
|
||||
Id Module::funcname(Id result_type, Id operand_1, Id operand_2) { \ |
|
||||
code->Reserve(5); \ |
|
||||
return *code << OpId{opcode, result_type} << operand_1 << operand_2 << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
DEFINE_UNARY(OpSNegate, spv::Op::OpSNegate) |
|
||||
DEFINE_UNARY(OpFNegate, spv::Op::OpFNegate) |
|
||||
|
|
||||
DEFINE_BINARY(OpIAdd, spv::Op::OpIAdd) |
|
||||
DEFINE_BINARY(OpFAdd, spv::Op::OpFAdd) |
|
||||
DEFINE_BINARY(OpISub, spv::Op::OpISub) |
|
||||
DEFINE_BINARY(OpFSub, spv::Op::OpFSub) |
|
||||
DEFINE_BINARY(OpIMul, spv::Op::OpIMul) |
|
||||
DEFINE_BINARY(OpFMul, spv::Op::OpFMul) |
|
||||
DEFINE_BINARY(OpUDiv, spv::Op::OpUDiv) |
|
||||
DEFINE_BINARY(OpSDiv, spv::Op::OpSDiv) |
|
||||
DEFINE_BINARY(OpFDiv, spv::Op::OpFDiv) |
|
||||
DEFINE_BINARY(OpUMod, spv::Op::OpUMod) |
|
||||
DEFINE_BINARY(OpSMod, spv::Op::OpSMod) |
|
||||
DEFINE_BINARY(OpFMod, spv::Op::OpFMod) |
|
||||
DEFINE_BINARY(OpSRem, spv::Op::OpSRem) |
|
||||
DEFINE_BINARY(OpFRem, spv::Op::OpFRem) |
|
||||
DEFINE_BINARY(OpIAddCarry, spv::Op::OpIAddCarry) |
|
||||
DEFINE_BINARY(OpVectorTimesScalar, spv::Op::OpVectorTimesScalar) |
|
||||
DEFINE_BINARY(OpDot, spv::Op::OpDot) |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,104 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpAtomicLoad(Id result_type, Id pointer, Id memory, Id semantics) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpAtomicLoad, result_type} << pointer << memory << semantics |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicStore(Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpAtomicStore} << pointer << memory << semantics << value |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicExchange(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicExchange, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicCompareExchange(Id result_type, Id pointer, Id memory, Id equal, Id unequal, |
|
||||
Id value, Id comparator) { |
|
||||
code->Reserve(9); |
|
||||
return *code << OpId{spv::Op::OpAtomicCompareExchange, result_type} << pointer << memory |
|
||||
<< equal << unequal << value << comparator << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicIIncrement(Id result_type, Id pointer, Id memory, Id semantics) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpAtomicIIncrement, result_type} << pointer << memory << semantics |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicIDecrement(Id result_type, Id pointer, Id memory, Id semantics) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpAtomicIDecrement, result_type} << pointer << memory << semantics |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicIAdd(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicIAdd, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicISub(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicISub, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicSMin(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicSMin, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicUMin(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicUMin, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicSMax(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicSMax, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicUMax(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicUMax, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicAnd(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicAnd, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicOr(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicOr, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAtomicXor(Id result_type, Id pointer, Id memory, Id semantics, Id value) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpAtomicXor, result_type} << pointer << memory << semantics |
|
||||
<< value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,23 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpControlBarrier(Id execution, Id memory, Id semantics) { |
|
||||
code->Reserve(4); |
|
||||
return *code << spv::Op::OpControlBarrier << execution << memory << semantics << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpMemoryBarrier(Id scope, Id semantics) { |
|
||||
code->Reserve(3); |
|
||||
return *code << spv::Op::OpMemoryBarrier << scope << semantics << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,76 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpShiftRightLogical(Id result_type, Id base, Id shift) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpShiftRightLogical, result_type} << base << shift << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpShiftRightArithmetic(Id result_type, Id base, Id shift) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpShiftRightArithmetic, result_type} << base << shift << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpShiftLeftLogical(Id result_type, Id base, Id shift) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpShiftLeftLogical, result_type} << base << shift << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitwiseOr(Id result_type, Id operand_1, Id operand_2) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpBitwiseOr, result_type} << operand_1 << operand_2 << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitwiseXor(Id result_type, Id operand_1, Id operand_2) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpBitwiseXor, result_type} << operand_1 << operand_2 << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitwiseAnd(Id result_type, Id operand_1, Id operand_2) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpBitwiseAnd, result_type} << operand_1 << operand_2 << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpNot(Id result_type, Id operand) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpNot, result_type} << operand << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitFieldInsert(Id result_type, Id base, Id insert, Id offset, Id count) { |
|
||||
code->Reserve(7); |
|
||||
return *code << OpId{spv::Op::OpBitFieldInsert, result_type} << base << insert << offset |
|
||||
<< count << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitFieldSExtract(Id result_type, Id base, Id offset, Id count) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpBitFieldSExtract, result_type} << base << offset << count |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitFieldUExtract(Id result_type, Id base, Id offset, Id count) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpBitFieldUExtract, result_type} << base << offset << count |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitReverse(Id result_type, Id base) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpBitReverse, result_type} << base << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBitCount(Id result_type, Id base) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpBitCount, result_type} << base << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,48 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <cassert>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::ConstantTrue(Id result_type) { |
|
||||
declarations->Reserve(3); |
|
||||
return *declarations << OpId{spv::Op::OpConstantTrue, result_type} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::ConstantFalse(Id result_type) { |
|
||||
declarations->Reserve(3); |
|
||||
return *declarations << OpId{spv::Op::OpConstantFalse, result_type} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::Constant(Id result_type, const Literal& literal) { |
|
||||
declarations->Reserve(3 + 2); |
|
||||
return *declarations << OpId{spv::Op::OpConstant, result_type} << literal << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::ConstantComposite(Id result_type, std::span<const Id> constituents) { |
|
||||
declarations->Reserve(3 + constituents.size()); |
|
||||
return *declarations << OpId{spv::Op::OpConstantComposite, result_type} << constituents |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::ConstantSampler(Id result_type, spv::SamplerAddressingMode addressing_mode, |
|
||||
bool normalized, spv::SamplerFilterMode filter_mode) { |
|
||||
declarations->Reserve(6); |
|
||||
return *declarations << OpId{spv::Op::OpConstantSampler, result_type} << addressing_mode |
|
||||
<< normalized << filter_mode << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::ConstantNull(Id result_type) { |
|
||||
declarations->Reserve(3); |
|
||||
return *declarations << OpId{spv::Op::OpConstantNull, result_type} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,29 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
#define DEFINE_UNARY(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id operand) { \ |
|
||||
code->Reserve(4); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << operand << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
DEFINE_UNARY(OpConvertFToU) |
|
||||
DEFINE_UNARY(OpConvertFToS) |
|
||||
DEFINE_UNARY(OpConvertSToF) |
|
||||
DEFINE_UNARY(OpConvertUToF) |
|
||||
DEFINE_UNARY(OpUConvert) |
|
||||
DEFINE_UNARY(OpSConvert) |
|
||||
DEFINE_UNARY(OpFConvert) |
|
||||
DEFINE_UNARY(OpQuantizeToF16) |
|
||||
DEFINE_UNARY(OpBitcast) |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,36 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "common_types.h"
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::Name(Id target, std::string_view name) { |
|
||||
debug->Reserve(3 + WordsInString(name)); |
|
||||
*debug << spv::Op::OpName << target << name << EndOp{}; |
|
||||
return target; |
|
||||
} |
|
||||
|
|
||||
Id Module::MemberName(Id type, u32 member, std::string_view name) { |
|
||||
debug->Reserve(4 + WordsInString(name)); |
|
||||
*debug << spv::Op::OpMemberName << type << member << name << EndOp{}; |
|
||||
return type; |
|
||||
} |
|
||||
|
|
||||
Id Module::String(std::string_view string) { |
|
||||
debug->Reserve(3 + WordsInString(string)); |
|
||||
return *debug << OpId{spv::Op::OpString} << string << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpLine(Id file, Literal line, Literal column) { |
|
||||
debug->Reserve(4); |
|
||||
return *debug << spv::Op::OpLine << file << line << column << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,29 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2021 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
#define DEFINE_UNARY(funcname, opcode) \
|
|
||||
Id Module::funcname(Id result_type, Id operand) { \ |
|
||||
code->Reserve(4); \ |
|
||||
return *code << OpId{opcode, result_type} << operand << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
DEFINE_UNARY(OpDPdx, spv::Op::OpDPdx) |
|
||||
DEFINE_UNARY(OpDPdy, spv::Op::OpDPdy) |
|
||||
DEFINE_UNARY(OpFwidth, spv::Op::OpFwidth) |
|
||||
DEFINE_UNARY(OpDPdxFine, spv::Op::OpDPdxFine) |
|
||||
DEFINE_UNARY(OpDPdyFine, spv::Op::OpDPdyFine) |
|
||||
DEFINE_UNARY(OpFwidthFine, spv::Op::OpFwidthFine) |
|
||||
DEFINE_UNARY(OpDPdxCoarse, spv::Op::OpDPdxCoarse) |
|
||||
DEFINE_UNARY(OpDPdyCoarse, spv::Op::OpDPdyCoarse) |
|
||||
DEFINE_UNARY(OpFwidthCoarse, spv::Op::OpFwidthCoarse) |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,80 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <spirv/unified1/GLSL.std.450.h>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpExtInst(Id result_type, Id set, u32 instruction, std::span<const Id> operands) { |
|
||||
code->Reserve(5 + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpExtInst, result_type} << set << instruction << operands |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_UNARY(funcname, opcode) \
|
|
||||
Id Module::funcname(Id result_type, Id operand) { \ |
|
||||
return OpExtInst(result_type, GetGLSLstd450(), opcode, operand); \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_BINARY(funcname, opcode) \
|
|
||||
Id Module::funcname(Id result_type, Id operand_1, Id operand_2) { \ |
|
||||
return OpExtInst(result_type, GetGLSLstd450(), opcode, operand_1, operand_2); \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_TRINARY(funcname, opcode) \
|
|
||||
Id Module::funcname(Id result_type, Id operand_1, Id operand_2, Id operand_3) { \ |
|
||||
return OpExtInst(result_type, GetGLSLstd450(), opcode, operand_1, operand_2, operand_3); \ |
|
||||
} |
|
||||
|
|
||||
DEFINE_UNARY(OpFAbs, GLSLstd450FAbs) |
|
||||
DEFINE_UNARY(OpSAbs, GLSLstd450SAbs) |
|
||||
DEFINE_UNARY(OpRound, GLSLstd450Round) |
|
||||
DEFINE_UNARY(OpRoundEven, GLSLstd450RoundEven) |
|
||||
DEFINE_UNARY(OpTrunc, GLSLstd450Trunc) |
|
||||
DEFINE_UNARY(OpFSign, GLSLstd450FSign) |
|
||||
DEFINE_UNARY(OpSSign, GLSLstd450SSign) |
|
||||
DEFINE_UNARY(OpFloor, GLSLstd450Floor) |
|
||||
DEFINE_UNARY(OpCeil, GLSLstd450Ceil) |
|
||||
DEFINE_UNARY(OpFract, GLSLstd450Fract) |
|
||||
DEFINE_UNARY(OpSin, GLSLstd450Sin) |
|
||||
DEFINE_UNARY(OpCos, GLSLstd450Cos) |
|
||||
DEFINE_UNARY(OpAsin, GLSLstd450Asin) |
|
||||
DEFINE_UNARY(OpAcos, GLSLstd450Acos) |
|
||||
DEFINE_BINARY(OpPow, GLSLstd450Pow) |
|
||||
DEFINE_UNARY(OpExp, GLSLstd450Exp) |
|
||||
DEFINE_UNARY(OpLog, GLSLstd450Log) |
|
||||
DEFINE_UNARY(OpExp2, GLSLstd450Exp2) |
|
||||
DEFINE_UNARY(OpLog2, GLSLstd450Log2) |
|
||||
DEFINE_UNARY(OpSqrt, GLSLstd450Sqrt) |
|
||||
DEFINE_UNARY(OpInverseSqrt, GLSLstd450InverseSqrt) |
|
||||
DEFINE_BINARY(OpFMin, GLSLstd450FMin) |
|
||||
DEFINE_BINARY(OpUMin, GLSLstd450UMin) |
|
||||
DEFINE_BINARY(OpSMin, GLSLstd450SMin) |
|
||||
DEFINE_BINARY(OpFMax, GLSLstd450FMax) |
|
||||
DEFINE_BINARY(OpUMax, GLSLstd450UMax) |
|
||||
DEFINE_BINARY(OpSMax, GLSLstd450SMax) |
|
||||
DEFINE_TRINARY(OpFClamp, GLSLstd450FClamp) |
|
||||
DEFINE_TRINARY(OpUClamp, GLSLstd450UClamp) |
|
||||
DEFINE_TRINARY(OpSClamp, GLSLstd450SClamp) |
|
||||
DEFINE_TRINARY(OpFma, GLSLstd450Fma) |
|
||||
DEFINE_UNARY(OpPackHalf2x16, GLSLstd450PackHalf2x16) |
|
||||
DEFINE_UNARY(OpUnpackHalf2x16, GLSLstd450UnpackHalf2x16) |
|
||||
DEFINE_UNARY(OpFindILsb, GLSLstd450FindILsb) |
|
||||
DEFINE_UNARY(OpFindSMsb, GLSLstd450FindSMsb) |
|
||||
DEFINE_UNARY(OpFindUMsb, GLSLstd450FindUMsb) |
|
||||
DEFINE_UNARY(OpInterpolateAtCentroid, GLSLstd450InterpolateAtCentroid) |
|
||||
DEFINE_BINARY(OpInterpolateAtSample, GLSLstd450InterpolateAtSample) |
|
||||
DEFINE_BINARY(OpInterpolateAtOffset, GLSLstd450InterpolateAtOffset) |
|
||||
DEFINE_UNARY(OpNormalize, GLSLstd450Normalize) |
|
||||
DEFINE_BINARY(OpCross, GLSLstd450Cross) |
|
||||
DEFINE_UNARY(OpLength, GLSLstd450Length) |
|
||||
DEFINE_TRINARY(OpFMix, GLSLstd450FMix) |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,109 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <cassert>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpPhi(Id result_type, std::span<const Id> operands) { |
|
||||
assert(operands.size() % 2 == 0); |
|
||||
code->Reserve(3 + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpPhi, result_type} << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::DeferredOpPhi(Id result_type, std::span<const Id> blocks) { |
|
||||
deferred_phi_nodes.push_back(code->LocalAddress()); |
|
||||
code->Reserve(3 + blocks.size() * 2); |
|
||||
*code << OpId{spv::Op::OpPhi, result_type}; |
|
||||
for (const Id block : blocks) { |
|
||||
*code << u32{0} << block; |
|
||||
} |
|
||||
return *code << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpLoopMerge(Id merge_block, Id continue_target, spv::LoopControlMask loop_control, |
|
||||
std::span<const Id> literals) { |
|
||||
code->Reserve(4 + literals.size()); |
|
||||
return *code << spv::Op::OpLoopMerge << merge_block << continue_target << loop_control |
|
||||
<< literals << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpSelectionMerge(Id merge_block, spv::SelectionControlMask selection_control) { |
|
||||
code->Reserve(3); |
|
||||
return *code << spv::Op::OpSelectionMerge << merge_block << selection_control << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpLabel() { |
|
||||
return Id{++bound}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBranch(Id target_label) { |
|
||||
code->Reserve(2); |
|
||||
return *code << spv::Op::OpBranch << target_label << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpBranchConditional(Id condition, Id true_label, Id false_label, u32 true_weight, |
|
||||
u32 false_weight) { |
|
||||
code->Reserve(6); |
|
||||
*code << spv::Op::OpBranchConditional << condition << true_label << false_label; |
|
||||
if (true_weight != 0 || false_weight != 0) { |
|
||||
*code << true_weight << false_weight; |
|
||||
} |
|
||||
return *code << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpSwitch(Id selector, Id default_label, std::span<const Literal> literals, |
|
||||
std::span<const Id> labels) { |
|
||||
assert(literals.size() == labels.size()); |
|
||||
const size_t size = literals.size(); |
|
||||
code->Reserve(3 + size * 2); |
|
||||
|
|
||||
*code << spv::Op::OpSwitch << selector << default_label; |
|
||||
for (std::size_t i = 0; i < size; ++i) { |
|
||||
*code << literals[i] << labels[i]; |
|
||||
} |
|
||||
return *code << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpReturn() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpReturn << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpUnreachable() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpUnreachable << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpReturnValue(Id value) { |
|
||||
code->Reserve(2); |
|
||||
return *code << spv::Op::OpReturnValue << value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpKill() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpKill << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpDemoteToHelperInvocation() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpDemoteToHelperInvocation << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpDemoteToHelperInvocationEXT() { |
|
||||
OpDemoteToHelperInvocation(); |
|
||||
} |
|
||||
|
|
||||
void Module::OpTerminateInvocation() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpTerminateInvocation << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,34 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpFunction(Id result_type, spv::FunctionControlMask function_control, Id function_type) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpFunction, result_type} << function_control << function_type |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpFunctionEnd() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpFunctionEnd << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpFunctionCall(Id result_type, Id function, std::span<const Id> arguments) { |
|
||||
code->Reserve(4 + arguments.size()); |
|
||||
return *code << OpId{spv::Op::OpFunctionCall, result_type} << function << arguments << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpFunctionParameter(Id result_type) { |
|
||||
code->Reserve(3); |
|
||||
return *code << OpId{spv::Op::OpFunctionParameter, result_type} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,88 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpSubgroupBallotKHR(Id result_type, Id predicate) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpSubgroupBallotKHR, result_type} << predicate << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpSubgroupReadInvocationKHR(Id result_type, Id value, Id index) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpSubgroupReadInvocationKHR, result_type} << value << index |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpSubgroupAllKHR(Id result_type, Id predicate) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpSubgroupAllKHR, result_type} << predicate << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpSubgroupAnyKHR(Id result_type, Id predicate) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpSubgroupAnyKHR, result_type} << predicate << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpSubgroupAllEqualKHR(Id result_type, Id predicate) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpSubgroupAllEqualKHR, result_type} << predicate << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformElect(Id result_type, Id scope) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformElect, result_type} << scope << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformBroadcastFirst(Id result_type, Id scope, Id value) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformBroadcastFirst, result_type} << scope << value |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformBroadcast(Id result_type, Id scope, Id value, Id id) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformBroadcast, result_type} << scope << value |
|
||||
<< id << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformShuffle(Id result_type, Id scope, Id value, Id id) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformShuffle, result_type} << scope << value << id |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformShuffleXor(Id result_type, Id scope, Id value, Id mask) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformShuffleXor, result_type} << scope << value |
|
||||
<< mask << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformAll(Id result_type, Id scope, Id predicate) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformAll, result_type} << scope << predicate << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformAny(Id result_type, Id scope, Id predicate) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformAny, result_type} << scope << predicate << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformAllEqual(Id result_type, Id scope, Id value) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformAllEqual, result_type} << scope << value << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpGroupNonUniformBallot(Id result_type, Id scope, Id predicate) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpGroupNonUniformBallot, result_type} << scope << predicate << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,169 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <cassert>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
#define DEFINE_IMAGE_OP(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id sampled_image, Id coordinate, \ |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, \ |
|
||||
std::span<const Id> operands) { \ |
|
||||
code->Reserve(6 + operands.size()); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << sampled_image << coordinate \ |
|
||||
<< image_operands << operands << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_IMAGE_EXP_OP(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id sampled_image, Id coordinate, \ |
|
||||
spv::ImageOperandsMask image_operands, std::span<const Id> operands) { \ |
|
||||
code->Reserve(6 + operands.size()); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << sampled_image << coordinate \ |
|
||||
<< image_operands << operands << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_IMAGE_EXTRA_OP(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id sampled_image, Id coordinate, Id extra, \ |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, \ |
|
||||
std::span<const Id> operands) { \ |
|
||||
code->Reserve(7 + operands.size()); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << sampled_image << coordinate << extra \ |
|
||||
<< image_operands << operands << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_IMAGE_EXTRA_EXP_OP(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id sampled_image, Id coordinate, Id extra, \ |
|
||||
spv::ImageOperandsMask image_operands, std::span<const Id> operands) { \ |
|
||||
code->Reserve(8 + operands.size()); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << sampled_image << coordinate << extra \ |
|
||||
<< image_operands << operands << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_IMAGE_QUERY_OP(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id image) { \ |
|
||||
code->Reserve(5); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << image << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_IMAGE_QUERY_BIN_OP(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id image, Id extra) { \ |
|
||||
code->Reserve(5); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << image << extra << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
DEFINE_IMAGE_OP(OpImageSampleImplicitLod) |
|
||||
DEFINE_IMAGE_EXP_OP(OpImageSampleExplicitLod) |
|
||||
DEFINE_IMAGE_EXTRA_OP(OpImageSampleDrefImplicitLod) |
|
||||
DEFINE_IMAGE_EXTRA_EXP_OP(OpImageSampleDrefExplicitLod) |
|
||||
DEFINE_IMAGE_OP(OpImageSampleProjImplicitLod) |
|
||||
DEFINE_IMAGE_EXP_OP(OpImageSampleProjExplicitLod) |
|
||||
DEFINE_IMAGE_EXTRA_OP(OpImageSampleProjDrefImplicitLod) |
|
||||
DEFINE_IMAGE_EXTRA_EXP_OP(OpImageSampleProjDrefExplicitLod) |
|
||||
DEFINE_IMAGE_OP(OpImageFetch) |
|
||||
DEFINE_IMAGE_EXTRA_OP(OpImageGather) |
|
||||
DEFINE_IMAGE_EXTRA_OP(OpImageDrefGather) |
|
||||
DEFINE_IMAGE_OP(OpImageRead) |
|
||||
DEFINE_IMAGE_QUERY_BIN_OP(OpImageQuerySizeLod) |
|
||||
DEFINE_IMAGE_QUERY_OP(OpImageQuerySize) |
|
||||
DEFINE_IMAGE_QUERY_BIN_OP(OpImageQueryLod) |
|
||||
DEFINE_IMAGE_QUERY_OP(OpImageQueryLevels) |
|
||||
DEFINE_IMAGE_QUERY_OP(OpImageQuerySamples) |
|
||||
|
|
||||
Id Module::OpSampledImage(Id result_type, Id image, Id sampler) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpSampledImage, result_type} << image << sampler << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageWrite(Id image, Id coordinate, Id texel, |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
assert(image_operands.has_value() != operands.empty()); |
|
||||
code->Reserve(5 + operands.size()); |
|
||||
return *code << spv::Op::OpImageWrite << image << coordinate << texel << image_operands |
|
||||
<< operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImage(Id result_type, Id sampled_image) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpImage, result_type} << sampled_image << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseSampleImplicitLod(Id result_type, Id sampled_image, Id coordinate, |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(5 + (image_operands.has_value() ? 1 : 0) + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseSampleImplicitLod, result_type} << sampled_image |
|
||||
<< coordinate << image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseSampleExplicitLod(Id result_type, Id sampled_image, Id coordinate, |
|
||||
spv::ImageOperandsMask image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(6 + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseSampleExplicitLod, result_type} << sampled_image |
|
||||
<< coordinate << image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseSampleDrefImplicitLod(Id result_type, Id sampled_image, Id coordinate, |
|
||||
Id dref, |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(6 + (image_operands.has_value() ? 1 : 0) + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseSampleDrefImplicitLod, result_type} << sampled_image |
|
||||
<< coordinate << dref << image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseSampleDrefExplicitLod(Id result_type, Id sampled_image, Id coordinate, |
|
||||
Id dref, spv::ImageOperandsMask image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(7 + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseSampleDrefExplicitLod, result_type} << sampled_image |
|
||||
<< coordinate << dref << image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseFetch(Id result_type, Id image, Id coordinate, |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(5 + (image_operands.has_value() ? 1 : 0) + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseFetch, result_type} << image << coordinate |
|
||||
<< image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseGather(Id result_type, Id sampled_image, Id coordinate, Id component, |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(6 + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseGather, result_type} << sampled_image << coordinate |
|
||||
<< component << image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseDrefGather(Id result_type, Id sampled_image, Id coordinate, Id dref, |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(6 + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseDrefGather, result_type} << sampled_image |
|
||||
<< coordinate << dref << image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseTexelsResident(Id result_type, Id resident_code) { |
|
||||
code->Reserve(4); |
|
||||
return *code << OpId{spv::Op::OpImageSparseTexelsResident, result_type} << resident_code |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpImageSparseRead(Id result_type, Id image, Id coordinate, |
|
||||
std::optional<spv::ImageOperandsMask> image_operands, |
|
||||
std::span<const Id> operands) { |
|
||||
code->Reserve(5 + (image_operands.has_value() ? 1 : 0) + operands.size()); |
|
||||
return *code << OpId{spv::Op::OpImageSparseTexelsResident, result_type} << image << coordinate |
|
||||
<< image_operands << operands << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,65 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
#define DEFINE_UNARY(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id operand) { \ |
|
||||
code->Reserve(4); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << operand << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_BINARY(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id operand_1, Id operand_2) { \ |
|
||||
code->Reserve(5); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << operand_1 << operand_2 << EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
#define DEFINE_TRINARY(opcode) \
|
|
||||
Id Module::opcode(Id result_type, Id operand_1, Id operand_2, Id operand_3) { \ |
|
||||
code->Reserve(6); \ |
|
||||
return *code << OpId{spv::Op::opcode, result_type} << operand_1 << operand_2 << operand_3 \ |
|
||||
<< EndOp{}; \ |
|
||||
} |
|
||||
|
|
||||
DEFINE_UNARY(OpAny) |
|
||||
DEFINE_UNARY(OpAll) |
|
||||
DEFINE_UNARY(OpIsNan) |
|
||||
DEFINE_UNARY(OpIsInf) |
|
||||
DEFINE_BINARY(OpLogicalEqual) |
|
||||
DEFINE_BINARY(OpLogicalNotEqual) |
|
||||
DEFINE_BINARY(OpLogicalOr) |
|
||||
DEFINE_BINARY(OpLogicalAnd) |
|
||||
DEFINE_UNARY(OpLogicalNot) |
|
||||
DEFINE_TRINARY(OpSelect) |
|
||||
DEFINE_BINARY(OpIEqual) |
|
||||
DEFINE_BINARY(OpINotEqual) |
|
||||
DEFINE_BINARY(OpUGreaterThan) |
|
||||
DEFINE_BINARY(OpSGreaterThan) |
|
||||
DEFINE_BINARY(OpUGreaterThanEqual) |
|
||||
DEFINE_BINARY(OpSGreaterThanEqual) |
|
||||
DEFINE_BINARY(OpULessThan) |
|
||||
DEFINE_BINARY(OpSLessThan) |
|
||||
DEFINE_BINARY(OpULessThanEqual) |
|
||||
DEFINE_BINARY(OpSLessThanEqual) |
|
||||
DEFINE_BINARY(OpFOrdEqual) |
|
||||
DEFINE_BINARY(OpFUnordEqual) |
|
||||
DEFINE_BINARY(OpFOrdNotEqual) |
|
||||
DEFINE_BINARY(OpFUnordNotEqual) |
|
||||
DEFINE_BINARY(OpFOrdLessThan) |
|
||||
DEFINE_BINARY(OpFUnordLessThan) |
|
||||
DEFINE_BINARY(OpFOrdGreaterThan) |
|
||||
DEFINE_BINARY(OpFUnordGreaterThan) |
|
||||
DEFINE_BINARY(OpFOrdLessThanEqual) |
|
||||
DEFINE_BINARY(OpFUnordLessThanEqual) |
|
||||
DEFINE_BINARY(OpFOrdGreaterThanEqual) |
|
||||
DEFINE_BINARY(OpFUnordGreaterThanEqual) |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,74 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <cassert>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpImageTexelPointer(Id result_type, Id image, Id coordinate, Id sample) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpImageTexelPointer, result_type} << image << coordinate << sample |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpLoad(Id result_type, Id pointer, std::optional<spv::MemoryAccessMask> memory_access) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpLoad, result_type} << pointer << memory_access << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpStore(Id pointer, Id object, std::optional<spv::MemoryAccessMask> memory_access) { |
|
||||
code->Reserve(4); |
|
||||
return *code << spv::Op::OpStore << pointer << object << memory_access << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpAccessChain(Id result_type, Id base, std::span<const Id> indexes) { |
|
||||
assert(!indexes.empty()); |
|
||||
code->Reserve(4 + indexes.size()); |
|
||||
return *code << OpId{spv::Op::OpAccessChain, result_type} << base << indexes << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpVectorExtractDynamic(Id result_type, Id vector, Id index) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpVectorExtractDynamic, result_type} << vector << index |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpVectorInsertDynamic(Id result_type, Id vector, Id component, Id index) { |
|
||||
code->Reserve(6); |
|
||||
return *code << OpId{spv::Op::OpVectorInsertDynamic, result_type} << vector << component |
|
||||
<< index << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpVectorShuffle(Id result_type, Id vector_1, Id vector_2, std::span<const Literal> components) { |
|
||||
code->Reserve(5 + components.size()); |
|
||||
return *code << OpId{spv::Op::OpVectorShuffle, result_type} << vector_1 << vector_2 |
|
||||
<< components << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpCompositeInsert(Id result_type, Id object, Id composite, |
|
||||
std::span<const Literal> indexes) { |
|
||||
code->Reserve(5 + indexes.size()); |
|
||||
return *code << OpId{spv::Op::OpCompositeInsert, result_type} << object << composite << indexes |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpCompositeExtract(Id result_type, Id composite, std::span<const Literal> indexes) { |
|
||||
code->Reserve(4 + indexes.size()); |
|
||||
return *code << OpId{spv::Op::OpCompositeExtract, result_type} << composite << indexes |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::OpCompositeConstruct(Id result_type, std::span<const Id> ids) { |
|
||||
assert(ids.size() >= 1); |
|
||||
code->Reserve(3 + ids.size()); |
|
||||
return *code << OpId{spv::Op::OpCompositeConstruct, result_type} << ids << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,38 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::OpUndef(Id result_type) { |
|
||||
code->Reserve(3); |
|
||||
return *code << OpId{spv::Op::OpUndef, result_type} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpEmitVertex() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpEmitVertex << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpEndPrimitive() { |
|
||||
code->Reserve(1); |
|
||||
*code << spv::Op::OpEndPrimitive << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpEmitStreamVertex(Id stream) { |
|
||||
code->Reserve(2); |
|
||||
*code << spv::Op::OpEmitStreamVertex << stream << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::OpEndStreamPrimitive(Id stream) { |
|
||||
code->Reserve(2); |
|
||||
*code << spv::Op::OpEndStreamPrimitive << stream << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,130 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <cassert>
|
|
||||
#include <optional>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
Id Module::TypeVoid() { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypeVoid} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeBool() { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypeBool} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeInt(int width, bool is_signed) { |
|
||||
declarations->Reserve(4); |
|
||||
return *declarations << OpId{spv::Op::OpTypeInt} << width << is_signed << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeSInt(int width) { |
|
||||
return TypeInt(width, true); |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeUInt(int width) { |
|
||||
return TypeInt(width, false); |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeFloat(int width) { |
|
||||
declarations->Reserve(3); |
|
||||
return *declarations << OpId{spv::Op::OpTypeFloat} << width << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeVector(Id component_type, int component_count) { |
|
||||
assert(component_count >= 2); |
|
||||
declarations->Reserve(4); |
|
||||
return *declarations << OpId{spv::Op::OpTypeVector} << component_type << component_count |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeMatrix(Id column_type, int column_count) { |
|
||||
assert(column_count >= 2); |
|
||||
declarations->Reserve(4); |
|
||||
return *declarations << OpId{spv::Op::OpTypeMatrix} << column_type << column_count << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeImage(Id sampled_type, spv::Dim dim, int depth, bool arrayed, bool ms, int sampled, |
|
||||
spv::ImageFormat image_format, |
|
||||
std::optional<spv::AccessQualifier> access_qualifier) { |
|
||||
declarations->Reserve(10); |
|
||||
return *declarations << OpId{spv::Op::OpTypeImage} << sampled_type << dim << depth << arrayed |
|
||||
<< ms << sampled << image_format << access_qualifier << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeSampler() { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypeSampler} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeSampledImage(Id image_type) { |
|
||||
declarations->Reserve(3); |
|
||||
return *declarations << OpId{spv::Op::OpTypeSampledImage} << image_type << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeArray(Id element_type, Id length) { |
|
||||
declarations->Reserve(4); |
|
||||
return *declarations << OpId{spv::Op::OpTypeArray} << element_type << length << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeRuntimeArray(Id element_type) { |
|
||||
declarations->Reserve(3); |
|
||||
return *declarations << OpId{spv::Op::OpTypeRuntimeArray} << element_type << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeStruct(std::span<const Id> members) { |
|
||||
declarations->Reserve(2 + members.size()); |
|
||||
return *declarations << OpId{spv::Op::OpTypeStruct} << members << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeOpaque(std::string_view name) { |
|
||||
declarations->Reserve(3 + WordsInString(name)); |
|
||||
return *declarations << OpId{spv::Op::OpTypeOpaque} << name << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypePointer(spv::StorageClass storage_class, Id type) { |
|
||||
declarations->Reserve(4); |
|
||||
return *declarations << OpId{spv::Op::OpTypePointer} << storage_class << type << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeFunction(Id return_type, std::span<const Id> arguments) { |
|
||||
declarations->Reserve(3 + arguments.size()); |
|
||||
return *declarations << OpId{spv::Op::OpTypeFunction} << return_type << arguments << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeEvent() { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypeEvent} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeDeviceEvent() { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypeDeviceEvent} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeReserveId() { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypeReserveId} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypeQueue() { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypeQueue} << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::TypePipe(spv::AccessQualifier access_qualifier) { |
|
||||
declarations->Reserve(2); |
|
||||
return *declarations << OpId{spv::Op::OpTypePipe} << access_qualifier << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,142 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <cassert>
|
|
||||
|
|
||||
#include "sirit/sirit.h"
|
|
||||
|
|
||||
#include "common_types.h"
|
|
||||
#include "stream.h"
|
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
constexpr u32 MakeWord0(spv::Op op, size_t word_count) { |
|
||||
return static_cast<u32>(op) | static_cast<u32>(word_count) << 16; |
|
||||
} |
|
||||
|
|
||||
Module::Module(u32 version_) |
|
||||
: version{version_}, ext_inst_imports{std::make_unique<Stream>(&bound)}, |
|
||||
entry_points{std::make_unique<Stream>(&bound)}, |
|
||||
execution_modes{std::make_unique<Stream>(&bound)}, debug{std::make_unique<Stream>(&bound)}, |
|
||||
annotations{std::make_unique<Stream>(&bound)}, declarations{std::make_unique<Declarations>( |
|
||||
&bound)}, |
|
||||
global_variables{std::make_unique<Stream>(&bound)}, code{std::make_unique<Stream>(&bound)} {} |
|
||||
|
|
||||
Module::~Module() = default; |
|
||||
|
|
||||
std::vector<u32> Module::Assemble() const { |
|
||||
std::vector<u32> words = {spv::MagicNumber, version, GENERATOR_MAGIC_NUMBER, bound + 1, 0}; |
|
||||
const auto insert = [&words](std::span<const u32> input) { |
|
||||
words.insert(words.end(), input.begin(), input.end()); |
|
||||
}; |
|
||||
|
|
||||
words.reserve(words.size() + capabilities.size() * 2); |
|
||||
for (const spv::Capability capability : capabilities) { |
|
||||
insert(std::array{ |
|
||||
MakeWord0(spv::Op::OpCapability, 2), |
|
||||
static_cast<u32>(capability), |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
for (const std::string_view extension_name : extensions) { |
|
||||
size_t string_words = WordsInString(extension_name); |
|
||||
words.push_back(MakeWord0(spv::Op::OpExtension, string_words + 1)); |
|
||||
size_t insert_index = words.size(); |
|
||||
words.resize(words.size() + string_words); |
|
||||
InsertStringView(words, insert_index, extension_name); |
|
||||
} |
|
||||
|
|
||||
insert(ext_inst_imports->Words()); |
|
||||
|
|
||||
insert(std::array{ |
|
||||
MakeWord0(spv::Op::OpMemoryModel, 3), |
|
||||
static_cast<u32>(addressing_model), |
|
||||
static_cast<u32>(memory_model), |
|
||||
}); |
|
||||
|
|
||||
insert(entry_points->Words()); |
|
||||
insert(execution_modes->Words()); |
|
||||
insert(debug->Words()); |
|
||||
insert(annotations->Words()); |
|
||||
insert(declarations->Words()); |
|
||||
insert(global_variables->Words()); |
|
||||
insert(code->Words()); |
|
||||
|
|
||||
return words; |
|
||||
} |
|
||||
|
|
||||
void Module::PatchDeferredPhi(const std::function<Id(std::size_t index)>& func) { |
|
||||
for (const u32 phi_index : deferred_phi_nodes) { |
|
||||
const u32 first_word = code->Value(phi_index); |
|
||||
[[maybe_unused]] const spv::Op op = static_cast<spv::Op>(first_word & 0xffff); |
|
||||
assert(op == spv::Op::OpPhi); |
|
||||
const u32 num_words = first_word >> 16; |
|
||||
const u32 num_args = (num_words - 3) / 2; |
|
||||
u32 cursor = phi_index + 3; |
|
||||
for (u32 arg = 0; arg < num_args; ++arg, cursor += 2) { |
|
||||
code->SetValue(cursor, func(arg).value); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void Module::AddExtension(std::string extension_name) { |
|
||||
extensions.insert(std::move(extension_name)); |
|
||||
} |
|
||||
|
|
||||
void Module::AddCapability(spv::Capability capability) { |
|
||||
capabilities.insert(capability); |
|
||||
} |
|
||||
|
|
||||
void Module::SetMemoryModel(spv::AddressingModel addressing_model_, |
|
||||
spv::MemoryModel memory_model_) { |
|
||||
addressing_model = addressing_model_; |
|
||||
memory_model = memory_model_; |
|
||||
} |
|
||||
|
|
||||
void Module::AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point, |
|
||||
std::string_view name, std::span<const Id> interfaces) { |
|
||||
entry_points->Reserve(4 + WordsInString(name) + interfaces.size()); |
|
||||
*entry_points << spv::Op::OpEntryPoint << execution_model << entry_point << name << interfaces |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
void Module::AddExecutionMode(Id entry_point, spv::ExecutionMode mode, |
|
||||
std::span<const Literal> literals) { |
|
||||
execution_modes->Reserve(3 + literals.size()); |
|
||||
*execution_modes << spv::Op::OpExecutionMode << entry_point << mode << literals << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::AddLabel(Id label) { |
|
||||
assert(label.value != 0); |
|
||||
code->Reserve(2); |
|
||||
*code << MakeWord0(spv::Op::OpLabel, 2) << label.value; |
|
||||
return label; |
|
||||
} |
|
||||
|
|
||||
Id Module::AddLocalVariable(Id result_type, spv::StorageClass storage_class, |
|
||||
std::optional<Id> initializer) { |
|
||||
code->Reserve(5); |
|
||||
return *code << OpId{spv::Op::OpVariable, result_type} << storage_class << initializer |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::AddGlobalVariable(Id result_type, spv::StorageClass storage_class, |
|
||||
std::optional<Id> initializer) { |
|
||||
global_variables->Reserve(5); |
|
||||
return *global_variables << OpId{spv::Op::OpVariable, result_type} << storage_class |
|
||||
<< initializer << EndOp{}; |
|
||||
} |
|
||||
|
|
||||
Id Module::GetGLSLstd450() { |
|
||||
if (!glsl_std_450) { |
|
||||
ext_inst_imports->Reserve(3 + 4); |
|
||||
glsl_std_450 = *ext_inst_imports << OpId{spv::Op::OpExtInstImport} << "GLSL.std.450" |
|
||||
<< EndOp{}; |
|
||||
} |
|
||||
return *glsl_std_450; |
|
||||
} |
|
||||
|
|
||||
} // namespace Sirit
|
|
||||
@ -1,267 +0,0 @@ |
|||||
/* This file is part of the sirit project. |
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include <bit> |
|
||||
#include <cassert> |
|
||||
#include <concepts> |
|
||||
#include <cstddef> |
|
||||
#include <functional> |
|
||||
#include <span> |
|
||||
#include <string_view> |
|
||||
#include <unordered_map> |
|
||||
#include <variant> |
|
||||
#include <vector> |
|
||||
#include <utility> |
|
||||
|
|
||||
#ifndef __cpp_lib_bit_cast |
|
||||
#include <cstring> |
|
||||
#endif |
|
||||
|
|
||||
#include <spirv/unified1/spirv.hpp> |
|
||||
|
|
||||
#include "common_types.h" |
|
||||
|
|
||||
namespace Sirit { |
|
||||
|
|
||||
class Declarations; |
|
||||
|
|
||||
struct OpId { |
|
||||
OpId(spv::Op opcode_) : opcode{opcode_} {} |
|
||||
OpId(spv::Op opcode_, Id result_type_) : opcode{opcode_}, result_type{result_type_} { |
|
||||
assert(result_type.value != 0); |
|
||||
} |
|
||||
|
|
||||
spv::Op opcode{}; |
|
||||
Id result_type{}; |
|
||||
}; |
|
||||
|
|
||||
struct EndOp {}; |
|
||||
|
|
||||
inline size_t WordsInString(std::string_view string) { |
|
||||
return string.size() / sizeof(u32) + 1; |
|
||||
} |
|
||||
|
|
||||
inline void InsertStringView(std::vector<u32>& words, size_t& insert_index, |
|
||||
std::string_view string) { |
|
||||
const size_t size = string.size(); |
|
||||
const auto read = [string, size](size_t offset) { |
|
||||
return offset < size ? static_cast<u32>(string[offset]) : 0u; |
|
||||
}; |
|
||||
|
|
||||
for (size_t i = 0; i < size; i += sizeof(u32)) { |
|
||||
words[insert_index++] = read(i) | read(i + 1) << 8 | read(i + 2) << 16 | read(i + 3) << 24; |
|
||||
} |
|
||||
if (size % sizeof(u32) == 0) { |
|
||||
words[insert_index++] = 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
class Stream { |
|
||||
friend Declarations; |
|
||||
|
|
||||
public: |
|
||||
explicit Stream(u32* bound_) : bound{bound_} {} |
|
||||
|
|
||||
void Reserve(size_t num_words) { |
|
||||
if (insert_index + num_words <= words.size()) { |
|
||||
return; |
|
||||
} |
|
||||
words.resize(insert_index + num_words); |
|
||||
} |
|
||||
|
|
||||
std::span<const u32> Words() const noexcept { |
|
||||
return std::span(words.data(), insert_index); |
|
||||
} |
|
||||
|
|
||||
u32 LocalAddress() const noexcept { |
|
||||
return static_cast<u32>(words.size()); |
|
||||
} |
|
||||
|
|
||||
u32 Value(u32 index) const noexcept { |
|
||||
return words[index]; |
|
||||
} |
|
||||
|
|
||||
void SetValue(u32 index, u32 value) noexcept { |
|
||||
words[index] = value; |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(spv::Op op) { |
|
||||
op_index = insert_index; |
|
||||
words[insert_index++] = static_cast<u32>(op); |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(OpId op) { |
|
||||
op_index = insert_index; |
|
||||
words[insert_index++] = static_cast<u32>(op.opcode); |
|
||||
if (op.result_type.value != 0) { |
|
||||
words[insert_index++] = op.result_type.value; |
|
||||
} |
|
||||
words[insert_index++] = ++*bound; |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
Id operator<<(EndOp) { |
|
||||
const size_t num_words = insert_index - op_index; |
|
||||
words[op_index] |= static_cast<u32>(num_words) << 16; |
|
||||
return Id{*bound}; |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(u32 value) { |
|
||||
words[insert_index++] = value; |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(s32 value) { |
|
||||
return *this << static_cast<u32>(value); |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(u64 value) { |
|
||||
return *this << static_cast<u32>(value) << static_cast<u32>(value >> 32); |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(s64 value) { |
|
||||
return *this << static_cast<u64>(value); |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(float value) { |
|
||||
#ifdef __cpp_lib_bit_cast |
|
||||
return *this << std::bit_cast<u32>(value); |
|
||||
#else |
|
||||
static_assert(sizeof(float) == sizeof(u32)); |
|
||||
u32 int_value; |
|
||||
std::memcpy(&int_value, &value, sizeof(int_value)); |
|
||||
return *this << int_value; |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(double value) { |
|
||||
#ifdef __cpp_lib_bit_cast |
|
||||
return *this << std::bit_cast<u64>(value); |
|
||||
#else |
|
||||
static_assert(sizeof(double) == sizeof(u64)); |
|
||||
u64 int_value; |
|
||||
std::memcpy(&int_value, &value, sizeof(int_value)); |
|
||||
return *this << int_value; |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(bool value) { |
|
||||
return *this << static_cast<u32>(value ? 1 : 0); |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(Id value) { |
|
||||
assert(value.value != 0); |
|
||||
return *this << value.value; |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(const Literal& literal) { |
|
||||
std::visit([this](auto value) { *this << value; }, literal); |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(std::string_view string) { |
|
||||
InsertStringView(words, insert_index, string); |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
Stream& operator<<(const char* string) { |
|
||||
return *this << std::string_view{string}; |
|
||||
} |
|
||||
|
|
||||
template <typename T> |
|
||||
requires std::is_enum_v<T> Stream& operator<<(T value) { |
|
||||
static_assert(sizeof(T) == sizeof(u32)); |
|
||||
return *this << static_cast<u32>(value); |
|
||||
} |
|
||||
|
|
||||
template <typename T> |
|
||||
Stream& operator<<(std::optional<T> value) { |
|
||||
if (value) { |
|
||||
*this << *value; |
|
||||
} |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
template <typename T> |
|
||||
Stream& operator<<(std::span<const T> values) { |
|
||||
for (const auto& value : values) { |
|
||||
*this << value; |
|
||||
} |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
u32* bound = nullptr; |
|
||||
std::vector<u32> words; |
|
||||
size_t insert_index = 0; |
|
||||
size_t op_index = 0; |
|
||||
}; |
|
||||
|
|
||||
class Declarations { |
|
||||
public: |
|
||||
explicit Declarations(u32* bound) : stream{bound} {} |
|
||||
|
|
||||
void Reserve(size_t num_words) { |
|
||||
return stream.Reserve(num_words); |
|
||||
} |
|
||||
|
|
||||
std::span<const u32> Words() const noexcept { |
|
||||
return stream.Words(); |
|
||||
} |
|
||||
|
|
||||
template <typename T> |
|
||||
Declarations& operator<<(const T& value) { |
|
||||
stream << value; |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
// Declarations without an id don't exist |
|
||||
Declarations& operator<<(spv::Op) = delete; |
|
||||
|
|
||||
Declarations& operator<<(OpId op) { |
|
||||
id_index = op.result_type.value != 0 ? 2 : 1; |
|
||||
stream << op; |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
Id operator<<(EndOp) { |
|
||||
const auto begin = stream.words.data(); |
|
||||
std::vector<u32> declarations(begin + stream.op_index, begin + stream.insert_index); |
|
||||
|
|
||||
// Normalize result id for lookups |
|
||||
const u32 id = std::exchange(declarations[id_index], 0); |
|
||||
|
|
||||
const auto [entry, inserted] = existing_declarations.emplace(declarations, id); |
|
||||
if (inserted) { |
|
||||
return stream << EndOp{}; |
|
||||
} |
|
||||
// If the declaration already exists, undo the operation |
|
||||
stream.insert_index = stream.op_index; |
|
||||
--*stream.bound; |
|
||||
|
|
||||
return Id{entry->second}; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
struct HashVector { |
|
||||
size_t operator()(const std::vector<u32>& vector) const noexcept { |
|
||||
size_t hash = std::hash<size_t>{}(vector.size()); |
|
||||
for (const u32 value : vector) { |
|
||||
hash ^= std::hash<u32>{}(value); |
|
||||
} |
|
||||
return hash; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
Stream stream; |
|
||||
std::unordered_map<std::vector<u32>, u32, HashVector> existing_declarations; |
|
||||
size_t id_index = 0; |
|
||||
}; |
|
||||
|
|
||||
} // namespace Sirit |
|
||||
@ -1,6 +0,0 @@ |
|||||
add_executable(sirit_tests |
|
||||
main.cpp) |
|
||||
target_link_libraries(sirit_tests PRIVATE sirit) |
|
||||
target_include_directories(sirit_tests PRIVATE . ../include) |
|
||||
|
|
||||
add_test(sirit_tests sirit_tests) |
|
||||
@ -1,139 +0,0 @@ |
|||||
/* This file is part of the sirit project.
|
|
||||
* Copyright (c) 2019 sirit |
|
||||
* This software may be used and distributed according to the terms of the |
|
||||
* 3-Clause BSD License |
|
||||
*/ |
|
||||
|
|
||||
#include <cstdio>
|
|
||||
#include <cstdlib>
|
|
||||
#include <cstring>
|
|
||||
|
|
||||
#include <sirit/sirit.h>
|
|
||||
|
|
||||
class MyModule : public Sirit::Module { |
|
||||
public: |
|
||||
MyModule() : Sirit::Module{0x00010300} {} |
|
||||
~MyModule() = default; |
|
||||
|
|
||||
void Generate() { |
|
||||
AddCapability(spv::Capability::Shader); |
|
||||
SetMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450); |
|
||||
|
|
||||
const auto t_void = Name(TypeVoid(), "void"); |
|
||||
const auto t_uint = Name(TypeInt(32, false), "uint"); |
|
||||
const auto t_float = Name(TypeFloat(32), "float"); |
|
||||
|
|
||||
const auto float4 = Name(TypeVector(t_float, 4), "float4"); |
|
||||
const auto in_float = Name(TypePointer(spv::StorageClass::Input, t_float), "in_float"); |
|
||||
const auto in_float4 = Name(TypePointer(spv::StorageClass::Input, float4), "in_float4"); |
|
||||
const auto out_float4 = Name(TypePointer(spv::StorageClass::Output, float4), "out_float4"); |
|
||||
|
|
||||
const auto gl_per_vertex = Name(TypeStruct(float4), "gl_PerVertex"); |
|
||||
const auto gl_per_vertex_ptr = |
|
||||
Name(TypePointer(spv::StorageClass::Output, gl_per_vertex), "out_gl_PerVertex"); |
|
||||
|
|
||||
const auto in_pos = Name(AddGlobalVariable(in_float4, spv::StorageClass::Input), "in_pos"); |
|
||||
const auto per_vertex = |
|
||||
Name(AddGlobalVariable(gl_per_vertex_ptr, spv::StorageClass::Output), "per_vertex"); |
|
||||
|
|
||||
Decorate(in_pos, spv::Decoration::Location, 0); |
|
||||
Decorate(gl_per_vertex, spv::Decoration::Block); |
|
||||
Decorate(gl_per_vertex, spv::Decoration::Block); |
|
||||
MemberDecorate(gl_per_vertex, 0, spv::Decoration::BuiltIn, |
|
||||
static_cast<std::uint32_t>(spv::BuiltIn::Position)); |
|
||||
|
|
||||
const auto main_func = Name( |
|
||||
OpFunction(t_void, spv::FunctionControlMask::MaskNone, TypeFunction(t_void)), "main"); |
|
||||
AddLabel(); |
|
||||
|
|
||||
const auto ptr_pos_x = OpAccessChain(in_float, in_pos, Constant(t_uint, 0u)); |
|
||||
const auto ptr_pos_y = OpAccessChain(in_float, in_pos, Constant(t_uint, 1u)); |
|
||||
|
|
||||
const auto pos_x = OpLoad(t_float, ptr_pos_x); |
|
||||
const auto pos_y = OpLoad(t_float, ptr_pos_y); |
|
||||
|
|
||||
auto tmp_position = OpUndef(float4); |
|
||||
tmp_position = OpCompositeInsert(float4, pos_x, tmp_position, 0); |
|
||||
tmp_position = OpCompositeInsert(float4, pos_y, tmp_position, 1); |
|
||||
tmp_position = OpCompositeInsert(float4, Constant(t_float, 0.0f), tmp_position, 2); |
|
||||
tmp_position = OpCompositeInsert(float4, Constant(t_float, 1.0f), tmp_position, 3); |
|
||||
|
|
||||
const auto gl_position = OpAccessChain(out_float4, per_vertex, Constant(t_uint, 0u)); |
|
||||
OpStore(gl_position, tmp_position); |
|
||||
|
|
||||
OpReturn(); |
|
||||
OpFunctionEnd(); |
|
||||
|
|
||||
AddEntryPoint(spv::ExecutionModel::Vertex, main_func, "main", in_pos, per_vertex); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
static constexpr std::uint8_t expected_binary[] = { |
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, |
|
||||
0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, |
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||
0x0d, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, |
|
||||
0x0b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x76, 0x6f, 0x69, 0x64, |
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x75, 0x69, 0x6e, 0x74, |
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x6f, 0x61, |
|
||||
0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x66, 0x6c, 0x6f, 0x61, |
|
||||
0x74, 0x34, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x66, |
|
||||
0x6c, 0x6f, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, |
|
||||
0x69, 0x6e, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, |
|
||||
0x07, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x00, 0x00, |
|
||||
0x05, 0x00, 0x06, 0x00, 0x08, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, |
|
||||
0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, |
|
||||
0x6f, 0x75, 0x74, 0x5f, 0x67, 0x6c, 0x5f, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, |
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x70, |
|
||||
0x6f, 0x73, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x70, 0x65, 0x72, 0x5f, |
|
||||
0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, |
|
||||
0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, |
|
||||
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, |
|
||||
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, |
|
||||
0x48, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, |
|
||||
0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, |
|
||||
0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, |
|
||||
0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, |
|
||||
0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, |
|
||||
0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, |
|
||||
0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, |
|
||||
0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, |
|
||||
0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, |
|
||||
0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
|
||||
0x2b, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||
0x2b, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
|
||||
0x2b, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||
0x2b, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, |
|
||||
0x3b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
|
||||
0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, |
|
||||
0x36, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
|
||||
0x0c, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, |
|
||||
0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, |
|
||||
0x41, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, |
|
||||
0x11, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, |
|
||||
0x10, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, |
|
||||
0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, |
|
||||
0x52, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, |
|
||||
0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, |
|
||||
0x17, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, |
|
||||
0x52, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, |
|
||||
0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x52, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, |
|
||||
0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, |
|
||||
0x41, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, |
|
||||
0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, |
|
||||
0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, |
|
||||
}; |
|
||||
|
|
||||
int main(int argc, char** argv) { |
|
||||
MyModule module; |
|
||||
module.Generate(); |
|
||||
|
|
||||
std::vector<std::uint32_t> code = module.Assemble(); |
|
||||
if (std::size(code) * sizeof(std::uint32_t) != std::size(expected_binary)) { |
|
||||
return EXIT_FAILURE; |
|
||||
} |
|
||||
if (std::memcmp(std::data(code), std::data(expected_binary), std::size(expected_binary)) != 0) { |
|
||||
return EXIT_FAILURE; |
|
||||
} |
|
||||
return EXIT_SUCCESS; |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue