mirror of
https://github.com/rt64/rt64.git
synced 2024-12-26 21:18:31 +00:00
Deprecate and remove offline shader cache.
This commit is contained in:
parent
6853ac4c35
commit
5749e90548
@ -395,10 +395,6 @@ namespace RT64 {
|
||||
state->updateScreen(core.decodeVI(), false);
|
||||
}
|
||||
|
||||
bool Application::loadOfflineShaderCache(std::istream &stream) {
|
||||
return rasterShaderCache->loadOfflineList(stream);
|
||||
}
|
||||
|
||||
void Application::destroyShaderCache() {
|
||||
workloadQueue->waitForWorkloadId(state->workloadId);
|
||||
presentQueue->waitForPresentId(state->presentId);
|
||||
@ -434,7 +430,6 @@ namespace RT64 {
|
||||
|
||||
// Wait for all pipelines of the ubershader to be ready again.
|
||||
rasterShaderCache->shaderUber->waitForPipelineCreation();
|
||||
rasterShaderCache->resetOfflineList();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -157,7 +157,6 @@ namespace RT64 {
|
||||
SetupResult setup(uint32_t threadId);
|
||||
void processDisplayLists(uint8_t *memory, uint32_t dlStartAddress, uint32_t dlEndAddress, bool isHLE);
|
||||
void updateScreen();
|
||||
bool loadOfflineShaderCache(std::istream &stream);
|
||||
void destroyShaderCache();
|
||||
void updateMultisampling();
|
||||
void end();
|
||||
|
@ -2127,32 +2127,7 @@ namespace RT64 {
|
||||
ImGui::Indent();
|
||||
enhanceConfigChanged = ImGui::Checkbox("Scale LOD", &enhancementConfig.textureLOD.scale) || enhanceConfigChanged;
|
||||
ImGui::Unindent();
|
||||
ImGui::Text("Shader cache");
|
||||
ImGui::Indent();
|
||||
bool dumpingDisabled = (userConfig.graphicsAPI != UserConfiguration::GraphicsAPI::D3D12);
|
||||
ImGui::BeginDisabled(dumpingDisabled);
|
||||
bool offlineDumperActive = ext.rasterShaderCache->isOfflineDumperActive();
|
||||
bool offlineDumperToggled = ImGui::Button(offlineDumperActive ? "Stop dumping##shaderCache" : "Start dumping##shaderCache");
|
||||
if (offlineDumperToggled) {
|
||||
if (offlineDumperActive) {
|
||||
ext.rasterShaderCache->stopOfflineDumper();
|
||||
}
|
||||
else {
|
||||
std::filesystem::path savePath = FileDialog::getSaveFilename({ FileFilter("BIN Files", "bin") });
|
||||
if (!savePath.empty()) {
|
||||
ext.rasterShaderCache->startOfflineDumper(savePath);
|
||||
shaderCacheChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (dumpingDisabled) {
|
||||
ImGui::Text("Shader cache dumping is only available in D3D12.");
|
||||
}
|
||||
|
||||
ImGui::Unindent();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
@ -2434,10 +2409,7 @@ namespace RT64 {
|
||||
}
|
||||
# endif
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Text("Offline Shaders: %zu", ext.rasterShaderCache->offlineList.entries.size());
|
||||
ImGui::Text("Specialized Shaders: %u", ext.rasterShaderCache->shaderCount());
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
bool ubershadersOnly = ext.workloadQueue->ubershadersOnly;
|
||||
|
@ -76,7 +76,7 @@ namespace RT64 {
|
||||
// RasterShader
|
||||
|
||||
RasterShader::RasterShader(RenderDevice *device, const ShaderDescription &desc, const RenderPipelineLayout *pipelineLayout, RenderShaderFormat shaderFormat, const RenderMultisampling &multisampling,
|
||||
const ShaderCompiler *shaderCompiler, const OptimizerCacheSPIRV *optimizerCacheSPIRV, std::vector<uint8_t> *vsBytes, std::vector<uint8_t> *psBytes, bool useBytes)
|
||||
const ShaderCompiler *shaderCompiler, const OptimizerCacheSPIRV *optimizerCacheSPIRV)
|
||||
{
|
||||
assert(device != nullptr);
|
||||
|
||||
@ -138,11 +138,6 @@ namespace RT64 {
|
||||
}
|
||||
else {
|
||||
# if defined(_WIN32)
|
||||
if (useBytes) {
|
||||
vertexShader = device->createShader(vsBytes->data(), vsBytes->size(), "VSMain", shaderFormat);
|
||||
pixelShader = device->createShader(psBytes->data(), psBytes->size(), "PSMain", shaderFormat);
|
||||
}
|
||||
else {
|
||||
RasterShaderText shaderText = generateShaderText(desc, useMSAA);
|
||||
|
||||
// Compile both shaders from text with the constants hard-coded in.
|
||||
@ -171,15 +166,6 @@ namespace RT64 {
|
||||
vertexShader = device->createShader(blobVS->GetBufferPointer(), blobVS->GetBufferSize(), "VSMain", shaderFormat);
|
||||
pixelShader = device->createShader(blobPS->GetBufferPointer(), blobPS->GetBufferSize(), "PSMain", shaderFormat);
|
||||
|
||||
// Store the bytes in the auxiliary buffers if specified.
|
||||
if (vsBytes != nullptr) {
|
||||
*vsBytes = std::vector<uint8_t>((const uint8_t *)(blobVS->GetBufferPointer()), (const uint8_t *)(blobVS->GetBufferPointer()) + blobVS->GetBufferSize());
|
||||
}
|
||||
|
||||
if (psBytes != nullptr) {
|
||||
*psBytes = std::vector<uint8_t>((const uint8_t *)(blobPS->GetBufferPointer()), (const uint8_t *)(blobPS->GetBufferPointer()) + blobPS->GetBufferSize());
|
||||
}
|
||||
|
||||
// Blobs can be discarded once the shaders are created.
|
||||
blobVSLibraries[0]->Release();
|
||||
blobVSLibraries[1]->Release();
|
||||
@ -187,7 +173,6 @@ namespace RT64 {
|
||||
blobPSLibraries[1]->Release();
|
||||
blobPS->Release();
|
||||
blobVS->Release();
|
||||
}
|
||||
# else
|
||||
assert(false && "This platform does not support runtime shader compilation.");
|
||||
# endif
|
||||
|
@ -64,7 +64,7 @@ namespace RT64 {
|
||||
std::unique_ptr<RenderPipeline> pipeline;
|
||||
|
||||
RasterShader(RenderDevice *device, const ShaderDescription &desc, const RenderPipelineLayout *pipelineLayout, RenderShaderFormat shaderFormat, const RenderMultisampling &multisampling,
|
||||
const ShaderCompiler *shaderCompiler, const OptimizerCacheSPIRV *optimizerCacheSPIRV, std::vector<uint8_t> *vsBytes = nullptr, std::vector<uint8_t> *psBytes = nullptr, bool useBytes = false);
|
||||
const ShaderCompiler *shaderCompiler, const OptimizerCacheSPIRV *optimizerCacheSPIRV);
|
||||
|
||||
~RasterShader();
|
||||
static RasterShaderText generateShaderText(const ShaderDescription &desc, bool multisampling);
|
||||
|
@ -9,117 +9,6 @@
|
||||
#define ENABLE_OPTIMIZED_SHADER_GENERATION
|
||||
|
||||
namespace RT64 {
|
||||
// RasterShaderCache::OfflineList
|
||||
|
||||
static const uint32_t OfflineMagic = 0x43535452;
|
||||
static const uint32_t OfflineVersion = 3;
|
||||
|
||||
RasterShaderCache::OfflineList::OfflineList() {
|
||||
entryIterator = entries.end();
|
||||
}
|
||||
|
||||
bool RasterShaderCache::OfflineList::load(std::istream &stream) {
|
||||
Entry entry;
|
||||
while (!stream.eof()) {
|
||||
uint32_t magic = 0;
|
||||
uint32_t version = 0;
|
||||
uint64_t vsHash = 0;
|
||||
uint64_t psHash = 0;
|
||||
stream.read(reinterpret_cast<char *>(&magic), sizeof(uint32_t));
|
||||
stream.read(reinterpret_cast<char *>(&version), sizeof(uint32_t));
|
||||
stream.read(reinterpret_cast<char *>(&vsHash), sizeof(uint64_t));
|
||||
stream.read(reinterpret_cast<char *>(&psHash), sizeof(uint64_t));
|
||||
if (stream.eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((magic != OfflineMagic) || (version != OfflineVersion) || (vsHash != RasterShaderUber::RasterVSLibraryHash) || (psHash != RasterShaderUber::RasterPSLibraryHash)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stream.read(reinterpret_cast<char *>(&entry.shaderDesc), sizeof(ShaderDescription));
|
||||
|
||||
uint32_t vsDxilSize = 0;
|
||||
stream.read(reinterpret_cast<char *>(&vsDxilSize), sizeof(uint32_t));
|
||||
entry.vsDxilBytes.resize(vsDxilSize);
|
||||
stream.read(reinterpret_cast<char *>(entry.vsDxilBytes.data()), vsDxilSize);
|
||||
if (stream.bad() || entry.vsDxilBytes.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t psDxilSize = 0;
|
||||
stream.read(reinterpret_cast<char *>(&psDxilSize), sizeof(uint32_t));
|
||||
entry.psDxilBytes.resize(psDxilSize);
|
||||
stream.read(reinterpret_cast<char *>(entry.psDxilBytes.data()), psDxilSize);
|
||||
if (stream.bad() || entry.psDxilBytes.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
entries.emplace_back(entry);
|
||||
}
|
||||
|
||||
entryIterator = entries.begin();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RasterShaderCache::OfflineList::reset() {
|
||||
if (!entries.empty()) {
|
||||
entryIterator = entries.begin();
|
||||
}
|
||||
}
|
||||
|
||||
void RasterShaderCache::OfflineList::step(Entry &entry) {
|
||||
if (entryIterator != entries.end()) {
|
||||
entry = *entryIterator;
|
||||
entryIterator++;
|
||||
}
|
||||
}
|
||||
|
||||
bool RasterShaderCache::OfflineList::atEnd() const {
|
||||
if (!entries.empty()) {
|
||||
return entryIterator == entries.end();
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// RasterShaderCache::OfflineDumper
|
||||
|
||||
bool RasterShaderCache::OfflineDumper::startDumping(const std::filesystem::path &path) {
|
||||
assert(!dumpStream.is_open());
|
||||
dumpStream.open(path, std::ios::binary);
|
||||
return dumpStream.is_open();
|
||||
}
|
||||
|
||||
bool RasterShaderCache::OfflineDumper::stepDumping(const ShaderDescription &shaderDesc, const std::vector<uint8_t> &vsDxilBytes, const std::vector<uint8_t> &psDxilBytes) {
|
||||
assert(!vsDxilBytes.empty());
|
||||
assert(!psDxilBytes.empty());
|
||||
uint32_t vsDxilSize = uint32_t(vsDxilBytes.size());
|
||||
uint32_t psDxilSize = uint32_t(psDxilBytes.size());
|
||||
dumpStream.write(reinterpret_cast<const char *>(&OfflineMagic), sizeof(uint32_t));
|
||||
dumpStream.write(reinterpret_cast<const char *>(&OfflineVersion), sizeof(uint32_t));
|
||||
dumpStream.write(reinterpret_cast<const char *>(&RasterShaderUber::RasterVSLibraryHash), sizeof(uint64_t));
|
||||
dumpStream.write(reinterpret_cast<const char *>(&RasterShaderUber::RasterPSLibraryHash), sizeof(uint64_t));
|
||||
dumpStream.write(reinterpret_cast<const char *>(&shaderDesc), sizeof(ShaderDescription));
|
||||
dumpStream.write(reinterpret_cast<const char *>(&vsDxilSize), sizeof(uint32_t));
|
||||
dumpStream.write(reinterpret_cast<const char *>(vsDxilBytes.data()), vsDxilSize);
|
||||
dumpStream.write(reinterpret_cast<const char *>(&psDxilSize), sizeof(uint32_t));
|
||||
dumpStream.write(reinterpret_cast<const char *>(psDxilBytes.data()), psDxilSize);
|
||||
return dumpStream.bad();
|
||||
}
|
||||
|
||||
bool RasterShaderCache::OfflineDumper::stopDumping() {
|
||||
assert(dumpStream.is_open());
|
||||
dumpStream.close();
|
||||
return dumpStream.bad();
|
||||
}
|
||||
|
||||
bool RasterShaderCache::OfflineDumper::isDumping() const {
|
||||
return dumpStream.is_open();
|
||||
}
|
||||
|
||||
// RasterShaderCache::CompilationThread
|
||||
|
||||
RasterShaderCache::CompilationThread::CompilationThread(RasterShaderCache *shaderCache) {
|
||||
@ -146,20 +35,16 @@ namespace RT64 {
|
||||
|
||||
threadRunning = true;
|
||||
|
||||
OfflineList::Entry offlineListEntry;
|
||||
std::vector<uint8_t> dumperVsBytes;
|
||||
std::vector<uint8_t> dumperPsBytes;
|
||||
while (threadRunning) {
|
||||
ShaderDescription shaderDesc;
|
||||
bool fromPriorityQueue = false;
|
||||
bool fromOfflineList = false;
|
||||
|
||||
// Check the top of the queue or wait if it's empty.
|
||||
{
|
||||
std::unique_lock<std::mutex> queueLock(shaderCache->descQueueMutex);
|
||||
shaderCache->descQueueActiveCount--;
|
||||
shaderCache->descQueueChanged.wait(queueLock, [this]() {
|
||||
return !threadRunning || !shaderCache->descQueue.empty() || !shaderCache->offlineList.atEnd();
|
||||
return !threadRunning || !shaderCache->descQueue.empty();
|
||||
});
|
||||
|
||||
shaderCache->descQueueActiveCount++;
|
||||
@ -168,62 +53,14 @@ namespace RT64 {
|
||||
shaderCache->descQueue.pop();
|
||||
fromPriorityQueue = true;
|
||||
}
|
||||
else if (!shaderCache->offlineList.atEnd()) {
|
||||
std::unique_lock<std::mutex> queueLock(shaderCache->submissionMutex);
|
||||
while (!shaderCache->offlineList.atEnd() && !fromOfflineList) {
|
||||
shaderCache->offlineList.step(offlineListEntry);
|
||||
|
||||
// Make sure the hash hasn't been submitted yet by the game. If it hasn't, mark it as such and use this entry of the list.
|
||||
// Also make sure the internal color format used by the shader is compatible.
|
||||
uint64_t shaderHash = offlineListEntry.shaderDesc.hash();
|
||||
const bool matchesColorFormat = (offlineListEntry.shaderDesc.flags.usesHDR == shaderCache->usesHDR);
|
||||
const bool hashMissing = (shaderCache->shaderHashes.find(shaderHash) == shaderCache->shaderHashes.end());
|
||||
if (matchesColorFormat && hashMissing) {
|
||||
shaderDesc = offlineListEntry.shaderDesc;
|
||||
shaderCache->shaderHashes[shaderHash] = true;
|
||||
fromOfflineList = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compile the shader at the top of the queue.
|
||||
if (fromPriorityQueue || fromOfflineList) {
|
||||
// Check if the shader dumper is active. Specify the shader's bytes should be stored in the thread's vectors.
|
||||
std::vector<uint8_t> *shaderVsBytes = nullptr;
|
||||
std::vector<uint8_t> *shaderPsBytes = nullptr;
|
||||
bool useShaderBytes = false;
|
||||
if (fromPriorityQueue) {
|
||||
const std::unique_lock<std::mutex> lock(shaderCache->offlineDumperMutex);
|
||||
if (shaderCache->offlineDumper.isDumping()) {
|
||||
shaderVsBytes = &dumperVsBytes;
|
||||
shaderPsBytes = &dumperPsBytes;
|
||||
}
|
||||
}
|
||||
else {
|
||||
shaderVsBytes = &offlineListEntry.vsDxilBytes;
|
||||
shaderPsBytes = &offlineListEntry.psDxilBytes;
|
||||
useShaderBytes = true;
|
||||
}
|
||||
|
||||
assert((shaderCache->shaderUber != nullptr) && "Ubershader should've been created by the time a new shader is submitted to the cache.");
|
||||
const RenderPipelineLayout *uberPipelineLayout = shaderCache->shaderUber->pipelineLayout.get();
|
||||
const RenderMultisampling multisampling = shaderCache->multisampling;
|
||||
std::unique_ptr<RasterShader> newShader = std::make_unique<RasterShader>(shaderCache->device, shaderDesc, uberPipelineLayout, shaderCache->shaderFormat, multisampling, shaderCache->shaderCompiler.get(), &shaderCache->optimizerCacheSPIRV, shaderVsBytes, shaderPsBytes, useShaderBytes);
|
||||
|
||||
// Dump the bytes of the shader if requested.
|
||||
if (!useShaderBytes && (shaderVsBytes != nullptr) && (shaderPsBytes != nullptr)) {
|
||||
const std::unique_lock<std::mutex> lock(shaderCache->offlineDumperMutex);
|
||||
if (shaderCache->offlineDumper.isDumping()) {
|
||||
shaderCache->offlineDumper.stepDumping(shaderDesc, dumperVsBytes, dumperPsBytes);
|
||||
|
||||
// Toggle the use of HDR and compile another shader.
|
||||
ShaderDescription shaderDescAlt = shaderDesc;
|
||||
shaderDescAlt.flags.usesHDR = (shaderDescAlt.flags.usesHDR == 0);
|
||||
std::unique_ptr<RasterShader> altShader = std::make_unique<RasterShader>(shaderCache->device, shaderDescAlt, uberPipelineLayout, shaderCache->shaderFormat, multisampling, shaderCache->shaderCompiler.get(), &shaderCache->optimizerCacheSPIRV, shaderVsBytes, shaderPsBytes, useShaderBytes);
|
||||
shaderCache->offlineDumper.stepDumping(shaderDescAlt, dumperVsBytes, dumperPsBytes);
|
||||
}
|
||||
}
|
||||
std::unique_ptr<RasterShader> newShader = std::make_unique<RasterShader>(shaderCache->device, shaderDesc, uberPipelineLayout, shaderCache->shaderFormat, multisampling, shaderCache->shaderCompiler.get(), &shaderCache->optimizerCacheSPIRV);
|
||||
|
||||
{
|
||||
const std::unique_lock<std::mutex> lock(shaderCache->GPUShadersMutex);
|
||||
@ -338,42 +175,6 @@ namespace RT64 {
|
||||
return shaderUber.get();
|
||||
}
|
||||
|
||||
bool RasterShaderCache::isOfflineDumperActive() {
|
||||
const std::unique_lock<std::mutex> lock(offlineDumperMutex);
|
||||
return offlineDumper.isDumping();
|
||||
}
|
||||
|
||||
bool RasterShaderCache::startOfflineDumper(const std::filesystem::path &path) {
|
||||
const std::unique_lock<std::mutex> lock(offlineDumperMutex);
|
||||
return offlineDumper.startDumping(path);
|
||||
}
|
||||
|
||||
bool RasterShaderCache::stopOfflineDumper() {
|
||||
const std::unique_lock<std::mutex> lock(offlineDumperMutex);
|
||||
return offlineDumper.stopDumping();
|
||||
}
|
||||
|
||||
bool RasterShaderCache::loadOfflineList(std::istream &stream) {
|
||||
bool result = false;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> queueLock(descQueueMutex);
|
||||
result = offlineList.load(stream);
|
||||
}
|
||||
|
||||
descQueueChanged.notify_all();
|
||||
return result;
|
||||
}
|
||||
|
||||
void RasterShaderCache::resetOfflineList() {
|
||||
{
|
||||
std::unique_lock<std::mutex> queueLock(descQueueMutex);
|
||||
offlineList.reset();
|
||||
}
|
||||
|
||||
descQueueChanged.notify_all();
|
||||
}
|
||||
|
||||
uint32_t RasterShaderCache::shaderCount() {
|
||||
std::unique_lock<std::mutex> lock(GPUShadersMutex);
|
||||
return GPUShaders.size();
|
||||
|
@ -17,32 +17,6 @@
|
||||
|
||||
namespace RT64 {
|
||||
struct RasterShaderCache {
|
||||
struct OfflineList {
|
||||
struct Entry {
|
||||
ShaderDescription shaderDesc;
|
||||
std::vector<uint8_t> vsDxilBytes;
|
||||
std::vector<uint8_t> psDxilBytes;
|
||||
};
|
||||
|
||||
std::list<Entry> entries;
|
||||
std::list<Entry>::iterator entryIterator;
|
||||
|
||||
OfflineList();
|
||||
bool load(std::istream &stream);
|
||||
void reset();
|
||||
void step(Entry &entry);
|
||||
bool atEnd() const;
|
||||
};
|
||||
|
||||
struct OfflineDumper {
|
||||
std::ofstream dumpStream;
|
||||
|
||||
bool startDumping(const std::filesystem::path &path);
|
||||
bool stepDumping(const ShaderDescription &shaderDesc, const std::vector<uint8_t> &vsDxilBytes, const std::vector<uint8_t> &psDxilBytes);
|
||||
bool stopDumping();
|
||||
bool isDumping() const;
|
||||
};
|
||||
|
||||
struct CompilationThread {
|
||||
RasterShaderCache *shaderCache;
|
||||
std::unique_ptr<std::thread> thread;
|
||||
@ -70,9 +44,6 @@ namespace RT64 {
|
||||
RenderShaderFormat shaderFormat;
|
||||
std::unique_ptr<ShaderCompiler> shaderCompiler;
|
||||
RenderMultisampling multisampling;
|
||||
OfflineList offlineList;
|
||||
OfflineDumper offlineDumper;
|
||||
std::mutex offlineDumperMutex;
|
||||
bool usesHDR = false;
|
||||
|
||||
RasterShaderCache(uint32_t threadCount, uint32_t ubershaderThreadCount);
|
||||
@ -83,11 +54,6 @@ namespace RT64 {
|
||||
void destroyAll();
|
||||
RasterShader *getGPUShader(const ShaderDescription &desc);
|
||||
RasterShaderUber *getGPUShaderUber() const;
|
||||
bool isOfflineDumperActive();
|
||||
bool startOfflineDumper(const std::filesystem::path &path);
|
||||
bool stopOfflineDumper();
|
||||
bool loadOfflineList(std::istream &stream);
|
||||
void resetOfflineList();
|
||||
uint32_t shaderCount();
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user