Browse Source

Add debugname field to shader options table.

Sasha Szpakowski 1 year ago
parent
commit
dbcdbc47d5

+ 2 - 2
src/modules/graphics/Graphics.cpp

@@ -402,7 +402,7 @@ Shader *Graphics::newShader(const std::vector<std::string> &stagessource, const
 
 	}
 
-	return newShaderInternal(stages);
+	return newShaderInternal(stages, options);
 }
 
 Shader *Graphics::newComputeShader(const std::string &source, const Shader::CompileOptions &options)
@@ -418,7 +418,7 @@ Shader *Graphics::newComputeShader(const std::string &source, const Shader::Comp
 	// shouldn't be much reuse.
 	stages[SHADERSTAGE_COMPUTE].set(newShaderStage(SHADERSTAGE_COMPUTE, source, options, info, false));
 
-	return newShaderInternal(stages);
+	return newShaderInternal(stages, options);
 }
 
 Buffer *Graphics::newBuffer(const Buffer::Settings &settings, DataFormat format, const void *data, size_t size, size_t arraylength)

+ 1 - 1
src/modules/graphics/Graphics.h

@@ -1020,7 +1020,7 @@ protected:
 
 	ShaderStage *newShaderStage(ShaderStageType stage, const std::string &source, const Shader::CompileOptions &options, const Shader::SourceInfo &info, bool cache);
 	virtual ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) = 0;
-	virtual Shader *newShaderInternal(StrongRef<ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) = 0;
+	virtual Shader *newShaderInternal(StrongRef<ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options) = 0;
 	virtual StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) = 0;
 
 	virtual GraphicsReadback *newReadbackInternal(ReadbackMethod method, Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset) = 0;

+ 16 - 1
src/modules/graphics/Shader.cpp

@@ -686,8 +686,9 @@ std::string Shader::createShaderStageCode(Graphics *gfx, ShaderStageType stage,
 	return ss.str();
 }
 
-Shader::Shader(StrongRef<ShaderStage> _stages[])
+Shader::Shader(StrongRef<ShaderStage> _stages[], const CompileOptions &options)
 	: stages()
+	, debugName(options.debugName)
 {
 	std::string err;
 	if (!validateInternal(_stages, err, validationReflection))
@@ -1250,6 +1251,20 @@ bool Shader::fillUniformReflectionData(UniformInfo &u)
 	return true;
 }
 
+std::string Shader::getShaderStageDebugName(ShaderStageType stage) const
+{
+	std::string name = debugName;
+
+	if (!name.empty())
+	{
+		const char *stagename = "unknown";
+		ShaderStage::getConstant(stage, stagename);
+		name += " (" + std::string(stagename) + ")";
+	}
+
+	return name;
+}
+
 bool Shader::initialize()
 {
 	return glslang::InitializeProcess();

+ 8 - 1
src/modules/graphics/Shader.h

@@ -111,6 +111,7 @@ public:
 	struct CompileOptions
 	{
 		std::map<std::string, std::string> defines;
+		std::string debugName;
 	};
 
 	struct SourceInfo
@@ -189,7 +190,7 @@ public:
 	// Pointer to the default Shader.
 	static Shader *standardShaders[STANDARD_MAX_ENUM];
 
-	Shader(StrongRef<ShaderStage> stages[]);
+	Shader(StrongRef<ShaderStage> stages[], const CompileOptions &options);
 	virtual ~Shader();
 
 	/**
@@ -217,6 +218,8 @@ public:
 	 **/
 	virtual std::string getWarnings() const = 0;
 
+	const std::string &getDebugName() const { return debugName; }
+
 	virtual int getVertexAttributeIndex(const std::string &name) = 0;
 
 	virtual const UniformInfo *getUniformInfo(const std::string &name) const = 0;
@@ -291,6 +294,8 @@ protected:
 
 	bool fillUniformReflectionData(UniformInfo &u);
 
+	std::string getShaderStageDebugName(ShaderStageType stage) const;
+
 	static bool validateInternal(StrongRef<ShaderStage> stages[], std::string& err, ValidationReflection &reflection);
 	static DataBaseType getDataBaseType(PixelFormat format);
 	static bool isResourceBaseTypeCompatible(DataBaseType a, DataBaseType b);
@@ -302,6 +307,8 @@ protected:
 
 	ValidationReflection validationReflection;
 
+	std::string debugName;
+
 }; // Shader
 
 } // graphics

+ 1 - 1
src/modules/graphics/metal/Graphics.h

@@ -196,7 +196,7 @@ private:
 	};
 
 	love::graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
-	love::graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override;
+	love::graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options) override;
 	love::graphics::StreamBuffer *newStreamBuffer(BufferUsage usage, size_t size) override;
 
 	love::graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset) override;

+ 2 - 2
src/modules/graphics/metal/Graphics.mm

