Commit for 2021.07.18 00-48-23.7z

This commit is contained in:
mrq 2021-07-18 00:48:00 -05:00
parent 6d8fbc6ee5
commit 8aeca4944c
30 changed files with 568 additions and 373 deletions

View File

@ -38,6 +38,13 @@
"min": [ -1.5, -1.5, -1.5 ],
"max": [ 1.5, 1.5, 1.5 ]
}
},
"bloom": {
"scale": 1.0,
"strength": 1.0,
"threshold": 1.0,
"sigma": 0.8,
"samples": 5
}
},
"ext": {
@ -69,12 +76,13 @@
"multithreaded command rendering": false,
"deferred mode": "",
"deferred reconstruct position": true,
"deferred alias output to swapchain": true,
"deferred alias output to swapchain": false,
"vsync": true,
"hdr": false,
"vxgi": true,
"deferred sampling": true,
"culling": false
"deferred sampling": false,
"culling": false,
"bloom": true
},
"formats": {
"depth": "D32_SFLOAT",

View File

@ -29,10 +29,16 @@
"bgm": 0.75,
"voice": 1.0
},
"bloom": {
"scale": 1.0,
"strength": 0.5,
"sigma": 0.75,
"samples": 8
},
"light": {
"exposure": 1.0,
"gamma": 1.0,
"brightnessThreshold": 1.0,
"ambient": [ 0.1, 0.1, 0.1 ],
"fog": {

View File

@ -15,6 +15,9 @@ vec3 orthogonal(vec3 u){
vec4 blend( vec4 source, vec4 dest, float a ) {
return source * a + dest * (1.0 - a);
}
float gauss( float x, float sigma ) {
return (1.0 / (2.0 * 3.14157 * sigma) * exp(-(x*x) / (2.0 * sigma)));
}
bool enabled( uint flag, uint bit ) {
return (flag & (1 << bit)) != 0;
}
@ -35,7 +38,7 @@ bool validTextureIndex( int textureIndex ) {
bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < CUBEMAPS;
}
#if DEFERRED || COMPUTE
#if !BLOOM && (DEFERRED || COMPUTE)
bool validTextureIndex( uint id ) {
return 0 <= id && id < MAX_TEXTURES;
}

View File

@ -0,0 +1,67 @@
#version 450
#pragma shader_stage(compute)
#define COMPUTE 1
#define TEXTURES 0
#define CUBEMAPS 0
#define BLOOM 1
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
layout( push_constant ) uniform PushBlock {
uint eye;
uint mode;
} PushConstant;
layout (binding = 0) uniform UBO {
float scale;
float strength;
float threshold;
float sigma;
float gamma;
float exposure;
uint samples;
uint padding;
} ubo;
layout (binding = 1, rgba16f) uniform volatile coherent image2D imageColor;
layout (binding = 2, rgba16f) uniform volatile coherent image2D imageBloom;
layout (binding = 3, rgba16f) uniform volatile coherent image2D imagePingPong;
#include "../common/macros.h"
#include "../common/structs.h"
#include "../common/functions.h"
void main() {
const uint mode = PushConstant.mode;
const ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
const ivec2 size = imageSize( imageColor );
if ( texel.x >= size.x || texel.y >= size.y ) return;
if ( mode == 0 ) { // fill bloom
vec3 result = imageLoad( imageColor, texel ).rgb;
float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
if ( brightness < ubo.threshold ) result = vec3(0, 0, 0);
imageStore( imageBloom, texel, vec4( result, 1.0 ) );
} else if ( mode == 1 ) { // bloom horizontal
vec3 result = imageLoad( imageBloom, texel ).rgb * gauss( 0, ubo.sigma ) * ubo.strength;
for( int i = 1; i < ubo.samples; ++i ) {
result += imageLoad( imageBloom, texel + ivec2(i * ubo.scale, 0.0)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
result += imageLoad( imageBloom, texel - ivec2(i * ubo.scale, 0.0)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
}
// write to PingPong
imageStore( imagePingPong, texel, vec4( result, 1.0 ) );
} else if ( mode == 2 ) { // bloom vertical
vec3 result = imageLoad( imagePingPong, texel ).rgb * gauss( 0, ubo.sigma ) * ubo.strength;
for( int i = 1; i < ubo.samples; ++i ) {
result += imageLoad( imagePingPong, texel + ivec2(0.0, i * ubo.scale)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
result += imageLoad( imagePingPong, texel - ivec2(0.0, i * ubo.scale)).rgb * gauss( i * ubo.scale / ubo.samples, ubo.sigma ) * ubo.strength;
}
// write to Bloom
imageStore( imageBloom, texel, vec4( result, 1.0 ) );
} else if ( mode == 3 ) { // combine
vec3 result = imageLoad( imageColor, texel ).rgb + imageLoad( imageBloom, texel ).rgb;
imageStore( imageColor, texel, vec4( result, 1.0 ) );
}
}

View File

@ -49,9 +49,14 @@ layout (binding = 4) uniform UBO {
float gamma;
float exposure;
float brightnessThreshold;
uint msaa;
uint shadowSamples;
uint indexSkybox;
uint padding1;
uint padding2;
uint padding3;
} ubo;
/*
layout (std140, binding = 5) readonly buffer DrawCommands {
@ -81,9 +86,10 @@ layout (binding = 11) uniform sampler3D samplerNoise;
#endif
layout (location = 0) in vec2 inUv;
layout (location = 1) in flat uint inPushConstantPass;
layout (location = 1) in flat uvec2 inPushConstantPass;
layout (location = 0) out vec4 outFragColor;
layout (location = 1) out vec4 outFragBright;
#include "../common/functions.h"
#include "../common/fog.h"
@ -94,6 +100,9 @@ layout (location = 0) out vec4 outFragColor;
#endif
void postProcess() {
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
outFragBright = brightness > ubo.brightnessThreshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
#if FOG
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );
#endif
@ -106,12 +115,12 @@ void postProcess() {
#if WHITENOISE
if ( enabled(ubo.mode.type, 1) ) whitenoise(surface.fragment.rgb, ubo.mode.parameters);
#endif
outFragColor = vec4(surface.fragment.rgb,1);
outFragColor = vec4(surface.fragment.rgb, 1.0);
}
void populateSurface() {
surface.pass = inPushConstantPass;
surface.pass = inPushConstantPass.x;
{
#if !MULTISAMPLING
const float depth = subpassLoad(samplerDepth).r;

View File

@ -6,7 +6,7 @@ layout (location = 0) in vec2 inPos;
layout (location = 1) in vec2 inUv;
#endif
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat uint outPushConstantPass;
layout (location = 1) out flat uvec2 outPushConstantPass;
layout( push_constant ) uniform PushBlock {
uint pass;
@ -19,7 +19,7 @@ out gl_PerVertex {
void main() {
outPushConstantPass = PushConstant.pass;
outPushConstantPass = uvec2(PushConstant.pass, PushConstant.draw);
outUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outUv * 2.0f + -1.0f, 0.0f, 1.0f);
#if 0

View File

@ -32,9 +32,14 @@ layout (binding = 4) uniform UBO {
float gamma;
float exposure;
float brightnessThreshold;
uint msaa;
uint shadowSamples;
uint indexSkybox;
uint padding1;
uint padding2;
uint padding3;
} ubo;
/*
layout (std140, binding = 5) readonly buffer DrawCommands {

View File

@ -40,6 +40,7 @@ namespace ext {
extern UF_API bool vxgi;
extern UF_API bool deferredSampling;
extern UF_API bool culling;
extern UF_API bool bloom;
}
namespace formats {

View File

@ -36,6 +36,7 @@ namespace ext {
void update( const Graphic& graphic );
void update( const Graphic& graphic, const GraphicDescriptor& descriptor );
void record( const Graphic& graphic, VkCommandBuffer, size_t = 0, size_t = 0 ) const;
void record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer, size_t = 0, size_t = 0 ) const;
void destroy();
uf::stl::vector<Shader*> getShaders( uf::stl::vector<Shader>& );

View File

@ -27,15 +27,15 @@ namespace ext {
uf::stl::vector<Attachment> attachments;
struct Subpass {
VkPipelineStageFlags stage;
VkAccessFlags access;
uint8_t layer;
VkPipelineStageFlags stage = {};
VkAccessFlags access = {};
uint8_t layer = 0;
bool autoBuildPipeline;
uf::stl::vector<VkAttachmentReference> colors;
uf::stl::vector<VkAttachmentReference> inputs;
uf::stl::vector<VkAttachmentReference> resolves;
VkAttachmentReference depth;
uf::stl::vector<VkAttachmentReference> colors = {};
uf::stl::vector<VkAttachmentReference> inputs = {};
uf::stl::vector<VkAttachmentReference> resolves = {};
VkAttachmentReference depth = {};
};
uf::stl::vector<Subpass> passes;

View File

@ -98,6 +98,10 @@ namespace ext {
ext::vulkan::userdata_t specializationConstants;
uf::stl::vector<ext::vulkan::userdata_t> pushConstants;
uf::stl::vector<ext::vulkan::userdata_t> uniforms;
// for per-shader texture allotment, needed for our bloom pipeline
uf::stl::vector<Texture2D> textures;
// ~Shader();
void initialize( Device& device, const uf::stl::string&, VkShaderStageFlagBits );
void destroy();

View File

@ -67,6 +67,7 @@ namespace ext {
extern UF_API bool vxgi;
extern UF_API bool deferredSampling;
extern UF_API bool culling;
extern UF_API bool bloom;
}
namespace formats {

View File

@ -98,4 +98,6 @@
#endif
#define MIN(X, Y) X < Y ? X : Y
#define MAX(X, Y) X > Y ? X : Y
#define MAX(X, Y) X > Y ? X : Y
#define LENGTH_OF(X) *(&X + 1) - X
#define FOR_ARRAY(X) for ( auto i = 0; i < LENGTH_OF(X); ++i )

View File

@ -57,104 +57,104 @@ namespace {
}
// standard pipeline
uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/base.vert.spv");
uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/base.vert.spv"); {
std::pair<bool, uf::stl::string> settings[] = {
{ graph.metadata["flags"]["SKINNED"].as<bool>(), "skinned.vert" },
{ graph.metadata["flags"]["SEPARATE"].as<bool>(), "instanced.vert" },
};
FOR_ARRAY(settings) if ( settings[i].first ) vertexShaderFilename = uf::string::replace( vertexShaderFilename, "vert", settings[i].second );
vertexShaderFilename = entity.grabURI( vertexShaderFilename, root );
}
uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as<uf::stl::string>("");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/graph/base.frag.spv");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/graph/base.frag.spv"); {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::experimental::deferredSampling, "deferredSampling.frag" },
};
FOR_ARRAY(settings) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
fragmentShaderFilename = entity.grabURI( fragmentShaderFilename, root );
}
{
graphic.material.metadata.autoInitializeUniforms = false;
if ( uf::renderer::settings::experimental::deferredSampling ) {
fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "deferredSampling.frag" );
}
{
if ( !graph.metadata["flags"]["SEPARATE"].as<bool>() ) {
vertexShaderFilename = graph.metadata["flags"]["SKINNED"].as<bool>() ? "/graph/skinned.instanced.vert.spv" : "/graph/instanced.vert.spv";
} else if ( graph.metadata["flags"]["SKINNED"].as<bool>() ) vertexShaderFilename = "/graph/skinned.vert.spv";
vertexShaderFilename = entity.grabURI( vertexShaderFilename, root );
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX);
}
{
fragmentShaderFilename = entity.grabURI( fragmentShaderFilename, root );
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT);
}
#if UF_USE_VULKAN
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX);
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT);
graphic.material.metadata.autoInitializeUniforms = true;
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
geometryShaderFilename = entity.grabURI( geometryShaderFilename, root );
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY);
}
{
uint32_t maxPasses = 6;
auto& shader = graphic.material.getShader("vertex");
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses);
}
uf::renderer::Buffer* indirect = NULL;
for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer;
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
}
{
uint32_t maxTextures = graph.textures.size(); // texture2Ds;
auto& shader = graphic.material.getShader("fragment");
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures);
}
for ( auto pair : shader.metadata.definitions.textures ) {
auto& tx = pair.second;
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != tx.binding ) continue;
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures;
}
}
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
}
#endif
}
#if UF_USE_VULKAN
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
geometryShaderFilename = entity.grabURI( geometryShaderFilename, root );
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY);
}
{
uint32_t maxPasses = 6;
auto& shader = graphic.material.getShader("vertex");
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "PASSES" ) sc.value.ui = (specializationConstants[sc.index] = maxPasses);
}
uf::renderer::Buffer* indirect = NULL;
for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer;
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
// shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.drawCommands );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
}
{
uint32_t maxTextures = graph.textures.size(); // texture2Ds;
auto& shader = graphic.material.getShader("fragment");
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
auto& sc = pair.second;
if ( sc.name == "TEXTURES" ) sc.value.ui = (specializationConstants[sc.index] = maxTextures);
}
for ( auto pair : shader.metadata.definitions.textures ) {
auto& tx = pair.second;
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != tx.binding ) continue;
if ( tx.name == "samplerTextures" ) layout.descriptorCount = maxTextures;
}
}
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
}
#endif
// culling pipeline
if ( uf::renderer::settings::experimental::culling ) {
graphic.material.metadata.autoInitializeUniforms = false;
uf::renderer::Buffer* indirect = NULL;
for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer;
UF_ASSERT( indirect );
uf::stl::string compShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/cull.comp.spv");
{
graphic.material.metadata.autoInitializeUniforms = false;
compShaderFilename = entity.grabURI( compShaderFilename, root );
graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, "culling");
graphic.material.metadata.autoInitializeUniforms = true;
}
graphic.descriptor.inputs.dispatch = { graphic.descriptor.inputs.indirect.count, 1, 1 };
auto& shader = graphic.material.getShader("compute", "culling");
uf::renderer::Buffer* indirect = NULL;
for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer;
UF_ASSERT( indirect );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
shader.buffers.emplace_back().aliasBuffer( *indirect );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
}
#if UF_USE_VULKAN
// depth only pipeline
#if UF_USE_VULKAN
{
graphic.material.metadata.autoInitializeUniforms = false;
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/depth.frag.spv");
{
graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "depth");
}
{
fragmentShaderFilename = entity.grabURI( fragmentShaderFilename, root );
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "depth");
}
fragmentShaderFilename = entity.grabURI( fragmentShaderFilename, root );
// graphic.material.attachShader(vertexShaderFilename, uf::renderer::enums::Shader::VERTEX, "depth");
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "depth");
graphic.material.metadata.autoInitializeUniforms = true;
/*
{
uint32_t maxPasses = 6;
@ -173,6 +173,7 @@ namespace {
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.joint );
}
*/
{
uint32_t maxTextures = graph.textures.size(); // texture2Ds;
@ -197,20 +198,16 @@ namespace {
}
// vxgi pipeline
if ( uf::renderer::settings::experimental::vxgi ) {
// graphic.material.metadata.json["shader"]["autoInitializeUniformBuffers"] = false;
graphic.material.metadata.autoInitializeUniforms = false;
uf::stl::string vertexShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/base.vert.spv");
uf::stl::string geometryShaderFilename = graph.metadata["shaders"]["geometry"].as<uf::stl::string>("/graph/voxelize.geom.spv");
uf::stl::string fragmentShaderFilename = graph.metadata["shaders"]["fragment"].as<uf::stl::string>("/graph/voxelize.frag.spv");
if ( uf::renderer::settings::experimental::deferredSampling ) {
// fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "deferredSampling.frag" );
}
{
fragmentShaderFilename = entity.grabURI( fragmentShaderFilename, root );
graphic.material.metadata.autoInitializeUniforms = false;
graphic.material.attachShader(fragmentShaderFilename, uf::renderer::enums::Shader::FRAGMENT, "vxgi");
graphic.material.metadata.autoInitializeUniforms = true;
}
// graphic.material.metadata.json["shader"]["autoInitializeUniformBuffers"] = true;
graphic.material.metadata.autoInitializeUniforms = true;
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
geometryShaderFilename = entity.grabURI( geometryShaderFilename, root );
graphic.material.attachShader(geometryShaderFilename, uf::renderer::enums::Shader::GEOMETRY, "vxgi");
@ -246,36 +243,13 @@ namespace {
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
/*
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
ext::json::forEach( shader.metadata.json["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
uf::stl::string name = sc["name"].as<uf::stl::string>();
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures);
else if ( name == "CASCADES" ) sc["value"] = (specializationConstants[i] = maxCascades);
});
ext::json::forEach( shader.metadata.json["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
uf::stl::string name = t["name"].as<uf::stl::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures;
else if ( name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelDepth" ) layout.descriptorCount = maxCascades;
}
});
*/
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.material );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.texture );
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.light );
}
}
#endif
// graphic.process = true;
#endif
}
void initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
auto& graphic = entity.getComponent<uf::Graphic>();

View File

@ -44,6 +44,9 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
transform.reference = &controller.getComponent<pod::Transform<>>();
}
});
this->addHook( "object:Reload.%UID%", [&](ext::json::Value& json){
this->callHook("object:UpdateMetadata.%UID%", json);
});
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
if ( ext::json::isNull( json ) ) return;
if ( json["type"].as<uf::stl::string>() == "merge" ) {
@ -105,7 +108,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
metadata.deserialize(self, metadataJson);
});
metadata.deserialize(self, metadataJson);

