Merge pull request #2210 from etang-cw/ShaderDump
Add option to dump shaders
This commit is contained in:
commit
756f00ae8f
@ -676,3 +676,14 @@ features that are difficult to support otherwise.
|
|||||||
Unlike `MVK_USE_METAL_PRIVATE_API`, this setting may be overridden at run time.
|
Unlike `MVK_USE_METAL_PRIVATE_API`, this setting may be overridden at run time.
|
||||||
|
|
||||||
This option is not available unless MoltenVK were built with `MVK_USE_METAL_PRIVATE_API` set to `1`.
|
This option is not available unless MoltenVK were built with `MVK_USE_METAL_PRIVATE_API` set to `1`.
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
#### MVK_CONFIG_SHADER_DUMP_DIR
|
||||||
|
|
||||||
|
##### Type: String
|
||||||
|
##### Default: `""`
|
||||||
|
|
||||||
|
_(The default value is an empty string)._
|
||||||
|
|
||||||
|
If not empty, MoltenVK will dump all SPIRV shaders, compiled MSL shaders, and pipeline shader lists to the given directory.
|
||||||
|
The directory will be non-recursively created if it doesn't already exist.
|
||||||
|
@ -244,6 +244,7 @@ typedef struct {
|
|||||||
VkBool32 shouldMaximizeConcurrentCompilation; /**< MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION */
|
VkBool32 shouldMaximizeConcurrentCompilation; /**< MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION */
|
||||||
float timestampPeriodLowPassAlpha; /**< MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA */
|
float timestampPeriodLowPassAlpha; /**< MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA */
|
||||||
VkBool32 useMetalPrivateAPI; /**< MVK_CONFIG_USE_METAL_PRIVATE_API */
|
VkBool32 useMetalPrivateAPI; /**< MVK_CONFIG_USE_METAL_PRIVATE_API */
|
||||||
|
const char* shaderDumpDir; /**< MVK_CONFIG_SHADER_DUMP_DIR */
|
||||||
} MVKConfiguration;
|
} MVKConfiguration;
|
||||||
|
|
||||||
// Legacy support for renamed struct elements.
|
// Legacy support for renamed struct elements.
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h"
|
#include "MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h"
|
||||||
#endif
|
#endif
|
||||||
#include "mvk_datatypes.hpp"
|
#include "mvk_datatypes.hpp"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#ifndef MVK_USE_CEREAL
|
#ifndef MVK_USE_CEREAL
|
||||||
#define MVK_USE_CEREAL (1)
|
#define MVK_USE_CEREAL (1)
|
||||||
@ -685,6 +686,34 @@ void MVKGraphicsPipeline::initMTLRenderPipelineState(const VkGraphicsPipelineCre
|
|||||||
if (isUsingMetalArgumentBuffers()) { _descriptorBindingUse.resize(_descriptorSetCount); }
|
if (isUsingMetalArgumentBuffers()) { _descriptorBindingUse.resize(_descriptorSetCount); }
|
||||||
if (isUsingPipelineStageMetalArgumentBuffers()) { _mtlArgumentEncoders.resize(_descriptorSetCount); }
|
if (isUsingPipelineStageMetalArgumentBuffers()) { _mtlArgumentEncoders.resize(_descriptorSetCount); }
|
||||||
|
|
||||||
|
const char* dumpDir = getMVKConfig().shaderDumpDir;
|
||||||
|
if (dumpDir && *dumpDir) {
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
char text[1024];
|
||||||
|
char* ptext = text;
|
||||||
|
size_t full_hash = 0;
|
||||||
|
const char* type = pTessCtlSS && pTessEvalSS ? "-tess" : "";
|
||||||
|
auto addShader = [&](const char* type, const VkPipelineShaderStageCreateInfo* ss) {
|
||||||
|
if (!ss) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t hash = reinterpret_cast<MVKShaderModule*>(ss->module)->getKey().codeHash;
|
||||||
|
full_hash = full_hash * 33 ^ hash;
|
||||||
|
ptext = std::min(ptext + snprintf(ptext, std::end(text) - ptext, "%s: %016zx\n", type, hash), std::end(text) - 1);
|
||||||
|
};
|
||||||
|
addShader(" VS", pVertexSS);
|
||||||
|
addShader("TCS", pTessCtlSS);
|
||||||
|
addShader("TES", pTessEvalSS);
|
||||||
|
addShader(" FS", pFragmentSS);
|
||||||
|
mkdir(dumpDir, 0755);
|
||||||
|
snprintf(filename, sizeof(filename), "%s/pipeline%s-%016zx.txt", dumpDir, type, full_hash);
|
||||||
|
FILE* file = fopen(filename, "w");
|
||||||
|
if (file) {
|
||||||
|
fwrite(text, 1, ptext - text, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isTessellationPipeline()) {
|
if (!isTessellationPipeline()) {
|
||||||
MTLRenderPipelineDescriptor* plDesc = newMTLRenderPipelineDescriptor(pCreateInfo, reflectData, pVertexSS, pVertexFB, pFragmentSS, pFragmentFB); // temp retain
|
MTLRenderPipelineDescriptor* plDesc = newMTLRenderPipelineDescriptor(pCreateInfo, reflectData, pVertexSS, pVertexFB, pFragmentSS, pFragmentFB); // temp retain
|
||||||
if (plDesc) {
|
if (plDesc) {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "MVKShaderModule.h"
|
#include "MVKShaderModule.h"
|
||||||
#include "MVKPipeline.h"
|
#include "MVKPipeline.h"
|
||||||
#include "MVKFoundation.h"
|
#include "MVKFoundation.h"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -379,6 +380,42 @@ bool MVKShaderModule::convert(SPIRVToMSLConversionConfiguration* pShaderConfig,
|
|||||||
bool wasConverted = _spvConverter.convert(*pShaderConfig, conversionResult, shouldLogCode, shouldLogCode, shouldLogEstimatedGLSL);
|
bool wasConverted = _spvConverter.convert(*pShaderConfig, conversionResult, shouldLogCode, shouldLogCode, shouldLogEstimatedGLSL);
|
||||||
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.spirvToMSL, startTime);
|
_device->addPerformanceInterval(_device->_performanceStatistics.shaderCompilation.spirvToMSL, startTime);
|
||||||
|
|
||||||
|
const char* dumpDir = getMVKConfig().shaderDumpDir;
|
||||||
|
if (dumpDir && *dumpDir) {
|
||||||
|
char path[PATH_MAX];
|
||||||
|
const char* type;
|
||||||
|
switch (pShaderConfig->options.entryPointStage) {
|
||||||
|
case spv::ExecutionModelVertex: type = "-vs"; break;
|
||||||
|
case spv::ExecutionModelTessellationControl: type = "-tcs"; break;
|
||||||
|
case spv::ExecutionModelTessellationEvaluation: type = "-tes"; break;
|
||||||
|
case spv::ExecutionModelFragment: type = "-fs"; break;
|
||||||
|
case spv::ExecutionModelGeometry: type = "-gs"; break;
|
||||||
|
case spv::ExecutionModelTaskNV: type = "-ts"; break;
|
||||||
|
case spv::ExecutionModelMeshNV: type = "-ms"; break;
|
||||||
|
case spv::ExecutionModelGLCompute: type = "-cs"; break;
|
||||||
|
default: type = ""; break;
|
||||||
|
}
|
||||||
|
mkdir(dumpDir, 0755);
|
||||||
|
snprintf(path, sizeof(path), "%s/shader%s-%016zx.spv", dumpDir, type, _key.codeHash);
|
||||||
|
FILE* file = fopen(path, "wb");
|
||||||
|
if (file) {
|
||||||
|
fwrite(_spvConverter.getSPIRV().data(), sizeof(uint32_t), _spvConverter.getSPIRV().size(), file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
snprintf(path, sizeof(path), "%s/shader%s-%016zx.metal", dumpDir, type, _key.codeHash);
|
||||||
|
file = fopen(path, "wb");
|
||||||
|
if (file) {
|
||||||
|
if (wasConverted) {
|
||||||
|
fwrite(conversionResult.msl.data(), 1, conversionResult.msl.size(), file);
|
||||||
|
fclose(file);
|
||||||
|
} else {
|
||||||
|
fputs("Failed to convert:\n", file);
|
||||||
|
fwrite(conversionResult.resultLog.data(), 1, conversionResult.resultLog.size(), file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (wasConverted) {
|
if (wasConverted) {
|
||||||
if (shouldLogCode) { MVKLogInfo("%s", conversionResult.resultLog.c_str()); }
|
if (shouldLogCode) { MVKLogInfo("%s", conversionResult.resultLog.c_str()); }
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,6 +83,7 @@ MVK_CONFIG_MEMBER(shaderSourceCompressionAlgorithm, MVKConfigCompressionAl
|
|||||||
MVK_CONFIG_MEMBER(shouldMaximizeConcurrentCompilation, VkBool32, SHOULD_MAXIMIZE_CONCURRENT_COMPILATION)
|
MVK_CONFIG_MEMBER(shouldMaximizeConcurrentCompilation, VkBool32, SHOULD_MAXIMIZE_CONCURRENT_COMPILATION)
|
||||||
MVK_CONFIG_MEMBER(timestampPeriodLowPassAlpha, float, TIMESTAMP_PERIOD_LOWPASS_ALPHA)
|
MVK_CONFIG_MEMBER(timestampPeriodLowPassAlpha, float, TIMESTAMP_PERIOD_LOWPASS_ALPHA)
|
||||||
MVK_CONFIG_MEMBER(useMetalPrivateAPI, VkBool32, USE_METAL_PRIVATE_API)
|
MVK_CONFIG_MEMBER(useMetalPrivateAPI, VkBool32, USE_METAL_PRIVATE_API)
|
||||||
|
MVK_CONFIG_MEMBER_STRING(shaderDumpDir, char*, SHADER_DUMP_DIR)
|
||||||
|
|
||||||
#undef MVK_CONFIG_MEMBER
|
#undef MVK_CONFIG_MEMBER
|
||||||
#undef MVK_CONFIG_MEMBER_STRING
|
#undef MVK_CONFIG_MEMBER_STRING
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
/** The number of members of MVKConfiguration that are strings. */
|
/** The number of members of MVKConfiguration that are strings. */
|
||||||
static constexpr uint32_t kMVKConfigurationStringCount = 1;
|
static constexpr uint32_t kMVKConfigurationStringCount = 2;
|
||||||
|
|
||||||
/** Global function to access MoltenVK configuration info. */
|
/** Global function to access MoltenVK configuration info. */
|
||||||
const MVKConfiguration& getGlobalMVKConfig();
|
const MVKConfiguration& getGlobalMVKConfig();
|
||||||
@ -357,5 +357,8 @@ void mvkSetConfig(MVKConfiguration& dstMVKConfig, const MVKConfiguration& srcMVK
|
|||||||
# define MVK_CONFIG_USE_METAL_PRIVATE_API MVK_USE_METAL_PRIVATE_API
|
# define MVK_CONFIG_USE_METAL_PRIVATE_API MVK_USE_METAL_PRIVATE_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef MVK_CONFIG__UNUSED_STRUCT_PADDING
|
/** If set, MVK will dump spirv input, translated msl, and pipelines into the given directory. */
|
||||||
#define MVK_CONFIG__UNUSED_STRUCT_PADDING 0
|
#ifndef MVK_CONFIG_SHADER_DUMP_DIR
|
||||||
|
# define MVK_CONFIG_SHADER_DUMP_DIR ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user