@@ -438,9 +438,9 @@ love::graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStageType st
 	return new ShaderStage(this, stage, source, gles, cachekey);
 }
 
-love::graphics::Shader *Graphics::newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
+love::graphics::Shader *Graphics::newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options)
 {
-	return new Shader(device, stages);
+	return new Shader(device, stages, options);
 }
 
 love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const std::vector<Buffer::DataDeclaration> &format, const void *data, size_t size, size_t arraylength)

+ 1 - 1
src/modules/graphics/metal/Shader.h

@@ -100,7 +100,7 @@ public:
 		Access access;
 	};
 
-	Shader(id<MTLDevice> device, StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]);
+	Shader(id<MTLDevice> device, StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const CompileOptions &options);
 	virtual ~Shader();
 
 	// Implements Shader.

+ 6 - 2
src/modules/graphics/metal/Shader.mm

@@ -249,8 +249,8 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
 	return EShLangCount;
 }
 
-Shader::Shader(id<MTLDevice> device, StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
-	: love::graphics::Shader(stages)
+Shader::Shader(id<MTLDevice> device, StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const CompileOptions &options)
+	: love::graphics::Shader(stages, options)
 	, functions()
 	, builtinUniformInfo()
 	, localUniformStagingData(nullptr)
@@ -759,6 +759,10 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
 
 			functions[stageindex] = [library newFunctionWithName:library.functionNames[0]];
 
+			std::string debugname = getShaderStageDebugName((ShaderStageType)stageindex);
+			if (!debugname.empty())
+				functions[stageindex].label = @(debugname.c_str());
+
 			auto setTextureBinding = [this](CompilerMSL &msl, int stageindex, const spirv_cross::Resource &resource) -> void
 			{
 				auto it = uniforms.find(resource.name);

+ 2 - 2
src/modules/graphics/opengl/Graphics.cpp

@@ -168,9 +168,9 @@ love::graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStageType st
 	return new ShaderStage(this, stage, source, gles, cachekey);
 }
 
-love::graphics::Shader *Graphics::newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
+love::graphics::Shader *Graphics::newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options)
 {
-	return new Shader(stages);
+	return new Shader(stages, options);
 }
 
 love::graphics::Buffer *Graphics::newBuffer(const Buffer::Settings &settings, const std::vector<Buffer::DataDeclaration> &format, const void *data, size_t size, size_t arraylength)

+ 1 - 1
src/modules/graphics/opengl/Graphics.h

@@ -139,7 +139,7 @@ private:
 	};
 
 	love::graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
-	love::graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override;
+	love::graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options) override;
 	love::graphics::StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) override;
 
 	love::graphics::GraphicsReadback *newReadbackInternal(ReadbackMethod method, love::graphics::Buffer *buffer, size_t offset, size_t size, data::ByteData *dest, size_t destoffset) override;

+ 5 - 2
src/modules/graphics/opengl/Shader.cpp

@@ -43,8 +43,8 @@ static bool isBuffer(Shader::UniformType utype)
 	return utype == Shader::UNIFORM_TEXELBUFFER || utype == Shader::UNIFORM_STORAGEBUFFER;
 }
 
-Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
-	: love::graphics::Shader(stages)
+Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const CompileOptions &options)
+	: love::graphics::Shader(stages, options)
 	, program(0)
 	, splitUniformsPerDraw(false)
 	, builtinUniforms()
@@ -512,6 +512,9 @@ bool Shader::loadVolatile()
 	if (program == 0)
 		throw love::Exception("Cannot create shader program object.");
 
+	if (!debugName.empty() && (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_2))
+		glObjectLabel(GL_PROGRAM, program, -1, debugName.c_str());
+
 	for (const auto &stage : stages)
 	{
 		if (stage.get() != nullptr)

+ 1 - 1
src/modules/graphics/opengl/Shader.h

@@ -52,7 +52,7 @@ public:
 		GLenum internalFormat;
 	};
 
-	Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]);
+	Shader(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const CompileOptions &options);
 	virtual ~Shader();
 
 	// Implements Volatile

+ 2 - 2
src/modules/graphics/vulkan/Graphics.cpp

@@ -1150,9 +1150,9 @@ graphics::ShaderStage *Graphics::newShaderStageInternal(ShaderStageType stage, c
 	return new ShaderStage(this, stage, source, gles, cachekey);
 }
 
-graphics::Shader *Graphics::newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM])
+graphics::Shader *Graphics::newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options)
 {
-	return new Shader(stages);
+	return new Shader(stages, options);
 }
 
 graphics::StreamBuffer *Graphics::newStreamBuffer(BufferUsage type, size_t size)

+ 1 - 1
src/modules/graphics/vulkan/Graphics.h