View File

@ -47,6 +47,14 @@ void uf::GraphBehavior::initialize( uf::Object& self ) {
sceneMetadataJson["light"]["fog"] = graph.metadata["fog"];
shouldUpdate = true;
}
if ( !ext::json::isNull(graph.metadata["gamma"]) ) {
sceneMetadataJson["light"]["gamma"] = graph.metadata["gamma"];
shouldUpdate = true;
}
if ( !ext::json::isNull(graph.metadata["brightnessThreshold"]) ) {
sceneMetadataJson["light"]["brightnessThreshold"] = graph.metadata["brightnessThreshold"];
shouldUpdate = true;
}
if ( shouldUpdate ) scene.callHook("object:UpdateMetadata.%UID%");
// deferred shader loading

View File

@ -41,6 +41,7 @@ bool ext::opengl::settings::experimental::hdr = true;
bool ext::opengl::settings::experimental::vxgi = true;
bool ext::opengl::settings::experimental::deferredSampling = true;
bool ext::opengl::settings::experimental::culling = false;
bool ext::opengl::settings::experimental::bloom = false;
GLhandle(VkColorSpaceKHR) ext::opengl::settings::formats::colorSpace;
ext::opengl::enums::Format::type_t ext::opengl::settings::formats::color = ext::opengl::enums::Format::R8G8B8A8_UNORM;

