Commit for 2022.07.31 00-20-46.7z

This commit is contained in:
mrq 2022-07-31 00:20:00 -05:00
parent ae28b31d02
commit 212347ee9c
59 changed files with 921 additions and 1087 deletions

View File

@ -6,12 +6,12 @@
"meshes": { "interleaved": false },
"lights": { "enabled": true,
"useLightmaps": false,
"max": 8,
"max": 48,
"shadows": {
"enabled": true,
"update": 2,
"max": 4,
"samples": 1
"update": 4,
"max": 24,
"samples": 16
},
"bloom": {
"scale": 1.0,
@ -71,7 +71,10 @@
"0x7d560045", // VUID-vkCmdPipelineBarrier-dstStageMask-06462 (false positive, pipeline barrier for BLAS)
"0xde55a405", // VUID-VkDescriptorImageInfo-imageLayout-00344 (bitches because )
"0x9410d614" // VUID-vkCmdDrawIndexedIndirect-None-02699 (same as above)
"0x9410d614", // VUID-vkCmdDrawIndexedIndirect-None-02699 (same as above)
"0x97c889fd", // VUID-VkBufferDeviceAddressInfo-buffer-02601 (false positive, lies about not setting flags when I explicitly set flags for scratch)
"0xea5edaf3" // VUID-vkCmdBuildAccelerationStructuresKHR-pInfos-03674 (same as above)
// "0x9cacd67a" // UNASSIGNED-CoreValidation-DrawState-QueryNotReset (false positive)
@ -90,7 +93,7 @@
// "size": 0.25
// "size": 0.50
// "size": 0.75
"size": 0.5
"size": 1
// "size": [ 640, 480, "NEAREST" ]
// "size": [ 1280, 720 ]
// "size": [ 960, 540 ]
@ -109,10 +112,10 @@
"hdr": false,
"vxgi": false,
"culling": true,
"bloom": false,
"bloom": true,
"rt": false,
"postProcess": false,
"fsr": true
"fsr": false
},
"formats": {
"depth": "D32_SFLOAT",

View File

@ -11,7 +11,7 @@
"mass": 10,
"type": "bounding box",
"recenter": false
"recenter": true
}
}
}

View File

