Initial commit.
This commit is contained in:
commit
75471fbb98
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
*.o
|
||||||
|
*.d
|
||||||
|
*.txt
|
||||||
|
/test
|
||||||
|
/spir2cross
|
||||||
|
*.spv
|
||||||
|
/obj
|
||||||
|
/msvc/x64
|
||||||
|
/msvc/Debug
|
||||||
|
/msvc/Release
|
||||||
|
*.suo
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
131
GLSL.std.450.h
Normal file
131
GLSL.std.450.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
** of this software and/or associated documentation files (the "Materials"),
|
||||||
|
** to deal in the Materials without restriction, including without limitation
|
||||||
|
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||||
|
** Materials are furnished to do so, subject to the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included in
|
||||||
|
** all copies or substantial portions of the Materials.
|
||||||
|
**
|
||||||
|
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||||
|
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||||
|
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||||
|
**
|
||||||
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||||
|
** IN THE MATERIALS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GLSLstd450_H
|
||||||
|
#define GLSLstd450_H
|
||||||
|
|
||||||
|
static const int GLSLstd450Version = 100;
|
||||||
|
static const int GLSLstd450Revision = 1;
|
||||||
|
|
||||||
|
enum GLSLstd450 {
|
||||||
|
GLSLstd450Bad = 0, // Don't use
|
||||||
|
|
||||||
|
GLSLstd450Round = 1,
|
||||||
|
GLSLstd450RoundEven = 2,
|
||||||
|
GLSLstd450Trunc = 3,
|
||||||
|
GLSLstd450FAbs = 4,
|
||||||
|
GLSLstd450SAbs = 5,
|
||||||
|
GLSLstd450FSign = 6,
|
||||||
|
GLSLstd450SSign = 7,
|
||||||
|
GLSLstd450Floor = 8,
|
||||||
|
GLSLstd450Ceil = 9,
|
||||||
|
GLSLstd450Fract = 10,
|
||||||
|
|
||||||
|
GLSLstd450Radians = 11,
|
||||||
|
GLSLstd450Degrees = 12,
|
||||||
|
GLSLstd450Sin = 13,
|
||||||
|
GLSLstd450Cos = 14,
|
||||||
|
GLSLstd450Tan = 15,
|
||||||
|
GLSLstd450Asin = 16,
|
||||||
|
GLSLstd450Acos = 17,
|
||||||
|
GLSLstd450Atan = 18,
|
||||||
|
GLSLstd450Sinh = 19,
|
||||||
|
GLSLstd450Cosh = 20,
|
||||||
|
GLSLstd450Tanh = 21,
|
||||||
|
GLSLstd450Asinh = 22,
|
||||||
|
GLSLstd450Acosh = 23,
|
||||||
|
GLSLstd450Atanh = 24,
|
||||||
|
GLSLstd450Atan2 = 25,
|
||||||
|
|
||||||
|
GLSLstd450Pow = 26,
|
||||||
|
GLSLstd450Exp = 27,
|
||||||
|
GLSLstd450Log = 28,
|
||||||
|
GLSLstd450Exp2 = 29,
|
||||||
|
GLSLstd450Log2 = 30,
|
||||||
|
GLSLstd450Sqrt = 31,
|
||||||
|
GLSLstd450InverseSqrt = 32,
|
||||||
|
|
||||||
|
GLSLstd450Determinant = 33,
|
||||||
|
GLSLstd450MatrixInverse = 34,
|
||||||
|
|
||||||
|
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
|
||||||
|
GLSLstd450ModfStruct = 36, // no OpVariable operand
|
||||||
|
GLSLstd450FMin = 37,
|
||||||
|
GLSLstd450UMin = 38,
|
||||||
|
GLSLstd450SMin = 39,
|
||||||
|
GLSLstd450FMax = 40,
|
||||||
|
GLSLstd450UMax = 41,
|
||||||
|
GLSLstd450SMax = 42,
|
||||||
|
GLSLstd450FClamp = 43,
|
||||||
|
GLSLstd450UClamp = 44,
|
||||||
|
GLSLstd450SClamp = 45,
|
||||||
|
GLSLstd450FMix = 46,
|
||||||
|
GLSLstd450IMix = 47, // Reserved
|
||||||
|
GLSLstd450Step = 48,
|
||||||
|
GLSLstd450SmoothStep = 49,
|
||||||
|
|
||||||
|
GLSLstd450Fma = 50,
|
||||||
|
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
|
||||||
|
GLSLstd450FrexpStruct = 52, // no OpVariable operand
|
||||||
|
GLSLstd450Ldexp = 53,
|
||||||
|
|
||||||
|
GLSLstd450PackSnorm4x8 = 54,
|
||||||
|
GLSLstd450PackUnorm4x8 = 55,
|
||||||
|
GLSLstd450PackSnorm2x16 = 56,
|
||||||
|
GLSLstd450PackUnorm2x16 = 57,
|
||||||
|
GLSLstd450PackHalf2x16 = 58,
|
||||||
|
GLSLstd450PackDouble2x32 = 59,
|
||||||
|
GLSLstd450UnpackSnorm2x16 = 60,
|
||||||
|
GLSLstd450UnpackUnorm2x16 = 61,
|
||||||
|
GLSLstd450UnpackHalf2x16 = 62,
|
||||||
|
GLSLstd450UnpackSnorm4x8 = 63,
|
||||||
|
GLSLstd450UnpackUnorm4x8 = 64,
|
||||||
|
GLSLstd450UnpackDouble2x32 = 65,
|
||||||
|
|
||||||
|
GLSLstd450Length = 66,
|
||||||
|
GLSLstd450Distance = 67,
|
||||||
|
GLSLstd450Cross = 68,
|
||||||
|
GLSLstd450Normalize = 69,
|
||||||
|
GLSLstd450FaceForward = 70,
|
||||||
|
GLSLstd450Reflect = 71,
|
||||||
|
GLSLstd450Refract = 72,
|
||||||
|
|
||||||
|
GLSLstd450FindILsb = 73,
|
||||||
|
GLSLstd450FindSMsb = 74,
|
||||||
|
GLSLstd450FindUMsb = 75,
|
||||||
|
|
||||||
|
GLSLstd450InterpolateAtCentroid = 76,
|
||||||
|
GLSLstd450InterpolateAtSample = 77,
|
||||||
|
GLSLstd450InterpolateAtOffset = 78,
|
||||||
|
|
||||||
|
GLSLstd450NMin = 79,
|
||||||
|
GLSLstd450NMax = 80,
|
||||||
|
GLSLstd450NClamp = 81,
|
||||||
|
|
||||||
|
GLSLstd450Count
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #ifndef GLSLstd450_H
|
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
27
Makefile
Normal file
27
Makefile
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
TARGET := spir2cross
|
||||||
|
SOURCES := $(wildcard *.cpp)
|
||||||
|
OBJECTS := $(SOURCES:.cpp=.o)
|
||||||
|
DEPS := $(OBJECTS:.o=.d)
|
||||||
|
|
||||||
|
CXXFLAGS += -std=c++11 -Wall -Wextra
|
||||||
|
|
||||||
|
ifeq ($(DEBUG), 1)
|
||||||
|
CXXFLAGS += -O0 -gdwarf-2
|
||||||
|
else
|
||||||
|
CXXFLAGS += -O2 -gdwarf-2
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
-include $(DEPS)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJECTS)
|
||||||
|
$(CXX) -o $@ $(OBJECTS) $(LDFLAGS)
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CXX) -c -o $@ $< $(CXXFLAGS) -MMD
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET) $(OBJECTS)
|
||||||
|
|
||||||
|
.PHONY: clean
|
75
README.md
Normal file
75
README.md
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# SPIR2CROSS
|
||||||
|
|
||||||
|
SPIR2CROSS is a tool designed for parsing and converting SPIR-V to other shader languages.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Convert SPIR-V to readable, usable and efficient GLSL
|
||||||
|
- Convert SPIR-V to debuggable C++ [EXPERIMENTAL]
|
||||||
|
- Reflection API to simplify the creation of Vulkan pipeline layouts
|
||||||
|
- Reflection API to modify and tweak OpDecorations
|
||||||
|
- Supports "all" of vertex, fragment, tessellation, geometry and compute shaders.
|
||||||
|
|
||||||
|
SPIR2CROSS tries hard to emit readable and clean output from the SPIR-V.
|
||||||
|
The goal is to emit GLSL that looks like it was written by a human and not awkward IR/assembly-like code.
|
||||||
|
|
||||||
|
NOTE: Individual features are expected to be mostly complete, but it is possible that certain obscure GLSL features are not yet supported.
|
||||||
|
However, most missing features are expected to be "trivial" improvements at this stage.
|
||||||
|
|
||||||
|
Occasionally, missing features is due to glslangValidator's lack of proper support for that feature making testing hard.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
SPIR2CROSS has been tested on Linux, OSX and Windows.
|
||||||
|
|
||||||
|
### Linux and OSX
|
||||||
|
|
||||||
|
Just run `make` on the command line. A recent GCC (4.8+) or Clang (3.x+) compiler is required as SPIR2CROSS uses C++11 extensively.
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
MinGW-w64 based compilation works with `make`, and an MSVC 2013 solution is also included.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Creating a SPIR-V file from GLSL with glslang
|
||||||
|
|
||||||
|
```
|
||||||
|
glslangValidator -H -V -o test.spv test.frag
|
||||||
|
```
|
||||||
|
|
||||||
|
### Converting a SPIR-V file to GLSL ES
|
||||||
|
|
||||||
|
```
|
||||||
|
glslangValidator -H -V -o test.spv shaders/comp/basic.comp
|
||||||
|
./spir2cross --version 310 --es test.spv
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Converting to desktop GLSL
|
||||||
|
|
||||||
|
```
|
||||||
|
glslangValidator -H -V -o test.spv shaders/comp/basic.comp
|
||||||
|
./spir2cross --version 330 test.spv --output test.comp
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Disable prettifying optimizations
|
||||||
|
|
||||||
|
```
|
||||||
|
glslangValidator -H -V -o test.spv shaders/comp/basic.comp
|
||||||
|
./spir2cross --version 310 --es test.spv --output test.comp --force-temporary
|
||||||
|
```
|
||||||
|
|
||||||
|
## ABI concerns
|
||||||
|
|
||||||
|
### SPIR-V headers
|
||||||
|
|
||||||
|
The current repository uses the latest SPIR-V and GLSL.std.450 headers.
|
||||||
|
SPIR-V files created from older headers could have ABI issues.
|
||||||
|
|
||||||
|
## Regression testing
|
||||||
|
|
||||||
|
In shaders/ a collection of shaders are maintained for purposes of regression testing.
|
||||||
|
The current reference output is contained in reference/.
|
||||||
|
`./test_shaders.py shaders` can be run to perform regression testing.
|
||||||
|
Currently, the Mali Offline Compiler `malisc` is used to verify the outputs from SPIR2CROSS.
|
||||||
|
|
79
include/spir2cross/barrier.hpp
Normal file
79
include/spir2cross/barrier.hpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CROSS_BARRIER_HPP
|
||||||
|
#define SPIR2CROSS_BARRIER_HPP
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
class Barrier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Barrier()
|
||||||
|
{
|
||||||
|
count.store(0);
|
||||||
|
iteration.store(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_release_divisor(unsigned divisor)
|
||||||
|
{
|
||||||
|
this->divisor = divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void memoryBarrier()
|
||||||
|
{
|
||||||
|
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_counter()
|
||||||
|
{
|
||||||
|
count.store(0);
|
||||||
|
iteration.store(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
unsigned target_iteration = iteration.load(std::memory_order_relaxed) + 1;
|
||||||
|
// Overflows cleanly.
|
||||||
|
unsigned target_count = divisor * target_iteration;
|
||||||
|
|
||||||
|
// Barriers don't enforce memory ordering.
|
||||||
|
// Be as relaxed about the barrier as we possibly can!
|
||||||
|
unsigned c = count.fetch_add(1u, std::memory_order_relaxed);
|
||||||
|
|
||||||
|
if (c + 1 == target_count)
|
||||||
|
{
|
||||||
|
iteration.store(target_iteration, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If we have more threads than the CPU, don't hog the CPU for very long periods of time.
|
||||||
|
while (iteration.load(std::memory_order_relaxed) != target_iteration)
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned divisor = 1;
|
||||||
|
std::atomic<unsigned> count;
|
||||||
|
std::atomic<unsigned> iteration;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
137
include/spir2cross/external_interface.h
Normal file
137
include/spir2cross/external_interface.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CROSS_EXTERNAL_INTERFACE_H
|
||||||
|
#define SPIR2CROSS_EXTERNAL_INTERFACE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct spir2cross_shader spir2cross_shader_t;
|
||||||
|
|
||||||
|
struct spir2cross_interface
|
||||||
|
{
|
||||||
|
spir2cross_shader_t* (*construct)(void);
|
||||||
|
void (*destruct)(spir2cross_shader_t *thiz);
|
||||||
|
void (*invoke)(spir2cross_shader_t *thiz);
|
||||||
|
};
|
||||||
|
|
||||||
|
void spir2cross_set_stage_input(spir2cross_shader_t *thiz,
|
||||||
|
unsigned location, void *data, size_t size);
|
||||||
|
|
||||||
|
void spir2cross_set_stage_output(spir2cross_shader_t *thiz,
|
||||||
|
unsigned location, void *data, size_t size);
|
||||||
|
|
||||||
|
void spir2cross_set_push_constant(spir2cross_shader_t *thiz,
|
||||||
|
void *data, size_t size);
|
||||||
|
|
||||||
|
void spir2cross_set_uniform_constant(spir2cross_shader_t *thiz,
|
||||||
|
unsigned location,
|
||||||
|
void *data, size_t size);
|
||||||
|
|
||||||
|
void spir2cross_set_resource(spir2cross_shader_t *thiz,
|
||||||
|
unsigned set, unsigned binding,
|
||||||
|
void **data, size_t size);
|
||||||
|
|
||||||
|
const struct spir2cross_interface* spir2cross_get_interface(void);
|
||||||
|
|
||||||
|
typedef enum spir2cross_builtin
|
||||||
|
{
|
||||||
|
SPIR2CROSS_BUILTIN_POSITION = 0,
|
||||||
|
SPIR2CROSS_BUILTIN_FRAG_COORD = 1,
|
||||||
|
SPIR2CROSS_BUILTIN_WORK_GROUP_ID = 2,
|
||||||
|
SPIR2CROSS_BUILTIN_NUM_WORK_GROUPS = 3,
|
||||||
|
SPIR2CROSS_NUM_BUILTINS
|
||||||
|
} spir2cross_builtin;
|
||||||
|
|
||||||
|
void spir2cross_set_builtin(spir2cross_shader_t *thiz,
|
||||||
|
spir2cross_builtin builtin,
|
||||||
|
void *data, size_t size);
|
||||||
|
|
||||||
|
#define SPIR2CROSS_NUM_DESCRIPTOR_SETS 4
|
||||||
|
#define SPIR2CROSS_NUM_DESCRIPTOR_BINDINGS 16
|
||||||
|
#define SPIR2CROSS_NUM_STAGE_INPUTS 16
|
||||||
|
#define SPIR2CROSS_NUM_STAGE_OUTPUTS 16
|
||||||
|
#define SPIR2CROSS_NUM_UNIFORM_CONSTANTS 32
|
||||||
|
|
||||||
|
enum spir2cross_format
|
||||||
|
{
|
||||||
|
SPIR2CROSS_FORMAT_R8_UNORM = 0,
|
||||||
|
SPIR2CROSS_FORMAT_R8G8_UNORM = 1,
|
||||||
|
SPIR2CROSS_FORMAT_R8G8B8_UNORM = 2,
|
||||||
|
SPIR2CROSS_FORMAT_R8G8B8A8_UNORM = 3,
|
||||||
|
|
||||||
|
SPIR2CROSS_NUM_FORMATS
|
||||||
|
};
|
||||||
|
|
||||||
|
enum spir2cross_wrap
|
||||||
|
{
|
||||||
|
SPIR2CROSS_WRAP_CLAMP_TO_EDGE = 0,
|
||||||
|
SPIR2CROSS_WRAP_REPEAT = 1,
|
||||||
|
|
||||||
|
SPIR2CROSS_NUM_WRAP
|
||||||
|
};
|
||||||
|
|
||||||
|
enum spir2cross_filter
|
||||||
|
{
|
||||||
|
SPIR2CROSS_FILTER_NEAREST = 0,
|
||||||
|
SPIR2CROSS_FILTER_LINEAR = 1,
|
||||||
|
|
||||||
|
SPIR2CROSS_NUM_FILTER
|
||||||
|
};
|
||||||
|
|
||||||
|
enum spir2cross_mipfilter
|
||||||
|
{
|
||||||
|
SPIR2CROSS_MIPFILTER_BASE = 0,
|
||||||
|
SPIR2CROSS_MIPFILTER_NEAREST = 1,
|
||||||
|
SPIR2CROSS_MIPFILTER_LINEAR = 2,
|
||||||
|
|
||||||
|
SPIR2CROSS_NUM_MIPFILTER
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spir2cross_miplevel
|
||||||
|
{
|
||||||
|
const void *data;
|
||||||
|
unsigned width, height;
|
||||||
|
size_t stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spir2cross_sampler_info
|
||||||
|
{
|
||||||
|
const struct spir2cross_miplevel *mipmaps;
|
||||||
|
unsigned num_mipmaps;
|
||||||
|
|
||||||
|
enum spir2cross_format format;
|
||||||
|
enum spir2cross_wrap wrap_s;
|
||||||
|
enum spir2cross_wrap wrap_t;
|
||||||
|
enum spir2cross_filter min_filter;
|
||||||
|
enum spir2cross_filter mag_filter;
|
||||||
|
enum spir2cross_mipfilter mip_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct spir2cross_sampler_2d spir2cross_sampler_2d_t;
|
||||||
|
spir2cross_sampler_2d_t *spir2cross_create_sampler_2d(const struct spir2cross_sampler_info *info);
|
||||||
|
void spir2cross_destroy_sampler_2d(spir2cross_sampler_2d_t *samp);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
45
include/spir2cross/image.hpp
Normal file
45
include/spir2cross/image.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CROSS_IMAGE_HPP
|
||||||
|
#define SPIR2CROSS_IMAGE_HPP
|
||||||
|
|
||||||
|
#ifndef GLM_SWIZZLE
|
||||||
|
#define GLM_SWIZZLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLM_FORCE_RADIANS
|
||||||
|
#define GLM_FORCE_RADIANS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct image2DBase
|
||||||
|
{
|
||||||
|
virtual ~image2DBase() = default;
|
||||||
|
inline virtual T load(glm::ivec2 coord) { return T(0, 0, 0, 1); }
|
||||||
|
inline virtual void store(glm::ivec2 coord, const T &v) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef image2DBase<glm::vec4> image2D;
|
||||||
|
typedef image2DBase<glm::ivec4> iimage2D;
|
||||||
|
typedef image2DBase<glm::uvec4> uimage2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
531
include/spir2cross/internal_interface.hpp
Normal file
531
include/spir2cross/internal_interface.hpp
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CROSS_INTERNAL_INTERFACE_HPP
|
||||||
|
#define SPIR2CROSS_INTERNAL_INTERFACE_HPP
|
||||||
|
|
||||||
|
// This file must only be included by the shader generated by spir2cross!
|
||||||
|
|
||||||
|
#ifndef GLM_SWIZZLE
|
||||||
|
#define GLM_SWIZZLE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLM_FORCE_RADIANS
|
||||||
|
#define GLM_FORCE_RADIANS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "external_interface.h"
|
||||||
|
#include "barrier.hpp"
|
||||||
|
#include "thread_group.hpp"
|
||||||
|
#include "sampler.hpp"
|
||||||
|
#include "image.hpp"
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
// Adaptor helpers to adapt GLSL access chain syntax to C++.
|
||||||
|
// Don't bother with arrays of arrays on uniforms ...
|
||||||
|
// Would likely need horribly complex variadic template munging.
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct Interface
|
||||||
|
{
|
||||||
|
enum { ArraySize = 1, Size = sizeof(T) };
|
||||||
|
|
||||||
|
Interface() : ptr(0) {}
|
||||||
|
T& get()
|
||||||
|
{
|
||||||
|
assert(ptr);
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// For array types, return a pointer instead.
|
||||||
|
template<typename T, unsigned U>
|
||||||
|
struct Interface<T[U]>
|
||||||
|
{
|
||||||
|
enum { ArraySize = U, Size = U * sizeof(T) };
|
||||||
|
|
||||||
|
Interface() : ptr(0) {}
|
||||||
|
T* get()
|
||||||
|
{
|
||||||
|
assert(ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// For case when array size is 1, avoid double dereference.
|
||||||
|
template<typename T>
|
||||||
|
struct PointerInterface
|
||||||
|
{
|
||||||
|
enum { ArraySize = 1, Size = sizeof(T*) };
|
||||||
|
enum { PreDereference = true };
|
||||||
|
|
||||||
|
PointerInterface() : ptr(0) {}
|
||||||
|
|
||||||
|
T& get()
|
||||||
|
{
|
||||||
|
assert(ptr);
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Automatically converts a pointer down to reference to match GLSL syntax.
|
||||||
|
template<typename T>
|
||||||
|
struct DereferenceAdaptor
|
||||||
|
{
|
||||||
|
DereferenceAdaptor(T **ptr) : ptr(ptr) {}
|
||||||
|
T& operator[](unsigned index) const { return *(ptr[index]); }
|
||||||
|
T **ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// We can't have a linear array of T* since T* can be an abstract type in case of samplers.
|
||||||
|
// We also need a list of pointers since we can have run-time length SSBOs.
|
||||||
|
template<typename T, unsigned U>
|
||||||
|
struct PointerInterface<T[U]>
|
||||||
|
{
|
||||||
|
enum { ArraySize = U, Size = sizeof(T*) * U };
|
||||||
|
enum { PreDereference = false };
|
||||||
|
PointerInterface() : ptr(0) {}
|
||||||
|
|
||||||
|
DereferenceAdaptor<T> get()
|
||||||
|
{
|
||||||
|
assert(ptr);
|
||||||
|
return DereferenceAdaptor<T>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
T **ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Resources can be more abstract and be unsized,
|
||||||
|
// so we need to have an array of pointers for those cases.
|
||||||
|
template<typename T> struct Resource : PointerInterface<T> {};
|
||||||
|
|
||||||
|
// POD with no unknown sizes, so we can express these as flat arrays.
|
||||||
|
template<typename T> struct UniformConstant : Interface<T> {};
|
||||||
|
template<typename T> struct StageInput : Interface<T> {};
|
||||||
|
template<typename T> struct StageOutput : Interface<T> {};
|
||||||
|
template<typename T> struct PushConstant : Interface<T> {};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spir2cross_shader
|
||||||
|
{
|
||||||
|
struct PPSize
|
||||||
|
{
|
||||||
|
PPSize() : ptr(0), size(0) {}
|
||||||
|
void **ptr;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PPSizeResource
|
||||||
|
{
|
||||||
|
PPSizeResource() : ptr(0), size(0), pre_dereference(false) {}
|
||||||
|
void **ptr;
|
||||||
|
size_t size;
|
||||||
|
bool pre_dereference;
|
||||||
|
};
|
||||||
|
|
||||||
|
PPSizeResource resources[SPIR2CROSS_NUM_DESCRIPTOR_SETS][SPIR2CROSS_NUM_DESCRIPTOR_BINDINGS];
|
||||||
|
PPSize stage_inputs[SPIR2CROSS_NUM_STAGE_INPUTS];
|
||||||
|
PPSize stage_outputs[SPIR2CROSS_NUM_STAGE_OUTPUTS];
|
||||||
|
PPSize uniform_constants[SPIR2CROSS_NUM_UNIFORM_CONSTANTS];
|
||||||
|
PPSize push_constant;
|
||||||
|
PPSize builtins[SPIR2CROSS_NUM_BUILTINS];
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
void register_builtin(spir2cross_builtin builtin, const U& value)
|
||||||
|
{
|
||||||
|
assert(!builtins[builtin].ptr);
|
||||||
|
|
||||||
|
builtins[builtin].ptr = (void**)&value.ptr;
|
||||||
|
builtins[builtin].size = sizeof(*value.ptr) * U::ArraySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_builtin(spir2cross_builtin builtin, void *data, size_t size)
|
||||||
|
{
|
||||||
|
assert(builtins[builtin].ptr);
|
||||||
|
assert(size >= builtins[builtin].size);
|
||||||
|
|
||||||
|
*builtins[builtin].ptr = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
void register_resource(const internal::Resource<U> &value, unsigned set, unsigned binding)
|
||||||
|
{
|
||||||
|
assert(set < SPIR2CROSS_NUM_DESCRIPTOR_SETS);
|
||||||
|
assert(binding < SPIR2CROSS_NUM_DESCRIPTOR_BINDINGS);
|
||||||
|
assert(!resources[set][binding].ptr);
|
||||||
|
|
||||||
|
resources[set][binding].ptr = (void**)&value.ptr;
|
||||||
|
resources[set][binding].size = internal::Resource<U>::Size;
|
||||||
|
resources[set][binding].pre_dereference = internal::Resource<U>::PreDereference;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
void register_stage_input(const internal::StageInput<U> &value, unsigned location)
|
||||||
|
{
|
||||||
|
assert(location < SPIR2CROSS_NUM_STAGE_INPUTS);
|
||||||
|
assert(!stage_inputs[location].ptr);
|
||||||
|
|
||||||
|
stage_inputs[location].ptr = (void**)&value.ptr;
|
||||||
|
stage_inputs[location].size = internal::StageInput<U>::Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
void register_stage_output(const internal::StageOutput<U> &value, unsigned location)
|
||||||
|
{
|
||||||
|
assert(location < SPIR2CROSS_NUM_STAGE_OUTPUTS);
|
||||||
|
assert(!stage_outputs[location].ptr);
|
||||||
|
|
||||||
|
stage_outputs[location].ptr = (void**)&value.ptr;
|
||||||
|
stage_outputs[location].size = internal::StageOutput<U>::Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
void register_uniform_constant(const internal::UniformConstant<U> &value, unsigned location)
|
||||||
|
{
|
||||||
|
assert(location < SPIR2CROSS_NUM_UNIFORM_CONSTANTS);
|
||||||
|
assert(!uniform_constants[location].ptr);
|
||||||
|
|
||||||
|
uniform_constants[location].ptr = (void**)&value.ptr;
|
||||||
|
uniform_constants[location].size = internal::UniformConstant<U>::Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
void register_push_constant(const internal::PushConstant<U> &value)
|
||||||
|
{
|
||||||
|
assert(!push_constant.ptr);
|
||||||
|
|
||||||
|
push_constant.ptr = (void**)&value.ptr;
|
||||||
|
push_constant.size = internal::PushConstant<U>::Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_stage_input(unsigned location, void *data, size_t size)
|
||||||
|
{
|
||||||
|
assert(location < SPIR2CROSS_NUM_STAGE_INPUTS);
|
||||||
|
assert(stage_inputs[location].ptr);
|
||||||
|
assert(size >= stage_inputs[location].size);
|
||||||
|
|
||||||
|
*stage_inputs[location].ptr = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_stage_output(unsigned location, void *data, size_t size)
|
||||||
|
{
|
||||||
|
assert(location < SPIR2CROSS_NUM_STAGE_OUTPUTS);
|
||||||
|
assert(stage_outputs[location].ptr);
|
||||||
|
assert(size >= stage_outputs[location].size);
|
||||||
|
|
||||||
|
*stage_outputs[location].ptr = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_uniform_constant(unsigned location, void *data, size_t size)
|
||||||
|
{
|
||||||
|
assert(location < SPIR2CROSS_NUM_UNIFORM_CONSTANTS);
|
||||||
|
assert(uniform_constants[location].ptr);
|
||||||
|
assert(size >= uniform_constants[location].size);
|
||||||
|
|
||||||
|
*uniform_constants[location].ptr = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_push_constant(void *data, size_t size)
|
||||||
|
{
|
||||||
|
assert(push_constant.ptr);
|
||||||
|
assert(size >= push_constant.size);
|
||||||
|
|
||||||
|
*push_constant.ptr = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_resource(unsigned set, unsigned binding,
|
||||||
|
void **data, size_t size)
|
||||||
|
{
|
||||||
|
assert(set < SPIR2CROSS_NUM_DESCRIPTOR_SETS);
|
||||||
|
assert(binding < SPIR2CROSS_NUM_DESCRIPTOR_BINDINGS);
|
||||||
|
assert(resources[set][binding].ptr);
|
||||||
|
assert(size >= resources[set][binding].size);
|
||||||
|
|
||||||
|
// We're using the regular PointerInterface, dereference ahead of time.
|
||||||
|
if (resources[set][binding].pre_dereference)
|
||||||
|
*resources[set][binding].ptr = *data;
|
||||||
|
else
|
||||||
|
*resources[set][binding].ptr = data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct BaseShader : spir2cross_shader
|
||||||
|
{
|
||||||
|
void invoke()
|
||||||
|
{
|
||||||
|
static_cast<T*>(this)->main();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FragmentResources
|
||||||
|
{
|
||||||
|
internal::StageOutput<glm::vec4> gl_FragCoord;
|
||||||
|
void init(spir2cross_shader &s)
|
||||||
|
{
|
||||||
|
s.register_builtin(SPIR2CROSS_BUILTIN_FRAG_COORD, gl_FragCoord);
|
||||||
|
}
|
||||||
|
#define gl_FragCoord __res->gl_FragCoord.get()
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Res>
|
||||||
|
struct FragmentShader : BaseShader<FragmentShader<T, Res> >
|
||||||
|
{
|
||||||
|
inline void main()
|
||||||
|
{
|
||||||
|
impl.main();
|
||||||
|
}
|
||||||
|
|
||||||
|
FragmentShader()
|
||||||
|
{
|
||||||
|
resources.init(*this);
|
||||||
|
impl.__res = &resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
T impl;
|
||||||
|
Res resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexResources
|
||||||
|
{
|
||||||
|
internal::StageOutput<glm::vec4> gl_Position;
|
||||||
|
void init(spir2cross_shader &s)
|
||||||
|
{
|
||||||
|
s.register_builtin(SPIR2CROSS_BUILTIN_POSITION, gl_Position);
|
||||||
|
}
|
||||||
|
#define gl_Position __res->gl_Position.get()
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Res>
|
||||||
|
struct VertexShader : BaseShader<VertexShader<T, Res> >
|
||||||
|
{
|
||||||
|
inline void main()
|
||||||
|
{
|
||||||
|
impl.main();
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexShader()
|
||||||
|
{
|
||||||
|
resources.init(*this);
|
||||||
|
impl.__res = &resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
T impl;
|
||||||
|
Res resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TessEvaluationResources
|
||||||
|
{
|
||||||
|
inline void init(spir2cross_shader&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Res>
|
||||||
|
struct TessEvaluationShader : BaseShader<TessEvaluationShader<T, Res> >
|
||||||
|
{
|
||||||
|
inline void main()
|
||||||
|
{
|
||||||
|
impl.main();
|
||||||
|
}
|
||||||
|
|
||||||
|
TessEvaluationShader()
|
||||||
|
{
|
||||||
|
resources.init(*this);
|
||||||
|
impl.__res = &resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
T impl;
|
||||||
|
Res resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TessControlResources
|
||||||
|
{
|
||||||
|
inline void init(spir2cross_shader&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Res>
|
||||||
|
struct TessControlShader : BaseShader<TessControlShader<T, Res> >
|
||||||
|
{
|
||||||
|
inline void main()
|
||||||
|
{
|
||||||
|
impl.main();
|
||||||
|
}
|
||||||
|
|
||||||
|
TessControlShader()
|
||||||
|
{
|
||||||
|
resources.init(*this);
|
||||||
|
impl.__res = &resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
T impl;
|
||||||
|
Res resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GeometryResources
|
||||||
|
{
|
||||||
|
inline void init(spir2cross_shader&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Res>
|
||||||
|
struct GeometryShader : BaseShader<GeometryShader<T, Res> >
|
||||||
|
{
|
||||||
|
inline void main()
|
||||||
|
{
|
||||||
|
impl.main();
|
||||||
|
}
|
||||||
|
|
||||||
|
GeometryShader()
|
||||||
|
{
|
||||||
|
resources.init(*this);
|
||||||
|
impl.__res = &resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
T impl;
|
||||||
|
Res resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ComputeResources
|
||||||
|
{
|
||||||
|
internal::StageInput<glm::uvec3> gl_WorkGroupID__;
|
||||||
|
internal::StageInput<glm::uvec3> gl_NumWorkGroups__;
|
||||||
|
void init(spir2cross_shader &s)
|
||||||
|
{
|
||||||
|
s.register_builtin(SPIR2CROSS_BUILTIN_WORK_GROUP_ID, gl_WorkGroupID__);
|
||||||
|
s.register_builtin(SPIR2CROSS_BUILTIN_NUM_WORK_GROUPS, gl_NumWorkGroups__);
|
||||||
|
}
|
||||||
|
#define gl_WorkGroupID __res->gl_WorkGroupID__.get()
|
||||||
|
#define gl_NumWorkGroups __res->gl_NumWorkGroups.get()
|
||||||
|
|
||||||
|
Barrier barrier__;
|
||||||
|
#define barrier() __res->barrier__.wait()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ComputePrivateResources
|
||||||
|
{
|
||||||
|
uint32_t gl_LocalInvocationIndex__;
|
||||||
|
#define gl_LocalInvocationIndex __priv_res.gl_LocalInvocationIndex__
|
||||||
|
glm::uvec3 gl_LocalInvocationID__;
|
||||||
|
#define gl_LocalInvocationID __priv_res.gl_LocalInvocationID__
|
||||||
|
glm::uvec3 gl_GlobalInvocationID__;
|
||||||
|
#define gl_GlobalInvocationID __priv_res.gl_GlobalInvocationID__
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Res, unsigned WorkGroupX, unsigned WorkGroupY, unsigned WorkGroupZ>
|
||||||
|
struct ComputeShader : BaseShader<ComputeShader<T, Res, WorkGroupX, WorkGroupY, WorkGroupZ> >
|
||||||
|
{
|
||||||
|
inline void main()
|
||||||
|
{
|
||||||
|
resources.barrier__.reset_counter();
|
||||||
|
|
||||||
|
for (unsigned z = 0; z < WorkGroupZ; z++)
|
||||||
|
for (unsigned y = 0; y < WorkGroupY; y++)
|
||||||
|
for (unsigned x = 0; x < WorkGroupX; x++)
|
||||||
|
impl[z][y][x].__priv_res.gl_GlobalInvocationID__ =
|
||||||
|
glm::uvec3(WorkGroupX, WorkGroupY, WorkGroupZ) * resources.gl_WorkGroupID__.get() +
|
||||||
|
glm::uvec3(x, y, z);
|
||||||
|
|
||||||
|
group.run();
|
||||||
|
group.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComputeShader()
|
||||||
|
: group(&impl[0][0][0])
|
||||||
|
{
|
||||||
|
resources.init(*this);
|
||||||
|
resources.barrier__.set_release_divisor(WorkGroupX * WorkGroupY * WorkGroupZ);
|
||||||
|
|
||||||
|
unsigned i = 0;
|
||||||
|
for (unsigned z = 0; z < WorkGroupZ; z++)
|
||||||
|
{
|
||||||
|
for (unsigned y = 0; y < WorkGroupY; y++)
|
||||||
|
{
|
||||||
|
for (unsigned x = 0; x < WorkGroupX; x++)
|
||||||
|
{
|
||||||
|
impl[z][y][x].__priv_res.gl_LocalInvocationID__ =
|
||||||
|
glm::uvec3(x, y, z);
|
||||||
|
impl[z][y][x].__priv_res.gl_LocalInvocationIndex__ = i++;
|
||||||
|
impl[z][y][x].__res = &resources;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T impl[WorkGroupZ][WorkGroupY][WorkGroupX];
|
||||||
|
ThreadGroup<T, WorkGroupX * WorkGroupY * WorkGroupZ> group;
|
||||||
|
Res resources;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void memoryBarrierShared() { Barrier::memoryBarrier(); }
|
||||||
|
inline void memoryBarrier() { Barrier::memoryBarrier(); }
|
||||||
|
// TODO: Rest of the barriers.
|
||||||
|
|
||||||
|
// Atomics
|
||||||
|
template<typename T>
|
||||||
|
inline T atomicAdd(T &v, T a)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(std::atomic<T>) == sizeof(T), "Cannot cast properly to std::atomic<T>.");
|
||||||
|
|
||||||
|
// We need explicit memory barriers in GLSL to enfore any ordering.
|
||||||
|
// FIXME: Can we really cast this? There is no other way I think ...
|
||||||
|
return std::atomic_fetch_add_explicit(reinterpret_cast<std::atomic<T>*>(&v),
|
||||||
|
a, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spir2cross_set_stage_input(spir2cross_shader_t *shader, unsigned location, void *data, size_t size)
|
||||||
|
{
|
||||||
|
shader->set_stage_input(location, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spir2cross_set_stage_output(spir2cross_shader_t *shader, unsigned location, void *data, size_t size)
|
||||||
|
{
|
||||||
|
shader->set_stage_output(location, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spir2cross_set_uniform_constant(spir2cross_shader_t *shader, unsigned location, void *data, size_t size)
|
||||||
|
{
|
||||||
|
shader->set_uniform_constant(location, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spir2cross_set_resource(spir2cross_shader_t *shader, unsigned set, unsigned binding, void **data, size_t size)
|
||||||
|
{
|
||||||
|
shader->set_resource(set, binding, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spir2cross_set_push_constant(spir2cross_shader_t *shader, void *data, size_t size)
|
||||||
|
{
|
||||||
|
shader->set_push_constant(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spir2cross_set_builtin(spir2cross_shader_t *shader, spir2cross_builtin builtin,
|
||||||
|
void *data, size_t size)
|
||||||
|
{
|
||||||
|
shader->set_builtin(builtin, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
101
include/spir2cross/sampler.hpp
Normal file
101
include/spir2cross/sampler.hpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CROSS_SAMPLER_HPP
|
||||||
|
#define SPIR2CROSS_SAMPLER_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
struct spir2cross_sampler_2d
|
||||||
|
{
|
||||||
|
inline virtual ~spir2cross_sampler_2d() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct sampler2DBase : spir2cross_sampler_2d
|
||||||
|
{
|
||||||
|
sampler2DBase(const spir2cross_sampler_info *info)
|
||||||
|
{
|
||||||
|
mips.insert(mips.end(), info->mipmaps, info->mipmaps + info->num_mipmaps);
|
||||||
|
format = info->format;
|
||||||
|
wrap_s = info->wrap_s;
|
||||||
|
wrap_t = info->wrap_t;
|
||||||
|
min_filter = info->min_filter;
|
||||||
|
mag_filter = info->mag_filter;
|
||||||
|
mip_filter = info->mip_filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline virtual T sample(glm::vec2 uv, float bias)
|
||||||
|
{
|
||||||
|
return sampleLod(uv, bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline virtual T sampleLod(glm::vec2 uv, float lod)
|
||||||
|
{
|
||||||
|
if (mag_filter == SPIR2CROSS_FILTER_NEAREST)
|
||||||
|
{
|
||||||
|
uv.x = wrap(uv.x, wrap_s, mips[0].width);
|
||||||
|
uv.y = wrap(uv.y, wrap_t, mips[0].height);
|
||||||
|
glm::vec2 uv_full = uv * glm::vec2(mips[0].width, mips[0].height);
|
||||||
|
|
||||||
|
int x = int(uv_full.x);
|
||||||
|
int y = int(uv_full.y);
|
||||||
|
return sample(x, y, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return T(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float wrap(float v, spir2cross_wrap wrap, unsigned size)
|
||||||
|
{
|
||||||
|
switch (wrap)
|
||||||
|
{
|
||||||
|
case SPIR2CROSS_WRAP_REPEAT:
|
||||||
|
return v - glm::floor(v);
|
||||||
|
case SPIR2CROSS_WRAP_CLAMP_TO_EDGE:
|
||||||
|
{
|
||||||
|
float half = 0.5f / size;
|
||||||
|
return glm::clamp(v, half, 1.0f - half);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<spir2cross_miplevel> mips;
|
||||||
|
spir2cross_format format;
|
||||||
|
spir2cross_wrap wrap_s;
|
||||||
|
spir2cross_format wrap_t;
|
||||||
|
spir2cross_filter min_filter;
|
||||||
|
spir2cross_filter mag_filter;
|
||||||
|
spir2cross_mipfilter mip_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef sampler2DBase<glm::vec4> sampler2D;
|
||||||
|
typedef sampler2DBase<glm::ivec4> isampler2D;
|
||||||
|
typedef sampler2DBase<glm::uvec4> usampler2D;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline T texture(const sampler2DBase<T> &samp, const glm::vec2 &uv, float bias = 0.0f) { return samp.sample(uv, bias); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
113
include/spir2cross/thread_group.hpp
Normal file
113
include/spir2cross/thread_group.hpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CROSS_THREAD_GROUP_HPP
|
||||||
|
#define SPIR2CROSS_THREAD_GROUP_HPP
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
template<typename T, unsigned Size>
|
||||||
|
class ThreadGroup
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadGroup(T *impl)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < Size; i++)
|
||||||
|
workers[i].start(&impl[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
for (auto &worker : workers)
|
||||||
|
worker.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
for (auto &worker : workers)
|
||||||
|
worker.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Thread
|
||||||
|
{
|
||||||
|
enum State
|
||||||
|
{
|
||||||
|
Idle,
|
||||||
|
Running,
|
||||||
|
Dying
|
||||||
|
};
|
||||||
|
State state = Idle;
|
||||||
|
|
||||||
|
void start(T *impl)
|
||||||
|
{
|
||||||
|
worker = std::thread([impl, this] {
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l{lock};
|
||||||
|
cond.wait(l, [this] { return state != Idle; });
|
||||||
|
if (state == Dying)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl->main();
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> l{lock};
|
||||||
|
state = Idle;
|
||||||
|
cond.notify_one();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> l{lock};
|
||||||
|
cond.wait(l, [this] { return state == Idle; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> l{lock};
|
||||||
|
state = Running;
|
||||||
|
cond.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
~Thread()
|
||||||
|
{
|
||||||
|
if (worker.joinable())
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> l{lock};
|
||||||
|
state = Dying;
|
||||||
|
cond.notify_one();
|
||||||
|
}
|
||||||
|
worker.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::thread worker;
|
||||||
|
std::condition_variable cond;
|
||||||
|
std::mutex lock;
|
||||||
|
};
|
||||||
|
Thread workers[Size];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
11
jni/Android.mk
Normal file
11
jni/Android.mk
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_CFLAGS += -std=c++11 -Wall -Wextra
|
||||||
|
LOCAL_MODULE := spir2cross
|
||||||
|
LOCAL_SRC_FILES := ../spir2cross.cpp ../spir2glsl.cpp ../spir2cpp.cpp
|
||||||
|
LOCAL_CPP_FEATURES := exceptions
|
||||||
|
LOCAL_ARM_MODE := arm
|
||||||
|
|
||||||
|
include $(BUILD_STATIC_LIBRARY)
|
2
jni/Application.mk
Normal file
2
jni/Application.mk
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
APP_STL := c++_static
|
||||||
|
APP_ABI := armeabi-v7a
|
425
main.cpp
Normal file
425
main.cpp
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "spir2cpp.hpp"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <functional>
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <cstring>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
using namespace spv;
|
||||||
|
using namespace spir2cross;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct CLIParser;
|
||||||
|
struct CLICallbacks
|
||||||
|
{
|
||||||
|
void add(const char *cli, const function<void (CLIParser&)> &func)
|
||||||
|
{
|
||||||
|
callbacks[cli] = func;
|
||||||
|
}
|
||||||
|
unordered_map<string, function<void (CLIParser&)>> callbacks;
|
||||||
|
function<void ()> error_handler;
|
||||||
|
function<void (const char*)> default_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CLIParser
|
||||||
|
{
|
||||||
|
CLIParser(CLICallbacks cbs, int argc, char *argv[])
|
||||||
|
: cbs(move(cbs)), argc(argc), argv(argv)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool parse()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (argc && !ended_state)
|
||||||
|
{
|
||||||
|
const char *next = *argv++;
|
||||||
|
argc--;
|
||||||
|
|
||||||
|
if (*next != '-' && cbs.default_handler)
|
||||||
|
{
|
||||||
|
cbs.default_handler(next);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto itr = cbs.callbacks.find(next);
|
||||||
|
if (itr == ::end(cbs.callbacks))
|
||||||
|
{
|
||||||
|
throw logic_error("Invalid argument.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
itr->second(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
if (cbs.error_handler)
|
||||||
|
{
|
||||||
|
cbs.error_handler();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void end()
|
||||||
|
{
|
||||||
|
ended_state = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t next_uint()
|
||||||
|
{
|
||||||
|
if (!argc)
|
||||||
|
{
|
||||||
|
throw logic_error("Tried to parse uint, but nothing left in arguments.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t val = stoul(*argv);
|
||||||
|
if (val > numeric_limits<uint32_t>::max())
|
||||||
|
{
|
||||||
|
throw out_of_range("next_uint() out of range.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
double next_double()
|
||||||
|
{
|
||||||
|
if (!argc)
|
||||||
|
{
|
||||||
|
throw logic_error("Tried to parse double, but nothing left in arguments.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
double val = stod(*argv);
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *next_string()
|
||||||
|
{
|
||||||
|
if (!argc)
|
||||||
|
{
|
||||||
|
throw logic_error("Tried to parse string, but nothing left in arguments.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ret = *argv;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLICallbacks cbs;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
bool ended_state = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static vector<uint32_t> read_spirv_file(const char *path)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(path, "rb");
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to open SPIRV file: %s\n", path);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
long len = ftell(file) / sizeof(uint32_t);
|
||||||
|
rewind(file);
|
||||||
|
|
||||||
|
vector<uint32_t> spirv(len);
|
||||||
|
if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len))
|
||||||
|
spirv.clear();
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
return spirv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool write_string_to_file(const char *path, const char *string)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(path, "w");
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
fprintf(file, "Failed to write file: %s\n", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(file, "%s", string);
|
||||||
|
fclose(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_resources(const Compiler &compiler, const char *tag, const vector<Resource> &resources)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", tag);
|
||||||
|
fprintf(stderr, "=============\n\n");
|
||||||
|
for (auto &res : resources)
|
||||||
|
{
|
||||||
|
auto &type = compiler.get_type(res.type_id);
|
||||||
|
auto mask = compiler.get_decoration_mask(res.id);
|
||||||
|
|
||||||
|
// If we don't have a name, use the fallback for the type instead of the variable
|
||||||
|
// for SSBOs and UBOs since those are the only meaningful names to use externally.
|
||||||
|
// Push constant blocks are still accessed by name and not block name, even though they are technically Blocks.
|
||||||
|
bool is_push_constant = compiler.get_storage_class(res.id) == StorageClassPushConstant;
|
||||||
|
bool is_block = (compiler.get_decoration_mask(type.self) &
|
||||||
|
((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) != 0;
|
||||||
|
uint32_t fallback_id = !is_push_constant && is_block ? res.type_id : res.id;
|
||||||
|
|
||||||
|
fprintf(stderr, " ID %03u : %s", res.id,
|
||||||
|
!res.name.empty() ? res.name.c_str() : compiler.get_fallback_name(fallback_id).c_str());
|
||||||
|
|
||||||
|
if (mask & (1ull << DecorationLocation))
|
||||||
|
fprintf(stderr, " (Location : %u)", compiler.get_decoration(res.id, DecorationLocation));
|
||||||
|
if (mask & (1ull << DecorationDescriptorSet))
|
||||||
|
fprintf(stderr, " (Set : %u)", compiler.get_decoration(res.id, DecorationDescriptorSet));
|
||||||
|
if (mask & (1ull << DecorationBinding))
|
||||||
|
fprintf(stderr, " (Binding : %u)", compiler.get_decoration(res.id, DecorationBinding));
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
fprintf(stderr, "=============\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_resources(const Compiler &compiler, const ShaderResources &res)
|
||||||
|
{
|
||||||
|
print_resources(compiler, "subpass inputs", res.subpass_inputs);
|
||||||
|
print_resources(compiler, "inputs", res.stage_inputs);
|
||||||
|
print_resources(compiler, "outputs", res.stage_outputs);
|
||||||
|
print_resources(compiler, "textures", res.sampled_images);
|
||||||
|
print_resources(compiler, "images", res.storage_images);
|
||||||
|
print_resources(compiler, "ssbos", res.storage_buffers);
|
||||||
|
print_resources(compiler, "ubos", res.uniform_buffers);
|
||||||
|
print_resources(compiler, "push", res.push_constant_buffers);
|
||||||
|
print_resources(compiler, "counters", res.atomic_counters);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_push_constant_resources(const Compiler &compiler, const vector<Resource> &res)
|
||||||
|
{
|
||||||
|
for (auto &block : res)
|
||||||
|
{
|
||||||
|
auto ranges = compiler.get_active_buffer_ranges(block.id);
|
||||||
|
fprintf(stderr, "Active members in buffer: %s\n",
|
||||||
|
!block.name.empty() ? block.name.c_str() : compiler.get_fallback_name(block.id).c_str());
|
||||||
|
|
||||||
|
fprintf(stderr, "==================\n\n");
|
||||||
|
for (auto &range : ranges)
|
||||||
|
{
|
||||||
|
const auto &name = compiler.get_member_name(block.type_id, range.index);
|
||||||
|
|
||||||
|
fprintf(stderr, "Member #%3u (%s): Offset: %4u, Range: %4u\n",
|
||||||
|
range.index, !name.empty() ? name.c_str() : compiler.get_fallback_member_name(range.index).c_str(),
|
||||||
|
unsigned(range.offset), unsigned(range.range));
|
||||||
|
}
|
||||||
|
fprintf(stderr, "==================\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PLSArg
|
||||||
|
{
|
||||||
|
PlsFormat format;
|
||||||
|
string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CLIArguments
|
||||||
|
{
|
||||||
|
const char *input = nullptr;
|
||||||
|
const char *output = nullptr;
|
||||||
|
uint32_t version = 0;
|
||||||
|
bool es = false;
|
||||||
|
bool set_version = false;
|
||||||
|
bool set_es = false;
|
||||||
|
bool dump_resources = false;
|
||||||
|
bool force_temporary = false;
|
||||||
|
bool flatten_ubo = false;
|
||||||
|
bool fixup = false;
|
||||||
|
vector<PLSArg> pls_in;
|
||||||
|
vector<PLSArg> pls_out;
|
||||||
|
|
||||||
|
uint32_t iterations = 1;
|
||||||
|
bool cpp = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void print_help()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: spir2cross [--output <output path>] [SPIR-V file] [--es] [--no-es] [--version <GLSL version>] [--dump-resources] [--help] [--force-temporary] [-cpp] [--flatten-ubo] [--fixup-clipspace] [--iterations iter] [--pls-in format input-name] [--pls-out format output-name]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<PlsRemap> remap_pls(const vector<PLSArg> &pls_variables, const vector<Resource> &resources, const vector<Resource> *secondary_resources)
|
||||||
|
{
|
||||||
|
vector<PlsRemap> ret;
|
||||||
|
|
||||||
|
for (auto &pls : pls_variables)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (auto &res : resources)
|
||||||
|
{
|
||||||
|
if (res.name == pls.name)
|
||||||
|
{
|
||||||
|
ret.push_back({ res.id, pls.format });
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found && secondary_resources)
|
||||||
|
{
|
||||||
|
for (auto &res : *secondary_resources)
|
||||||
|
{
|
||||||
|
if (res.name == pls.name)
|
||||||
|
{
|
||||||
|
ret.push_back({ res.id, pls.format });
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
fprintf(stderr, "Did not find stage input/output/target with name \"%s\".\n",
|
||||||
|
pls.name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PlsFormat pls_format(const char *str)
|
||||||
|
{
|
||||||
|
if (!strcmp(str, "r11f_g11f_b10f")) return PlsR11FG11FB10F;
|
||||||
|
else if (!strcmp(str, "r32f")) return PlsR32F;
|
||||||
|
else if (!strcmp(str, "rg16f")) return PlsRG16F;
|
||||||
|
else if (!strcmp(str, "rg16")) return PlsRG16;
|
||||||
|
else if (!strcmp(str, "rgb10_a2")) return PlsRGB10A2;
|
||||||
|
else if (!strcmp(str, "rgba8")) return PlsRGBA8;
|
||||||
|
else if (!strcmp(str, "rgba8i")) return PlsRGBA8I;
|
||||||
|
else if (!strcmp(str, "rgba8ui")) return PlsRGBA8UI;
|
||||||
|
else if (!strcmp(str, "rg16i")) return PlsRG16I;
|
||||||
|
else if (!strcmp(str, "rgb10_a2ui")) return PlsRGB10A2UI;
|
||||||
|
else if (!strcmp(str, "rg16ui")) return PlsRG16UI;
|
||||||
|
else if (!strcmp(str, "r32ui")) return PlsR32UI;
|
||||||
|
else return PlsNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
CLIArguments args;
|
||||||
|
CLICallbacks cbs;
|
||||||
|
|
||||||
|
cbs.add("--help", [](CLIParser &parser) { print_help(); parser.end(); });
|
||||||
|
cbs.add("--output", [&args](CLIParser &parser) { args.output = parser.next_string(); });
|
||||||
|
cbs.add("--es", [&args](CLIParser &) { args.es = true; args.set_es = true; });
|
||||||
|
cbs.add("--no-es", [&args](CLIParser &) { args.es = false; args.set_es = true; });
|
||||||
|
cbs.add("--version", [&args](CLIParser &parser) { args.version = parser.next_uint(); args.set_version = true; });
|
||||||
|
cbs.add("--dump-resources", [&args](CLIParser &) { args.dump_resources = true; });
|
||||||
|
cbs.add("--force-temporary", [&args](CLIParser &) { args.force_temporary = true; });
|
||||||
|
cbs.add("--flatten-ubo", [&args](CLIParser &) { args.flatten_ubo = true; });
|
||||||
|
cbs.add("--fixup-clipspace", [&args](CLIParser &) { args.fixup = true; });
|
||||||
|
cbs.add("--iterations", [&args](CLIParser &parser) { args.iterations = parser.next_uint(); });
|
||||||
|
cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
|
||||||
|
|
||||||
|
cbs.add("--pls-in", [&args](CLIParser &parser) {
|
||||||
|
auto fmt = pls_format(parser.next_string());
|
||||||
|
auto name = parser.next_string();
|
||||||
|
args.pls_in.push_back({ move(fmt), move(name) });
|
||||||
|
});
|
||||||
|
cbs.add("--pls-out", [&args](CLIParser &parser) {
|
||||||
|
auto fmt = pls_format(parser.next_string());
|
||||||
|
auto name = parser.next_string();
|
||||||
|
args.pls_out.push_back({ move(fmt), move(name) });
|
||||||
|
});
|
||||||
|
|
||||||
|
cbs.default_handler = [&args](const char *value) { args.input = value; };
|
||||||
|
cbs.error_handler = []{ print_help(); };
|
||||||
|
|
||||||
|
CLIParser parser{move(cbs), argc - 1, argv + 1};
|
||||||
|
if (!parser.parse())
|
||||||
|
{
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else if (parser.ended_state)
|
||||||
|
{
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!args.input)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Didn't specify input file.\n");
|
||||||
|
print_help();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_ptr<CompilerGLSL> compiler;
|
||||||
|
|
||||||
|
if (args.cpp)
|
||||||
|
compiler = unique_ptr<CompilerGLSL>(new CompilerCPP(read_spirv_file(args.input)));
|
||||||
|
else
|
||||||
|
compiler = unique_ptr<CompilerGLSL>(new CompilerGLSL(read_spirv_file(args.input)));
|
||||||
|
|
||||||
|
if (!args.set_version && !compiler->get_options().version)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Didn't specify GLSL version and SPIR-V did not specify language.\n");
|
||||||
|
print_help();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompilerGLSL::Options opts = compiler->get_options();
|
||||||
|
if (args.set_version)
|
||||||
|
opts.version = args.version;
|
||||||
|
if (args.set_es)
|
||||||
|
opts.es = args.es;
|
||||||
|
opts.force_temporary = args.force_temporary;
|
||||||
|
opts.vertex.fixup_clipspace = args.fixup;
|
||||||
|
compiler->set_options(opts);
|
||||||
|
|
||||||
|
auto res = compiler->get_shader_resources();
|
||||||
|
|
||||||
|
if (args.flatten_ubo)
|
||||||
|
for (auto &ubo : res.uniform_buffers)
|
||||||
|
compiler->flatten_interface_block(ubo.id);
|
||||||
|
|
||||||
|
auto pls_inputs = remap_pls(args.pls_in, res.stage_inputs, &res.subpass_inputs);
|
||||||
|
auto pls_outputs = remap_pls(args.pls_out, res.stage_outputs, nullptr);
|
||||||
|
compiler->remap_pixel_local_storage(move(pls_inputs), move(pls_outputs));
|
||||||
|
|
||||||
|
if (args.dump_resources)
|
||||||
|
{
|
||||||
|
print_resources(*compiler, res);
|
||||||
|
print_push_constant_resources(*compiler, res.push_constant_buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
string glsl;
|
||||||
|
for (uint32_t i = 0; i < args.iterations; i++)
|
||||||
|
glsl = compiler->compile();
|
||||||
|
|
||||||
|
if (args.output)
|
||||||
|
write_string_to_file(args.output, glsl.c_str());
|
||||||
|
else
|
||||||
|
printf("%s", glsl.c_str());
|
||||||
|
}
|
||||||
|
|
28
msvc/spir2cross.sln
Normal file
28
msvc/spir2cross.sln
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Express 2013 for Windows Desktop
|
||||||
|
VisualStudioVersion = 12.0.31101.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spir2cross", "spir2cross.vcxproj", "{977E3701-1A21-4425-B7E5-6BDF5EA062CD}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{977E3701-1A21-4425-B7E5-6BDF5EA062CD}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
160
msvc/spir2cross.vcxproj
Normal file
160
msvc/spir2cross.vcxproj
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{977E3701-1A21-4425-B7E5-6BDF5EA062CD}</ProjectGuid>
|
||||||
|
<RootNamespace>spir2cross</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\cpp\compute.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cpp\culling.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cpp\shadertoy.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\main.cpp" />
|
||||||
|
<ClCompile Include="..\spir2cpp.cpp" />
|
||||||
|
<ClCompile Include="..\spir2cross.cpp" />
|
||||||
|
<ClCompile Include="..\spir2glsl.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\GLSL.std.450.h" />
|
||||||
|
<ClInclude Include="..\spir2common.hpp" />
|
||||||
|
<ClInclude Include="..\spir2cpp.hpp" />
|
||||||
|
<ClInclude Include="..\spir2cross.hpp" />
|
||||||
|
<ClInclude Include="..\spir2glsl.hpp" />
|
||||||
|
<ClInclude Include="..\spirv.hpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
63
msvc/spir2cross.vcxproj.filters
Normal file
63
msvc/spir2cross.vcxproj.filters
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\cpp">
|
||||||
|
<UniqueIdentifier>{61390b44-2b95-4b9a-8910-9ea1bc3a4920}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\spir2cross.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\spir2glsl.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\spir2cpp.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cpp\compute.cpp">
|
||||||
|
<Filter>Source Files\cpp</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cpp\culling.cpp">
|
||||||
|
<Filter>Source Files\cpp</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cpp\shadertoy.cpp">
|
||||||
|
<Filter>Source Files\cpp</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\GLSL.std.450.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\spir2cross.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\spir2glsl.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\spirv.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\spir2common.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\spir2cpp.hpp">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
47
reference/shaders/comp/atomic.comp
Normal file
47
reference/shaders/comp/atomic.comp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_OES_shader_image_atomic : require
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 2, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
uint u32;
|
||||||
|
int i32;
|
||||||
|
} ssbo;
|
||||||
|
|
||||||
|
layout(binding = 0, r32ui) uniform highp uimage2D uImage;
|
||||||
|
layout(binding = 1, r32i) uniform highp iimage2D iImage;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint _19 = imageAtomicAdd(uImage, ivec2(1, 5), 1u);
|
||||||
|
uint _21 = imageAtomicOr(uImage, ivec2(1, 5), 1u);
|
||||||
|
uint _23 = imageAtomicXor(uImage, ivec2(1, 5), 1u);
|
||||||
|
uint _25 = imageAtomicAnd(uImage, ivec2(1, 5), 1u);
|
||||||
|
uint _27 = imageAtomicMin(uImage, ivec2(1, 5), 1u);
|
||||||
|
uint _29 = imageAtomicMax(uImage, ivec2(1, 5), 1u);
|
||||||
|
uint _33 = imageAtomicCompSwap(uImage, ivec2(1, 5), 10u, 2u);
|
||||||
|
int _41 = imageAtomicAdd(iImage, ivec2(1, 6), 1);
|
||||||
|
int _43 = imageAtomicOr(iImage, ivec2(1, 6), 1);
|
||||||
|
int _45 = imageAtomicXor(iImage, ivec2(1, 6), 1);
|
||||||
|
int _47 = imageAtomicAnd(iImage, ivec2(1, 6), 1);
|
||||||
|
int _49 = imageAtomicMin(iImage, ivec2(1, 6), 1);
|
||||||
|
int _51 = imageAtomicMax(iImage, ivec2(1, 6), 1);
|
||||||
|
int _55 = imageAtomicCompSwap(iImage, ivec2(1, 5), 10, 2);
|
||||||
|
uint _62 = atomicAdd(ssbo.u32, 1u);
|
||||||
|
uint _64 = atomicOr(ssbo.u32, 1u);
|
||||||
|
uint _66 = atomicXor(ssbo.u32, 1u);
|
||||||
|
uint _68 = atomicAnd(ssbo.u32, 1u);
|
||||||
|
uint _70 = atomicMin(ssbo.u32, 1u);
|
||||||
|
uint _72 = atomicMax(ssbo.u32, 1u);
|
||||||
|
uint _74 = atomicExchange(ssbo.u32, 1u);
|
||||||
|
uint _76 = atomicCompSwap(ssbo.u32, 10u, 2u);
|
||||||
|
int _79 = atomicAdd(ssbo.i32, 1);
|
||||||
|
int _81 = atomicOr(ssbo.i32, 1);
|
||||||
|
int _83 = atomicXor(ssbo.i32, 1);
|
||||||
|
int _85 = atomicAnd(ssbo.i32, 1);
|
||||||
|
int _87 = atomicMin(ssbo.i32, 1);
|
||||||
|
int _89 = atomicMax(ssbo.i32, 1);
|
||||||
|
int _91 = atomicExchange(ssbo.i32, 1);
|
||||||
|
int _93 = atomicCompSwap(ssbo.i32, 10, 2);
|
||||||
|
}
|
||||||
|
|
39
reference/shaders/comp/bake_gradient.comp
Normal file
39
reference/shaders/comp/bake_gradient.comp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 4, std140) uniform UBO
|
||||||
|
{
|
||||||
|
vec4 uInvSize;
|
||||||
|
vec4 uScale;
|
||||||
|
} _46;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform mediump sampler2D uHeight;
|
||||||
|
layout(binding = 1) uniform mediump sampler2D uDisplacement;
|
||||||
|
layout(binding = 2, rgba16f) uniform mediump writeonly image2D iHeightDisplacement;
|
||||||
|
layout(binding = 3, rgba16f) uniform mediump writeonly image2D iGradJacobian;
|
||||||
|
|
||||||
|
mediump float jacobian(mediump vec2 dDdx, mediump vec2 dDdy)
|
||||||
|
{
|
||||||
|
return (((1.000000 + dDdx.x) * (1.000000 + dDdy.y)) - (dDdx.y * dDdy.x));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 uv = ((vec2(gl_GlobalInvocationID.xy) * _46.uInvSize.xy).xyxy + (_46.uInvSize * 0.500000));
|
||||||
|
float h = textureLod(uHeight, uv.xy, 0.000000).x;
|
||||||
|
float x0 = textureLodOffset(uHeight, uv.xy, 0.000000, ivec2(-1, 0)).x;
|
||||||
|
float x1 = textureLodOffset(uHeight, uv.xy, 0.000000, ivec2(1, 0)).x;
|
||||||
|
float y0 = textureLodOffset(uHeight, uv.xy, 0.000000, ivec2(0, -1)).x;
|
||||||
|
float y1 = textureLodOffset(uHeight, uv.xy, 0.000000, ivec2(0, 1)).x;
|
||||||
|
vec2 grad = ((_46.uScale.xy * 0.500000) * vec2((x1 - x0), (y1 - y0)));
|
||||||
|
vec2 displacement = (textureLod(uDisplacement, uv.zw, 0.000000).xy * 1.200000);
|
||||||
|
vec2 dDdx = ((textureLodOffset(uDisplacement, uv.zw, 0.000000, ivec2(1, 0)).xy - textureLodOffset(uDisplacement, uv.zw, 0.000000, ivec2(-1, 0)).xy) * 0.600000);
|
||||||
|
vec2 dDdy = ((textureLodOffset(uDisplacement, uv.zw, 0.000000, ivec2(0, 1)).xy - textureLodOffset(uDisplacement, uv.zw, 0.000000, ivec2(0, -1)).xy) * 0.600000);
|
||||||
|
vec2 param = (dDdx * _46.uScale.z);
|
||||||
|
vec2 param_1 = (dDdy * _46.uScale.z);
|
||||||
|
float j = jacobian(param, param_1);
|
||||||
|
displacement = vec2(0.000000);
|
||||||
|
imageStore(iHeightDisplacement, ivec2(gl_GlobalInvocationID.xy), vec4(h, displacement, 0.000000));
|
||||||
|
imageStore(iGradJacobian, ivec2(gl_GlobalInvocationID.xy), vec4(grad, j, 0.000000));
|
||||||
|
}
|
||||||
|
|
29
reference/shaders/comp/basic.comp
Normal file
29
reference/shaders/comp/basic.comp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 in_data[];
|
||||||
|
} _23;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
} _45;
|
||||||
|
|
||||||
|
layout(binding = 2, std430) buffer SSBO3
|
||||||
|
{
|
||||||
|
uint counter;
|
||||||
|
} _48;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 idata = _23.in_data[ident];
|
||||||
|
if ((dot(idata, vec4(1.000000, 5.000000, 6.000000, 2.000000)) > 8.200000))
|
||||||
|
{
|
||||||
|
uint _52 = atomicAdd(_48.counter, 1u);
|
||||||
|
_45.out_data[_52] = idata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
29
reference/shaders/comp/culling.comp
Normal file
29
reference/shaders/comp/culling.comp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 4, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
float in_data[];
|
||||||
|
} _22;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
float out_data[];
|
||||||
|
} _38;
|
||||||
|
|
||||||
|
layout(binding = 2, std430) buffer SSBO3
|
||||||
|
{
|
||||||
|
uint count;
|
||||||
|
} _41;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
float idata = _22.in_data[ident];
|
||||||
|
if ((idata > 12.000000))
|
||||||
|
{
|
||||||
|
uint _45 = atomicAdd(_41.count, 1u);
|
||||||
|
_38.out_data[_45] = idata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
29
reference/shaders/comp/dowhile.comp
Normal file
29
reference/shaders/comp/dowhile.comp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
vec4 in_data[];
|
||||||
|
} _28;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
} _52;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
i = 0;
|
||||||
|
vec4 idat = _28.in_data[ident];
|
||||||
|
do
|
||||||
|
{
|
||||||
|
idat = (_28.mvp * idat);
|
||||||
|
i = (i + 1);
|
||||||
|
} while ((i < 16));
|
||||||
|
_52.out_data[ident] = idat;
|
||||||
|
}
|
||||||
|
|
96
reference/shaders/comp/generate_height.comp
Normal file
96
reference/shaders/comp/generate_height.comp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer Distribution
|
||||||
|
{
|
||||||
|
vec2 distribution[];
|
||||||
|
} _190;
|
||||||
|
|
||||||
|
layout(binding = 2, std140) uniform UBO
|
||||||
|
{
|
||||||
|
vec4 uModTime;
|
||||||
|
} _218;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer HeightmapFFT
|
||||||
|
{
|
||||||
|
uint heights[];
|
||||||
|
} _276;
|
||||||
|
|
||||||
|
uvec2 workaround_mix(uvec2 a, uvec2 b, bvec2 sel)
|
||||||
|
{
|
||||||
|
uint _137;
|
||||||
|
uint _148;
|
||||||
|
if (sel.x)
|
||||||
|
{
|
||||||
|
_137 = b.x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_137 = a.x;
|
||||||
|
}
|
||||||
|
uint _147 = _137;
|
||||||
|
if (sel.y)
|
||||||
|
{
|
||||||
|
_148 = b.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_148 = a.y;
|
||||||
|
}
|
||||||
|
return uvec2(_147, _148);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 alias(vec2 i, vec2 N)
|
||||||
|
{
|
||||||
|
return mix(i, (i - N), greaterThan(i, (N * 0.500000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 cmul(vec2 a, vec2 b)
|
||||||
|
{
|
||||||
|
vec2 r3 = a.yx;
|
||||||
|
vec2 r1 = b.xx;
|
||||||
|
vec2 R0 = (a * r1);
|
||||||
|
vec2 r2 = b.yy;
|
||||||
|
vec2 R1 = (r2 * r3);
|
||||||
|
return (R0 + vec2((-R1.x), R1.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint pack2(vec2 v)
|
||||||
|
{
|
||||||
|
return packHalf2x16(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_heightmap()
|
||||||
|
{
|
||||||
|
uvec2 N = (uvec2(64u, 1u) * gl_NumWorkGroups.xy);
|
||||||
|
uvec2 i = gl_GlobalInvocationID.xy;
|
||||||
|
uvec2 param = (N - i);
|
||||||
|
uvec2 param_1 = uvec2(0u);
|
||||||
|
bvec2 param_2 = equal(i, uvec2(0u));
|
||||||
|
uvec2 wi = workaround_mix(param, param_1, param_2);
|
||||||
|
vec2 a = _190.distribution[((i.y * N.x) + i.x)];
|
||||||
|
vec2 b = _190.distribution[((wi.y * N.x) + wi.x)];
|
||||||
|
vec2 param_3 = vec2(i);
|
||||||
|
vec2 param_4 = vec2(N);
|
||||||
|
vec2 k = (_218.uModTime.xy * alias(param_3, param_4));
|
||||||
|
float k_len = length(k);
|
||||||
|
float w = (sqrt((9.810000 * k_len)) * _218.uModTime.z);
|
||||||
|
float cw = cos(w);
|
||||||
|
float sw = sin(w);
|
||||||
|
vec2 param_5 = a;
|
||||||
|
vec2 param_6 = vec2(cw, sw);
|
||||||
|
a = cmul(param_5, param_6);
|
||||||
|
vec2 param_7 = b;
|
||||||
|
vec2 param_8 = vec2(cw, sw);
|
||||||
|
b = cmul(param_7, param_8);
|
||||||
|
b = vec2(b.x, (-b.y));
|
||||||
|
vec2 res = (a + b);
|
||||||
|
vec2 param_9 = res;
|
||||||
|
_276.heights[((i.y * N.x) + i.x)] = pack2(param_9);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
generate_heightmap();
|
||||||
|
}
|
||||||
|
|
12
reference/shaders/comp/image.comp
Normal file
12
reference/shaders/comp/image.comp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, rgba8) uniform mediump readonly image2D uImageIn;
|
||||||
|
layout(binding = 1, rgba8) uniform mediump writeonly image2D uImageOut;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 v = imageLoad(uImageIn, (ivec2(gl_GlobalInvocationID.xy) + imageSize(uImageIn)));
|
||||||
|
imageStore(uImageOut, ivec2(gl_GlobalInvocationID.xy), v);
|
||||||
|
}
|
||||||
|
|
61
reference/shaders/comp/inout-struct.comp
Normal file
61
reference/shaders/comp/inout-struct.comp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
vec4 a;
|
||||||
|
vec4 b;
|
||||||
|
vec4 c;
|
||||||
|
vec4 d;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 data[];
|
||||||
|
} indata;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 data[];
|
||||||
|
} outdata;
|
||||||
|
|
||||||
|
layout(binding = 2, std430) buffer SSBO3
|
||||||
|
{
|
||||||
|
Foo foos[];
|
||||||
|
} foobar;
|
||||||
|
|
||||||
|
void baz(out Foo foo)
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
foo.a = indata.data[((4u * ident) + 0u)];
|
||||||
|
foo.b = indata.data[((4u * ident) + 1u)];
|
||||||
|
foo.c = indata.data[((4u * ident) + 2u)];
|
||||||
|
foo.d = indata.data[((4u * ident) + 3u)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void meow(inout Foo foo)
|
||||||
|
{
|
||||||
|
foo.a = (foo.a + vec4(10.000000));
|
||||||
|
foo.b = (foo.b + vec4(20.000000));
|
||||||
|
foo.c = (foo.c + vec4(30.000000));
|
||||||
|
foo.d = (foo.d + vec4(40.000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 bar(Foo foo)
|
||||||
|
{
|
||||||
|
return (((foo.a + foo.b) + foo.c) + foo.d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Foo param;
|
||||||
|
baz(param);
|
||||||
|
Foo foo = param;
|
||||||
|
Foo param_1 = foo;
|
||||||
|
meow(param_1);
|
||||||
|
foo = param_1;
|
||||||
|
Foo param_2 = foo;
|
||||||
|
Foo param_3 = foobar.foos[gl_GlobalInvocationID.x];
|
||||||
|
outdata.data[gl_GlobalInvocationID.x] = (bar(param_2) + bar(param_3));
|
||||||
|
}
|
||||||
|
|
19
reference/shaders/comp/insert.comp
Normal file
19
reference/shaders/comp/insert.comp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
} _27;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 v;
|
||||||
|
v.x = 10.000000;
|
||||||
|
v.y = 30.000000;
|
||||||
|
v.z = 70.000000;
|
||||||
|
v.w = 90.000000;
|
||||||
|
_27.out_data[gl_GlobalInvocationID.x] = v;
|
||||||
|
_27.out_data[gl_GlobalInvocationID.x].y = 20.000000;
|
||||||
|
}
|
||||||
|
|
72
reference/shaders/comp/loop.comp
Normal file
72
reference/shaders/comp/loop.comp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
vec4 in_data[];
|
||||||
|
} _24;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
} _125;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 idat = _24.in_data[ident];
|
||||||
|
int k = 0;
|
||||||
|
uint i;
|
||||||
|
uint j;
|
||||||
|
int l;
|
||||||
|
while ((k < 10))
|
||||||
|
{
|
||||||
|
idat = (idat * 2.000000);
|
||||||
|
k = (k + 1);
|
||||||
|
}
|
||||||
|
i = 0u;
|
||||||
|
for (; (i < 16u); i = (i + uint(1)), k = (k + 1))
|
||||||
|
{
|
||||||
|
j = 0u;
|
||||||
|
for (; (j < 30u); j = (j + uint(1)))
|
||||||
|
{
|
||||||
|
idat = (_24.mvp * idat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
k = (k + 1);
|
||||||
|
if ((k > 10))
|
||||||
|
{
|
||||||
|
k = (k + 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
k = (k + 3);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
k = (k + 10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
k = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
k = (k + 1);
|
||||||
|
} while ((k > 10));
|
||||||
|
l = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((l == 5))
|
||||||
|
{
|
||||||
|
l = (l + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
idat = (idat + vec4(1.000000));
|
||||||
|
l = (l + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_125.out_data[ident] = idat;
|
||||||
|
}
|
||||||
|
|
14
reference/shaders/comp/mat3.comp
Normal file
14
reference/shaders/comp/mat3.comp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
mat3 out_data[];
|
||||||
|
} _22;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
_22.out_data[ident] = mat3(vec3(10.000000), vec3(20.000000), vec3(40.000000));
|
||||||
|
}
|
||||||
|
|
22
reference/shaders/comp/modf.comp
Normal file
22
reference/shaders/comp/modf.comp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 in_data[];
|
||||||
|
} _23;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
} _35;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 i;
|
||||||
|
vec4 _31 = modf(_23.in_data[ident], i);
|
||||||
|
vec4 v = _31;
|
||||||
|
_35.out_data[ident] = v;
|
||||||
|
}
|
||||||
|
|
36
reference/shaders/comp/return.comp
Normal file
36
reference/shaders/comp/return.comp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
} _27;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
int i;
|
||||||
|
if ((ident == 2u))
|
||||||
|
{
|
||||||
|
_27.out_data[ident] = vec4(20.000000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((ident == 4u))
|
||||||
|
{
|
||||||
|
_27.out_data[ident] = vec4(10.000000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
for (; (i < 20); i = (i + 1))
|
||||||
|
{
|
||||||
|
if ((i == 10))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_27.out_data[ident] = vec4(10.000000);
|
||||||
|
}
|
||||||
|
|
25
reference/shaders/comp/shared.comp
Normal file
25
reference/shaders/comp/shared.comp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 4, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
float in_data[];
|
||||||
|
} _22;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
float out_data[];
|
||||||
|
} _44;
|
||||||
|
|
||||||
|
shared float sShared[4];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
float idata = _22.in_data[ident];
|
||||||
|
sShared[gl_LocalInvocationIndex] = idata;
|
||||||
|
memoryBarrierShared();
|
||||||
|
barrier();
|
||||||
|
_44.out_data[ident] = sShared[((4u - gl_LocalInvocationIndex) - 1u)];
|
||||||
|
}
|
||||||
|
|
24
reference/shaders/comp/struct-layout.comp
Normal file
24
reference/shaders/comp/struct-layout.comp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
mat4 m;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
Foo out_data[];
|
||||||
|
} _23;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
Foo in_data[];
|
||||||
|
} _30;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
_23.out_data[ident].m = (_30.in_data[ident].m * _30.in_data[ident].m);
|
||||||
|
}
|
||||||
|
|
68
reference/shaders/comp/struct-packing.comp
Normal file
68
reference/shaders/comp/struct-packing.comp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
struct S0
|
||||||
|
{
|
||||||
|
vec2 a[1];
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S1
|
||||||
|
{
|
||||||
|
vec3 a;
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S2
|
||||||
|
{
|
||||||
|
vec3 a[1];
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S3
|
||||||
|
{
|
||||||
|
vec2 a;
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Content
|
||||||
|
{
|
||||||
|
S0 m0s[1];
|
||||||
|
S1 m1s[1];
|
||||||
|
S2 m2s[1];
|
||||||
|
S0 m0;
|
||||||
|
S1 m1;
|
||||||
|
S2 m2;
|
||||||
|
S3 m3;
|
||||||
|
float m4;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 1, std140) buffer SSBO1
|
||||||
|
{
|
||||||
|
Content content;
|
||||||
|
Content content1[2];
|
||||||
|
Content content2;
|
||||||
|
mat2 m0;
|
||||||
|
mat2 m1;
|
||||||
|
mat2x3 m2[4];
|
||||||
|
mat3x2 m3;
|
||||||
|
layout(row_major) mat2 m4;
|
||||||
|
layout(row_major) mat2 m5[9];
|
||||||
|
layout(row_major) mat2x3 m6[2][4];
|
||||||
|
layout(row_major) mat3x2 m7;
|
||||||
|
float array[];
|
||||||
|
} ssbo_430;
|
||||||
|
|
||||||
|
layout(binding = 0, std140) buffer SSBO0
|
||||||
|
{
|
||||||
|
Content content;
|
||||||
|
Content content1[2];
|
||||||
|
Content content2;
|
||||||
|
float array[];
|
||||||
|
} ssbo_140;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ssbo_430.content = ssbo_140.content;
|
||||||
|
}
|
||||||
|
|
66
reference/shaders/comp/torture-loop.comp
Normal file
66
reference/shaders/comp/torture-loop.comp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
vec4 in_data[];
|
||||||
|
} _24;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
} _89;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 idat = _24.in_data[ident];
|
||||||
|
int k = 0;
|
||||||
|
uint i;
|
||||||
|
uint j;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int _39 = k;
|
||||||
|
int _40 = _39 + 1;
|
||||||
|
k = _40;
|
||||||
|
if ((_40 < 10))
|
||||||
|
{
|
||||||
|
idat = (idat * 2.000000);
|
||||||
|
int _47 = k;
|
||||||
|
k = (_47 + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = 0u;
|
||||||
|
int _76;
|
||||||
|
for (; (i < 16u); i = (i + uint(1)), _76 = k, k = (_76 + 1))
|
||||||
|
{
|
||||||
|
j = 0u;
|
||||||
|
for (; (j < 30u); j = (j + uint(1)))
|
||||||
|
{
|
||||||
|
idat = (_24.mvp * idat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int _84;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int _82 = k;
|
||||||
|
k = (_82 + 1);
|
||||||
|
int _84 = k;
|
||||||
|
if ((_84 > 10))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_89.out_data[ident] = idat;
|
||||||
|
}
|
||||||
|
|
18
reference/shaders/comp/udiv.comp
Normal file
18
reference/shaders/comp/udiv.comp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO2
|
||||||
|
{
|
||||||
|
uint outputs[];
|
||||||
|
} _10;
|
||||||
|
|
||||||
|
layout(binding = 0, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
uint inputs[];
|
||||||
|
} _23;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
_10.outputs[gl_GlobalInvocationID.x] = (_23.inputs[gl_GlobalInvocationID.x] / 29u);
|
||||||
|
}
|
||||||
|
|
15
reference/shaders/frag/basic.frag
Normal file
15
reference/shaders/frag/basic.frag
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform mediump sampler2D uTex;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
in vec4 vColor;
|
||||||
|
in vec2 vTex;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = (vColor * texture(uTex, vTex));
|
||||||
|
}
|
||||||
|
|
28
reference/shaders/frag/constant-array.frag
Normal file
28
reference/shaders/frag/constant-array.frag
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
struct Foobar
|
||||||
|
{
|
||||||
|
float a;
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
layout(location = 0) in mediump flat int index;
|
||||||
|
|
||||||
|
vec4 resolve(Foobar f)
|
||||||
|
{
|
||||||
|
return vec4((f.a + f.b));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
highp vec4 indexable[3] = vec4[](vec4(1.000000), vec4(2.000000), vec4(3.000000));
|
||||||
|
highp vec4 indexable_1[2][2] = vec4[][](vec4[](vec4(1.000000), vec4(2.000000)), vec4[](vec4(8.000000), vec4(10.000000)));
|
||||||
|
Foobar param = Foobar(10.000000, 20.000000);
|
||||||
|
Foobar indexable_2[2] = Foobar[](Foobar(10.000000, 40.000000), Foobar(90.000000, 70.000000));
|
||||||
|
Foobar param_1 = indexable_2[index];
|
||||||
|
FragColor = (((indexable[index] + indexable_1[index][(index + 1)]) + resolve(param)) + resolve(param_1));
|
||||||
|
}
|
||||||
|
|
30
reference/shaders/frag/flush_params.frag
Normal file
30
reference/shaders/frag/flush_params.frag
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
struct Structy
|
||||||
|
{
|
||||||
|
vec4 c;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
void foo2(out Structy f)
|
||||||
|
{
|
||||||
|
f.c = vec4(10.000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Structy foo()
|
||||||
|
{
|
||||||
|
Structy param;
|
||||||
|
foo2(param);
|
||||||
|
Structy f = param;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Structy s = foo();
|
||||||
|
FragColor = s.c;
|
||||||
|
}
|
||||||
|
|
62
reference/shaders/frag/ground.frag
Normal file
62
reference/shaders/frag/ground.frag
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(binding = 4, std140) uniform GlobalPSData
|
||||||
|
{
|
||||||
|
vec4 g_CamPos;
|
||||||
|
vec4 g_SunDir;
|
||||||
|
vec4 g_SunColor;
|
||||||
|
vec4 g_ResolutionParams;
|
||||||
|
vec4 g_TimeParams;
|
||||||
|
vec4 g_FogColor_Distance;
|
||||||
|
} _56;
|
||||||
|
|
||||||
|
layout(binding = 2) uniform mediump sampler2D TexNormalmap;
|
||||||
|
|
||||||
|
layout(location = 3) out vec4 LightingOut;
|
||||||
|
layout(location = 2) out vec4 NormalOut;
|
||||||
|
layout(location = 1) out vec4 SpecularOut;
|
||||||
|
layout(location = 0) out vec4 AlbedoOut;
|
||||||
|
layout(location = 0) in vec2 TexCoord;
|
||||||
|
layout(location = 1) in vec3 EyeVec;
|
||||||
|
|
||||||
|
float saturate(float x)
|
||||||
|
{
|
||||||
|
return clamp(x, 0.000000, 1.000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resolve(vec3 Albedo, vec3 Normal, float Roughness, float Metallic)
|
||||||
|
{
|
||||||
|
LightingOut = vec4(0.000000);
|
||||||
|
NormalOut = vec4(((Normal * 0.500000) + vec3(0.500000)), 0.000000);
|
||||||
|
SpecularOut = vec4(Roughness, Metallic, 0.000000, 0.000000);
|
||||||
|
AlbedoOut = vec4(Albedo, 1.000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 Normal = ((texture(TexNormalmap, TexCoord).xyz * 2.000000) - vec3(1.000000));
|
||||||
|
Normal = normalize(Normal);
|
||||||
|
highp float param = (length(EyeVec) / 1000.000000);
|
||||||
|
vec2 scatter_uv;
|
||||||
|
scatter_uv.x = saturate(param);
|
||||||
|
vec3 nEye = normalize(EyeVec);
|
||||||
|
scatter_uv.y = 0.000000;
|
||||||
|
vec3 Color = vec3(0.100000, 0.300000, 0.100000);
|
||||||
|
vec3 grass = vec3(0.100000, 0.300000, 0.100000);
|
||||||
|
vec3 dirt = vec3(0.100000);
|
||||||
|
vec3 snow = vec3(0.800000);
|
||||||
|
float grass_snow = smoothstep(0.000000, 0.150000, ((_56.g_CamPos.y + EyeVec.y) / 200.000000));
|
||||||
|
vec3 base = mix(grass, snow, vec3(grass_snow));
|
||||||
|
float edge = smoothstep(0.700000, 0.750000, Normal.y);
|
||||||
|
Color = mix(dirt, base, vec3(edge));
|
||||||
|
Color = (Color * Color);
|
||||||
|
float Roughness = (1.000000 - (edge * grass_snow));
|
||||||
|
highp vec3 param_1 = Color;
|
||||||
|
highp vec3 param_2 = Normal;
|
||||||
|
highp float param_3 = Roughness;
|
||||||
|
highp float param_4 = 0.000000;
|
||||||
|
Resolve(param_1, param_2, param_3, param_4);
|
||||||
|
}
|
||||||
|
|
38
reference/shaders/frag/mix.frag
Normal file
38
reference/shaders/frag/mix.frag
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
layout(location = 0) in vec4 vIn0;
|
||||||
|
layout(location = 1) in vec4 vIn1;
|
||||||
|
layout(location = 2) in float vIn2;
|
||||||
|
layout(location = 3) in float vIn3;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
bvec4 l = bvec4(false, true, false, false);
|
||||||
|
FragColor = mix(vIn0, vIn1, l);
|
||||||
|
bool f = true;
|
||||||
|
FragColor = vec4(mix(vIn2, vIn3, f));
|
||||||
|
highp vec4 _35;
|
||||||
|
highp float _44;
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
_35 = vIn0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_35 = vIn1;
|
||||||
|
}
|
||||||
|
FragColor = _35;
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
_44 = vIn2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_44 = vIn3;
|
||||||
|
}
|
||||||
|
FragColor = vec4(_44);
|
||||||
|
}
|
||||||
|
|
21
reference/shaders/frag/pls.frag
Normal file
21
reference/shaders/frag/pls.frag
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 PLSOut0;
|
||||||
|
layout(location = 0) in vec4 PLSIn0;
|
||||||
|
layout(location = 1) out vec4 PLSOut1;
|
||||||
|
layout(location = 1) in vec4 PLSIn1;
|
||||||
|
layout(location = 2) out vec4 PLSOut2;
|
||||||
|
in vec4 PLSIn2;
|
||||||
|
layout(location = 3) out vec4 PLSOut3;
|
||||||
|
in vec4 PLSIn3;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
PLSOut0 = (PLSIn0 * 2.000000);
|
||||||
|
PLSOut1 = (PLSIn1 * 6.000000);
|
||||||
|
PLSOut2 = (PLSIn2 * 7.000000);
|
||||||
|
PLSOut3 = (PLSIn3 * 4.000000);
|
||||||
|
}
|
||||||
|
|
21
reference/shaders/frag/sampler.frag
Normal file
21
reference/shaders/frag/sampler.frag
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform mediump sampler2D uTex;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
in vec4 vColor;
|
||||||
|
in vec2 vTex;
|
||||||
|
|
||||||
|
vec4 sample_texture(mediump sampler2D tex, vec2 uv)
|
||||||
|
{
|
||||||
|
return texture(tex, uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
highp vec2 param = vTex;
|
||||||
|
FragColor = (vColor * sample_texture(uTex, param));
|
||||||
|
}
|
||||||
|
|
20
reference/shaders/frag/swizzle.frag
Normal file
20
reference/shaders/frag/swizzle.frag
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(location = 0) uniform mediump sampler2D samp;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
layout(location = 2) in vec2 vUV;
|
||||||
|
layout(location = 1) in vec3 vNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vec4(texture(samp, vUV).xyz, 1.000000);
|
||||||
|
FragColor = vec4(texture(samp, vUV).xz, 1.000000, 4.000000);
|
||||||
|
FragColor = vec4(texture(samp, vUV).xx, texture(samp, (vUV + vec2(0.100000))).yy);
|
||||||
|
FragColor = vec4(vNormal, 1.000000);
|
||||||
|
FragColor = vec4((vNormal + vec3(1.800000)), 1.000000);
|
||||||
|
FragColor = vec4(vUV, (vUV + vec2(1.800000)));
|
||||||
|
}
|
||||||
|
|
26
reference/shaders/frag/ubo_layout.frag
Normal file
26
reference/shaders/frag/ubo_layout.frag
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
struct Str
|
||||||
|
{
|
||||||
|
mat4 foo;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform UBO1
|
||||||
|
{
|
||||||
|
layout(row_major) Str foo;
|
||||||
|
} ubo1;
|
||||||
|
|
||||||
|
layout(binding = 1, std140) uniform UBO2
|
||||||
|
{
|
||||||
|
Str foo;
|
||||||
|
} ubo0;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = (ubo1.foo.foo[0] + ubo0.foo.foo[0]);
|
||||||
|
}
|
||||||
|
|
26
reference/shaders/geom/basic.geom
Normal file
26
reference/shaders/geom/basic.geom
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_geometry_shader : require
|
||||||
|
layout(invocations = 4, triangles) in;
|
||||||
|
layout(max_vertices = 3, triangle_strip) out;
|
||||||
|
|
||||||
|
out vec3 vNormal;
|
||||||
|
in VertexData
|
||||||
|
{
|
||||||
|
vec3 normal;
|
||||||
|
} vin[3];
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = gl_in[0].gl_Position;
|
||||||
|
vNormal = (vin[0].normal + vec3(float(gl_InvocationID)));
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = gl_in[1].gl_Position;
|
||||||
|
vNormal = (vin[1].normal + vec3((4.000000 * float(gl_InvocationID))));
|
||||||
|
EmitVertex();
|
||||||
|
gl_Position = gl_in[2].gl_Position;
|
||||||
|
vNormal = (vin[2].normal + vec3((2.000000 * float(gl_InvocationID))));
|
||||||
|
EmitVertex();
|
||||||
|
EndPrimitive();
|
||||||
|
}
|
||||||
|
|
17
reference/shaders/tesc/basic.tesc
Normal file
17
reference/shaders/tesc/basic.tesc
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
layout(vertices = 1) out;
|
||||||
|
|
||||||
|
out patch vec3 vFoo;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_TessLevelInner[0] = 8.900000;
|
||||||
|
gl_TessLevelInner[1] = 6.900000;
|
||||||
|
gl_TessLevelOuter[0] = 8.900000;
|
||||||
|
gl_TessLevelOuter[1] = 6.900000;
|
||||||
|
gl_TessLevelOuter[2] = 3.900000;
|
||||||
|
gl_TessLevelOuter[3] = 4.900000;
|
||||||
|
vFoo = vec3(1.000000);
|
||||||
|
}
|
||||||
|
|
117
reference/shaders/tesc/water_tess.tesc
Normal file
117
reference/shaders/tesc/water_tess.tesc
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
layout(vertices = 1) out;
|
||||||
|
|
||||||
|
layout(std140) uniform UBO
|
||||||
|
{
|
||||||
|
vec4 uScale;
|
||||||
|
vec3 uCamPos;
|
||||||
|
vec2 uPatchSize;
|
||||||
|
vec2 uMaxTessLevel;
|
||||||
|
float uDistanceMod;
|
||||||
|
vec4 uFrustum[6];
|
||||||
|
} _41;
|
||||||
|
|
||||||
|
out patch vec2 vOutPatchPosBase;
|
||||||
|
out patch vec4 vPatchLods;
|
||||||
|
in vec2 vPatchPosBase[32];
|
||||||
|
|
||||||
|
bool frustum_cull(vec2 p0)
|
||||||
|
{
|
||||||
|
vec2 min_xz = ((p0 - vec2(10.000000)) * _41.uScale.xy);
|
||||||
|
vec2 max_xz = (((p0 + _41.uPatchSize) + vec2(10.000000)) * _41.uScale.xy);
|
||||||
|
vec3 bb_min = vec3(min_xz.x, -10.000000, min_xz.y);
|
||||||
|
vec3 bb_max = vec3(max_xz.x, 10.000000, max_xz.y);
|
||||||
|
vec3 center = ((bb_min + bb_max) * 0.500000);
|
||||||
|
float radius = (0.500000 * length((bb_max - bb_min)));
|
||||||
|
vec3 f0 = vec3(dot(_41.uFrustum[0], vec4(center, 1.000000)), dot(_41.uFrustum[1], vec4(center, 1.000000)), dot(_41.uFrustum[2], vec4(center, 1.000000)));
|
||||||
|
vec3 f1 = vec3(dot(_41.uFrustum[3], vec4(center, 1.000000)), dot(_41.uFrustum[4], vec4(center, 1.000000)), dot(_41.uFrustum[5], vec4(center, 1.000000)));
|
||||||
|
bool _205 = any(lessThanEqual(f0, vec3((-radius))));
|
||||||
|
bool _215;
|
||||||
|
if ((!_205))
|
||||||
|
{
|
||||||
|
_215 = any(lessThanEqual(f1, vec3((-radius))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_215 = _205;
|
||||||
|
}
|
||||||
|
return (!_215);
|
||||||
|
}
|
||||||
|
|
||||||
|
float lod_factor(vec2 pos_)
|
||||||
|
{
|
||||||
|
vec2 pos = (pos_ * _41.uScale.xy);
|
||||||
|
vec3 dist_to_cam = (_41.uCamPos - vec3(pos.x, 0.000000, pos.y));
|
||||||
|
float level = log2(((length(dist_to_cam) + 0.000100) * _41.uDistanceMod));
|
||||||
|
return clamp(level, 0.000000, _41.uMaxTessLevel.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 tess_level(vec4 lod)
|
||||||
|
{
|
||||||
|
return (exp2((-lod)) * _41.uMaxTessLevel.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float tess_level(float lod)
|
||||||
|
{
|
||||||
|
return (_41.uMaxTessLevel.y * exp2((-lod)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_tess_levels(vec2 p0)
|
||||||
|
{
|
||||||
|
vOutPatchPosBase = p0;
|
||||||
|
vec2 param = (p0 + (vec2(-0.500000) * _41.uPatchSize));
|
||||||
|
float l00 = lod_factor(param);
|
||||||
|
vec2 param_1 = (p0 + (vec2(0.500000, -0.500000) * _41.uPatchSize));
|
||||||
|
float l10 = lod_factor(param_1);
|
||||||
|
vec2 param_2 = (p0 + (vec2(1.500000, -0.500000) * _41.uPatchSize));
|
||||||
|
float l20 = lod_factor(param_2);
|
||||||
|
vec2 param_3 = (p0 + (vec2(-0.500000, 0.500000) * _41.uPatchSize));
|
||||||
|
float l01 = lod_factor(param_3);
|
||||||
|
vec2 param_4 = (p0 + (vec2(0.500000) * _41.uPatchSize));
|
||||||
|
float l11 = lod_factor(param_4);
|
||||||
|
vec2 param_5 = (p0 + (vec2(1.500000, 0.500000) * _41.uPatchSize));
|
||||||
|
float l21 = lod_factor(param_5);
|
||||||
|
vec2 param_6 = (p0 + (vec2(-0.500000, 1.500000) * _41.uPatchSize));
|
||||||
|
float l02 = lod_factor(param_6);
|
||||||
|
vec2 param_7 = (p0 + (vec2(0.500000, 1.500000) * _41.uPatchSize));
|
||||||
|
float l12 = lod_factor(param_7);
|
||||||
|
vec2 param_8 = (p0 + (vec2(1.500000) * _41.uPatchSize));
|
||||||
|
float l22 = lod_factor(param_8);
|
||||||
|
vec4 lods = vec4(dot(vec4(l01, l11, l02, l12), vec4(0.250000)), dot(vec4(l00, l10, l01, l11), vec4(0.250000)), dot(vec4(l10, l20, l11, l21), vec4(0.250000)), dot(vec4(l11, l21, l12, l22), vec4(0.250000)));
|
||||||
|
vPatchLods = lods;
|
||||||
|
vec4 outer_lods = min(lods, lods.yzwx);
|
||||||
|
vec4 param_9 = outer_lods;
|
||||||
|
vec4 levels = tess_level(param_9);
|
||||||
|
gl_TessLevelOuter[0] = levels.x;
|
||||||
|
gl_TessLevelOuter[1] = levels.y;
|
||||||
|
gl_TessLevelOuter[2] = levels.z;
|
||||||
|
gl_TessLevelOuter[3] = levels.w;
|
||||||
|
float min_lod = min(min(lods.x, lods.y), min(lods.z, lods.w));
|
||||||
|
float param_10 = min(min_lod, l11);
|
||||||
|
float inner = tess_level(param_10);
|
||||||
|
gl_TessLevelInner[0] = inner;
|
||||||
|
gl_TessLevelInner[1] = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 p0 = vPatchPosBase[0];
|
||||||
|
vec2 param = p0;
|
||||||
|
vec2 param_1;
|
||||||
|
if ((!frustum_cull(param)))
|
||||||
|
{
|
||||||
|
gl_TessLevelOuter[0] = -1.000000;
|
||||||
|
gl_TessLevelOuter[1] = -1.000000;
|
||||||
|
gl_TessLevelOuter[2] = -1.000000;
|
||||||
|
gl_TessLevelOuter[3] = -1.000000;
|
||||||
|
gl_TessLevelInner[0] = -1.000000;
|
||||||
|
gl_TessLevelInner[1] = -1.000000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
param_1 = p0;
|
||||||
|
compute_tess_levels(param_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
61
reference/shaders/tese/water_tess.tese
Normal file
61
reference/shaders/tese/water_tess.tese
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
layout(quads, cw, fractional_even_spacing) in;
|
||||||
|
|
||||||
|
layout(binding = 1, std140) uniform UBO
|
||||||
|
{
|
||||||
|
mat4 uMVP;
|
||||||
|
vec4 uScale;
|
||||||
|
vec2 uInvScale;
|
||||||
|
vec3 uCamPos;
|
||||||
|
vec2 uPatchSize;
|
||||||
|
vec2 uInvHeightmapSize;
|
||||||
|
} _31;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform mediump sampler2D uHeightmapDisplacement;
|
||||||
|
|
||||||
|
in patch vec2 vOutPatchPosBase;
|
||||||
|
in patch vec4 vPatchLods;
|
||||||
|
out vec4 vGradNormalTex;
|
||||||
|
out vec3 vWorld;
|
||||||
|
|
||||||
|
vec2 lerp_vertex(vec2 tess_coord)
|
||||||
|
{
|
||||||
|
return (vOutPatchPosBase + (tess_coord * _31.uPatchSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
mediump vec2 lod_factor(vec2 tess_coord)
|
||||||
|
{
|
||||||
|
mediump vec2 x = mix(vPatchLods.yx, vPatchLods.zw, vec2(tess_coord.x));
|
||||||
|
mediump float level = mix(x.x, x.y, tess_coord.y);
|
||||||
|
mediump float floor_level = floor(level);
|
||||||
|
mediump float fract_level = (level - floor_level);
|
||||||
|
return vec2(floor_level, fract_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
mediump vec3 sample_height_displacement(vec2 uv, vec2 off, mediump vec2 lod)
|
||||||
|
{
|
||||||
|
return mix(textureLod(uHeightmapDisplacement, (uv + (off * 0.500000)), lod.x).xyz, textureLod(uHeightmapDisplacement, (uv + (off * 1.000000)), (lod.x + 1.000000)).xyz, vec3(lod.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 tess_coord = gl_TessCoord.xy;
|
||||||
|
vec2 param = tess_coord;
|
||||||
|
vec2 pos = lerp_vertex(param);
|
||||||
|
vec2 param_1 = tess_coord;
|
||||||
|
mediump vec2 lod = lod_factor(param_1);
|
||||||
|
vec2 tex = (pos * _31.uInvHeightmapSize);
|
||||||
|
pos = (pos * _31.uScale.xy);
|
||||||
|
mediump float delta_mod = exp2(lod.x);
|
||||||
|
vec2 off = (_31.uInvHeightmapSize * delta_mod);
|
||||||
|
vGradNormalTex = vec4((tex + (_31.uInvHeightmapSize * 0.500000)), (tex * _31.uScale.zw));
|
||||||
|
vec2 param_2 = tex;
|
||||||
|
vec2 param_3 = off;
|
||||||
|
vec2 param_4 = lod;
|
||||||
|
vec3 height_displacement = sample_height_displacement(param_2, param_3, param_4);
|
||||||
|
pos = (pos + height_displacement.yz);
|
||||||
|
vWorld = vec3(pos.x, height_displacement.x, pos.y);
|
||||||
|
gl_Position = (_31.uMVP * vec4(vWorld, 1.000000));
|
||||||
|
}
|
||||||
|
|
17
reference/shaders/vert/basic.vert
Normal file
17
reference/shaders/vert/basic.vert
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
layout(std140) uniform UBO
|
||||||
|
{
|
||||||
|
mat4 uMVP;
|
||||||
|
} _16;
|
||||||
|
|
||||||
|
in vec4 aVertex;
|
||||||
|
out vec3 vNormal;
|
||||||
|
in vec3 aNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = (_16.uMVP * aVertex);
|
||||||
|
vNormal = aNormal;
|
||||||
|
}
|
||||||
|
|
111
reference/shaders/vert/ground.vert
Normal file
111
reference/shaders/vert/ground.vert
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
struct PatchData
|
||||||
|
{
|
||||||
|
vec4 Position;
|
||||||
|
vec4 LODs;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform GlobalVSData
|
||||||
|
{
|
||||||
|
vec4 g_ViewProj_Row0;
|
||||||
|
vec4 g_ViewProj_Row1;
|
||||||
|
vec4 g_ViewProj_Row2;
|
||||||
|
vec4 g_ViewProj_Row3;
|
||||||
|
vec4 g_CamPos;
|
||||||
|
vec4 g_CamRight;
|
||||||
|
vec4 g_CamUp;
|
||||||
|
vec4 g_CamFront;
|
||||||
|
vec4 g_SunDir;
|
||||||
|
vec4 g_SunColor;
|
||||||
|
vec4 g_TimeParams;
|
||||||
|
vec4 g_ResolutionParams;
|
||||||
|
vec4 g_CamAxisRight;
|
||||||
|
vec4 g_FogColor_Distance;
|
||||||
|
vec4 g_ShadowVP_Row0;
|
||||||
|
vec4 g_ShadowVP_Row1;
|
||||||
|
vec4 g_ShadowVP_Row2;
|
||||||
|
vec4 g_ShadowVP_Row3;
|
||||||
|
} _58;
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform PerPatch
|
||||||
|
{
|
||||||
|
PatchData Patches[256];
|
||||||
|
} _284;
|
||||||
|
|
||||||
|
layout(binding = 2, std140) uniform GlobalGround
|
||||||
|
{
|
||||||
|
vec4 GroundScale;
|
||||||
|
vec4 GroundPosition;
|
||||||
|
vec4 InvGroundSize_PatchScale;
|
||||||
|
} _381;
|
||||||
|
|
||||||
|
layout(binding = 1) uniform mediump sampler2D TexLOD;
|
||||||
|
layout(binding = 0) uniform mediump sampler2D TexHeightmap;
|
||||||
|
|
||||||
|
layout(location = 1) in vec4 LODWeights;
|
||||||
|
layout(location = 0) in vec2 Position;
|
||||||
|
layout(location = 1) out vec3 EyeVec;
|
||||||
|
layout(location = 0) out vec2 TexCoord;
|
||||||
|
|
||||||
|
vec2 warp_position()
|
||||||
|
{
|
||||||
|
float vlod = dot(LODWeights, _284.Patches[gl_InstanceID].LODs);
|
||||||
|
vlod = mix(vlod, _284.Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.000000))));
|
||||||
|
float floor_lod = floor(vlod);
|
||||||
|
float fract_lod = (vlod - floor_lod);
|
||||||
|
uint ufloor_lod = uint(floor_lod);
|
||||||
|
uvec2 uPosition = uvec2(Position);
|
||||||
|
uvec2 mask = ((uvec2(1u) << uvec2(ufloor_lod, (ufloor_lod + 1u))) - uvec2(1u));
|
||||||
|
uvec2 rounding;
|
||||||
|
uint _332;
|
||||||
|
uint _343;
|
||||||
|
vec4 lower_upper_snapped;
|
||||||
|
if ((uPosition.x < 32u))
|
||||||
|
{
|
||||||
|
_332 = mask.x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_332 = 0u;
|
||||||
|
}
|
||||||
|
uint _342 = _332;
|
||||||
|
if ((uPosition.y < 32u))
|
||||||
|
{
|
||||||
|
_343 = mask.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_343 = 0u;
|
||||||
|
}
|
||||||
|
rounding = uvec2(_342, _343);
|
||||||
|
lower_upper_snapped = vec4(((uPosition + rounding).xyxy & (~mask).xxyy));
|
||||||
|
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, vec2(fract_lod));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 lod_factor(vec2 uv)
|
||||||
|
{
|
||||||
|
float level = (textureLod(TexLOD, uv, 0.000000).x * 7.968750);
|
||||||
|
float floor_level = floor(level);
|
||||||
|
float fract_level = (level - floor_level);
|
||||||
|
return vec2(floor_level, fract_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 PatchPos = (_284.Patches[gl_InstanceID].Position.xz * _381.InvGroundSize_PatchScale.zw);
|
||||||
|
vec2 WarpedPos = warp_position();
|
||||||
|
vec2 VertexPos = (PatchPos + WarpedPos);
|
||||||
|
vec2 NormalizedPos = (VertexPos * _381.InvGroundSize_PatchScale.xy);
|
||||||
|
vec2 param = NormalizedPos;
|
||||||
|
vec2 lod = lod_factor(param);
|
||||||
|
vec2 Offset = (_381.InvGroundSize_PatchScale.xy * exp2(lod.x));
|
||||||
|
float Elevation = mix(textureLod(TexHeightmap, (NormalizedPos + (Offset * 0.500000)), lod.x).x, textureLod(TexHeightmap, (NormalizedPos + (Offset * 1.000000)), (lod.x + 1.000000)).x, lod.y);
|
||||||
|
vec3 WorldPos = vec3(NormalizedPos.x, Elevation, NormalizedPos.y);
|
||||||
|
WorldPos = (WorldPos * _381.GroundScale.xyz);
|
||||||
|
WorldPos = (WorldPos + _381.GroundPosition.xyz);
|
||||||
|
EyeVec = (WorldPos - _58.g_CamPos.xyz);
|
||||||
|
TexCoord = (NormalizedPos + (_381.InvGroundSize_PatchScale.xy * 0.500000));
|
||||||
|
gl_Position = ((((_58.g_ViewProj_Row0 * WorldPos.x) + (_58.g_ViewProj_Row1 * WorldPos.y)) + (_58.g_ViewProj_Row2 * WorldPos.z)) + _58.g_ViewProj_Row3);
|
||||||
|
}
|
||||||
|
|
133
reference/shaders/vert/ocean.vert
Normal file
133
reference/shaders/vert/ocean.vert
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
struct PatchData
|
||||||
|
{
|
||||||
|
vec4 Position;
|
||||||
|
vec4 LODs;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform GlobalVSData
|
||||||
|
{
|
||||||
|
vec4 g_ViewProj_Row0;
|
||||||
|
vec4 g_ViewProj_Row1;
|
||||||
|
vec4 g_ViewProj_Row2;
|
||||||
|
vec4 g_ViewProj_Row3;
|
||||||
|
vec4 g_CamPos;
|
||||||
|
vec4 g_CamRight;
|
||||||
|
vec4 g_CamUp;
|
||||||
|
vec4 g_CamFront;
|
||||||
|
vec4 g_SunDir;
|
||||||
|
vec4 g_SunColor;
|
||||||
|
vec4 g_TimeParams;
|
||||||
|
vec4 g_ResolutionParams;
|
||||||
|
vec4 g_CamAxisRight;
|
||||||
|
vec4 g_FogColor_Distance;
|
||||||
|
vec4 g_ShadowVP_Row0;
|
||||||
|
vec4 g_ShadowVP_Row1;
|
||||||
|
vec4 g_ShadowVP_Row2;
|
||||||
|
vec4 g_ShadowVP_Row3;
|
||||||
|
} _58;
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform Offsets
|
||||||
|
{
|
||||||
|
PatchData Patches[256];
|
||||||
|
} _284;
|
||||||
|
|
||||||
|
layout(binding = 4, std140) uniform GlobalOcean
|
||||||
|
{
|
||||||
|
vec4 OceanScale;
|
||||||
|
vec4 OceanPosition;
|
||||||
|
vec4 InvOceanSize_PatchScale;
|
||||||
|
vec4 NormalTexCoordScale;
|
||||||
|
} _405;
|
||||||
|
|
||||||
|
layout(binding = 1) uniform mediump sampler2D TexLOD;
|
||||||
|
layout(binding = 0) uniform mediump sampler2D TexDisplacement;
|
||||||
|
|
||||||
|
layout(location = 1) in vec4 LODWeights;
|
||||||
|
layout(location = 0) in vec4 Position;
|
||||||
|
layout(location = 0) out vec3 EyeVec;
|
||||||
|
layout(location = 1) out vec4 TexCoord;
|
||||||
|
|
||||||
|
vec2 warp_position()
|
||||||
|
{
|
||||||
|
float vlod = dot(LODWeights, _284.Patches[gl_InstanceID].LODs);
|
||||||
|
vlod = mix(vlod, _284.Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.000000))));
|
||||||
|
float floor_lod = floor(vlod);
|
||||||
|
float fract_lod = (vlod - floor_lod);
|
||||||
|
uint ufloor_lod = uint(floor_lod);
|
||||||
|
uvec4 uPosition = uvec4(Position);
|
||||||
|
uvec2 mask = ((uvec2(1u) << uvec2(ufloor_lod, (ufloor_lod + 1u))) - uvec2(1u));
|
||||||
|
uvec4 rounding;
|
||||||
|
uint _333;
|
||||||
|
uint _345;
|
||||||
|
uint _356;
|
||||||
|
uint _368;
|
||||||
|
vec4 lower_upper_snapped;
|
||||||
|
if ((uPosition.x < 32u))
|
||||||
|
{
|
||||||
|
_333 = mask.x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_333 = 0u;
|
||||||
|
}
|
||||||
|
rounding.x = _333;
|
||||||
|
if ((uPosition.y < 32u))
|
||||||
|
{
|
||||||
|
_345 = mask.x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_345 = 0u;
|
||||||
|
}
|
||||||
|
rounding.y = _345;
|
||||||
|
if ((uPosition.x < 32u))
|
||||||
|
{
|
||||||
|
_356 = mask.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_356 = 0u;
|
||||||
|
}
|
||||||
|
rounding.z = _356;
|
||||||
|
if ((uPosition.y < 32u))
|
||||||
|
{
|
||||||
|
_368 = mask.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_368 = 0u;
|
||||||
|
}
|
||||||
|
rounding.w = _368;
|
||||||
|
lower_upper_snapped = vec4(((uPosition.xyxy + rounding) & (~mask).xxyy));
|
||||||
|
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, vec2(fract_lod));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 lod_factor(vec2 uv)
|
||||||
|
{
|
||||||
|
float level = (textureLod(TexLOD, uv, 0.000000).x * 7.968750);
|
||||||
|
float floor_level = floor(level);
|
||||||
|
float fract_level = (level - floor_level);
|
||||||
|
return vec2(floor_level, fract_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 PatchPos = (_284.Patches[gl_InstanceID].Position.xz * _405.InvOceanSize_PatchScale.zw);
|
||||||
|
vec2 WarpedPos = warp_position();
|
||||||
|
vec2 VertexPos = (PatchPos + WarpedPos);
|
||||||
|
vec2 NormalizedPos = (VertexPos * _405.InvOceanSize_PatchScale.xy);
|
||||||
|
vec2 NormalizedTex = (NormalizedPos * _405.NormalTexCoordScale.zw);
|
||||||
|
vec2 param = NormalizedPos;
|
||||||
|
vec2 lod = lod_factor(param);
|
||||||
|
vec2 Offset = ((_405.InvOceanSize_PatchScale.xy * exp2(lod.x)) * _405.NormalTexCoordScale.zw);
|
||||||
|
vec3 Displacement = mix(textureLod(TexDisplacement, (NormalizedTex + (Offset * 0.500000)), lod.x).yxz, textureLod(TexDisplacement, (NormalizedTex + (Offset * 1.000000)), (lod.x + 1.000000)).yxz, vec3(lod.y));
|
||||||
|
vec3 WorldPos = (vec3(NormalizedPos.x, 0.000000, NormalizedPos.y) + Displacement);
|
||||||
|
WorldPos = (WorldPos * _405.OceanScale.xyz);
|
||||||
|
WorldPos = (WorldPos + _405.OceanPosition.xyz);
|
||||||
|
EyeVec = (WorldPos - _58.g_CamPos.xyz);
|
||||||
|
TexCoord = (vec4(NormalizedTex, (NormalizedTex * _405.NormalTexCoordScale.xy)) + ((_405.InvOceanSize_PatchScale.xyxy * 0.500000) * _405.NormalTexCoordScale.zwzw));
|
||||||
|
gl_Position = ((((_58.g_ViewProj_Row0 * WorldPos.x) + (_58.g_ViewProj_Row1 * WorldPos.y)) + (_58.g_ViewProj_Row2 * WorldPos.z)) + _58.g_ViewProj_Row3);
|
||||||
|
}
|
||||||
|
|
11
reference/shaders/vert/texture_buffer.vert
Normal file
11
reference/shaders/vert/texture_buffer.vert
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_OES_texture_buffer : require
|
||||||
|
|
||||||
|
layout(binding = 4) uniform highp samplerBuffer uSamp;
|
||||||
|
layout(binding = 5, rgba32f) uniform highp readonly imageBuffer uSampo;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = (texelFetch(uSamp, 10) + imageLoad(uSampo, 100));
|
||||||
|
}
|
||||||
|
|
17
reference/shaders/vert/ubo.vert
Normal file
17
reference/shaders/vert/ubo.vert
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform UBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
} _16;
|
||||||
|
|
||||||
|
in vec4 aVertex;
|
||||||
|
out vec3 vNormal;
|
||||||
|
in vec3 aNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = (_16.mvp * aVertex);
|
||||||
|
vNormal = aNormal;
|
||||||
|
}
|
||||||
|
|
51
shaders/comp/atomic.comp
Normal file
51
shaders/comp/atomic.comp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_OES_shader_image_atomic : require
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(r32ui, binding = 0) uniform highp uimage2D uImage;
|
||||||
|
layout(r32i, binding = 1) uniform highp iimage2D iImage;
|
||||||
|
layout(binding = 2, std430) buffer SSBO
|
||||||
|
{
|
||||||
|
uint u32;
|
||||||
|
int i32;
|
||||||
|
} ssbo;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
imageAtomicAdd(uImage, ivec2(1, 5), 1u);
|
||||||
|
imageAtomicOr(uImage, ivec2(1, 5), 1u);
|
||||||
|
imageAtomicXor(uImage, ivec2(1, 5), 1u);
|
||||||
|
imageAtomicAnd(uImage, ivec2(1, 5), 1u);
|
||||||
|
imageAtomicMin(uImage, ivec2(1, 5), 1u);
|
||||||
|
imageAtomicMax(uImage, ivec2(1, 5), 1u);
|
||||||
|
//imageAtomicExchange(uImage, ivec2(1, 5), 1u);
|
||||||
|
imageAtomicCompSwap(uImage, ivec2(1, 5), 10u, 2u);
|
||||||
|
|
||||||
|
imageAtomicAdd(iImage, ivec2(1, 6), 1);
|
||||||
|
imageAtomicOr(iImage, ivec2(1, 6), 1);
|
||||||
|
imageAtomicXor(iImage, ivec2(1, 6), 1);
|
||||||
|
imageAtomicAnd(iImage, ivec2(1, 6), 1);
|
||||||
|
imageAtomicMin(iImage, ivec2(1, 6), 1);
|
||||||
|
imageAtomicMax(iImage, ivec2(1, 6), 1);
|
||||||
|
//imageAtomicExchange(iImage, ivec2(1, 5), 1u);
|
||||||
|
imageAtomicCompSwap(iImage, ivec2(1, 5), 10, 2);
|
||||||
|
|
||||||
|
atomicAdd(ssbo.u32, 1u);
|
||||||
|
atomicOr(ssbo.u32, 1u);
|
||||||
|
atomicXor(ssbo.u32, 1u);
|
||||||
|
atomicAnd(ssbo.u32, 1u);
|
||||||
|
atomicMin(ssbo.u32, 1u);
|
||||||
|
atomicMax(ssbo.u32, 1u);
|
||||||
|
atomicExchange(ssbo.u32, 1u);
|
||||||
|
atomicCompSwap(ssbo.u32, 10u, 2u);
|
||||||
|
|
||||||
|
atomicAdd(ssbo.i32, 1);
|
||||||
|
atomicOr(ssbo.i32, 1);
|
||||||
|
atomicXor(ssbo.i32, 1);
|
||||||
|
atomicAnd(ssbo.i32, 1);
|
||||||
|
atomicMin(ssbo.i32, 1);
|
||||||
|
atomicMax(ssbo.i32, 1);
|
||||||
|
atomicExchange(ssbo.i32, 1);
|
||||||
|
atomicCompSwap(ssbo.i32, 10, 2);
|
||||||
|
}
|
||||||
|
|
55
shaders/comp/bake_gradient.comp
Normal file
55
shaders/comp/bake_gradient.comp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
layout(local_size_x = 8, local_size_y = 8) in;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform sampler2D uHeight;
|
||||||
|
layout(binding = 1) uniform sampler2D uDisplacement;
|
||||||
|
layout(rgba16f, binding = 2) uniform writeonly mediump image2D iHeightDisplacement;
|
||||||
|
layout(rgba16f, binding = 3) uniform writeonly mediump image2D iGradJacobian;
|
||||||
|
|
||||||
|
layout(binding = 4) uniform UBO
|
||||||
|
{
|
||||||
|
vec4 uInvSize;
|
||||||
|
vec4 uScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
mediump float jacobian(mediump vec2 dDdx, mediump vec2 dDdy)
|
||||||
|
{
|
||||||
|
return (1.0 + dDdx.x) * (1.0 + dDdy.y) - dDdx.y * dDdy.x;
|
||||||
|
}
|
||||||
|
#define LAMBDA 1.2
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 uv = (vec2(gl_GlobalInvocationID.xy) * uInvSize.xy).xyxy + 0.5 * uInvSize;
|
||||||
|
|
||||||
|
float h = textureLod(uHeight, uv.xy, 0.0).x;
|
||||||
|
|
||||||
|
// Compute the heightmap gradient by simple differentiation.
|
||||||
|
float x0 = textureLodOffset(uHeight, uv.xy, 0.0, ivec2(-1, 0)).x;
|
||||||
|
float x1 = textureLodOffset(uHeight, uv.xy, 0.0, ivec2(+1, 0)).x;
|
||||||
|
float y0 = textureLodOffset(uHeight, uv.xy, 0.0, ivec2(0, -1)).x;
|
||||||
|
float y1 = textureLodOffset(uHeight, uv.xy, 0.0, ivec2(0, +1)).x;
|
||||||
|
vec2 grad = uScale.xy * 0.5 * vec2(x1 - x0, y1 - y0);
|
||||||
|
|
||||||
|
// Displacement map must be sampled with a different offset since it's a smaller texture.
|
||||||
|
vec2 displacement = LAMBDA * textureLod(uDisplacement, uv.zw, 0.0).xy;
|
||||||
|
|
||||||
|
// Compute jacobian.
|
||||||
|
vec2 dDdx = 0.5 * LAMBDA * (
|
||||||
|
textureLodOffset(uDisplacement, uv.zw, 0.0, ivec2(+1, 0)).xy -
|
||||||
|
textureLodOffset(uDisplacement, uv.zw, 0.0, ivec2(-1, 0)).xy);
|
||||||
|
vec2 dDdy = 0.5 * LAMBDA * (
|
||||||
|
textureLodOffset(uDisplacement, uv.zw, 0.0, ivec2(0, +1)).xy -
|
||||||
|
textureLodOffset(uDisplacement, uv.zw, 0.0, ivec2(0, -1)).xy);
|
||||||
|
float j = jacobian(dDdx * uScale.z, dDdy * uScale.z);
|
||||||
|
|
||||||
|
displacement = vec2(0.0);
|
||||||
|
|
||||||
|
// Read by vertex shader/tess shader.
|
||||||
|
imageStore(iHeightDisplacement, ivec2(gl_GlobalInvocationID.xy), vec4(h, displacement, 0.0));
|
||||||
|
|
||||||
|
// Read by fragment shader.
|
||||||
|
imageStore(iGradJacobian, ivec2(gl_GlobalInvocationID.xy), vec4(grad, j, 0.0));
|
||||||
|
}
|
||||||
|
|
28
shaders/comp/basic.comp
Normal file
28
shaders/comp/basic.comp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 2) buffer SSBO3
|
||||||
|
{
|
||||||
|
uint counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 idata = in_data[ident];
|
||||||
|
if (dot(idata, vec4(1.0, 5.0, 6.0, 2.0)) > 8.2)
|
||||||
|
{
|
||||||
|
out_data[atomicAdd(counter, 1u)] = idata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
26
shaders/comp/culling.comp
Normal file
26
shaders/comp/culling.comp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 4) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
float in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
float out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 2) buffer SSBO3
|
||||||
|
{
|
||||||
|
uint count;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
float idata = in_data[ident];
|
||||||
|
if (idata > 12.0)
|
||||||
|
out_data[atomicAdd(count, 1u)] = idata;
|
||||||
|
}
|
||||||
|
|
31
shaders/comp/dowhile.comp
Normal file
31
shaders/comp/dowhile.comp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
vec4 in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
vec4 idat = in_data[ident];
|
||||||
|
do
|
||||||
|
{
|
||||||
|
idat = mvp * idat;
|
||||||
|
i++;
|
||||||
|
} while(i < 16);
|
||||||
|
|
||||||
|
out_data[ident] = idat;
|
||||||
|
}
|
||||||
|
|
97
shaders/comp/generate_height.comp
Normal file
97
shaders/comp/generate_height.comp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
layout(local_size_x = 64) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer Distribution
|
||||||
|
{
|
||||||
|
vec2 distribution[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer HeightmapFFT
|
||||||
|
{
|
||||||
|
uint heights[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 2, std140) uniform UBO
|
||||||
|
{
|
||||||
|
vec4 uModTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec2 alias(vec2 i, vec2 N)
|
||||||
|
{
|
||||||
|
return mix(i, i - N, greaterThan(i, 0.5 * N));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 cmul(vec4 a, vec4 b)
|
||||||
|
{
|
||||||
|
vec4 r3 = a.yxwz;
|
||||||
|
vec4 r1 = b.xxzz;
|
||||||
|
vec4 R0 = a * r1;
|
||||||
|
vec4 r2 = b.yyww;
|
||||||
|
vec4 R1 = r2 * r3;
|
||||||
|
return R0 + vec4(-R1.x, R1.y, -R1.z, R1.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 cmul(vec2 a, vec2 b)
|
||||||
|
{
|
||||||
|
vec2 r3 = a.yx;
|
||||||
|
vec2 r1 = b.xx;
|
||||||
|
vec2 R0 = a * r1;
|
||||||
|
vec2 r2 = b.yy;
|
||||||
|
vec2 R1 = r2 * r3;
|
||||||
|
return R0 + vec2(-R1.x, R1.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint pack2(vec2 v)
|
||||||
|
{
|
||||||
|
return packHalf2x16(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
uvec2 pack4(vec4 v)
|
||||||
|
{
|
||||||
|
return uvec2(packHalf2x16(v.xy), packHalf2x16(v.zw));
|
||||||
|
}
|
||||||
|
|
||||||
|
uvec2 workaround_mix(uvec2 a, uvec2 b, bvec2 sel)
|
||||||
|
{
|
||||||
|
return uvec2(sel.x ? b.x : a.x, sel.y ? b.y : a.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_heightmap()
|
||||||
|
{
|
||||||
|
uvec2 N = gl_WorkGroupSize.xy * gl_NumWorkGroups.xy;
|
||||||
|
uvec2 i = gl_GlobalInvocationID.xy;
|
||||||
|
// Pick out the negative frequency variant.
|
||||||
|
uvec2 wi = workaround_mix(N - i, uvec2(0u), equal(i, uvec2(0u)));
|
||||||
|
|
||||||
|
// Pick out positive and negative travelling waves.
|
||||||
|
vec2 a = distribution[i.y * N.x + i.x];
|
||||||
|
vec2 b = distribution[wi.y * N.x + wi.x];
|
||||||
|
|
||||||
|
vec2 k = uModTime.xy * alias(vec2(i), vec2(N));
|
||||||
|
float k_len = length(k);
|
||||||
|
|
||||||
|
const float G = 9.81;
|
||||||
|
|
||||||
|
// If this sample runs for hours on end, the cosines of very large numbers will eventually become unstable.
|
||||||
|
// It is fairly easy to fix this by wrapping uTime,
|
||||||
|
// and quantizing w such that wrapping uTime does not change the result.
|
||||||
|
// See Tessendorf's paper for how to do it.
|
||||||
|
// The sqrt(G * k_len) factor represents how fast ocean waves at different frequencies propagate.
|
||||||
|
float w = sqrt(G * k_len) * uModTime.z;
|
||||||
|
float cw = cos(w);
|
||||||
|
float sw = sin(w);
|
||||||
|
|
||||||
|
// Complex multiply to rotate our frequency samples.
|
||||||
|
a = cmul(a, vec2(cw, sw));
|
||||||
|
b = cmul(b, vec2(cw, sw));
|
||||||
|
b = vec2(b.x, -b.y); // Complex conjugate since we picked a frequency with the opposite direction.
|
||||||
|
vec2 res = a + b; // Sum up forward and backwards travelling waves.
|
||||||
|
heights[i.y * N.x + i.x] = pack2(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
generate_heightmap();
|
||||||
|
}
|
||||||
|
|
12
shaders/comp/image.comp
Normal file
12
shaders/comp/image.comp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(rgba8, binding = 0) uniform readonly mediump image2D uImageIn;
|
||||||
|
layout(rgba8, binding = 1) uniform writeonly mediump image2D uImageOut;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 v = imageLoad(uImageIn, ivec2(gl_GlobalInvocationID.xy) + imageSize(uImageIn));
|
||||||
|
imageStore(uImageOut, ivec2(gl_GlobalInvocationID.xy), v);
|
||||||
|
}
|
||||||
|
|
55
shaders/comp/inout-struct.comp
Normal file
55
shaders/comp/inout-struct.comp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) writeonly buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 data[];
|
||||||
|
} outdata;
|
||||||
|
|
||||||
|
layout(std430, binding = 1) readonly buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 data[];
|
||||||
|
} indata;
|
||||||
|
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
vec4 a;
|
||||||
|
vec4 b;
|
||||||
|
vec4 c;
|
||||||
|
vec4 d;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 2) readonly buffer SSBO3
|
||||||
|
{
|
||||||
|
Foo foos[];
|
||||||
|
} foobar;
|
||||||
|
|
||||||
|
vec4 bar(Foo foo)
|
||||||
|
{
|
||||||
|
return foo.a + foo.b + foo.c + foo.d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void baz(out Foo foo)
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
foo.a = indata.data[4u * ident + 0u];
|
||||||
|
foo.b = indata.data[4u * ident + 1u];
|
||||||
|
foo.c = indata.data[4u * ident + 2u];
|
||||||
|
foo.d = indata.data[4u * ident + 3u];
|
||||||
|
}
|
||||||
|
|
||||||
|
void meow(inout Foo foo)
|
||||||
|
{
|
||||||
|
foo.a += 10.0;
|
||||||
|
foo.b += 20.0;
|
||||||
|
foo.c += 30.0;
|
||||||
|
foo.d += 40.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Foo foo;
|
||||||
|
baz(foo);
|
||||||
|
meow(foo);
|
||||||
|
outdata.data[gl_GlobalInvocationID.x] = bar(foo) + bar(foobar.foos[gl_GlobalInvocationID.x]);
|
||||||
|
}
|
18
shaders/comp/insert.comp
Normal file
18
shaders/comp/insert.comp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) writeonly buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 v;
|
||||||
|
v.x = 10.0;
|
||||||
|
v.y = 30.0;
|
||||||
|
v.z = 70.0;
|
||||||
|
v.w = 90.0;
|
||||||
|
out_data[gl_GlobalInvocationID.x] = v;
|
||||||
|
out_data[gl_GlobalInvocationID.x].y = 20.0;
|
||||||
|
}
|
66
shaders/comp/loop.comp
Normal file
66
shaders/comp/loop.comp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
vec4 in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 idat = in_data[ident];
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
while (k < 10)
|
||||||
|
{
|
||||||
|
idat *= 2.0;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0u; i < 16u; i++, k++)
|
||||||
|
for (uint j = 0u; j < 30u; j++)
|
||||||
|
idat = mvp * idat;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
k++;
|
||||||
|
if (k > 10)
|
||||||
|
{
|
||||||
|
k += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
k += 3;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
k += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
k++;
|
||||||
|
} while (k > 10);
|
||||||
|
|
||||||
|
int l = 0;
|
||||||
|
for (;; l++)
|
||||||
|
{
|
||||||
|
if (l == 5)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
idat += 1.0;
|
||||||
|
}
|
||||||
|
out_data[ident] = idat;
|
||||||
|
}
|
||||||
|
|
14
shaders/comp/mat3.comp
Normal file
14
shaders/comp/mat3.comp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
mat3 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
out_data[ident] = mat3(vec3(10.0), vec3(20.0), vec3(40.0));
|
||||||
|
}
|
||||||
|
|
23
shaders/comp/modf.comp
Normal file
23
shaders/comp/modf.comp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
vec4 in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 i;
|
||||||
|
//vec4 v = frexp(in_data[ident], i);
|
||||||
|
//out_data[ident] = ldexp(v, i);
|
||||||
|
vec4 v = modf(in_data[ident], i);
|
||||||
|
out_data[ident] = v;
|
||||||
|
}
|
||||||
|
|
33
shaders/comp/return.comp
Normal file
33
shaders/comp/return.comp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
|
||||||
|
if (ident == 2u)
|
||||||
|
{
|
||||||
|
out_data[ident] = vec4(20.0);
|
||||||
|
}
|
||||||
|
else if (ident == 4u)
|
||||||
|
{
|
||||||
|
out_data[ident] = vec4(10.0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
if (i == 10)
|
||||||
|
break;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_data[ident] = vec4(10.0);
|
||||||
|
}
|
||||||
|
|
27
shaders/comp/shared.comp
Normal file
27
shaders/comp/shared.comp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 4) in;
|
||||||
|
|
||||||
|
shared float sShared[gl_WorkGroupSize.x];
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
float in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
float out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
float idata = in_data[ident];
|
||||||
|
|
||||||
|
sShared[gl_LocalInvocationIndex] = idata;
|
||||||
|
memoryBarrierShared();
|
||||||
|
barrier();
|
||||||
|
|
||||||
|
out_data[ident] = sShared[gl_WorkGroupSize.x - gl_LocalInvocationIndex - 1u];
|
||||||
|
}
|
||||||
|
|
24
shaders/comp/struct-layout.comp
Normal file
24
shaders/comp/struct-layout.comp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
mat4 m;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
Foo in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
Foo out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
out_data[ident].m = in_data[ident].m * in_data[ident].m;
|
||||||
|
}
|
||||||
|
|
69
shaders/comp/struct-packing.comp
Normal file
69
shaders/comp/struct-packing.comp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
struct S0
|
||||||
|
{
|
||||||
|
vec2 a[1];
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S1
|
||||||
|
{
|
||||||
|
vec3 a;
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S2
|
||||||
|
{
|
||||||
|
vec3 a[1];
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S3
|
||||||
|
{
|
||||||
|
vec2 a;
|
||||||
|
float b;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Content
|
||||||
|
{
|
||||||
|
S0 m0s[1];
|
||||||
|
S1 m1s[1];
|
||||||
|
S2 m2s[1];
|
||||||
|
S0 m0;
|
||||||
|
S1 m1;
|
||||||
|
S2 m2;
|
||||||
|
|
||||||
|
S3 m3;
|
||||||
|
float m4;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0, std140) buffer SSBO0
|
||||||
|
{
|
||||||
|
Content content;
|
||||||
|
Content content1[2];
|
||||||
|
Content content2;
|
||||||
|
float array[];
|
||||||
|
} ssbo_140;
|
||||||
|
|
||||||
|
layout(binding = 1, std430) buffer SSBO1
|
||||||
|
{
|
||||||
|
Content content;
|
||||||
|
Content content1[2];
|
||||||
|
Content content2;
|
||||||
|
|
||||||
|
layout(column_major) mat2 m0;
|
||||||
|
layout(column_major) mat2 m1;
|
||||||
|
layout(column_major) mat2x3 m2[4];
|
||||||
|
layout(column_major) mat3x2 m3;
|
||||||
|
layout(row_major) mat2 m4;
|
||||||
|
layout(row_major) mat2 m5[9];
|
||||||
|
layout(row_major) mat2x3 m6[4][2];
|
||||||
|
layout(row_major) mat3x2 m7;
|
||||||
|
float array[];
|
||||||
|
} ssbo_430;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
ssbo_430.content = ssbo_140.content;
|
||||||
|
}
|
||||||
|
|
40
shaders/comp/torture-loop.comp
Normal file
40
shaders/comp/torture-loop.comp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) readonly buffer SSBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
vec4 in_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) writeonly buffer SSBO2
|
||||||
|
{
|
||||||
|
vec4 out_data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uint ident = gl_GlobalInvocationID.x;
|
||||||
|
vec4 idat = in_data[ident];
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
// Continue with side effects.
|
||||||
|
while (++k < 10)
|
||||||
|
{
|
||||||
|
idat *= 2.0;
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Again used here ...
|
||||||
|
for (uint i = 0u; i < 16u; i++, k++)
|
||||||
|
for (uint j = 0u; j < 30u; j++)
|
||||||
|
idat = mvp * idat;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
k++;
|
||||||
|
} while (k > 10);
|
||||||
|
out_data[ident] = idat;
|
||||||
|
}
|
||||||
|
|
17
shaders/comp/udiv.comp
Normal file
17
shaders/comp/udiv.comp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 310 es
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) buffer SSBO
|
||||||
|
{
|
||||||
|
uint inputs[];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 0) buffer SSBO2
|
||||||
|
{
|
||||||
|
uint outputs[];
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
outputs[gl_GlobalInvocationID.x] = inputs[gl_GlobalInvocationID.x] / 29u;
|
||||||
|
}
|
13
shaders/frag/basic.frag
Normal file
13
shaders/frag/basic.frag
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
in vec4 vColor;
|
||||||
|
in vec2 vTex;
|
||||||
|
layout(binding = 0) uniform sampler2D uTex;
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vColor * texture(uTex, vTex);
|
||||||
|
}
|
||||||
|
|
21
shaders/frag/constant-array.frag
Normal file
21
shaders/frag/constant-array.frag
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
layout(location = 0) flat in int index;
|
||||||
|
|
||||||
|
struct Foobar { float a; float b; };
|
||||||
|
|
||||||
|
vec4 resolve(Foobar f)
|
||||||
|
{
|
||||||
|
return vec4(f.a + f.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
const vec4 foo[3] = vec4[](vec4(1.0), vec4(2.0), vec4(3.0));
|
||||||
|
const vec4 foobars[2][2] = vec4[][](vec4[](vec4(1.0), vec4(2.0)), vec4[](vec4(8.0), vec4(10.0)));
|
||||||
|
const Foobar foos[2] = Foobar[](Foobar(10.0, 40.0), Foobar(90.0, 70.0));
|
||||||
|
|
||||||
|
FragColor = foo[index] + foobars[index][index + 1] + resolve(Foobar(10.0, 20.0)) + resolve(foos[index]);
|
||||||
|
}
|
27
shaders/frag/flush_params.frag
Normal file
27
shaders/frag/flush_params.frag
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
struct Structy
|
||||||
|
{
|
||||||
|
vec4 c;
|
||||||
|
};
|
||||||
|
|
||||||
|
void foo2(out Structy f)
|
||||||
|
{
|
||||||
|
f.c = vec4(10.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Structy foo()
|
||||||
|
{
|
||||||
|
Structy f;
|
||||||
|
foo2(f);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Structy s = foo();
|
||||||
|
FragColor = s.c;
|
||||||
|
}
|
162
shaders/frag/ground.frag
Executable file
162
shaders/frag/ground.frag
Executable file
@ -0,0 +1,162 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
#define DEBUG_NONE 0
|
||||||
|
#define DEBUG_DIFFUSE 1
|
||||||
|
#define DEBUG_SPECULAR 2
|
||||||
|
#define DEBUG_LIGHTING 3
|
||||||
|
#define DEBUG_FOG 4
|
||||||
|
#define DEBUG DEBUG_NONE
|
||||||
|
|
||||||
|
#define FORWARD 0
|
||||||
|
#define DEFERRED 1
|
||||||
|
#define DEFERRED_VTEX 2
|
||||||
|
|
||||||
|
float saturate(float x) { return clamp(x, 0.0, 1.0); }
|
||||||
|
|
||||||
|
layout(std140, binding = 4) uniform GlobalPSData
|
||||||
|
{
|
||||||
|
vec4 g_CamPos;
|
||||||
|
vec4 g_SunDir;
|
||||||
|
vec4 g_SunColor;
|
||||||
|
vec4 g_ResolutionParams;
|
||||||
|
vec4 g_TimeParams;
|
||||||
|
vec4 g_FogColor_Distance;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec4 ComputeFogFactor(vec3 WorldPos)
|
||||||
|
{
|
||||||
|
vec4 FogData;
|
||||||
|
vec3 vEye = WorldPos - g_CamPos.xyz;
|
||||||
|
vec3 nEye = normalize(vEye);
|
||||||
|
FogData.w = exp(-dot(vEye, vEye) * g_FogColor_Distance.w * 0.75);
|
||||||
|
|
||||||
|
float fog_sun_factor = pow(saturate(dot(nEye, g_SunDir.xyz)), 8.0);
|
||||||
|
FogData.xyz = mix(vec3(1.0, 1.0, 1.0), vec3(0.6, 0.6, 0.9), nEye.y * 0.5 + 0.5);
|
||||||
|
FogData.xyz = mix(FogData.xyz, vec3(0.95, 0.87, 0.78), fog_sun_factor);
|
||||||
|
return FogData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyFog(inout vec3 Color, vec4 FogData)
|
||||||
|
{
|
||||||
|
Color = mix(FogData.xyz, Color, FogData.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyLighting(inout mediump vec3 Color, mediump float DiffuseFactor)
|
||||||
|
{
|
||||||
|
mediump vec3 DiffuseLight = g_SunColor.xyz * DiffuseFactor;
|
||||||
|
mediump vec3 AmbientLight = vec3(0.2, 0.35, 0.55) * 0.5;
|
||||||
|
mediump vec3 Lighting = DiffuseLight + AmbientLight;
|
||||||
|
#if DEBUG == DEBUG_LIGHTING
|
||||||
|
Color = Lighting;
|
||||||
|
#else
|
||||||
|
Color *= Lighting;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPECULAR 0
|
||||||
|
#define GLOSSMAP 0
|
||||||
|
|
||||||
|
void ApplySpecular(inout mediump vec3 Color, mediump vec3 EyeVec, mediump vec3 Normal, mediump vec3 SpecularColor, mediump float Shininess, mediump float FresnelAmount)
|
||||||
|
{
|
||||||
|
mediump vec3 HalfAngle = normalize(-EyeVec + g_SunDir.xyz);
|
||||||
|
|
||||||
|
mediump float v_dot_h = saturate(dot(HalfAngle, -EyeVec));
|
||||||
|
mediump float n_dot_l = saturate(dot(Normal, g_SunDir.xyz));
|
||||||
|
mediump float n_dot_h = saturate(dot(Normal, HalfAngle));
|
||||||
|
mediump float n_dot_v = saturate(dot(-EyeVec, Normal));
|
||||||
|
mediump float h_dot_l = saturate(dot(g_SunDir.xyz, HalfAngle));
|
||||||
|
|
||||||
|
const mediump float roughness_value = 0.25;
|
||||||
|
|
||||||
|
mediump float r_sq = roughness_value * roughness_value;
|
||||||
|
mediump float n_dot_h_sq = n_dot_h * n_dot_h;
|
||||||
|
mediump float roughness_a = 1.0 / (4.0 * r_sq * n_dot_h_sq * n_dot_h_sq);
|
||||||
|
mediump float roughness_b = n_dot_h_sq - 1.0;
|
||||||
|
mediump float roughness_c = r_sq * n_dot_h_sq;
|
||||||
|
mediump float roughness = saturate(roughness_a * exp(roughness_b / roughness_c));
|
||||||
|
|
||||||
|
FresnelAmount = 0.5;
|
||||||
|
mediump float fresnel_term = pow(1.0 - n_dot_v, 5.0) * (1.0 - FresnelAmount) + FresnelAmount;
|
||||||
|
|
||||||
|
mediump float geo_numerator = 2.0 * n_dot_h;
|
||||||
|
mediump float geo_denominator = 1.0 / v_dot_h;
|
||||||
|
mediump float geo_term = min(1.0, min(n_dot_v, n_dot_l) * geo_numerator * geo_denominator);
|
||||||
|
|
||||||
|
#if SPECULAR || GLOSSMAP
|
||||||
|
Color += SpecularColor * g_SunColor.xyz * fresnel_term * roughness * n_dot_l * geo_term / (n_dot_v * n_dot_l + 0.0001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Color = vec3(0.025 * 1.0 / (n_dot_v * n_dot_l));
|
||||||
|
}
|
||||||
|
layout(location = 0) in vec2 TexCoord;
|
||||||
|
layout(location = 1) in vec3 EyeVec;
|
||||||
|
|
||||||
|
layout(binding = 2) uniform sampler2D TexNormalmap;
|
||||||
|
//layout(binding = 3) uniform sampler2D TexScatteringLUT;
|
||||||
|
|
||||||
|
#define DIFFUSE_ONLY 0
|
||||||
|
#define GLOBAL_RENDERER DEFERRED
|
||||||
|
#define OUTPUT_FEEDBACK_TEXTURE 0
|
||||||
|
|
||||||
|
#if DIFFUSE_ONLY
|
||||||
|
layout(location = 0) out vec4 ColorOut;
|
||||||
|
layout(location = 1) out vec4 NormalOut;
|
||||||
|
#else
|
||||||
|
layout(location = 0) out vec4 AlbedoOut;
|
||||||
|
layout(location = 1) out vec4 SpecularOut;
|
||||||
|
layout(location = 2) out vec4 NormalOut;
|
||||||
|
layout(location = 3) out vec4 LightingOut;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Resolve(vec3 Albedo, vec3 Normal, float Roughness, float Metallic)
|
||||||
|
{
|
||||||
|
#if (GLOBAL_RENDERER == FORWARD) || OUTPUT_FEEDBACK_TEXTURE
|
||||||
|
float Lighting = saturate(dot(Normal, normalize(vec3(1.0, 0.5, 1.0))));
|
||||||
|
ColorOut.xyz = Albedo * Lighting;
|
||||||
|
ColorOut.w = 1.0;
|
||||||
|
#elif DIFFUSE_ONLY
|
||||||
|
ColorOut = vec4(Albedo, 0.0);
|
||||||
|
NormalOut.xyz = Normal * 0.5 + 0.5;
|
||||||
|
NormalOut.w = 1.0;
|
||||||
|
|
||||||
|
// linearize and map to 0..255 range
|
||||||
|
ColorOut.w = -0.003921569 / (gl_FragCoord.z - 1.003921569);
|
||||||
|
ColorOut.w = log2(1.0 + saturate(length(EyeVec.xyz) / 200.0));
|
||||||
|
ColorOut.w -= 1.0 / 255.0;
|
||||||
|
#else
|
||||||
|
LightingOut = vec4(0.0);
|
||||||
|
NormalOut = vec4(Normal * 0.5 + 0.5, 0.0);
|
||||||
|
SpecularOut = vec4(Roughness, Metallic, 0.0, 0.0);
|
||||||
|
AlbedoOut = vec4(Albedo, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 Normal = texture(TexNormalmap, TexCoord).xyz * 2.0 - 1.0;
|
||||||
|
Normal = normalize(Normal);
|
||||||
|
|
||||||
|
vec2 scatter_uv;
|
||||||
|
scatter_uv.x = saturate(length(EyeVec) / 1000.0);
|
||||||
|
|
||||||
|
vec3 nEye = normalize(EyeVec);
|
||||||
|
scatter_uv.y = 0.0; //nEye.x * 0.5 + 0.5;
|
||||||
|
|
||||||
|
vec3 Color = vec3(0.1, 0.3, 0.1);
|
||||||
|
vec3 grass = vec3(0.1, 0.3, 0.1);
|
||||||
|
vec3 dirt = vec3(0.1, 0.1, 0.1);
|
||||||
|
vec3 snow = vec3(0.8, 0.8, 0.8);
|
||||||
|
|
||||||
|
float grass_snow = smoothstep(0.0, 0.15, (g_CamPos.y + EyeVec.y) / 200.0);
|
||||||
|
vec3 base = mix(grass, snow, grass_snow);
|
||||||
|
|
||||||
|
float edge = smoothstep(0.7, 0.75, Normal.y);
|
||||||
|
Color = mix(dirt, base, edge);
|
||||||
|
Color *= Color;
|
||||||
|
|
||||||
|
float Roughness = 1.0 - edge * grass_snow;
|
||||||
|
|
||||||
|
Resolve(Color, Normal, Roughness, 0.0);
|
||||||
|
}
|
||||||
|
|
20
shaders/frag/mix.frag
Normal file
20
shaders/frag/mix.frag
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 vIn0;
|
||||||
|
layout(location = 1) in vec4 vIn1;
|
||||||
|
layout(location = 2) in float vIn2;
|
||||||
|
layout(location = 3) in float vIn3;
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
bvec4 l = bvec4(false, true, false, false);
|
||||||
|
FragColor = mix(vIn0, vIn1, l);
|
||||||
|
|
||||||
|
bool f = true;
|
||||||
|
FragColor = vec4(mix(vIn2, vIn3, f));
|
||||||
|
|
||||||
|
FragColor = f ? vIn0 : vIn1;
|
||||||
|
FragColor = vec4(f ? vIn2 : vIn3);
|
||||||
|
}
|
20
shaders/frag/pls.frag
Normal file
20
shaders/frag/pls.frag
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 PLSIn0;
|
||||||
|
layout(location = 1) in vec4 PLSIn1;
|
||||||
|
in vec4 PLSIn2;
|
||||||
|
in vec4 PLSIn3;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 PLSOut0;
|
||||||
|
layout(location = 1) out vec4 PLSOut1;
|
||||||
|
layout(location = 2) out vec4 PLSOut2;
|
||||||
|
layout(location = 3) out vec4 PLSOut3;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
PLSOut0 = 2.0 * PLSIn0;
|
||||||
|
PLSOut1 = 6.0 * PLSIn1;
|
||||||
|
PLSOut2 = 7.0 * PLSIn2;
|
||||||
|
PLSOut3 = 4.0 * PLSIn3;
|
||||||
|
}
|
18
shaders/frag/sampler.frag
Normal file
18
shaders/frag/sampler.frag
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
in vec4 vColor;
|
||||||
|
in vec2 vTex;
|
||||||
|
layout(binding = 0) uniform sampler2D uTex;
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
vec4 sample_texture(sampler2D tex, vec2 uv)
|
||||||
|
{
|
||||||
|
return texture(tex, uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vColor * sample_texture(uTex, vTex);
|
||||||
|
}
|
||||||
|
|
17
shaders/frag/swizzle.frag
Normal file
17
shaders/frag/swizzle.frag
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) uniform sampler2D samp;
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
layout(location = 1) in vec3 vNormal;
|
||||||
|
layout(location = 2) in vec2 vUV;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vec4(texture(samp, vUV).xyz, 1.0);
|
||||||
|
FragColor = vec4(texture(samp, vUV).xz, 1.0, 4.0);
|
||||||
|
FragColor = vec4(texture(samp, vUV).xx, texture(samp, vUV + vec2(0.1)).yy);
|
||||||
|
FragColor = vec4(vNormal, 1.0);
|
||||||
|
FragColor = vec4(vNormal + 1.8, 1.0);
|
||||||
|
FragColor = vec4(vUV, vUV + 1.8);
|
||||||
|
}
|
24
shaders/frag/ubo_layout.frag
Normal file
24
shaders/frag/ubo_layout.frag
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 FragColor;
|
||||||
|
|
||||||
|
struct Str
|
||||||
|
{
|
||||||
|
mat4 foo;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform UBO1
|
||||||
|
{
|
||||||
|
layout(row_major) Str foo;
|
||||||
|
} ubo1;
|
||||||
|
|
||||||
|
layout(binding = 1, std140) uniform UBO2
|
||||||
|
{
|
||||||
|
layout(column_major) Str foo;
|
||||||
|
} ubo0;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = ubo1.foo.foo[0] + ubo0.foo.foo[0];
|
||||||
|
}
|
28
shaders/geom/basic.geom
Normal file
28
shaders/geom/basic.geom
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_geometry_shader : require
|
||||||
|
|
||||||
|
layout(triangles, invocations = 4) in;
|
||||||
|
layout(triangle_strip, max_vertices = 3) out;
|
||||||
|
|
||||||
|
in VertexData {
|
||||||
|
vec3 normal;
|
||||||
|
} vin[];
|
||||||
|
|
||||||
|
out vec3 vNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = gl_in[0].gl_Position;
|
||||||
|
vNormal = vin[0].normal + float(gl_InvocationID);
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
gl_Position = gl_in[1].gl_Position;
|
||||||
|
vNormal = vin[1].normal + 4.0 * float(gl_InvocationID);
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
gl_Position = gl_in[2].gl_Position;
|
||||||
|
vNormal = vin[2].normal + 2.0 * float(gl_InvocationID);
|
||||||
|
EmitVertex();
|
||||||
|
|
||||||
|
EndPrimitive();
|
||||||
|
}
|
17
shaders/tesc/basic.tesc
Normal file
17
shaders/tesc/basic.tesc
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
|
||||||
|
patch out vec3 vFoo;
|
||||||
|
|
||||||
|
layout(vertices = 1) out;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_TessLevelInner[0] = 8.9;
|
||||||
|
gl_TessLevelInner[1] = 6.9;
|
||||||
|
gl_TessLevelOuter[0] = 8.9;
|
||||||
|
gl_TessLevelOuter[1] = 6.9;
|
||||||
|
gl_TessLevelOuter[2] = 3.9;
|
||||||
|
gl_TessLevelOuter[3] = 4.9;
|
||||||
|
vFoo = vec3(1.0);
|
||||||
|
}
|
115
shaders/tesc/water_tess.tesc
Normal file
115
shaders/tesc/water_tess.tesc
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
|
||||||
|
layout(vertices = 1) out;
|
||||||
|
in vec2 vPatchPosBase[];
|
||||||
|
|
||||||
|
layout(std140) uniform UBO
|
||||||
|
{
|
||||||
|
vec4 uScale;
|
||||||
|
highp vec3 uCamPos;
|
||||||
|
vec2 uPatchSize;
|
||||||
|
vec2 uMaxTessLevel;
|
||||||
|
float uDistanceMod;
|
||||||
|
vec4 uFrustum[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
patch out vec2 vOutPatchPosBase;
|
||||||
|
patch out vec4 vPatchLods;
|
||||||
|
|
||||||
|
float lod_factor(vec2 pos_)
|
||||||
|
{
|
||||||
|
vec2 pos = pos_ * uScale.xy;
|
||||||
|
vec3 dist_to_cam = uCamPos - vec3(pos.x, 0.0, pos.y);
|
||||||
|
float level = log2((length(dist_to_cam) + 0.0001) * uDistanceMod);
|
||||||
|
return clamp(level, 0.0, uMaxTessLevel.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float tess_level(float lod)
|
||||||
|
{
|
||||||
|
return uMaxTessLevel.y * exp2(-lod);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 tess_level(vec4 lod)
|
||||||
|
{
|
||||||
|
return uMaxTessLevel.y * exp2(-lod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guard band for vertex displacement.
|
||||||
|
#define GUARD_BAND 10.0
|
||||||
|
bool frustum_cull(vec2 p0)
|
||||||
|
{
|
||||||
|
vec2 min_xz = (p0 - GUARD_BAND) * uScale.xy;
|
||||||
|
vec2 max_xz = (p0 + uPatchSize + GUARD_BAND) * uScale.xy;
|
||||||
|
|
||||||
|
vec3 bb_min = vec3(min_xz.x, -GUARD_BAND, min_xz.y);
|
||||||
|
vec3 bb_max = vec3(max_xz.x, +GUARD_BAND, max_xz.y);
|
||||||
|
vec3 center = 0.5 * (bb_min + bb_max);
|
||||||
|
float radius = 0.5 * length(bb_max - bb_min);
|
||||||
|
|
||||||
|
vec3 f0 = vec3(
|
||||||
|
dot(uFrustum[0], vec4(center, 1.0)),
|
||||||
|
dot(uFrustum[1], vec4(center, 1.0)),
|
||||||
|
dot(uFrustum[2], vec4(center, 1.0)));
|
||||||
|
|
||||||
|
vec3 f1 = vec3(
|
||||||
|
dot(uFrustum[3], vec4(center, 1.0)),
|
||||||
|
dot(uFrustum[4], vec4(center, 1.0)),
|
||||||
|
dot(uFrustum[5], vec4(center, 1.0)));
|
||||||
|
|
||||||
|
return !(any(lessThanEqual(f0, vec3(-radius))) || any(lessThanEqual(f1, vec3(-radius))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_tess_levels(vec2 p0)
|
||||||
|
{
|
||||||
|
vOutPatchPosBase = p0;
|
||||||
|
|
||||||
|
float l00 = lod_factor(p0 + vec2(-0.5, -0.5) * uPatchSize);
|
||||||
|
float l10 = lod_factor(p0 + vec2(+0.5, -0.5) * uPatchSize);
|
||||||
|
float l20 = lod_factor(p0 + vec2(+1.5, -0.5) * uPatchSize);
|
||||||
|
float l01 = lod_factor(p0 + vec2(-0.5, +0.5) * uPatchSize);
|
||||||
|
float l11 = lod_factor(p0 + vec2(+0.5, +0.5) * uPatchSize);
|
||||||
|
float l21 = lod_factor(p0 + vec2(+1.5, +0.5) * uPatchSize);
|
||||||
|
float l02 = lod_factor(p0 + vec2(-0.5, +1.5) * uPatchSize);
|
||||||
|
float l12 = lod_factor(p0 + vec2(+0.5, +1.5) * uPatchSize);
|
||||||
|
float l22 = lod_factor(p0 + vec2(+1.5, +1.5) * uPatchSize);
|
||||||
|
|
||||||
|
vec4 lods = vec4(
|
||||||
|
dot(vec4(l01, l11, l02, l12), vec4(0.25)),
|
||||||
|
dot(vec4(l00, l10, l01, l11), vec4(0.25)),
|
||||||
|
dot(vec4(l10, l20, l11, l21), vec4(0.25)),
|
||||||
|
dot(vec4(l11, l21, l12, l22), vec4(0.25)));
|
||||||
|
|
||||||
|
vPatchLods = lods;
|
||||||
|
|
||||||
|
vec4 outer_lods = min(lods.xyzw, lods.yzwx);
|
||||||
|
vec4 levels = tess_level(outer_lods);
|
||||||
|
gl_TessLevelOuter[0] = levels.x;
|
||||||
|
gl_TessLevelOuter[1] = levels.y;
|
||||||
|
gl_TessLevelOuter[2] = levels.z;
|
||||||
|
gl_TessLevelOuter[3] = levels.w;
|
||||||
|
|
||||||
|
float min_lod = min(min(lods.x, lods.y), min(lods.z, lods.w));
|
||||||
|
float inner = tess_level(min(min_lod, l11));
|
||||||
|
gl_TessLevelInner[0] = inner;
|
||||||
|
gl_TessLevelInner[1] = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 p0 = vPatchPosBase[0];
|
||||||
|
if (!frustum_cull(p0))
|
||||||
|
{
|
||||||
|
gl_TessLevelOuter[0] = -1.0;
|
||||||
|
gl_TessLevelOuter[1] = -1.0;
|
||||||
|
gl_TessLevelOuter[2] = -1.0;
|
||||||
|
gl_TessLevelOuter[3] = -1.0;
|
||||||
|
gl_TessLevelInner[0] = -1.0;
|
||||||
|
gl_TessLevelInner[1] = -1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compute_tess_levels(p0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
65
shaders/tese/water_tess.tese
Normal file
65
shaders/tese/water_tess.tese
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_EXT_tessellation_shader : require
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(cw, quads, fractional_even_spacing) in;
|
||||||
|
|
||||||
|
patch in vec2 vOutPatchPosBase;
|
||||||
|
patch in vec4 vPatchLods;
|
||||||
|
|
||||||
|
layout(binding = 1, std140) uniform UBO
|
||||||
|
{
|
||||||
|
mat4 uMVP;
|
||||||
|
vec4 uScale;
|
||||||
|
vec2 uInvScale;
|
||||||
|
vec3 uCamPos;
|
||||||
|
vec2 uPatchSize;
|
||||||
|
vec2 uInvHeightmapSize;
|
||||||
|
};
|
||||||
|
layout(binding = 0) uniform mediump sampler2D uHeightmapDisplacement;
|
||||||
|
|
||||||
|
highp out vec3 vWorld;
|
||||||
|
highp out vec4 vGradNormalTex;
|
||||||
|
|
||||||
|
vec2 lerp_vertex(vec2 tess_coord)
|
||||||
|
{
|
||||||
|
return vOutPatchPosBase + tess_coord * uPatchSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
mediump vec2 lod_factor(vec2 tess_coord)
|
||||||
|
{
|
||||||
|
mediump vec2 x = mix(vPatchLods.yx, vPatchLods.zw, tess_coord.x);
|
||||||
|
mediump float level = mix(x.x, x.y, tess_coord.y);
|
||||||
|
mediump float floor_level = floor(level);
|
||||||
|
mediump float fract_level = level - floor_level;
|
||||||
|
return vec2(floor_level, fract_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
mediump vec3 sample_height_displacement(vec2 uv, vec2 off, mediump vec2 lod)
|
||||||
|
{
|
||||||
|
return mix(
|
||||||
|
textureLod(uHeightmapDisplacement, uv + 0.5 * off, lod.x).xyz,
|
||||||
|
textureLod(uHeightmapDisplacement, uv + 1.0 * off, lod.x + 1.0).xyz,
|
||||||
|
lod.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 tess_coord = gl_TessCoord.xy;
|
||||||
|
vec2 pos = lerp_vertex(tess_coord);
|
||||||
|
mediump vec2 lod = lod_factor(tess_coord);
|
||||||
|
|
||||||
|
vec2 tex = pos * uInvHeightmapSize.xy;
|
||||||
|
pos *= uScale.xy;
|
||||||
|
|
||||||
|
mediump float delta_mod = exp2(lod.x);
|
||||||
|
vec2 off = uInvHeightmapSize.xy * delta_mod;
|
||||||
|
|
||||||
|
vGradNormalTex = vec4(tex + 0.5 * uInvHeightmapSize.xy, tex * uScale.zw);
|
||||||
|
vec3 height_displacement = sample_height_displacement(tex, off, lod);
|
||||||
|
|
||||||
|
pos += height_displacement.yz;
|
||||||
|
vWorld = vec3(pos.x, height_displacement.x, pos.y);
|
||||||
|
gl_Position = uMVP * vec4(vWorld, 1.0);
|
||||||
|
}
|
||||||
|
|
15
shaders/vert/basic.vert
Normal file
15
shaders/vert/basic.vert
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
layout(std140) uniform UBO
|
||||||
|
{
|
||||||
|
uniform mat4 uMVP;
|
||||||
|
};
|
||||||
|
in vec4 aVertex;
|
||||||
|
in vec3 aNormal;
|
||||||
|
out vec3 vNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = uMVP * aVertex;
|
||||||
|
vNormal = aNormal;
|
||||||
|
}
|
196
shaders/vert/ground.vert
Executable file
196
shaders/vert/ground.vert
Executable file
@ -0,0 +1,196 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
#define YFLIP 0
|
||||||
|
#define SPECULAR 0
|
||||||
|
#define GLOSSMAP 0
|
||||||
|
|
||||||
|
#define DEBUG_NONE 0
|
||||||
|
#define DEBUG_DIFFUSE 1
|
||||||
|
#define DEBUG_SPECULAR 2
|
||||||
|
#define DEBUG_LIGHTING 3
|
||||||
|
#define DEBUG_FOG 4
|
||||||
|
#define DEBUG DEBUG_NONE
|
||||||
|
|
||||||
|
#define FORWARD 0
|
||||||
|
#define DEFERRED 1
|
||||||
|
#define DEFERRED_VTEX 2
|
||||||
|
|
||||||
|
float saturate(float x) { return clamp(x, 0.0, 1.0); }
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform GlobalVSData
|
||||||
|
{
|
||||||
|
vec4 g_ViewProj_Row0;
|
||||||
|
vec4 g_ViewProj_Row1;
|
||||||
|
vec4 g_ViewProj_Row2;
|
||||||
|
vec4 g_ViewProj_Row3;
|
||||||
|
vec4 g_CamPos;
|
||||||
|
vec4 g_CamRight;
|
||||||
|
vec4 g_CamUp;
|
||||||
|
vec4 g_CamFront;
|
||||||
|
vec4 g_SunDir;
|
||||||
|
vec4 g_SunColor;
|
||||||
|
vec4 g_TimeParams;
|
||||||
|
vec4 g_ResolutionParams;
|
||||||
|
vec4 g_CamAxisRight;
|
||||||
|
vec4 g_FogColor_Distance;
|
||||||
|
vec4 g_ShadowVP_Row0;
|
||||||
|
vec4 g_ShadowVP_Row1;
|
||||||
|
vec4 g_ShadowVP_Row2;
|
||||||
|
vec4 g_ShadowVP_Row3;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec4 ComputeFogFactor(vec3 WorldPos)
|
||||||
|
{
|
||||||
|
vec4 FogData;
|
||||||
|
vec3 vEye = WorldPos - g_CamPos.xyz;
|
||||||
|
vec3 nEye = normalize(vEye);
|
||||||
|
FogData.w = exp(-dot(vEye, vEye) * g_FogColor_Distance.w * 0.75);
|
||||||
|
|
||||||
|
float fog_sun_factor = pow(saturate(dot(nEye, g_SunDir.xyz)), 8.0);
|
||||||
|
FogData.xyz = mix(vec3(1.0, 1.0, 1.0), vec3(0.6, 0.6, 0.9), nEye.y * 0.5 + 0.5);
|
||||||
|
FogData.xyz = mix(FogData.xyz, vec3(0.95, 0.87, 0.78), fog_sun_factor);
|
||||||
|
return FogData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyFog(inout vec3 Color, vec4 FogData)
|
||||||
|
{
|
||||||
|
Color = mix(FogData.xyz, Color, FogData.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyLighting(inout mediump vec3 Color, mediump float DiffuseFactor)
|
||||||
|
{
|
||||||
|
mediump vec3 DiffuseLight = g_SunColor.xyz * DiffuseFactor;
|
||||||
|
mediump vec3 AmbientLight = vec3(0.2, 0.35, 0.55) * 0.5;
|
||||||
|
mediump vec3 Lighting = DiffuseLight + AmbientLight;
|
||||||
|
#if DEBUG == DEBUG_LIGHTING
|
||||||
|
Color = Lighting;
|
||||||
|
#else
|
||||||
|
Color *= Lighting;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma VARIANT SPECULAR
|
||||||
|
#pragma VARIANT GLOSSMAP
|
||||||
|
|
||||||
|
void ApplySpecular(inout mediump vec3 Color, mediump vec3 EyeVec, mediump vec3 Normal, mediump vec3 SpecularColor, mediump float Shininess, mediump float FresnelAmount)
|
||||||
|
{
|
||||||
|
mediump vec3 HalfAngle = normalize(-EyeVec + g_SunDir.xyz);
|
||||||
|
|
||||||
|
mediump float v_dot_h = saturate(dot(HalfAngle, -EyeVec));
|
||||||
|
mediump float n_dot_l = saturate(dot(Normal, g_SunDir.xyz));
|
||||||
|
mediump float n_dot_h = saturate(dot(Normal, HalfAngle));
|
||||||
|
mediump float n_dot_v = saturate(dot(-EyeVec, Normal));
|
||||||
|
mediump float h_dot_l = saturate(dot(g_SunDir.xyz, HalfAngle));
|
||||||
|
|
||||||
|
const mediump float roughness_value = 0.25;
|
||||||
|
|
||||||
|
mediump float r_sq = roughness_value * roughness_value;
|
||||||
|
mediump float n_dot_h_sq = n_dot_h * n_dot_h;
|
||||||
|
mediump float roughness_a = 1.0 / (4.0 * r_sq * n_dot_h_sq * n_dot_h_sq);
|
||||||
|
mediump float roughness_b = n_dot_h_sq - 1.0;
|
||||||
|
mediump float roughness_c = r_sq * n_dot_h_sq;
|
||||||
|
mediump float roughness = saturate(roughness_a * exp(roughness_b / roughness_c));
|
||||||
|
|
||||||
|
FresnelAmount = 0.5;
|
||||||
|
mediump float fresnel_term = pow(1.0 - n_dot_v, 5.0) * (1.0 - FresnelAmount) + FresnelAmount;
|
||||||
|
|
||||||
|
mediump float geo_numerator = 2.0 * n_dot_h;
|
||||||
|
mediump float geo_denominator = 1.0 / v_dot_h;
|
||||||
|
mediump float geo_term = min(1.0, min(n_dot_v, n_dot_l) * geo_numerator * geo_denominator);
|
||||||
|
|
||||||
|
#if SPECULAR || GLOSSMAP
|
||||||
|
Color += SpecularColor * g_SunColor.xyz * fresnel_term * roughness * n_dot_l * geo_term / (n_dot_v * n_dot_l + 0.0001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Color = vec3(0.025 * 1.0 / (n_dot_v * n_dot_l));
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 Position;
|
||||||
|
layout(location = 1) in vec4 LODWeights;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 TexCoord;
|
||||||
|
layout(location = 1) out vec3 EyeVec;
|
||||||
|
|
||||||
|
layout(std140, binding = 2) uniform GlobalGround
|
||||||
|
{
|
||||||
|
vec4 GroundScale;
|
||||||
|
vec4 GroundPosition;
|
||||||
|
vec4 InvGroundSize_PatchScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PatchData
|
||||||
|
{
|
||||||
|
vec4 Position;
|
||||||
|
vec4 LODs;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform PerPatch
|
||||||
|
{
|
||||||
|
PatchData Patches[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(binding = 0) uniform sampler2D TexHeightmap;
|
||||||
|
layout(binding = 1) uniform sampler2D TexLOD;
|
||||||
|
|
||||||
|
vec2 lod_factor(vec2 uv)
|
||||||
|
{
|
||||||
|
float level = textureLod(TexLOD, uv, 0.0).x * (255.0 / 32.0);
|
||||||
|
float floor_level = floor(level);
|
||||||
|
float fract_level = level - floor_level;
|
||||||
|
return vec2(floor_level, fract_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 warp_position()
|
||||||
|
{
|
||||||
|
float vlod = dot(LODWeights, Patches[gl_InstanceID].LODs);
|
||||||
|
vlod = mix(vlod, Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||||
|
|
||||||
|
#ifdef DEBUG_LOD_HEIGHT
|
||||||
|
LODFactor = vec4(vlod);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float floor_lod = floor(vlod);
|
||||||
|
float fract_lod = vlod - floor_lod;
|
||||||
|
uint ufloor_lod = uint(floor_lod);
|
||||||
|
|
||||||
|
#ifdef DEBUG_LOD_HEIGHT
|
||||||
|
LODFactor = vec4(fract_lod);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uvec2 uPosition = uvec2(Position);
|
||||||
|
uvec2 mask = (uvec2(1u) << uvec2(ufloor_lod, ufloor_lod + 1u)) - 1u;
|
||||||
|
//uvec2 rounding = mix(uvec2(0u), mask, lessThan(uPosition, uvec2(32u)));
|
||||||
|
|
||||||
|
uvec2 rounding = uvec2(
|
||||||
|
uPosition.x < 32u ? mask.x : 0u,
|
||||||
|
uPosition.y < 32u ? mask.y : 0u);
|
||||||
|
|
||||||
|
vec4 lower_upper_snapped = vec4((uPosition + rounding).xyxy & (~mask).xxyy);
|
||||||
|
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, fract_lod);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 PatchPos = Patches[gl_InstanceID].Position.xz * InvGroundSize_PatchScale.zw;
|
||||||
|
vec2 WarpedPos = warp_position();
|
||||||
|
vec2 VertexPos = PatchPos + WarpedPos;
|
||||||
|
vec2 NormalizedPos = VertexPos * InvGroundSize_PatchScale.xy;
|
||||||
|
vec2 lod = lod_factor(NormalizedPos);
|
||||||
|
|
||||||
|
vec2 Offset = exp2(lod.x) * InvGroundSize_PatchScale.xy;
|
||||||
|
|
||||||
|
float Elevation =
|
||||||
|
mix(textureLod(TexHeightmap, NormalizedPos + 0.5 * Offset, lod.x).x,
|
||||||
|
textureLod(TexHeightmap, NormalizedPos + 1.0 * Offset, lod.x + 1.0).x,
|
||||||
|
lod.y);
|
||||||
|
|
||||||
|
vec3 WorldPos = vec3(NormalizedPos.x, Elevation, NormalizedPos.y);
|
||||||
|
WorldPos *= GroundScale.xyz;
|
||||||
|
WorldPos += GroundPosition.xyz;
|
||||||
|
|
||||||
|
EyeVec = WorldPos - g_CamPos.xyz;
|
||||||
|
TexCoord = NormalizedPos + 0.5 * InvGroundSize_PatchScale.xy;
|
||||||
|
|
||||||
|
gl_Position = WorldPos.x * g_ViewProj_Row0 + WorldPos.y * g_ViewProj_Row1 + WorldPos.z * g_ViewProj_Row2 + g_ViewProj_Row3;
|
||||||
|
}
|
||||||
|
|
194
shaders/vert/ocean.vert
Normal file
194
shaders/vert/ocean.vert
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
#define YFLIP 0
|
||||||
|
#define SPECULAR 0
|
||||||
|
#define GLOSSMAP 0
|
||||||
|
|
||||||
|
#define DEBUG_NONE 0
|
||||||
|
#define DEBUG_DIFFUSE 1
|
||||||
|
#define DEBUG_SPECULAR 2
|
||||||
|
#define DEBUG_LIGHTING 3
|
||||||
|
#define DEBUG_FOG 4
|
||||||
|
#define DEBUG DEBUG_NONE
|
||||||
|
|
||||||
|
#define FORWARD 0
|
||||||
|
#define DEFERRED 1
|
||||||
|
#define DEFERRED_VTEX 2
|
||||||
|
|
||||||
|
float saturate(float x) { return clamp(x, 0.0, 1.0); }
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform GlobalVSData
|
||||||
|
{
|
||||||
|
vec4 g_ViewProj_Row0;
|
||||||
|
vec4 g_ViewProj_Row1;
|
||||||
|
vec4 g_ViewProj_Row2;
|
||||||
|
vec4 g_ViewProj_Row3;
|
||||||
|
vec4 g_CamPos;
|
||||||
|
vec4 g_CamRight;
|
||||||
|
vec4 g_CamUp;
|
||||||
|
vec4 g_CamFront;
|
||||||
|
vec4 g_SunDir;
|
||||||
|
vec4 g_SunColor;
|
||||||
|
vec4 g_TimeParams;
|
||||||
|
vec4 g_ResolutionParams;
|
||||||
|
vec4 g_CamAxisRight;
|
||||||
|
vec4 g_FogColor_Distance;
|
||||||
|
vec4 g_ShadowVP_Row0;
|
||||||
|
vec4 g_ShadowVP_Row1;
|
||||||
|
vec4 g_ShadowVP_Row2;
|
||||||
|
vec4 g_ShadowVP_Row3;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec4 ComputeFogFactor(vec3 WorldPos)
|
||||||
|
{
|
||||||
|
vec4 FogData;
|
||||||
|
vec3 vEye = WorldPos - g_CamPos.xyz;
|
||||||
|
vec3 nEye = normalize(vEye);
|
||||||
|
FogData.w = exp(-dot(vEye, vEye) * g_FogColor_Distance.w * 0.75);
|
||||||
|
|
||||||
|
float fog_sun_factor = pow(saturate(dot(nEye, g_SunDir.xyz)), 8.0);
|
||||||
|
FogData.xyz = mix(vec3(1.0, 1.0, 1.0), vec3(0.6, 0.6, 0.9), nEye.y * 0.5 + 0.5);
|
||||||
|
FogData.xyz = mix(FogData.xyz, vec3(0.95, 0.87, 0.78), fog_sun_factor);
|
||||||
|
return FogData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyFog(inout vec3 Color, vec4 FogData)
|
||||||
|
{
|
||||||
|
Color = mix(FogData.xyz, Color, FogData.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyLighting(inout mediump vec3 Color, mediump float DiffuseFactor)
|
||||||
|
{
|
||||||
|
mediump vec3 DiffuseLight = g_SunColor.xyz * DiffuseFactor;
|
||||||
|
mediump vec3 AmbientLight = vec3(0.2, 0.35, 0.55) * 0.5;
|
||||||
|
mediump vec3 Lighting = DiffuseLight + AmbientLight;
|
||||||
|
#if DEBUG == DEBUG_LIGHTING
|
||||||
|
Color = Lighting;
|
||||||
|
#else
|
||||||
|
Color *= Lighting;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplySpecular(inout mediump vec3 Color, mediump vec3 EyeVec, mediump vec3 Normal, mediump vec3 SpecularColor, mediump float Shininess, mediump float FresnelAmount)
|
||||||
|
{
|
||||||
|
mediump vec3 HalfAngle = normalize(-EyeVec + g_SunDir.xyz);
|
||||||
|
|
||||||
|
mediump float v_dot_h = saturate(dot(HalfAngle, -EyeVec));
|
||||||
|
mediump float n_dot_l = saturate(dot(Normal, g_SunDir.xyz));
|
||||||
|
mediump float n_dot_h = saturate(dot(Normal, HalfAngle));
|
||||||
|
mediump float n_dot_v = saturate(dot(-EyeVec, Normal));
|
||||||
|
mediump float h_dot_l = saturate(dot(g_SunDir.xyz, HalfAngle));
|
||||||
|
|
||||||
|
const mediump float roughness_value = 0.25;
|
||||||
|
|
||||||
|
mediump float r_sq = roughness_value * roughness_value;
|
||||||
|
mediump float n_dot_h_sq = n_dot_h * n_dot_h;
|
||||||
|
mediump float roughness_a = 1.0 / (4.0 * r_sq * n_dot_h_sq * n_dot_h_sq);
|
||||||
|
mediump float roughness_b = n_dot_h_sq - 1.0;
|
||||||
|
mediump float roughness_c = r_sq * n_dot_h_sq;
|
||||||
|
mediump float roughness = saturate(roughness_a * exp(roughness_b / roughness_c));
|
||||||
|
|
||||||
|
FresnelAmount = 0.5;
|
||||||
|
mediump float fresnel_term = pow(1.0 - n_dot_v, 5.0) * (1.0 - FresnelAmount) + FresnelAmount;
|
||||||
|
|
||||||
|
mediump float geo_numerator = 2.0 * n_dot_h;
|
||||||
|
mediump float geo_denominator = 1.0 / v_dot_h;
|
||||||
|
mediump float geo_term = min(1.0, min(n_dot_v, n_dot_l) * geo_numerator * geo_denominator);
|
||||||
|
|
||||||
|
#if SPECULAR || GLOSSMAP
|
||||||
|
Color += SpecularColor * g_SunColor.xyz * fresnel_term * roughness * n_dot_l * geo_term / (n_dot_v * n_dot_l + 0.0001);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//Color = vec3(0.025 * 1.0 / (n_dot_v * n_dot_l));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform mediump sampler2D TexDisplacement;
|
||||||
|
layout(binding = 1) uniform mediump sampler2D TexLOD;
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 Position;
|
||||||
|
layout(location = 1) in vec4 LODWeights;
|
||||||
|
|
||||||
|
layout(location = 0) out highp vec3 EyeVec;
|
||||||
|
layout(location = 1) out highp vec4 TexCoord;
|
||||||
|
|
||||||
|
layout(std140, binding = 4) uniform GlobalOcean
|
||||||
|
{
|
||||||
|
vec4 OceanScale;
|
||||||
|
vec4 OceanPosition;
|
||||||
|
vec4 InvOceanSize_PatchScale;
|
||||||
|
vec4 NormalTexCoordScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PatchData
|
||||||
|
{
|
||||||
|
vec4 Position;
|
||||||
|
vec4 LODs;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std140, binding = 0) uniform Offsets
|
||||||
|
{
|
||||||
|
PatchData Patches[256];
|
||||||
|
};
|
||||||
|
|
||||||
|
vec2 lod_factor(vec2 uv)
|
||||||
|
{
|
||||||
|
float level = textureLod(TexLOD, uv, 0.0).x * (255.0 / 32.0);
|
||||||
|
float floor_level = floor(level);
|
||||||
|
float fract_level = level - floor_level;
|
||||||
|
return vec2(floor_level, fract_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 warp_position()
|
||||||
|
{
|
||||||
|
float vlod = dot(LODWeights, Patches[gl_InstanceID].LODs);
|
||||||
|
vlod = mix(vlod, Patches[gl_InstanceID].Position.w, all(equal(LODWeights, vec4(0.0))));
|
||||||
|
|
||||||
|
float floor_lod = floor(vlod);
|
||||||
|
float fract_lod = vlod - floor_lod;
|
||||||
|
uint ufloor_lod = uint(floor_lod);
|
||||||
|
|
||||||
|
uvec4 uPosition = uvec4(Position);
|
||||||
|
uvec2 mask = (uvec2(1u) << uvec2(ufloor_lod, ufloor_lod + 1u)) - 1u;
|
||||||
|
|
||||||
|
uvec4 rounding;
|
||||||
|
rounding.x = uPosition.x < 32u ? mask.x : 0u;
|
||||||
|
rounding.y = uPosition.y < 32u ? mask.x : 0u;
|
||||||
|
rounding.z = uPosition.x < 32u ? mask.y : 0u;
|
||||||
|
rounding.w = uPosition.y < 32u ? mask.y : 0u;
|
||||||
|
|
||||||
|
//rounding = uPosition.xyxy * mask.xxyy;
|
||||||
|
vec4 lower_upper_snapped = vec4((uPosition.xyxy + rounding) & (~mask).xxyy);
|
||||||
|
return mix(lower_upper_snapped.xy, lower_upper_snapped.zw, fract_lod);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 PatchPos = Patches[gl_InstanceID].Position.xz * InvOceanSize_PatchScale.zw;
|
||||||
|
vec2 WarpedPos = warp_position();
|
||||||
|
vec2 VertexPos = PatchPos + WarpedPos;
|
||||||
|
vec2 NormalizedPos = VertexPos * InvOceanSize_PatchScale.xy;
|
||||||
|
vec2 NormalizedTex = NormalizedPos * NormalTexCoordScale.zw;
|
||||||
|
vec2 lod = lod_factor(NormalizedPos);
|
||||||
|
vec2 Offset = exp2(lod.x) * InvOceanSize_PatchScale.xy * NormalTexCoordScale.zw;
|
||||||
|
|
||||||
|
vec3 Displacement =
|
||||||
|
mix(textureLod(TexDisplacement, NormalizedTex + 0.5 * Offset, lod.x).yxz,
|
||||||
|
textureLod(TexDisplacement, NormalizedTex + 1.0 * Offset, lod.x + 1.0).yxz,
|
||||||
|
lod.y);
|
||||||
|
|
||||||
|
vec3 WorldPos = vec3(NormalizedPos.x, 0.0, NormalizedPos.y) + Displacement;
|
||||||
|
WorldPos *= OceanScale.xyz;
|
||||||
|
WorldPos += OceanPosition.xyz;
|
||||||
|
|
||||||
|
EyeVec = WorldPos - g_CamPos.xyz;
|
||||||
|
TexCoord = vec4(NormalizedTex, NormalizedTex * NormalTexCoordScale.xy) + 0.5 * InvOceanSize_PatchScale.xyxy * NormalTexCoordScale.zwzw;
|
||||||
|
|
||||||
|
gl_Position = WorldPos.x * g_ViewProj_Row0 + WorldPos.y * g_ViewProj_Row1 + WorldPos.z * g_ViewProj_Row2 + g_ViewProj_Row3;
|
||||||
|
#if YFLIP
|
||||||
|
gl_Position *= vec4(1.0, -1.0, 1.0, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
10
shaders/vert/texture_buffer.vert
Normal file
10
shaders/vert/texture_buffer.vert
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 310 es
|
||||||
|
#extension GL_OES_texture_buffer : require
|
||||||
|
|
||||||
|
layout(binding = 4) uniform highp samplerBuffer uSamp;
|
||||||
|
layout(rgba32f, binding = 5) uniform readonly highp imageBuffer uSampo;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = texelFetch(uSamp, 10) + imageLoad(uSampo, 100);
|
||||||
|
}
|
16
shaders/vert/ubo.vert
Normal file
16
shaders/vert/ubo.vert
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
layout(binding = 0, std140) uniform UBO
|
||||||
|
{
|
||||||
|
mat4 mvp;
|
||||||
|
};
|
||||||
|
|
||||||
|
in vec4 aVertex;
|
||||||
|
in vec3 aNormal;
|
||||||
|
out vec3 vNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = mvp * aVertex;
|
||||||
|
vNormal = aNormal;
|
||||||
|
}
|
635
spir2common.hpp
Normal file
635
spir2common.hpp
Normal file
@ -0,0 +1,635 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2COMMON_HPP
|
||||||
|
#define SPIR2COMMON_HPP
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
class CompilerError : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompilerError(const std::string &str) : std::runtime_error(str) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace inner
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
void join_helper(std::ostringstream &stream, T&& t)
|
||||||
|
{
|
||||||
|
stream << std::forward<T>(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Ts>
|
||||||
|
void join_helper(std::ostringstream &stream, T&& t, Ts&&... ts)
|
||||||
|
{
|
||||||
|
stream << std::forward<T>(t);
|
||||||
|
join_helper(stream, std::forward<Ts>(ts)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper template to avoid lots of nasty string temporary munging.
|
||||||
|
template<typename... Ts>
|
||||||
|
std::string join(Ts&&... ts)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
inner::join_helper(stream, std::forward<Ts>(ts)...);
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string merge(const std::vector<std::string> &list)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
for (auto &elem : list)
|
||||||
|
{
|
||||||
|
s += elem;
|
||||||
|
if (&elem != &list.back())
|
||||||
|
s += ", ";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline std::string convert_to_string(T&& t)
|
||||||
|
{
|
||||||
|
return std::to_string(std::forward<T>(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string convert_to_string(float t)
|
||||||
|
{
|
||||||
|
// std::to_string for floating point values is broken.
|
||||||
|
// Fallback to something more sane.
|
||||||
|
char buf[64];
|
||||||
|
sprintf(buf, "%.32g", t);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string convert_to_string(double t)
|
||||||
|
{
|
||||||
|
// std::to_string for floating point values is broken.
|
||||||
|
// Fallback to something more sane.
|
||||||
|
char buf[64];
|
||||||
|
sprintf(buf, "%.32g", t);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Instruction
|
||||||
|
{
|
||||||
|
Instruction(const std::vector<uint32_t> &spirv, uint32_t &index);
|
||||||
|
|
||||||
|
uint16_t op;
|
||||||
|
uint16_t count;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper for Variant interface.
|
||||||
|
struct IVariant
|
||||||
|
{
|
||||||
|
virtual ~IVariant() = default;
|
||||||
|
uint32_t self = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Types
|
||||||
|
{
|
||||||
|
TypeNone,
|
||||||
|
TypeType,
|
||||||
|
TypeVariable,
|
||||||
|
TypeConstant,
|
||||||
|
TypeFunction,
|
||||||
|
TypeFunctionPrototype,
|
||||||
|
TypePointer,
|
||||||
|
TypeBlock,
|
||||||
|
TypeExtension,
|
||||||
|
TypeExpression,
|
||||||
|
TypeUndef
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRUndef : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeUndef };
|
||||||
|
SPIRUndef(uint32_t basetype) : basetype(basetype) {}
|
||||||
|
uint32_t basetype;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRType : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeType };
|
||||||
|
|
||||||
|
enum BaseType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Void,
|
||||||
|
Bool,
|
||||||
|
Int,
|
||||||
|
UInt,
|
||||||
|
AtomicCounter,
|
||||||
|
Float,
|
||||||
|
Struct,
|
||||||
|
Image,
|
||||||
|
SampledImage,
|
||||||
|
Sampler
|
||||||
|
};
|
||||||
|
|
||||||
|
// Scalar/vector/matrix support.
|
||||||
|
BaseType basetype = Unknown;
|
||||||
|
uint32_t width = 0;
|
||||||
|
uint32_t vecsize = 1;
|
||||||
|
uint32_t columns = 1;
|
||||||
|
|
||||||
|
// Arrays, suport array of arrays by having a vector of array sizes.
|
||||||
|
std::vector<uint32_t> array;
|
||||||
|
|
||||||
|
// Pointers
|
||||||
|
bool pointer = false;
|
||||||
|
spv::StorageClass storage = spv::StorageClassGeneric;
|
||||||
|
|
||||||
|
std::vector<uint32_t> member_types;
|
||||||
|
|
||||||
|
struct Image
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
spv::Dim dim;
|
||||||
|
bool depth;
|
||||||
|
bool arrayed;
|
||||||
|
bool ms;
|
||||||
|
uint32_t sampled;
|
||||||
|
spv::ImageFormat format;
|
||||||
|
} image;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRExtension : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeExtension };
|
||||||
|
|
||||||
|
enum Extension
|
||||||
|
{
|
||||||
|
GLSL
|
||||||
|
};
|
||||||
|
|
||||||
|
SPIRExtension(Extension ext)
|
||||||
|
: ext(ext) {}
|
||||||
|
|
||||||
|
Extension ext;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRExpression : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeExpression };
|
||||||
|
|
||||||
|
// Only created by the backend target to avoid creating tons of temporaries.
|
||||||
|
SPIRExpression(std::string expr, uint32_t expression_type, bool immutable)
|
||||||
|
: expression(move(expr)), expression_type(expression_type), immutable(immutable) {}
|
||||||
|
|
||||||
|
// If non-zero, prepend expression with to_expression(base_expression).
|
||||||
|
// Used in amortizing multiple calls to to_expression()
|
||||||
|
// where in certain cases that would quickly force a temporary when not needed.
|
||||||
|
uint32_t base_expression = 0;
|
||||||
|
|
||||||
|
std::string expression;
|
||||||
|
uint32_t expression_type = 0;
|
||||||
|
|
||||||
|
// If this expression is a forwarded load,
|
||||||
|
// allow us to reference the original variable.
|
||||||
|
uint32_t loaded_from = 0;
|
||||||
|
|
||||||
|
// If this expression will never change, we can avoid lots of temporaries
|
||||||
|
// in high level source.
|
||||||
|
bool immutable = false;
|
||||||
|
|
||||||
|
// If this expression has been used while invalidated.
|
||||||
|
bool used_while_invalidated = false;
|
||||||
|
|
||||||
|
// A list of a variables for which this expression was invalidated by.
|
||||||
|
std::vector<uint32_t> invalidated_by;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRFunctionPrototype : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeFunctionPrototype };
|
||||||
|
|
||||||
|
SPIRFunctionPrototype(uint32_t return_type)
|
||||||
|
: return_type(return_type) {}
|
||||||
|
|
||||||
|
uint32_t return_type;
|
||||||
|
std::vector<uint32_t> parameter_types;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRBlock : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeBlock };
|
||||||
|
|
||||||
|
enum Terminator
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Direct, // Emit next block directly without a particular condition.
|
||||||
|
|
||||||
|
Select, // Block ends with an if/else block.
|
||||||
|
MultiSelect, // Block ends with switch statement.
|
||||||
|
Loop, // Block ends with a loop.
|
||||||
|
|
||||||
|
Return, // Block ends with return.
|
||||||
|
Unreachable, // Noop
|
||||||
|
Kill // Discard
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Merge
|
||||||
|
{
|
||||||
|
MergeNone,
|
||||||
|
MergeLoop,
|
||||||
|
MergeSelection
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Method
|
||||||
|
{
|
||||||
|
MergeToSelectForLoop,
|
||||||
|
MergeToDirectForLoop
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ContinueBlockType
|
||||||
|
{
|
||||||
|
ContinueNone,
|
||||||
|
|
||||||
|
// Continue block is branchless and has at least one instruction.
|
||||||
|
ForLoop,
|
||||||
|
|
||||||
|
// Noop continue block.
|
||||||
|
WhileLoop,
|
||||||
|
|
||||||
|
// Continue block is conditional.
|
||||||
|
DoWhileLoop,
|
||||||
|
|
||||||
|
// Highly unlikely that anything will use this,
|
||||||
|
// since it is really awkward/impossible to express in GLSL.
|
||||||
|
ComplexLoop
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { NoDominator = 0xffffffffu };
|
||||||
|
|
||||||
|
Terminator terminator = Unknown;
|
||||||
|
Merge merge = MergeNone;
|
||||||
|
uint32_t next_block = 0;
|
||||||
|
uint32_t merge_block = 0;
|
||||||
|
uint32_t continue_block = 0;
|
||||||
|
|
||||||
|
uint32_t return_value = 0; // If 0, return nothing (void).
|
||||||
|
uint32_t condition = 0;
|
||||||
|
uint32_t true_block = 0;
|
||||||
|
uint32_t false_block = 0;
|
||||||
|
uint32_t default_block = 0;
|
||||||
|
|
||||||
|
std::vector<Instruction> ops;
|
||||||
|
|
||||||
|
struct Phi
|
||||||
|
{
|
||||||
|
uint32_t local_variable; // flush local variable ...
|
||||||
|
uint32_t parent; // If we're in from_block and want to branch into this block ...
|
||||||
|
uint32_t function_variable; // to this function-global "phi" variable first.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Before entering this block flush out local variables to magical "phi" variables.
|
||||||
|
std::vector<Phi> phi_variables;
|
||||||
|
|
||||||
|
// Declare these temporaries before beginning the block.
|
||||||
|
// Used for handling complex continue blocks which have side effects.
|
||||||
|
std::vector<std::pair<uint32_t, uint32_t>> declare_temporary;
|
||||||
|
|
||||||
|
struct Case
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
uint32_t block;
|
||||||
|
};
|
||||||
|
std::vector<Case> cases;
|
||||||
|
|
||||||
|
// If we have tried to optimize code for this block but failed,
|
||||||
|
// keep track of this.
|
||||||
|
bool disable_block_optimization = false;
|
||||||
|
|
||||||
|
// If the continue block is complex, fallback to "dumb" for loops.
|
||||||
|
bool complex_continue = false;
|
||||||
|
|
||||||
|
// The dominating block which this block might be within.
|
||||||
|
// Used in continue; blocks to determine if we really need to write continue.
|
||||||
|
uint32_t loop_dominator = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRFunction : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeFunction };
|
||||||
|
|
||||||
|
SPIRFunction(uint32_t return_type, uint32_t function_type)
|
||||||
|
: return_type(return_type), function_type(function_type)
|
||||||
|
{}
|
||||||
|
|
||||||
|
struct Parameter
|
||||||
|
{
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t read_count;
|
||||||
|
uint32_t write_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t return_type;
|
||||||
|
uint32_t function_type;
|
||||||
|
std::vector<Parameter> arguments;
|
||||||
|
std::vector<uint32_t> local_variables;
|
||||||
|
uint32_t entry_block = 0;
|
||||||
|
std::vector<uint32_t> blocks;
|
||||||
|
|
||||||
|
void add_local_variable(uint32_t id)
|
||||||
|
{
|
||||||
|
local_variables.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_parameter(uint32_t type, uint32_t id)
|
||||||
|
{
|
||||||
|
// Arguments are read-only until proven otherwise.
|
||||||
|
arguments.push_back({ type, id, 0u, 0u });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool active = false;
|
||||||
|
bool flush_undeclared = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRVariable : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeVariable };
|
||||||
|
|
||||||
|
SPIRVariable() = default;
|
||||||
|
SPIRVariable(uint32_t basetype, spv::StorageClass storage, uint32_t initializer = 0)
|
||||||
|
: basetype(basetype), storage(storage), initializer(initializer)
|
||||||
|
{}
|
||||||
|
|
||||||
|
uint32_t basetype = 0;
|
||||||
|
spv::StorageClass storage = spv::StorageClassGeneric;
|
||||||
|
uint32_t decoration = 0;
|
||||||
|
uint32_t initializer = 0;
|
||||||
|
|
||||||
|
std::vector<uint32_t> dereference_chain;
|
||||||
|
bool compat_builtin = false;
|
||||||
|
|
||||||
|
// If a variable is shadowed, we only statically assign to it
|
||||||
|
// and never actually emit a statement for it.
|
||||||
|
// When we read the variable as an expression, just forward
|
||||||
|
// shadowed_id as the expression.
|
||||||
|
bool statically_assigned = false;
|
||||||
|
uint32_t static_expression = 0;
|
||||||
|
|
||||||
|
// Temporaries which can remain forwarded as long as this variable is not modified.
|
||||||
|
std::vector<uint32_t> dependees;
|
||||||
|
bool forwardable = true;
|
||||||
|
|
||||||
|
bool deferred_declaration = false;
|
||||||
|
bool phi_variable = false;
|
||||||
|
bool remapped_variable = false;
|
||||||
|
|
||||||
|
SPIRFunction::Parameter *parameter = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SPIRConstant : IVariant
|
||||||
|
{
|
||||||
|
enum { type = TypeConstant };
|
||||||
|
|
||||||
|
union Constant
|
||||||
|
{
|
||||||
|
uint32_t u32;
|
||||||
|
int32_t i32;
|
||||||
|
float f32;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstantVector
|
||||||
|
{
|
||||||
|
Constant r[4];
|
||||||
|
uint32_t vecsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstantMatrix
|
||||||
|
{
|
||||||
|
ConstantVector c[4];
|
||||||
|
uint32_t columns;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline uint32_t scalar(uint32_t col = 0, uint32_t row = 0) const
|
||||||
|
{
|
||||||
|
return m.c[col].r[row].u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float scalar_f32(uint32_t col = 0, uint32_t row = 0) const
|
||||||
|
{
|
||||||
|
return m.c[col].r[row].f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int scalar_i32(uint32_t col = 0, uint32_t row = 0) const
|
||||||
|
{
|
||||||
|
return m.c[col].r[row].i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const ConstantVector& vector() const { return m.c[0]; }
|
||||||
|
inline uint32_t vector_size() const { return m.c[0].vecsize; }
|
||||||
|
inline uint32_t columns() const { return m.columns; }
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type, const uint32_t *elements, uint32_t num_elements) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
subconstants.insert(end(subconstants), elements, elements + num_elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type, uint32_t v0) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.c[0].r[0].u32 = v0;
|
||||||
|
m.c[0].vecsize = 1;
|
||||||
|
m.columns = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type, uint32_t v0, uint32_t v1) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.c[0].r[0].u32 = v0;
|
||||||
|
m.c[0].r[1].u32 = v1;
|
||||||
|
m.c[0].vecsize = 2;
|
||||||
|
m.columns = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type, uint32_t v0, uint32_t v1, uint32_t v2) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.c[0].r[0].u32 = v0;
|
||||||
|
m.c[0].r[1].u32 = v1;
|
||||||
|
m.c[0].r[2].u32 = v2;
|
||||||
|
m.c[0].vecsize = 3;
|
||||||
|
m.columns = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type, uint32_t v0, uint32_t v1, uint32_t v2, uint32_t v3) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.c[0].r[0].u32 = v0;
|
||||||
|
m.c[0].r[1].u32 = v1;
|
||||||
|
m.c[0].r[2].u32 = v2;
|
||||||
|
m.c[0].r[3].u32 = v3;
|
||||||
|
m.c[0].vecsize = 4;
|
||||||
|
m.columns = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type,
|
||||||
|
const ConstantVector &vec0) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.columns = 1;
|
||||||
|
m.c[0] = vec0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type,
|
||||||
|
const ConstantVector &vec0, const ConstantVector &vec1) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.columns = 2;
|
||||||
|
m.c[0] = vec0;
|
||||||
|
m.c[1] = vec1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type,
|
||||||
|
const ConstantVector &vec0, const ConstantVector &vec1,
|
||||||
|
const ConstantVector &vec2) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.columns = 3;
|
||||||
|
m.c[0] = vec0;
|
||||||
|
m.c[1] = vec1;
|
||||||
|
m.c[2] = vec2;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIRConstant(uint32_t constant_type,
|
||||||
|
const ConstantVector &vec0, const ConstantVector &vec1,
|
||||||
|
const ConstantVector &vec2, const ConstantVector &vec3) :
|
||||||
|
constant_type(constant_type)
|
||||||
|
{
|
||||||
|
m.columns = 4;
|
||||||
|
m.c[0] = vec0;
|
||||||
|
m.c[1] = vec1;
|
||||||
|
m.c[2] = vec2;
|
||||||
|
m.c[3] = vec3;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t constant_type;
|
||||||
|
ConstantMatrix m;
|
||||||
|
bool specialization = false; // If the constant is a specialization constant.
|
||||||
|
|
||||||
|
// For composites which are constant arrays, etc.
|
||||||
|
std::vector<uint32_t> subconstants;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Variant
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// MSVC 2013 workaround, we shouldn't need these constructors.
|
||||||
|
Variant() = default;
|
||||||
|
Variant(Variant&& other) { *this = std::move(other); }
|
||||||
|
Variant& operator=(Variant&& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
holder = move(other.holder);
|
||||||
|
type = other.type;
|
||||||
|
other.type = TypeNone;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(std::unique_ptr<IVariant> val, uint32_t type)
|
||||||
|
{
|
||||||
|
holder = std::move(val);
|
||||||
|
if (this->type != TypeNone && this->type != type)
|
||||||
|
throw CompilerError("Overwriting a variant with new type.");
|
||||||
|
this->type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& get()
|
||||||
|
{
|
||||||
|
if (!holder)
|
||||||
|
throw CompilerError("nullptr");
|
||||||
|
if (T::type != type)
|
||||||
|
throw CompilerError("Bad cast");
|
||||||
|
return *static_cast<T*>(holder.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& get() const
|
||||||
|
{
|
||||||
|
if (!holder)
|
||||||
|
throw CompilerError("nullptr");
|
||||||
|
if (T::type != type)
|
||||||
|
throw CompilerError("Bad cast");
|
||||||
|
return *static_cast<const T*>(holder.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_type() const { return type; }
|
||||||
|
bool empty() const { return !holder; }
|
||||||
|
void reset() { holder.reset(); type = TypeNone; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<IVariant> holder;
|
||||||
|
uint32_t type = TypeNone;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& variant_get(Variant &var)
|
||||||
|
{
|
||||||
|
return var.get<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& variant_get(const Variant &var)
|
||||||
|
{
|
||||||
|
return var.get<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... P>
|
||||||
|
T& variant_set(Variant &var, P&&... args)
|
||||||
|
{
|
||||||
|
auto uptr = std::unique_ptr<T>(new T(std::forward<P>(args)...));
|
||||||
|
auto ptr = uptr.get();
|
||||||
|
var.set(std::move(uptr), T::type);
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Meta
|
||||||
|
{
|
||||||
|
struct Decoration
|
||||||
|
{
|
||||||
|
std::string alias;
|
||||||
|
uint64_t decoration_flags = 0;
|
||||||
|
spv::BuiltIn builtin_type;
|
||||||
|
uint32_t location = 0;
|
||||||
|
uint32_t set = 0;
|
||||||
|
uint32_t binding = 0;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint32_t array_stride = 0;
|
||||||
|
bool builtin = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Decoration decoration;
|
||||||
|
std::vector<Decoration> members;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
436
spir2cpp.cpp
Normal file
436
spir2cpp.cpp
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "spir2cpp.hpp"
|
||||||
|
|
||||||
|
using namespace spv;
|
||||||
|
using namespace spir2cross;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void CompilerCPP::emit_buffer_block(const SPIRVariable &var)
|
||||||
|
{
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
auto instance_name = to_name(var.self);
|
||||||
|
|
||||||
|
uint32_t set = meta[var.self].decoration.set;
|
||||||
|
uint32_t binding = meta[var.self].decoration.binding;
|
||||||
|
|
||||||
|
emit_struct(type);
|
||||||
|
statement("internal::Resource<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
|
||||||
|
statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
|
||||||
|
resource_registrations.push_back(join("s.register_resource(", instance_name, "__", ", ", set, ", ", binding, ");"));
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_interface_block(const SPIRVariable &var)
|
||||||
|
{
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
|
||||||
|
const char *qual = var.storage == StorageClassInput ? "StageInput" : "StageOutput";
|
||||||
|
const char *lowerqual = var.storage == StorageClassInput ? "stage_input" : "stage_output";
|
||||||
|
auto instance_name = to_name(var.self);
|
||||||
|
uint32_t location = meta[var.self].decoration.location;
|
||||||
|
|
||||||
|
auto flags = meta[type.self].decoration.decoration_flags;
|
||||||
|
if (flags & (1ull << DecorationBlock))
|
||||||
|
emit_struct(type);
|
||||||
|
|
||||||
|
statement("internal::", qual, "<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
|
||||||
|
statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
|
||||||
|
resource_registrations.push_back(join("s.register_", lowerqual, "(", instance_name, "__", ", ", location, ");"));
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_shared(const SPIRVariable &var)
|
||||||
|
{
|
||||||
|
auto instance_name = to_name(var.self);
|
||||||
|
statement(variable_decl(var), ";");
|
||||||
|
statement_no_indent("#define ", instance_name, " __res->", instance_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_uniform(const SPIRVariable &var)
|
||||||
|
{
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
auto instance_name = to_name(var.self);
|
||||||
|
|
||||||
|
uint32_t set = meta[var.self].decoration.set;
|
||||||
|
uint32_t binding = meta[var.self].decoration.binding;
|
||||||
|
uint32_t location = meta[var.self].decoration.location;
|
||||||
|
|
||||||
|
if (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage || type.basetype == SPIRType::AtomicCounter)
|
||||||
|
{
|
||||||
|
statement("internal::Resource<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
|
||||||
|
statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
|
||||||
|
resource_registrations.push_back(join("s.register_resource(", instance_name, "__", ", ", set, ", ", binding, ");"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
statement("internal::UniformConstant<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, "__;");
|
||||||
|
statement_no_indent("#define ", instance_name, " __res->", instance_name, "__.get()");
|
||||||
|
resource_registrations.push_back(join("s.register_uniform_constant(", instance_name, "__", ", ", location, ");"));
|
||||||
|
}
|
||||||
|
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_push_constant_block(const SPIRVariable &var)
|
||||||
|
{
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
auto &flags = meta[var.self].decoration.decoration_flags;
|
||||||
|
if ((flags & (1ull << DecorationBinding)) || (flags & (1ull << DecorationDescriptorSet)))
|
||||||
|
throw CompilerError("Push constant blocks cannot be compiled to GLSL with Binding or Set syntax. "
|
||||||
|
"Remap to location with reflection API first or disable these decorations.");
|
||||||
|
|
||||||
|
emit_struct(type);
|
||||||
|
auto instance_name = to_name(var.self);
|
||||||
|
|
||||||
|
statement("internal::PushConstant<", type_to_glsl(type), type_to_array_glsl(type), "> ", instance_name, ";");
|
||||||
|
statement_no_indent("#define ", instance_name, " __res->", instance_name, ".get()");
|
||||||
|
resource_registrations.push_back(join("s.register_push_constant(", instance_name, "__", ");"));
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_resources()
|
||||||
|
{
|
||||||
|
// Output all basic struct types which are not Block or BufferBlock as these are declared inplace
|
||||||
|
// when such variables are instantiated.
|
||||||
|
for (auto &id : ids)
|
||||||
|
{
|
||||||
|
if (id.get_type() == TypeType)
|
||||||
|
{
|
||||||
|
auto &type = id.get<SPIRType>();
|
||||||
|
if (type.basetype == SPIRType::Struct &&
|
||||||
|
type.array.empty() &&
|
||||||
|
!type.pointer &&
|
||||||
|
(meta[type.self].decoration.decoration_flags & ((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))) == 0)
|
||||||
|
{
|
||||||
|
emit_struct(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
statement("struct Resources : ", resource_type);
|
||||||
|
begin_scope();
|
||||||
|
|
||||||
|
// Output UBOs and SSBOs
|
||||||
|
for (auto &id : ids)
|
||||||
|
{
|
||||||
|
if (id.get_type() == TypeVariable)
|
||||||
|
{
|
||||||
|
auto &var = id.get<SPIRVariable>();
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
|
||||||
|
if (type.pointer && type.storage == StorageClassUniform &&
|
||||||
|
!is_builtin_variable(var) &&
|
||||||
|
(meta[type.self].decoration.decoration_flags & ((1ull << DecorationBlock) | (1ull << DecorationBufferBlock))))
|
||||||
|
{
|
||||||
|
emit_buffer_block(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output push constant blocks
|
||||||
|
for (auto &id : ids)
|
||||||
|
{
|
||||||
|
if (id.get_type() == TypeVariable)
|
||||||
|
{
|
||||||
|
auto &var = id.get<SPIRVariable>();
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
if (type.pointer && type.storage == StorageClassPushConstant)
|
||||||
|
emit_push_constant_block(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output in/out interfaces.
|
||||||
|
for (auto &id : ids)
|
||||||
|
{
|
||||||
|
if (id.get_type() == TypeVariable)
|
||||||
|
{
|
||||||
|
auto &var = id.get<SPIRVariable>();
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
|
||||||
|
if (!is_builtin_variable(var) &&
|
||||||
|
!var.remapped_variable &&
|
||||||
|
type.pointer &&
|
||||||
|
(var.storage == StorageClassInput || var.storage == StorageClassOutput))
|
||||||
|
{
|
||||||
|
emit_interface_block(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output Uniform Constants (values, samplers, images, etc).
|
||||||
|
for (auto &id : ids)
|
||||||
|
{
|
||||||
|
if (id.get_type() == TypeVariable)
|
||||||
|
{
|
||||||
|
auto &var = id.get<SPIRVariable>();
|
||||||
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
|
||||||
|
if (!is_builtin_variable(var) && !var.remapped_variable && type.pointer &&
|
||||||
|
(type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter))
|
||||||
|
{
|
||||||
|
emit_uniform(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global variables.
|
||||||
|
bool emitted = false;
|
||||||
|
for (auto global : global_variables)
|
||||||
|
{
|
||||||
|
auto &var = get<SPIRVariable>(global);
|
||||||
|
if (var.storage == StorageClassWorkgroup)
|
||||||
|
{
|
||||||
|
emit_shared(var);
|
||||||
|
emitted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emitted)
|
||||||
|
statement("");
|
||||||
|
|
||||||
|
statement("inline void init(spir2cross_shader& s)");
|
||||||
|
begin_scope();
|
||||||
|
statement(resource_type, "::init(s);");
|
||||||
|
for (auto ® : resource_registrations)
|
||||||
|
statement(reg);
|
||||||
|
end_scope();
|
||||||
|
resource_registrations.clear();
|
||||||
|
|
||||||
|
end_scope_decl();
|
||||||
|
|
||||||
|
statement("");
|
||||||
|
statement("Resources* __res;");
|
||||||
|
if (execution.model == ExecutionModelGLCompute)
|
||||||
|
statement("ComputePrivateResources __priv_res;");
|
||||||
|
statement("");
|
||||||
|
|
||||||
|
// Emit regular globals which are allocated per invocation.
|
||||||
|
emitted = false;
|
||||||
|
for (auto global : global_variables)
|
||||||
|
{
|
||||||
|
auto &var = get<SPIRVariable>(global);
|
||||||
|
if (var.storage == StorageClassPrivate)
|
||||||
|
{
|
||||||
|
if (var.storage == StorageClassWorkgroup)
|
||||||
|
emit_shared(var);
|
||||||
|
else
|
||||||
|
statement(variable_decl(var), ";");
|
||||||
|
emitted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emitted)
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
string CompilerCPP::compile()
|
||||||
|
{
|
||||||
|
// Do not deal with ES-isms like precision, older extensions and such.
|
||||||
|
options.es = false;
|
||||||
|
options.version = 450;
|
||||||
|
backend.float_literal_suffix = true;
|
||||||
|
backend.uint32_t_literal_suffix = true;
|
||||||
|
backend.basic_int_type = "int32_t";
|
||||||
|
backend.basic_uint_type = "uint32_t";
|
||||||
|
backend.swizzle_is_function = true;
|
||||||
|
backend.shared_is_implied = true;
|
||||||
|
|
||||||
|
uint32_t pass_count = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (pass_count >= 2)
|
||||||
|
throw CompilerError("Over 2 compilation loops detected. Must be a bug!");
|
||||||
|
|
||||||
|
resource_registrations.clear();
|
||||||
|
reset();
|
||||||
|
|
||||||
|
// Move constructor for this type is broken on GCC 4.9 ...
|
||||||
|
buffer = unique_ptr<ostringstream>(new ostringstream());
|
||||||
|
|
||||||
|
emit_header();
|
||||||
|
emit_resources();
|
||||||
|
|
||||||
|
emit_function(get<SPIRFunction>(execution.entry_point), 0);
|
||||||
|
|
||||||
|
pass_count++;
|
||||||
|
} while (force_recompile);
|
||||||
|
|
||||||
|
// Match opening scope of emit_header().
|
||||||
|
end_scope_decl();
|
||||||
|
// namespace
|
||||||
|
end_scope();
|
||||||
|
|
||||||
|
// Emit C entry points
|
||||||
|
emit_c_linkage();
|
||||||
|
|
||||||
|
return buffer->str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_c_linkage()
|
||||||
|
{
|
||||||
|
statement("");
|
||||||
|
|
||||||
|
statement("spir2cross_shader_t* spir2cross_construct(void)");
|
||||||
|
begin_scope();
|
||||||
|
statement("return new ", impl_type, "();");
|
||||||
|
end_scope();
|
||||||
|
|
||||||
|
statement("");
|
||||||
|
statement("void spir2cross_destruct(spir2cross_shader_t *shader)");
|
||||||
|
begin_scope();
|
||||||
|
statement("delete static_cast<", impl_type, "*>(shader);");
|
||||||
|
end_scope();
|
||||||
|
|
||||||
|
statement("");
|
||||||
|
statement("void spir2cross_invoke(spir2cross_shader_t *shader)");
|
||||||
|
begin_scope();
|
||||||
|
statement("static_cast<", impl_type, "*>(shader)->invoke();");
|
||||||
|
end_scope();
|
||||||
|
|
||||||
|
statement("");
|
||||||
|
statement("static const struct spir2cross_interface vtable =");
|
||||||
|
begin_scope();
|
||||||
|
statement("spir2cross_construct,");
|
||||||
|
statement("spir2cross_destruct,");
|
||||||
|
statement("spir2cross_invoke,");
|
||||||
|
end_scope_decl();
|
||||||
|
|
||||||
|
statement("");
|
||||||
|
statement("const struct spir2cross_interface* spir2cross_get_interface(void)");
|
||||||
|
begin_scope();
|
||||||
|
statement("return &vtable;");
|
||||||
|
end_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_function_prototype(SPIRFunction &func, uint64_t)
|
||||||
|
{
|
||||||
|
local_variables.clear();
|
||||||
|
string decl;
|
||||||
|
|
||||||
|
auto &type = get<SPIRType>(func.return_type);
|
||||||
|
decl += "inline ";
|
||||||
|
decl += type_to_glsl(type);
|
||||||
|
decl += " ";
|
||||||
|
|
||||||
|
if (func.self == execution.entry_point)
|
||||||
|
{
|
||||||
|
decl += "main";
|
||||||
|
processing_entry_point = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
decl += to_name(func.self);
|
||||||
|
|
||||||
|
decl += "(";
|
||||||
|
for (auto &arg : func.arguments)
|
||||||
|
{
|
||||||
|
add_local_variable(arg.id);
|
||||||
|
|
||||||
|
decl += argument_decl(arg);
|
||||||
|
if (&arg != &func.arguments.back())
|
||||||
|
decl += ", ";
|
||||||
|
|
||||||
|
// Hold a pointer to the parameter so we can invalidate the readonly field if needed.
|
||||||
|
auto *var = maybe_get<SPIRVariable>(arg.id);
|
||||||
|
if (var)
|
||||||
|
var->parameter = &arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
decl += ")";
|
||||||
|
statement(decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
string CompilerCPP::argument_decl(const SPIRFunction::Parameter &arg)
|
||||||
|
{
|
||||||
|
auto &type = expression_type(arg.id);
|
||||||
|
bool constref = !type.pointer || arg.write_count == 0;
|
||||||
|
|
||||||
|
auto &var = get<SPIRVariable>(arg.id);
|
||||||
|
return join(constref ? "const " : "",
|
||||||
|
type_to_glsl(type), "& ", to_name(var.self), type_to_array_glsl(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilerCPP::emit_header()
|
||||||
|
{
|
||||||
|
statement("// This C++ shader is autogenerated by spir2cross.");
|
||||||
|
statement("#include \"spir2cross/internal_interface.hpp\"");
|
||||||
|
statement("#include \"spir2cross/external_interface.h\"");
|
||||||
|
statement("#include <stdint.h>");
|
||||||
|
statement("");
|
||||||
|
statement("using namespace spir2cross;");
|
||||||
|
statement("using namespace glm;");
|
||||||
|
statement("");
|
||||||
|
|
||||||
|
statement("namespace Impl");
|
||||||
|
begin_scope();
|
||||||
|
|
||||||
|
switch (execution.model)
|
||||||
|
{
|
||||||
|
case ExecutionModelGeometry:
|
||||||
|
case ExecutionModelTessellationControl:
|
||||||
|
case ExecutionModelTessellationEvaluation:
|
||||||
|
case ExecutionModelGLCompute:
|
||||||
|
case ExecutionModelFragment:
|
||||||
|
case ExecutionModelVertex:
|
||||||
|
statement("struct Shader");
|
||||||
|
begin_scope();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw CompilerError("Unsupported execution model.");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (execution.model)
|
||||||
|
{
|
||||||
|
case ExecutionModelGeometry:
|
||||||
|
impl_type = "GeometryShader<Impl::Shader, Impl::Shader::Resources>";
|
||||||
|
resource_type = "GeometryResources";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExecutionModelVertex:
|
||||||
|
impl_type = "VertexShader<Impl::Shader, Impl::Shader::Resources>";
|
||||||
|
resource_type = "VertexResources";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExecutionModelFragment:
|
||||||
|
impl_type = "FragmentShader<Impl::Shader, Impl::Shader::Resources>";
|
||||||
|
resource_type = "FragmentResources";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExecutionModelGLCompute:
|
||||||
|
impl_type = join("ComputeShader<Impl::Shader, Impl::Shader::Resources, ",
|
||||||
|
execution.workgroup_size.x, ", ",
|
||||||
|
execution.workgroup_size.y, ", ",
|
||||||
|
execution.workgroup_size.z, ">");
|
||||||
|
resource_type = "ComputeResources";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExecutionModelTessellationControl:
|
||||||
|
impl_type = "TessControlShader<Impl::Shader, Impl::Shader::Resources>";
|
||||||
|
resource_type = "TessControlResources";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExecutionModelTessellationEvaluation:
|
||||||
|
impl_type = "TessEvaluationShader<Impl::Shader, Impl::Shader::Resources>";
|
||||||
|
resource_type = "TessEvaluationResources";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw CompilerError("Unsupported execution model.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
53
spir2cpp.hpp
Normal file
53
spir2cpp.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CPP
|
||||||
|
#define SPIR2CPP
|
||||||
|
|
||||||
|
#include "spir2glsl.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
class CompilerCPP : public CompilerGLSL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompilerCPP(std::vector<uint32_t> spirv) : CompilerGLSL(move(spirv)) {}
|
||||||
|
std::string compile() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void emit_header() override;
|
||||||
|
void emit_c_linkage();
|
||||||
|
void emit_function_prototype(SPIRFunction &func, uint64_t return_flags) override;
|
||||||
|
|
||||||
|
void emit_resources();
|
||||||
|
void emit_buffer_block(const SPIRVariable &type);
|
||||||
|
void emit_push_constant_block(const SPIRVariable &var);
|
||||||
|
void emit_interface_block(const SPIRVariable &type);
|
||||||
|
void emit_block_chain(SPIRBlock &block);
|
||||||
|
void emit_uniform(const SPIRVariable &var);
|
||||||
|
void emit_shared(const SPIRVariable &var);
|
||||||
|
|
||||||
|
std::string argument_decl(const SPIRFunction::Parameter &arg);
|
||||||
|
|
||||||
|
std::vector<std::string> resource_registrations;
|
||||||
|
std::string impl_type;
|
||||||
|
std::string resource_type;
|
||||||
|
uint32_t shared_counter = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1802
spir2cross.cpp
Normal file
1802
spir2cross.cpp
Normal file
File diff suppressed because it is too large
Load Diff
345
spir2cross.hpp
Normal file
345
spir2cross.hpp
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2CROSS_HPP
|
||||||
|
#define SPIR2CROSS_HPP
|
||||||
|
|
||||||
|
#include "spirv.hpp"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "spir2common.hpp"
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
struct Resource
|
||||||
|
{
|
||||||
|
// Resources are identified with their SPIR-V ID.
|
||||||
|
// This is the ID of the OpVariable.
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
// The type of the declared resource.
|
||||||
|
uint32_t type_id;
|
||||||
|
|
||||||
|
// The declared name (OpName) of the resource.
|
||||||
|
// For Buffer blocks, the name actually reflects the externally
|
||||||
|
// visible Block name.
|
||||||
|
//
|
||||||
|
// This name can be retrieved again by using either
|
||||||
|
// get_name(id) or get_name(type_id) depending if it's a buffer block or not.
|
||||||
|
//
|
||||||
|
// This name can be an empty string in which case get_fallback_name(id) can be
|
||||||
|
// used which obtains a suitable fallback identifier for an ID.
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShaderResources
|
||||||
|
{
|
||||||
|
std::vector<Resource> uniform_buffers;
|
||||||
|
std::vector<Resource> storage_buffers;
|
||||||
|
std::vector<Resource> stage_inputs;
|
||||||
|
std::vector<Resource> stage_outputs;
|
||||||
|
std::vector<Resource> subpass_inputs;
|
||||||
|
std::vector<Resource> storage_images;
|
||||||
|
std::vector<Resource> sampled_images;
|
||||||
|
std::vector<Resource> atomic_counters;
|
||||||
|
|
||||||
|
// There can only be one push constant block,
|
||||||
|
// but keep the vector in case this restriction is lifted in the future.
|
||||||
|
std::vector<Resource> push_constant_buffers;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BufferRange
|
||||||
|
{
|
||||||
|
unsigned index;
|
||||||
|
size_t offset;
|
||||||
|
size_t range;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Compiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// The constructor takes a buffer of SPIR-V words and parses it.
|
||||||
|
Compiler(std::vector<uint32_t> ir);
|
||||||
|
|
||||||
|
// After parsing, API users can modify the SPIR-V via reflection and call this
|
||||||
|
// to disassemble the SPIR-V into the desired langauage.
|
||||||
|
// Sub-classes actually implement this.
|
||||||
|
virtual std::string compile();
|
||||||
|
|
||||||
|
// Gets the identifier (OpName) of an ID. If not defined, an empty string will be returned.
|
||||||
|
const std::string& get_name(uint32_t id) const;
|
||||||
|
|
||||||
|
// Applies a decoration to an ID. Effectively injects OpDecorate.
|
||||||
|
void set_decoration(uint32_t id, spv::Decoration decoration, uint32_t argument = 0);
|
||||||
|
|
||||||
|
// Overrides the identifier OpName of an ID.
|
||||||
|
// Identifiers beginning with underscores or identifiers which contain double underscores
|
||||||
|
// are reserved by the implementation.
|
||||||
|
void set_name(uint32_t id, const std::string& name);
|
||||||
|
|
||||||
|
// Gets a bitmask for the decorations which are applied to ID.
|
||||||
|
// I.e. (1ull << spv::DecorationFoo) | (1ull << spv::DecorationBar)
|
||||||
|
uint64_t get_decoration_mask(uint32_t id) const;
|
||||||
|
|
||||||
|
// Gets the value for decorations which take arguments.
|
||||||
|
// If decoration doesn't exist or decoration is not recognized,
|
||||||
|
// 0 will be returned.
|
||||||
|
uint32_t get_decoration(uint32_t id, spv::Decoration decoration) const;
|
||||||
|
|
||||||
|
// Removes the decoration for a an ID.
|
||||||
|
void unset_decoration(uint32_t id, spv::Decoration decoration);
|
||||||
|
|
||||||
|
// Gets the SPIR-V associated with ID.
|
||||||
|
// Mostly used with Resource::type_id to parse the underlying type of a resource.
|
||||||
|
const SPIRType& get_type(uint32_t id) const;
|
||||||
|
|
||||||
|
// Gets the underlying storage class for an OpVariable.
|
||||||
|
spv::StorageClass get_storage_class(uint32_t id) const;
|
||||||
|
|
||||||
|
// If get_name() is an empty string, get the fallback name which will be used
|
||||||
|
// instead in the disassembled source.
|
||||||
|
virtual const std::string get_fallback_name(uint32_t id) const
|
||||||
|
{
|
||||||
|
return join("_", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given an OpTypeStruct in ID, obtain the identifier for member number "index".
|
||||||
|
// This may be an empty string.
|
||||||
|
const std::string& get_member_name(uint32_t id, uint32_t index) const;
|
||||||
|
|
||||||
|
// Given an OpTypeStruct in ID, obtain the OpMemberDecoration for member number "index".
|
||||||
|
uint32_t get_member_decoration(uint32_t id, uint32_t index, spv::Decoration decoration) const;
|
||||||
|
|
||||||
|
// Sets the member identifier for OpTypeStruct ID, member number "index".
|
||||||
|
void set_member_name(uint32_t id, uint32_t index, const std::string& name);
|
||||||
|
|
||||||
|
// Gets the decoration mask for a member of a struct, similar to get_decoration_mask.
|
||||||
|
uint64_t get_member_decoration_mask(uint32_t id, uint32_t index) const;
|
||||||
|
|
||||||
|
// Similar to set_decoration, but for struct members.
|
||||||
|
void set_member_decoration(uint32_t id, uint32_t index,
|
||||||
|
spv::Decoration decoration, uint32_t argument = 0);
|
||||||
|
|
||||||
|
// Unsets a member decoration, similar to unset_decoration.
|
||||||
|
void unset_member_decoration(uint32_t id, uint32_t index, spv::Decoration decoration);
|
||||||
|
|
||||||
|
// Gets the fallback name for a member, similar to get_fallback_name.
|
||||||
|
virtual const std::string get_fallback_member_name(uint32_t index) const
|
||||||
|
{
|
||||||
|
return join("_", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a vector of which members of a struct are potentially in use by a
|
||||||
|
// SPIR-V shader. The granularity of this analysis is per-member of a struct.
|
||||||
|
// This can be used for Buffer (UBO), BufferBlock (SSBO) and PushConstant blocks.
|
||||||
|
// ID is the Resource::id obtained from get_shader_resources().
|
||||||
|
std::vector<BufferRange> get_active_buffer_ranges(unsigned id) const;
|
||||||
|
|
||||||
|
// Returns the effective size of a buffer block.
|
||||||
|
size_t get_declared_struct_size(const SPIRType &struct_type) const;
|
||||||
|
|
||||||
|
// Legacy GLSL compatibility method.
|
||||||
|
// Takes a variable with a block interface and flattens it into a T array[N]; array instead.
|
||||||
|
// For this to work, all types in the block must not themselves be composites
|
||||||
|
// (except vectors and matrices), and all types must be the same.
|
||||||
|
// The name of the uniform will be the same as the interface block name.
|
||||||
|
void flatten_interface_block(uint32_t id);
|
||||||
|
|
||||||
|
// Query shader resources, use ids with reflection interface to modify or query binding points, etc.
|
||||||
|
ShaderResources get_shader_resources() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const uint32_t* stream(uint32_t offset) const
|
||||||
|
{
|
||||||
|
if (offset > spirv.size())
|
||||||
|
throw CompilerError("Compiler::stream() out of range.");
|
||||||
|
return &spirv[offset];
|
||||||
|
}
|
||||||
|
std::vector<uint32_t> spirv;
|
||||||
|
|
||||||
|
std::vector<Instruction> inst;
|
||||||
|
std::vector<Variant> ids;
|
||||||
|
std::vector<Meta> meta;
|
||||||
|
|
||||||
|
SPIRFunction *function = nullptr;
|
||||||
|
SPIRBlock *block = nullptr;
|
||||||
|
std::vector<uint32_t> global_variables;
|
||||||
|
std::vector<uint32_t> aliased_variables;
|
||||||
|
|
||||||
|
// If our IDs are out of range here as part of opcodes, throw instead of
|
||||||
|
// undefined behavior.
|
||||||
|
template<typename T, typename... P>
|
||||||
|
T& set(uint32_t id, P&&... args)
|
||||||
|
{
|
||||||
|
auto &var = variant_set<T>(ids.at(id), std::forward<P>(args)...);
|
||||||
|
var.self = id;
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& get(uint32_t id)
|
||||||
|
{
|
||||||
|
return variant_get<T>(ids.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* maybe_get(uint32_t id)
|
||||||
|
{
|
||||||
|
if (ids.at(id).get_type() == T::type)
|
||||||
|
return &get<T>(id);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T& get(uint32_t id) const
|
||||||
|
{
|
||||||
|
return variant_get<T>(ids.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const T* maybe_get(uint32_t id) const
|
||||||
|
{
|
||||||
|
if (ids.at(id).get_type() == T::type)
|
||||||
|
return &get<T>(id);
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t flags = 0;
|
||||||
|
spv::ExecutionModel model;
|
||||||
|
uint32_t entry_point = 0;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t x = 0, y = 0, z = 0;
|
||||||
|
} workgroup_size;
|
||||||
|
uint32_t invocations = 0;
|
||||||
|
uint32_t output_vertices = 0;
|
||||||
|
} execution;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t version = 0;
|
||||||
|
bool es = false;
|
||||||
|
bool known = false;
|
||||||
|
} source;
|
||||||
|
|
||||||
|
std::unordered_set<uint32_t> loop_block;
|
||||||
|
std::unordered_set<uint32_t> continue_block;
|
||||||
|
std::unordered_set<uint32_t> loop_merge_target;
|
||||||
|
std::unordered_set<uint32_t> selection_merge_target;
|
||||||
|
std::unordered_set<uint32_t> multiselect_merge_target;
|
||||||
|
|
||||||
|
std::string to_name(uint32_t id);
|
||||||
|
bool is_builtin_variable(const SPIRVariable &var) const;
|
||||||
|
bool is_immutable(uint32_t id) const;
|
||||||
|
bool is_member_builtin(const SPIRType &type, uint32_t index, spv::BuiltIn *builtin) const;
|
||||||
|
const SPIRType& expression_type(uint32_t id) const;
|
||||||
|
bool expression_is_lvalue(uint32_t id) const;
|
||||||
|
bool variable_storage_is_aliased(const SPIRVariable &var);
|
||||||
|
SPIRVariable* maybe_get_backing_variable(uint32_t chain);
|
||||||
|
|
||||||
|
void register_read(uint32_t expr, uint32_t chain, bool forwarded);
|
||||||
|
void register_write(uint32_t chain);
|
||||||
|
|
||||||
|
inline bool is_continue(uint32_t next) const
|
||||||
|
{
|
||||||
|
return continue_block.find(next) != end(continue_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_break(uint32_t next) const
|
||||||
|
{
|
||||||
|
return loop_merge_target.find(next) != end(loop_merge_target) ||
|
||||||
|
multiselect_merge_target.find(next) != end(multiselect_merge_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_conditional(uint32_t next) const
|
||||||
|
{
|
||||||
|
return selection_merge_target.find(next) != end(selection_merge_target) &&
|
||||||
|
multiselect_merge_target.find(next) == end(multiselect_merge_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dependency tracking for temporaries read from variables.
|
||||||
|
void flush_dependees(SPIRVariable &var);
|
||||||
|
void flush_all_active_variables();
|
||||||
|
void flush_all_atomic_capable_variables();
|
||||||
|
void flush_all_aliased_variables();
|
||||||
|
void register_global_read_dependencies(const SPIRBlock &func, uint32_t id);
|
||||||
|
void register_global_read_dependencies(const SPIRFunction &func, uint32_t id);
|
||||||
|
std::unordered_set<uint32_t> invalid_expressions;
|
||||||
|
|
||||||
|
void update_name_cache(std::unordered_set<std::string> &cache, std::string &name);
|
||||||
|
std::unordered_set<std::string> global_struct_cache;
|
||||||
|
|
||||||
|
bool function_is_pure(const SPIRFunction &func);
|
||||||
|
bool block_is_pure(const SPIRBlock &block);
|
||||||
|
bool block_is_outside_flow_control_from_block(const SPIRBlock &from, const SPIRBlock &to);
|
||||||
|
|
||||||
|
bool execution_is_branchless(const SPIRBlock &from, const SPIRBlock &to) const;
|
||||||
|
bool execution_is_noop(const SPIRBlock &from, const SPIRBlock &to) const;
|
||||||
|
SPIRBlock::ContinueBlockType continue_block_type(const SPIRBlock &continue_block) const;
|
||||||
|
|
||||||
|
bool force_recompile = false;
|
||||||
|
|
||||||
|
uint32_t type_struct_member_offset(const SPIRType &type, uint32_t index) const;
|
||||||
|
uint32_t type_struct_member_array_stride(const SPIRType &type, uint32_t index) const;
|
||||||
|
|
||||||
|
bool block_is_loop_candidate(const SPIRBlock &block, SPIRBlock::Method method) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parse();
|
||||||
|
void parse(const Instruction &i);
|
||||||
|
|
||||||
|
// Used internally to implement various traversals for queries.
|
||||||
|
struct OpcodeHandler
|
||||||
|
{
|
||||||
|
virtual ~OpcodeHandler() = default;
|
||||||
|
|
||||||
|
// Return true if traversal should continue.
|
||||||
|
// If false, traversal will end immediately.
|
||||||
|
virtual bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BufferAccessHandler : OpcodeHandler
|
||||||
|
{
|
||||||
|
BufferAccessHandler(const Compiler &compiler, std::vector<BufferRange> &ranges, unsigned id)
|
||||||
|
: compiler(compiler), ranges(ranges), id(id) {}
|
||||||
|
|
||||||
|
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
|
||||||
|
|
||||||
|
const Compiler &compiler;
|
||||||
|
std::vector<BufferRange> &ranges;
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
std::unordered_set<uint32_t> seen;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const;
|
||||||
|
bool traverse_all_reachable_opcodes(const SPIRFunction &block, OpcodeHandler &handler) const;
|
||||||
|
|
||||||
|
size_t get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
4225
spir2glsl.cpp
Normal file
4225
spir2glsl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
298
spir2glsl.hpp
Normal file
298
spir2glsl.hpp
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPIR2GLSL
|
||||||
|
#define SPIR2GLSL
|
||||||
|
|
||||||
|
#include "spir2cross.hpp"
|
||||||
|
#include <sstream>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace spir2cross
|
||||||
|
{
|
||||||
|
enum PlsFormat
|
||||||
|
{
|
||||||
|
PlsNone = 0,
|
||||||
|
|
||||||
|
PlsR11FG11FB10F,
|
||||||
|
PlsR32F,
|
||||||
|
PlsRG16F,
|
||||||
|
PlsRGB10A2,
|
||||||
|
PlsRGBA8,
|
||||||
|
PlsRG16,
|
||||||
|
|
||||||
|
PlsRGBA8I,
|
||||||
|
PlsRG16I,
|
||||||
|
|
||||||
|
PlsRGB10A2UI,
|
||||||
|
PlsRGBA8UI,
|
||||||
|
PlsRG16UI,
|
||||||
|
PlsR32UI
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlsRemap
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
PlsFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompilerGLSL : public Compiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Options
|
||||||
|
{
|
||||||
|
uint32_t version = 450;
|
||||||
|
bool es = false;
|
||||||
|
bool force_temporary = false;
|
||||||
|
|
||||||
|
enum Precision
|
||||||
|
{
|
||||||
|
DontCare,
|
||||||
|
Lowp,
|
||||||
|
Mediump,
|
||||||
|
Highp
|
||||||
|
};
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
// In vertex shaders, rewrite [0, w] depth (Vulkan/D3D style) to [-w, w] depth (GL style).
|
||||||
|
bool fixup_clipspace = true;
|
||||||
|
} vertex;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
// Add precision mediump float in ES targets when emitting GLES source.
|
||||||
|
// Add precision highp int in ES targets when emitting GLES source.
|
||||||
|
Precision default_float_precision = Mediump;
|
||||||
|
Precision default_int_precision = Highp;
|
||||||
|
} fragment;
|
||||||
|
};
|
||||||
|
|
||||||
|
void remap_pixel_local_storage(std::vector<PlsRemap> inputs, std::vector<PlsRemap> outputs)
|
||||||
|
{
|
||||||
|
pls_inputs = std::move(inputs);
|
||||||
|
pls_outputs = std::move(outputs);
|
||||||
|
remap_pls_variables();
|
||||||
|
}
|
||||||
|
|
||||||
|
CompilerGLSL(std::vector<uint32_t> spirv) : Compiler(move(spirv))
|
||||||
|
{
|
||||||
|
if (source.known)
|
||||||
|
{
|
||||||
|
options.es = source.es;
|
||||||
|
options.version = source.version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Options& get_options() const { return options; }
|
||||||
|
void set_options(Options &opts) { options = opts; }
|
||||||
|
std::string compile() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void reset();
|
||||||
|
void emit_function(SPIRFunction &func, uint64_t return_flags);
|
||||||
|
|
||||||
|
// Virtualize methods which need to be overridden by subclass targets like C++ and such.
|
||||||
|
virtual void emit_function_prototype(SPIRFunction &func, uint64_t return_flags);
|
||||||
|
virtual void emit_header();
|
||||||
|
|
||||||
|
std::unique_ptr<std::ostringstream> buffer;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void statement_inner(T&& t)
|
||||||
|
{
|
||||||
|
(*buffer) << std::forward<T>(t);
|
||||||
|
statement_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Ts>
|
||||||
|
inline void statement_inner(T&& t, Ts&&... ts)
|
||||||
|
{
|
||||||
|
(*buffer) << std::forward<T>(t);
|
||||||
|
statement_count++;
|
||||||
|
statement_inner(std::forward<Ts>(ts)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
inline void statement(Ts&&... ts)
|
||||||
|
{
|
||||||
|
if (redirect_statement)
|
||||||
|
redirect_statement->push_back(join(std::forward<Ts>(ts)...));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < indent; i++)
|
||||||
|
(*buffer) << " ";
|
||||||
|
|
||||||
|
statement_inner(std::forward<Ts>(ts)...);
|
||||||
|
(*buffer) << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
inline void statement_no_indent(Ts&&... ts)
|
||||||
|
{
|
||||||
|
auto old_indent = indent;
|
||||||
|
indent = 0;
|
||||||
|
statement(std::forward<Ts>(ts)...);
|
||||||
|
indent = old_indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for implementing continue blocks where
|
||||||
|
// we want to obtain a list of statements we can merge
|
||||||
|
// on a single line separated by comma.
|
||||||
|
std::vector<std::string> *redirect_statement = nullptr;
|
||||||
|
const SPIRBlock *current_continue_block = nullptr;
|
||||||
|
|
||||||
|
void begin_scope();
|
||||||
|
void end_scope();
|
||||||
|
void end_scope_decl();
|
||||||
|
void end_scope_decl(const std::string &decl);
|
||||||
|
|
||||||
|
Options options;
|
||||||
|
|
||||||
|
std::string type_to_glsl(const SPIRType &type);
|
||||||
|
std::string type_to_array_glsl(const SPIRType &type);
|
||||||
|
std::string variable_decl(const SPIRVariable &variable);
|
||||||
|
|
||||||
|
void add_local_variable(uint32_t id);
|
||||||
|
std::unordered_set<std::string> local_variables;
|
||||||
|
|
||||||
|
bool processing_entry_point = false;
|
||||||
|
|
||||||
|
// Can be overriden by subclass backends for trivial things which
|
||||||
|
// shouldn't need polymorphism.
|
||||||
|
struct BackendVariations
|
||||||
|
{
|
||||||
|
bool float_literal_suffix = false;
|
||||||
|
bool uint32_t_literal_suffix = true;
|
||||||
|
const char *basic_int_type = "int";
|
||||||
|
const char *basic_uint_type = "uint";
|
||||||
|
bool swizzle_is_function = false;
|
||||||
|
bool shared_is_implied = false;
|
||||||
|
} backend;
|
||||||
|
|
||||||
|
void emit_struct(const SPIRType &type);
|
||||||
|
void emit_instruction(const Instruction &instr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void emit_resources();
|
||||||
|
void emit_buffer_block(const SPIRVariable &type);
|
||||||
|
void emit_push_constant_block(const SPIRVariable &var);
|
||||||
|
void emit_interface_block(const SPIRVariable &type);
|
||||||
|
void emit_block_chain(SPIRBlock &block);
|
||||||
|
std::string emit_continue_block(uint32_t continue_block);
|
||||||
|
bool attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method method);
|
||||||
|
void emit_uniform(const SPIRVariable &var);
|
||||||
|
void propagate_loop_dominators(const SPIRBlock &block);
|
||||||
|
|
||||||
|
void branch(uint32_t from, uint32_t to);
|
||||||
|
void branch(uint32_t from, uint32_t cond, uint32_t true_block, uint32_t false_block);
|
||||||
|
void flush_phi(uint32_t from, uint32_t to);
|
||||||
|
bool flush_phi_required(uint32_t from, uint32_t to);
|
||||||
|
void flush_variable_declaration(uint32_t id);
|
||||||
|
void flush_undeclared_variables();
|
||||||
|
|
||||||
|
bool should_forward(uint32_t id);
|
||||||
|
void emit_texture_op(const Instruction &i);
|
||||||
|
void emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, uint32_t right, uint32_t lerp);
|
||||||
|
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, uint32_t count);
|
||||||
|
void emit_quaternary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, uint32_t op3, const char *op);
|
||||||
|
void emit_trinary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, const char *op);
|
||||||
|
void emit_binary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
|
||||||
|
void emit_unary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op);
|
||||||
|
void emit_binary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
|
||||||
|
void emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op);
|
||||||
|
bool expression_is_forwarded(uint32_t id);
|
||||||
|
SPIRExpression& emit_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs, bool extra_parens, bool suppress_usage_tracking = false);
|
||||||
|
std::string access_chain(uint32_t base, const uint32_t *indices, uint32_t count, bool index_is_literal, bool chain_only = false);
|
||||||
|
|
||||||
|
const char* index_to_swizzle(uint32_t index);
|
||||||
|
std::string remap_swizzle(uint32_t result_type, uint32_t input_components, uint32_t expr);
|
||||||
|
std::string declare_temporary(uint32_t type, uint32_t id);
|
||||||
|
std::string to_expression(uint32_t id);
|
||||||
|
std::string to_member_name(const SPIRType &type, uint32_t index);
|
||||||
|
std::string type_to_glsl_constructor(const SPIRType &type);
|
||||||
|
std::string argument_decl(const SPIRFunction::Parameter &arg);
|
||||||
|
std::string member_decl(const SPIRType &type, const SPIRType &member_type, uint32_t member);
|
||||||
|
std::string image_type_glsl(const SPIRType &type);
|
||||||
|
std::string to_qualifiers_glsl(uint32_t id);
|
||||||
|
const char* to_precision_qualifiers_glsl(uint32_t id);
|
||||||
|
const char* flags_to_precision_qualifiers_glsl(const SPIRType &type, uint64_t flags);
|
||||||
|
std::string constant_expression(const SPIRConstant &c);
|
||||||
|
std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector);
|
||||||
|
const char* format_to_glsl(spv::ImageFormat format);
|
||||||
|
std::string layout_for_member(const SPIRType &type, uint32_t index);
|
||||||
|
uint64_t combined_decoration_for_member(const SPIRType &type, uint32_t index);
|
||||||
|
std::string layout_for_variable(const SPIRVariable &variable);
|
||||||
|
|
||||||
|
bool ssbo_is_std430_packing(const SPIRType &type);
|
||||||
|
uint32_t type_to_std430_alignment(const SPIRType &type, uint64_t flags);
|
||||||
|
uint32_t type_to_std430_array_stride(const SPIRType &type, uint64_t flags);
|
||||||
|
uint32_t type_to_std430_size(const SPIRType &type, uint64_t flags);
|
||||||
|
|
||||||
|
std::string bitcast_glsl(uint32_t result_type, uint32_t arg);
|
||||||
|
std::string bitcast_glsl_op(uint32_t result_type, uint32_t arg);
|
||||||
|
const char* builtin_to_glsl(spv::BuiltIn builtin);
|
||||||
|
std::string build_composite_combiner(const uint32_t *elems, uint32_t length);
|
||||||
|
bool remove_duplicate_swizzle(std::string &op);
|
||||||
|
bool remove_unity_swizzle(uint32_t base, std::string &op);
|
||||||
|
|
||||||
|
// Can modify flags to remote readonly/writeonly if image type
|
||||||
|
// and force recompile.
|
||||||
|
bool check_atomic_image(uint32_t id);
|
||||||
|
void require_extension(const std::string &ext);
|
||||||
|
|
||||||
|
void replace_fragment_output(SPIRVariable &var);
|
||||||
|
void replace_fragment_outputs();
|
||||||
|
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype);
|
||||||
|
|
||||||
|
uint32_t indent = 0;
|
||||||
|
void emit_fixup();
|
||||||
|
|
||||||
|
std::unordered_set<uint32_t> emitted_functions;
|
||||||
|
|
||||||
|
// Usage tracking. If a temporary is used more than once, use the temporary instead to
|
||||||
|
// avoid AST explosion when SPIRV is generated with pure SSA and doesn't write stuff to variables.
|
||||||
|
std::unordered_map<uint32_t, uint32_t> expression_usage_counts;
|
||||||
|
std::unordered_set<uint32_t> forced_temporaries;
|
||||||
|
std::unordered_set<uint32_t> forwarded_temporaries;
|
||||||
|
void track_expression_read(uint32_t id);
|
||||||
|
|
||||||
|
std::unordered_set<std::string> forced_extensions;
|
||||||
|
|
||||||
|
uint32_t statement_count;
|
||||||
|
|
||||||
|
inline bool is_legacy() const { return (options.es && options.version < 300) || (!options.es && options.version < 130); }
|
||||||
|
|
||||||
|
bool args_will_forward(uint32_t id, const uint32_t *args, uint32_t num_args, bool pure);
|
||||||
|
void register_call_out_argument(uint32_t id);
|
||||||
|
void register_impure_function_call();
|
||||||
|
|
||||||
|
// GL_EXT_shader_pixel_local_storage support.
|
||||||
|
std::vector<PlsRemap> pls_inputs;
|
||||||
|
std::vector<PlsRemap> pls_outputs;
|
||||||
|
std::string pls_decl(const PlsRemap &variable);
|
||||||
|
const char* to_pls_qualifiers_glsl(const SPIRVariable &variable);
|
||||||
|
void emit_pls();
|
||||||
|
void remap_pls_variables();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
879
spirv.hpp
Normal file
879
spirv.hpp
Normal file
@ -0,0 +1,879 @@
|
|||||||
|
// Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and/or associated documentation files (the "Materials"),
|
||||||
|
// to deal in the Materials without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Materials, and to permit persons to whom the
|
||||||
|
// Materials are furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Materials.
|
||||||
|
//
|
||||||
|
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||||
|
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||||
|
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||||
|
//
|
||||||
|
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||||
|
// IN THE MATERIALS.
|
||||||
|
|
||||||
|
// This header is automatically generated by the same tool that creates
|
||||||
|
// the Binary Section of the SPIR-V specification.
|
||||||
|
|
||||||
|
// Enumeration tokens for SPIR-V, in various styles:
|
||||||
|
// C, C++, C++11, JSON, Lua, Python
|
||||||
|
//
|
||||||
|
// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
|
||||||
|
// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
|
||||||
|
// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
|
||||||
|
// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
|
||||||
|
// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
|
||||||
|
//
|
||||||
|
// Some tokens act like mask values, which can be OR'd together,
|
||||||
|
// while others are mutually exclusive. The mask-like ones have
|
||||||
|
// "Mask" in their name, and a parallel enum that has the shift
|
||||||
|
// amount (1 << x) for each corresponding enumerant.
|
||||||
|
|
||||||
|
#ifndef spirv_HPP
|
||||||
|
#define spirv_HPP
|
||||||
|
|
||||||
|
namespace spv {
|
||||||
|
|
||||||
|
typedef unsigned int Id;
|
||||||
|
|
||||||
|
#define SPV_VERSION 0x10000
|
||||||
|
#define SPV_REVISION 3
|
||||||
|
|
||||||
|
static const unsigned int MagicNumber = 0x07230203;
|
||||||
|
static const unsigned int Version = 0x00010000;
|
||||||
|
static const unsigned int Revision = 3;
|
||||||
|
static const unsigned int OpCodeMask = 0xffff;
|
||||||
|
static const unsigned int WordCountShift = 16;
|
||||||
|
|
||||||
|
enum SourceLanguage {
|
||||||
|
SourceLanguageUnknown = 0,
|
||||||
|
SourceLanguageESSL = 1,
|
||||||
|
SourceLanguageGLSL = 2,
|
||||||
|
SourceLanguageOpenCL_C = 3,
|
||||||
|
SourceLanguageOpenCL_CPP = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ExecutionModel {
|
||||||
|
ExecutionModelVertex = 0,
|
||||||
|
ExecutionModelTessellationControl = 1,
|
||||||
|
ExecutionModelTessellationEvaluation = 2,
|
||||||
|
ExecutionModelGeometry = 3,
|
||||||
|
ExecutionModelFragment = 4,
|
||||||
|
ExecutionModelGLCompute = 5,
|
||||||
|
ExecutionModelKernel = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AddressingModel {
|
||||||
|
AddressingModelLogical = 0,
|
||||||
|
AddressingModelPhysical32 = 1,
|
||||||
|
AddressingModelPhysical64 = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MemoryModel {
|
||||||
|
MemoryModelSimple = 0,
|
||||||
|
MemoryModelGLSL450 = 1,
|
||||||
|
MemoryModelOpenCL = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ExecutionMode {
|
||||||
|
ExecutionModeInvocations = 0,
|
||||||
|
ExecutionModeSpacingEqual = 1,
|
||||||
|
ExecutionModeSpacingFractionalEven = 2,
|
||||||
|
ExecutionModeSpacingFractionalOdd = 3,
|
||||||
|
ExecutionModeVertexOrderCw = 4,
|
||||||
|
ExecutionModeVertexOrderCcw = 5,
|
||||||
|
ExecutionModePixelCenterInteger = 6,
|
||||||
|
ExecutionModeOriginUpperLeft = 7,
|
||||||
|
ExecutionModeOriginLowerLeft = 8,
|
||||||
|
ExecutionModeEarlyFragmentTests = 9,
|
||||||
|
ExecutionModePointMode = 10,
|
||||||
|
ExecutionModeXfb = 11,
|
||||||
|
ExecutionModeDepthReplacing = 12,
|
||||||
|
ExecutionModeDepthGreater = 14,
|
||||||
|
ExecutionModeDepthLess = 15,
|
||||||
|
ExecutionModeDepthUnchanged = 16,
|
||||||
|
ExecutionModeLocalSize = 17,
|
||||||
|
ExecutionModeLocalSizeHint = 18,
|
||||||
|
ExecutionModeInputPoints = 19,
|
||||||
|
ExecutionModeInputLines = 20,
|
||||||
|
ExecutionModeInputLinesAdjacency = 21,
|
||||||
|
ExecutionModeTriangles = 22,
|
||||||
|
ExecutionModeInputTrianglesAdjacency = 23,
|
||||||
|
ExecutionModeQuads = 24,
|
||||||
|
ExecutionModeIsolines = 25,
|
||||||
|
ExecutionModeOutputVertices = 26,
|
||||||
|
ExecutionModeOutputPoints = 27,
|
||||||
|
ExecutionModeOutputLineStrip = 28,
|
||||||
|
ExecutionModeOutputTriangleStrip = 29,
|
||||||
|
ExecutionModeVecTypeHint = 30,
|
||||||
|
ExecutionModeContractionOff = 31,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StorageClass {
|
||||||
|
StorageClassUniformConstant = 0,
|
||||||
|
StorageClassInput = 1,
|
||||||
|
StorageClassUniform = 2,
|
||||||
|
StorageClassOutput = 3,
|
||||||
|
StorageClassWorkgroup = 4,
|
||||||
|
StorageClassCrossWorkgroup = 5,
|
||||||
|
StorageClassPrivate = 6,
|
||||||
|
StorageClassFunction = 7,
|
||||||
|
StorageClassGeneric = 8,
|
||||||
|
StorageClassPushConstant = 9,
|
||||||
|
StorageClassAtomicCounter = 10,
|
||||||
|
StorageClassImage = 11,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Dim {
|
||||||
|
Dim1D = 0,
|
||||||
|
Dim2D = 1,
|
||||||
|
Dim3D = 2,
|
||||||
|
DimCube = 3,
|
||||||
|
DimRect = 4,
|
||||||
|
DimBuffer = 5,
|
||||||
|
DimSubpassData = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SamplerAddressingMode {
|
||||||
|
SamplerAddressingModeNone = 0,
|
||||||
|
SamplerAddressingModeClampToEdge = 1,
|
||||||
|
SamplerAddressingModeClamp = 2,
|
||||||
|
SamplerAddressingModeRepeat = 3,
|
||||||
|
SamplerAddressingModeRepeatMirrored = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SamplerFilterMode {
|
||||||
|
SamplerFilterModeNearest = 0,
|
||||||
|
SamplerFilterModeLinear = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImageFormat {
|
||||||
|
ImageFormatUnknown = 0,
|
||||||
|
ImageFormatRgba32f = 1,
|
||||||
|
ImageFormatRgba16f = 2,
|
||||||
|
ImageFormatR32f = 3,
|
||||||
|
ImageFormatRgba8 = 4,
|
||||||
|
ImageFormatRgba8Snorm = 5,
|
||||||
|
ImageFormatRg32f = 6,
|
||||||
|
ImageFormatRg16f = 7,
|
||||||
|
ImageFormatR11fG11fB10f = 8,
|
||||||
|
ImageFormatR16f = 9,
|
||||||
|
ImageFormatRgba16 = 10,
|
||||||
|
ImageFormatRgb10A2 = 11,
|
||||||
|
ImageFormatRg16 = 12,
|
||||||
|
ImageFormatRg8 = 13,
|
||||||
|
ImageFormatR16 = 14,
|
||||||
|
ImageFormatR8 = 15,
|
||||||
|
ImageFormatRgba16Snorm = 16,
|
||||||
|
ImageFormatRg16Snorm = 17,
|
||||||
|
ImageFormatRg8Snorm = 18,
|
||||||
|
ImageFormatR16Snorm = 19,
|
||||||
|
ImageFormatR8Snorm = 20,
|
||||||
|
ImageFormatRgba32i = 21,
|
||||||
|
ImageFormatRgba16i = 22,
|
||||||
|
ImageFormatRgba8i = 23,
|
||||||
|
ImageFormatR32i = 24,
|
||||||
|
ImageFormatRg32i = 25,
|
||||||
|
ImageFormatRg16i = 26,
|
||||||
|
ImageFormatRg8i = 27,
|
||||||
|
ImageFormatR16i = 28,
|
||||||
|
ImageFormatR8i = 29,
|
||||||
|
ImageFormatRgba32ui = 30,
|
||||||
|
ImageFormatRgba16ui = 31,
|
||||||
|
ImageFormatRgba8ui = 32,
|
||||||
|
ImageFormatR32ui = 33,
|
||||||
|
ImageFormatRgb10a2ui = 34,
|
||||||
|
ImageFormatRg32ui = 35,
|
||||||
|
ImageFormatRg16ui = 36,
|
||||||
|
ImageFormatRg8ui = 37,
|
||||||
|
ImageFormatR16ui = 38,
|
||||||
|
ImageFormatR8ui = 39,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImageChannelOrder {
|
||||||
|
ImageChannelOrderR = 0,
|
||||||
|
ImageChannelOrderA = 1,
|
||||||
|
ImageChannelOrderRG = 2,
|
||||||
|
ImageChannelOrderRA = 3,
|
||||||
|
ImageChannelOrderRGB = 4,
|
||||||
|
ImageChannelOrderRGBA = 5,
|
||||||
|
ImageChannelOrderBGRA = 6,
|
||||||
|
ImageChannelOrderARGB = 7,
|
||||||
|
ImageChannelOrderIntensity = 8,
|
||||||
|
ImageChannelOrderLuminance = 9,
|
||||||
|
ImageChannelOrderRx = 10,
|
||||||
|
ImageChannelOrderRGx = 11,
|
||||||
|
ImageChannelOrderRGBx = 12,
|
||||||
|
ImageChannelOrderDepth = 13,
|
||||||
|
ImageChannelOrderDepthStencil = 14,
|
||||||
|
ImageChannelOrdersRGB = 15,
|
||||||
|
ImageChannelOrdersRGBx = 16,
|
||||||
|
ImageChannelOrdersRGBA = 17,
|
||||||
|
ImageChannelOrdersBGRA = 18,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImageChannelDataType {
|
||||||
|
ImageChannelDataTypeSnormInt8 = 0,
|
||||||
|
ImageChannelDataTypeSnormInt16 = 1,
|
||||||
|
ImageChannelDataTypeUnormInt8 = 2,
|
||||||
|
ImageChannelDataTypeUnormInt16 = 3,
|
||||||
|
ImageChannelDataTypeUnormShort565 = 4,
|
||||||
|
ImageChannelDataTypeUnormShort555 = 5,
|
||||||
|
ImageChannelDataTypeUnormInt101010 = 6,
|
||||||
|
ImageChannelDataTypeSignedInt8 = 7,
|
||||||
|
ImageChannelDataTypeSignedInt16 = 8,
|
||||||
|
ImageChannelDataTypeSignedInt32 = 9,
|
||||||
|
ImageChannelDataTypeUnsignedInt8 = 10,
|
||||||
|
ImageChannelDataTypeUnsignedInt16 = 11,
|
||||||
|
ImageChannelDataTypeUnsignedInt32 = 12,
|
||||||
|
ImageChannelDataTypeHalfFloat = 13,
|
||||||
|
ImageChannelDataTypeFloat = 14,
|
||||||
|
ImageChannelDataTypeUnormInt24 = 15,
|
||||||
|
ImageChannelDataTypeUnormInt101010_2 = 16,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImageOperandsShift {
|
||||||
|
ImageOperandsBiasShift = 0,
|
||||||
|
ImageOperandsLodShift = 1,
|
||||||
|
ImageOperandsGradShift = 2,
|
||||||
|
ImageOperandsConstOffsetShift = 3,
|
||||||
|
ImageOperandsOffsetShift = 4,
|
||||||
|
ImageOperandsConstOffsetsShift = 5,
|
||||||
|
ImageOperandsSampleShift = 6,
|
||||||
|
ImageOperandsMinLodShift = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImageOperandsMask {
|
||||||
|
ImageOperandsMaskNone = 0,
|
||||||
|
ImageOperandsBiasMask = 0x00000001,
|
||||||
|
ImageOperandsLodMask = 0x00000002,
|
||||||
|
ImageOperandsGradMask = 0x00000004,
|
||||||
|
ImageOperandsConstOffsetMask = 0x00000008,
|
||||||
|
ImageOperandsOffsetMask = 0x00000010,
|
||||||
|
ImageOperandsConstOffsetsMask = 0x00000020,
|
||||||
|
ImageOperandsSampleMask = 0x00000040,
|
||||||
|
ImageOperandsMinLodMask = 0x00000080,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FPFastMathModeShift {
|
||||||
|
FPFastMathModeNotNaNShift = 0,
|
||||||
|
FPFastMathModeNotInfShift = 1,
|
||||||
|
FPFastMathModeNSZShift = 2,
|
||||||
|
FPFastMathModeAllowRecipShift = 3,
|
||||||
|
FPFastMathModeFastShift = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FPFastMathModeMask {
|
||||||
|
FPFastMathModeMaskNone = 0,
|
||||||
|
FPFastMathModeNotNaNMask = 0x00000001,
|
||||||
|
FPFastMathModeNotInfMask = 0x00000002,
|
||||||
|
FPFastMathModeNSZMask = 0x00000004,
|
||||||
|
FPFastMathModeAllowRecipMask = 0x00000008,
|
||||||
|
FPFastMathModeFastMask = 0x00000010,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FPRoundingMode {
|
||||||
|
FPRoundingModeRTE = 0,
|
||||||
|
FPRoundingModeRTZ = 1,
|
||||||
|
FPRoundingModeRTP = 2,
|
||||||
|
FPRoundingModeRTN = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LinkageType {
|
||||||
|
LinkageTypeExport = 0,
|
||||||
|
LinkageTypeImport = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AccessQualifier {
|
||||||
|
AccessQualifierReadOnly = 0,
|
||||||
|
AccessQualifierWriteOnly = 1,
|
||||||
|
AccessQualifierReadWrite = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FunctionParameterAttribute {
|
||||||
|
FunctionParameterAttributeZext = 0,
|
||||||
|
FunctionParameterAttributeSext = 1,
|
||||||
|
FunctionParameterAttributeByVal = 2,
|
||||||
|
FunctionParameterAttributeSret = 3,
|
||||||
|
FunctionParameterAttributeNoAlias = 4,
|
||||||
|
FunctionParameterAttributeNoCapture = 5,
|
||||||
|
FunctionParameterAttributeNoWrite = 6,
|
||||||
|
FunctionParameterAttributeNoReadWrite = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Decoration {
|
||||||
|
DecorationRelaxedPrecision = 0,
|
||||||
|
DecorationSpecId = 1,
|
||||||
|
DecorationBlock = 2,
|
||||||
|
DecorationBufferBlock = 3,
|
||||||
|
DecorationRowMajor = 4,
|
||||||
|
DecorationColMajor = 5,
|
||||||
|
DecorationArrayStride = 6,
|
||||||
|
DecorationMatrixStride = 7,
|
||||||
|
DecorationGLSLShared = 8,
|
||||||
|
DecorationGLSLPacked = 9,
|
||||||
|
DecorationCPacked = 10,
|
||||||
|
DecorationBuiltIn = 11,
|
||||||
|
DecorationNoPerspective = 13,
|
||||||
|
DecorationFlat = 14,
|
||||||
|
DecorationPatch = 15,
|
||||||
|
DecorationCentroid = 16,
|
||||||
|
DecorationSample = 17,
|
||||||
|
DecorationInvariant = 18,
|
||||||
|
DecorationRestrict = 19,
|
||||||
|
DecorationAliased = 20,
|
||||||
|
DecorationVolatile = 21,
|
||||||
|
DecorationConstant = 22,
|
||||||
|
DecorationCoherent = 23,
|
||||||
|
DecorationNonWritable = 24,
|
||||||
|
DecorationNonReadable = 25,
|
||||||
|
DecorationUniform = 26,
|
||||||
|
DecorationSaturatedConversion = 28,
|
||||||
|
DecorationStream = 29,
|
||||||
|
DecorationLocation = 30,
|
||||||
|
DecorationComponent = 31,
|
||||||
|
DecorationIndex = 32,
|
||||||
|
DecorationBinding = 33,
|
||||||
|
DecorationDescriptorSet = 34,
|
||||||
|
DecorationOffset = 35,
|
||||||
|
DecorationXfbBuffer = 36,
|
||||||
|
DecorationXfbStride = 37,
|
||||||
|
DecorationFuncParamAttr = 38,
|
||||||
|
DecorationFPRoundingMode = 39,
|
||||||
|
DecorationFPFastMathMode = 40,
|
||||||
|
DecorationLinkageAttributes = 41,
|
||||||
|
DecorationNoContraction = 42,
|
||||||
|
DecorationInputAttachmentIndex = 43,
|
||||||
|
DecorationAlignment = 44,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BuiltIn {
|
||||||
|
BuiltInPosition = 0,
|
||||||
|
BuiltInPointSize = 1,
|
||||||
|
BuiltInClipDistance = 3,
|
||||||
|
BuiltInCullDistance = 4,
|
||||||
|
BuiltInVertexId = 5,
|
||||||
|
BuiltInInstanceId = 6,
|
||||||
|
BuiltInPrimitiveId = 7,
|
||||||
|
BuiltInInvocationId = 8,
|
||||||
|
BuiltInLayer = 9,
|
||||||
|
BuiltInViewportIndex = 10,
|
||||||
|
BuiltInTessLevelOuter = 11,
|
||||||
|
BuiltInTessLevelInner = 12,
|
||||||
|
BuiltInTessCoord = 13,
|
||||||
|
BuiltInPatchVertices = 14,
|
||||||
|
BuiltInFragCoord = 15,
|
||||||
|
BuiltInPointCoord = 16,
|
||||||
|
BuiltInFrontFacing = 17,
|
||||||
|
BuiltInSampleId = 18,
|
||||||
|
BuiltInSamplePosition = 19,
|
||||||
|
BuiltInSampleMask = 20,
|
||||||
|
BuiltInFragDepth = 22,
|
||||||
|
BuiltInHelperInvocation = 23,
|
||||||
|
BuiltInNumWorkgroups = 24,
|
||||||
|
BuiltInWorkgroupSize = 25,
|
||||||
|
BuiltInWorkgroupId = 26,
|
||||||
|
BuiltInLocalInvocationId = 27,
|
||||||
|
BuiltInGlobalInvocationId = 28,
|
||||||
|
BuiltInLocalInvocationIndex = 29,
|
||||||
|
BuiltInWorkDim = 30,
|
||||||
|
BuiltInGlobalSize = 31,
|
||||||
|
BuiltInEnqueuedWorkgroupSize = 32,
|
||||||
|
BuiltInGlobalOffset = 33,
|
||||||
|
BuiltInGlobalLinearId = 34,
|
||||||
|
BuiltInSubgroupSize = 36,
|
||||||
|
BuiltInSubgroupMaxSize = 37,
|
||||||
|
BuiltInNumSubgroups = 38,
|
||||||
|
BuiltInNumEnqueuedSubgroups = 39,
|
||||||
|
BuiltInSubgroupId = 40,
|
||||||
|
BuiltInSubgroupLocalInvocationId = 41,
|
||||||
|
BuiltInVertexIndex = 42,
|
||||||
|
BuiltInInstanceIndex = 43,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SelectionControlShift {
|
||||||
|
SelectionControlFlattenShift = 0,
|
||||||
|
SelectionControlDontFlattenShift = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SelectionControlMask {
|
||||||
|
SelectionControlMaskNone = 0,
|
||||||
|
SelectionControlFlattenMask = 0x00000001,
|
||||||
|
SelectionControlDontFlattenMask = 0x00000002,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LoopControlShift {
|
||||||
|
LoopControlUnrollShift = 0,
|
||||||
|
LoopControlDontUnrollShift = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LoopControlMask {
|
||||||
|
LoopControlMaskNone = 0,
|
||||||
|
LoopControlUnrollMask = 0x00000001,
|
||||||
|
LoopControlDontUnrollMask = 0x00000002,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FunctionControlShift {
|
||||||
|
FunctionControlInlineShift = 0,
|
||||||
|
FunctionControlDontInlineShift = 1,
|
||||||
|
FunctionControlPureShift = 2,
|
||||||
|
FunctionControlConstShift = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FunctionControlMask {
|
||||||
|
FunctionControlMaskNone = 0,
|
||||||
|
FunctionControlInlineMask = 0x00000001,
|
||||||
|
FunctionControlDontInlineMask = 0x00000002,
|
||||||
|
FunctionControlPureMask = 0x00000004,
|
||||||
|
FunctionControlConstMask = 0x00000008,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MemorySemanticsShift {
|
||||||
|
MemorySemanticsAcquireShift = 1,
|
||||||
|
MemorySemanticsReleaseShift = 2,
|
||||||
|
MemorySemanticsAcquireReleaseShift = 3,
|
||||||
|
MemorySemanticsSequentiallyConsistentShift = 4,
|
||||||
|
MemorySemanticsUniformMemoryShift = 6,
|
||||||
|
MemorySemanticsSubgroupMemoryShift = 7,
|
||||||
|
MemorySemanticsWorkgroupMemoryShift = 8,
|
||||||
|
MemorySemanticsCrossWorkgroupMemoryShift = 9,
|
||||||
|
MemorySemanticsAtomicCounterMemoryShift = 10,
|
||||||
|
MemorySemanticsImageMemoryShift = 11,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MemorySemanticsMask {
|
||||||
|
MemorySemanticsMaskNone = 0,
|
||||||
|
MemorySemanticsAcquireMask = 0x00000002,
|
||||||
|
MemorySemanticsReleaseMask = 0x00000004,
|
||||||
|
MemorySemanticsAcquireReleaseMask = 0x00000008,
|
||||||
|
MemorySemanticsSequentiallyConsistentMask = 0x00000010,
|
||||||
|
MemorySemanticsUniformMemoryMask = 0x00000040,
|
||||||
|
MemorySemanticsSubgroupMemoryMask = 0x00000080,
|
||||||
|
MemorySemanticsWorkgroupMemoryMask = 0x00000100,
|
||||||
|
MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,
|
||||||
|
MemorySemanticsAtomicCounterMemoryMask = 0x00000400,
|
||||||
|
MemorySemanticsImageMemoryMask = 0x00000800,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MemoryAccessShift {
|
||||||
|
MemoryAccessVolatileShift = 0,
|
||||||
|
MemoryAccessAlignedShift = 1,
|
||||||
|
MemoryAccessNontemporalShift = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MemoryAccessMask {
|
||||||
|
MemoryAccessMaskNone = 0,
|
||||||
|
MemoryAccessVolatileMask = 0x00000001,
|
||||||
|
MemoryAccessAlignedMask = 0x00000002,
|
||||||
|
MemoryAccessNontemporalMask = 0x00000004,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Scope {
|
||||||
|
ScopeCrossDevice = 0,
|
||||||
|
ScopeDevice = 1,
|
||||||
|
ScopeWorkgroup = 2,
|
||||||
|
ScopeSubgroup = 3,
|
||||||
|
ScopeInvocation = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GroupOperation {
|
||||||
|
GroupOperationReduce = 0,
|
||||||
|
GroupOperationInclusiveScan = 1,
|
||||||
|
GroupOperationExclusiveScan = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KernelEnqueueFlags {
|
||||||
|
KernelEnqueueFlagsNoWait = 0,
|
||||||
|
KernelEnqueueFlagsWaitKernel = 1,
|
||||||
|
KernelEnqueueFlagsWaitWorkGroup = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KernelProfilingInfoShift {
|
||||||
|
KernelProfilingInfoCmdExecTimeShift = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KernelProfilingInfoMask {
|
||||||
|
KernelProfilingInfoMaskNone = 0,
|
||||||
|
KernelProfilingInfoCmdExecTimeMask = 0x00000001,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Capability {
|
||||||
|
CapabilityMatrix = 0,
|
||||||
|
CapabilityShader = 1,
|
||||||
|
CapabilityGeometry = 2,
|
||||||
|
CapabilityTessellation = 3,
|
||||||
|
CapabilityAddresses = 4,
|
||||||
|
CapabilityLinkage = 5,
|
||||||
|
CapabilityKernel = 6,
|
||||||
|
CapabilityVector16 = 7,
|
||||||
|
CapabilityFloat16Buffer = 8,
|
||||||
|
CapabilityFloat16 = 9,
|
||||||
|
CapabilityFloat64 = 10,
|
||||||
|
CapabilityInt64 = 11,
|
||||||
|
CapabilityInt64Atomics = 12,
|
||||||
|
CapabilityImageBasic = 13,
|
||||||
|
CapabilityImageReadWrite = 14,
|
||||||
|
CapabilityImageMipmap = 15,
|
||||||
|
CapabilityPipes = 17,
|
||||||
|
CapabilityGroups = 18,
|
||||||
|
CapabilityDeviceEnqueue = 19,
|
||||||
|
CapabilityLiteralSampler = 20,
|
||||||
|
CapabilityAtomicStorage = 21,
|
||||||
|
CapabilityInt16 = 22,
|
||||||
|
CapabilityTessellationPointSize = 23,
|
||||||
|
CapabilityGeometryPointSize = 24,
|
||||||
|
CapabilityImageGatherExtended = 25,
|
||||||
|
CapabilityStorageImageMultisample = 27,
|
||||||
|
CapabilityUniformBufferArrayDynamicIndexing = 28,
|
||||||
|
CapabilitySampledImageArrayDynamicIndexing = 29,
|
||||||
|
CapabilityStorageBufferArrayDynamicIndexing = 30,
|
||||||
|
CapabilityStorageImageArrayDynamicIndexing = 31,
|
||||||
|
CapabilityClipDistance = 32,
|
||||||
|
CapabilityCullDistance = 33,
|
||||||
|
CapabilityImageCubeArray = 34,
|
||||||
|
CapabilitySampleRateShading = 35,
|
||||||
|
CapabilityImageRect = 36,
|
||||||
|
CapabilitySampledRect = 37,
|
||||||
|
CapabilityGenericPointer = 38,
|
||||||
|
CapabilityInt8 = 39,
|
||||||
|
CapabilityInputAttachment = 40,
|
||||||
|
CapabilitySparseResidency = 41,
|
||||||
|
CapabilityMinLod = 42,
|
||||||
|
CapabilitySampled1D = 43,
|
||||||
|
CapabilityImage1D = 44,
|
||||||
|
CapabilitySampledCubeArray = 45,
|
||||||
|
CapabilitySampledBuffer = 46,
|
||||||
|
CapabilityImageBuffer = 47,
|
||||||
|
CapabilityImageMSArray = 48,
|
||||||
|
CapabilityStorageImageExtendedFormats = 49,
|
||||||
|
CapabilityImageQuery = 50,
|
||||||
|
CapabilityDerivativeControl = 51,
|
||||||
|
CapabilityInterpolationFunction = 52,
|
||||||
|
CapabilityTransformFeedback = 53,
|
||||||
|
CapabilityGeometryStreams = 54,
|
||||||
|
CapabilityStorageImageReadWithoutFormat = 55,
|
||||||
|
CapabilityStorageImageWriteWithoutFormat = 56,
|
||||||
|
CapabilityMultiViewport = 57,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Op {
|
||||||
|
OpNop = 0,
|
||||||
|
OpUndef = 1,
|
||||||
|
OpSourceContinued = 2,
|
||||||
|
OpSource = 3,
|
||||||
|
OpSourceExtension = 4,
|
||||||
|
OpName = 5,
|
||||||
|
OpMemberName = 6,
|
||||||
|
OpString = 7,
|
||||||
|
OpLine = 8,
|
||||||
|
OpExtension = 10,
|
||||||
|
OpExtInstImport = 11,
|
||||||
|
OpExtInst = 12,
|
||||||
|
OpMemoryModel = 14,
|
||||||
|
OpEntryPoint = 15,
|
||||||
|
OpExecutionMode = 16,
|
||||||
|
OpCapability = 17,
|
||||||
|
OpTypeVoid = 19,
|
||||||
|
OpTypeBool = 20,
|
||||||
|
OpTypeInt = 21,
|
||||||
|
OpTypeFloat = 22,
|
||||||
|
OpTypeVector = 23,
|
||||||
|
OpTypeMatrix = 24,
|
||||||
|
OpTypeImage = 25,
|
||||||
|
OpTypeSampler = 26,
|
||||||
|
OpTypeSampledImage = 27,
|
||||||
|
OpTypeArray = 28,
|
||||||
|
OpTypeRuntimeArray = 29,
|
||||||
|
OpTypeStruct = 30,
|
||||||
|
OpTypeOpaque = 31,
|
||||||
|
OpTypePointer = 32,
|
||||||
|
OpTypeFunction = 33,
|
||||||
|
OpTypeEvent = 34,
|
||||||
|
OpTypeDeviceEvent = 35,
|
||||||
|
OpTypeReserveId = 36,
|
||||||
|
OpTypeQueue = 37,
|
||||||
|
OpTypePipe = 38,
|
||||||
|
OpTypeForwardPointer = 39,
|
||||||
|
OpConstantTrue = 41,
|
||||||
|
OpConstantFalse = 42,
|
||||||
|
OpConstant = 43,
|
||||||
|
OpConstantComposite = 44,
|
||||||
|
OpConstantSampler = 45,
|
||||||
|
OpConstantNull = 46,
|
||||||
|
OpSpecConstantTrue = 48,
|
||||||
|
OpSpecConstantFalse = 49,
|
||||||
|
OpSpecConstant = 50,
|
||||||
|
OpSpecConstantComposite = 51,
|
||||||
|
OpSpecConstantOp = 52,
|
||||||
|
OpFunction = 54,
|
||||||
|
OpFunctionParameter = 55,
|
||||||
|
OpFunctionEnd = 56,
|
||||||
|
OpFunctionCall = 57,
|
||||||
|
OpVariable = 59,
|
||||||
|
OpImageTexelPointer = 60,
|
||||||
|
OpLoad = 61,
|
||||||
|
OpStore = 62,
|
||||||
|
OpCopyMemory = 63,
|
||||||
|
OpCopyMemorySized = 64,
|
||||||
|
OpAccessChain = 65,
|
||||||
|
OpInBoundsAccessChain = 66,
|
||||||
|
OpPtrAccessChain = 67,
|
||||||
|
OpArrayLength = 68,
|
||||||
|
OpGenericPtrMemSemantics = 69,
|
||||||
|
OpInBoundsPtrAccessChain = 70,
|
||||||
|
OpDecorate = 71,
|
||||||
|
OpMemberDecorate = 72,
|
||||||
|
OpDecorationGroup = 73,
|
||||||
|
OpGroupDecorate = 74,
|
||||||
|
OpGroupMemberDecorate = 75,
|
||||||
|
OpVectorExtractDynamic = 77,
|
||||||
|
OpVectorInsertDynamic = 78,
|
||||||
|
OpVectorShuffle = 79,
|
||||||
|
OpCompositeConstruct = 80,
|
||||||
|
OpCompositeExtract = 81,
|
||||||
|
OpCompositeInsert = 82,
|
||||||
|
OpCopyObject = 83,
|
||||||
|
OpTranspose = 84,
|
||||||
|
OpSampledImage = 86,
|
||||||
|
OpImageSampleImplicitLod = 87,
|
||||||
|
OpImageSampleExplicitLod = 88,
|
||||||
|
OpImageSampleDrefImplicitLod = 89,
|
||||||
|
OpImageSampleDrefExplicitLod = 90,
|
||||||
|
OpImageSampleProjImplicitLod = 91,
|
||||||
|
OpImageSampleProjExplicitLod = 92,
|
||||||
|
OpImageSampleProjDrefImplicitLod = 93,
|
||||||
|
OpImageSampleProjDrefExplicitLod = 94,
|
||||||
|
OpImageFetch = 95,
|
||||||
|
OpImageGather = 96,
|
||||||
|
OpImageDrefGather = 97,
|
||||||
|
OpImageRead = 98,
|
||||||
|
OpImageWrite = 99,
|
||||||
|
OpImage = 100,
|
||||||
|
OpImageQueryFormat = 101,
|
||||||
|
OpImageQueryOrder = 102,
|
||||||
|
OpImageQuerySizeLod = 103,
|
||||||
|
OpImageQuerySize = 104,
|
||||||
|
OpImageQueryLod = 105,
|
||||||
|
OpImageQueryLevels = 106,
|
||||||
|
OpImageQuerySamples = 107,
|
||||||
|
OpConvertFToU = 109,
|
||||||
|
OpConvertFToS = 110,
|
||||||
|
OpConvertSToF = 111,
|
||||||
|
OpConvertUToF = 112,
|
||||||
|
OpUConvert = 113,
|
||||||
|
OpSConvert = 114,
|
||||||
|
OpFConvert = 115,
|
||||||
|
OpQuantizeToF16 = 116,
|
||||||
|
OpConvertPtrToU = 117,
|
||||||
|
OpSatConvertSToU = 118,
|
||||||
|
OpSatConvertUToS = 119,
|
||||||
|
OpConvertUToPtr = 120,
|
||||||
|
OpPtrCastToGeneric = 121,
|
||||||
|
OpGenericCastToPtr = 122,
|
||||||
|
OpGenericCastToPtrExplicit = 123,
|
||||||
|
OpBitcast = 124,
|
||||||
|
OpSNegate = 126,
|
||||||
|
OpFNegate = 127,
|
||||||
|
OpIAdd = 128,
|
||||||
|
OpFAdd = 129,
|
||||||
|
OpISub = 130,
|
||||||
|
OpFSub = 131,
|
||||||
|
OpIMul = 132,
|
||||||
|
OpFMul = 133,
|
||||||
|
OpUDiv = 134,
|
||||||
|
OpSDiv = 135,
|
||||||
|
OpFDiv = 136,
|
||||||
|
OpUMod = 137,
|
||||||
|
OpSRem = 138,
|
||||||
|
OpSMod = 139,
|
||||||
|
OpFRem = 140,
|
||||||
|
OpFMod = 141,
|
||||||
|
OpVectorTimesScalar = 142,
|
||||||
|
OpMatrixTimesScalar = 143,
|
||||||
|
OpVectorTimesMatrix = 144,
|
||||||
|
OpMatrixTimesVector = 145,
|
||||||
|
OpMatrixTimesMatrix = 146,
|
||||||
|
OpOuterProduct = 147,
|
||||||
|
OpDot = 148,
|
||||||
|
OpIAddCarry = 149,
|
||||||
|
OpISubBorrow = 150,
|
||||||
|
OpUMulExtended = 151,
|
||||||
|
OpSMulExtended = 152,
|
||||||
|
OpAny = 154,
|
||||||
|
OpAll = 155,
|
||||||
|
OpIsNan = 156,
|
||||||
|
OpIsInf = 157,
|
||||||
|
OpIsFinite = 158,
|
||||||
|
OpIsNormal = 159,
|
||||||
|
OpSignBitSet = 160,
|
||||||
|
OpLessOrGreater = 161,
|
||||||
|
OpOrdered = 162,
|
||||||
|
OpUnordered = 163,
|
||||||
|
OpLogicalEqual = 164,
|
||||||
|
OpLogicalNotEqual = 165,
|
||||||
|
OpLogicalOr = 166,
|
||||||
|
OpLogicalAnd = 167,
|
||||||
|
OpLogicalNot = 168,
|
||||||
|
OpSelect = 169,
|
||||||
|
OpIEqual = 170,
|
||||||
|
OpINotEqual = 171,
|
||||||
|
OpUGreaterThan = 172,
|
||||||
|
OpSGreaterThan = 173,
|
||||||
|
OpUGreaterThanEqual = 174,
|
||||||
|
OpSGreaterThanEqual = 175,
|
||||||
|
OpULessThan = 176,
|
||||||
|
OpSLessThan = 177,
|
||||||
|
OpULessThanEqual = 178,
|
||||||
|
OpSLessThanEqual = 179,
|
||||||
|
OpFOrdEqual = 180,
|
||||||
|
OpFUnordEqual = 181,
|
||||||
|
OpFOrdNotEqual = 182,
|
||||||
|
OpFUnordNotEqual = 183,
|
||||||
|
OpFOrdLessThan = 184,
|
||||||
|
OpFUnordLessThan = 185,
|
||||||
|
OpFOrdGreaterThan = 186,
|
||||||
|
OpFUnordGreaterThan = 187,
|
||||||
|
OpFOrdLessThanEqual = 188,
|
||||||
|
OpFUnordLessThanEqual = 189,
|
||||||
|
OpFOrdGreaterThanEqual = 190,
|
||||||
|
OpFUnordGreaterThanEqual = 191,
|
||||||
|
OpShiftRightLogical = 194,
|
||||||
|
OpShiftRightArithmetic = 195,
|
||||||
|
OpShiftLeftLogical = 196,
|
||||||
|
OpBitwiseOr = 197,
|
||||||
|
OpBitwiseXor = 198,
|
||||||
|
OpBitwiseAnd = 199,
|
||||||
|
OpNot = 200,
|
||||||
|
OpBitFieldInsert = 201,
|
||||||
|
OpBitFieldSExtract = 202,
|
||||||
|
OpBitFieldUExtract = 203,
|
||||||
|
OpBitReverse = 204,
|
||||||
|
OpBitCount = 205,
|
||||||
|
OpDPdx = 207,
|
||||||
|
OpDPdy = 208,
|
||||||
|
OpFwidth = 209,
|
||||||
|
OpDPdxFine = 210,
|
||||||
|
OpDPdyFine = 211,
|
||||||
|
OpFwidthFine = 212,
|
||||||
|
OpDPdxCoarse = 213,
|
||||||
|
OpDPdyCoarse = 214,
|
||||||
|
OpFwidthCoarse = 215,
|
||||||
|
OpEmitVertex = 218,
|
||||||
|
OpEndPrimitive = 219,
|
||||||
|
OpEmitStreamVertex = 220,
|
||||||
|
OpEndStreamPrimitive = 221,
|
||||||
|
OpControlBarrier = 224,
|
||||||
|
OpMemoryBarrier = 225,
|
||||||
|
OpAtomicLoad = 227,
|
||||||
|
OpAtomicStore = 228,
|
||||||
|
OpAtomicExchange = 229,
|
||||||
|
OpAtomicCompareExchange = 230,
|
||||||
|
OpAtomicCompareExchangeWeak = 231,
|
||||||
|
OpAtomicIIncrement = 232,
|
||||||
|
OpAtomicIDecrement = 233,
|
||||||
|
OpAtomicIAdd = 234,
|
||||||
|
OpAtomicISub = 235,
|
||||||
|
OpAtomicSMin = 236,
|
||||||
|
OpAtomicUMin = 237,
|
||||||
|
OpAtomicSMax = 238,
|
||||||
|
OpAtomicUMax = 239,
|
||||||
|
OpAtomicAnd = 240,
|
||||||
|
OpAtomicOr = 241,
|
||||||
|
OpAtomicXor = 242,
|
||||||
|
OpPhi = 245,
|
||||||
|
OpLoopMerge = 246,
|
||||||
|
OpSelectionMerge = 247,
|
||||||
|
OpLabel = 248,
|
||||||
|
OpBranch = 249,
|
||||||
|
OpBranchConditional = 250,
|
||||||
|
OpSwitch = 251,
|
||||||
|
OpKill = 252,
|
||||||
|
OpReturn = 253,
|
||||||
|
OpReturnValue = 254,
|
||||||
|
OpUnreachable = 255,
|
||||||
|
OpLifetimeStart = 256,
|
||||||
|
OpLifetimeStop = 257,
|
||||||
|
OpGroupAsyncCopy = 259,
|
||||||
|
OpGroupWaitEvents = 260,
|
||||||
|
OpGroupAll = 261,
|
||||||
|
OpGroupAny = 262,
|
||||||
|
OpGroupBroadcast = 263,
|
||||||
|
OpGroupIAdd = 264,
|
||||||
|
OpGroupFAdd = 265,
|
||||||
|
OpGroupFMin = 266,
|
||||||
|
OpGroupUMin = 267,
|
||||||
|
OpGroupSMin = 268,
|
||||||
|
OpGroupFMax = 269,
|
||||||
|
OpGroupUMax = 270,
|
||||||
|
OpGroupSMax = 271,
|
||||||
|
OpReadPipe = 274,
|
||||||
|
OpWritePipe = 275,
|
||||||
|
OpReservedReadPipe = 276,
|
||||||
|
OpReservedWritePipe = 277,
|
||||||
|
OpReserveReadPipePackets = 278,
|
||||||
|
OpReserveWritePipePackets = 279,
|
||||||
|
OpCommitReadPipe = 280,
|
||||||
|
OpCommitWritePipe = 281,
|
||||||
|
OpIsValidReserveId = 282,
|
||||||
|
OpGetNumPipePackets = 283,
|
||||||
|
OpGetMaxPipePackets = 284,
|
||||||
|
OpGroupReserveReadPipePackets = 285,
|
||||||
|
OpGroupReserveWritePipePackets = 286,
|
||||||
|
OpGroupCommitReadPipe = 287,
|
||||||
|
OpGroupCommitWritePipe = 288,
|
||||||
|
OpEnqueueMarker = 291,
|
||||||
|
OpEnqueueKernel = 292,
|
||||||
|
OpGetKernelNDrangeSubGroupCount = 293,
|
||||||
|
OpGetKernelNDrangeMaxSubGroupSize = 294,
|
||||||
|
OpGetKernelWorkGroupSize = 295,
|
||||||
|
OpGetKernelPreferredWorkGroupSizeMultiple = 296,
|
||||||
|
OpRetainEvent = 297,
|
||||||
|
OpReleaseEvent = 298,
|
||||||
|
OpCreateUserEvent = 299,
|
||||||
|
OpIsValidEvent = 300,
|
||||||
|
OpSetUserEventStatus = 301,
|
||||||
|
OpCaptureEventProfilingInfo = 302,
|
||||||
|
OpGetDefaultQueue = 303,
|
||||||
|
OpBuildNDRange = 304,
|
||||||
|
OpImageSparseSampleImplicitLod = 305,
|
||||||
|
OpImageSparseSampleExplicitLod = 306,
|
||||||
|
OpImageSparseSampleDrefImplicitLod = 307,
|
||||||
|
OpImageSparseSampleDrefExplicitLod = 308,
|
||||||
|
OpImageSparseSampleProjImplicitLod = 309,
|
||||||
|
OpImageSparseSampleProjExplicitLod = 310,
|
||||||
|
OpImageSparseSampleProjDrefImplicitLod = 311,
|
||||||
|
OpImageSparseSampleProjDrefExplicitLod = 312,
|
||||||
|
OpImageSparseFetch = 313,
|
||||||
|
OpImageSparseGather = 314,
|
||||||
|
OpImageSparseDrefGather = 315,
|
||||||
|
OpImageSparseTexelsResident = 316,
|
||||||
|
OpNoLine = 317,
|
||||||
|
OpAtomicFlagTestAndSet = 318,
|
||||||
|
OpAtomicFlagClear = 319,
|
||||||
|
OpImageSparseRead = 320,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Overload operator| for mask bit combining
|
||||||
|
|
||||||
|
inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
|
||||||
|
inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
|
||||||
|
|
||||||
|
} // end namespace spv
|
||||||
|
|
||||||
|
#endif // #ifndef spirv_HPP
|
127
test_shaders.py
Executable file
127
test_shaders.py
Executable file
@ -0,0 +1,127 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import re
|
||||||
|
import itertools
|
||||||
|
import hashlib
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
def parse_stats(stats):
|
||||||
|
m = re.search('([0-9]+) work registers', stats)
|
||||||
|
registers = int(m.group(1)) if m else 0
|
||||||
|
|
||||||
|
m = re.search('([0-9]+) uniform registers', stats)
|
||||||
|
uniform_regs = int(m.group(1)) if m else 0
|
||||||
|
|
||||||
|
m_list = re.findall('(-?[0-9]+)\s+(-?[0-9]+)\s+(-?[0-9]+)', stats)
|
||||||
|
alu_short = float(m_list[1][0]) if m_list else 0
|
||||||
|
ls_short = float(m_list[1][1]) if m_list else 0
|
||||||
|
tex_short = float(m_list[1][2]) if m_list else 0
|
||||||
|
alu_long = float(m_list[2][0]) if m_list else 0
|
||||||
|
ls_long = float(m_list[2][1]) if m_list else 0
|
||||||
|
tex_long = float(m_list[2][2]) if m_list else 0
|
||||||
|
|
||||||
|
return (registers, uniform_regs, alu_short, ls_short, tex_short, alu_long, ls_long, tex_long)
|
||||||
|
|
||||||
|
def get_shader_type(shader):
|
||||||
|
_, ext = os.path.splitext(shader)
|
||||||
|
if ext == '.vert':
|
||||||
|
return '--vertex'
|
||||||
|
elif ext == '.frag':
|
||||||
|
return '--fragment'
|
||||||
|
elif ext == '.comp':
|
||||||
|
return '--compute'
|
||||||
|
elif ext == '.tesc':
|
||||||
|
return '--tessellation_control'
|
||||||
|
elif ext == '.tese':
|
||||||
|
return '--tessellation_evaluation'
|
||||||
|
elif ext == '.geom':
|
||||||
|
return '--geometry'
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def get_shader_stats(shader):
|
||||||
|
f, path = tempfile.mkstemp()
|
||||||
|
|
||||||
|
os.close(f)
|
||||||
|
p = subprocess.Popen(['malisc', get_shader_type(shader), '--core', 'Mali-T760', '-V', shader], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
if p.returncode != 0:
|
||||||
|
print(stderr.decode('utf-8'))
|
||||||
|
raise OSError('malisc failed')
|
||||||
|
p.wait()
|
||||||
|
|
||||||
|
returned = stdout.decode('utf-8')
|
||||||
|
return parse_stats(returned)
|
||||||
|
|
||||||
|
def cross_compile(shader):
|
||||||
|
spirv_f, spirv_path = tempfile.mkstemp()
|
||||||
|
glsl_f, glsl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
|
||||||
|
os.close(spirv_f)
|
||||||
|
os.close(glsl_f)
|
||||||
|
|
||||||
|
subprocess.check_call(['glslangValidator', '-G', '-o', spirv_path, shader])
|
||||||
|
subprocess.check_call(['./spir2cross', '--output', glsl_path, spirv_path])
|
||||||
|
return (spirv_path, glsl_path)
|
||||||
|
|
||||||
|
def md5_for_file(path):
|
||||||
|
md5 = hashlib.md5()
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
for chunk in iter(lambda: f.read(8192), b''):
|
||||||
|
md5.update(chunk)
|
||||||
|
return md5.digest()
|
||||||
|
|
||||||
|
def make_reference_dir(path):
|
||||||
|
base = os.path.dirname(path)
|
||||||
|
if not os.path.exists(base):
|
||||||
|
os.makedirs(base)
|
||||||
|
|
||||||
|
def regression_check(shader, glsl):
|
||||||
|
reference = os.path.join('./reference', shader)
|
||||||
|
if os.path.exists(reference):
|
||||||
|
if md5_for_file(glsl) != md5_for_file(reference):
|
||||||
|
print('Generated GLSL has changed for {}!'.format(reference))
|
||||||
|
if os.path.exists(reference):
|
||||||
|
os.remove(reference)
|
||||||
|
make_reference_dir(reference)
|
||||||
|
shutil.move(glsl, reference)
|
||||||
|
else:
|
||||||
|
os.remove(glsl)
|
||||||
|
else:
|
||||||
|
print('Found new shader {}. Placing GLSL in {}'.format(shader, reference))
|
||||||
|
make_reference_dir(reference)
|
||||||
|
shutil.move(glsl, reference)
|
||||||
|
|
||||||
|
def test_shader(stats, shader):
|
||||||
|
print('Testing shader:', shader)
|
||||||
|
pristine_stats = get_shader_stats(shader)
|
||||||
|
spirv, glsl = cross_compile(shader)
|
||||||
|
cross_stats = get_shader_stats(glsl)
|
||||||
|
|
||||||
|
regression_check(shader, glsl)
|
||||||
|
os.remove(spirv)
|
||||||
|
|
||||||
|
a = []
|
||||||
|
a.append(shader)
|
||||||
|
for i in pristine_stats:
|
||||||
|
a.append(str(i))
|
||||||
|
for i in cross_stats:
|
||||||
|
a.append(str(i))
|
||||||
|
print(','.join(a), file = stats)
|
||||||
|
|
||||||
|
def test_shaders(shader_dir):
|
||||||
|
with open('stats.csv', 'w') as stats:
|
||||||
|
print('Shader,OrigRegs,OrigUniRegs,OrigALUShort,OrigLSShort,OrigTEXShort,OrigALULong,OrigLSLong,OrigTEXLong,CrossRegs,CrossUniRegs,CrossALUShort,CrossLSShort,CrossTEXShort,CrossALULong,CrossLSLong,CrossTEXLong', file = stats)
|
||||||
|
for f in os.walk(os.path.join(shader_dir)):
|
||||||
|
for i in f[2]:
|
||||||
|
shader = os.path.join(f[0], i)
|
||||||
|
test_shader(stats, shader)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_shaders(sys.argv[1])
|
||||||
|
print('Stats in stats.csv!')
|
Loading…
Reference in New Issue
Block a user