View File

@ -325,6 +325,9 @@ PIPELINE_INITIALIZATION_INVALID:
return;
}
void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer commandBuffer, size_t pass, size_t draw ) const {
return record( graphic, descriptor, commandBuffer, pass, draw );
}
void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescriptor& descriptor, VkCommandBuffer commandBuffer, size_t pass, size_t draw ) const {
auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
auto shaders = getShaders( graphic.material.shaders );
for ( auto* shader : shaders ) {
@ -424,7 +427,8 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
}
}
for ( auto& texture : graphic.material.textures ) {
auto& textures = !shader->textures.empty() ? shader->textures : graphic.material.textures;
for ( auto& texture : textures ) {
infos.image.emplace_back(texture.descriptor);
switch ( texture.viewType ) {
case VK_IMAGE_VIEW_TYPE_2D: infos.image2D.emplace_back(texture.descriptor); break;
@ -957,7 +961,7 @@ void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, const GraphicD
return;
}
if ( !pipeline.metadata.process ) return;
pipeline.record(*this, commandBuffer, pass, draw);
pipeline.record(*this, descriptor, commandBuffer, pass, draw);
auto shaders = pipeline.getShaders( material.shaders );
for ( auto* shader : shaders ) if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) return;

View File

@ -38,105 +38,115 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
}
if ( settings::experimental::bloom ) settings::experimental::deferredAliasOutputToSwapchain = false;
ext::vulkan::RenderMode::initialize( device );
renderTarget.device = &device;
renderTarget.views = metadata.eyes;
size_t msaa = ext::vulkan::settings::msaa;
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
struct {
size_t id, normals, uvs, albedo, depth, output, debug;
} attachments = {};
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UINT,
struct {
size_t id, normals, uvs, albedo, depth, color, bright, scratch, output;
} attachments = {};
attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UINT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_SFLOAT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
if ( ext::vulkan::settings::experimental::deferredSampling ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_SFLOAT,
} else {
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
if ( ext::vulkan::settings::experimental::deferredSampling ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
} else {
attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */true,
/*.samples = */msaa,
});
}
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.blend = */true,
/*.samples = */msaa,
});
}
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */msaa,
});
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
// Attach swapchain's image as output
if ( settings::experimental::deferredAliasOutputToSwapchain ) {
attachments.output = renderTarget.attachments.size();
auto& swapchainAttachment = renderTarget.attachments.emplace_back();
swapchainAttachment.descriptor.format = ext::vulkan::settings::formats::color; //device.formats.color;
swapchainAttachment.descriptor.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainAttachment.descriptor.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
swapchainAttachment.descriptor.aliased = true;
{
VkBool32 blendEnabled = VK_TRUE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
writeMask,
blendEnabled
);
if ( blendEnabled == VK_TRUE ) {
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
}
swapchainAttachment.blendState = blendAttachmentState;
// Attach swapchain's image as output
if ( settings::experimental::deferredAliasOutputToSwapchain ) {
attachments.output = renderTarget.attachments.size();
auto& swapchainAttachment = renderTarget.attachments.emplace_back();
swapchainAttachment.descriptor.format = ext::vulkan::settings::formats::color; //device.formats.color;
swapchainAttachment.descriptor.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainAttachment.descriptor.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
swapchainAttachment.descriptor.aliased = true;
{
VkBool32 blendEnabled = VK_TRUE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
VkPipelineColorBlendAttachmentState blendAttachmentState = ext::vulkan::initializers::pipelineColorBlendAttachmentState(
writeMask,
blendEnabled
);
if ( blendEnabled == VK_TRUE ) {
blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
blendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
blendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
}
} else {
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R8G8B8A8_UNORM,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
swapchainAttachment.blendState = blendAttachmentState;
}
attachments.debug = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R32G32B32A32_SFLOAT,
} else {
attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ false,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
/*.blend =*/ true,
/*.samples =*/ 1,
});
metadata.outputs.emplace_back(attachments.output);
#if 0
attachments.debug = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
/*.blend = */false,
/*.samples = */1,
});
#endif
}
metadata.outputs.emplace_back(attachments.color);
// metadata.outputs.emplace_back(attachments.output);
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
if ( ext::vulkan::settings::experimental::deferredSampling ) {
// First pass: fill the G-Buffer
{
@ -144,24 +154,38 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
/*.colors =*/ { attachments.id, attachments.normals, attachments.uvs },
/*.inputs =*/ {},
/*.resolve =*/ {},
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.layer = */eye,
/*.autoBuildPipeline =*/ true
);
}
// Second pass: write to output
// Second pass: write to color
{
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ { attachments.output, attachments.debug },
/*.colors =*/ { attachments.color, attachments.bright },
/*.inputs =*/ { attachments.id, attachments.normals, attachments.uvs, attachments.depth },
/*.resolve =*/ {},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.resolve =*/{},
/*.depth = */attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ false
);
}
#if 0
// Third pass: solely to transition
if ( settings::experimental::bloom ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ {},
/*.inputs =*/ { attachments.color, attachments.bright, attachments.scratch, attachments.output, attachments.depth },
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ false
);
}
#endif
} else {
// First pass: fill the G-Buffer
{
@ -169,26 +193,41 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
/*.colors =*/ { attachments.id, attachments.normals, attachments.albedo },
/*.inputs =*/ {},
/*.resolve =*/ {},
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.layer = */eye,
/*.autoBuildPipeline =*/ true
);
}
// Second pass: write to output
// Second pass: write to color
{
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ { attachments.output, attachments.debug },
/*.colors =*/ { attachments.color, attachments.bright },
/*.inputs =*/ { attachments.id, attachments.normals, attachments.albedo, attachments.depth },
/*.resolve =*/ {},
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */0,
/*.layer = */eye,
/*.autoBuildPipeline =*/ false
);
}
#if 0
// Third pass: solely to transition
if ( settings::experimental::bloom ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ {},
/*.inputs =*/ { attachments.color, attachments.bright, attachments.scratch, attachments.output, attachments.depth },
/*.resolve =*/{},
/*.depth = */ attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ false
);
}
#endif
}
}
renderTarget.initialize( device );
{
@ -215,25 +254,40 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
blitter.initializeMesh( mesh );
uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/subpass.vert.spv";
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/subpass.frag.spv";
if ( uf::renderer::settings::experimental::vxgi ) {
fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "vxgi.frag" );
}
if ( msaa > 1 ) {
fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "msaa.frag" );
}
if ( uf::renderer::settings::experimental::deferredSampling ) {
fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "deferredSampling.frag" );
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/subpass.frag.spv"; {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::experimental::vxgi, "vxgi.frag" },
{ msaa > 1, "msaa.frag" },
{ uf::renderer::settings::experimental::deferredSampling, "deferredSampling.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
}
blitter.material.initializeShaders({
{uf::io::resolveURI(vertexShaderFilename), VK_SHADER_STAGE_VERTEX_BIT},
{uf::io::resolveURI(fragmentShaderFilename), VK_SHADER_STAGE_FRAGMENT_BIT}
});
{
auto& scene = uf::scene::getCurrentScene();
auto& scene = uf::scene::getCurrentScene();
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
if ( settings::experimental::bloom ) {
uf::stl::string computeShaderFilename = uf::io::resolveURI(uf::io::root+"/shaders/display/bloom.comp.spv");
blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom");
auto& shader = blitter.material.getShader("compute", "bloom");
shader.textures.clear();
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[attachments.color], (size_t) 0 );
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[attachments.bright], (size_t) 0 );
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[attachments.scratch], (size_t) 0 );
for ( auto& texture : shader.textures ) {
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
}
{
auto& shader = blitter.material.getShader("fragment");
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
size_t maxLights = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
size_t maxTextures2D = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
size_t maxTexturesCube = sceneMetadataJson["system"]["config"]["engine"]["scenes"]["textures"]["max"]["cube"].as<size_t>(128);
@ -267,28 +321,6 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
/*
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
ext::json::forEach( shader.metadata.json["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
uf::stl::string name = sc["name"].as<uf::stl::string>();
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
else if ( name == "CUBEMAPS" ) sc["value"] = (specializationConstants[i] = maxTexturesCube);
else if ( name == "CASCADES" ) sc["value"] = (specializationConstants[i] = maxCascades);
});
ext::json::forEach( shader.metadata.json["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
uf::stl::string name = t["name"].as<uf::stl::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
else if ( name == "voxelId" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelUv" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelNormal" ) layout.descriptorCount = maxCascades;
else if ( name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
});
*/
} else {
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
for ( auto pair : shader.metadata.definitions.specializationConstants ) {
@ -304,63 +336,22 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
else if ( tx.name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
}
}
/*
uint32_t* specializationConstants = (uint32_t*) (void*) shader.specializationConstants;
ext::json::forEach( shader.metadata.json["specializationConstants"], [&]( size_t i, ext::json::Value& sc ){
uf::stl::string name = sc["name"].as<uf::stl::string>();
if ( name == "TEXTURES" ) sc["value"] = (specializationConstants[i] = maxTextures2D);
else if ( name == "CUBEMAPS" ) sc["value"] = (specializationConstants[i] = maxTexturesCube);
});
ext::json::forEach( shader.metadata.json["definitions"]["textures"], [&]( ext::json::Value& t ){
size_t binding = t["binding"].as<size_t>();
uf::stl::string name = t["name"].as<uf::stl::string>();
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
if ( layout.binding != binding ) continue;
if ( name == "samplerTextures" ) layout.descriptorCount = maxTextures2D;
else if ( name == "samplerCubemaps" ) layout.descriptorCount = maxTexturesCube;
}
});
*/
}
/*
uf::stl::vector<pod::Light> lights(maxLights);
uf::stl::vector<pod::Material> materials(maxTextures2D);
uf::stl::vector<pod::Texture> textures(maxTextures2D);
uf::stl::vector<pod::DrawCommand> drawCommands(maxTextures2D);
for ( auto& material : materials ) material.colorBase = {0,0,0,0};
metadata.lightBufferIndex = shader.initializeBuffer(
(const void*) lights.data(),
lights.size() * sizeof(pod::Light),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.materialBufferIndex = shader.initializeBuffer(
(const void*) materials.data(),
materials.size() * sizeof(pod::Material),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.textureBufferIndex = shader.initializeBuffer(
(const void*) textures.data(),
textures.size() * sizeof(pod::Texture),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
metadata.drawCallBufferIndex = shader.initializeBuffer(
(const void*) drawCommands.data(),
drawCommands.size() * sizeof(pod::DrawCommand),
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
);
*/
}
// blitter.initializePipeline();
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
blitter.descriptor.subpass = 2 * eye + 1;
if ( blitter.hasPipeline( blitter.descriptor ) ) continue;
blitter.initializePipeline( blitter.descriptor );
auto descriptor = blitter.descriptor;
descriptor.subpass = (renderTarget.passes.size() / metadata.eyes) * eye + 1;
if ( !blitter.hasPipeline( descriptor ) ) blitter.initializePipeline( descriptor );
if ( settings::experimental::bloom ) {
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.pipeline = "bloom";
descriptor.subpass = 0;
if ( !blitter.hasPipeline( descriptor ) ) {
blitter.initializePipeline( descriptor );
}
}
}
blitter.descriptor.subpass = 1;
}
}
void ext::vulkan::DeferredRenderMode::tick() {
@ -371,15 +362,37 @@ void ext::vulkan::DeferredRenderMode::tick() {
if ( resized ) {
renderTarget.initialize( *renderTarget.device );
if ( settings::experimental::bloom ) {
auto& shader = blitter.material.getShader("compute", "bloom");
#if 1
shader.textures.clear();
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[renderTarget.attachments.size() - 5], (size_t) 0 ); // attachments.color
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[renderTarget.attachments.size() - 4], (size_t) 0 ); // attachments.bright
shader.textures.emplace_back().aliasAttachment( renderTarget.attachments[renderTarget.attachments.size() - 3], (size_t) 0 ); // attachments.scratch
for ( auto& texture : shader.textures ) {
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
#endif
}
}
// update blitter descriptor set
if ( rebuild && blitter.initialized ) {
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
blitter.descriptor.subpass = 2 * eye + 1;
if ( !blitter.hasPipeline( blitter.descriptor ) ) continue;
blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor );
auto descriptor = blitter.descriptor;
descriptor.subpass = (renderTarget.passes.size() / metadata.eyes) * eye + 1;
if ( blitter.hasPipeline( blitter.descriptor ) ) blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor );
if ( settings::experimental::bloom ) {
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.pipeline = "bloom";
descriptor.subpass = 0;
if ( blitter.hasPipeline( descriptor ) ) {
blitter.getPipeline( descriptor ).update( blitter, descriptor );
}
}
}
blitter.descriptor.subpass = 1;
}
}
void ext::vulkan::DeferredRenderMode::destroy() {
@ -530,6 +543,57 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
}
vkCmdEndRenderPass(commands[i]);
if ( settings::experimental::bloom ) {
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.pipeline = "bloom";
descriptor.subpass = 0;
auto& shader = blitter.material.getShader("compute", "bloom");
imageMemoryBarrier.srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.image = attachment.image;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
}
#if 0
blitter.record(commands[i], descriptor, 0, 0);
imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.image = attachment.image;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
}
#endif
blitter.record(commands[i], descriptor, 0, 1);
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.image = attachment.image;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
}
blitter.record(commands[i], descriptor, 0, 2);
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.image = attachment.image;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
}
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.image = attachment.image;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
}
blitter.record(commands[i], descriptor, 0, 3);
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.image = attachment.image;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_FLAGS_NONE, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
}
}
for ( auto layer : layers ) {
layer->pipelineBarrier( commands[i], 1 );
}
@ -581,7 +645,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
// outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;
@ -608,10 +672,10 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
imageMemoryBarrier.image = outputAttachment.image;
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
imageMemoryBarrier.oldLayout = outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; //outputAttachment.descriptor.layout;
imageMemoryBarrier.newLayout = outputAttachment.descriptor.layout; //VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, NULL, 0, NULL, 1, &imageMemoryBarrier );
outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
// outputAttachment.descriptor.layout = imageMemoryBarrier.newLayout;
}
{
imageMemoryBarrier.image = swapchainRender.renderTarget.attachments[i].image;

View File

@ -211,7 +211,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.blend = */false,
/*.samples = */msaa,
});
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
if ( !true && ext::vulkan::settings::experimental::deferredMode != "" ) {
attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16_UNORM,
/*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@ -242,7 +242,7 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
/*.blend =*/ true,
/*.samples =*/ 1,
});
if ( false && ext::vulkan::settings::experimental::deferredMode != "" ) {
if ( !true && ext::vulkan::settings::experimental::deferredMode != "" ) {
// First pass: fill the G-Buffer
{
renderTarget.addPass(
@ -346,16 +346,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
else if ( sType == "geometry" ) type = ext::vulkan::enums::Shader::GEOMETRY;
else if ( sType == "compute" ) type = ext::vulkan::enums::Shader::COMPUTE;
}
#if 0
if ( type == ext::vulkan::enums::Shader::FRAGMENT ) {
if ( msaa > 1 ) {
filename = uf::string::replace( filename, "frag", "msaa.frag" );
}
if ( uf::renderer::settings::experimental::deferredSampling ) {
filename = uf::string::replace( filename, "frag", "deferredSampling.frag" );
}
}
#endif
blitter.material.attachShader( uf::io::root+filename, type, pipeline );
});
} else if ( ext::json::isObject( metadata.json["shaders"] ) ) {
@ -373,16 +363,6 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
else if ( key == "fragment" ) type = ext::vulkan::enums::Shader::FRAGMENT;
else if ( key == "geometry" ) type = ext::vulkan::enums::Shader::GEOMETRY;
else if ( key == "compute" ) type = ext::vulkan::enums::Shader::COMPUTE;
#if 0
if ( type == ext::vulkan::enums::Shader::FRAGMENT ) {
if ( msaa > 1 ) {
filename = uf::string::replace( filename, "frag", "msaa.frag" );
}
if ( uf::renderer::settings::experimental::deferredSampling ) {
filename = uf::string::replace( filename, "frag", "deferredSampling.frag" );
}
}
#endif
blitter.material.attachShader( uf::io::root+filename, type, pipeline );
});
} else if ( metadata.json["shaders"].is<bool>() && !metadata.json["shaders"].as<bool>() ) {
@ -390,13 +370,13 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
blitter.process = false;
} else {
uf::stl::string vertexShaderFilename = uf::io::root+"/shaders/display/renderTarget.vert.spv";
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTarget.frag.spv";
if ( msaa > 1 ) {
fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "msaa.frag" );
}
// I don't actually have support for deferred sampling within a render target
if ( uf::renderer::settings::experimental::deferredSampling ) {
// fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", "deferredSampling.frag" );
uf::stl::string fragmentShaderFilename = uf::io::root+"/shaders/display/renderTarget.frag.spv"; {
std::pair<bool, uf::stl::string> settings[] = {
{ msaa > 1, "msaa.frag" },
// I don't actually have support for deferred sampling within a render target
// { uf::renderer::settings::experimental::deferredSampling, "deferredSampling.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
}
blitter.material.initializeShaders({
{uf::io::resolveURI(vertexShaderFilename), VK_SHADER_STAGE_VERTEX_BIT},

View File

@ -11,15 +11,15 @@ void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFla
pass.access = access;
pass.layer = layer;
pass.autoBuildPipeline = autoBuildPipeline;
for ( auto& i : colors ) pass.colors.push_back( { (uint32_t) i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } );
for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
for ( auto& i : resolves ) pass.resolves.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
for ( auto& i : colors ) pass.colors.emplace_back( VkAttachmentReference{ (uint32_t) i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } );
for ( auto& i : inputs ) pass.inputs.emplace_back( VkAttachmentReference{ (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
for ( auto& i : resolves ) pass.resolves.emplace_back( VkAttachmentReference{ (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } );
if ( depth < attachments.size() ) pass.depth = { (uint32_t) depth, attachments[depth].descriptor.layout };
if ( !resolves.empty() && resolves.size() != colors.size() )
VK_VALIDATION_MESSAGE("Mismatching resolves count: Expecting " << colors.size() << ", got " << resolves.size());
passes.push_back(pass);
passes.emplace_back(pass);
}
size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descriptor, Attachment* attachment ) {
if ( this->views == 0 ) this->views = 1;
@ -180,7 +180,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
description.finalLayout = attachment.descriptor.layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : attachment.descriptor.layout;
description.flags = 0;
attachments.push_back(description);
attachments.emplace_back(description);
}
}
@ -208,7 +208,9 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
size_t i = 0;
// std::cout << this << ": " << std::endl;
#if 0
UF_MSG_DEBUG(this << ": ");
#endif
for ( auto& pass : passes ) {
VkSubpassDescription description;
// describe renderpass
@ -228,13 +230,12 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
break;
}
}
descriptions.push_back(description);
descriptions.emplace_back(description);
#if 0
UF_MSG_DEBUG("Pass: " << descriptions.size() - 1);
for ( auto& color : pass.colors ) UF_MSG_DEBUG("Color: " << color.attachment << "\t" << std::hex << color.layout << "\t" << this->attachments[color.attachment].image);
for ( auto& input : pass.inputs ) UF_MSG_DEBUG("Input: " << input.attachment << "\t" << std::hex << input.layout << "\t" << this->attachments[input.attachment].image);
std::cout << std::endl;
#endif
// transition dependency between subpasses
dependency.srcSubpass = dependency.dstSubpass;
@ -243,7 +244,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
dependency.dstSubpass = i++;
dependency.dstStageMask = pass.stage;
dependency.dstAccessMask = pass.access;
dependencies.push_back(dependency);
dependencies.emplace_back(dependency);
}
// dependency: transition to final
{
@ -253,7 +254,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies.push_back(dependency);
dependencies.emplace_back(dependency);
}
// depth dependency
@ -270,7 +271,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
dependency.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependencies.push_back(dependency);
dependencies.emplace_back(dependency);
}
{
VkSubpassDependency dependency;
@ -284,7 +285,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
dependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies.push_back(dependency);
dependencies.emplace_back(dependency);
}
#if 0
@ -293,7 +294,6 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
UF_MSG_DEBUG("\tStage: " << std::hex << dependency.srcStageMask << " -> " << std::hex << dependency.dstStageMask);
UF_MSG_DEBUG("\tAccess: " << std::hex << dependency.srcAccessMask << " -> " << std::hex << dependency.dstAccessMask);
}
std::cout << std::endl;
#endif
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
@ -327,7 +327,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
*/
VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass));
// std::cout << renderPass << ": " << attachments.size() << std::endl;
// UF_MSG_DEBUG(renderPass << ": " << attachments.size());
}
{
// destroy previous framebuffers
@ -340,8 +340,8 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
for ( size_t j = 0; j < this->views; ++j ) {
for ( auto& attachment : this->attachments ) {
if ( attachment.descriptor.aliased && attachment.descriptor.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ) {
attachmentViews.push_back(base.renderTarget.attachments[i].view);
} else attachmentViews.push_back(attachment.views[j]);
attachmentViews.emplace_back(base.renderTarget.attachments[i].view);
} else attachmentViews.emplace_back(attachment.views[j]);
}
}