@ -39,15 +39,30 @@
"ambient": [ 0.0, 0.0, 0.0 ],
// "ambient": [ 0.1, 0.1, 0.2 ],
"exposure": 0.25,
"exposure": 0.125,
"gamma": 2.2,
"brightnessThreshold": 1.2,
"bloom": {
"threshold": 1.0,
"scale": 1.0,
"strength": 0.125,
"sigma": 0.8,
"samples": 5
"strength": 0.25,
"sigma": 1.0,
"samples": 4
},
"fog": {
// "color": [ 0.1, 0.1, 0.1 ],
// "color": [ 0.2, 0.2, 0.2 ],
"color": [ 0.3, 0.3, 0.3 ],
"range": [ 64, 256 ],
"step scale": 4,
"absorbtion": 0.0125,
"density": {
"threshold": 0.35,
"multiplier": 2.0,
"scale": 25.0,
"offset": [0.2, 0, 1],
"timescale": 32
}
},
"shadows": {
"enabled": true

View File

@ -6,31 +6,22 @@
],
"metadata": {
"light": {
// "ambient": [ 0, 0, 0 ],
"ambient": [ 0, 0, 0 ],
// "ambient": [ 0.05, 0.05, 0.05 ],
"ambient": [ 0.15, 0.15, 0.15 ],
// "ambient": [ 0.15, 0.15, 0.15 ],
// "ambient": [ 0.5, 0.5, 0.5 ],
// "ambient": [ 0.8, 0.8, 0.8 ],
// "ambient": [ 0.1, 0.1, 0.2 ],
"exposure": 0.125,
"gamma": 2.2,
"brightnessThreshold": 1.2,
"fog-": {
// "color": [ 0.1, 0.1, 0.1 ],
// "color": [ 0.2, 0.2, 0.2 ],
"color": [ 0.3, 0.3, 0.3 ],
"range": [ 64, 256 ],
"step scale": 4,
"absorbtion": 0.0125,
"density": {
"threshold": 0.35,
"multiplier": 2.0,
"scale": 25.0,
"offset": [0.2, 0, 1],
"timescale": 32
}
"bloom": {
"threshold": 1.2,
"scale": 1.0,
"strength": 1,
"sigma": 1.0,
"samples": 4
}
}
}

View File

@ -1,6 +1,6 @@
{
// "import": "./rp_downtown_v2.json"
// "import": "./ss2_medsci1.json"
"import": "./ss2_medsci1.json"
// "import": "./sh2_mcdonalds.json"
"import": "./gm_construct.json"
// "import": "./gm_construct.json"
}

View File

@ -27,6 +27,21 @@ float rnd(inout uint prev) { return (float(lcg(prev)) / float(0x01000000)); }
uint prngSeed;
float rnd() { return rnd(prngSeed); }
//
float shadowFactor( const Light light, float def );
float ndfGGX(float cosLh, float roughness) {
const float alpha = roughness * roughness;
const float alphaSq = alpha * alpha;
const float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom);
}
float gaSchlickG1(float cosTheta, float k) { return cosTheta / (cosTheta * (1.0 - k) + k); }
float gaSchlickGGX(float cosLi, float cosLo, float roughness) {
const float r = roughness + 1.0;
const float k = (r * r) / 8.0;
return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k);
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); }
//
void tangentBitangent(in vec3 N, out vec3 Nt, out vec3 Nb) {
if(abs(N.x) > abs(N.y)) Nt = vec3(N.z, 0, -N.x) / sqrt(N.x * N.x + N.z * N.z);
else Nt = vec3(0, -N.z, N.y) / sqrt(N.y * N.y + N.z * N.z);
@ -53,16 +68,6 @@ vec3 samplingHemisphere(inout uint seed, in vec3 z) {
return direction;
}
//
#if BUFFER_REFERENCE
uint64_t uvec2uint64( uvec2 src ) {
uint64_t dst;
dst = (src.x << 32) | src.y;
return dst;
}
#endif
//
float max3( vec3 v ) { return max(max(v.x, v.y), v.z); }
float min3( vec3 v ) { return min(min(v.x, v.y), v.z); }
uint biasedRound( float x, float bias ) { return uint( ( x < bias ) ? floor(x) : ceil(x)); }
@ -109,15 +114,12 @@ vec3 decodeSrgb(vec3 rgb) {
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
}
#if MAX_CUBEMAPS
bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < CUBEMAPS;
return 0 <= textureIndex && textureIndex < MAX_CUBEMAPS;
}
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE)
#if !NO_NONUNIFORM_EXT
#extension GL_EXT_nonuniform_qualifier : enable
#endif
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE)
bool validTextureIndex( uint id ) {
return 0 <= id && id < MAX_TEXTURES;
}
@ -262,44 +264,53 @@ void populateSurfaceMaterial() {
surface.normal.eye = normalize(vec3( ubo.eyes[surface.pass].view * vec4(surface.normal.world, 0.0) ));
}
}
bool isValidAddress( uint64_t address ) {
#if UINT64_ENABLED
return bool(address);
#else
return bool(address.x) && bool(address.y);
#endif
}
void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
Triangle triangle;
Vertex points[3];
if ( 0 < instanceAddresses.vertex ) {
if ( isValidAddress(instanceAddresses.vertex) ) {
Vertices vertices = Vertices(nonuniformEXT(instanceAddresses.vertex));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_] = vertices.v[/*triangle.*/indices[_]];
} else {
if ( 0 < instanceAddresses.position ) {
if ( isValidAddress(instanceAddresses.position) ) {
VPos buf = VPos(nonuniformEXT(instanceAddresses.position));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].position = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.uv ) {
if ( isValidAddress(instanceAddresses.uv) ) {
VUv buf = VUv(nonuniformEXT(instanceAddresses.uv));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].uv = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.st ) {
if ( isValidAddress(instanceAddresses.st) ) {
VSt buf = VSt(nonuniformEXT(instanceAddresses.st));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].st = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.normal ) {
if ( isValidAddress(instanceAddresses.normal) ) {
VNormal buf = VNormal(nonuniformEXT(instanceAddresses.normal));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].normal = buf.v[/*triangle.*/indices[_]];
}
if ( 0 < instanceAddresses.tangent ) {
if ( isValidAddress(instanceAddresses.tangent) ) {
VTangent buf = VTangent(nonuniformEXT(instanceAddresses.tangent));
#pragma unroll 3
for ( uint _ = 0; _ < 3; ++_ ) /*triangle.*/points[_].tangent = buf.v[/*triangle.*/indices[_]];
}
}
#if FETCH_BARYCENTRIC
#if BARYCENTRIC_CALCULATE
{
const vec3 p = vec3(inverse( surface.instance.model ) * vec4(surface.position.world, 1));
@ -341,7 +352,7 @@ void populateSurface( InstanceAddresses instanceAddresses, uvec3 indices ) {
}
// bind position
#if !FETCH_BARYCENTRIC
#if 1 || BARYCENTRIC_CALCULATE
{
surface.position.world = vec3( surface.instance.model * vec4(triangle.point.position, 1.0 ) );
surface.position.eye = vec3( ubo.eyes[surface.pass].view * vec4(surface.position.world, 1.0) );
@ -368,7 +379,7 @@ void populateSurface( uint instanceID, uint primitiveID ) {
surface.instance = instances[instanceID];
const InstanceAddresses instanceAddresses = instanceAddresses[instanceID];
if ( !(0 < instanceAddresses.index) ) return;
if ( !isValidAddress(instanceAddresses.index) ) return;
const DrawCommand drawCommand = Indirects(nonuniformEXT(instanceAddresses.indirect)).dc[instanceAddresses.drawID];
const uint triangleID = primitiveID + (drawCommand.indexID / 3);
uvec3 indices = Indices(nonuniformEXT(instanceAddresses.index)).i[triangleID];

View File

@ -3,12 +3,19 @@
// enable if shaderNonUniform is not supported
// Nvidia hardware does not require nonuniformEXT, but AMD does
#endif
// implicit variables
#ifndef MULTISAMPLING
#define MULTISAMPLING 1
#endif
#ifndef MAX_MSAA_SAMPLES
#define MAX_MSAA_SAMPLES 16
#endif
#ifndef MAX_TEXTURES
#define MAX_TEXTURES TEXTURES
#endif
// implicit shader settings
#ifndef CAN_DISCARD
#define CAN_DISCARD 1
#endif
@ -19,16 +26,14 @@
#define VXGI_NDC 1
#define VXGI_SHADOWS 0
#endif
#ifndef MAX_TEXTURES
#define MAX_TEXTURES TEXTURES
#endif
/*
#ifndef FOG
#define FOG 1
#endif
#ifndef FOG_RAY_MARCH
#define FOG_RAY_MARCH 1
#endif
#ifndef WHITENOISE
#define WHITENOISE 1
#endif
@ -38,28 +43,46 @@
#ifndef TONE_MAP
#define TONE_MAP 1
#endif
#ifndef PHONG
#define PHONG 0
#endif
#ifndef LAMBERT
#define LAMBERT 0
#endif
#ifndef PBR
#define PBR 1
#endif
*/
#if NO_NONUNIFORM_EXT
#define nonuniformEXT(X) X
#else
#extension GL_EXT_nonuniform_qualifier : enable
#endif
#ifndef BUFFER_REFERENCE
#define BUFFER_REFERENCE 1
#else
#define UINT64_ENABLED 1
#if !UINT64_ENABLED
#define uint64_t uvec2
#endif
// easy and accessible in one place
#ifndef BARYCENTRIC
#define BARYCENTRIC 1
#endif
#if BARYCENTRIC
#ifndef BARYCENTRIC_CALCULATE
#define BARYCENTRIC_CALCULATE 1
#endif
#endif
#if BUFFER_REFERENCE
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
#extension GL_EXT_scalar_block_layout : enable
#extension GL_EXT_buffer_reference : enable
#extension GL_EXT_buffer_reference2 : enable
#extension GL_EXT_scalar_block_layout : enable
#if UINT64_ENABLED
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : enable
#else
#extension GL_EXT_buffer_reference_uvec2 : enable
#endif
#endif
const float PI = 3.14159265359;

View File

@ -1,19 +1,4 @@
// PBR
float shadowFactor( const Light light, float def );
float ndfGGX(float cosLh, float roughness) {
const float alpha = roughness * roughness;
const float alphaSq = alpha * alpha;
const float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
return alphaSq / (PI * denom * denom);
}
float gaSchlickG1(float cosTheta, float k) { return cosTheta / (cosTheta * (1.0 - k) + k); }
float gaSchlickGGX(float cosLi, float cosLo, float roughness) {
const float r = roughness + 1.0;
const float k = (r * r) / 8.0;
return gaSchlickG1(cosLi, k) * gaSchlickG1(cosLo, k);
}
vec3 fresnelSchlick(vec3 F0, float cosTheta) { return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); }
#if (!BAKING && !COMPUTE) || RAYTRACE || DEFERRED
void pbr() {
if ( surface.material.lightmapped ) return;
@ -52,5 +37,4 @@ void pbr() {
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
surface.light.a += light.power * La * Ls;
}
}
#endif
}

View File

@ -119,7 +119,6 @@ struct Instance {
// InstanceAddresses addresses;
};
#if UINT64_ENABLED
struct InstanceAddresses {
uint64_t vertex;
uint64_t index;
@ -143,31 +142,6 @@ struct InstanceAddresses {
uint64_t id;
uint64_t padding1;
};
#else
struct InstanceAddresses {
uvec2 vertex;
uvec2 index;
uvec2 indirect;
uint drawID;
uint padding0;
uvec2 position;
uvec2 uv;
uvec2 color;
uvec2 st;
uvec2 normal;
uvec2 tangent;
uvec2 joints;
uvec2 weights;
uvec2 id;
uvec2 padding1;
};
#endif
struct SurfaceMaterial {
vec4 albedo;
@ -250,8 +224,8 @@ struct SettingsFog {
};
struct SettingsBloom {
float exposure;
float brightnessThreshold;
float gamma;
float threshold;
uint padding;
};
struct SettingsVxgi {

View File

@ -8,19 +8,14 @@
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define COMPUTE 1
#define TONE_MAP 0
#define GAMMA_CORRECT 0
#define DEFERRED 1
#define MAX_TEXTURES TEXTURES
#define WHITENOISE 0
#define DEFERRED_SAMPLING 1
#define PBR 1
#define BUFFER_REFERENCE 1
#define DEFERRED_SAMPLING 1
#define FETCH_BARYCENTRIC 0
#define EXTENDED_ATTRIBUTES 0
//#define TEXTURE_WORKAROUND 0
#define UINT64_ENABLED 1
#include "../../common/macros.h"
#include "../../../common/macros.h"
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
@ -30,20 +25,24 @@ layout (constant_id = 1) const uint CUBEMAPS = 128;
#if !MULTISAMPLING
layout(binding = 0) uniform utexture2D samplerId;
#if EXTENDED_ATTRIBUTES
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
layout(binding = 1) uniform texture2D samplerBary;
#endif
#else
layout(binding = 1) uniform texture2D samplerUv;
layout(binding = 2) uniform texture2D samplerNormal;
#else
layout(binding = 1) uniform texture2D samplerBary;
#endif
layout(binding = 3) uniform texture2D samplerDepth;
#else
layout(binding = 0) uniform utexture2DMS samplerId;
#if EXTENDED_ATTRIBUTES
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
layout(binding = 1) uniform texture2DMS samplerBary;
#endif
#else
layout(binding = 1) uniform texture2DMS samplerUv;
layout(binding = 2) uniform texture2DMS samplerNormal;
#else
layout(binding = 1) uniform texture2DMS samplerBary;
#endif
layout(binding = 3) uniform texture2DMS samplerDepth;
#endif
@ -58,7 +57,7 @@ layout( push_constant ) uniform PushBlock {
uint draw;
} PushConstant;
#include "../../common/structs.h"
#include "../../../common/structs.h"
layout (binding = 10) uniform UBO {
EyeMatrices eyes[2];
@ -110,12 +109,12 @@ layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
#include "../../common/functions.h"
#include "../../common/fog.h"
#include "../../common/light.h"
#include "../../common/shadows.h"
#include "../../../common/functions.h"
#include "../../../common/fog.h"
#include "../../../common/light.h"
#include "../../../common/shadows.h"
#if VXGI
#include "../../common/vxgi.h"
#include "../../../common/vxgi.h"
#endif
#if MULTISAMPLING
@ -128,7 +127,7 @@ layout(buffer_reference, scalar) buffer VID { uint v[]; };
void postProcess() {
float brightness = dot(surface.fragment.rgb, vec3(0.2126, 0.7152, 0.0722));
vec4 outFragBright = brightness > ubo.settings.bloom.brightnessThreshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
vec4 outFragBright = brightness > ubo.settings.bloom.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
vec2 outFragMotion = surface.motion;
#if FOG
@ -151,13 +150,14 @@ void postProcess() {
}
void populateSurface() {
if ( gl_GlobalInvocationID.x >= imageSize(imageColor).x|| gl_GlobalInvocationID.y >= imageSize(imageColor).y ) return;
uvec2 renderSize = imageSize(imageColor);
if ( gl_GlobalInvocationID.x >= renderSize.x|| gl_GlobalInvocationID.y >= renderSize.y ) return;
surface.fragment = vec4(0);
surface.pass = PushConstant.pass;
{
vec2 inUv = (vec2(gl_GlobalInvocationID.xy) / imageSize(imageColor)) * 2.0f - 1.0f;
vec2 inUv = (vec2(gl_GlobalInvocationID.xy) / vec2(renderSize)) * 2.0f - 1.0f;
const mat4 iProjectionView = inverse( ubo.eyes[surface.pass].projection * mat4(mat3(ubo.eyes[surface.pass].view)) );
const vec4 near4 = iProjectionView * (vec4(inUv, -1.0, 1.0));
const vec4 far4 = iProjectionView * (vec4(inUv, 1.0, 1.0));
@ -168,10 +168,12 @@ void populateSurface() {
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz;
const float depth = IMAGE_LOAD(samplerDepth).r;
vec4 positionEye = ubo.eyes[surface.pass].iProjection * vec4(inUv, depth, 1.0);
positionEye /= positionEye.w;
surface.position.eye = positionEye.xyz;
surface.position.world = vec3( ubo.eyes[surface.pass].iView * positionEye );
vec4 eye = ubo.eyes[surface.pass].iProjection * vec4(inUv, depth, 1.0);
eye /= eye.w;
surface.position.eye = eye.xyz;
surface.position.world = vec3( ubo.eyes[surface.pass].iView * eye );
}
#if !MULTISAMPLING
@ -193,7 +195,12 @@ void populateSurface() {
const uint instanceID = ID.y - 1;
surface.subID = 1;
#if EXTENDED_ATTRIBUTES
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
surface.barycentric = decodeBarycentrics(IMAGE_LOAD(samplerBary).xy).xyz;
#endif
populateSurface( instanceID, triangleID );
#else
vec4 uvst = IMAGE_LOAD(samplerUv);
vec4 normaltangent = IMAGE_LOAD(samplerNormal);
@ -210,9 +217,6 @@ void populateSurface() {
surface.instance = instances[instanceID];
populateSurfaceMaterial();
#else
surface.barycentric = decodeBarycentrics(IMAGE_LOAD(samplerBary).xy).xyz;
populateSurface( instanceID, triangleID );
#endif
}

View File

@ -6,11 +6,11 @@
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
#define LAMBERT 0
#define PBR 1
#define VXGI 1
#define COMPUTE 1
#define VXGI 1
#define MAX_CUBEMAPS CUBEMAPS
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CUBEMAPS = 128;
layout (constant_id = 2) const uint CASCADES = 16;
@ -58,7 +58,7 @@ layout (binding = 11, rg16f) uniform volatile coherent image3D voxelNormal[CASCA
#include "../../common/light.h"
#undef VXGI
#include "../../common/shadows.h"
#define PBR 1
void main() {
const vec3 tUvw = gl_GlobalInvocationID.xzy;
for ( uint CASCADE = 0; CASCADE < CASCADES; ++CASCADE ) {

View File

@ -13,8 +13,6 @@ layout (binding = 6) uniform samplerCube samplerCubemaps[CUBEMAPS];
#define SHADOW_SAMPLES 16
#define FRAGMENT 1
#define BAKING 1
#define PBR 1
#define LAMBERT 0
#include "../../common/macros.h"
#include "../../common/structs.h"
@ -42,9 +40,8 @@ layout (binding = 13, rgba8) uniform volatile coherent image3D outAlbedos;
#include "../../common/functions.h"
#include "../../common/shadows.h"
#if PBR
#include "../../common/pbr.h"
#endif
#define PBR 1
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;

View File

@ -5,6 +5,5 @@
#define SKINNED 0
#define BAKING 1
#define LAYERED 1
#define EXTRA_ATTRIBUTES 1
#include "../base/vert.h"

View File

@ -3,30 +3,23 @@
//#extension GL_EXT_nonuniform_qualifier : enable
#define QUERY_MIPMAP 0
#define CUBEMAPS 1
#define FRAGMENT 1
#define CAN_DISCARD 1
#define EXTENDED_ATTRIBUTES 0
#if !EXTENDED_ATTRIBUTES
#define STABILIZE_BARY 1
#define BARYCENTRIC 1
#endif
// #define MAX_TEXTURES TEXTURES
#define MAX_TEXTURES textures.length()
#if BARYCENTRIC
#extension GL_EXT_fragment_shader_barycentric : enable
#extension GL_AMD_shader_explicit_vertex_parameter : enable
#endif
layout (constant_id = 0) const uint TEXTURES = 1;
#include "../../common/macros.h"
#include "../../common/structs.h"
#if BARYCENTRIC && !BARYCENTRIC_CALCULATE
#define BARYCENTRIC_STABILIZE 1
#extension GL_EXT_fragment_shader_barycentric : enable
#extension GL_AMD_shader_explicit_vertex_parameter : enable
#endif
layout (binding = 5) uniform sampler2D samplerTextures[TEXTURES];
layout (std140, binding = 6) readonly buffer DrawCommands {
DrawCommand drawCommands[];
@ -51,10 +44,10 @@ layout (std140, binding = 11) readonly buffer Lights {
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
#if STABILIZE_BARY
layout (location = 2) __explicitInterpAMD in vec4 inPOS1;
#if BARYCENTRIC_STABILIZE
layout (location = 2) __explicitInterpAMD in vec4 inPOS1;
#else
layout (location = 2) in vec4 inPOS1;
layout (location = 2) in vec4 inPOS1;
#endif
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
@ -64,11 +57,11 @@ layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
layout (location = 0) out uvec2 outId;
#if EXTENDED_ATTRIBUTES
layout (location = 1) out vec4 outUv;
layout (location = 2) out vec4 outNormal;
#if BARYCENTRIC
layout (location = 1) out vec2 outBary;
#else
layout (location = 1) out vec2 outBary;
layout (location = 1) out vec4 outUv;
layout (location = 2) out vec4 outNormal;
#endif
void main() {
@ -105,7 +98,7 @@ void main() {
}
if ( A.a < 0.0001 ) discard;
#if EXTENDED_ATTRIBUTES
#if !BARYCENTRIC
outUv = vec4(surface.uv, surface.st);
outNormal = vec4( encodeNormals(inNormal), encodeNormals(inTangent) );
#endif
@ -114,8 +107,8 @@ void main() {
outId = uvec2(triangleID + 1, instanceID + 1);
#if BARYCENTRIC
#if STABILIZE_BARY
#if BARYCENTRIC && !BARYCENTRIC_CALCULATE
#if BARYCENTRIC_STABILIZE
vec4 v0 = interpolateAtVertexAMD(inPOS1, 0);
vec4 v1 = interpolateAtVertexAMD(inPOS1, 1);
vec4 v2 = interpolateAtVertexAMD(inPOS1, 2);

View File

@ -4,8 +4,6 @@ layout (constant_id = 0) const uint PASSES = 6;
#extension GL_ARB_shader_viewport_layer_array : enable
#endif
#define EXTRA_ATTRIBUTES 1
#include "../../common/macros.h"
#include "../../common/structs.h"
@ -47,14 +45,12 @@ layout (std140, binding = 2) readonly buffer Instances {
layout (location = 0) out uvec4 outId;
layout (location = 1) flat out vec4 outPOS0;
layout (location = 2) out vec4 outPOS1;
#if EXTRA_ATTRIBUTES
layout (location = 3) out vec3 outPosition;
layout (location = 4) out vec2 outUv;
layout (location = 5) out vec4 outColor;
layout (location = 6) out vec2 outSt;
layout (location = 7) out vec3 outNormal;
layout (location = 8) out vec3 outTangent;
#endif
layout (location = 3) out vec3 outPosition;
layout (location = 4) out vec2 outUv;
layout (location = 5) out vec4 outColor;
layout (location = 6) out vec2 outSt;
layout (location = 7) out vec3 outNormal;
layout (location = 8) out vec3 outTangent;
vec4 snap(vec4 vertex, vec2 resolution) {
vec4 snappedPos = vertex;
@ -98,12 +94,10 @@ void main() {
outId = uvec4(triangleID, drawID, instanceID, PushConstant.pass);
#if EXTRA_ATTRIBUTES
outPosition = vec3(model * vec4(inPos.xyz, 1.0));
outUv = inUv;
outSt = inSt;
outColor = inColor * instance.color;
outNormal = normalize(vec3(model * vec4(inNormal.xyz, 0.0)));
outTangent = normalize(vec3(view * model * vec4(inTangent.xyz, 0.0)));
#endif
}

View File

@ -1,11 +1,9 @@
#version 450
#pragma shader_stage(fragment)
#define EXTRA_ATTRIBUTES 1
#define FRAGMENT 1
#define CUBEMAPS 1
// #define MAX_TEXTURES TEXTURES
#define MAX_TEXTURES textures.length()
layout (constant_id = 0) const uint TEXTURES = 1;
#include "../../common/macros.h"
@ -36,14 +34,12 @@ layout (std140, binding = 11) readonly buffer Lights {
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
layout (location = 2) in vec4 inPOS1;
#if EXTRA_ATTRIBUTES
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
#endif
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
void main() {
const uint triangleID = uint(inId.x); // gl_PrimitiveID

View File

@ -1,13 +1,15 @@
#version 450
#pragma shader_stage(fragment)
//#extension GL_EXT_nonuniform_qualifier : enable
#define DEFERRED_SAMPLING 0
// to-do: convert to use functions.h surface population functions
#define FRAGMENT 1
#define DEFERRED_SAMPLING 0
#define CUBEMAPS 1
#define BLEND 1
#define DEPTH_TEST 0
#define CUBEMAPS 1
#define TEXTURE_WORKAROUND 1
#define USE_LIGHTMAP 1
layout (constant_id = 0) const uint TEXTURES = 512;
layout (constant_id = 1) const uint CASCADES = 16;
@ -50,14 +52,12 @@ layout (binding = 13, rg16f) uniform volatile coherent image3D voxelNormal[CASCA
layout (location = 0) flat in uvec4 inId;
layout (location = 1) flat in vec4 inPOS0;
layout (location = 2) in vec4 inPOS1;
#if 1 || EXTRA_ATTRIBUTES
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
#endif
layout (location = 3) in vec3 inPosition;
layout (location = 4) in vec2 inUv;
layout (location = 5) in vec4 inColor;
layout (location = 6) in vec2 inSt;
layout (location = 7) in vec3 inNormal;
layout (location = 8) in vec3 inTangent;
#include "../../common/functions.h"
@ -103,7 +103,7 @@ void main() {
}
if ( A.a == 0 ) discard;
#if USE_LIGHTMAP && !DEFERRED_SAMPLING
#if USE_LIGHTMAP
if ( validTextureIndex( instance.lightmapID ) ) {
A.rgb *= sampleTexture( instance.lightmapID, inSt ).rgb;
}

View File

@ -23,18 +23,15 @@ layout (binding = 0) uniform UBO {
layout (location = 0) out vec2 outUv;
layout (location = 1) out flat Gui outGui;
#if GLYPH
layout (location = 7) out flat Glyph outGlyph;
#endif
#if 0
out gl_PerVertex {
vec4 gl_Position;
};
layout (location = 7) out flat Glyph outGlyph;
#endif
void main() {
outUv = inUv;
outGui = ubo.gui;
#if GLYPH
outGlyph = ubo.glyph;
#endif
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(inPos.xy, ubo.gui.depth, 1.0);
}

View File

@ -9,18 +9,19 @@ layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 8;
layout (constant_id = 3) const uint CASCADES = 1;
// shader type settings
#define RT 1
#define COMPUTE 1
#define PBR 1
#define VXGI 0
#define RAYTRACE 1
#define BUFFER_REFERENCE 1
#define FOG 1
#define BLOOM 0
#define WHITENOISE 0
#define MAX_TEXTURES TEXTURES
#define TONE_MAP 0
#define GAMMA_CORRECT 0
#define DEFERRED_SAMPLING 1
#define BUFFER_REFERENCE 1
#define UINT64_ENABLED 1
#define PBR 1
// shader function settings
#define FOG 1
//force it off
#define BARYCENTRIC 0
#define BARYCENTRIC_CALCULATE 0
#include "../common/macros.h"
#include "../common/structs.h"
@ -377,7 +378,8 @@ void main() {
{
#if BLOOM
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);
vec4 outFragBright = brightness > ubo.threshold ? vec4(surface.fragment.rgb, 1.0) : vec4(0, 0, 0, 1);
imageStore(outImage, ivec2(gl_LaunchIDEXT.xy), outFragBright);
#endif
#if FOG
fog( surface.ray, surface.fragment.rgb, surface.fragment.a );

View File

@ -9,33 +9,12 @@ layout (constant_id = 0) const uint PASSES = 2;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 128;
#define BUFFER_REFERENCE 1
#define RT 1
#define COMPUTE 1
#define PBR 1
#define RAYTRACE 1
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"
/*
layout (std140, binding = 10) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
layout(buffer_reference, scalar) buffer Indices { uvec3 i[]; };
layout(buffer_reference, scalar) buffer Indirects { DrawCommand dc[]; };
layout(buffer_reference, scalar) buffer VPos { vec3 v[]; };
layout(buffer_reference, scalar) buffer VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
*/
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;

View File

@ -7,32 +7,12 @@ layout (constant_id = 0) const uint PASSES = 2;
layout (constant_id = 1) const uint TEXTURES = 512;
layout (constant_id = 2) const uint CUBEMAPS = 128;
#define BUFFER_REFERENCE 1
#define RT 1
#define COMPUTE 1
#define PBR 1
#define RAYTRACE 1
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"
/*
layout (std140, binding = 9) readonly buffer InstanceAddresseses {
InstanceAddresses instanceAddresses[];
};
layout(buffer_reference, scalar) buffer Vertices { Vertex v[]; };
layout(buffer_reference, scalar) buffer Indices { uvec3 i[]; };
layout(buffer_reference, scalar) buffer Indirects { DrawCommand dc[]; };
layout(buffer_reference, scalar) buffer VPos { vec3 v[]; };
layout(buffer_reference, scalar) buffer VUv { vec2 v[]; };
layout(buffer_reference, scalar) buffer VColor { uint v[]; };
layout(buffer_reference, scalar) buffer VSt { vec2 v[]; };
layout(buffer_reference, scalar) buffer VNormal { vec3 v[]; };
layout(buffer_reference, scalar) buffer VTangent { vec3 v[]; };
layout(buffer_reference, scalar) buffer VID { uint v[]; };
*/
layout(location = 0) rayPayloadInEXT RayTracePayload payload;
hitAttributeEXT vec2 attribs;

View File

@ -2,11 +2,8 @@
#extension GL_EXT_ray_tracing : enable
#pragma shader_stage(miss)
#define BUFFER_REFERENCE 1
#define RT 1
#define COMPUTE 1
#define PBR 1
#define RAYTRACE 1
#define MAX_TEXTURES TEXTURES
#include "../common/macros.h"
#include "../common/structs.h"

View File

@ -79,87 +79,4 @@ namespace ext {
}
}
template<typename T>
uf::stl::vector<T> ext::json::vector( const ext::json::Value& value ) {
uf::stl::vector<T> res;
res.reserve( value.size() );
ext::json::forEach( value, [&]( const ext::json::Value& value ){
res.emplace_back( value.as<T>() );
});
return res;
}
template<typename T>
T& ext::json::encode( const ext::json::Value& json, T& output, const ext::json::EncodingSettings& settings ) {
// ext::json::Value json = ext::json::reencode( _json, settings );
#define UF_JSON_PARSE_ENCODING(ENC)\
if ( settings.encoding == #ENC ) {\
auto buffer = nlohmann::json::to_ ## ENC( (const ext::json::base_value&) (json) );\
output = T( buffer.begin(), buffer.end() );\
}
if ( settings.encoding == "" || settings.encoding == "json" ) {
output = settings.pretty ? json.dump(1, '\t') : json.dump();
}
else UF_JSON_PARSE_ENCODING(bson)
else UF_JSON_PARSE_ENCODING(cbor)
else UF_JSON_PARSE_ENCODING(msgpack)
else UF_JSON_PARSE_ENCODING(ubjson)
else UF_JSON_PARSE_ENCODING(bjdata)
#if UF_USE_TOML
else if ( settings.encoding == "toml" ) {
uf::stl::string buffer = ext::toml::fromJson( json.dump() );
output = T( buffer.begin(), buffer.end() );
}
#endif
else {
// should probably default to json, not my problem
UF_MSG_ERROR("invalid encoding requested: {}", settings.encoding);
}
return output;
#undef UF_JSON_PARSE_ENCODING
}
template<typename T>
ext::json::Value& ext::json::decode( ext::json::Value& json, const T& input, const DecodingSettings& settings ) {
#define UF_JSON_PARSE_ENCODING(ENC)\
if ( settings.encoding == #ENC ) {\
json = nlohmann::json::from_ ## ENC(input, strict, exceptions);\
}
constexpr bool comments = true;
constexpr bool strict = true;
constexpr bool exceptions = true;
#if UF_EXCEPTIONS
try {
#endif
if ( settings.encoding == "" || settings.encoding == "json" ) {
json = nlohmann::json::parse(input, nullptr, exceptions, comments);
}
else UF_JSON_PARSE_ENCODING(bson)
else UF_JSON_PARSE_ENCODING(cbor)
else UF_JSON_PARSE_ENCODING(msgpack)
else UF_JSON_PARSE_ENCODING(ubjson)
else UF_JSON_PARSE_ENCODING(bjdata)
#if UF_USE_TOML
else if ( settings.encoding == "toml" ) {
// UF_MSG_DEBUG("TOML: {}", std::string_view{ (const char*) input.data(), input.size() });
T parsed = ext::toml::toJson( input );
// UF_MSG_DEBUG("JSON: {}", std::string_view{ (const char*) parsed.data(), parsed.size() });
json = nlohmann::json::parse(parsed, nullptr, exceptions, comments);
// UF_MSG_DEBUG("ENCODED: {}", json.dump());
}
#endif
else {
// should probably default to json, not my problem
UF_MSG_ERROR("invalid encoding requested: {}", settings.encoding);
}
#if UF_EXCEPTIONS
} catch ( nlohmann::json::parse_error& e ) {
UF_MSG_ERROR("JSON error: {}", e.what());
}
#endif
return json;
#undef UF_JSON_PARSE_ENCODING
}
#include "json.inl"

View File

@ -0,0 +1,81 @@
template<typename T>
uf::stl::vector<T> ext::json::vector( const ext::json::Value& value ) {
uf::stl::vector<T> res;
res.reserve( value.size() );
ext::json::forEach( value, [&]( const ext::json::Value& value ){
res.emplace_back( value.as<T>() );
});
return res;
}
template<typename T>
T& ext::json::encode( const ext::json::Value& json, T& output, const ext::json::EncodingSettings& settings ) {
// ext::json::Value json = ext::json::reencode( _json, settings );
#define UF_JSON_PARSE_ENCODING(ENC)\
if ( settings.encoding == #ENC ) {\
auto buffer = nlohmann::json::to_ ## ENC( (const ext::json::base_value&) (json) );\
output = T( buffer.begin(), buffer.end() );\
}
if ( settings.encoding == "" || settings.encoding == "json" ) {
output = settings.pretty ? json.dump(1, '\t') : json.dump();
}
else UF_JSON_PARSE_ENCODING(bson)
else UF_JSON_PARSE_ENCODING(cbor)
else UF_JSON_PARSE_ENCODING(msgpack)
else UF_JSON_PARSE_ENCODING(ubjson)
else UF_JSON_PARSE_ENCODING(bjdata)
#if UF_USE_TOML
else if ( settings.encoding == "toml" ) {
uf::stl::string buffer = ext::toml::fromJson( json.dump() );
output = T( buffer.begin(), buffer.end() );
}
#endif
else {
// should probably default to json, not my problem
UF_MSG_ERROR("invalid encoding requested: {}", settings.encoding);
}
return output;
#undef UF_JSON_PARSE_ENCODING
}
template<typename T>
ext::json::Value& ext::json::decode( ext::json::Value& json, const T& input, const DecodingSettings& settings ) {
#define UF_JSON_PARSE_ENCODING(ENC)\
if ( settings.encoding == #ENC ) {\
json = nlohmann::json::from_ ## ENC(input, strict, exceptions);\
}
constexpr bool comments = true;
constexpr bool strict = true;
constexpr bool exceptions = true;
#if UF_EXCEPTIONS
try {
#endif
if ( settings.encoding == "" || settings.encoding == "json" ) {
json = nlohmann::json::parse(input, nullptr, exceptions, comments);
}
else UF_JSON_PARSE_ENCODING(bson)
else UF_JSON_PARSE_ENCODING(cbor)
else UF_JSON_PARSE_ENCODING(msgpack)
else UF_JSON_PARSE_ENCODING(ubjson)
else UF_JSON_PARSE_ENCODING(bjdata)
#if UF_USE_TOML
else if ( settings.encoding == "toml" ) {
T parsed = ext::toml::toJson( input );
json = nlohmann::json::parse(parsed, nullptr, exceptions, comments);
}
#endif
else {
// should probably default to json, not my problem
UF_MSG_ERROR("invalid encoding requested: {}", settings.encoding);
}
#if UF_EXCEPTIONS
} catch ( nlohmann::json::parse_error& e ) {
UF_MSG_ERROR("JSON error: {}", e.what());
}
#endif
return json;
#undef UF_JSON_PARSE_ENCODING
}

View File

@ -71,89 +71,5 @@ namespace ext {
uf::stl::vector<uf::stl::string> UF_API keys( const Value& v );
}
}
/*
namespace pod {
template<typename T, size_t N> struct UF_API Vector;
template<typename T, size_t R, size_t C> struct UF_API Matrix;
template<typename T> struct UF_API Transform;
}
template<typename T, size_t N> ext::json::Value& ext::json::Value::operator=( const pod::Vector<T,N>& v ) {
ext::json::base_value::operator=( ext::json::encode(v) );
return *this;
}
template<typename T, size_t R, size_t C = R> ext::json::Value& ext::json::Value::operator=( const pod::Matrix<T,R,C>& m ) {
ext::json::base_value::operator=( ext::json::encode(m) );
return *this;
}
template<typename T> ext::json::Value& ext::json::Value::operator=( const pod::Vector<T,R,C>& t ) {
ext::json::base_value::operator=( ext::json::encode(t) );
return *this;
}
*/
template<typename... Args> ext::json::Value& ext::json::Value::operator[]( Args... args ) {
return (ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> const ext::json::Value& ext::json::Value::operator[]( Args... args ) const {
return (const ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> ext::json::Value& ext::json::Value::operator=( Args... args ) {
ext::json::base_value::operator=(args...);
return *this;
}
template<typename T> ext::json::Value& ext::json::Value::emplace_back( const T& v ) {
return (ext::json::Value&) ext::json::base_value::emplace_back(v);
}
/*
template<> ext::json::Value& ext::json::Value::emplace_back<ext::json::Value>( const ext::json::Value& value ) {
return (ext::json::Value&) ext::json::base_value::emplace_back( (const ext::json::base_value&) value );
}
*/
template<> inline bool ext::json::Value::is<bool>(bool strict) const { return is_boolean(); }
template<> inline bool ext::json::Value::is<int8_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<int16_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<int32_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<int64_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<uint8_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<uint16_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<uint32_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<uint64_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<float>(bool strict) const { return strict ? is_number_float() : is_number(); }
template<> inline bool ext::json::Value::is<double>(bool strict) const { return strict ? is_number_float() : is_number(); }
template<> inline bool ext::json::Value::is<uf::stl::string>(bool strict) const { return is_string(); }
// template<> template<typename T, size_t N> inline bool ext::json::Value::is<pod::Vector<T,N>>(bool strict) const { return is_array() && size() == N; }
// template<> inline bool ext::json::Value::is<std::string>(bool strict) const { return is_string(); }
#if UF_ENV_DREAMCAST
template<> inline bool ext::json::Value::is<int>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<unsigned int>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
#endif
template<typename T> inline T ext::json::Value::as() const {
return !is<T>(false) ? T() : get<T>();
/*
if ( !is<T>() ) return T();
return get<T>();
*/
}
template<typename T> inline T ext::json::Value::as( const T& fallback ) const {
return !is<T>(false) ? fallback : get<T>();
/*
if ( !is<T>() ) return fallback;
return get<T>();
*/
}
template<> inline bool ext::json::Value::as<bool>() const {
// explicitly a bool
if ( is<bool>() ) return get<bool>();
// implicit conversion
if ( is_null() ) return false; // always return falce
if ( is_number() ) return get<int>(); // implicit conversion to bool
if ( is_string() ) return get<uf::stl::string>() != ""; // true if not empty
if ( is_object() ) return !ext::json::keys( *this ).empty(); // true if not empty
if ( is_array() ) return size() > 0; // true if not empty
return false;
}
#include "nlohmann.inl"

View File

@ -0,0 +1,86 @@
/*
namespace pod {
template<typename T, size_t N> struct UF_API Vector;
template<typename T, size_t R, size_t C> struct UF_API Matrix;
template<typename T> struct UF_API Transform;
}
template<typename T, size_t N> ext::json::Value& ext::json::Value::operator=( const pod::Vector<T,N>& v ) {
ext::json::base_value::operator=( ext::json::encode(v) );
return *this;
}
template<typename T, size_t R, size_t C = R> ext::json::Value& ext::json::Value::operator=( const pod::Matrix<T,R,C>& m ) {
ext::json::base_value::operator=( ext::json::encode(m) );
return *this;
}
template<typename T> ext::json::Value& ext::json::Value::operator=( const pod::Vector<T,R,C>& t ) {
ext::json::base_value::operator=( ext::json::encode(t) );
return *this;
}
*/
template<typename... Args> ext::json::Value& ext::json::Value::operator[]( Args... args ) {
return (ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> const ext::json::Value& ext::json::Value::operator[]( Args... args ) const {
return (const ext::json::Value&) ext::json::base_value::operator[](args...);
}
template<typename... Args> ext::json::Value& ext::json::Value::operator=( Args... args ) {
ext::json::base_value::operator=(args...);
return *this;
}
template<typename T> ext::json::Value& ext::json::Value::emplace_back( const T& v ) {
return (ext::json::Value&) ext::json::base_value::emplace_back(v);
}
/*
template<> ext::json::Value& ext::json::Value::emplace_back<ext::json::Value>( const ext::json::Value& value ) {
return (ext::json::Value&) ext::json::base_value::emplace_back( (const ext::json::base_value&) value );
}
*/
template<> inline bool ext::json::Value::is<bool>(bool strict) const { return is_boolean(); }
template<> inline bool ext::json::Value::is<int8_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<int16_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<int32_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<int64_t>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<uint8_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<uint16_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<uint32_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<uint64_t>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
template<> inline bool ext::json::Value::is<float>(bool strict) const { return strict ? is_number_float() : is_number(); }
template<> inline bool ext::json::Value::is<double>(bool strict) const { return strict ? is_number_float() : is_number(); }
template<> inline bool ext::json::Value::is<uf::stl::string>(bool strict) const { return is_string(); }
// template<> template<typename T, size_t N> inline bool ext::json::Value::is<pod::Vector<T,N>>(bool strict) const { return is_array() && size() == N; }
// template<> inline bool ext::json::Value::is<std::string>(bool strict) const { return is_string(); }
#if UF_ENV_DREAMCAST
template<> inline bool ext::json::Value::is<int>(bool strict) const { return strict ? is_number_integer() : is_number(); }
template<> inline bool ext::json::Value::is<unsigned int>(bool strict) const { return strict ? is_number_unsigned() : is_number(); }
#endif
template<typename T> inline T ext::json::Value::as() const {
return !is<T>(false) ? T() : get<T>();
/*
if ( !is<T>() ) return T();
return get<T>();
*/
}
template<typename T> inline T ext::json::Value::as( const T& fallback ) const {
return !is<T>(false) ? fallback : get<T>();
/*
if ( !is<T>() ) return fallback;
return get<T>();
*/
}
template<> inline bool ext::json::Value::as<bool>() const {
// explicitly a bool
if ( is<bool>() ) return get<bool>();
// implicit conversion
if ( is_null() ) return false; // always return falce
if ( is_number() ) return get<int>(); // implicit conversion to bool
if ( is_string() ) return get<uf::stl::string>() != ""; // true if not empty
if ( is_object() ) return !ext::json::keys( *this ).empty(); // true if not empty
if ( is_array() ) return size() > 0; // true if not empty
return false;
}

View File

@ -1,31 +0,0 @@
#pragma once
#include <uf/ext/vulkan/rendermode.h>
#include <uf/ext/vulkan/graphic.h>
namespace ext {
namespace vulkan {
struct UF_API ComputeRenderMode : public ext::vulkan::RenderMode {
ext::vulkan::Graphic blitter;
//
const uf::stl::string getTarget() const;
void setTarget( const uf::stl::string& );
//
virtual const uf::stl::string getType() const;
virtual const size_t blitters() const;
virtual ext::vulkan::Graphic* getBlitter(size_t = 0);
virtual uf::stl::vector<ext::vulkan::Graphic*> getBlitters();
virtual GraphicDescriptor bindGraphicDescriptor( const GraphicDescriptor&, size_t = 0 );
virtual void createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics );
virtual void initialize( Device& device );
virtual void tick();
virtual void destroy();
virtual void render();
virtual void pipelineBarrier( VkCommandBuffer, uint8_t = -1 );
};
}
}

View File

@ -102,6 +102,8 @@ namespace ext {
uf::stl::unordered_map<uf::stl::string, AccelerationStructure> accelerationStructure;
uf::stl::unordered_map<uf::stl::string, PushConstant> pushConstants;
uf::stl::unordered_map<uf::stl::string, SpecializationConstants> specializationConstants;
pod::Vector3ui localSize{};
} definitions;
// to automatically grab attachments from the target renderMode
@ -129,6 +131,8 @@ namespace ext {
void aliasAttachment( const Metadata::AttachmentDescriptor& descriptor );
void aliasAttachment( const uf::stl::string& name, const ext::vulkan::RenderMode* renderMode = NULL, VkImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, VkFilter filter = VK_FILTER_NEAREST );
bool hasAttachment( const uf::stl::string& name );
bool hasUniform( const uf::stl::string& name ) const;
Buffer& getUniformBuffer( const uf::stl::string& name );

View File

@ -9,7 +9,7 @@
#include <cassert>
#include <mutex>
#define VK_VALIDATION_MESSAGE(...) if ( ext::vulkan::settings::validation ) UF_MSG_DEBUG(__VA_ARGS__);
#define VK_VALIDATION_MESSAGE(...) if ( ext::vulkan::settings::validation ) UF_MSG("VULKAN", __VA_ARGS__);
#define VK_CHECK_RESULT(f) { VkResult res = (f); if ( res != VK_SUCCESS ) UF_EXCEPTION("{}", ext::vulkan::errorString( res )); }

View File

@ -121,6 +121,7 @@ namespace ext {
extern UF_API uint32_t frameAccumulate;
extern UF_API bool frameAccumulateReset;
extern UF_API bool frameSkip;
}
extern UF_API Device device;

View File

@ -4,7 +4,6 @@
#include <uf/ext/vulkan/graphic.h>
#include <uf/ext/vulkan/rendermodes/rendertarget.h>
#include <uf/ext/vulkan/rendermodes/deferred.h>
#include <uf/ext/vulkan/rendermodes/compute.h>
#include <uf/ext/vulkan/rendertarget.h>
namespace spec {

View File

@ -297,12 +297,17 @@ namespace ext {
uint32_t renderTarget = 0;
uint32_t subpass = 0;
struct {
size_t width = 1;
size_t height = 1;
size_t depth = 1;
uint32_t point = 0;
} bind;
struct {
uf::Mesh::Input vertex, index, instance, indirect;
size_t bufferOffset = 0;
pod::Vector3ui dispatch = { 0, 0, 0 };
size_t width = 0;
size_t height = 0;
} inputs;
ext::RENDERER::enums::PrimitiveTopology::type_t topology = ext::RENDERER::enums::PrimitiveTopology::TRIANGLE_LIST;

View File

@ -243,7 +243,9 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, uf::renderer::settings::pipelines::names::culling);
graphic.material.metadata.autoInitializeUniformBuffers = true;
}
graphic.descriptor.inputs.dispatch = { graphic.descriptor.inputs.indirect.count, 1, 1 };
graphic.descriptor.bind.width = graphic.descriptor.inputs.indirect.count;
graphic.descriptor.bind.height = 1;
graphic.descriptor.bind.depth = 1;
auto& shader = graphic.material.getShader("compute", uf::renderer::settings::pipelines::names::culling);
@ -1424,10 +1426,10 @@ void uf::graph::tick() {
::newGraphAdded = false;
if ( rebuild ) {
UF_MSG_DEBUG("Graph buffers requesting renderer update");
uf::renderer::states::rebuild = true;
}
}
if ( rebuild ) {
UF_MSG_DEBUG("Graph buffers requesting renderer update");
uf::renderer::states::rebuild = true;
}
}
void uf::graph::render() {

View File

@ -34,28 +34,6 @@ void uf::GraphBehavior::initialize( uf::Object& self ) {
auto& graph = (this->getComponent<pod::Graph>() = std::move( assetLoader.get<pod::Graph>(payload.filename) ));
assetLoader.remove<pod::Graph>(payload.filename);
#if 0
bool shouldUpdate = false;
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
if ( !ext::json::isNull(graph.metadata["ambient"]) ) {
sceneMetadataJson["light"]["ambient"] = graph.metadata["ambient"];
shouldUpdate = true;
}
if ( !ext::json::isNull(graph.metadata["fog"]) ) {
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:Deserialize.%UID%");
#endif
// deferred shader loading
auto& transform = this->getComponent<pod::Transform<>>();
graph.root.entity->getComponent<pod::Transform<>>().reference = &transform;

View File

@ -159,7 +159,7 @@ bool uf::Object::reload( bool hard ) {
transform.reference = reference;
}
payload["new"] = metadataJson;
this->queueHook("object:Reload.%UID%", payload);
this->queueHook("object:Reload.%UID%", metadataJson);
return true;
}

View File

@ -71,43 +71,43 @@ namespace {
if ( !uf::renderer::hasRenderMode("Compute:RT", true) ) return;
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
auto& blitter = *renderMode.getBlitter(); if ( !blitter.material.hasShader("fragment") ) return;
auto& shader = blitter.material.getShader("fragment"); if ( shader.textures.empty() ) return;
auto& attachmentColor = shader.textures.front();
pod::Vector2ui renderSize = {
attachmentColor.width > 0 ? attachmentColor.width : uf::renderer::settings::width,
attachmentColor.height > 0 ? attachmentColor.height : uf::renderer::settings::height,
renderMode.width > 0 ? renderMode.width : uf::renderer::settings::width,
renderMode.height > 0 ? renderMode.height : uf::renderer::settings::height,
};
dispatchParameters.renderSize.width = renderSize.x;
dispatchParameters.renderSize.height = renderSize.y;
auto& attachmentColor = renderMode.hasAttachment("output") ? renderMode.getAttachment("output") : renderMode.getAttachment("color");
auto& attachmentDepth = renderMode.getAttachment("depth");
auto& attachmentMotion = renderMode.getAttachment("motion");
dispatchParameters.color = ffxGetTextureResourceVK(&::context,
attachmentColor.image,
attachmentColor.view,
renderSize.x,
renderSize.y,
attachmentColor.format,
attachmentColor.descriptor.format,
L"FSR2_InputColor"
);
dispatchParameters.depth = ffxGetTextureResourceVK(&::context,
nullptr,
nullptr,
1,
1,
VK_FORMAT_UNDEFINED,
attachmentDepth.image,
attachmentDepth.view,
renderSize.x,
renderSize.y,
attachmentDepth.descriptor.format,
L"FSR2_InputDepth"
);
dispatchParameters.motionVectors = ffxGetTextureResourceVK(&::context,
nullptr,
nullptr,
1,
1,
VK_FORMAT_UNDEFINED,
attachmentMotion.image,
attachmentMotion.view,
renderSize.x,
renderSize.y,
attachmentMotion.descriptor.format,
L"FSR2_InputMotionVectors"
);
dispatchParameters.motionVectorScale.x = 0;
dispatchParameters.motionVectorScale.y = 0;
dispatchParameters.motionVectorScale.x = renderSize.x;
dispatchParameters.motionVectorScale.y = renderSize.y;
} else {
if ( !uf::renderer::hasRenderMode("", true) ) return;

View File

@ -12,8 +12,6 @@
#include <uf/utils/serialize/serializer.h>
#define UF_MSG_VALIDATION(...) if ( ext::vulkan::settings::validation ) UF_MSG("VULKAN", __VA_ARGS__);
namespace {
struct DeviceInfo {
VkPhysicalDevice handle = VK_NULL_HANDLE;
@ -232,8 +230,8 @@ namespace {
if ( feature == #NAME ) {\
if ( device.features.NAME == VK_TRUE ) {\
device.enabledFeatures.NAME = true;\
UF_MSG_VALIDATION("Enabled feature: {}", feature);\
} else UF_MSG_VALIDATION("Failed to enable feature: {}", feature);\
VK_VALIDATION_MESSAGE("Enabled feature: {}", feature);\
} else VK_VALIDATION_MESSAGE("Failed to enable feature: {}", feature);\
}
for ( auto& feature : ext::vulkan::settings::requestedDeviceFeatures ) {
@ -299,8 +297,8 @@ namespace {
if ( feature == #NAME ) {\
if ( device.features2.NAME == VK_TRUE ) {\
device.enabledFeatures2.NAME = true;\
UF_MSG_VALIDATION("Enabled feature: {}", feature);\
} else UF_MSG_VALIDATION("Failed to enable feature: {}", feature);\
VK_VALIDATION_MESSAGE("Enabled feature: {}", feature);\
} else VK_VALIDATION_MESSAGE("Failed to enable feature: {}", feature);\
}
#undef CHECK_FEATURE2
}
@ -383,8 +381,8 @@ namespace {
if ( feature == #NAME ) {\
if ( features.NAME == VK_TRUE ) {\
enabledFeatures.NAME = true;\
UF_MSG_VALIDATION("Enabled feature: {}", feature);\
} else UF_MSG_VALIDATION("Failed to enable feature: {}", feature);\
VK_VALIDATION_MESSAGE("Enabled feature: {}", feature);\
} else VK_VALIDATION_MESSAGE("Failed to enable feature: {}", feature);\
}
for ( auto& feature : ext::vulkan::settings::requestedDeviceFeatures ) {
@ -442,8 +440,8 @@ namespace {
if ( feature == #NAME ) {\
if ( device.features2.NAME == VK_TRUE ) {\
device.enabledFeatures2.NAME = true;\
UF_MSG_VALIDATION("Enabled feature: {}", feature);\
} else UF_MSG_VALIDATION("Failed to enable feature: {}", feature);\
VK_VALIDATION_MESSAGE("Enabled feature: {}", feature);\
} else VK_VALIDATION_MESSAGE("Failed to enable feature: {}", feature);\
}
#undef CHECK_FEATURE2
}
@ -769,7 +767,7 @@ void ext::vulkan::Device::initialize() {
}
}
if ( layerFound ) {
UF_MSG_VALIDATION("Vulkan layer enabled: {}", layerName);
VK_VALIDATION_MESSAGE("Vulkan layer enabled: {}", layerName);
} else UF_EXCEPTION("Vulkan error: layer requested, but not available: {}", layerName);
}
}
@ -801,7 +799,7 @@ void ext::vulkan::Device::initialize() {
{
uf::stl::vector<uf::stl::string> instanceExtensions;
for ( auto& s : supportedExtensions.instance ) {
UF_MSG_VALIDATION("Enabled instance extension: {}", s);
VK_VALIDATION_MESSAGE("Enabled instance extension: {}", s);
instanceExtensions.emplace_back( s );
}
@ -871,7 +869,7 @@ void ext::vulkan::Device::initialize() {
for ( size_t i = 0; i < deviceCount; ++i ) {
auto& deviceInfo = deviceInfos.emplace_back( rate(*this, physicalDevices[i]) );
/*
UF_MSG_VALIDATION("[" << i << "] "
VK_VALIDATION_MESSAGE("[" << i << "] "
"Found device: " << deviceInfo.properties.deviceName << " ("
"score: " << deviceInfo.score << " | "
"device ID: " << deviceInfo.properties.deviceID << " | "
@ -890,7 +888,7 @@ void ext::vulkan::Device::initialize() {
auto& deviceInfo = deviceInfos[bestDeviceIndex];
this->physicalDevice = deviceInfo.handle;
/*
UF_MSG_VALIDATION("Using device #" << bestDeviceIndex << " ("
VK_VALIDATION_MESSAGE("Using device #" << bestDeviceIndex << " ("
"score: " << deviceInfo.score << " | "
"device ID: " << deviceInfo.properties.deviceID << " | "
"vendor ID: " << deviceInfo.properties.vendorID << " | "
@ -951,7 +949,7 @@ void ext::vulkan::Device::initialize() {
#endif
{
// Allocate enough ExtensionProperties to support all extensions being enabled
for ( auto ext : requestedExtensions ) UF_MSG_VALIDATION("Requested device extension: {}", ext);
for ( auto ext : requestedExtensions ) VK_VALIDATION_MESSAGE("Requested device extension: {}", ext);
uint32_t extensionsCount = 0;
uint32_t enabledExtensionsCount = 0;
@ -966,7 +964,7 @@ void ext::vulkan::Device::initialize() {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
for ( auto& s : supportedExtensions.device ) {
UF_MSG_VALIDATION("Enabled device extension: {}", s);
VK_VALIDATION_MESSAGE("Enabled device extension: {}", s);
deviceExtensions.emplace_back( s );
}
@ -1152,7 +1150,7 @@ void ext::vulkan::Device::initialize() {
}
{
ext::json::Value payload = retrieveDeviceFeatures( *this );
UF_MSG_VALIDATION("{}", payload.dump());
VK_VALIDATION_MESSAGE("{}", payload.dump());
uf::hooks.call("vulkan:Device.FeaturesEnabled", payload);
}
}
@ -1188,10 +1186,10 @@ void ext::vulkan::Device::initialize() {
i++;
}
UF_MSG_VALIDATION("Graphics queue: {}", device.queueFamilyIndices.graphics);
UF_MSG_VALIDATION("Compute queue: {}", device.queueFamilyIndices.compute);
UF_MSG_VALIDATION("Transfer queue: {}", device.queueFamilyIndices.transfer);
UF_MSG_VALIDATION("Present queue: {}", device.queueFamilyIndices.present);
VK_VALIDATION_MESSAGE("Graphics queue: {}", device.queueFamilyIndices.graphics);
VK_VALIDATION_MESSAGE("Compute queue: {}", device.queueFamilyIndices.compute);
VK_VALIDATION_MESSAGE("Transfer queue: {}", device.queueFamilyIndices.transfer);
VK_VALIDATION_MESSAGE("Present queue: {}", device.queueFamilyIndices.present);
device.queueFamilyIndices.present = presentQueueNodeIndex;
getQueue( QueueEnum::GRAPHICS );

View File

@ -390,29 +390,37 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer comm
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 );
bool bound = false;
for ( auto* shader : shaders ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
if (
// compute shaders
if ( shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT ) {
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_COMPUTE ) bound = true;
else continue;
// raytrace shaders
} else if (
shader->descriptor.stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_MISS_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR ||
shader->descriptor.stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR
) bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
#if 1
) {
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ) bound = true;
else continue;
// anything else
} else {
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_GRAPHICS ) bound = true;
else continue;
}
if ( shader->metadata.definitions.pushConstants.count("PushConstant") > 0 ) {
if ( shader->descriptor.stage == VK_SHADER_STAGE_VERTEX_BIT || shader->descriptor.stage == VK_SHADER_STAGE_COMPUTE_BIT || shader->descriptor.stage == VK_SHADER_STAGE_RAYGEN_BIT_KHR ) {
struct PushConstant {
uint32_t pass;
uint32_t draw;
} pushConstant = { pass, draw };
vkCmdPushConstants( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
}
} else
#endif
if ( !shader->pushConstants.empty() ) {
struct PushConstant {
uint32_t pass;
uint32_t draw;
} pushConstant = { pass, draw };
vkCmdPushConstants( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
} else if ( !shader->pushConstants.empty() ) {
auto& pushConstant = shader->pushConstants.front();
size_t size = pushConstant.size();
void* data = pushConstant.data().data;
@ -421,25 +429,41 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, const GraphicDescrip
}
}
}
// no matching bind point for shaders, skip
if ( !bound ) return;
// Bind descriptor sets describing shader binding points
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
vkCmdBindDescriptorSets(commandBuffer, (VkPipelineBindPoint)descriptor.bind.point, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
// Bind the rendering pipeline
// The pipeline (state object) contains all states of the rendering pipeline, binding it will set all the states specified at pipeline creation time
vkCmdBindPipeline(commandBuffer, bindPoint, pipeline);
vkCmdBindPipeline(commandBuffer, (VkPipelineBindPoint)descriptor.bind.point, pipeline);
if ( bindPoint == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ) {
uint32_t width = descriptor.bind.width ? descriptor.bind.width : ext::vulkan::settings::width;
uint32_t height = descriptor.bind.height ? descriptor.bind.height : ext::vulkan::settings::height;
uint32_t depth = descriptor.bind.depth ? descriptor.bind.depth : 1;
if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR ) {
uf::renderer::vkCmdTraceRaysKHR(
commandBuffer,
&sbtEntries[0],
&sbtEntries[1],
&sbtEntries[2],
&sbtEntries[3],
descriptor.inputs.width ? descriptor.inputs.width : ext::vulkan::settings::width,
descriptor.inputs.height ? descriptor.inputs.height : ext::vulkan::settings::height,
width,
height,
1
);
} else if ( bindPoint == VK_PIPELINE_BIND_POINT_COMPUTE && descriptor.inputs.dispatch.x != 0 && descriptor.inputs.dispatch.y != 0 && descriptor.inputs.dispatch.z != 0 ) {
vkCmdDispatch(commandBuffer, descriptor.inputs.dispatch.x, descriptor.inputs.dispatch.y, descriptor.inputs.dispatch.z);
} else if ( descriptor.bind.point == VK_PIPELINE_BIND_POINT_COMPUTE ) {
for ( auto* shader : shaders ) {
if ( shader->descriptor.stage != VK_SHADER_STAGE_COMPUTE_BIT ) continue;
auto& localSize = shader->metadata.definitions.localSize;
vkCmdDispatch(commandBuffer,
localSize.x ? ((width / localSize.x) + 1) : 1,
localSize.y ? ((height / localSize.y) + 1) : 1,
localSize.z ? ((depth / localSize.z) + 1) : 1
);
}
}
}
void ext::vulkan::Pipeline::update( const Graphic& graphic ) {
@ -1714,7 +1738,7 @@ void ext::vulkan::Graphic::generateTopAccelerationStructure( const uf::stl::vect
// UF_MSG_DEBUG("Reduced size to {}% ({} -> {} = {})", (float) (oldSize - compactedSize) / (float) (oldSize), oldSize, compactedSize, oldSize - compactedSize);
ext::vulkan::Buffer oldBuffer;
oldBuffer.initialize( NULL, tlasBufferSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS );
oldBuffer.initialize( NULL, tlasBufferSize, uf::renderer::enums::Buffer::ACCELERATION_STRUCTURE | uf::renderer::enums::Buffer::ADDRESS | uf::renderer::enums::Buffer::STORAGE );
this->buffers[tlasBufferIndex].swap(oldBuffer);
tlas.buffer = this->buffers[tlasBufferIndex].alias();

View File

@ -67,12 +67,15 @@ uf::Image ext::vulkan::RenderMode::screenshot( size_t attachmentID, size_t layer
vkGetPhysicalDeviceFormatProperties(device->physicalDevice, VK_FORMAT_R8G8B8A8_UNORM, &formatProperties);
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) blitting = false;
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
VkImage temporary;
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
imageCreateInfo.extent = { renderTarget.width, renderTarget.height, 1 };
imageCreateInfo.extent = { width, height, 1 };
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
@ -186,8 +189,11 @@ ext::vulkan::GraphicDescriptor ext::vulkan::RenderMode::bindGraphicDescriptor( c
ext::vulkan::GraphicDescriptor descriptor = reference;
descriptor.subpass = pass;
descriptor.pipeline = metadata.pipeline;
descriptor.inputs.width = this->width ? this->width : settings::width;
descriptor.inputs.height = this->height ? this->height : settings::height;
descriptor.bind.width = this->width ? this->width : settings::width;
descriptor.bind.height = this->height ? this->height : settings::height;
descriptor.bind.depth = metadata.eyes;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS;
descriptor.parse( metadata.json["descriptor"] );
// descriptor.renderMode = this->getName();
@ -376,6 +382,16 @@ void ext::vulkan::RenderMode::tick() {
}
this->synchronize();
if ( metadata.limiter.frequency > 0 ) {
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
metadata.limiter.timer = 0;
metadata.limiter.execute = true;
} else {
metadata.limiter.timer = metadata.limiter.timer + uf::time::delta;
metadata.limiter.execute = false;
}
}
}
void ext::vulkan::RenderMode::render() {

View File

@ -1,260 +0,0 @@
#if UF_USE_VULKAN
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/rendermodes/compute.h>
#include <uf/ext/vulkan/initializers.h>
#include <uf/utils/window/window.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/ext/vulkan/graphic.h>
#include <uf/engine/graph/graph.h>
#include <uf/utils/camera/camera.h>
const uf::stl::string ext::vulkan::ComputeRenderMode::getTarget() const {
// auto& metadata = *const_cast<uf::Serializer*>(&this->metadata);
// return metadata["target"].as<uf::stl::string>();
return metadata.target;
}
void ext::vulkan::ComputeRenderMode::setTarget( const uf::stl::string& target ) {
// this->metadata["target"] = target;
metadata.target = target;
}
const uf::stl::string ext::vulkan::ComputeRenderMode::getType() const {
return "Compute";
}
const size_t ext::vulkan::ComputeRenderMode::blitters() const {
return 1;
}
ext::vulkan::Graphic* ext::vulkan::ComputeRenderMode::getBlitter( size_t i ) {
return &this->blitter;
}
uf::stl::vector<ext::vulkan::Graphic*> ext::vulkan::ComputeRenderMode::getBlitters() {
return { &this->blitter };
}
ext::vulkan::GraphicDescriptor ext::vulkan::ComputeRenderMode::bindGraphicDescriptor( const ext::vulkan::GraphicDescriptor& reference, size_t pass ) {
ext::vulkan::GraphicDescriptor descriptor = ext::vulkan::RenderMode::bindGraphicDescriptor(reference, pass);
/*
descriptor.parse(metadata.json["descriptor"]);
// invalidate
if ( metadata.target != "" && descriptor.renderMode != this->getName() && descriptor.renderMode != metadata.target ) {
descriptor.invalidated = true;
} else {
descriptor.renderMode = this->getName();
}
*/
return descriptor;
}
void ext::vulkan::ComputeRenderMode::initialize( Device& device ) {
this->setTarget("Compute");
ext::vulkan::RenderMode::initialize( device );
#if 0
{
uf::Mesh mesh;
mesh.bind<pod::Vertex_3F>();
/*
mesh.insertVertices<pod::Vertex_3F>({
{ {-0.5f, -0.5f, 0.0f } },
{ { 0.5f, -0.5f, 0.0f } },
{ { 0.0f, 0.5f, 0.0f } },
});
*/
mesh.insertVertices<pod::Vertex_3F>({
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{-1.0f,-1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{-1.0f,-1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f,-1.0f,},
{1.0f,-1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f,-1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f,-1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f, 1.0f, 1.0f,},
{-1.0f, 1.0f, 1.0f,},
{1.0f,-1.0f, 1.0f,},
});
mesh.updateDescriptor();
blitter.initialize( this->getName() );
blitter.initializeMesh( mesh );
ext::vulkan::generateAccelerationStructures( blitter );
}
#endif
}
void ext::vulkan::ComputeRenderMode::tick() {
ext::vulkan::RenderMode::tick();
bool resized = this->width == 0 && this->height == 0 && ext::vulkan::states::resized;
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
#if 0
{
auto& shader = blitter.material.getShader("ray:gen");
auto& image = shader.textures.front();
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
alignas(16) pod::Matrix4f iView;
alignas(16) pod::Matrix4f iProjection;
alignas(16) pod::Matrix4f iProjectionView;
alignas(16) pod::Vector4f eyePos;
} matrices[2];
} uniforms;
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
for ( auto i = 0; i < 2; ++i ) {
uniforms.matrices[i] = UniformDescriptor::Matrices{
.view = camera.getView(i),
.projection = camera.getProjection(i),
.iView = uf::matrix::inverse( camera.getView(i) ),
.iProjection = uf::matrix::inverse( camera.getProjection(i) ),
.iProjectionView = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) ),
.eyePos = camera.getEye( i ),
};
}
for ( auto& buffer : shader.buffers ) {
if ( !(buffer.usage & uf::renderer::enums::Buffer::UNIFORM) ) continue;
if ( buffer.allocationInfo.size != sizeof(UniformDescriptor) ) continue;
buffer.update( (const void*) &uniforms, sizeof(UniformDescriptor) );
break;
}
if ( resized ) {
image.destroy();
image.fromBuffers( NULL, 0, uf::renderer::enums::Format::R8G8B8A8_UNORM, uf::renderer::settings::width, uf::renderer::settings::height, 1, 1, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL );
blitter.descriptor.inputs.width = image.width;
blitter.descriptor.inputs.height = image.height;
blitter.getPipeline().update( blitter );
}
}
#endif
if ( metadata.limiter.frequency > 0 ) {
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
metadata.limiter.timer = 0;
metadata.limiter.execute = true;
} else {
metadata.limiter.timer = metadata.limiter.timer + uf::physics::time::delta;
metadata.limiter.execute = false;
}
}
}
void ext::vulkan::ComputeRenderMode::destroy() {
#if 0
auto& shader = blitter.material.getShader("ray:gen");
auto& image = shader.textures.front();
image.screenshot().save("./data/rt.png");
image.destroy();
blitter.destroy();
#endif
ext::vulkan::RenderMode::destroy();
}
void ext::vulkan::ComputeRenderMode::render() {
if ( commandBufferCallbacks.count(EXECUTE_BEGIN) > 0 ) commandBufferCallbacks[EXECUTE_BEGIN]( VkCommandBuffer{}, 0 );
//lockMutex( this->mostRecentCommandPoolId );
auto& commands = getCommands( this->mostRecentCommandPoolId );
// Submit commands
// Use a fence to ensure that command buffer has finished executing before using it again
VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[states::currentBuffer], VK_TRUE, VK_DEFAULT_FENCE_TIMEOUT ));
VK_CHECK_RESULT(vkResetFences( *device, 1, &fences[states::currentBuffer] ));
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = NULL; // Pointer to the list of pipeline stages that the semaphore waits will occur at
submitInfo.pWaitSemaphores = NULL; // Semaphore(s) to wait upon before the submitted command buffer starts executing
submitInfo.waitSemaphoreCount = 0; // One wait semaphore
submitInfo.pSignalSemaphores = NULL; // Semaphore(s) to be signaled when command buffers have completed
submitInfo.signalSemaphoreCount = 0; // One signal semaphore
submitInfo.pCommandBuffers = &commands[states::currentBuffer]; // Command buffers(s) to execute in this batch (submission)
submitInfo.commandBufferCount = 1;
VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( uf::renderer::QueueEnum::COMPUTE ), 1, &submitInfo, fences[states::currentBuffer]));
if ( commandBufferCallbacks.count(EXECUTE_END) > 0 ) commandBufferCallbacks[EXECUTE_END]( VkCommandBuffer{}, 0 );
this->executed = true;
//unlockMutex( this->mostRecentCommandPoolId );
}
void ext::vulkan::ComputeRenderMode::pipelineBarrier( VkCommandBuffer commandBuffer, uint8_t state ) {
}
void ext::vulkan::ComputeRenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {
// destroy if exists
float width = this->width > 0 ? this->width : ext::vulkan::settings::width;
float height = this->height > 0 ? this->height : ext::vulkan::settings::height;
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.pNext = nullptr;
size_t subpasses = 1;
auto& commands = getCommands();
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// pre-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_BEGIN) > 0 ) commandBufferCallbacks[CALLBACK_BEGIN]( commands[i], i );
// if ( blitter.process ) blitter.getPipeline().record( blitter, blitter.descriptor, commands[i] );
/*
for ( ; currentPass < subpasses; ++currentPass ) {
size_t currentDraw = 0;
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
graphic->record( commands[i], descriptor, currentPass, currentDraw++ );
}
if ( commandBufferCallbacks.count( currentPass ) > 0 ) commandBufferCallbacks[currentPass]( commands[i], i );
if ( currentPass + 1 < subpasses ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE);
}
*/
// post-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i], i );
VK_CHECK_RESULT(vkEndCommandBuffer(commands[i]));
}
}
#endif

View File

@ -14,7 +14,18 @@
#include <uf/ext/vulkan/graphic.h>
#include <uf/engine/graph/graph.h>
#define EXTENDED_ATTRIBUTES 0
#define BARYCENTRIC 1
#if BARYCENTRIC
#ifndef BARYCENTRIC_CALCULATE
#define BARYCENTRIC_CALCULATE 1
#endif
#endif
namespace {
const uf::stl::string DEFERRED_MODE = "compute";
}
#include "./transition.inl"
const uf::stl::string ext::vulkan::DeferredRenderMode::getType() const {
return "Deferred";
@ -39,7 +50,8 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
size_t msaa = ext::vulkan::settings::msaa;
struct {
size_t id, bary, depth, uv, normal, color, bright, motion, scratch, output;
size_t id, bary, depth, uv, normal;
size_t color, bright, motion, scratch, output;
} attachments = {};
bool blend = true; // !ext::vulkan::settings::invariant::deferredSampling;
@ -53,7 +65,17 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.samples = */msaa,
});
#if EXTENDED_ATTRIBUTES
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
attachments.bary = 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,
});
#endif
#else
attachments.uv = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */VK_FORMAT_R16G16B16A16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
@ -68,14 +90,6 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.blend = */false,
/*.samples = */msaa,
});
#else
attachments.bary = 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,
});
#endif
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
@ -117,11 +131,13 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
metadata.attachments["id"] = attachments.id;
#if EXTENDED_ATTRIBUTES
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
metadata.attachments["bary"] = attachments.bary;
#endif
#else
metadata.attachments["uv"] = attachments.uv;
metadata.attachments["normal"] = attachments.normal;
#else
metadata.attachments["bary"] = attachments.bary;
#endif
metadata.attachments["depth"] = attachments.depth;
@ -136,10 +152,14 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
#if EXTENDED_ATTRIBUTES
/*.colors =*/ { attachments.id, attachments.uv, attachments.normal },
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
/*.colors =*/ { attachments.id, attachments.bary },
#else
/*.colors =*/ { attachments.id },
#endif
#else
/*.colors =*/ { attachments.id, attachments.bary },
/*.colors =*/ { attachments.id, attachments.uv, attachments.normal },
#endif
/*.inputs =*/ {},
/*.resolve =*/{},
@ -148,6 +168,27 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
/*.autoBuildPipeline =*/ true
);
}
if ( DEFERRED_MODE == "fragment" ) {
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
renderTarget.addPass(
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
/*.colors =*/ { attachments.color, attachments.bright, attachments.motion },
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
/*.inputs =*/ { attachments.id, attachments.depth, attachments.bary },
#else
/*.inputs =*/ { attachments.id, attachments.depth },
#endif
#else
/*.inputs =*/ { attachments.id, attachments.depth, attachments.uv, attachments.normal },
#endif
/*.resolve =*/{},
/*.depth = */attachments.depth,
/*.layer = */eye,
/*.autoBuildPipeline =*/ false
);
}
}
// metadata.outputs.emplace_back(metadata.attachments["output"]);
renderTarget.initialize( device );
@ -188,17 +229,32 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
shader.aliasAttachment("output", this);
}
if ( settings::pipelines::deferred ) {
uf::stl::string computeShaderFilename = "comp.spv"; {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
{ msaa > 1, "msaa.comp" },
{ uf::renderer::settings::pipelines::rt, "rt.comp" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", settings[i].second );
if ( DEFERRED_MODE == "compute" ) {
uf::stl::string computeShaderFilename = "comp.spv"; {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
{ msaa > 1, "msaa.comp" },
{ uf::renderer::settings::pipelines::rt, "rt.comp" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", settings[i].second );
}
computeShaderFilename = uf::io::root+"/shaders/display/deferred/comp/" + computeShaderFilename;
blitter.material.attachShader(uf::io::resolveURI(computeShaderFilename), uf::renderer::enums::Shader::COMPUTE, "deferred");
UF_MSG_DEBUG("Using deferred shader: {}", computeShaderFilename);
} else if ( DEFERRED_MODE == "fragment" ) {
uf::stl::string vertexShaderFilename = "vert.spv";
uf::stl::string fragmentShaderFilename = "frag.spv"; {
std::pair<bool, uf::stl::string> settings[] = {
{ uf::renderer::settings::pipelines::vxgi, "vxgi.frag" },
{ msaa > 1, "msaa.frag" },
{ uf::renderer::settings::pipelines::rt, "rt.frag" },
};
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
}
fragmentShaderFilename = uf::io::root+"/shaders/display/deferred/frag/" + fragmentShaderFilename;
blitter.material.attachShader(uf::io::resolveURI(fragmentShaderFilename), uf::renderer::enums::Shader::FRAGMENT, "deferred");
UF_MSG_DEBUG("Using deferred shader: {}", fragmentShaderFilename);
}
computeShaderFilename = uf::io::root+"/shaders/display/deferred-compute/" + computeShaderFilename;
blitter.material.attachShader(uf::io::resolveURI(computeShaderFilename), uf::renderer::enums::Shader::COMPUTE, "deferred-compute");
UF_MSG_DEBUG("Using deferred shader: {}", computeShaderFilename);
}
if ( settings::pipelines::bloom ) {
@ -206,18 +262,13 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
blitter.material.attachShader(computeShaderFilename, uf::renderer::enums::Shader::COMPUTE, "bloom");
auto& shader = blitter.material.getShader("compute", "bloom");
shader.textures.clear();
shader.aliasAttachment("color", this);
shader.aliasAttachment("bright", this);
shader.aliasAttachment("scratch", this);
for ( auto& texture : shader.textures ) {
texture.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
}
shader.aliasAttachment("color", this, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("bright", this, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("scratch", this, VK_IMAGE_LAYOUT_GENERAL);
}
if ( settings::pipelines::deferred ) {
auto& shader = blitter.material.getShader("compute", "deferred-compute");
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
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);
@ -272,14 +323,16 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
}
}
if ( settings::pipelines::deferred && blitter.material.hasShader("compute", "deferred-compute") ) {
auto& shader = blitter.material.getShader("compute", "deferred-compute");
if ( settings::pipelines::deferred && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
shader.aliasAttachment("id", this);
#if EXTENDED_ATTRIBUTES
#if BARYCENTRIC
#if !BARYCENTRIC_CALCULATE
shader.aliasAttachment("bary", this);
#endif
#else
shader.aliasAttachment("uv", this);
shader.aliasAttachment("normal", this);
#else
shader.aliasAttachment("bary", this);
#endif
shader.aliasAttachment("depth", this);
@ -295,11 +348,19 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
{
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.renderMode = "";
descriptor.bind.width = width;
descriptor.bind.height = height;
descriptor.bind.depth = 1;
if ( settings::pipelines::deferred && blitter.material.hasShader("compute", "deferred-compute") ) {
descriptor.pipeline = "deferred-compute";
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.subpass = 0;
if ( settings::pipelines::deferred && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
descriptor.pipeline = "deferred";
if ( DEFERRED_MODE == "fragment" ) {
descriptor.subpass = 1;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS;
} else if ( DEFERRED_MODE == "compute" ) {
descriptor.subpass = 0;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
}
if ( !blitter.hasPipeline( descriptor ) ) {
blitter.initializePipeline( descriptor );
}
@ -307,8 +368,8 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
if ( settings::pipelines::bloom ) {
descriptor.pipeline = "bloom";
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.subpass = 0;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
if ( !blitter.hasPipeline( descriptor ) ) {
blitter.initializePipeline( descriptor );
}
@ -337,6 +398,7 @@ void ext::vulkan::DeferredRenderMode::tick() {
if ( resized ) {
this->resized = false;
rebuild = true;
renderTarget.initialize( *renderTarget.device );
}
// update blitter descriptor set
@ -347,10 +409,19 @@ void ext::vulkan::DeferredRenderMode::tick() {
{
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.renderMode = "";
if ( settings::pipelines::deferred && blitter.material.hasShader("compute", "deferred-compute") ) {
descriptor.pipeline = "deferred-compute";
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.subpass = 0;
descriptor.bind.width = width;
descriptor.bind.height = height;
descriptor.bind.depth = 1;
if ( settings::pipelines::deferred && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
descriptor.pipeline = "deferred";
if ( DEFERRED_MODE == "fragment" ) {
descriptor.subpass = 1;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS;
} else if ( DEFERRED_MODE == "compute" ) {
descriptor.subpass = 0;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
}
if ( blitter.hasPipeline( descriptor ) ) {
blitter.getPipeline( descriptor ).update( blitter, descriptor );
}
@ -358,8 +429,8 @@ void ext::vulkan::DeferredRenderMode::tick() {
if ( settings::pipelines::bloom ) {
descriptor.pipeline = "bloom";
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.subpass = 0;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
if ( blitter.hasPipeline( descriptor ) ) {
blitter.getPipeline( descriptor ).update( blitter, descriptor );
}
@ -467,7 +538,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
for (size_t i = 0; i < commands.size(); ++i) {
VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo));
// Fill GBuffer
{
if ( !settings::pipelines::rt ) {
VkRenderPassBeginInfo renderPassBeginInfo = {};
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@ -522,59 +593,87 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
size_t currentPass = 0;
size_t currentDraw = 0;
if ( !settings::pipelines::rt ) for ( auto graphic : graphics ) {
for ( auto graphic : graphics ) {
// only draw graphics that are assigned to this type of render mode
if ( graphic->descriptor.renderMode != this->getName() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
graphic->record( commands[i], descriptor, eye, currentDraw++ );
}
if ( eye + 1 < metadata.eyes ) {
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass;
}
}
// skip deferred pass if RT is enabled, we still process geometry for a depth buffer
if ( !settings::pipelines::rt ) for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
size_t currentPass = 0;
size_t currentDraw = 0;
{
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; // = bindGraphicDescriptor(blitter.descriptor, currentSubpass);
descriptor.renderMode = "";
descriptor.pipeline = "deferred";
descriptor.subpass = currentSubpass;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS;
blitter.record(commands[i], descriptor, eye, currentDraw++);
}
if ( eye + 1 < metadata.eyes ) {
vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass;
}
}
vkCmdEndRenderPass(commands[i]);
if ( !settings::pipelines::rt && settings::pipelines::deferred && blitter.material.hasShader("compute", "deferred-compute") ) {
auto& shader = blitter.material.getShader("compute", "deferred-compute");
if ( !settings::pipelines::rt && settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.renderMode = "";
descriptor.pipeline = "deferred-compute";
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.pipeline = "deferred";
descriptor.bind.width = width;
descriptor.bind.height = height;
descriptor.bind.depth = metadata.eyes;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
descriptor.subpass = 0;
imageMemoryBarrier.subresourceRange.layerCount = metadata.eyes;
for ( auto& descriptor : shader.metadata.attachments ) {
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
VkImage image = VK_NULL_HANDLE;
if ( descriptor.renderMode ) {
if ( descriptor.renderMode->hasAttachment(descriptor.name) )
image = descriptor.renderMode->getAttachment(descriptor.name).image;
// transition attachments to general attachments for imageStore
::transitionAttachmentsTo( this, shader, commands[i] );
} else if ( this->hasAttachment(descriptor.name) ) {
if ( this->hasAttachment(descriptor.name) )
image = this->getAttachment(descriptor.name).image;
}
if ( image == VK_NULL_HANDLE ) continue;
uf::renderer::Texture::setImageLayout( commands[i], image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, descriptor.layout, imageMemoryBarrier.subresourceRange );
}
for ( size_t eye = 0; eye < metadata.eyes; ++eye ) {
blitter.record(commands[i], descriptor, eye, 0);
}
for ( auto& descriptor : shader.metadata.attachments ) {
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
VkImage image = VK_NULL_HANDLE;
if ( descriptor.renderMode ) {
if ( descriptor.renderMode->hasAttachment(descriptor.name) )
image = descriptor.renderMode->getAttachment(descriptor.name).image;
} else if ( this->hasAttachment(descriptor.name) ) {
image = this->getAttachment(descriptor.name).image;
}
if ( image == VK_NULL_HANDLE ) continue;
uf::renderer::Texture::setImageLayout( commands[i], image, descriptor.layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, imageMemoryBarrier.subresourceRange );
}
imageMemoryBarrier.subresourceRange.layerCount = 1;
// dispatch compute shader
blitter.record(commands[i], descriptor, 0, 0);
// transition attachments back to shader read layouts
::transitionAttachmentsFrom( this, shader, commands[i] );
}
// VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
// VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
if ( settings::pipelines::bloom && blitter.material.hasShader("compute", "bloom") ) {
auto& shader = blitter.material.getShader("compute", "bloom");
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.renderMode = "";
descriptor.pipeline = "bloom";
descriptor.bind.width = width;
descriptor.bind.height = height;
descriptor.bind.depth = metadata.eyes;
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
descriptor.subpass = 0;
// transition attachments to general attachments for imageStore
::transitionAttachmentsTo( this, shader, commands[i] );
// dispatch compute shader
VkMemoryBarrier memoryBarrier{VK_STRUCTURE_TYPE_MEMORY_BARRIER};
memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
blitter.record(commands[i], descriptor, 0, 1);
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL );
blitter.record(commands[i], descriptor, 0, 2);
vkCmdPipelineBarrier( commands[i], VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FLAGS_NONE, 1, &memoryBarrier, 0, NULL, 0, NULL );
blitter.record(commands[i], descriptor, 0, 3);
// transition attachments back to shader read layouts
::transitionAttachmentsFrom( this, shader, commands[i] );
}
// post-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i], i );
#if 0
if ( this->hasAttachment("depth") ) {
auto& attachment = this->getAttachment("depth");
@ -604,85 +703,6 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
}
#endif
// post-renderpass commands
if ( commandBufferCallbacks.count(CALLBACK_END) > 0 ) commandBufferCallbacks[CALLBACK_END]( commands[i], i );
#if 0
if ( settings::pipelines::bloom ) {
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.pipeline = "bloom";
descriptor.inputs.dispatch = { (width / 8) + 1, (height / 8) + 1, 1 };
descriptor.subpass = 0;
auto& shader = blitter.material.getShader("compute", "bloom");
imageMemoryBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
#if 0
if ( device->queueFamilyIndices.graphics != device->queueFamilyIndices.compute ) {
imageMemoryBarrier.srcQueueFamilyIndex = device->queueFamilyIndices.graphics;
imageMemoryBarrier.dstQueueFamilyIndex = device->queueFamilyIndices.compute;
} else {
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
}
#endif
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.oldLayout = attachment.imageLayout; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
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 );
}
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
#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);
#if 0
if ( device->queueFamilyIndices.graphics != device->queueFamilyIndices.compute ) {
imageMemoryBarrier.srcQueueFamilyIndex = device->queueFamilyIndices.compute;
imageMemoryBarrier.dstQueueFamilyIndex = device->queueFamilyIndices.graphics;
}
#endif
for ( auto& attachment : shader.textures ) {
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.newLayout = attachment.imageLayout; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
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 );
}
}
#endif
for ( auto layer : layers ) {
layer->pipelineBarrier( commands[i], 1 );
}

View File

@ -95,6 +95,71 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
true
);
}
} else if ( metadata.type == settings::pipelines::names::rt ) {
#if 1
struct {
size_t depth, color, bright, motion, scratch, output;
} attachments = {};
auto HDR_FORMAT = uf::renderer::enums::Format::R32G32B32A32_SFLOAT;
auto SDR_FORMAT = uf::renderer::enums::Format::R16G16B16A16_SFLOAT; // uf::renderer::enums::Format::R8G8B8A8_UNORM
bool blend = true;
attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format = */ext::vulkan::settings::formats::depth,
/*.layout = */VK_IMAGE_LAYOUT_GENERAL,
/*.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 | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
/*.blend = */false,
/*.samples = */1,
});
attachments.color = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.bright = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.scratch = renderTarget.attach(RenderTarget::Attachment::Descriptor{
/*.format =*/ ext::vulkan::settings::pipelines::hdr ? HDR_FORMAT : SDR_FORMAT,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend =*/ blend,
/*.samples =*/ 1,
});
attachments.motion = renderTarget.attach(RenderTarget::Attachment::Descriptor{
// /*.format = */VK_FORMAT_R32G32B32A32_SFLOAT,
/*.format = */VK_FORMAT_R16G16_SFLOAT,
/*.layout = */ VK_IMAGE_LAYOUT_GENERAL,
/*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
/*.blend = */false,
/*.samples = */1,
});
renderTarget.addPass(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
{},
{},
{},
attachments.depth,
0,
true
);
metadata.attachments["depth"] = attachments.depth;
metadata.attachments["color"] = attachments.color;
metadata.attachments["bright"] = attachments.bright;
metadata.attachments["motion"] = attachments.motion;
metadata.attachments["scratch"] = attachments.scratch;
metadata.attachments["output"] = attachments.color;
#endif
} else {
for ( size_t currentPass = 0; currentPass < metadata.subpasses; ++currentPass ) {
struct {
@ -240,16 +305,21 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) {
else if ( tx.name == "voxelRadiance" ) layout.descriptorCount = maxCascades;
}
}
} else if ( metadata.type != uf::renderer::settings::pipelines::names::rt ) {
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
} else if ( metadata.type == uf::renderer::settings::pipelines::names::rt ) {
#if 0
auto& shader = blitter.material.getShader("fragment");
shader.aliasAttachment("output", this);
#endif
} else {
auto& shader = blitter.material.getShader("fragment");
for ( auto i = 0; i < renderTarget.attachments.size(); ++i ) {
if ( !(renderTarget.attachments[i].descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
Texture2D& texture = blitter.material.textures.emplace_back();
enums::Filter::type_t filter = VK_FILTER_NEAREST;
texture.sampler.descriptor.filter.min = filter;
texture.sampler.descriptor.filter.mag = filter;
texture.aliasAttachment(attachment);
for ( auto& pair : metadata.attachments ) {
if ( pair.second != i ) continue;
shader.aliasAttachment(pair.first, this);
break;
}
}
}
}
@ -261,46 +331,24 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
bool resized = this->width == 0 && this->height == 0 && (ext::vulkan::states::resized || this->resized);
bool rebuild = resized || ext::vulkan::states::rebuild || this->rebuild;
if ( metadata.type == uf::renderer::settings::pipelines::names::vxgi ) {
if ( resized ) {
renderTarget.initialize( *renderTarget.device );
}
if ( rebuild && blitter.process ) {
blitter.getPipeline().update( blitter );
}
return;
}
uint32_t width = this->width > 0 ? this->width : ext::vulkan::settings::width;
uint32_t height = this->height > 0 ? this->height : ext::vulkan::settings::height;
if ( resized ) {
this->resized = false;
renderTarget.initialize( *renderTarget.device );
if ( metadata.type != uf::renderer::settings::pipelines::names::rt ) {
blitter.material.textures.clear();
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ) continue;
Texture2D& texture = blitter.material.textures.emplace_back();
enums::Filter::type_t filter = VK_FILTER_NEAREST;
texture.sampler.descriptor.filter.min = filter;
texture.sampler.descriptor.filter.mag = filter;
texture.aliasAttachment(attachment);
}
}
}
if ( rebuild && blitter.process ) {
auto& mainRenderMode = ext::vulkan::getRenderMode("");
size_t eyes = mainRenderMode.metadata.eyes;
for ( size_t eye = 0; eye < eyes; ++eye ) {
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
descriptor.subpass = 0; // 2 * eye; // + 1;
if ( !blitter.hasPipeline( descriptor ) ) {
blitter.initializePipeline( descriptor );
} else {
blitter.getPipeline( descriptor ).update( blitter, descriptor );
}
blitter.descriptor.bind.width = width;
blitter.descriptor.bind.height = height;
if ( !blitter.hasPipeline( blitter.descriptor ) ) {
blitter.initializePipeline( blitter.descriptor );
} else if ( blitter.hasPipeline( blitter.descriptor ) ){
blitter.getPipeline( blitter.descriptor ).update( blitter, blitter.descriptor );
}
}
/*
if ( metadata.limiter.frequency > 0 ) {
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
metadata.limiter.timer = 0;
@ -310,6 +358,7 @@ void ext::vulkan::RenderTargetRenderMode::tick() {
metadata.limiter.execute = false;
}
}
*/
}
void ext::vulkan::RenderTargetRenderMode::destroy() {
ext::vulkan::RenderMode::destroy();
@ -423,6 +472,7 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const uf::stl::v
if ( graphic->descriptor.renderMode != this->getTarget() ) continue;
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentPass);
descriptor.pipeline = pipeline;
if ( pipeline == "rt" ) descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic->record( commands[i], descriptor, 0, metadata.type == uf::renderer::settings::pipelines::names::vxgi ? 0 : MIN(subpasses,6) );
}
}

View File

@ -0,0 +1,60 @@
namespace {
void transitionAttachmentsTo(
ext::vulkan::RenderMode* self,
ext::vulkan::Shader& shader,
VkCommandBuffer commandBuffer,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
) {
VkImageSubresourceRange subresourceRange;
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.baseArrayLayer = 0;
subresourceRange.layerCount = 1;
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.layerCount = self->metadata.eyes;
for ( auto& descriptor : shader.metadata.attachments ) {
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
VkImage image = VK_NULL_HANDLE;
if ( descriptor.renderMode ) {
if ( descriptor.renderMode->hasAttachment(descriptor.name) )
image = descriptor.renderMode->getAttachment(descriptor.name).image;
} else if ( self->hasAttachment(descriptor.name) ) {
if ( self->hasAttachment(descriptor.name) )
image = self->getAttachment(descriptor.name).image;
}
if ( image == VK_NULL_HANDLE ) continue;
uf::renderer::Texture::setImageLayout( commandBuffer, image, layout, descriptor.layout, subresourceRange );
}
}
void transitionAttachmentsFrom(
ext::vulkan::RenderMode* self,
ext::vulkan::Shader& shader,
VkCommandBuffer commandBuffer,
VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
) {
VkImageSubresourceRange subresourceRange;
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.baseArrayLayer = 0;
subresourceRange.layerCount = 1;
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.layerCount = self->metadata.eyes;
for ( auto& descriptor : shader.metadata.attachments ) {
if ( descriptor.layout == VK_IMAGE_LAYOUT_UNDEFINED ) continue;
VkImage image = VK_NULL_HANDLE;
if ( descriptor.renderMode ) {
if ( descriptor.renderMode->hasAttachment(descriptor.name) )
image = descriptor.renderMode->getAttachment(descriptor.name).image;
} else if ( self->hasAttachment(descriptor.name) ) {
if ( self->hasAttachment(descriptor.name) )
image = self->getAttachment(descriptor.name).image;
}
if ( image == VK_NULL_HANDLE ) continue;
uf::renderer::Texture::setImageLayout( commandBuffer, image, descriptor.layout, layout, subresourceRange );
}
}
}

View File

@ -114,7 +114,6 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
imageView.image = attachment->image;
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->view));
#if 1
size_t viewIndex = 0;
for ( size_t layer = 0; layer < this->views; ++layer ) {
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
@ -126,23 +125,6 @@ size_t ext::vulkan::RenderTarget::attach( const Attachment::Descriptor& descript
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->views[viewIndex++]));
}
}
#endif
#if 0
if ( this->views == 1 ) {
attachment->views[0] = attachment->view;
for ( ) {
}
} else {
imageView.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageView.subresourceRange.layerCount = 1;
for ( size_t i = 0; i < this->views; ++i ) {
imageView.subresourceRange.baseArrayLayer = i;
VK_CHECK_RESULT(vkCreateImageView(*device, &imageView, nullptr, &attachment->views[i]));
}
}
#endif
{
VkBool32 blendEnabled = attachment->descriptor.blend ? VK_TRUE : VK_FALSE;
VkColorComponentFlags writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;

View File

@ -328,6 +328,10 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const uf::stl
{
spirv_cross::Compiler comp( (uint32_t*) &spirv[0], spirv.size() / 4 );
spirv_cross::ShaderResources res = comp.get_shader_resources();
for ( auto i = 0; i < 3; ++i )
metadata.definitions.localSize[i] = comp.get_execution_mode_argument( spv::ExecutionModeLocalSize, i );
#if UF_SHADER_PARSE_AS_JSON
std::function<ext::json::Value(spirv_cross::TypeID)> parseMembers = [&]( spirv_cross::TypeID type_id ) {
auto parseMember = [&]( auto type_id ){
@ -858,6 +862,12 @@ void ext::vulkan::Shader::aliasAttachment( const ext::vulkan::Shader::Metadata::
void ext::vulkan::Shader::aliasAttachment( const uf::stl::string& name, const ext::vulkan::RenderMode* renderMode, VkImageLayout layout, VkFilter filter ) {
return aliasAttachment({ name, renderMode, layout, filter });
}
bool ext::vulkan::Shader::hasAttachment( const uf::stl::string& name ) {
for ( auto& attachment : metadata.attachments ) {
if ( attachment.name == name ) return true;
}
return false;
}
bool ext::vulkan::Shader::hasUniform( const uf::stl::string& name ) const {
return metadata.definitions.uniforms.count(name) > 0;

View File

@ -89,6 +89,7 @@ bool ext::vulkan::states::rebuild = false;
uint32_t ext::vulkan::states::currentBuffer = 0;
uint32_t ext::vulkan::states::frameAccumulate = 0;
bool ext::vulkan::states::frameAccumulateReset = false;
bool ext::vulkan::states::frameSkip = false;
uf::ThreadUnique<ext::vulkan::RenderMode*> ext::vulkan::currentRenderMode;
@ -445,6 +446,10 @@ void ext::vulkan::tick() {
ext::vulkan::mutex.unlock();
}
void ext::vulkan::render() {
if ( ext::vulkan::states::frameSkip ) {
ext::vulkan::states::frameSkip = false;
return;
}
ext::vulkan::mutex.lock();
// cleanup in-flight commands

View File

@ -30,14 +30,14 @@ uf::Hooks::return_t uf::Hooks::call( const uf::Hooks::name_t& name, const pod::H
results.reserve( container.size() );
for ( auto& hook : container ) {
if ( payload.size() != hook.type.size && hook.type.size > 0 ) continue;
if ( payload.size() != hook.type.size /*&& hook.type.size > 0*/ ) continue;
pod::Hook::userdata_t& unconst_payload = const_cast<pod::Hook::userdata_t&>(payload);
pod::Hook::userdata_t hookResult = hook.callback(unconst_payload);
auto& returnResult = results.emplace_back();
returnResult.move( hookResult );
}
return results;
}

View File

@ -20,6 +20,8 @@ namespace {
uf::renderer::Texture emptyTexture;
}
#define UF_USE_EXTERNAL_IMAGE 1
UF_BEHAVIOR_REGISTER_CPP(ext::RayTraceSceneBehavior)
UF_BEHAVIOR_TRAITS_CPP(ext::RayTraceSceneBehavior, ticks = true, renders = false, multithread = true)
#define this (&self)
@ -56,7 +58,8 @@ void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
// renderMode->blitter.process = false;
uf::renderer::addRenderMode( renderMode, "Compute:RT" );
}
#if !UF_USE_EXTERNAL_IMAGE
#else
{
uf::stl::vector<uint8_t> pixels = {
0, 0, 0, 0, 0, 0, 0, 0,
@ -70,6 +73,7 @@ void ext::RayTraceSceneBehavior::initialize( uf::Object& self ) {
auto& blitter = *renderMode.getBlitter();
blitter.material.textures.emplace_back().aliasTexture( ::emptyTexture );
}
#endif
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
}
@ -119,6 +123,18 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
if ( !metadata.renderer.bound ) {
if ( graphic.material.hasShader("ray:gen", uf::renderer::settings::pipelines::names::rt) ) {
#if !UF_USE_EXTERNAL_IMAGE
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
shader.aliasAttachment("color", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("bright", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
shader.aliasAttachment("motion", &renderMode, VK_IMAGE_LAYOUT_GENERAL);
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : ext::vulkan::settings::width;
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : ext::vulkan::settings::height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
#else
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
//
pod::Vector2ui size = metadata.renderer.size;
@ -139,8 +155,10 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
);
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
graphic.descriptor.inputs.width = image.width;
graphic.descriptor.inputs.height = image.height;
graphic.descriptor.bind.width = image.width;
graphic.descriptor.bind.height = image.height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
#endif
//
auto& scene = uf::scene::getCurrentScene();
@ -196,7 +214,16 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
ext::ExtSceneBehavior::bindBuffers( *this, graphic, "ray:gen", uf::renderer::settings::pipelines::names::rt );
}
if ( !metadata.renderer.bound ) return;
#if !UF_USE_EXTERNAL_IMAGE
if ( uf::renderer::states::resized ) {
auto& renderMode = uf::renderer::getRenderMode("Compute:RT", true);
graphic.descriptor.bind.width = renderMode.width > 0 ? renderMode.width : ext::vulkan::settings::width;
graphic.descriptor.bind.height = renderMode.height > 0 ? renderMode.height : ext::vulkan::settings::height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.descriptor.pipeline = uf::renderer::settings::pipelines::names::rt;
graphic.getPipeline().update( graphic );
}
#else
auto& shader = graphic.material.getShader("ray:gen", uf::renderer::settings::pipelines::names::rt);
auto& image = shader.textures.front();
@ -232,8 +259,9 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_GENERAL
);
graphic.descriptor.inputs.width = image.width;
graphic.descriptor.inputs.height = image.height;
graphic.descriptor.bind.width = image.width;
graphic.descriptor.bind.height = image.height;
graphic.descriptor.bind.point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
graphic.getPipeline().update( graphic );
@ -242,7 +270,7 @@ void ext::RayTraceSceneBehavior::tick( uf::Object& self ) {
shader.textures.front().aliasTexture( image );
}
}
#endif
#if 0
TIMER(1.0, uf::Window::isKeyPressed("R") ) {
UF_MSG_DEBUG("Screenshotting RT scene...");

View File

@ -597,8 +597,8 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
/* Update lights */ if ( uf::renderer::settings::pipelines::deferred && !uf::renderer::settings::pipelines::vxgi ) {
auto& deferredRenderMode = uf::renderer::getRenderMode("", true);
auto& deferredBlitter = *deferredRenderMode.getBlitter();
if ( deferredBlitter.material.hasShader("compute", "deferred-compute") ) {
ext::ExtSceneBehavior::bindBuffers( *this, "", "compute", "deferred-compute" );
if ( deferredBlitter.material.hasShader("compute", "deferred") ) {
ext::ExtSceneBehavior::bindBuffers( *this, "", "compute", "deferred" );
} else {
ext::ExtSceneBehavior::bindBuffers( *this, "", "fragment", "deferred" );
}
@ -633,7 +633,6 @@ void ext::ExtSceneBehavior::Metadata::serialize( uf::Object& self, uf::Serialize
serializer["light"]["ambient"] = uf::vector::encode( /*this->*/light.ambient );
serializer["light"]["exposure"] = /*this->*/light.exposure;
serializer["light"]["gamma"] = /*this->*/light.gamma;
serializer["light"]["brightnessThreshold"] = /*this->*/light.brightnessThreshold;
serializer["light"]["useLightmaps"] = /*this->*/light.useLightmaps;
serializer["light"]["fog"]["color"] = uf::vector::encode( /*this->*/fog.color );
@ -701,9 +700,9 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
/*this->*/light.exposure = serializer["light"]["exposure"].as(/*this->*/light.exposure);
/*this->*/light.gamma = serializer["light"]["gamma"].as(/*this->*/light.gamma);
/*this->*/light.brightnessThreshold = serializer["light"]["brightnessThreshold"].as(/*this->*/light.brightnessThreshold);
/*this->*/light.useLightmaps = serializer["light"]["useLightmaps"].as(/*this->*/light.useLightmaps);
/*this->*/bloom.threshold = serializer["light"]["bloom"]["threshold"].as(/*this->*/bloom.threshold);
/*this->*/bloom.scale = serializer["light"]["bloom"]["scale"].as(/*this->*/bloom.scale);
/*this->*/bloom.strength = serializer["light"]["bloom"]["strength"].as(/*this->*/bloom.strength);
/*this->*/bloom.sigma = serializer["light"]["bloom"]["sigma"].as(/*this->*/bloom.sigma);
@ -775,7 +774,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
UniformDescriptor uniforms = {
.scale = bloom.scale,
.strength = bloom.strength,
.threshold = light.brightnessThreshold,
.threshold = bloom.threshold,
.sigma = bloom.sigma,
.gamma = light.gamma,
@ -868,8 +867,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
struct Bloom {
alignas(4) float exposure;
alignas(4) float brightnessThreshold;
alignas(4) float gamma;
alignas(4) float threshold;
alignas(4) uint32_t padding2;
} bloom;
@ -997,8 +996,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, uf::renderer::Graphic
};
uniforms.settings.bloom = UniformDescriptor::Settings::Bloom{
.exposure = metadata.light.exposure,
.brightnessThreshold = metadata.light.brightnessThreshold,
.gamma = metadata.light.gamma,
.threshold = metadata.bloom.threshold,
};
uniforms.settings.vxgi = UniformDescriptor::Settings::VXGI{
.matrix = metadataVxgi.extents.matrix,

View File

@ -25,10 +25,10 @@ namespace ext {
pod::Vector4f _placeholder = {1,1,1,1};
float exposure = 1.0f;
float gamma = 1.0f;
float brightnessThreshold = 1.0f;
bool useLightmaps = true;
} light;
struct {
float threshold = 1.0f;
float scale = 1.0f;
float strength = 1.0f;
float sigma = 0.8f;

View File

@ -124,11 +124,17 @@ void ext::VoxelizerSceneBehavior::initialize( uf::Object& self ) {
renderMode.metadata.json["shaders"]["compute"] = computeShaderFilename;
renderMode.blitter.descriptor.renderMode = metadata.renderModeName;
renderMode.blitter.descriptor.subpass = -1;
renderMode.blitter.descriptor.inputs.dispatch = {
renderMode.blitter.descriptor.bind.width = metadata.voxelSize.x;
renderMode.blitter.descriptor.bind.height = metadata.voxelSize.y;
renderMode.blitter.descriptor.bind.depth = metadata.voxelSize.z;
renderMode.blitter.descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
/*
renderMode.blitter.descriptor.bind.dispatch = {
(metadata.voxelSize.x / metadata.dispatchSize.x),
(metadata.voxelSize.y / metadata.dispatchSize.y),
(metadata.voxelSize.z / metadata.dispatchSize.z),
};
*/
renderMode.blitter.process = true;
size_t maxTextures2D = ext::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
@ -212,7 +218,6 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
if ( renderMode.executed ) {
if ( !metadata.initialized ) metadata.initialized = true;
if ( metadata.limiter.frequency > 0 ) {
if ( metadata.limiter.timer > metadata.limiter.frequency ) {
metadata.limiter.timer = 0;
@ -304,8 +309,8 @@ void ext::VoxelizerSceneBehavior::tick( uf::Object& self ) {
auto& deferredRenderMode = uf::renderer::getRenderMode("", true);
auto& deferredBlitter = *deferredRenderMode.getBlitter();
if ( deferredBlitter.material.hasShader("compute", "deferred-compute") ) {
ext::ExtSceneBehavior::bindBuffers( scene, "", "compute", "deferred-compute" );
if ( deferredBlitter.material.hasShader("compute", "deferred") ) {
ext::ExtSceneBehavior::bindBuffers( scene, "", "compute", "deferred" );
} else {
ext::ExtSceneBehavior::bindBuffers( scene, "", "fragment", "deferred" );
}