From b9b58296c74dc098aa39eac34a660b75fd126fd5 Mon Sep 17 00:00:00 2001 From: attilaz Date: Mon, 14 Jan 2019 09:24:06 +0100 Subject: [PATCH] metal compute shader generation --- scripts/shader.mk | 2 +- scripts/shaderc.lua | 2 ++ src/bgfx_compute.sh | 6 ++++ src/renderer_mtl.h | 3 +- src/renderer_mtl.mm | 25 +++++++------- tools/shaderc/shaderc.cpp | 16 ++++++--- tools/shaderc/shaderc_spirv.cpp | 58 ++++++++++++++++++++++++++++++--- 7 files changed, 88 insertions(+), 24 deletions(-) diff --git a/scripts/shader.mk b/scripts/shader.mk index 657140544..95a02cd67 100644 --- a/scripts/shader.mk +++ b/scripts/shader.mk @@ -116,7 +116,7 @@ CS_BIN = $(addprefix $(BUILD_INTERMEDIATE_DIR)/, $(addsuffix .bin, $(basename $( BIN = $(VS_BIN) $(FS_BIN) ASM = $(VS_ASM) $(FS_ASM) -ifeq ($(TARGET), $(filter $(TARGET),1 3 4 6)) +ifeq ($(TARGET), $(filter $(TARGET),1 3 4 5 6)) BIN += $(CS_BIN) ASM += $(CS_ASM) endif diff --git a/scripts/shaderc.lua b/scripts/shaderc.lua index 7fdae316d..5d262602f 100644 --- a/scripts/shaderc.lua +++ b/scripts/shaderc.lua @@ -604,6 +604,8 @@ project "shaderc" path.join(GLSL_OPTIMIZER, "include"), path.join(GLSL_OPTIMIZER, "src/glsl"), + + SPIRV_CROSS, } links { diff --git a/src/bgfx_compute.sh b/src/bgfx_compute.sh index 2f61a455f..4b4ddf378 100644 --- a/src/bgfx_compute.sh +++ b/src/bgfx_compute.sh @@ -124,9 +124,15 @@ #define IMAGE3D_WR( _name, _format, _reg) IMAGE3D_RW(_name, _format, _reg) #define UIMAGE3D_WR(_name, _format, _reg) IMAGE3D_RW(_name, _format, _reg) +#if BGFX_SHADER_LANGUAGE_METAL +#define BUFFER_RO(_name, _struct, _reg) StructuredBuffer<_struct> _name : REGISTER(t, _reg) +#define BUFFER_RW(_name, _struct, _reg) RWStructuredBuffer <_struct> _name : REGISTER(u, _reg) +#define BUFFER_WR(_name, _struct, _reg) BUFFER_RW(_name, _struct, _reg) +#else #define BUFFER_RO(_name, _struct, _reg) Buffer<_struct> _name : REGISTER(t, _reg) #define BUFFER_RW(_name, _struct, _reg) RWBuffer<_struct> _name : REGISTER(u, _reg) #define BUFFER_WR(_name, _struct, _reg) BUFFER_RW(_name, _struct, _reg) +#endif #define NUM_THREADS(_x, _y, _z) [numthreads(_x, _y, _z)] diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index ae73cee52..b7e9ff779 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -831,6 +831,7 @@ namespace bgfx { namespace mtl Function m_function; uint32_t m_hash; + uint16_t m_numThreads[3]; }; struct SamplerInfo @@ -912,7 +913,7 @@ namespace bgfx { namespace mtl SamplerInfo m_samplers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; uint32_t m_samplerCount; - uint32_t m_numThreads[3]; + uint16_t m_numThreads[3]; PredefinedUniform m_predefined[PredefinedUniform::Count*2]; uint8_t m_numPredefined; diff --git a/src/renderer_mtl.mm b/src/renderer_mtl.mm index 1804ad41f..5bd683e4f 100644 --- a/src/renderer_mtl.mm +++ b/src/renderer_mtl.mm @@ -1763,18 +1763,6 @@ namespace bgfx { namespace mtl MTLDataType dataType = uniform.dataType; uint32_t num = 1; - if (dataType == MTLDataTypeInt && bx::strLen(name) > 14 - && 0 == bx::strCmp(name, "NUM_THREADS_", 12) ) - { - const int32_t dim = name[12] - 'X'; - - if (dim >= 0 - && dim <= 2) - { - bx::fromString(&ps->m_numThreads[dim], bx::StringView(name, 14, INT_MAX)); - } - } - if (dataType == MTLDataTypeArray) { dataType = uniform.arrayType.elementType; @@ -2147,6 +2135,11 @@ namespace bgfx { namespace mtl ComputePipelineReflection reflection = NULL; pso->m_cps = m_device.newComputePipelineStateWithFunction(program.m_vsh->m_function, MTLPipelineOptionBufferTypeInfo, &reflection); processArguments(pso, reflection.arguments, NULL); + + for (uint32_t ii = 0; ii < 3; ++ii) + { + pso->m_numThreads[ii] = program.m_vsh->m_numThreads[ii]; + } } return program.m_computePS; @@ -2378,6 +2371,14 @@ namespace bgfx { namespace mtl bx::read(&reader, regCount); } + if (isShaderType(magic, 'C')) + { + for (uint32_t ii = 0; ii < 3; ++ii) + { + bx::read(&reader, m_numThreads[ii]); + } + } + uint32_t shaderSize; bx::read(&reader, shaderSize); diff --git a/tools/shaderc/shaderc.cpp b/tools/shaderc/shaderc.cpp index 194ce9d5c..4d4a06ef5 100644 --- a/tools/shaderc/shaderc.cpp +++ b/tools/shaderc/shaderc.cpp @@ -1046,7 +1046,14 @@ namespace bgfx else if (0 == bx::strCmpI(platform, "osx") ) { preprocessor.setDefine("BX_PLATFORM_OSX=1"); - preprocessor.setDefine(glslDefine); + if (_options.shaderType == 'c') + { + preprocessor.setDefine("BGFX_SHADER_LANGUAGE_SPIRV=1"); + } + else + { + preprocessor.setDefine(glslDefine); + } char temp[256]; bx::snprintf(temp, sizeof(temp), "BGFX_SHADER_LANGUAGE_METAL=%d", metal); preprocessor.setDefine(temp); @@ -1327,8 +1334,7 @@ namespace bgfx else { if (0 != glsl - || 0 != essl - || 0 != metal) + || 0 != essl) { } else @@ -1456,9 +1462,9 @@ namespace bgfx code += _comment; code += preprocessor.m_preprocessed; - if (0 != spirv) + if (0 != spirv || 0 != metal) { - compiled = compileSPIRVShader(_options, 0, code, _writer); + compiled = compileSPIRVShader(_options, metal ? BX_MAKEFOURCC('M', 'T', 'L', 0) : 0, code, _writer); } else if (0 != pssl) { diff --git a/tools/shaderc/shaderc_spirv.cpp b/tools/shaderc/shaderc_spirv.cpp index 105a4314e..ac7349f22 100644 --- a/tools/shaderc/shaderc_spirv.cpp +++ b/tools/shaderc/shaderc_spirv.cpp @@ -14,6 +14,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u #include #include #include +#include BX_PRAGMA_DIAGNOSTIC_POP() namespace bgfx @@ -799,12 +800,59 @@ namespace bgfx { namespace spirv bx::MemoryReader reader(spirv.data(), uint32_t(spirv.size()*4) ); disassemble(writer, &reader, &err); - uint32_t shaderSize = (uint32_t)spirv.size()*sizeof(uint32_t); - bx::write(_writer, shaderSize); - bx::write(_writer, spirv.data(), shaderSize); - uint8_t nul = 0; - bx::write(_writer, nul); + if (_version == BX_MAKEFOURCC('M', 'T', 'L', 0)) + { + if (g_verbose) + { + glslang::SpirvToolsDisassemble(std::cout, spirv); + } + spirv_cross::CompilerMSL msl(std::move(spirv)); + + spirv_cross::ShaderResources resources = msl.get_shader_resources(); + + int numThreads[3]; + for (int i = 0; i < 3; ++i) + numThreads[i] = msl.get_execution_mode_argument(spv::ExecutionMode::ExecutionModeLocalSize, i); + + msl.rename_entry_point("main", "xlatMtlMain", spv::ExecutionModel::ExecutionModelGLCompute); + + for (auto &resource : resources.uniform_buffers) + { + msl.set_name(resource.id, "_mtl_u"); + } + + for (auto &resource : resources.storage_buffers) + { + unsigned binding = msl.get_decoration(resource.id, spv::DecorationBinding); + msl.set_decoration(resource.id, spv::DecorationBinding, binding + 1); + + // workaround spirv -> msl codegen problem: same name was used as struct type and function parameter name + msl.set_name(resource.id, "_" + msl.get_name(resource.id)); + } + + std::string source = msl.compile(); + + for (int i = 0; i < 3; ++i) + { + uint16_t dim = (uint16_t)msl.get_execution_mode_argument(spv::ExecutionMode::ExecutionModeLocalSize, i); + bx::write(_writer, dim); + } + + uint32_t shaderSize = (uint32_t)source.size(); + bx::write(_writer, shaderSize); + bx::write(_writer, source.c_str(), shaderSize); + uint8_t nul = 0; + bx::write(_writer, nul); + } + else + { + uint32_t shaderSize = (uint32_t)spirv.size() * sizeof(uint32_t); + bx::write(_writer, shaderSize); + bx::write(_writer, spirv.data(), shaderSize); + uint8_t nul = 0; + bx::write(_writer, nul); + } // const uint8_t numAttr = (uint8_t)program->getNumLiveAttributes(); bx::write(_writer, numAttr);