View File

@ -41,6 +41,7 @@ bool ext::vulkan::settings::experimental::hdr = true;
bool ext::vulkan::settings::experimental::vxgi = true;
bool ext::vulkan::settings::experimental::deferredSampling = true;
bool ext::vulkan::settings::experimental::culling = false;
bool ext::vulkan::settings::experimental::bloom = false;
VkColorSpaceKHR ext::vulkan::settings::formats::colorSpace;
ext::vulkan::enums::Format::type_t ext::vulkan::settings::formats::color = ext::vulkan::enums::Format::R8G8B8A8_UNORM;

View File

@ -99,7 +99,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
renderMode.height = size.y;
}
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
metadata.deserialize(self, metadataJson);
});
metadata.deserialize(self, metadataJson);

View File

@ -121,7 +121,7 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
this->queueHook("discord.Activity.Update.%UID%", ext::json::null(), 1.0);
#endif
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
metadata.deserialize(self, metadataJson);
});
metadata.deserialize(self, metadataJson);

View File

@ -28,7 +28,7 @@ void ext::PlayerModelBehavior::initialize( uf::Object& self ) {
metadata.reference = &controllerTransform;
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
metadata.deserialize(self, metadataJson);
});
metadata.deserialize(self, metadataJson);

View File

@ -190,7 +190,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
}
#endif
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&]( ext::json::Value& json ){
metadata.deserialize(self, metadataJson);
});
metadata.deserialize(self, metadataJson);
@ -502,6 +502,7 @@ void ext::ExtSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serialize
serializer["light"]["specular"] = uf::vector::encode( /*this->*/light.specular );
serializer["light"]["exposure"] = /*this->*/light.exposure;
serializer["light"]["gamma"] = /*this->*/light.gamma;
serializer["light"]["brightnessThreshold"] = /*this->*/light.brightnessThreshold;
serializer["light"]["fog"]["color"] = uf::vector::encode( /*this->*/fog.color );
serializer["light"]["fog"]["step scale"] = /*this->*/fog.stepScale;
@ -518,26 +519,30 @@ void ext::ExtSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serialize
serializer["system"]["renderer"]["shader"]["parameters"] = uf::vector::encode( /*this->*/shader.parameters );
}
void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ) {
if ( !serializer["light"]["point light eye depth scale"].is<float>() )
serializer["light"]["point light eye depth scale"] = ext::config["engine"]["scenes"]["lights"]["point light eye depth scale"];
/*this->*/max.textures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<uint32_t>(/*this->*/max.textures2D);
/*this->*/max.texturesCube = ext::config["engine"]["scenes"]["textures"]["max"]["cube"].as<uint32_t>(/*this->*/max.texturesCube);
/*this->*/max.textures3D = ext::config["engine"]["scenes"]["textures"]["max"]["3D"].as<uint32_t>(/*this->*/max.textures3D);
/*this->*/max.lights = ext::config["engine"]["scenes"]["lights"]["max"].as<uint32_t>(/*this->*/max.lights);
/*this->*/light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>(true) && serializer["light"]["should"].as<bool>(true);
/*this->*/shadow.enabled = ext::config["engine"]["scenes"]["shadows"]["enabled"].as<bool>(true) && serializer["light"]["shadows"].as<bool>(true);
/*this->*/shadow.samples = ext::config["engine"]["scenes"]["shadows"]["samples"].as<uint32_t>();
/*this->*/shadow.max = ext::config["engine"]["scenes"]["shadows"]["max"].as<uint32_t>();
/*this->*/shadow.update = ext::config["engine"]["scenes"]["shadows"]["update"].as<uint32_t>();
/*this->*/shadow.experimentalMode = ext::config["engine"]["scenes"]["shadows"]["experimental mode"].as<uint32_t>(0);
/*this->*/light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>(true) && serializer["light"]["should"].as<bool>(true);
/*this->*/light.ambient = uf::vector::decode( serializer["light"]["ambient"], pod::Vector4f{ 1, 1, 1, 1 } );
/*this->*/light.specular = uf::vector::decode( serializer["light"]["specular"], pod::Vector4f{ 1, 1, 1, 1 } );
/*this->*/light.exposure = serializer["light"]["exposure"].as<float>(1.0f);
/*this->*/light.gamma = serializer["light"]["gamma"].as<float>(2.2f);
/*this->*/light.brightnessThreshold = serializer["light"]["brightnessThreshold"].as<float>(ext::config["engine"]["scenes"]["bloom"]["brightnessThreshold"].as<float>(1.0f));
UF_MSG_DEBUG( serializer["bloom"] );
/*this->*/bloom.scale = serializer["bloom"]["scale"].as(ext::config["engine"]["scenes"]["bloom"]["scale"].as(bloom.scale));
/*this->*/bloom.strength = serializer["bloom"]["strength"].as(ext::config["engine"]["scenes"]["bloom"]["strength"].as(bloom.strength));
/*this->*/bloom.sigma = serializer["bloom"]["sigma"].as(ext::config["engine"]["scenes"]["bloom"]["sigma"].as(bloom.sigma));
/*this->*/bloom.samples = serializer["bloom"]["samples"].as(ext::config["engine"]["scenes"]["bloom"]["samples"].as(bloom.samples));
/*this->*/fog.color = uf::vector::decode( serializer["light"]["fog"]["color"], pod::Vector3f{ 1, 1, 1 } );
/*this->*/fog.stepScale = serializer["light"]["fog"]["step scale"].as<float>();
@ -561,6 +566,39 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
#if UF_USE_OPENGL_FIXED_FUNCTION
uf::renderer::states::rebuild = true;
#endif
if ( uf::renderer::settings::experimental::bloom ) {
auto& renderMode = uf::renderer::getRenderMode("", true);
auto& blitter = *renderMode.getBlitters().front();
auto& shader = blitter.material.getShader("compute", "bloom");
struct UniformDescriptor {
float scale;
float strength;
float threshold;
float sigma;
float gamma;
float exposure;
uint32_t samples;
uint32_t padding;
};
UniformDescriptor uniforms = {
.scale = bloom.scale,
.strength = bloom.strength,
.threshold = light.brightnessThreshold,
.sigma = bloom.sigma,
.gamma = light.gamma,
.exposure = light.exposure,
.samples = bloom.samples,
};
UF_MSG_DEBUG( bloom.scale << " " << bloom.strength << " " << light.brightnessThreshold << " " << bloom.sigma << " " << light.gamma << " " << light.exposure << " " << bloom.samples );
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
}
}
void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string& renderModeName, bool isCompute ) {
@ -574,7 +612,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
auto& metadataJson = this->getComponent<uf::Serializer>();
auto& renderMode = uf::renderer::getRenderMode(renderModeName, true);
uf::stl::vector<uf::Graphic*> blitters = renderMode.getBlitters();
auto blitters = renderMode.getBlitters();
#if UF_USE_OPENGL
struct LightInfo {
@ -680,9 +718,14 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
alignas(4) float gamma;
alignas(4) float exposure;
alignas(4) float brightnessThreshold;
alignas(4) uint32_t msaa;
alignas(4) uint32_t shadowSamples;
alignas(4) uint32_t shadowSamples;
alignas(4) uint32_t indexSkybox;
alignas(4) uint32_t padding1;
alignas(4) uint32_t padding2;
alignas(4) uint32_t padding3;
};
// struct that contains our skybox cubemap, noise texture, and VXGI voxels
@ -774,8 +817,10 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
uniforms.gamma = metadata.light.gamma;
uniforms.exposure = metadata.light.exposure;
uniforms.brightnessThreshold = metadata.light.brightnessThreshold;
uniforms.msaa = ext::vulkan::settings::msaa;
uniforms.shadowSamples = std::min( 0, metadata.shadow.samples );
uniforms.indexSkybox = indexSkybox;
}

