Просмотр исходного кода

metal compute shader generation

attilaz 7 лет назад
Родитель
Сommit
b9b58296c7

+ 1 - 1
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

+ 2 - 0
scripts/shaderc.lua

@@ -604,6 +604,8 @@ project "shaderc"
 
 		path.join(GLSL_OPTIMIZER, "include"),
 		path.join(GLSL_OPTIMIZER, "src/glsl"),
+
+		SPIRV_CROSS,
 	}
 
 	links {

+ 6 - 0
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)]
 

+ 2 - 1
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;

+ 13 - 12
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);
 

+ 11 - 5
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)
 							{

+ 53 - 5
tools/shaderc/shaderc_spirv.cpp

@@ -14,6 +14,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow") // warning: declaration of 'u
 #include <ResourceLimits.h>
 #include <SPIRV/SPVRemapper.h>
 #include <SPIRV/GlslangToSpv.h>
+#include <spirv_msl.hpp>
 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);