Externals: Update glslang to upstream commit 32d3ec3
This commit is contained in:
+59
-5
@@ -3,27 +3,81 @@ set(SOURCES
|
||||
InReadableOrder.cpp
|
||||
Logger.cpp
|
||||
SpvBuilder.cpp
|
||||
SPVRemapper.cpp
|
||||
doc.cpp
|
||||
disassemble.cpp)
|
||||
|
||||
set(SPVREMAP_SOURCES
|
||||
SPVRemapper.cpp
|
||||
doc.cpp)
|
||||
|
||||
set(HEADERS
|
||||
bitutils.h
|
||||
spirv.hpp
|
||||
GLSL.std.450.h
|
||||
GLSL.ext.EXT.h
|
||||
GLSL.ext.KHR.h
|
||||
GlslangToSpv.h
|
||||
hex_float.h
|
||||
Logger.h
|
||||
SpvBuilder.h
|
||||
SPVRemapper.h
|
||||
spvIR.h
|
||||
doc.h
|
||||
disassemble.h)
|
||||
|
||||
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
|
||||
set(SPVREMAP_HEADERS
|
||||
SPVRemapper.h
|
||||
doc.h)
|
||||
|
||||
if(ENABLE_AMD_EXTENSIONS)
|
||||
list(APPEND
|
||||
HEADERS
|
||||
GLSL.ext.AMD.h)
|
||||
endif(ENABLE_AMD_EXTENSIONS)
|
||||
|
||||
if(ENABLE_NV_EXTENSIONS)
|
||||
list(APPEND
|
||||
HEADERS
|
||||
GLSL.ext.NV.h)
|
||||
endif(ENABLE_NV_EXTENSIONS)
|
||||
|
||||
add_library(SPIRV ${LIB_TYPE} ${SOURCES} ${HEADERS})
|
||||
set_property(TARGET SPIRV PROPERTY FOLDER glslang)
|
||||
set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(SPIRV PUBLIC ..)
|
||||
|
||||
add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
|
||||
set_property(TARGET SPVRemapper PROPERTY FOLDER glslang)
|
||||
set_property(TARGET SPVRemapper PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(WIN32 AND BUILD_SHARED_LIBS)
|
||||
set_target_properties(SPIRV PROPERTIES PREFIX "")
|
||||
set_target_properties(SPVRemapper PROPERTIES PREFIX "")
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPT)
|
||||
target_include_directories(SPIRV
|
||||
PRIVATE ${spirv-tools_SOURCE_DIR}/include
|
||||
PRIVATE ${spirv-tools_SOURCE_DIR}/source
|
||||
)
|
||||
target_link_libraries(SPIRV glslang SPIRV-Tools-opt)
|
||||
else()
|
||||
target_link_libraries(SPIRV glslang)
|
||||
endif(ENABLE_OPT)
|
||||
|
||||
if(WIN32)
|
||||
source_group("Source" FILES ${SOURCES} ${HEADERS})
|
||||
source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
|
||||
endif(WIN32)
|
||||
|
||||
install(TARGETS SPIRV
|
||||
ARCHIVE DESTINATION lib)
|
||||
if(ENABLE_GLSLANG_INSTALL)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
install(TARGETS SPIRV SPVRemapper
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
else()
|
||||
install(TARGETS SPIRV SPVRemapper
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SPIRV/)
|
||||
endif(ENABLE_GLSLANG_INSTALL)
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
** 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 GLSLextAMD_H
|
||||
#define GLSLextAMD_H
|
||||
|
||||
static const int GLSLextAMDVersion = 100;
|
||||
static const int GLSLextAMDRevision = 7;
|
||||
|
||||
// SPV_AMD_shader_ballot
|
||||
static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
|
||||
|
||||
enum ShaderBallotAMD {
|
||||
ShaderBallotBadAMD = 0, // Don't use
|
||||
|
||||
SwizzleInvocationsAMD = 1,
|
||||
SwizzleInvocationsMaskedAMD = 2,
|
||||
WriteInvocationAMD = 3,
|
||||
MbcntAMD = 4,
|
||||
|
||||
ShaderBallotCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_shader_trinary_minmax
|
||||
static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax";
|
||||
|
||||
enum ShaderTrinaryMinMaxAMD {
|
||||
ShaderTrinaryMinMaxBadAMD = 0, // Don't use
|
||||
|
||||
FMin3AMD = 1,
|
||||
UMin3AMD = 2,
|
||||
SMin3AMD = 3,
|
||||
FMax3AMD = 4,
|
||||
UMax3AMD = 5,
|
||||
SMax3AMD = 6,
|
||||
FMid3AMD = 7,
|
||||
UMid3AMD = 8,
|
||||
SMid3AMD = 9,
|
||||
|
||||
ShaderTrinaryMinMaxCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_shader_explicit_vertex_parameter
|
||||
static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter";
|
||||
|
||||
enum ShaderExplicitVertexParameterAMD {
|
||||
ShaderExplicitVertexParameterBadAMD = 0, // Don't use
|
||||
|
||||
InterpolateAtVertexAMD = 1,
|
||||
|
||||
ShaderExplicitVertexParameterCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_gcn_shader
|
||||
static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader";
|
||||
|
||||
enum GcnShaderAMD {
|
||||
GcnShaderBadAMD = 0, // Don't use
|
||||
|
||||
CubeFaceIndexAMD = 1,
|
||||
CubeFaceCoordAMD = 2,
|
||||
TimeAMD = 3,
|
||||
|
||||
GcnShaderCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_gpu_shader_half_float
|
||||
static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float";
|
||||
|
||||
// SPV_AMD_texture_gather_bias_lod
|
||||
static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod";
|
||||
|
||||
// SPV_AMD_gpu_shader_int16
|
||||
static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16";
|
||||
|
||||
// SPV_AMD_shader_image_load_store_lod
|
||||
static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod";
|
||||
|
||||
// SPV_AMD_shader_fragment_mask
|
||||
static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask";
|
||||
|
||||
// SPV_AMD_gpu_shader_half_float_fetch
|
||||
static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch";
|
||||
|
||||
#endif // #ifndef GLSLextAMD_H
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
** 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 GLSLextEXT_H
|
||||
#define GLSLextEXT_H
|
||||
|
||||
static const int GLSLextEXTVersion = 100;
|
||||
static const int GLSLextEXTRevision = 1;
|
||||
|
||||
static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export";
|
||||
static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer";
|
||||
static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
|
||||
|
||||
#endif // #ifndef GLSLextEXT_H
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
** 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 GLSLextKHR_H
|
||||
#define GLSLextKHR_H
|
||||
|
||||
static const int GLSLextKHRVersion = 100;
|
||||
static const int GLSLextKHRRevision = 2;
|
||||
|
||||
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
|
||||
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
|
||||
static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group";
|
||||
static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview";
|
||||
static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters";
|
||||
static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage";
|
||||
static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class";
|
||||
static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage";
|
||||
|
||||
#endif // #ifndef GLSLextKHR_H
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
** Copyright (c) 2014-2017 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 GLSLextNV_H
|
||||
#define GLSLextNV_H
|
||||
|
||||
enum BuiltIn;
|
||||
enum Decoration;
|
||||
enum Op;
|
||||
enum Capability;
|
||||
|
||||
static const int GLSLextNVVersion = 100;
|
||||
static const int GLSLextNVRevision = 5;
|
||||
|
||||
//SPV_NV_sample_mask_override_coverage
|
||||
const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage";
|
||||
|
||||
//SPV_NV_geometry_shader_passthrough
|
||||
const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough";
|
||||
|
||||
//SPV_NV_viewport_array2
|
||||
const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2";
|
||||
const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array";
|
||||
|
||||
//SPV_NV_stereo_view_rendering
|
||||
const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering";
|
||||
|
||||
//SPV_NVX_multiview_per_view_attributes
|
||||
const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes";
|
||||
|
||||
//SPV_NV_shader_subgroup_partitioned
|
||||
const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned";
|
||||
|
||||
#endif // #ifndef GLSLextNV_H
|
||||
+3121
-570
File diff suppressed because it is too large
Load Diff
+37
-20
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
// Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,18 +19,24 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
|
||||
#include "../glslang/Include/intermediate.h"
|
||||
|
||||
@@ -41,10 +47,21 @@
|
||||
|
||||
namespace glslang {
|
||||
|
||||
struct SpvOptions {
|
||||
SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
|
||||
optimizeSize(false) { }
|
||||
bool generateDebugInfo;
|
||||
bool disableOptimizer;
|
||||
bool optimizeSize;
|
||||
};
|
||||
|
||||
void GetSpirvVersion(std::string&);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger);
|
||||
int GetSpirvGeneratorVersion();
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
SpvOptions* options = nullptr);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
||||
spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
|
||||
void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
|
||||
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName);
|
||||
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
|
||||
|
||||
}
|
||||
|
||||
+25
-25
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2016 Google, Inc.
|
||||
// Copyright (C) 2016 Google, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,18 +19,18 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The SPIR-V spec requires code blocks to appear in an order satisfying the
|
||||
// dominator-tree direction (ie, dominator before the dominated). This is,
|
||||
@@ -51,7 +51,7 @@
|
||||
#include "spvIR.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
using spv::Block;
|
||||
using spv::Id;
|
||||
@@ -69,33 +69,33 @@ public:
|
||||
void visit(Block* block)
|
||||
{
|
||||
assert(block);
|
||||
if (visited_[block] || delayed_[block])
|
||||
if (visited_.count(block) || delayed_.count(block))
|
||||
return;
|
||||
callback_(block);
|
||||
visited_[block] = true;
|
||||
visited_.insert(block);
|
||||
Block* mergeBlock = nullptr;
|
||||
Block* continueBlock = nullptr;
|
||||
auto mergeInst = block->getMergeInstruction();
|
||||
if (mergeInst) {
|
||||
Id mergeId = mergeInst->getIdOperand(0);
|
||||
mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock();
|
||||
delayed_[mergeBlock] = true;
|
||||
delayed_.insert(mergeBlock);
|
||||
if (mergeInst->getOpCode() == spv::OpLoopMerge) {
|
||||
Id continueId = mergeInst->getIdOperand(1);
|
||||
continueBlock =
|
||||
block->getParent().getParent().getInstruction(continueId)->getBlock();
|
||||
delayed_[continueBlock] = true;
|
||||
delayed_.insert(continueBlock);
|
||||
}
|
||||
}
|
||||
const auto successors = block->getSuccessors();
|
||||
for (auto it = successors.cbegin(); it != successors.cend(); ++it)
|
||||
visit(*it);
|
||||
if (continueBlock) {
|
||||
delayed_[continueBlock] = false;
|
||||
delayed_.erase(continueBlock);
|
||||
visit(continueBlock);
|
||||
}
|
||||
if (mergeBlock) {
|
||||
delayed_[mergeBlock] = false;
|
||||
delayed_.erase(mergeBlock);
|
||||
visit(mergeBlock);
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
private:
|
||||
std::function<void(Block*)> callback_;
|
||||
// Whether a block has already been visited or is being delayed.
|
||||
std::unordered_map<Block *, bool> visited_, delayed_;
|
||||
std::unordered_set<Block *> visited_, delayed_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+355
-117
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2015 LunarG, Inc.
|
||||
// Copyright (C) 2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,18 +19,18 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include "SPVRemapper.h"
|
||||
@@ -103,10 +103,10 @@ namespace spv {
|
||||
|
||||
switch (opCode) {
|
||||
case spv::OpTypeVector: // fall through
|
||||
case spv::OpTypeMatrix: // ...
|
||||
case spv::OpTypeSampler: // ...
|
||||
case spv::OpTypeArray: // ...
|
||||
case spv::OpTypeRuntimeArray: // ...
|
||||
case spv::OpTypeMatrix: // ...
|
||||
case spv::OpTypeSampler: // ...
|
||||
case spv::OpTypeArray: // ...
|
||||
case spv::OpTypeRuntimeArray: // ...
|
||||
case spv::OpTypePipe: return range_t(2, 3);
|
||||
case spv::OpTypeStruct: // fall through
|
||||
case spv::OpTypeFunction: return range_t(2, maxCount);
|
||||
@@ -127,6 +127,38 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return the size of a type in 32-bit words. This currently only
|
||||
// handles ints and floats, and is only invoked by queries which must be
|
||||
// integer types. If ever needed, it can be generalized.
|
||||
unsigned spirvbin_t::typeSizeInWords(spv::Id id) const
|
||||
{
|
||||
const unsigned typeStart = idPos(id);
|
||||
const spv::Op opCode = asOpCode(typeStart);
|
||||
|
||||
if (errorLatch)
|
||||
return 0;
|
||||
|
||||
switch (opCode) {
|
||||
case spv::OpTypeInt: // fall through...
|
||||
case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Looks up the type of a given const or variable ID, and
|
||||
// returns its size in 32-bit words.
|
||||
unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const
|
||||
{
|
||||
const auto tid_it = idTypeSizeMap.find(id);
|
||||
if (tid_it == idTypeSizeMap.end()) {
|
||||
error("type size for ID not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tid_it->second;
|
||||
}
|
||||
|
||||
// Is this an opcode we should remove when using --strip?
|
||||
bool spirvbin_t::isStripOp(spv::Op opCode) const
|
||||
{
|
||||
@@ -140,6 +172,7 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if this opcode is flow control
|
||||
bool spirvbin_t::isFlowCtrl(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
@@ -155,6 +188,7 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if this opcode defines a type
|
||||
bool spirvbin_t::isTypeOp(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
@@ -182,17 +216,23 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if this opcode defines a constant
|
||||
bool spirvbin_t::isConstOp(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
case spv::OpConstantNull: error("unimplemented constant type");
|
||||
case spv::OpConstantSampler: error("unimplemented constant type");
|
||||
case spv::OpConstantNull:
|
||||
case spv::OpConstantSampler:
|
||||
error("unimplemented constant type");
|
||||
return true;
|
||||
|
||||
case spv::OpConstantTrue:
|
||||
case spv::OpConstantFalse:
|
||||
case spv::OpConstantComposite:
|
||||
case spv::OpConstant: return true;
|
||||
default: return false;
|
||||
case spv::OpConstant:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,21 +256,33 @@ namespace spv {
|
||||
|
||||
spv::Id spirvbin_t::localId(spv::Id id, spv::Id newId)
|
||||
{
|
||||
assert(id != spv::NoResult && newId != spv::NoResult);
|
||||
//assert(id != spv::NoResult && newId != spv::NoResult);
|
||||
|
||||
if (id > bound()) {
|
||||
error(std::string("ID out of range: ") + std::to_string(id));
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
if (id >= idMapL.size())
|
||||
idMapL.resize(id+1, unused);
|
||||
|
||||
if (newId != unmapped && newId != unused) {
|
||||
if (isOldIdUnused(id))
|
||||
if (isOldIdUnused(id)) {
|
||||
error(std::string("ID unused in module: ") + std::to_string(id));
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
if (!isOldIdUnmapped(id))
|
||||
if (!isOldIdUnmapped(id)) {
|
||||
error(std::string("ID already mapped: ") + std::to_string(id) + " -> "
|
||||
+ std::to_string(localId(id)));
|
||||
+ std::to_string(localId(id)));
|
||||
|
||||
if (isNewIdMapped(newId))
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
if (isNewIdMapped(newId)) {
|
||||
error(std::string("ID already used in module: ") + std::to_string(newId));
|
||||
return spirvbin_t::unused;
|
||||
}
|
||||
|
||||
msg(4, 4, std::string("map: ") + std::to_string(id) + " -> " + std::to_string(newId));
|
||||
setMapped(newId);
|
||||
@@ -256,7 +308,6 @@ namespace spv {
|
||||
return literal;
|
||||
}
|
||||
|
||||
|
||||
void spirvbin_t::applyMap()
|
||||
{
|
||||
msg(3, 2, std::string("Applying map: "));
|
||||
@@ -265,12 +316,15 @@ namespace spv {
|
||||
process(inst_fn_nop, // ignore instructions
|
||||
[this](spv::Id& id) {
|
||||
id = localId(id);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
assert(id != unused && id != unmapped);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Find free IDs for anything we haven't mapped
|
||||
void spirvbin_t::mapRemainder()
|
||||
{
|
||||
@@ -284,25 +338,31 @@ namespace spv {
|
||||
continue;
|
||||
|
||||
// Find a new mapping for any used but unmapped IDs
|
||||
if (isOldIdUnmapped(id))
|
||||
if (isOldIdUnmapped(id)) {
|
||||
localId(id, unusedId = nextUnusedId(unusedId));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
|
||||
if (isOldIdUnmapped(id))
|
||||
if (isOldIdUnmapped(id)) {
|
||||
error(std::string("old ID not mapped: ") + std::to_string(id));
|
||||
return;
|
||||
}
|
||||
|
||||
// Track max bound
|
||||
maxBound = std::max(maxBound, localId(id) + 1);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
|
||||
bound(maxBound); // reset header ID bound to as big as it now needs to be
|
||||
}
|
||||
|
||||
// Mark debug instructions for stripping
|
||||
void spirvbin_t::stripDebug()
|
||||
{
|
||||
if ((options & STRIP) == 0)
|
||||
return;
|
||||
|
||||
// build local Id and name maps
|
||||
// Strip instructions in the stripOp set: debug info.
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// remember opcodes we want to strip later
|
||||
@@ -313,6 +373,32 @@ namespace spv {
|
||||
op_fn_nop);
|
||||
}
|
||||
|
||||
// Mark instructions that refer to now-removed IDs for stripping
|
||||
void spirvbin_t::stripDeadRefs()
|
||||
{
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// strip opcodes pointing to removed data
|
||||
switch (opCode) {
|
||||
case spv::OpName:
|
||||
case spv::OpMemberName:
|
||||
case spv::OpDecorate:
|
||||
case spv::OpMemberDecorate:
|
||||
if (idPosR.find(asId(start+1)) == idPosR.end())
|
||||
stripInst(start);
|
||||
break;
|
||||
default:
|
||||
break; // leave it alone
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
op_fn_nop);
|
||||
|
||||
strip();
|
||||
}
|
||||
|
||||
// Update local maps of ID, type, etc positions
|
||||
void spirvbin_t::buildLocalMaps()
|
||||
{
|
||||
msg(2, 2, std::string("build local maps: "));
|
||||
@@ -321,10 +407,9 @@ namespace spv {
|
||||
idMapL.clear();
|
||||
// preserve nameMap, so we don't clear that.
|
||||
fnPos.clear();
|
||||
fnPosDCE.clear();
|
||||
fnCalls.clear();
|
||||
typeConstPos.clear();
|
||||
typeConstPosR.clear();
|
||||
idPosR.clear();
|
||||
entryPoint = spv::NoResult;
|
||||
largestNewId = 0;
|
||||
|
||||
@@ -336,9 +421,27 @@ namespace spv {
|
||||
// build local Id and name maps
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// remember opcodes we want to strip later
|
||||
if ((options & STRIP) && isStripOp(opCode))
|
||||
stripInst(start);
|
||||
unsigned word = start+1;
|
||||
spv::Id typeId = spv::NoResult;
|
||||
|
||||
if (spv::InstructionDesc[opCode].hasType())
|
||||
typeId = asId(word++);
|
||||
|
||||
// If there's a result ID, remember the size of its type
|
||||
if (spv::InstructionDesc[opCode].hasResult()) {
|
||||
const spv::Id resultId = asId(word++);
|
||||
idPosR[resultId] = start;
|
||||
|
||||
if (typeId != spv::NoResult) {
|
||||
const unsigned idTypeSize = typeSizeInWords(typeId);
|
||||
|
||||
if (errorLatch)
|
||||
return false;
|
||||
|
||||
if (idTypeSize != 0)
|
||||
idTypeSizeMap[resultId] = idTypeSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (opCode == spv::Op::OpName) {
|
||||
const spv::Id target = asId(start+1);
|
||||
@@ -350,24 +453,31 @@ namespace spv {
|
||||
} else if (opCode == spv::Op::OpEntryPoint) {
|
||||
entryPoint = asId(start + 2);
|
||||
} else if (opCode == spv::Op::OpFunction) {
|
||||
if (fnStart != 0)
|
||||
if (fnStart != 0) {
|
||||
error("nested function found");
|
||||
return false;
|
||||
}
|
||||
|
||||
fnStart = start;
|
||||
fnRes = asId(start + 2);
|
||||
} else if (opCode == spv::Op::OpFunctionEnd) {
|
||||
assert(fnRes != spv::NoResult);
|
||||
if (fnStart == 0)
|
||||
if (fnStart == 0) {
|
||||
error("function end without function start");
|
||||
return false;
|
||||
}
|
||||
|
||||
fnPos[fnRes] = range_t(fnStart, start + asWordCount(start));
|
||||
fnStart = 0;
|
||||
} else if (isConstOp(opCode)) {
|
||||
if (errorLatch)
|
||||
return false;
|
||||
|
||||
assert(asId(start + 2) != spv::NoResult);
|
||||
typeConstPos.insert(start);
|
||||
typeConstPosR[asId(start + 2)] = start;
|
||||
} else if (isTypeOp(opCode)) {
|
||||
assert(asId(start + 1) != spv::NoResult);
|
||||
typeConstPos.insert(start);
|
||||
typeConstPosR[asId(start + 1)] = start;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -382,30 +492,37 @@ namespace spv {
|
||||
{
|
||||
msg(2, 2, std::string("validating: "));
|
||||
|
||||
if (spv.size() < header_size)
|
||||
if (spv.size() < header_size) {
|
||||
error("file too short: ");
|
||||
return;
|
||||
}
|
||||
|
||||
if (magic() != spv::MagicNumber)
|
||||
if (magic() != spv::MagicNumber) {
|
||||
error("bad magic number");
|
||||
return;
|
||||
}
|
||||
|
||||
// field 1 = version
|
||||
// field 2 = generator magic
|
||||
// field 3 = result <id> bound
|
||||
|
||||
if (schemaNum() != 0)
|
||||
if (schemaNum() != 0) {
|
||||
error("bad schema, must be 0");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int spirvbin_t::processInstruction(unsigned word, instfn_t instFn, idfn_t idFn)
|
||||
{
|
||||
const auto instructionStart = word;
|
||||
const unsigned wordCount = asWordCount(instructionStart);
|
||||
const spv::Op opCode = asOpCode(instructionStart);
|
||||
const int nextInst = word++ + wordCount;
|
||||
spv::Op opCode = asOpCode(instructionStart);
|
||||
|
||||
if (nextInst > int(spv.size()))
|
||||
if (nextInst > int(spv.size())) {
|
||||
error("spir instruction terminated too early");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Base for computing number of operands; will be updated as more is learned
|
||||
unsigned numOperands = wordCount - 1;
|
||||
@@ -436,10 +553,31 @@ namespace spv {
|
||||
return nextInst;
|
||||
}
|
||||
|
||||
// Circular buffer so we can look back at previous unmapped values during the mapping pass.
|
||||
static const unsigned idBufferSize = 4;
|
||||
spv::Id idBuffer[idBufferSize];
|
||||
unsigned idBufferPos = 0;
|
||||
|
||||
// Store IDs from instruction in our map
|
||||
for (int op = 0; numOperands > 0; ++op, --numOperands) {
|
||||
// SpecConstantOp is special: it includes the operands of another opcode which is
|
||||
// given as a literal in the 3rd word. We will switch over to pretending that the
|
||||
// opcode being processed is the literal opcode value of the SpecConstantOp. See the
|
||||
// SPIRV spec for details. This way we will handle IDs and literals as appropriate for
|
||||
// the embedded op.
|
||||
if (opCode == spv::OpSpecConstantOp) {
|
||||
if (op == 0) {
|
||||
opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp.
|
||||
--numOperands;
|
||||
}
|
||||
}
|
||||
|
||||
switch (spv::InstructionDesc[opCode].operands.getClass(op)) {
|
||||
case spv::OperandId:
|
||||
case spv::OperandScope:
|
||||
case spv::OperandMemorySemantics:
|
||||
idBuffer[idBufferPos] = asId(word);
|
||||
idBufferPos = (idBufferPos + 1) % idBufferSize;
|
||||
idFn(asId(word++));
|
||||
break;
|
||||
|
||||
@@ -457,13 +595,28 @@ namespace spv {
|
||||
// word += numOperands;
|
||||
return nextInst;
|
||||
|
||||
case spv::OperandVariableLiteralId:
|
||||
while (numOperands > 0) {
|
||||
++word; // immediate
|
||||
idFn(asId(word++)); // ID
|
||||
numOperands -= 2;
|
||||
case spv::OperandVariableLiteralId: {
|
||||
if (opCode == OpSwitch) {
|
||||
// word-2 is the position of the selector ID. OpSwitch Literals match its type.
|
||||
// In case the IDs are currently being remapped, we get the word[-2] ID from
|
||||
// the circular idBuffer.
|
||||
const unsigned literalSizePos = (idBufferPos+idBufferSize-2) % idBufferSize;
|
||||
const unsigned literalSize = idTypeSizeInWords(idBuffer[literalSizePos]);
|
||||
const unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize);
|
||||
|
||||
if (errorLatch)
|
||||
return -1;
|
||||
|
||||
for (unsigned arg=0; arg<numLiteralIdPairs; ++arg) {
|
||||
word += literalSize; // literal
|
||||
idFn(asId(word++)); // label
|
||||
}
|
||||
} else {
|
||||
assert(0); // currentely, only OpSwitch uses OperandVariableLiteralId
|
||||
}
|
||||
|
||||
return nextInst;
|
||||
}
|
||||
|
||||
case spv::OperandLiteralString: {
|
||||
const int stringWordCount = literalStringWords(literalString(word));
|
||||
@@ -500,9 +653,7 @@ namespace spv {
|
||||
case spv::OperandSelect:
|
||||
case spv::OperandLoop:
|
||||
case spv::OperandFunction:
|
||||
case spv::OperandMemorySemantics:
|
||||
case spv::OperandMemoryAccess:
|
||||
case spv::OperandScope:
|
||||
case spv::OperandGroupOperation:
|
||||
case spv::OperandKernelEnqueueFlags:
|
||||
case spv::OperandKernelProfilingInfo:
|
||||
@@ -532,9 +683,13 @@ namespace spv {
|
||||
// basic parsing and InstructionDesc table borrowed from SpvDisassemble.cpp...
|
||||
unsigned nextInst = unsigned(spv.size());
|
||||
|
||||
for (unsigned word = begin; word < end; word = nextInst)
|
||||
for (unsigned word = begin; word < end; word = nextInst) {
|
||||
nextInst = processInstruction(word, instFn, idFn);
|
||||
|
||||
if (errorLatch)
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -549,8 +704,11 @@ namespace spv {
|
||||
for (const char c : name.first)
|
||||
hashval = hashval * 1009 + c;
|
||||
|
||||
if (isOldIdUnmapped(name.second))
|
||||
if (isOldIdUnmapped(name.second)) {
|
||||
localId(name.second, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,6 +730,9 @@ namespace spv {
|
||||
[&](spv::Op, unsigned start) { instPos.push_back(start); return true; },
|
||||
op_fn_nop);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Window size for context-sensitive canonicalization values
|
||||
// Empirical best size from a single data set. TODO: Would be a good tunable.
|
||||
// We essentially perform a little convolution around each instruction,
|
||||
@@ -607,8 +768,12 @@ namespace spv {
|
||||
hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime
|
||||
}
|
||||
|
||||
if (isOldIdUnmapped(resId))
|
||||
if (isOldIdUnmapped(resId)) {
|
||||
localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -701,6 +866,9 @@ namespace spv {
|
||||
[&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; }
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// EXPERIMENTAL: Implicit output stores
|
||||
fnLocalVars.clear();
|
||||
idMap.clear();
|
||||
@@ -721,11 +889,17 @@ namespace spv {
|
||||
},
|
||||
op_fn_nop);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
process(
|
||||
inst_fn_nop,
|
||||
[&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; }
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
}
|
||||
|
||||
@@ -817,7 +991,7 @@ namespace spv {
|
||||
},
|
||||
|
||||
// If local var id used anywhere else, don't eliminate
|
||||
[&](spv::Id& id) {
|
||||
[&](spv::Id& id) {
|
||||
if (fnLocalVars.count(id) > 0) {
|
||||
fnLocalVars.erase(id);
|
||||
idMap.erase(id);
|
||||
@@ -825,6 +999,9 @@ namespace spv {
|
||||
}
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0)
|
||||
@@ -833,6 +1010,9 @@ namespace spv {
|
||||
},
|
||||
op_fn_nop);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Chase replacements to their origins, in case there is a chain such as:
|
||||
// 2 = store 1
|
||||
// 3 = load 2
|
||||
@@ -866,6 +1046,9 @@ namespace spv {
|
||||
}
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
}
|
||||
|
||||
@@ -891,7 +1074,6 @@ namespace spv {
|
||||
if (call_it == fnCalls.end() || call_it->second == 0) {
|
||||
changed = true;
|
||||
stripRange.push_back(fn->second);
|
||||
fnPosDCE.insert(*fn);
|
||||
|
||||
// decrease counts of called functions
|
||||
process(
|
||||
@@ -910,6 +1092,9 @@ namespace spv {
|
||||
fn->second.first,
|
||||
fn->second.second);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
fn = fnPos.erase(fn);
|
||||
} else ++fn;
|
||||
}
|
||||
@@ -942,14 +1127,21 @@ namespace spv {
|
||||
[&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; }
|
||||
);
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Remove single-use function variables + associated decorations and names
|
||||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
if ((opCode == spv::OpVariable && varUseCount[asId(start+2)] == 1) ||
|
||||
(opCode == spv::OpDecorate && varUseCount[asId(start+1)] == 1) ||
|
||||
(opCode == spv::OpName && varUseCount[asId(start+1)] == 1)) {
|
||||
stripInst(start);
|
||||
}
|
||||
spv::Id id = spv::NoResult;
|
||||
if (opCode == spv::OpVariable)
|
||||
id = asId(start+2);
|
||||
if (opCode == spv::OpDecorate || opCode == spv::OpName)
|
||||
id = asId(start+1);
|
||||
|
||||
if (id != spv::NoResult && varUseCount[id] == 1)
|
||||
stripInst(start);
|
||||
|
||||
return true;
|
||||
},
|
||||
op_fn_nop);
|
||||
@@ -966,28 +1158,37 @@ namespace spv {
|
||||
|
||||
std::unordered_map<spv::Id, int> typeUseCount;
|
||||
|
||||
// Count total type usage
|
||||
process(inst_fn_nop,
|
||||
[&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; }
|
||||
);
|
||||
// This is not the most efficient algorithm, but this is an offline tool, and
|
||||
// it's easy to write this way. Can be improved opportunistically if needed.
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
strip();
|
||||
typeUseCount.clear();
|
||||
|
||||
// Remove types from deleted code
|
||||
for (const auto& fn : fnPosDCE)
|
||||
// Count total type usage
|
||||
process(inst_fn_nop,
|
||||
[&](spv::Id& id) { if (isType[id]) --typeUseCount[id]; },
|
||||
fn.second.first, fn.second.second);
|
||||
[&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; }
|
||||
);
|
||||
|
||||
// Remove single reference types
|
||||
for (const auto typeStart : typeConstPos) {
|
||||
const spv::Id typeId = asTypeConstId(typeStart);
|
||||
if (typeUseCount[typeId] == 1) {
|
||||
--typeUseCount[typeId];
|
||||
stripInst(typeStart);
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
// Remove single reference types
|
||||
for (const auto typeStart : typeConstPos) {
|
||||
const spv::Id typeId = asTypeConstId(typeStart);
|
||||
if (typeUseCount[typeId] == 1) {
|
||||
changed = true;
|
||||
--typeUseCount[typeId];
|
||||
stripInst(typeStart);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NOTDEF
|
||||
bool spirvbin_t::matchType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const
|
||||
{
|
||||
@@ -1047,7 +1248,6 @@ namespace spv {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Look for an equivalent type in the globalTypes map
|
||||
spv::Id spirvbin_t::findType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt) const
|
||||
{
|
||||
@@ -1060,12 +1260,14 @@ namespace spv {
|
||||
}
|
||||
#endif // NOTDEF
|
||||
|
||||
// Return start position in SPV of given type. error if not found.
|
||||
unsigned spirvbin_t::typePos(spv::Id id) const
|
||||
// Return start position in SPV of given Id. error if not found.
|
||||
unsigned spirvbin_t::idPos(spv::Id id) const
|
||||
{
|
||||
const auto tid_it = typeConstPosR.find(id);
|
||||
if (tid_it == typeConstPosR.end())
|
||||
error("type ID not found");
|
||||
const auto tid_it = idPosR.find(id);
|
||||
if (tid_it == idPosR.end()) {
|
||||
error("ID not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tid_it->second;
|
||||
}
|
||||
@@ -1083,11 +1285,11 @@ namespace spv {
|
||||
case spv::OpTypeInt: return 3 + (spv[typeStart+3]);
|
||||
case spv::OpTypeFloat: return 5;
|
||||
case spv::OpTypeVector:
|
||||
return 6 + hashType(typePos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
return 6 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
case spv::OpTypeMatrix:
|
||||
return 30 + hashType(typePos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
return 30 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
case spv::OpTypeImage:
|
||||
return 120 + hashType(typePos(spv[typeStart+2])) +
|
||||
return 120 + hashType(idPos(spv[typeStart+2])) +
|
||||
spv[typeStart+3] + // dimensionality
|
||||
spv[typeStart+4] * 8 * 16 + // depth
|
||||
spv[typeStart+5] * 4 * 16 + // arrayed
|
||||
@@ -1098,24 +1300,24 @@ namespace spv {
|
||||
case spv::OpTypeSampledImage:
|
||||
return 502;
|
||||
case spv::OpTypeArray:
|
||||
return 501 + hashType(typePos(spv[typeStart+2])) * spv[typeStart+3];
|
||||
return 501 + hashType(idPos(spv[typeStart+2])) * spv[typeStart+3];
|
||||
case spv::OpTypeRuntimeArray:
|
||||
return 5000 + hashType(typePos(spv[typeStart+2]));
|
||||
return 5000 + hashType(idPos(spv[typeStart+2]));
|
||||
case spv::OpTypeStruct:
|
||||
{
|
||||
std::uint32_t hash = 10000;
|
||||
for (unsigned w=2; w < wordCount; ++w)
|
||||
hash += w * hashType(typePos(spv[typeStart+w]));
|
||||
hash += w * hashType(idPos(spv[typeStart+w]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
case spv::OpTypeOpaque: return 6000 + spv[typeStart+2];
|
||||
case spv::OpTypePointer: return 100000 + hashType(typePos(spv[typeStart+3]));
|
||||
case spv::OpTypePointer: return 100000 + hashType(idPos(spv[typeStart+3]));
|
||||
case spv::OpTypeFunction:
|
||||
{
|
||||
std::uint32_t hash = 200000;
|
||||
for (unsigned w=2; w < wordCount; ++w)
|
||||
hash += w * hashType(typePos(spv[typeStart+w]));
|
||||
hash += w * hashType(idPos(spv[typeStart+w]));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -1132,14 +1334,14 @@ namespace spv {
|
||||
case spv::OpConstantFalse: return 300008;
|
||||
case spv::OpConstantComposite:
|
||||
{
|
||||
std::uint32_t hash = 300011 + hashType(typePos(spv[typeStart+1]));
|
||||
std::uint32_t hash = 300011 + hashType(idPos(spv[typeStart+1]));
|
||||
for (unsigned w=3; w < wordCount; ++w)
|
||||
hash += w * hashType(typePos(spv[typeStart+w]));
|
||||
hash += w * hashType(idPos(spv[typeStart+w]));
|
||||
return hash;
|
||||
}
|
||||
case spv::OpConstant:
|
||||
{
|
||||
std::uint32_t hash = 400011 + hashType(typePos(spv[typeStart+1]));
|
||||
std::uint32_t hash = 400011 + hashType(idPos(spv[typeStart+1]));
|
||||
for (unsigned w=3; w < wordCount; ++w)
|
||||
hash += w * spv[typeStart+w];
|
||||
return hash;
|
||||
@@ -1164,12 +1366,17 @@ namespace spv {
|
||||
const spv::Id resId = asTypeConstId(typeStart);
|
||||
const std::uint32_t hashval = hashType(typeStart);
|
||||
|
||||
if (isOldIdUnmapped(resId))
|
||||
if (errorLatch)
|
||||
return;
|
||||
|
||||
if (isOldIdUnmapped(resId)) {
|
||||
localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));
|
||||
if (errorLatch)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Strip a single binary by removing ranges given in stripRange
|
||||
void spirvbin_t::strip()
|
||||
{
|
||||
@@ -1185,7 +1392,7 @@ namespace spv {
|
||||
|
||||
int strippedPos = 0;
|
||||
for (unsigned word = 0; word < unsigned(spv.size()); ++word) {
|
||||
if (strip_it != stripRange.end() && word >= strip_it->second)
|
||||
while (strip_it != stripRange.end() && word >= strip_it->second)
|
||||
++strip_it;
|
||||
|
||||
if (strip_it == stripRange.end() || word < strip_it->first || word >= strip_it->second)
|
||||
@@ -1206,25 +1413,56 @@ namespace spv {
|
||||
// Set up opcode tables from SpvDoc
|
||||
spv::Parameterize();
|
||||
|
||||
validate(); // validate header
|
||||
buildLocalMaps();
|
||||
validate(); // validate header
|
||||
buildLocalMaps(); // build ID maps
|
||||
|
||||
msg(3, 4, std::string("ID bound: ") + std::to_string(bound()));
|
||||
|
||||
if (options & STRIP) stripDebug();
|
||||
if (errorLatch) return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & OPT_LOADSTORE) optLoadStore();
|
||||
if (options & OPT_FWD_LS) forwardLoadStores();
|
||||
if (options & DCE_FUNCS) dceFuncs();
|
||||
if (options & DCE_VARS) dceVars();
|
||||
if (options & DCE_TYPES) dceTypes();
|
||||
if (options & MAP_TYPES) mapTypeConst();
|
||||
if (options & MAP_NAMES) mapNames();
|
||||
if (options & MAP_FUNCS) mapFnBodies();
|
||||
if (errorLatch) return;
|
||||
|
||||
mapRemainder(); // map any unmapped IDs
|
||||
applyMap(); // Now remap each shader to the new IDs we've come up with
|
||||
strip(); // strip out data we decided to eliminate
|
||||
if (options & OPT_FWD_LS) forwardLoadStores();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & DCE_FUNCS) dceFuncs();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & DCE_VARS) dceVars();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & DCE_TYPES) dceTypes();
|
||||
if (errorLatch) return;
|
||||
|
||||
strip(); // strip out data we decided to eliminate
|
||||
if (errorLatch) return;
|
||||
|
||||
stripDeadRefs(); // remove references to things we DCEed
|
||||
if (errorLatch) return;
|
||||
|
||||
// after the last strip, we must clean any debug info referring to now-deleted data
|
||||
|
||||
if (options & MAP_TYPES) mapTypeConst();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & MAP_NAMES) mapNames();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & MAP_FUNCS) mapFnBodies();
|
||||
if (errorLatch) return;
|
||||
|
||||
if (options & MAP_ALL) {
|
||||
mapRemainder(); // map any unmapped IDs
|
||||
if (errorLatch) return;
|
||||
|
||||
applyMap(); // Now remap each shader to the new IDs we've come up with
|
||||
if (errorLatch) return;
|
||||
}
|
||||
}
|
||||
|
||||
// remap from a memory image
|
||||
|
||||
+57
-41
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2015 LunarG, Inc.
|
||||
// Copyright (C) 2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,18 +19,18 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef SPIRVREMAPPER_H
|
||||
@@ -38,7 +38,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
|
||||
namespace spv {
|
||||
|
||||
@@ -74,7 +75,8 @@ public:
|
||||
} // namespace SPV
|
||||
|
||||
#if !defined (use_cpp11)
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
namespace spv {
|
||||
class spirvbin_t : public spirvbin_base_t
|
||||
@@ -82,7 +84,7 @@ class spirvbin_t : public spirvbin_base_t
|
||||
public:
|
||||
spirvbin_t(int /*verbose = 0*/) { }
|
||||
|
||||
void remap(std::vector<unsigned int>& /*spv*/, unsigned int /*opts = 0*/)
|
||||
void remap(std::vector<std::uint32_t>& /*spv*/, unsigned int /*opts = 0*/)
|
||||
{
|
||||
printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n");
|
||||
exit(5);
|
||||
@@ -110,8 +112,11 @@ namespace spv {
|
||||
class spirvbin_t : public spirvbin_base_t
|
||||
{
|
||||
public:
|
||||
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose) { }
|
||||
|
||||
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false)
|
||||
{ }
|
||||
|
||||
virtual ~spirvbin_t() { }
|
||||
|
||||
// remap on an existing binary in memory
|
||||
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
|
||||
|
||||
@@ -159,17 +164,22 @@ private:
|
||||
typedef std::set<int> posmap_t;
|
||||
typedef std::unordered_map<spv::Id, int> posmap_rev_t;
|
||||
|
||||
// Maps and ID to the size of its base type, if known.
|
||||
typedef std::unordered_map<spv::Id, unsigned> typesize_map_t;
|
||||
|
||||
// handle error
|
||||
void error(const std::string& txt) const { errorHandler(txt); }
|
||||
void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); }
|
||||
|
||||
bool isConstOp(spv::Op opCode) const;
|
||||
bool isTypeOp(spv::Op opCode) const;
|
||||
bool isStripOp(spv::Op opCode) const;
|
||||
bool isFlowCtrl(spv::Op opCode) const;
|
||||
range_t literalRange(spv::Op opCode) const;
|
||||
range_t typeRange(spv::Op opCode) const;
|
||||
range_t constRange(spv::Op opCode) const;
|
||||
unsigned typeSizeInWords(spv::Id id) const;
|
||||
unsigned idTypeSizeInWords(spv::Id id) const;
|
||||
|
||||
bool isConstOp(spv::Op opCode) const;
|
||||
bool isTypeOp(spv::Op opCode) const;
|
||||
bool isStripOp(spv::Op opCode) const;
|
||||
bool isFlowCtrl(spv::Op opCode) const;
|
||||
range_t literalRange(spv::Op opCode) const;
|
||||
range_t typeRange(spv::Op opCode) const;
|
||||
range_t constRange(spv::Op opCode) const;
|
||||
|
||||
spv::Id& asId(unsigned word) { return spv[word]; }
|
||||
const spv::Id& asId(unsigned word) const { return spv[word]; }
|
||||
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
|
||||
@@ -177,10 +187,10 @@ private:
|
||||
spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
|
||||
unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); }
|
||||
spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); }
|
||||
unsigned typePos(spv::Id id) const;
|
||||
unsigned idPos(spv::Id id) const;
|
||||
|
||||
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
||||
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
||||
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
||||
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
||||
|
||||
// Header access & set methods
|
||||
spirword_t magic() const { return spv[0]; } // return magic number
|
||||
@@ -233,9 +243,10 @@ private:
|
||||
|
||||
void applyMap(); // remap per local name map
|
||||
void mapRemainder(); // map any IDs we haven't touched yet
|
||||
void stripDebug(); // strip debug info
|
||||
void stripDebug(); // strip all debug info
|
||||
void stripDeadRefs(); // strips debug info for now-dead references after DCE
|
||||
void strip(); // remove debug symbols
|
||||
|
||||
|
||||
std::vector<spirword_t> spv; // SPIR words
|
||||
|
||||
namemap_t nameMap; // ID names from OpName
|
||||
@@ -258,14 +269,14 @@ private:
|
||||
// Function start and end. use unordered_map because we'll have
|
||||
// many fewer functions than IDs.
|
||||
std::unordered_map<spv::Id, range_t> fnPos;
|
||||
std::unordered_map<spv::Id, range_t> fnPosDCE; // deleted functions
|
||||
|
||||
// Which functions are called, anywhere in the module, with a call count
|
||||
std::unordered_map<spv::Id, int> fnCalls;
|
||||
|
||||
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
||||
posmap_rev_t typeConstPosR; // reverse map from IDs to positions
|
||||
|
||||
|
||||
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
||||
posmap_rev_t idPosR; // reverse map from IDs to positions
|
||||
typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known.
|
||||
|
||||
std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
|
||||
|
||||
spv::Id entryPoint; // module entry point
|
||||
@@ -278,6 +289,11 @@ private:
|
||||
std::uint32_t options;
|
||||
int verbose; // verbosity level
|
||||
|
||||
// Error latch: this is set if the error handler is ever executed. It would be better to
|
||||
// use a try/catch block and throw, but that's not desired for certain environments, so
|
||||
// this is the alternative.
|
||||
mutable bool errorLatch;
|
||||
|
||||
static errorfn_t errorHandler;
|
||||
static logfn_t logHandler;
|
||||
};
|
||||
|
||||
+444
-167
File diff suppressed because it is too large
Load Diff
Vendored
+109
-54
@@ -1,12 +1,13 @@
|
||||
//
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//Copyright (C) 2015-2016 Google, Inc.
|
||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
||||
// Copyright (C) 2015-2016 Google, Inc.
|
||||
// Copyright (C) 2017 ARM Limited.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -20,18 +21,18 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// "Builder" is an interface to fully build SPIR-V IR. Allocate one of
|
||||
@@ -55,22 +56,36 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace spv {
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
Builder(unsigned int userNumber, SpvBuildLogger* logger);
|
||||
Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
|
||||
virtual ~Builder();
|
||||
|
||||
static const int maxMatrixSize = 4;
|
||||
|
||||
unsigned int getSpvVersion() const { return spvVersion; }
|
||||
|
||||
void setSource(spv::SourceLanguage lang, int version)
|
||||
{
|
||||
source = lang;
|
||||
sourceVersion = version;
|
||||
}
|
||||
void addSourceExtension(const char* ext) { extensions.push_back(ext); }
|
||||
void setSourceFile(const std::string& file)
|
||||
{
|
||||
Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString);
|
||||
fileString->addStringOperand(file.c_str());
|
||||
sourceFileStringId = fileString->getResultId();
|
||||
strings.push_back(std::unique_ptr<Instruction>(fileString));
|
||||
}
|
||||
void setSourceText(const std::string& text) { sourceText = text; }
|
||||
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
|
||||
void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
|
||||
void setEmitOpLines() { emitOpLines = true; }
|
||||
void addExtension(const char* ext) { extensions.insert(ext); }
|
||||
Id import(const char*);
|
||||
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
|
||||
{
|
||||
@@ -91,6 +106,12 @@ public:
|
||||
return id;
|
||||
}
|
||||
|
||||
// Log the current line, and if different than the last one,
|
||||
// issue a new OpLine, using the current file name.
|
||||
void setLine(int line);
|
||||
// Low-level OpLine. See setLine() for a layered helper.
|
||||
void addLine(Id fileName, int line, int column);
|
||||
|
||||
// For creating new types (will return old type if the requested one was already made).
|
||||
Id makeVoidType();
|
||||
Id makeBoolType();
|
||||
@@ -132,7 +153,10 @@ public:
|
||||
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
|
||||
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
|
||||
|
||||
bool isBoolType(Id typeId) const { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
|
||||
bool isBoolType(Id typeId) { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
|
||||
bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
|
||||
bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
|
||||
bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
|
||||
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
|
||||
bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
|
||||
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
|
||||
@@ -152,6 +176,13 @@ public:
|
||||
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
|
||||
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
|
||||
|
||||
int getScalarTypeWidth(Id typeId) const
|
||||
{
|
||||
Id scalarTypeId = getScalarTypeId(typeId);
|
||||
assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat);
|
||||
return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
|
||||
}
|
||||
|
||||
int getTypeNumColumns(Id typeId) const
|
||||
{
|
||||
assert(isMatrixType(typeId));
|
||||
@@ -184,24 +215,32 @@ public:
|
||||
|
||||
// For making new constants (will return old constant if the requested one was already made).
|
||||
Id makeBoolConstant(bool b, bool specConstant = false);
|
||||
Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
|
||||
Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); }
|
||||
Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
|
||||
Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); }
|
||||
Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
|
||||
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
|
||||
Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
|
||||
Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); }
|
||||
Id makeFloatConstant(float f, bool specConstant = false);
|
||||
Id makeDoubleConstant(double d, bool specConstant = false);
|
||||
Id makeFloat16Constant(float f16, bool specConstant = false);
|
||||
Id makeFpConstant(Id type, double d, bool specConstant = false);
|
||||
|
||||
// Turn the array of constants into a proper spv constant of the requested type.
|
||||
Id makeCompositeConstant(Id type, std::vector<Id>& comps, bool specConst = false);
|
||||
Id makeCompositeConstant(Id type, const std::vector<Id>& comps, bool specConst = false);
|
||||
|
||||
// Methods for adding information outside the CFG.
|
||||
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
|
||||
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
|
||||
void addName(Id, const char* name);
|
||||
void addMemberName(Id, int member, const char* name);
|
||||
void addLine(Id target, Id fileName, int line, int column);
|
||||
void addDecoration(Id, Decoration, int num = -1);
|
||||
void addDecoration(Id, Decoration, const char*);
|
||||
void addDecorationId(Id id, Decoration, Id idDecoration);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
|
||||
|
||||
// At the end of what block do the next create*() instructions go?
|
||||
void setBuildPoint(Block* bp) { buildPoint = bp; }
|
||||
@@ -209,13 +248,13 @@ public:
|
||||
|
||||
// Make the entry-point function. The returned pointer is only valid
|
||||
// for the lifetime of this builder.
|
||||
Function* makeEntrypoint(const char*);
|
||||
Function* makeEntryPoint(const char*);
|
||||
|
||||
// Make a shader-style function, and create its entry block if entry is non-zero.
|
||||
// Return the function, pass back the entry.
|
||||
// The returned pointer is only valid for the lifetime of this builder.
|
||||
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
|
||||
const std::vector<Decoration>& precisions, Block **entry = 0);
|
||||
const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
|
||||
|
||||
// Create a return. An 'implicit' return is one not appearing in the source
|
||||
// code. In the case of an implicit return, no post-return block is inserted.
|
||||
@@ -240,16 +279,16 @@ public:
|
||||
Id createLoad(Id lValue);
|
||||
|
||||
// Create an OpAccessChain instruction
|
||||
Id createAccessChain(StorageClass, Id base, std::vector<Id>& offsets);
|
||||
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
|
||||
|
||||
// Create an OpArrayLength instruction
|
||||
Id createArrayLength(Id base, unsigned int member);
|
||||
|
||||
// Create an OpCompositeExtract instruction
|
||||
Id createCompositeExtract(Id composite, Id typeId, unsigned index);
|
||||
Id createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes);
|
||||
Id createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes);
|
||||
|
||||
Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
|
||||
Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
|
||||
@@ -263,18 +302,18 @@ public:
|
||||
Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
|
||||
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
|
||||
Id createOp(Op, Id typeId, const std::vector<Id>& operands);
|
||||
Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
|
||||
Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&);
|
||||
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
|
||||
|
||||
// Take an rvalue (source) and a set of channels to extract from it to
|
||||
// make a new rvalue, which is returned.
|
||||
Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, std::vector<unsigned>& channels);
|
||||
Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels);
|
||||
|
||||
// Take a copy of an lvalue (target) and a source of components, and set the
|
||||
// source components into the lvalue where the 'channels' say to put them.
|
||||
// An updated version of the target is returned.
|
||||
// (No true lvalue or stores are used.)
|
||||
Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
|
||||
Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels);
|
||||
|
||||
// If both the id and precision are valid, the id
|
||||
// gets tagged with the requested precision.
|
||||
@@ -297,7 +336,7 @@ public:
|
||||
// Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'.
|
||||
// The type of the created vector is a vector of components of the same type as the scalar.
|
||||
//
|
||||
// Note: One of the arguments will change, with the result coming back that way rather than
|
||||
// Note: One of the arguments will change, with the result coming back that way rather than
|
||||
// through the return value.
|
||||
void promoteScalar(Decoration precision, Id& left, Id& right);
|
||||
|
||||
@@ -307,7 +346,7 @@ public:
|
||||
Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
|
||||
|
||||
// Create a call to a built-in function.
|
||||
Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, std::vector<Id>& args);
|
||||
Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args);
|
||||
|
||||
// List of parameters used to create a texture operation
|
||||
struct TextureParameters {
|
||||
@@ -331,7 +370,7 @@ public:
|
||||
|
||||
// Emit the OpTextureQuery* instruction that was passed in.
|
||||
// Figure out the right return value and type, and return it.
|
||||
Id createTextureQueryCall(Op, const TextureParameters&);
|
||||
Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult);
|
||||
|
||||
Id createSamplePositionCall(Decoration precision, Id, Id);
|
||||
|
||||
@@ -342,7 +381,7 @@ public:
|
||||
Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
|
||||
|
||||
// OpCompositeConstruct
|
||||
Id createCompositeConstruct(Id typeId, std::vector<Id>& constituents);
|
||||
Id createCompositeConstruct(Id typeId, const std::vector<Id>& constituents);
|
||||
|
||||
// vector or scalar constructor
|
||||
Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
|
||||
@@ -353,7 +392,7 @@ public:
|
||||
// Helper to use for building nested control flow with if-then-else.
|
||||
class If {
|
||||
public:
|
||||
If(Id condition, Builder& builder);
|
||||
If(Id condition, unsigned int ctrl, Builder& builder);
|
||||
~If() {}
|
||||
|
||||
void makeBeginElse();
|
||||
@@ -365,6 +404,7 @@ public:
|
||||
|
||||
Builder& builder;
|
||||
Id condition;
|
||||
unsigned int control;
|
||||
Function* function;
|
||||
Block* headerBlock;
|
||||
Block* thenBlock;
|
||||
@@ -384,8 +424,8 @@ public:
|
||||
// Returns the right set of basic blocks to start each code segment with, so that the caller's
|
||||
// recursion stack can hold the memory for it.
|
||||
//
|
||||
void makeSwitch(Id condition, int numSegments, std::vector<int>& caseValues, std::vector<int>& valueToSegment, int defaultSegment,
|
||||
std::vector<Block*>& segmentBB); // return argument
|
||||
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
|
||||
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument
|
||||
|
||||
// Add a branch to the innermost switch's merge block.
|
||||
void addSwitchBreak();
|
||||
@@ -466,7 +506,7 @@ public:
|
||||
|
||||
//
|
||||
// the SPIR-V builder maintains a single active chain that
|
||||
// the following methods operated on
|
||||
// the following methods operate on
|
||||
//
|
||||
|
||||
// for external save and restore
|
||||
@@ -499,19 +539,22 @@ public:
|
||||
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
|
||||
|
||||
// push a variable component selection onto the access chain; supporting only one, so unsided
|
||||
// push a dynamic component selection onto the access chain, only applicable with a
|
||||
// non-trivial swizzle or no swizzle
|
||||
void accessChainPushComponent(Id component, Id preSwizzleBaseType)
|
||||
{
|
||||
accessChain.component = component;
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
if (accessChain.swizzle.size() != 1) {
|
||||
accessChain.component = component;
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
||||
}
|
||||
}
|
||||
|
||||
// use accessChain and swizzle to store value
|
||||
void accessChainStore(Id rvalue);
|
||||
|
||||
// use accessChain and swizzle to load an r-value
|
||||
Id accessChainLoad(Decoration precision, Id ResultType);
|
||||
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType);
|
||||
|
||||
// get the direct pointer for an l-value
|
||||
Id accessChainGetLValue();
|
||||
@@ -527,7 +570,7 @@ public:
|
||||
|
||||
void createBranch(Block* block);
|
||||
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
|
||||
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
|
||||
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, unsigned int dependencyLength);
|
||||
|
||||
// Sets to generate opcode for specialization constants.
|
||||
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
|
||||
@@ -539,19 +582,30 @@ public:
|
||||
protected:
|
||||
Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
|
||||
Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant);
|
||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const;
|
||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const;
|
||||
Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
|
||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value);
|
||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2);
|
||||
Id findCompositeConstant(Op typeClass, const std::vector<Id>& comps);
|
||||
Id findStructConstant(Id typeId, const std::vector<Id>& comps);
|
||||
Id collapseAccessChain();
|
||||
void remapDynamicSwizzle();
|
||||
void transferAccessChainSwizzle(bool dynamic);
|
||||
void simplifyAccessChainSwizzle();
|
||||
void createAndSetNoPredecessorBlock(const char*);
|
||||
void createSelectionMerge(Block* mergeBlock, unsigned int control);
|
||||
void dumpSourceInstructions(std::vector<unsigned int>&) const;
|
||||
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
|
||||
void dumpModuleProcesses(std::vector<unsigned int>&) const;
|
||||
|
||||
unsigned int spvVersion; // the version of SPIR-V to emit in the header
|
||||
SourceLanguage source;
|
||||
int sourceVersion;
|
||||
std::vector<const char*> extensions;
|
||||
spv::Id sourceFileStringId;
|
||||
std::string sourceText;
|
||||
int currentLine;
|
||||
bool emitOpLines;
|
||||
std::set<std::string> extensions;
|
||||
std::vector<const char*> sourceExtensions;
|
||||
std::vector<const char*> moduleProcesses;
|
||||
AddressingModel addressModel;
|
||||
MemoryModel memoryModel;
|
||||
std::set<spv::Capability> capabilities;
|
||||
@@ -559,24 +613,25 @@ public:
|
||||
Module module;
|
||||
Block* buildPoint;
|
||||
Id uniqueId;
|
||||
Function* mainFunction;
|
||||
Function* entryPointFunction;
|
||||
bool generatingOpCodeForSpecConst;
|
||||
AccessChain accessChain;
|
||||
|
||||
// special blocks of instructions for output
|
||||
std::vector<std::unique_ptr<Instruction> > strings;
|
||||
std::vector<std::unique_ptr<Instruction> > imports;
|
||||
std::vector<std::unique_ptr<Instruction> > entryPoints;
|
||||
std::vector<std::unique_ptr<Instruction> > executionModes;
|
||||
std::vector<std::unique_ptr<Instruction> > names;
|
||||
std::vector<std::unique_ptr<Instruction> > lines;
|
||||
std::vector<std::unique_ptr<Instruction> > decorations;
|
||||
std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
|
||||
std::vector<std::unique_ptr<Instruction> > externals;
|
||||
std::vector<std::unique_ptr<Function> > functions;
|
||||
|
||||
// not output, internally used for quick & dirty canonical (unique) creation
|
||||
std::vector<Instruction*> groupedConstants[OpConstant]; // all types appear before OpConstant
|
||||
std::vector<Instruction*> groupedTypes[OpConstant];
|
||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants; // map type opcodes to constant inst.
|
||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions
|
||||
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes; // map type opcodes to type instructions
|
||||
|
||||
// stack of switches
|
||||
std::stack<Block*> switchMerges;
|
||||
@@ -584,7 +639,7 @@ public:
|
||||
// Our loop stack.
|
||||
std::stack<LoopBlocks> loops;
|
||||
|
||||
// The stream for outputing warnings and errors.
|
||||
// The stream for outputting warnings and errors.
|
||||
SpvBuildLogger* logger;
|
||||
}; // end Builder class
|
||||
|
||||
|
||||
Vendored
+81
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// 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 LIBSPIRV_UTIL_BITUTILS_H_
|
||||
#define LIBSPIRV_UTIL_BITUTILS_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace spvutils {
|
||||
|
||||
// Performs a bitwise copy of source to the destination type Dest.
|
||||
template <typename Dest, typename Src>
|
||||
Dest BitwiseCast(Src source) {
|
||||
Dest dest;
|
||||
static_assert(sizeof(source) == sizeof(dest),
|
||||
"BitwiseCast: Source and destination must have the same size");
|
||||
std::memcpy(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
// SetBits<T, First, Num> returns an integer of type <T> with bits set
|
||||
// for position <First> through <First + Num - 1>, counting from the least
|
||||
// significant bit. In particular when Num == 0, no positions are set to 1.
|
||||
// A static assert will be triggered if First + Num > sizeof(T) * 8, that is,
|
||||
// a bit that will not fit in the underlying type is set.
|
||||
template <typename T, size_t First = 0, size_t Num = 0>
|
||||
struct SetBits {
|
||||
static_assert(First < sizeof(T) * 8,
|
||||
"Tried to set a bit that is shifted too far.");
|
||||
const static T get = (T(1) << First) | SetBits<T, First + 1, Num - 1>::get;
|
||||
};
|
||||
|
||||
template <typename T, size_t Last>
|
||||
struct SetBits<T, Last, 0> {
|
||||
const static T get = T(0);
|
||||
};
|
||||
|
||||
// This is all compile-time so we can put our tests right here.
|
||||
static_assert(SetBits<uint32_t, 0, 0>::get == uint32_t(0x00000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 1>::get == uint32_t(0x00000001),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 31, 1>::get == uint32_t(0x80000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 1, 2>::get == uint32_t(0x00000006),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 30, 2>::get == uint32_t(0xc0000000),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 31>::get == uint32_t(0x7FFFFFFF),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 0, 32>::get == uint32_t(0xFFFFFFFF),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint32_t, 16, 16>::get == uint32_t(0xFFFF0000),
|
||||
"SetBits failed");
|
||||
|
||||
static_assert(SetBits<uint64_t, 0, 1>::get == uint64_t(0x0000000000000001LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 63, 1>::get == uint64_t(0x8000000000000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 62, 2>::get == uint64_t(0xc000000000000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 31, 1>::get == uint64_t(0x0000000080000000LL),
|
||||
"SetBits failed");
|
||||
static_assert(SetBits<uint64_t, 16, 16>::get == uint64_t(0x00000000FFFF0000LL),
|
||||
"SetBits failed");
|
||||
|
||||
} // namespace spvutils
|
||||
|
||||
#endif // LIBSPIRV_UTIL_BITUTILS_H_
|
||||
+180
-34
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,41 +19,58 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Disassembler for SPIR-V.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <stack>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
namespace spv {
|
||||
// Include C-based headers that don't have a namespace
|
||||
#include "GLSL.std.450.h"
|
||||
}
|
||||
const char* GlslStd450DebugNames[spv::GLSLstd450Count];
|
||||
|
||||
#include "disassemble.h"
|
||||
#include "doc.h"
|
||||
|
||||
namespace spv {
|
||||
extern "C" {
|
||||
// Include C-based headers that don't have a namespace
|
||||
#include "GLSL.std.450.h"
|
||||
#ifdef AMD_EXTENSIONS
|
||||
#include "GLSL.ext.AMD.h"
|
||||
#endif
|
||||
|
||||
#ifdef NV_EXTENSIONS
|
||||
#include "GLSL.ext.NV.h"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
const char* GlslStd450DebugNames[spv::GLSLstd450Count];
|
||||
|
||||
namespace spv {
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
|
||||
#endif
|
||||
|
||||
#ifdef NV_EXTENSIONS
|
||||
static const char* GLSLextNVGetDebugNames(const char*, unsigned);
|
||||
#endif
|
||||
|
||||
static void Kill(std::ostream& out, const char* message)
|
||||
{
|
||||
@@ -64,6 +81,15 @@ static void Kill(std::ostream& out, const char* message)
|
||||
// used to identify the extended instruction library imported when printing
|
||||
enum ExtInstSet {
|
||||
GLSL450Inst,
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
GLSLextAMDInst,
|
||||
#endif
|
||||
|
||||
#ifdef NV_EXTENSIONS
|
||||
GLSLextNVInst,
|
||||
#endif
|
||||
|
||||
OpenCLExtInst,
|
||||
};
|
||||
|
||||
@@ -205,10 +231,12 @@ void SpirvStream::outputIndent()
|
||||
|
||||
void SpirvStream::formatId(Id id, std::stringstream& idStream)
|
||||
{
|
||||
if (id >= bound)
|
||||
Kill(out, "Bad <id>");
|
||||
|
||||
if (id != 0) {
|
||||
// On instructions with no IDs, this is called with "0", which does not
|
||||
// have to be within ID bounds on null shaders.
|
||||
if (id >= bound)
|
||||
Kill(out, "Bad <id>");
|
||||
|
||||
idStream << id;
|
||||
if (idDescriptor[id].size() > 0)
|
||||
idStream << "(" << idDescriptor[id] << ")";
|
||||
@@ -322,13 +350,24 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
||||
idDescriptor[resultId] = (const char*)(&stream[word]);
|
||||
}
|
||||
else {
|
||||
if (idDescriptor[resultId].size() == 0) {
|
||||
if (resultId != 0 && idDescriptor[resultId].size() == 0) {
|
||||
switch (opCode) {
|
||||
case OpTypeInt:
|
||||
idDescriptor[resultId] = "int";
|
||||
switch (stream[word]) {
|
||||
case 8: idDescriptor[resultId] = "int8_t"; break;
|
||||
case 16: idDescriptor[resultId] = "int16_t"; break;
|
||||
default: assert(0); // fallthrough
|
||||
case 32: idDescriptor[resultId] = "int"; break;
|
||||
case 64: idDescriptor[resultId] = "int64_t"; break;
|
||||
}
|
||||
break;
|
||||
case OpTypeFloat:
|
||||
idDescriptor[resultId] = "float";
|
||||
switch (stream[word]) {
|
||||
case 16: idDescriptor[resultId] = "float16_t"; break;
|
||||
default: assert(0); // fallthrough
|
||||
case 32: idDescriptor[resultId] = "float"; break;
|
||||
case 64: idDescriptor[resultId] = "float64_t"; break;
|
||||
}
|
||||
break;
|
||||
case OpTypeBool:
|
||||
idDescriptor[resultId] = "bool";
|
||||
@@ -340,8 +379,18 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
||||
idDescriptor[resultId] = "ptr";
|
||||
break;
|
||||
case OpTypeVector:
|
||||
if (idDescriptor[stream[word]].size() > 0)
|
||||
if (idDescriptor[stream[word]].size() > 0) {
|
||||
idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
|
||||
if (strstr(idDescriptor[stream[word]].c_str(), "8")) {
|
||||
idDescriptor[resultId].append("8");
|
||||
}
|
||||
if (strstr(idDescriptor[stream[word]].c_str(), "16")) {
|
||||
idDescriptor[resultId].append("16");
|
||||
}
|
||||
if (strstr(idDescriptor[stream[word]].c_str(), "64")) {
|
||||
idDescriptor[resultId].append("64");
|
||||
}
|
||||
}
|
||||
idDescriptor[resultId].append("vec");
|
||||
switch (stream[word + 1]) {
|
||||
case 2: idDescriptor[resultId].append("2"); break;
|
||||
@@ -446,14 +495,38 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
||||
--numOperands;
|
||||
if (opCode == OpExtInst) {
|
||||
ExtInstSet extInstSet = GLSL450Inst;
|
||||
if (0 == memcmp("OpenCL", (const char*)(idDescriptor[stream[word-2]].c_str()), 6)) {
|
||||
const char* name = idDescriptor[stream[word - 2]].c_str();
|
||||
if (0 == memcmp("OpenCL", name, 6)) {
|
||||
extInstSet = OpenCLExtInst;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
|
||||
strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
|
||||
strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
|
||||
strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
|
||||
extInstSet = GLSLextAMDInst;
|
||||
#endif
|
||||
#ifdef NV_EXTENSIONS
|
||||
}else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
|
||||
strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
|
||||
strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
|
||||
strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) {
|
||||
extInstSet = GLSLextNVInst;
|
||||
#endif
|
||||
}
|
||||
unsigned entrypoint = stream[word - 1];
|
||||
if (extInstSet == GLSL450Inst) {
|
||||
if (entrypoint < GLSLstd450Count) {
|
||||
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
|
||||
}
|
||||
#ifdef AMD_EXTENSIONS
|
||||
} else if (extInstSet == GLSLextAMDInst) {
|
||||
out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
|
||||
#endif
|
||||
#ifdef NV_EXTENSIONS
|
||||
}
|
||||
else if (extInstSet == GLSLextNVInst) {
|
||||
out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -561,6 +634,79 @@ static void GLSLstd450GetDebugNames(const char** names)
|
||||
names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
|
||||
}
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
|
||||
{
|
||||
if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
|
||||
switch (entrypoint) {
|
||||
case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";
|
||||
case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";
|
||||
case WriteInvocationAMD: return "WriteInvocationAMD";
|
||||
case MbcntAMD: return "MbcntAMD";
|
||||
default: return "Bad";
|
||||
}
|
||||
} else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {
|
||||
switch (entrypoint) {
|
||||
case FMin3AMD: return "FMin3AMD";
|
||||
case UMin3AMD: return "UMin3AMD";
|
||||
case SMin3AMD: return "SMin3AMD";
|
||||
case FMax3AMD: return "FMax3AMD";
|
||||
case UMax3AMD: return "UMax3AMD";
|
||||
case SMax3AMD: return "SMax3AMD";
|
||||
case FMid3AMD: return "FMid3AMD";
|
||||
case UMid3AMD: return "UMid3AMD";
|
||||
case SMid3AMD: return "SMid3AMD";
|
||||
default: return "Bad";
|
||||
}
|
||||
} else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {
|
||||
switch (entrypoint) {
|
||||
case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";
|
||||
default: return "Bad";
|
||||
}
|
||||
}
|
||||
else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {
|
||||
switch (entrypoint) {
|
||||
case CubeFaceIndexAMD: return "CubeFaceIndexAMD";
|
||||
case CubeFaceCoordAMD: return "CubeFaceCoordAMD";
|
||||
case TimeAMD: return "TimeAMD";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "Bad";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NV_EXTENSIONS
|
||||
static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
|
||||
{
|
||||
if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
|
||||
strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||
|
||||
strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||
|
||||
strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||
|
||||
strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) {
|
||||
switch (entrypoint) {
|
||||
case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
|
||||
case DecorationPassthroughNV: return "PassthroughNV";
|
||||
case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
|
||||
case DecorationViewportRelativeNV: return "ViewportRelativeNV";
|
||||
case BuiltInViewportMaskNV: return "ViewportMaskNV";
|
||||
case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
|
||||
case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
|
||||
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
|
||||
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
|
||||
case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
|
||||
case BuiltInPositionPerViewNV: return "PositionPerViewNV";
|
||||
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
|
||||
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
|
||||
default: return "Bad";
|
||||
}
|
||||
}
|
||||
return "Bad";
|
||||
}
|
||||
#endif
|
||||
|
||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
|
||||
{
|
||||
SpirvStream SpirvStream(out, stream);
|
||||
|
||||
+17
-17
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,18 +19,18 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Disassembler for SPIR-V.
|
||||
|
||||
Vendored
+468
-608
File diff suppressed because it is too large
Load Diff
Vendored
+20
-22
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,23 +19,25 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Parameterize the SPIR-V enumerants.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <vector>
|
||||
@@ -149,7 +151,7 @@ enum OperandClass {
|
||||
OperandMemorySemantics,
|
||||
OperandMemoryAccess,
|
||||
OperandScope,
|
||||
OperandGroupOperation,
|
||||
OperandGroupOperation,
|
||||
OperandKernelEnqueueFlags,
|
||||
OperandKernelProfilingInfo,
|
||||
OperandCapability,
|
||||
@@ -188,7 +190,6 @@ protected:
|
||||
class EnumParameters {
|
||||
public:
|
||||
EnumParameters() : desc(0) { }
|
||||
EnumCaps caps;
|
||||
const char* desc;
|
||||
};
|
||||
|
||||
@@ -233,7 +234,6 @@ public:
|
||||
bool hasType() const { return typePresent != 0; }
|
||||
|
||||
const char* opDesc;
|
||||
EnumCaps capabilities;
|
||||
OpcodeClass opClass;
|
||||
OperandParameters operands;
|
||||
|
||||
@@ -242,8 +242,6 @@ protected:
|
||||
int resultPresent : 1;
|
||||
};
|
||||
|
||||
const int OpcodeCeiling = 321;
|
||||
|
||||
// The set of objects that hold all the instruction/operand
|
||||
// parameterization information.
|
||||
extern InstructionParameters InstructionDesc[];
|
||||
|
||||
Vendored
+1078
File diff suppressed because it is too large
Load Diff
+191
-5
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
// Copyright (c) 2014-2018 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"),
|
||||
@@ -46,12 +46,12 @@ namespace spv {
|
||||
|
||||
typedef unsigned int Id;
|
||||
|
||||
#define SPV_VERSION 0x10000
|
||||
#define SPV_REVISION 6
|
||||
#define SPV_VERSION 0x10300
|
||||
#define SPV_REVISION 1
|
||||
|
||||
static const unsigned int MagicNumber = 0x07230203;
|
||||
static const unsigned int Version = 0x00010000;
|
||||
static const unsigned int Revision = 6;
|
||||
static const unsigned int Version = 0x00010300;
|
||||
static const unsigned int Revision = 1;
|
||||
static const unsigned int OpCodeMask = 0xffff;
|
||||
static const unsigned int WordCountShift = 16;
|
||||
|
||||
@@ -122,6 +122,15 @@ enum ExecutionMode {
|
||||
ExecutionModeOutputTriangleStrip = 29,
|
||||
ExecutionModeVecTypeHint = 30,
|
||||
ExecutionModeContractionOff = 31,
|
||||
ExecutionModeInitializer = 33,
|
||||
ExecutionModeFinalizer = 34,
|
||||
ExecutionModeSubgroupSize = 35,
|
||||
ExecutionModeSubgroupsPerWorkgroup = 36,
|
||||
ExecutionModeSubgroupsPerWorkgroupId = 37,
|
||||
ExecutionModeLocalSizeId = 38,
|
||||
ExecutionModeLocalSizeHintId = 39,
|
||||
ExecutionModePostDepthCoverage = 4446,
|
||||
ExecutionModeStencilRefReplacingEXT = 5027,
|
||||
ExecutionModeMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -138,6 +147,7 @@ enum StorageClass {
|
||||
StorageClassPushConstant = 9,
|
||||
StorageClassAtomicCounter = 10,
|
||||
StorageClassImage = 11,
|
||||
StorageClassStorageBuffer = 12,
|
||||
StorageClassMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -375,6 +385,17 @@ enum Decoration {
|
||||
DecorationNoContraction = 42,
|
||||
DecorationInputAttachmentIndex = 43,
|
||||
DecorationAlignment = 44,
|
||||
DecorationMaxByteOffset = 45,
|
||||
DecorationAlignmentId = 46,
|
||||
DecorationMaxByteOffsetId = 47,
|
||||
DecorationExplicitInterpAMD = 4999,
|
||||
DecorationOverrideCoverageNV = 5248,
|
||||
DecorationPassthroughNV = 5250,
|
||||
DecorationViewportRelativeNV = 5252,
|
||||
DecorationSecondaryViewportRelativeNV = 5256,
|
||||
DecorationNonUniformEXT = 5300,
|
||||
DecorationHlslCounterBufferGOOGLE = 5634,
|
||||
DecorationHlslSemanticGOOGLE = 5635,
|
||||
DecorationMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -420,6 +441,35 @@ enum BuiltIn {
|
||||
BuiltInSubgroupLocalInvocationId = 41,
|
||||
BuiltInVertexIndex = 42,
|
||||
BuiltInInstanceIndex = 43,
|
||||
BuiltInSubgroupEqMask = 4416,
|
||||
BuiltInSubgroupEqMaskKHR = 4416,
|
||||
BuiltInSubgroupGeMask = 4417,
|
||||
BuiltInSubgroupGeMaskKHR = 4417,
|
||||
BuiltInSubgroupGtMask = 4418,
|
||||
BuiltInSubgroupGtMaskKHR = 4418,
|
||||
BuiltInSubgroupLeMask = 4419,
|
||||
BuiltInSubgroupLeMaskKHR = 4419,
|
||||
BuiltInSubgroupLtMask = 4420,
|
||||
BuiltInSubgroupLtMaskKHR = 4420,
|
||||
BuiltInBaseVertex = 4424,
|
||||
BuiltInBaseInstance = 4425,
|
||||
BuiltInDrawIndex = 4426,
|
||||
BuiltInDeviceIndex = 4438,
|
||||
BuiltInViewIndex = 4440,
|
||||
BuiltInBaryCoordNoPerspAMD = 4992,
|
||||
BuiltInBaryCoordNoPerspCentroidAMD = 4993,
|
||||
BuiltInBaryCoordNoPerspSampleAMD = 4994,
|
||||
BuiltInBaryCoordSmoothAMD = 4995,
|
||||
BuiltInBaryCoordSmoothCentroidAMD = 4996,
|
||||
BuiltInBaryCoordSmoothSampleAMD = 4997,
|
||||
BuiltInBaryCoordPullModelAMD = 4998,
|
||||
BuiltInFragStencilRefEXT = 5014,
|
||||
BuiltInViewportMaskNV = 5253,
|
||||
BuiltInSecondaryPositionNV = 5257,
|
||||
BuiltInSecondaryViewportMaskNV = 5258,
|
||||
BuiltInPositionPerViewNV = 5261,
|
||||
BuiltInViewportMaskPerViewNV = 5262,
|
||||
BuiltInFullyCoveredEXT = 5264,
|
||||
BuiltInMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -438,6 +488,8 @@ enum SelectionControlMask {
|
||||
enum LoopControlShift {
|
||||
LoopControlUnrollShift = 0,
|
||||
LoopControlDontUnrollShift = 1,
|
||||
LoopControlDependencyInfiniteShift = 2,
|
||||
LoopControlDependencyLengthShift = 3,
|
||||
LoopControlMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -445,6 +497,8 @@ enum LoopControlMask {
|
||||
LoopControlMaskNone = 0,
|
||||
LoopControlUnrollMask = 0x00000001,
|
||||
LoopControlDontUnrollMask = 0x00000002,
|
||||
LoopControlDependencyInfiniteMask = 0x00000004,
|
||||
LoopControlDependencyLengthMask = 0x00000008,
|
||||
};
|
||||
|
||||
enum FunctionControlShift {
|
||||
@@ -518,6 +572,10 @@ enum GroupOperation {
|
||||
GroupOperationReduce = 0,
|
||||
GroupOperationInclusiveScan = 1,
|
||||
GroupOperationExclusiveScan = 2,
|
||||
GroupOperationClusteredReduce = 3,
|
||||
GroupOperationPartitionedReduceNV = 6,
|
||||
GroupOperationPartitionedInclusiveScanNV = 7,
|
||||
GroupOperationPartitionedExclusiveScanNV = 8,
|
||||
GroupOperationMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -595,6 +653,61 @@ enum Capability {
|
||||
CapabilityStorageImageReadWithoutFormat = 55,
|
||||
CapabilityStorageImageWriteWithoutFormat = 56,
|
||||
CapabilityMultiViewport = 57,
|
||||
CapabilitySubgroupDispatch = 58,
|
||||
CapabilityNamedBarrier = 59,
|
||||
CapabilityPipeStorage = 60,
|
||||
CapabilityGroupNonUniform = 61,
|
||||
CapabilityGroupNonUniformVote = 62,
|
||||
CapabilityGroupNonUniformArithmetic = 63,
|
||||
CapabilityGroupNonUniformBallot = 64,
|
||||
CapabilityGroupNonUniformShuffle = 65,
|
||||
CapabilityGroupNonUniformShuffleRelative = 66,
|
||||
CapabilityGroupNonUniformClustered = 67,
|
||||
CapabilityGroupNonUniformQuad = 68,
|
||||
CapabilitySubgroupBallotKHR = 4423,
|
||||
CapabilityDrawParameters = 4427,
|
||||
CapabilitySubgroupVoteKHR = 4431,
|
||||
CapabilityStorageBuffer16BitAccess = 4433,
|
||||
CapabilityStorageUniformBufferBlock16 = 4433,
|
||||
CapabilityStorageUniform16 = 4434,
|
||||
CapabilityUniformAndStorageBuffer16BitAccess = 4434,
|
||||
CapabilityStoragePushConstant16 = 4435,
|
||||
CapabilityStorageInputOutput16 = 4436,
|
||||
CapabilityDeviceGroup = 4437,
|
||||
CapabilityMultiView = 4439,
|
||||
CapabilityVariablePointersStorageBuffer = 4441,
|
||||
CapabilityVariablePointers = 4442,
|
||||
CapabilityAtomicStorageOps = 4445,
|
||||
CapabilitySampleMaskPostDepthCoverage = 4447,
|
||||
CapabilityFloat16ImageAMD = 5008,
|
||||
CapabilityImageGatherBiasLodAMD = 5009,
|
||||
CapabilityFragmentMaskAMD = 5010,
|
||||
CapabilityStencilExportEXT = 5013,
|
||||
CapabilityImageReadWriteLodAMD = 5015,
|
||||
CapabilitySampleMaskOverrideCoverageNV = 5249,
|
||||
CapabilityGeometryShaderPassthroughNV = 5251,
|
||||
CapabilityShaderViewportIndexLayerEXT = 5254,
|
||||
CapabilityShaderViewportIndexLayerNV = 5254,
|
||||
CapabilityShaderViewportMaskNV = 5255,
|
||||
CapabilityShaderStereoViewNV = 5259,
|
||||
CapabilityPerViewAttributesNV = 5260,
|
||||
CapabilityFragmentFullyCoveredEXT = 5265,
|
||||
CapabilityGroupNonUniformPartitionedNV = 5297,
|
||||
CapabilityShaderNonUniformEXT = 5301,
|
||||
CapabilityRuntimeDescriptorArrayEXT = 5302,
|
||||
CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303,
|
||||
CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304,
|
||||
CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305,
|
||||
CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306,
|
||||
CapabilitySampledImageArrayNonUniformIndexingEXT = 5307,
|
||||
CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308,
|
||||
CapabilityStorageImageArrayNonUniformIndexingEXT = 5309,
|
||||
CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310,
|
||||
CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311,
|
||||
CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,
|
||||
CapabilitySubgroupShuffleINTEL = 5568,
|
||||
CapabilitySubgroupBufferBlockIOINTEL = 5569,
|
||||
CapabilitySubgroupImageBlockIOINTEL = 5570,
|
||||
CapabilityMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -893,6 +1006,79 @@ enum Op {
|
||||
OpAtomicFlagTestAndSet = 318,
|
||||
OpAtomicFlagClear = 319,
|
||||
OpImageSparseRead = 320,
|
||||
OpSizeOf = 321,
|
||||
OpTypePipeStorage = 322,
|
||||
OpConstantPipeStorage = 323,
|
||||
OpCreatePipeFromPipeStorage = 324,
|
||||
OpGetKernelLocalSizeForSubgroupCount = 325,
|
||||
OpGetKernelMaxNumSubgroups = 326,
|
||||
OpTypeNamedBarrier = 327,
|
||||
OpNamedBarrierInitialize = 328,
|
||||
OpMemoryNamedBarrier = 329,
|
||||
OpModuleProcessed = 330,
|
||||
OpExecutionModeId = 331,
|
||||
OpDecorateId = 332,
|
||||
OpGroupNonUniformElect = 333,
|
||||
OpGroupNonUniformAll = 334,
|
||||
OpGroupNonUniformAny = 335,
|
||||
OpGroupNonUniformAllEqual = 336,
|
||||
OpGroupNonUniformBroadcast = 337,
|
||||
OpGroupNonUniformBroadcastFirst = 338,
|
||||
OpGroupNonUniformBallot = 339,
|
||||
OpGroupNonUniformInverseBallot = 340,
|
||||
OpGroupNonUniformBallotBitExtract = 341,
|
||||
OpGroupNonUniformBallotBitCount = 342,
|
||||
OpGroupNonUniformBallotFindLSB = 343,
|
||||
OpGroupNonUniformBallotFindMSB = 344,
|
||||
OpGroupNonUniformShuffle = 345,
|
||||
OpGroupNonUniformShuffleXor = 346,
|
||||
OpGroupNonUniformShuffleUp = 347,
|
||||
OpGroupNonUniformShuffleDown = 348,
|
||||
OpGroupNonUniformIAdd = 349,
|
||||
OpGroupNonUniformFAdd = 350,
|
||||
OpGroupNonUniformIMul = 351,
|
||||
OpGroupNonUniformFMul = 352,
|
||||
OpGroupNonUniformSMin = 353,
|
||||
OpGroupNonUniformUMin = 354,
|
||||
OpGroupNonUniformFMin = 355,
|
||||
OpGroupNonUniformSMax = 356,
|
||||
OpGroupNonUniformUMax = 357,
|
||||
OpGroupNonUniformFMax = 358,
|
||||
OpGroupNonUniformBitwiseAnd = 359,
|
||||
OpGroupNonUniformBitwiseOr = 360,
|
||||
OpGroupNonUniformBitwiseXor = 361,
|
||||
OpGroupNonUniformLogicalAnd = 362,
|
||||
OpGroupNonUniformLogicalOr = 363,
|
||||
OpGroupNonUniformLogicalXor = 364,
|
||||
OpGroupNonUniformQuadBroadcast = 365,
|
||||
OpGroupNonUniformQuadSwap = 366,
|
||||
OpSubgroupBallotKHR = 4421,
|
||||
OpSubgroupFirstInvocationKHR = 4422,
|
||||
OpSubgroupAllKHR = 4428,
|
||||
OpSubgroupAnyKHR = 4429,
|
||||
OpSubgroupAllEqualKHR = 4430,
|
||||
OpSubgroupReadInvocationKHR = 4432,
|
||||
OpGroupIAddNonUniformAMD = 5000,
|
||||
OpGroupFAddNonUniformAMD = 5001,
|
||||
OpGroupFMinNonUniformAMD = 5002,
|
||||
OpGroupUMinNonUniformAMD = 5003,
|
||||
OpGroupSMinNonUniformAMD = 5004,
|
||||
OpGroupFMaxNonUniformAMD = 5005,
|
||||
OpGroupUMaxNonUniformAMD = 5006,
|
||||
OpGroupSMaxNonUniformAMD = 5007,
|
||||
OpFragmentMaskFetchAMD = 5011,
|
||||
OpFragmentFetchAMD = 5012,
|
||||
OpGroupNonUniformPartitionNV = 5296,
|
||||
OpSubgroupShuffleINTEL = 5571,
|
||||
OpSubgroupShuffleDownINTEL = 5572,
|
||||
OpSubgroupShuffleUpINTEL = 5573,
|
||||
OpSubgroupShuffleXorINTEL = 5574,
|
||||
OpSubgroupBlockReadINTEL = 5575,
|
||||
OpSubgroupBlockWriteINTEL = 5576,
|
||||
OpSubgroupImageBlockReadINTEL = 5577,
|
||||
OpSubgroupImageBlockWriteINTEL = 5578,
|
||||
OpDecorateStringGOOGLE = 5632,
|
||||
OpMemberDecorateStringGOOGLE = 5633,
|
||||
OpMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
|
||||
Vendored
+39
-31
@@ -1,11 +1,11 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
// Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
// All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
@@ -19,26 +19,26 @@
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// SPIRV-IR
|
||||
//
|
||||
// Simple in-memory representation (IR) of SPIRV. Just for holding
|
||||
// Each function's CFG of blocks. Has this hierarchy:
|
||||
// - Module, which is a list of
|
||||
// - Function, which is a list of
|
||||
// - Block, which is a list of
|
||||
// - Module, which is a list of
|
||||
// - Function, which is a list of
|
||||
// - Block, which is a list of
|
||||
// - Instruction
|
||||
//
|
||||
|
||||
@@ -65,12 +65,17 @@ const Id NoResult = 0;
|
||||
const Id NoType = 0;
|
||||
|
||||
const Decoration NoPrecision = DecorationMax;
|
||||
const MemorySemanticsMask MemorySemanticsAllMemory =
|
||||
(MemorySemanticsMask)(MemorySemanticsSequentiallyConsistentMask |
|
||||
MemorySemanticsUniformMemoryMask |
|
||||
MemorySemanticsSubgroupMemoryMask |
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define POTENTIALLY_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define POTENTIALLY_UNUSED
|
||||
#endif
|
||||
|
||||
POTENTIALLY_UNUSED
|
||||
const MemorySemanticsMask MemorySemanticsAllMemory =
|
||||
(MemorySemanticsMask)(MemorySemanticsUniformMemoryMask |
|
||||
MemorySemanticsWorkgroupMemoryMask |
|
||||
MemorySemanticsCrossWorkgroupMemoryMask |
|
||||
MemorySemanticsAtomicCounterMemoryMask |
|
||||
MemorySemanticsImageMemoryMask);
|
||||
|
||||
@@ -87,7 +92,6 @@ public:
|
||||
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
|
||||
void addStringOperand(const char* str)
|
||||
{
|
||||
originalString = str;
|
||||
unsigned int word;
|
||||
char* wordString = (char*)&word;
|
||||
char* wordPtr = wordString;
|
||||
@@ -120,7 +124,6 @@ public:
|
||||
Id getTypeId() const { return typeId; }
|
||||
Id getIdOperand(int op) const { return operands[op]; }
|
||||
unsigned int getImmediateOperand(int op) const { return operands[op]; }
|
||||
const char* getStringOperand() const { return originalString.c_str(); }
|
||||
|
||||
// Write out the binary form.
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
@@ -151,7 +154,6 @@ protected:
|
||||
Id typeId;
|
||||
Op opCode;
|
||||
std::vector<Id> operands;
|
||||
std::string originalString; // could be optimized away; convenience for getting string operand
|
||||
Block* block;
|
||||
};
|
||||
|
||||
@@ -229,7 +231,7 @@ protected:
|
||||
std::vector<std::unique_ptr<Instruction> > localVariables;
|
||||
Function& parent;
|
||||
|
||||
// track whether this block is known to be uncreachable (not necessarily
|
||||
// track whether this block is known to be uncreachable (not necessarily
|
||||
// true for all unreachable blocks, but should be set at least
|
||||
// for the extraneous ones introduced by the builder).
|
||||
bool unreachable;
|
||||
@@ -256,7 +258,8 @@ public:
|
||||
delete blocks[i];
|
||||
}
|
||||
Id getId() const { return functionInstruction.getResultId(); }
|
||||
Id getParamId(int p) { return parameterInstructions[p]->getResultId(); }
|
||||
Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); }
|
||||
Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); }
|
||||
|
||||
void addBlock(Block* block) { blocks.push_back(block); }
|
||||
void removeBlock(Block* block)
|
||||
@@ -273,6 +276,10 @@ public:
|
||||
const std::vector<Block*>& getBlocks() const { return blocks; }
|
||||
void addLocalVariable(std::unique_ptr<Instruction> inst);
|
||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
||||
|
||||
void setImplicitThis() { implicitThis = true; }
|
||||
bool hasImplicitThis() const { return implicitThis; }
|
||||
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// OpFunction
|
||||
@@ -296,6 +303,7 @@ protected:
|
||||
Instruction functionInstruction;
|
||||
std::vector<Instruction*> parameterInstructions;
|
||||
std::vector<Block*> blocks;
|
||||
bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument
|
||||
};
|
||||
|
||||
//
|
||||
@@ -354,7 +362,7 @@ protected:
|
||||
// - the OpFunction instruction
|
||||
// - all the OpFunctionParameter instructions
|
||||
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
|
||||
: parent(parent), functionInstruction(id, resultType, OpFunction)
|
||||
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false)
|
||||
{
|
||||
// OpFunction
|
||||
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
|
||||
|
||||
Reference in New Issue
Block a user