Skip to content

Commit

Permalink
Merge pull request #2210 from etang-cw/ShaderDump
Browse files Browse the repository at this point in the history
Add option to dump shaders
  • Loading branch information
billhollings authored Apr 19, 2024
2 parents d0f066a + 6a6fa2c commit 756f00a
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 3 deletions.
11 changes: 11 additions & 0 deletions Docs/MoltenVK_Configuration_Parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

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.
1 change: 1 addition & 0 deletions MoltenVK/MoltenVK/API/mvk_private_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ typedef struct {
VkBool32 shouldMaximizeConcurrentCompilation; /**< MVK_CONFIG_SHOULD_MAXIMIZE_CONCURRENT_COMPILATION */
float timestampPeriodLowPassAlpha; /**< MVK_CONFIG_TIMESTAMP_PERIOD_LOWPASS_ALPHA */
VkBool32 useMetalPrivateAPI; /**< MVK_CONFIG_USE_METAL_PRIVATE_API */
const char* shaderDumpDir; /**< MVK_CONFIG_SHADER_DUMP_DIR */
} MVKConfiguration;

// Legacy support for renamed struct elements.
Expand Down
29 changes: 29 additions & 0 deletions MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "MTLRenderPipelineColorAttachmentDescriptor+MoltenVK.h"
#endif
#include "mvk_datatypes.hpp"
#include <sys/stat.h>

#ifndef MVK_USE_CEREAL
#define MVK_USE_CEREAL (1)
Expand Down Expand Up @@ -685,6 +686,34 @@ static MVKRenderStateType getRenderStateType(VkDynamicState vkDynamicState) {
if (isUsingMetalArgumentBuffers()) { _descriptorBindingUse.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()) {
MTLRenderPipelineDescriptor* plDesc = newMTLRenderPipelineDescriptor(pCreateInfo, reflectData, pVertexSS, pVertexFB, pFragmentSS, pFragmentFB); // temp retain
if (plDesc) {
Expand Down
37 changes: 37 additions & 0 deletions MoltenVK/MoltenVK/GPUObjects/MVKShaderModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "MVKShaderModule.h"
#include "MVKPipeline.h"
#include "MVKFoundation.h"
#include <sys/stat.h>

using namespace std;

Expand Down Expand Up @@ -379,6 +380,42 @@ static uint32_t getWorkgroupDimensionSize(const SPIRVWorkgroupSizeDimension& wgD
bool wasConverted = _spvConverter.convert(*pShaderConfig, conversionResult, shouldLogCode, shouldLogCode, shouldLogEstimatedGLSL);
_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 (shouldLogCode) { MVKLogInfo("%s", conversionResult.resultLog.c_str()); }
} else {
Expand Down
1 change: 1 addition & 0 deletions MoltenVK/MoltenVK/Utility/MVKConfigMembers.def
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ MVK_CONFIG_MEMBER(shaderSourceCompressionAlgorithm, MVKConfigCompressionAl
MVK_CONFIG_MEMBER(shouldMaximizeConcurrentCompilation, VkBool32, SHOULD_MAXIMIZE_CONCURRENT_COMPILATION)
MVK_CONFIG_MEMBER(timestampPeriodLowPassAlpha, float, TIMESTAMP_PERIOD_LOWPASS_ALPHA)
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_STRING
Expand Down
9 changes: 6 additions & 3 deletions MoltenVK/MoltenVK/Utility/MVKEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
#ifdef __cplusplus

/** 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. */
const MVKConfiguration& getGlobalMVKConfig();
Expand Down Expand Up @@ -357,5 +357,8 @@ void mvkSetConfig(MVKConfiguration& dstMVKConfig, const MVKConfiguration& srcMVK
# define MVK_CONFIG_USE_METAL_PRIVATE_API MVK_USE_METAL_PRIVATE_API
#endif

#undef MVK_CONFIG__UNUSED_STRUCT_PADDING
#define MVK_CONFIG__UNUSED_STRUCT_PADDING 0
/** If set, MVK will dump spirv input, translated msl, and pipelines into the given directory. */
#ifndef MVK_CONFIG_SHADER_DUMP_DIR
# define MVK_CONFIG_SHADER_DUMP_DIR ""
#endif

0 comments on commit 756f00a

Please sign in to comment.