Shader test past
This commit is contained in:
@@ -5,10 +5,13 @@
|
||||
#include "../platform/HiddenGlWindow.h"
|
||||
#include "Bgra8ReadbackPipeline.h"
|
||||
#include "GLExtensions.h"
|
||||
#include "RuntimeShaderRenderer.h"
|
||||
#include "SimpleMotionRenderer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <windows.h>
|
||||
|
||||
RenderThread::RenderThread(SystemFrameExchange& frameExchange, Config config) :
|
||||
mFrameExchange(frameExchange),
|
||||
@@ -83,12 +86,14 @@ void RenderThread::ThreadMain()
|
||||
}
|
||||
|
||||
SimpleMotionRenderer renderer;
|
||||
RuntimeShaderRenderer runtimeShaderRenderer;
|
||||
Bgra8ReadbackPipeline readback;
|
||||
if (!renderer.InitializeGl(mConfig.width, mConfig.height) || !readback.Initialize(mConfig.width, mConfig.height, mConfig.pboDepth))
|
||||
{
|
||||
SignalStartupFailure("Render pipeline initialization failed.");
|
||||
return;
|
||||
}
|
||||
mSlangCompiler.StartHappyAccidentBuild();
|
||||
|
||||
RenderCadenceClock clock(mConfig.frameDurationMilliseconds);
|
||||
uint64_t frameIndex = 0;
|
||||
@@ -114,7 +119,13 @@ void RenderThread::ThreadMain()
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!readback.RenderAndQueue(frameIndex, [&renderer](uint64_t index) { renderer.RenderFrame(index); }))
|
||||
TryCommitReadyRuntimeShader(runtimeShaderRenderer);
|
||||
if (!readback.RenderAndQueue(frameIndex, [this, &renderer, &runtimeShaderRenderer](uint64_t index) {
|
||||
if (runtimeShaderRenderer.HasProgram())
|
||||
runtimeShaderRenderer.RenderFrame(index, mConfig.width, mConfig.height);
|
||||
else
|
||||
renderer.RenderFrame(index);
|
||||
}))
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
++mMetrics.pboQueueMisses;
|
||||
@@ -143,7 +154,9 @@ void RenderThread::ThreadMain()
|
||||
}
|
||||
|
||||
readback.Shutdown();
|
||||
runtimeShaderRenderer.ShutdownGl();
|
||||
renderer.ShutdownGl();
|
||||
mSlangCompiler.Stop();
|
||||
window.ClearCurrent();
|
||||
mRunning.store(false, std::memory_order_release);
|
||||
}
|
||||
@@ -179,3 +192,34 @@ void RenderThread::CountAcquireMiss()
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
++mMetrics.acquireMisses;
|
||||
}
|
||||
|
||||
void RenderThread::TryCommitReadyRuntimeShader(RuntimeShaderRenderer& runtimeShaderRenderer)
|
||||
{
|
||||
RuntimeSlangShaderBuild build;
|
||||
if (!mSlangCompiler.TryConsume(build))
|
||||
return;
|
||||
|
||||
if (!build.succeeded)
|
||||
{
|
||||
std::cout << "Runtime Slang build failed: " << build.message << "\n";
|
||||
OutputDebugStringA(("Runtime Slang build failed: " + build.message + "\n").c_str());
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
++mMetrics.shaderBuildFailures;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string commitError;
|
||||
if (!runtimeShaderRenderer.CommitFragmentShader(build.fragmentShaderSource, commitError))
|
||||
{
|
||||
std::cout << "Runtime shader GL commit failed: " << commitError << "\n";
|
||||
OutputDebugStringA(("Runtime shader GL commit failed: " + commitError + "\n").c_str());
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
++mMetrics.shaderBuildFailures;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "Runtime shader committed: " << build.shaderId << ". " << build.message << "\n";
|
||||
OutputDebugStringA(("Runtime shader committed: " + build.shaderId + ". " + build.message + "\n").c_str());
|
||||
std::lock_guard<std::mutex> lock(mMetricsMutex);
|
||||
++mMetrics.shaderBuildsCommitted;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "RenderCadenceClock.h"
|
||||
#include "../runtime/RuntimeSlangShaderCompiler.h"
|
||||
#include "RuntimeShaderRenderer.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
@@ -31,6 +33,8 @@ public:
|
||||
uint64_t pboQueueMisses = 0;
|
||||
uint64_t clockOverruns = 0;
|
||||
uint64_t skippedFrames = 0;
|
||||
uint64_t shaderBuildsCommitted = 0;
|
||||
uint64_t shaderBuildFailures = 0;
|
||||
};
|
||||
|
||||
RenderThread(SystemFrameExchange& frameExchange, Config config);
|
||||
@@ -51,9 +55,11 @@ private:
|
||||
void CountRendered();
|
||||
void CountCompleted();
|
||||
void CountAcquireMiss();
|
||||
void TryCommitReadyRuntimeShader(RuntimeShaderRenderer& runtimeShaderRenderer);
|
||||
|
||||
SystemFrameExchange& mFrameExchange;
|
||||
Config mConfig;
|
||||
RuntimeSlangShaderCompiler mSlangCompiler;
|
||||
std::thread mThread;
|
||||
std::atomic<bool> mStopping{ false };
|
||||
std::atomic<bool> mRunning{ false };
|
||||
|
||||
214
apps/RenderCadenceCompositor/render/RuntimeShaderRenderer.cpp
Normal file
214
apps/RenderCadenceCompositor/render/RuntimeShaderRenderer.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
#include "RuntimeShaderRenderer.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr GLuint kGlobalParamsBindingPoint = 0;
|
||||
|
||||
const char* kVertexShaderSource = R"GLSL(
|
||||
#version 430 core
|
||||
out vec2 vTexCoord;
|
||||
void main()
|
||||
{
|
||||
vec2 positions[3] = vec2[3](
|
||||
vec2(-1.0, -1.0),
|
||||
vec2( 3.0, -1.0),
|
||||
vec2(-1.0, 3.0));
|
||||
vec2 texCoords[3] = vec2[3](
|
||||
vec2(0.0, 0.0),
|
||||
vec2(2.0, 0.0),
|
||||
vec2(0.0, 2.0));
|
||||
gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0);
|
||||
vTexCoord = texCoords[gl_VertexID];
|
||||
}
|
||||
)GLSL";
|
||||
|
||||
struct GlobalParamsStd140
|
||||
{
|
||||
float time = 0.0f;
|
||||
float pad0 = 0.0f;
|
||||
float inputResolution[2] = {};
|
||||
float outputResolution[2] = {};
|
||||
float utcTimeSeconds = 0.0f;
|
||||
float utcOffsetSeconds = 0.0f;
|
||||
float startupRandom = 0.37f;
|
||||
float frameCount = 0.0f;
|
||||
float mixAmount = 1.0f;
|
||||
float bypass = 0.0f;
|
||||
int sourceHistoryLength = 0;
|
||||
int temporalHistoryLength = 0;
|
||||
int feedbackAvailable = 0;
|
||||
float speed = 1.0f;
|
||||
float scale = 1.0f;
|
||||
float raySteps = 77.0f;
|
||||
float intensity = 1.0f;
|
||||
float sourceMix = 0.0f;
|
||||
float pad1[3] = {};
|
||||
};
|
||||
}
|
||||
|
||||
RuntimeShaderRenderer::~RuntimeShaderRenderer()
|
||||
{
|
||||
ShutdownGl();
|
||||
}
|
||||
|
||||
bool RuntimeShaderRenderer::CommitFragmentShader(const std::string& fragmentShaderSource, std::string& error)
|
||||
{
|
||||
if (fragmentShaderSource.empty())
|
||||
{
|
||||
error = "Cannot commit an empty fragment shader.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EnsureStaticGlResources(error))
|
||||
return false;
|
||||
|
||||
GLuint vertexShader = 0;
|
||||
GLuint fragmentShader = 0;
|
||||
GLuint program = 0;
|
||||
if (!CompileShader(GL_VERTEX_SHADER, kVertexShaderSource, vertexShader, error))
|
||||
return false;
|
||||
if (!CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource.c_str(), fragmentShader, error))
|
||||
{
|
||||
glDeleteShader(vertexShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
glLinkProgram(program);
|
||||
|
||||
GLint linkResult = GL_FALSE;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &linkResult);
|
||||
if (linkResult == GL_FALSE)
|
||||
{
|
||||
std::array<char, 4096> log = {};
|
||||
GLsizei length = 0;
|
||||
glGetProgramInfoLog(program, static_cast<GLsizei>(log.size()), &length, log.data());
|
||||
error = std::string(log.data(), static_cast<std::size_t>(length));
|
||||
glDeleteProgram(program);
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
return false;
|
||||
}
|
||||
|
||||
const GLuint globalParamsIndex = glGetUniformBlockIndex(program, "GlobalParams");
|
||||
if (globalParamsIndex != GL_INVALID_INDEX)
|
||||
glUniformBlockBinding(program, globalParamsIndex, kGlobalParamsBindingPoint);
|
||||
|
||||
glUseProgram(program);
|
||||
const GLint videoInputLocation = glGetUniformLocation(program, "gVideoInput");
|
||||
if (videoInputLocation >= 0)
|
||||
glUniform1i(videoInputLocation, 0);
|
||||
const GLint layerInputLocation = glGetUniformLocation(program, "gLayerInput");
|
||||
if (layerInputLocation >= 0)
|
||||
glUniform1i(layerInputLocation, 0);
|
||||
glUseProgram(0);
|
||||
|
||||
DestroyProgram();
|
||||
mProgram = program;
|
||||
mVertexShader = vertexShader;
|
||||
mFragmentShader = fragmentShader;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::RenderFrame(uint64_t frameIndex, unsigned width, unsigned height)
|
||||
{
|
||||
if (mProgram == 0)
|
||||
return;
|
||||
|
||||
GlobalParamsStd140 params;
|
||||
params.time = static_cast<float>(frameIndex) / 60.0f;
|
||||
params.inputResolution[0] = static_cast<float>(width);
|
||||
params.inputResolution[1] = static_cast<float>(height);
|
||||
params.outputResolution[0] = static_cast<float>(width);
|
||||
params.outputResolution[1] = static_cast<float>(height);
|
||||
params.frameCount = static_cast<float>(frameIndex);
|
||||
|
||||
glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, mGlobalParamsBuffer);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(params), ¶ms);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, kGlobalParamsBindingPoint, mGlobalParamsBuffer);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
glBindVertexArray(mVertexArray);
|
||||
glUseProgram(mProgram);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glUseProgram(0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::ShutdownGl()
|
||||
{
|
||||
DestroyProgram();
|
||||
DestroyStaticGlResources();
|
||||
}
|
||||
|
||||
bool RuntimeShaderRenderer::EnsureStaticGlResources(std::string& error)
|
||||
{
|
||||
if (mVertexArray == 0)
|
||||
glGenVertexArrays(1, &mVertexArray);
|
||||
if (mGlobalParamsBuffer == 0)
|
||||
{
|
||||
glGenBuffers(1, &mGlobalParamsBuffer);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, mGlobalParamsBuffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, static_cast<GLsizeiptr>(sizeof(GlobalParamsStd140)), nullptr, GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
if (mVertexArray == 0 || mGlobalParamsBuffer == 0)
|
||||
{
|
||||
error = "Failed to create runtime shader GL resources.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuntimeShaderRenderer::CompileShader(GLenum shaderType, const char* source, GLuint& shader, std::string& error) const
|
||||
{
|
||||
shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, &source, nullptr);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint compileResult = GL_FALSE;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
|
||||
if (compileResult != GL_FALSE)
|
||||
return true;
|
||||
|
||||
std::array<char, 4096> log = {};
|
||||
GLsizei length = 0;
|
||||
glGetShaderInfoLog(shader, static_cast<GLsizei>(log.size()), &length, log.data());
|
||||
error = std::string(log.data(), static_cast<std::size_t>(length));
|
||||
glDeleteShader(shader);
|
||||
shader = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::DestroyProgram()
|
||||
{
|
||||
if (mProgram != 0)
|
||||
glDeleteProgram(mProgram);
|
||||
if (mVertexShader != 0)
|
||||
glDeleteShader(mVertexShader);
|
||||
if (mFragmentShader != 0)
|
||||
glDeleteShader(mFragmentShader);
|
||||
mProgram = 0;
|
||||
mVertexShader = 0;
|
||||
mFragmentShader = 0;
|
||||
}
|
||||
|
||||
void RuntimeShaderRenderer::DestroyStaticGlResources()
|
||||
{
|
||||
if (mGlobalParamsBuffer != 0)
|
||||
glDeleteBuffers(1, &mGlobalParamsBuffer);
|
||||
if (mVertexArray != 0)
|
||||
glDeleteVertexArrays(1, &mVertexArray);
|
||||
mGlobalParamsBuffer = 0;
|
||||
mVertexArray = 0;
|
||||
}
|
||||
32
apps/RenderCadenceCompositor/render/RuntimeShaderRenderer.h
Normal file
32
apps/RenderCadenceCompositor/render/RuntimeShaderRenderer.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "GLExtensions.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class RuntimeShaderRenderer
|
||||
{
|
||||
public:
|
||||
RuntimeShaderRenderer() = default;
|
||||
RuntimeShaderRenderer(const RuntimeShaderRenderer&) = delete;
|
||||
RuntimeShaderRenderer& operator=(const RuntimeShaderRenderer&) = delete;
|
||||
~RuntimeShaderRenderer();
|
||||
|
||||
bool CommitFragmentShader(const std::string& fragmentShaderSource, std::string& error);
|
||||
bool HasProgram() const { return mProgram != 0; }
|
||||
void RenderFrame(uint64_t frameIndex, unsigned width, unsigned height);
|
||||
void ShutdownGl();
|
||||
|
||||
private:
|
||||
bool EnsureStaticGlResources(std::string& error);
|
||||
bool CompileShader(GLenum shaderType, const char* source, GLuint& shader, std::string& error) const;
|
||||
void DestroyProgram();
|
||||
void DestroyStaticGlResources();
|
||||
|
||||
GLuint mProgram = 0;
|
||||
GLuint mVertexShader = 0;
|
||||
GLuint mFragmentShader = 0;
|
||||
GLuint mVertexArray = 0;
|
||||
GLuint mGlobalParamsBuffer = 0;
|
||||
};
|
||||
Reference in New Issue
Block a user