@@ -328,7 +328,7 @@ public:
 
 protected:
 	graphics::ShaderStage *newShaderStageInternal(ShaderStageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
-	graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]) override;
+	graphics::Shader *newShaderInternal(StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM], const Shader::CompileOptions &options) override;
 	graphics::StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) override;
 	bool dispatch(love::graphics::Shader *shader, int x, int y, int z) override;
 	bool dispatch(love::graphics::Shader *shader, love::graphics::Buffer *indirectargs, size_t argsoffset) override;

+ 15 - 2
src/modules/graphics/vulkan/Shader.cpp

@@ -241,8 +241,8 @@ static bool usesLocalUniformData(const graphics::Shader::UniformInfo *info)
 		info->baseType == graphics::Shader::UNIFORM_UINT;
 }
 
-Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[])
-	: graphics::Shader(stages)
+Shader::Shader(StrongRef<love::graphics::ShaderStage> stages[], const CompileOptions &options)
+	: graphics::Shader(stages, options)
 {
 	auto gfx = Module::getInstance<Graphics>(Module::ModuleType::M_GRAPHICS);
 	vgfx = dynamic_cast<Graphics*>(gfx);
@@ -949,6 +949,19 @@ void Shader::compileShaders()
 		if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS)
 			throw love::Exception("failed to create shader module");
 
+		std::string debugname = getShaderStageDebugName(shaderStage);
+		if (!debugname.empty() && vgfx->getEnabledOptionalInstanceExtensions().debugInfo)
+		{
+			auto device = vgfx->getDevice();
+
+			VkDebugUtilsObjectNameInfoEXT nameInfo{};
+			nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+			nameInfo.objectType = VK_OBJECT_TYPE_SHADER_MODULE;
+			nameInfo.objectHandle = (uint64_t)shaderModule;
+			nameInfo.pObjectName = debugname.c_str();
+			vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
+		}
+
 		shaderModules.push_back(shaderModule);
 
 		VkPipelineShaderStageCreateInfo shaderStageInfo{};

+ 1 - 1
src/modules/graphics/vulkan/Shader.h

@@ -52,7 +52,7 @@ class Shader final
 	, public Volatile
 {
 public:
-	Shader(StrongRef<love::graphics::ShaderStage> stages[]);
+	Shader(StrongRef<love::graphics::ShaderStage> stages[], const CompileOptions &options);
 	virtual ~Shader();
 
 	bool loadVolatile() override;

+ 5 - 0
src/modules/graphics/wrap_Graphics.cpp

@@ -1463,6 +1463,11 @@ static int w_getShaderSource(lua_State *L, int startidx, std::vector<std::string
 			}
 		}
 		lua_pop(L, 1);
+
+		lua_getfield(L, optionsidx, "debugname");
+		if (!lua_isnoneornil(L, -1))
+			options.debugName = luax_checkstring(L, -1);
+		lua_pop(L, 1);
 	}
 
 	return 0;

+ 12 - 0
src/modules/graphics/wrap_Shader.cpp

@@ -517,6 +517,17 @@ int w_Shader_getLocalThreadgroupSize(lua_State* L)
 	return 3;
 }
 
+int w_Shader_getDebugName(lua_State *L)
+{
+	Shader *shader = luax_checkshader(L, 1);
+	const std::string &debugName = shader->getDebugName();
+	if (debugName.empty())
+		lua_pushnil(L);
+	else
+		luax_pushstring(L, debugName);
+	return 1;
+}
+
 static const luaL_Reg w_Shader_functions[] =
 {
 	{ "getWarnings",             w_Shader_getWarnings },
@@ -525,6 +536,7 @@ static const luaL_Reg w_Shader_functions[] =
 	{ "hasUniform",              w_Shader_hasUniform },
 	{ "hasStage",                w_Shader_hasStage },
 	{ "getLocalThreadgroupSize", w_Shader_getLocalThreadgroupSize },
+	{ "getDebugName",            w_Shader_getDebugName },
 	{ 0, 0 }
 };
 

+ 2 - 1
testing/tests/graphics.lua

@@ -710,11 +710,12 @@ love.test.graphics.Shader = function(test)
       return transform_projection * vertex_position; 
     }
   ]]
-  local shader1 = love.graphics.newShader(pixelcode1, vertexcode1)
+  local shader1 = love.graphics.newShader(pixelcode1, vertexcode1, {debugname = 'testshader'})
   test:assertObject(shader1)
   test:assertEquals('vertex shader:\npixel shader:\n', shader1:getWarnings(), 'check shader valid')
   test:assertFalse(shader1:hasUniform('tex1'), 'check invalid uniform')
   test:assertTrue(shader1:hasUniform('tex2'), 'check valid uniform')
+  test:assertEquals('testshader', shader1:getDebugName())
 
   -- check invalid shader
   local pixelcode2 = [[