#include "RuntimeSnapshotProvider.h" #include "RuntimeEventDispatcher.h" #include #include RuntimeSnapshotProvider::RuntimeSnapshotProvider(RenderSnapshotBuilder& renderSnapshotBuilder, RuntimeEventDispatcher& runtimeEventDispatcher) : mRenderSnapshotBuilder(renderSnapshotBuilder), mRuntimeEventDispatcher(runtimeEventDispatcher) { } bool RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources(const std::string& layerId, std::vector& passSources, std::string& error) const { try { return mRenderSnapshotBuilder.BuildLayerPassFragmentShaderSources(layerId, passSources, error); } catch (const std::exception& exception) { error = std::string("RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources exception: ") + exception.what(); return false; } catch (...) { error = "RuntimeSnapshotProvider::BuildLayerPassFragmentShaderSources threw a non-standard exception."; return false; } } unsigned RuntimeSnapshotProvider::GetMaxTemporalHistoryFrames() const { return mRenderSnapshotBuilder.GetMaxTemporalHistoryFrames(); } RuntimeSnapshotVersions RuntimeSnapshotProvider::GetVersions() const { return mRenderSnapshotBuilder.GetVersions(); } void RuntimeSnapshotProvider::AdvanceFrame() { mRenderSnapshotBuilder.AdvanceFrame(); } RuntimeRenderStateSnapshot RuntimeSnapshotProvider::PublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight) const { PublishRenderSnapshotPublishRequested(outputWidth, outputHeight, "publish-render-state-snapshot"); for (;;) { const RuntimeSnapshotVersions versionsBefore = GetVersions(); RuntimeRenderStateSnapshot publishedSnapshot; if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, publishedSnapshot)) { PublishRenderSnapshotPublished(publishedSnapshot); return publishedSnapshot; } RuntimeRenderStateSnapshot snapshot; snapshot.outputWidth = outputWidth; snapshot.outputHeight = outputHeight; mRenderSnapshotBuilder.BuildLayerRenderStates(outputWidth, outputHeight, snapshot.states); const RuntimeSnapshotVersions versionsAfter = GetVersions(); if (versionsBefore.renderStateVersion == versionsAfter.renderStateVersion && versionsBefore.parameterStateVersion == versionsAfter.parameterStateVersion) { snapshot.versions = versionsAfter; StorePublishedRenderStateSnapshot(snapshot); PublishRenderSnapshotPublished(snapshot); return snapshot; } } } bool RuntimeSnapshotProvider::TryPublishRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, RuntimeRenderStateSnapshot& snapshot) const { PublishRenderSnapshotPublishRequested(outputWidth, outputHeight, "try-publish-render-state-snapshot"); const RuntimeSnapshotVersions versionsBefore = GetVersions(); if (TryGetPublishedRenderStateSnapshot(outputWidth, outputHeight, versionsBefore, snapshot)) { PublishRenderSnapshotPublished(snapshot); return true; } std::vector states; if (!mRenderSnapshotBuilder.TryBuildLayerRenderStates(outputWidth, outputHeight, states)) return false; const RuntimeSnapshotVersions versionsAfter = GetVersions(); if (versionsBefore.renderStateVersion != versionsAfter.renderStateVersion || versionsBefore.parameterStateVersion != versionsAfter.parameterStateVersion) { return false; } snapshot.outputWidth = outputWidth; snapshot.outputHeight = outputHeight; snapshot.versions = versionsAfter; snapshot.states = std::move(states); StorePublishedRenderStateSnapshot(snapshot); PublishRenderSnapshotPublished(snapshot); return true; } bool RuntimeSnapshotProvider::TryRefreshPublishedSnapshotParameters(RuntimeRenderStateSnapshot& snapshot) const { const uint64_t expectedRenderStateVersion = snapshot.versions.renderStateVersion; if (!mRenderSnapshotBuilder.TryRefreshLayerParameters(snapshot.states)) return false; const RuntimeSnapshotVersions versions = GetVersions(); if (versions.renderStateVersion != expectedRenderStateVersion) return false; snapshot.versions = versions; StorePublishedRenderStateSnapshot(snapshot); PublishRenderSnapshotPublished(snapshot); return true; } void RuntimeSnapshotProvider::RefreshDynamicRenderStateFields(std::vector& states) const { mRenderSnapshotBuilder.RefreshDynamicRenderStateFields(states); } bool RuntimeSnapshotProvider::TryGetPublishedRenderStateSnapshot(unsigned outputWidth, unsigned outputHeight, const RuntimeSnapshotVersions& versions, RuntimeRenderStateSnapshot& snapshot) const { std::lock_guard lock(mPublishedSnapshotMutex); if (!mHasPublishedRenderStateSnapshot || !SnapshotMatches(mPublishedRenderStateSnapshot, outputWidth, outputHeight, versions)) { return false; } snapshot = mPublishedRenderStateSnapshot; return true; } void RuntimeSnapshotProvider::StorePublishedRenderStateSnapshot(const RuntimeRenderStateSnapshot& snapshot) const { std::lock_guard lock(mPublishedSnapshotMutex); mPublishedRenderStateSnapshot = snapshot; mHasPublishedRenderStateSnapshot = true; } bool RuntimeSnapshotProvider::SnapshotMatches(const RuntimeRenderStateSnapshot& snapshot, unsigned outputWidth, unsigned outputHeight, const RuntimeSnapshotVersions& versions) { return snapshot.outputWidth == outputWidth && snapshot.outputHeight == outputHeight && snapshot.versions.renderStateVersion == versions.renderStateVersion && snapshot.versions.parameterStateVersion == versions.parameterStateVersion; } void RuntimeSnapshotProvider::PublishRenderSnapshotPublishRequested(unsigned outputWidth, unsigned outputHeight, const std::string& reason) const { try { RenderSnapshotPublishRequestedEvent event; event.outputWidth = outputWidth; event.outputHeight = outputHeight; event.reason = reason; if (!mRuntimeEventDispatcher.PublishPayload(event, "RuntimeSnapshotProvider")) OutputDebugStringA("RenderSnapshotPublishRequested event publish failed.\n"); } catch (...) { OutputDebugStringA("RenderSnapshotPublishRequested event publish threw.\n"); } } void RuntimeSnapshotProvider::PublishRenderSnapshotPublished(const RuntimeRenderStateSnapshot& snapshot) const { try { RenderSnapshotPublishedEvent event; event.snapshotVersion = snapshot.versions.renderStateVersion; event.structureVersion = snapshot.versions.renderStateVersion; event.parameterVersion = snapshot.versions.parameterStateVersion; event.outputWidth = snapshot.outputWidth; event.outputHeight = snapshot.outputHeight; event.layerCount = snapshot.states.size(); if (!mRuntimeEventDispatcher.PublishPayload(event, "RuntimeSnapshotProvider")) OutputDebugStringA("RenderSnapshotPublished event publish failed.\n"); } catch (...) { OutputDebugStringA("RenderSnapshotPublished event publish threw.\n"); } }