View File

@ -24,7 +24,14 @@ namespace ext {
pod::Vector4f specular = {1,1,1,1};
float exposure = 1.0f;
float gamma = 1.0f;
float brightnessThreshold = 1.0f;
} light;
struct {
float scale = 1.0f;
float strength = 1.0f;
float sigma = 0.8f;
uint32_t samples = 1;
} bloom;
struct {
bool enabled = true;
int samples = 4;

View File

@ -426,7 +426,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<ext::GuiBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
metadata.deserialize(self, metadataJson);
});
metadata.deserialize(self, metadataJson);
@ -570,7 +570,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
});
auto& metadataGlyph = this->getComponent<ext::GuiBehavior::GlyphMetadata>();
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
metadataGlyph.deserialize(self, metadataJson);
});
// metadataGlyph.deserialize(self, metadataJson);

View File

@ -84,7 +84,7 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
}
});
this->addHook( "object:UpdateMetadata.%UID%", [&](){
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
metadata.deserialize(self, metadataJson);
});
metadata.deserialize(self, metadataJson);

View File

@ -354,6 +354,7 @@ void EXT_API ext::initialize() {
uf::renderer::settings::experimental::vxgi = ::config["engine"]["ext"][RENDERER]["experimental"]["vxgi"].as( uf::renderer::settings::experimental::vxgi );
uf::renderer::settings::experimental::deferredSampling = ::config["engine"]["ext"][RENDERER]["experimental"]["deferred sampling"].as( uf::renderer::settings::experimental::deferredSampling );
uf::renderer::settings::experimental::culling = ::config["engine"]["ext"][RENDERER]["experimental"]["culling"].as( uf::renderer::settings::experimental::culling );
uf::renderer::settings::experimental::bloom = ::config["engine"]["ext"][RENDERER]["experimental"]["bloom"].as( uf::renderer::settings::experimental::bloom );
#define JSON_TO_VKFORMAT( key ) if ( ::config["engine"]["ext"][RENDERER]["formats"][#key].is<uf::stl::string>() ) {\
uf::stl::string format = ::config["engine"]["ext"][RENDERER]["formats"][#key].as<uf::stl::string>();\
format = uf::string::replace( uf::string::uppercase(format), " ", "_" );\